diff --git a/.beautyamp.json b/.beautyamp.json new file mode 100644 index 000000000..612573c50 --- /dev/null +++ b/.beautyamp.json @@ -0,0 +1,13 @@ +{ + "ampscript": { + "capitalizeAndOrNot": true, + "capitalizeIfFor": true, + "capitalizeSet": true, + "capitalizeVar": true, + "maxParametersPerLine": 4 + }, + "editor": { + "insertSpaces": true, + "tabSize": 4 + } +} diff --git a/.coverage-comment-template.svelte b/.coverage-comment-template.svelte new file mode 100644 index 000000000..ae2267b27 --- /dev/null +++ b/.coverage-comment-template.svelte @@ -0,0 +1,194 @@ + + +

Coverage Report

+ +Commit:{short_commit_sha}
+Base: {base_ref}@{base_short_commit_sha}

+ + + + + {#if has_base_data} + + {/if} + + + + {#each summary_list as { type, percent }} + + + {#if has_base_data} + + {/if} + + + {/each} + +
TypeBaseThis PR
{type} + {#if Number.isFinite(percent.base)} +  {percent.base}% + {:else} + - + {/if} + + {#if Number.isFinite(percent.total)} +  {percent.total}% + {#if has_base_data} +  ({formatPercentDiff(percent.diff)}) + {/if} + {:else} + - + {/if} +
+ +
+ Details (changed files):
+ + + + + + + + + + {#each changed_files_coverage_data as [file, data]} + {@const percents = [ + data.statements.pct, + data.branches.pct, + data.functions.pct, + data.lines.pct, + ]} + + + {#each percents as percent} + + {/each} + + {/each} + +
FileStatementsBranchesFunctionsLines
+ {file} + + {#if Number.isFinite(percent)} +  {percent}% + {:else} + - + {/if} +
+
diff --git a/.eslintignore b/.eslintignore deleted file mode 100644 index 92e33c296..000000000 --- a/.eslintignore +++ /dev/null @@ -1,3 +0,0 @@ -/docs/** -/node_modules/** -/retrieve/** diff --git a/.eslintrc.json b/.eslintrc.json deleted file mode 100644 index 944d3aea1..000000000 --- a/.eslintrc.json +++ /dev/null @@ -1,47 +0,0 @@ -{ - "env": { - "es6": true, - "node": true, - "mocha": true - }, - "extends": ["eslint:recommended", "prettier", "ssjs"], - "plugins": ["mocha", "prettier"], - "globals": { - "Atomics": "readonly", - "SharedArrayBuffer": "readonly" - }, - "parserOptions": { - "ecmaVersion": 2020, - "sourceType": "module" - }, - "rules": { - "arrow-body-style": ["error", "as-needed"], - "curly": "error", - "mocha/no-exclusive-tests": "error", - "no-console": "off", - "require-jsdoc": [ - "warn", - { - "require": { - "FunctionDeclaration": true, - "MethodDefinition": true, - "ClassDeclaration": true, - "ArrowFunctionExpression": false, - "FunctionExpression": true - } - } - ], - "valid-jsdoc": "error", - "spaced-comment": ["warn", "always", { "block": { "exceptions": ["*"], "balanced": true } }] - }, - "overrides": [ - { - "files": ["*.js"], - "rules": { - "no-var": "error", - "prefer-const": "error", - "prettier/prettier": "warn" - } - } - ] -} diff --git a/.fork/.prettierrc b/.fork/.prettierrc new file mode 100644 index 000000000..074ff283b --- /dev/null +++ b/.fork/.prettierrc @@ -0,0 +1,6 @@ +{ + "useTabs": false, + "tabWidth": 2, + "printWidth": 40, + "trailingComma": "none" +} diff --git a/.fork/custom-commands.json b/.fork/custom-commands.json new file mode 100644 index 000000000..1c2944ecc --- /dev/null +++ b/.fork/custom-commands.json @@ -0,0 +1,140 @@ +[ + { + "version" : 1 + }, + { + "action" : { + "type" : "url", + "url" : "https://github.com/Accenture/sfmc-devtools/compare/main...${ref:short}?expand=1&template=pr_template_release.md" + }, + "name" : "Create PR/Release-PR to master branch", + "refTargets" : [ + "localbranch", + "remotebranch" + ], + "target" : "ref" + }, + { + "action" : { + "type" : "url", + "url" : "https://github.com/Accenture/sfmc-devtools/compare/develop...${ref:short}?expand=1" + }, + "name" : "Create PR/To develop branch", + "refTargets" : [ + "localbranch", + "remotebranch" + ], + "target" : "ref" + }, + { + "action" : { + "type" : "url", + "url" : "https://github.com/Accenture/sfmc-devtools/compare/hotfix...${ref:short}?expand=1" + }, + "name" : "Create PR/To hotfix branch", + "refTargets" : [ + "localbranch", + "remotebranch" + ], + "target" : "ref" + }, + { + "action" : { + "script" : "SKIP_HOOKS=1 git switch ${ref}", + "showOutput" : false, + "type" : "sh", + "waitForExit" : true + }, + "name" : "Skip Hooks/Checkout", + "refTargets" : [ + "localbranch" + ], + "target" : "ref" + }, + { + "action" : { + "script" : "SKIP_HOOKS=1 git switch ${ref:short} && SKIP_HOOKS=2 git pull", + "showOutput" : false, + "type" : "sh", + "waitForExit" : true + }, + "name" : "Skip Hooks/Checkout & Pull", + "refTargets" : [ + "remotebranch" + ], + "target" : "ref" + }, + { + "name" : "Skip Hooks/Commit", + "refTargets" : [ + "localbranch", + "remotebranch" + ], + "target" : "ref", + "ui" : { + "buttons" : [ + { + "action" : { + "args" : "commit -n -m \"$1{text}\" -m \" $2{text}\"", + "path" : "${git}", + "showOutput" : false, + "type" : "process", + "waitForExit" : true + }, + "title" : "Commit without Hooks" + }, + { + "action" : { + "type" : "cancel" + }, + "title" : "Cancel" + } + ], + "controls" : [ + { + "placeholder" : "", + "text" : "", + "textBoxType" : "generic", + "title" : "Commit subject", + "type" : "textBox" + }, + { + "placeholder" : "", + "text" : "", + "textBoxType" : "generic", + "title" : "Description", + "type" : "textBox" + } + ], + "description" : "This will create a commit but not run pre-commit hooks", + "title" : "Commit skipping Hooks" + } + }, + { + "action" : { + "script" : "SKIP_HOOKS=4 git merge ${ref:short}", + "showOutput" : false, + "type" : "sh", + "waitForExit" : true + }, + "name" : "Skip Hooks/Merge into current branch", + "refTargets" : [ + "localbranch" + ], + "target" : "ref" + }, + { + "action" : { + "script" : "SKIP_HOOKS=3 git pull", + "showOutput" : false, + "type" : "sh", + "waitForExit" : true + }, + "name" : "Skip Hooks/Pull", + "refTargets" : [ + "localbranch", + "remotebranch" + ], + "target" : "ref" + } +] \ No newline at end of file diff --git a/.gitattributes b/.gitattributes index 8310c41d5..4a8fe9801 100644 --- a/.gitattributes +++ b/.gitattributes @@ -3,3 +3,5 @@ # Declare files that will always have LF line endings on checkout. *.ssjs text eol=lf + +@types/** linguist-generated diff --git a/.github/ISSUE_TEMPLATE/bug.yml b/.github/ISSUE_TEMPLATE/bug.yml index ff5c7df7c..30c2448e8 100644 --- a/.github/ISSUE_TEMPLATE/bug.yml +++ b/.github/ISSUE_TEMPLATE/bug.yml @@ -1,76 +1,149 @@ name: 🐞 Bug description: File a bug/issue -title: "[BUG] " +title: '[BUG] <title>' labels: [bug, NEW] body: -- type: checkboxes - attributes: - label: Is there an existing issue for this? - description: Please [search here](https://github.com/Accenture/sfmc-devtools/issues) to see if an issue already exists for your problem. - options: - - label: I have searched the existing issues - required: true -- type: textarea - attributes: - label: Current Behavior - description: A clear & concise description of what you're experiencing. - validations: - required: false -- type: textarea - attributes: - label: Expected Behavior - description: A clear & concise description of what you expected to happen. - validations: - required: false -- type: textarea - attributes: - label: Steps To Reproduce - description: Steps to reproduce the behavior. - value: | - 1. Go to '...' - 2. Click on '....' - 3. Run '...' - 4. See error... - validations: - required: false -- type: dropdown - id: version - attributes: - label: Version - description: What version of our software are you running? (mcdev --version) - options: - - 3.2.0 - - 3.1.3 - - 3.1.2 - - 3.1.1 - - 3.1.0 - - 3.0.3 - - 3.0.2 - - 3.0.1 - - develop-branch - validations: - required: true -- type: textarea - attributes: - label: Environment - description: | - examples: - - **Operating system (Windows/Mac/Linux/...)**: Windows 10 - - **Node (node --version)**: 13.14.0 - - **npm (npm --version)**: 7.6.3 - value: | - - OS: - - Node: - - npm: - validations: - required: false -- type: checkboxes - attributes: - label: Participation - options: - - label: I am willing to submit a pull request for this issue. - required: false -- type: textarea - attributes: - label: Additional comments - description: Is there anything else that's important for the team to know? + - type: checkboxes + attributes: + label: Is there an existing issue for this? + description: Please [search here](https://github.com/Accenture/sfmc-devtools/issues) to see if an issue already exists for your problem. + options: + - label: I have searched the existing issues + required: true + - type: textarea + attributes: + label: Current Behavior + description: A clear & concise description of what you're experiencing. + validations: + required: false + - type: textarea + attributes: + label: Expected Behavior + description: A clear & concise description of what you expected to happen. + validations: + required: false + - type: textarea + attributes: + label: Steps To Reproduce + description: Steps to reproduce the behavior. + value: | + 1. Go to '...' + 2. Click on '....' + 3. Run '...' + 4. See error... + validations: + required: false + - type: dropdown + id: version + attributes: + label: Version + description: What version of our software are you running? (mcdev --version) + options: + - 9.0.2 + - 9.0.1 + - 9.0.0 + - 8.4.0 + - 8.3.1 + - 8.3.0 + - 8.2.1 + - 8.2.0 + - 8.1.0 + - 8.0.2 + - 8.0.1 + - 8.0.0 + - 7.10.1 + - 7.10.0 + - 7.9.0 + - 7.8.0 + - 7.7.2 + - 7.7.1 + - 7.7.0 + - 7.6.3 + - 7.6.2 + - 7.6.1 + - 7.6.0 + - 7.5.0 + - 7.4.4 + - 7.4.3 + - 7.4.2 + - 7.4.1 + - 7.4.0 + - 7.3.1 + - 7.3.0 + - 7.2.0 + - 7.1.4 + - 7.1.3 + - 7.1.2 + - 7.1.1 + - 7.1.0 + - 7.0.4 + - 7.0.3 + - 7.0.2 + - 7.0.1 + - 7.0.0 + - 6.0.2 + - 6.0.1 + - 6.0.0 + - 5.3.0 + - 5.2.0 + - 5.1.0 + - 5.0.2 + - 5.0.1 + - 5.0.0 + - 4.3.4 + - 4.3.3 + - 4.3.2 + - 4.3.1 + - 4.3.0 + - 4.2.1 + - 4.2.0 + - 4.1.12 + - 4.1.11 + - 4.1.10 + - 4.1.9 + - 4.1.8 + - 4.1.7 + - 4.1.6 + - 4.1.5 + - 4.1.4 + - 4.1.3 + - 4.1.2 + - 4.1.1 + - 4.1.0 + - 4.0.2 + - 4.0.1 + - 4.0.0 + - 3.1.3 + - 3.1.2 + - 3.1.1 + - 3.1.0 + - 3.0.3 + - 3.0.2 + - 3.0.1 + - develop-branch + validations: + required: true + - type: textarea + attributes: + label: Environment + description: | + examples: + - **Operating system (Windows/Mac/Linux/...)**: Windows 10 + - **Node (node --version)**: 13.14.0 + - **npm (npm --version)**: 7.6.3 + value: | + - OS: + - Node: + - npm: + validations: + required: false + - type: checkboxes + attributes: + label: Participation + options: + - label: I am willing to submit a pull request for this issue. + required: false + - type: textarea + attributes: + label: Additional comments + description: Is there anything else that's important for the team to know? diff --git a/.github/ISSUE_TEMPLATE/task.md b/.github/ISSUE_TEMPLATE/task.md index e22c4ec49..fda68d04e 100644 --- a/.github/ISSUE_TEMPLATE/task.md +++ b/.github/ISSUE_TEMPLATE/task.md @@ -4,7 +4,7 @@ about: Technical improvements without functional impact / changes to the Documen title: "[TASK] " labels: NEW, chore assignees: '' - +issueType: task --- diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index bfd3e1d6d..3664a97a2 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -1,22 +1,10 @@ # PR details -## What is the purpose of this pull request? (put an "X" next to an item) - -_Please delete options that are not relevant._ - -- [ ] Documentation update -- [ ] Bug fix -- [ ] New metadata support -- [ ] Enhanced metadata -- [ ] Add a CLI option -- [ ] Add something to the core -- [ ] Other, please explain: - ## What changes did you make? (Give an overview) -... +- closes #1234 -## Is there anything you'd like reviewers to focus on? +## Further details (optional) ... @@ -24,7 +12,5 @@ _Please delete options that are not relevant._ - [ ] I have performed a self-review of my own code - [ ] I have commented my code, particularly in hard-to-understand areas -- [ ] ESLint & Prettier are not outputting errors or warnings -- [ ] README.md updated (if applicable) -- [ ] CHANGELOG.md updated -- [ ] ran `npm run docs` to update developer docs +- [ ] test scripts updated +- [ ] Wiki updated (if applicable) diff --git a/.github/PULL_REQUEST_TEMPLATE/pr_template_release.md b/.github/PULL_REQUEST_TEMPLATE/pr_template_release.md new file mode 100644 index 000000000..176a02bd4 --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE/pr_template_release.md @@ -0,0 +1,28 @@ +# Release details + +## Checklist + +### Before merge + +- [ ] Wiki updated with info in ticket listed under **Documentation** +- [ ] ran `npm run prepare-release` (which runs `npm audit fix`, `npm run lint-ts`, `npm run lint:fix`, `git add`, `git commit`) +- [ ] pushed potential changes made by prepare-release + +### After merge + +- [ ] merged all dependabot PRs that target main branch +- [ ] updated [bug template](/.github/ISSUE_TEMPLATE/bug.yml) to include the new version +- [ ] updated [.mcdevrc](/test/mockRoot/.mcdevrc.json) for tests to the new version +- [ ] ran `npm run version:major/minor/patch` +- [ ] pushed version-prep commits +- [ ] merged main branch into develop branch +- [ ] closed GitHub milestone +- [ ] created [new GitHub Release](https://github.com/Accenture/sfmc-devtools/releases/new) + +## Documentation + +... insert updated documentation here ... + +## Issues + +- closes #1234567 diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 000000000..df559c42b --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,23 @@ +# To get started with Dependabot version updates, you'll need to specify which +# package ecosystems to update and where the package manifests are located. +# Please see the documentation for all configuration options: +# https://help.github.com/github/administering-a-repository/configuration-options-for-dependency-updates + +version: 2 +updates: + - package-ecosystem: 'npm' # See documentation for possible values + directory: '/' # Location of package manifests + schedule: + interval: 'weekly' + target-branch: 'develop' + open-pull-requests-limit: 10 + labels: + - 'dependencies' + - package-ecosystem: 'github-actions' + directory: '/' + schedule: + interval: 'weekly' + target-branch: 'main' + labels: + - 'dependencies' + - 'github-action' diff --git a/.github/pr-labeler.yml b/.github/pr-labeler.yml new file mode 100644 index 000000000..980729c45 --- /dev/null +++ b/.github/pr-labeler.yml @@ -0,0 +1,3 @@ +enhancement: ['feature/*', 'feat/*'] +bug: ['bugfix/*', 'bug/*', 'fix/*', 'hotfix/*'] +chore: ['chore/*', 'task/*'] diff --git a/.github/workflows/close_issues_on_merge.yml b/.github/workflows/close_issues_on_merge.yml new file mode 100644 index 000000000..a5e82e14e --- /dev/null +++ b/.github/workflows/close_issues_on_merge.yml @@ -0,0 +1,23 @@ +name: Close issues related to a merged pull request based on master branch. + +on: + pull_request: + types: [closed] + branches: + - develop + - hotfix + +jobs: + closeIssueOnPrMergeTrigger: + permissions: + contents: read + pull-requests: read + issues: write + + runs-on: ubuntu-latest + + steps: + - name: Closes issues related to a merged pull request. + uses: ldez/gha-mjolnir@v1.5.0 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/code-test.yml b/.github/workflows/code-test.yml new file mode 100644 index 000000000..feadd8abc --- /dev/null +++ b/.github/workflows/code-test.yml @@ -0,0 +1,41 @@ +# Custom tests for mcdev +# +name: "Code Testing" + +on: + push: + branches: [main, develop, hotfix] + pull_request: + # The branches below must be a subset of the branches above + branches: [main, develop, hotfix] + +jobs: + lintandTesting: + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + node: ["20.19", 21, 22, 23, 24, 25] + name: lint & test w/ node v${{ matrix.node }} + permissions: + actions: read + contents: read + security-events: write + + steps: + - name: Checkout repository + uses: actions/checkout@v6 + + - name: Setup node + uses: actions/setup-node@v6 + with: + node-version: ${{ matrix.node }} + registry-url: https://registry.npmjs.org/ + + - run: npm ci --ignore-scripts + + - run: npm run lint + + # Assuming code passes, run tests + - name: Run mcdev-tests + run: npm run test diff --git a/.github/workflows/coverage-base-update.yml b/.github/workflows/coverage-base-update.yml new file mode 100644 index 000000000..cefe5a48d --- /dev/null +++ b/.github/workflows/coverage-base-update.yml @@ -0,0 +1,61 @@ +name: Update coverage comment # base-update.yml +on: + pull_request: + types: [edited] + +permissions: + # allow dependabot to execute this workflow + pull-requests: write + +jobs: + hello_world_job: + runs-on: ubuntu-latest + name: Test and report + steps: + - name: Checkout + uses: actions/checkout@v6 + with: + ref: ${{ github.event.pull_request.head.sha }} + fetch-depth: 1000 + + - name: Prepare for Report Coverage (without nyc run) + run: | + npm i svelte-to-html@1.0.9 + git fetch origin ${{ github.event.pull_request.base.ref }} --depth=1000 + + - name: Download artifact for base branch + uses: dawidd6/action-download-artifact@v16 + continue-on-error: true + with: + workflow: ${{ github.event.pull_request.base.ref == 'main' && 'coverage-main-branch.yml' || github.event.pull_request.base.ref == 'develop' && 'coverage-develop-branch.yml' || 'coverage.yml' }} + workflow_conclusion: success + commit: ${{github.event.pull_request.base.sha}} + name: 'test-coverage-output' + path: base-artifacts + search_artifacts: true + + - name: Download artifact for to be merged branch + uses: dawidd6/action-download-artifact@v16 + continue-on-error: true + with: + workflow: 'coverage.yml' + workflow_conclusion: success + commit: ${{github.event.pull_request.head.sha}} + name: 'test-coverage-output' + path: artifacts + search_artifacts: true + + - name: Check file existence + id: check_files + uses: andstor/file-existence-action@v3 + with: + files: 'base-artifacts/coverage-summary.json, artifacts/coverage-summary.json' + + - name: Update Coverage comment + uses: sidx1024/report-nyc-coverage-github-action@v1.2.7 + if: steps.check_files.outputs.files_exists == 'true' + # Only runs if all of the files exists + with: + coverage_file: 'artifacts/coverage-summary.json' + base_coverage_file: 'base-artifacts/coverage-summary.json' + comment_template_file: '.coverage-comment-template.svelte' diff --git a/.github/workflows/coverage-develop-branch.yml b/.github/workflows/coverage-develop-branch.yml new file mode 100644 index 000000000..b9a213415 --- /dev/null +++ b/.github/workflows/coverage-develop-branch.yml @@ -0,0 +1,42 @@ +name: Test coverage for develop branch # default-branch.yml + +on: + push: + branches: + - develop + +permissions: + # allow dependabot to execute this workflow + pull-requests: write + +jobs: + hello_world_job: + runs-on: ubuntu-latest + name: Test and upload coverage + steps: + - name: Checkout + uses: actions/checkout@v6 + with: + ref: ${{ github.event.ref }} + fetch-depth: 1000 + + - uses: actions/setup-node@v6 + with: + node-version-file: ./package.json + + - run: npm ci --ignore-scripts + + - name: Run mcdev-tests with coverage + run: npm run coverage + + - name: Prepare for Report Coverage (mini) + run: | + npx c8 report --reporter json-summary --exclude-after-remap false + + - name: Upload coverage artifact + uses: actions/upload-artifact@v7 + with: + name: test-coverage-output + path: coverage + overwrite: true + retention-days: 90 diff --git a/.github/workflows/coverage-main-branch.yml b/.github/workflows/coverage-main-branch.yml new file mode 100644 index 000000000..818690642 --- /dev/null +++ b/.github/workflows/coverage-main-branch.yml @@ -0,0 +1,42 @@ +name: Test coverage for main branch # default-branch.yml + +on: + push: + branches: + - main + +permissions: + # allow dependabot to execute this workflow + pull-requests: write + +jobs: + hello_world_job: + runs-on: ubuntu-latest + name: Test and upload coverage + steps: + - name: Checkout + uses: actions/checkout@v6 + with: + ref: ${{ github.event.ref }} + fetch-depth: 1000 + + - uses: actions/setup-node@v6 + with: + node-version-file: ./package.json + + - run: npm ci --ignore-scripts + + - name: Run mcdev-tests with coverage + run: npm run coverage + + - name: Prepare for Report Coverage (mini) + run: | + npx c8 report --reporter json-summary --exclude-after-remap false + + - name: Upload coverage artifact + uses: actions/upload-artifact@v7 + with: + name: test-coverage-output + path: coverage + overwrite: true + retention-days: 90 diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml new file mode 100644 index 000000000..a5b69be0a --- /dev/null +++ b/.github/workflows/coverage.yml @@ -0,0 +1,82 @@ +on: [pull_request] + +name: Test coverage report # main.yml + +permissions: + # allow dependabot to execute this workflow + pull-requests: write + +jobs: + hello_world_job: + runs-on: ubuntu-latest + name: Test and report + steps: + - name: Checkout + uses: actions/checkout@v6 + with: + ref: ${{ github.event.pull_request.head.sha }} + fetch-depth: 1000 + + - uses: actions/setup-node@v6 + with: + node-version-file: ./package.json + + - run: npm ci --ignore-scripts + + - name: Run mcdev-tests with coverage + run: npm run coverage + + - name: Prepare for Report Coverage + run: | + npx c8 report --reporter json-summary --exclude-after-remap false + npm i svelte-to-html@1.0.9 + git fetch origin ${{ github.event.pull_request.base.ref }} --depth=1000 + + - name: Upload coverage artifact + uses: actions/upload-artifact@v7 + with: + name: test-coverage-output + path: coverage + overwrite: true + retention-days: 90 + + - name: Download coverage artifact + uses: actions/download-artifact@v8 + with: + path: artifacts/test-coverage-output + + - name: Get Run ID + id: get_run_id + run: | + echo "name=run_id::$(\ + gh run list \ + --workflow "${{ github.event.pull_request.base.ref == 'main' && 'coverage-main-branch.yml' || github.event.pull_request.base.ref == 'develop' && 'coverage-develop-branch.yml' || 'coverage.yml' }}" \ + --json conclusion,headSha,status,databaseId \ + --jq ".[] | select( .conclusion == \"success\" and .headSha == \"${{github.event.pull_request.base.sha}}\") | .databaseId" \ + )" >> $GITHUB_OUTPUT + env: + GITHUB_TOKEN: ${{ github.token }} + + - name: Download artifact for base branch if available, previous + uses: dawidd6/action-download-artifact@v16 + continue-on-error: true + with: + workflow: ${{ github.event.pull_request.base.ref == 'main' && 'coverage-main-branch.yml' || github.event.pull_request.base.ref == 'develop' && 'coverage-develop-branch.yml' || 'coverage.yml' }} + run_id: ${{steps.get_run_id.outputs.run_id}} + name: 'test-coverage-output' + path: base-artifacts + search_artifacts: true + + - name: Check file existence + id: check_files + uses: andstor/file-existence-action@v3 + with: + files: 'base-artifacts/coverage-summary.json, artifacts/test-coverage-output/coverage-summary.json' + + - name: Report coverage + uses: sidx1024/report-nyc-coverage-github-action@v1.2.7 + id: report + with: + coverage_file: 'artifacts/test-coverage-output/coverage-summary.json' + base_coverage_file: ${{steps.check_files.outputs.files_exists == 'true' && 'base-artifacts/coverage-summary.json' || ''}} + comment_template_file: '.coverage-comment-template.svelte' diff --git a/.github/workflows/npm-publish.yml b/.github/workflows/npm-publish.yml index 20fd491b5..0b79c3008 100644 --- a/.github/workflows/npm-publish.yml +++ b/.github/workflows/npm-publish.yml @@ -4,30 +4,33 @@ name: Publish NPM on Release on: - release: - types: [created] + release: + types: [published] + +permissions: + id-token: write # Required for OIDC + contents: read jobs: - build: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v2 - - uses: actions/setup-node@v1 - with: - node-version: 14 - - run: npm ci - - run: npm test + build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v6 + - uses: actions/setup-node@v6 + with: + node-version-file: ./package.json + + - run: npm ci + - run: npm test + + publish-npm: + needs: build + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v6 + - uses: actions/setup-node@v6 + with: + node-version-file: ./package.json + registry-url: https://registry.npmjs.org/ + - run: npm publish - publish-npm: - needs: build - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v2 - - uses: actions/setup-node@v1 - with: - node-version: 14 - registry-url: https://registry.npmjs.org/ - - run: npm ci - - run: npm publish - env: - NODE_AUTH_TOKEN: ${{secrets.npm_token}} diff --git a/.github/workflows/pr-labeler.yml b/.github/workflows/pr-labeler.yml new file mode 100644 index 000000000..9d205244b --- /dev/null +++ b/.github/workflows/pr-labeler.yml @@ -0,0 +1,19 @@ +name: PR Labeler +on: + pull_request: + types: [opened] + +permissions: + contents: read + +jobs: + pr-labeler: + permissions: + contents: read # for TimonVS/pr-labeler-action to read config file + pull-requests: write # for TimonVS/pr-labeler-action to add labels in PR + runs-on: ubuntu-latest + steps: + - uses: TimonVS/pr-labeler-action@v5 + with: + repo-token: ${{ secrets.GITHUB_TOKEN }} + configuration-path: .github/pr-labeler.yml # optional, .github/pr-labeler.yml is the default value diff --git a/.gitignore b/.gitignore index bbceb0330..418f88f8c 100644 --- a/.gitignore +++ b/.gitignore @@ -1,11 +1,14 @@ -businessUnits/ -deploy/ -logs/ +/.nyc_output/ +/businessUnits/ +/coverage/ +/deploy/ +/logs/ +/retrieve/ +/roles/ +/template/ +/tmp/ node_modules/ -retrieve/ -roles/ -template/ -tmp/ .mcdev-auth.json .mcdevrc.json .vscode/tasks.json +!test/mockRoot/* diff --git a/.husky/commit-msg b/.husky/commit-msg new file mode 100644 index 000000000..cf02777be --- /dev/null +++ b/.husky/commit-msg @@ -0,0 +1,8 @@ +INPUT_FILE=$1 +START_LINE=`head -n1 $INPUT_FILE` +PATTERN="^(#[[:digit:]]|Merge|Revert)" + +if ! echo "$START_LINE" | grep -qE "$PATTERN" ; then + echo "Bad commit message, see example: \"#431 commit message\", you provided: \"$START_LINE\"" + exit 1 +fi diff --git a/.husky/post-checkout b/.husky/post-checkout new file mode 100755 index 000000000..b1ebc3d06 --- /dev/null +++ b/.husky/post-checkout @@ -0,0 +1,38 @@ +#!/bin/sh +# ### git commit message template ### +git config commit.template .git/templatemessage +TICKETID=`git rev-parse --abbrev-ref HEAD | LC_ALL=en_US.utf8 grep -oP '^((feature|bug|bugfix|fix|hotfix|task|chore)\/)?\K\d{1,7}' || true` +if [ -z "$TICKETID" ] +then + TICKETID="0" +fi +TEMPLATE="#$TICKETID: " +echo "[POST-CHECKOUT] Setting template commit to '$TEMPLATE'" +# wrap $TEMPLATE in quotes or else it is trimmed automatically +echo "$TEMPLATE" > ".git/templatemessage" + + +if [ "${SKIP_HOOKS:-0}" -gt 0 ] 2>/dev/null; then + echo "[POST-CHECKOUT] skipping hooks ($SKIP_HOOKS)" + exit 0 +fi + +# ### run npm install ### +echo "[POST-CHECKOUT] 📦 Checking for changes to dependencies" +# $1 is the new HEAD pointer +NEWHEAD=$1 +# $2 is the previous HEAD pointer +OLDHEAD=$2 +# extract all paths to package-lock.json files +PACKAGES=$(git diff --name-only "$OLDHEAD" "$NEWHEAD" | grep -E "^package-lock\.json" || true) + +if [ -n "$PACKAGES" ]; then + for package in $PACKAGES; do + echo "📦 $package was changed." + done + echo "📦 Running npm install to update your dependencies..." + npm install + npm run lint:fix +else + echo "📦 All packages up-to-date. No need to run npm install." +fi diff --git a/.husky/post-merge b/.husky/post-merge new file mode 100644 index 000000000..afff68cfb --- /dev/null +++ b/.husky/post-merge @@ -0,0 +1,24 @@ +if [[ $SKIP_HOOKS>0 ]]; then + echo "[POST-MERGE] skipping hooks ($SKIP_HOOKS)" + exit 0 +fi + +# ### run npm install ### +echo "[POST-MERGE] 📦 Checking for changes to dependencies" +# define how to split strings into array elements +IFS=$'\n' +# extract all paths to package-lock.json files +PACKAGE_LOCK_REGEX="(^package-lock\.json)" +echo "[POST-MERGE] running git diff --name-only HEAD^1 HEAD" +PACKAGES=$(git diff --name-only HEAD^1 HEAD | grep -E $PACKAGE_LOCK_REGEX || true) + +if [[ ${PACKAGES[@]} ]]; then + for package in $PACKAGES; do + echo "📦 $package was changed." + done + echo "📦 Running npm install to update your dependencies..." + npm install + npm run lint:fix +else + echo "📦 All packages up-to-date. No need to run npm install." +fi diff --git a/.husky/pre-commit b/.husky/pre-commit index 3f831e70f..2c1fdc583 100644 --- a/.husky/pre-commit +++ b/.husky/pre-commit @@ -1,4 +1,8 @@ -#!/bin/sh -. "$(dirname "$0")/_/husky.sh" +# run lint-staged hooks +echo "[PRE-COMMIT] Run lint-staged" +lint-staged -npx --no lint-staged +# update typescript type declarations +echo "[PRE-COMMIT] Run typescript validation and create/update d.ts files" +tsc -p tsconfig.precommit.json +git add @types diff --git a/.mcdev-validations.js b/.mcdev-validations.js new file mode 100644 index 000000000..e69de29bb diff --git a/.nycrc.json b/.nycrc.json new file mode 100644 index 000000000..eed922e02 --- /dev/null +++ b/.nycrc.json @@ -0,0 +1,5 @@ +{ + "all": true, + "include": ["lib/**"], + "exclude": ["lib/metadataTypes/definitions/*.js", "test/**", "types/**"] +} diff --git a/.prettierrc b/.prettierrc index fc1ff66b4..b62a90ecd 100644 --- a/.prettierrc +++ b/.prettierrc @@ -2,6 +2,7 @@ "tabWidth": 4, "printWidth": 100, "singleQuote": true, + "trailingComma": "es5", "overrides": [ { "files": "*.json", @@ -9,6 +10,12 @@ "parser": "json" } }, + { + "files": "package.json|package-lock.json", + "options": { + "printWidth": 40 + } + }, { "files": "*.ssjs", "options": { diff --git a/.vscode/extensions.json b/.vscode/extensions.json index fa1939335..8480c16a5 100644 --- a/.vscode/extensions.json +++ b/.vscode/extensions.json @@ -5,9 +5,9 @@ // List of extensions which should be recommended for users of this workspace. "recommendations": [ // collaboration - "gruntfuggly.todo-tree", "aaron-bond.better-comments", "github.vscode-pull-request-github", + "johnpapa.vscode-peacock", // Linters "dbaeumer.vscode-eslint", @@ -15,11 +15,14 @@ // Formatting & colors "editorconfig.editorconfig", "esbenp.prettier-vscode", - "sergey-agadzhanov.ampscript", + "xnerd.ampscript-language", + "FiB.beautyAmp", + + // mcdev tests + "hbenl.vscode-mocha-test-adapter", + "IBM.output-colorizer", // Markdown / Readme.md - "yzhang.markdown-all-in-one", - "davidanson.vscode-markdownlint", "joernberkefeld.markdown-preview-bitbucket-innersource" ] } diff --git a/.vscode/settings.json b/.vscode/settings.json index c8d15142f..3ea569ef4 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,15 +1,16 @@ { "editor.codeActionsOnSave": { - "source.fixAll.eslint": true, - "source.fixAll.markdownlint": true + "source.fixAll.eslint": "explicit", + "source.fixAll.markdownlint": "explicit" }, "editor.formatOnSave": true, "files.associations": { - "*.ssjs": "javascript" + "*.ssjs": "javascript", + "*.html": "ampscript" }, "files.eol": "\n", "js/ts.implicitProjectConfig.checkJs": true, - "javascript.validate.enable": false, + "javascript.validate.enable": true, "markdown.extension.italic.indicator": "_", "markdown.extension.list.indentationSize": "adaptive", "markdown.extension.toc.levels": "2..6", @@ -19,7 +20,7 @@ "sql-formatter.indent": " ", "sql-formatter.uppercase": true, "[html]": { - "editor.defaultFormatter": "esbenp.prettier-vscode" + "editor.defaultFormatter": "FiB.beautyAmp" }, "[javascript]": { "editor.defaultFormatter": "esbenp.prettier-vscode" @@ -31,7 +32,7 @@ "editor.defaultFormatter": "esbenp.prettier-vscode" }, "[markdown]": { - "editor.defaultFormatter": "yzhang.markdown-all-in-one" + "editor.defaultFormatter": "esbenp.prettier-vscode" }, "[typescript]": { "editor.defaultFormatter": "esbenp.prettier-vscode" @@ -42,7 +43,7 @@ "outline.showVariables": false, "breadcrumbs.showVariables": false, "breadcrumbs.showProperties": false, - "githubIssues.issueBranchTitle": "bugfix/i${issueNumber}-${sanitizedIssueTitle}", + "githubIssues.issueBranchTitle": "feature/${issueNumber}-${sanitizedIssueTitle}", "githubIssues.queries": [ { "label": "My Issues", @@ -56,5 +57,36 @@ "label": "Created By Me", "query": "author:${user} state:open repo:${owner}/${repository} sort:created-desc" } - ] + ], + "vsicons.associations.files": [ + { + "icon": "apex", + "languages": [ + { "ids": "ampscript", "defaultExtension": "amp" }, + { "ids": "AMPscript", "defaultExtension": "amp" } + ], + "light": true, + "format": "FileFormat.svg" + } + ], + "workbench.colorCustomizations": { + "activityBar.activeBackground": "#fbed80", + "activityBar.background": "#fbed80", + "activityBar.foreground": "#15202b", + "activityBar.inactiveForeground": "#15202b99", + "activityBarBadge.background": "#06b9a5", + "activityBarBadge.foreground": "#15202b", + "commandCenter.border": "#15202b99", + "sash.hoverBorder": "#fbed80", + "statusBar.background": "#f9e64f", + "statusBar.foreground": "#15202b", + "statusBarItem.hoverBackground": "#f7df1e", + "statusBarItem.remoteBackground": "#f9e64f", + "statusBarItem.remoteForeground": "#15202b", + "titleBar.activeBackground": "#f9e64f", + "titleBar.activeForeground": "#15202b", + "titleBar.inactiveBackground": "#f9e64f99", + "titleBar.inactiveForeground": "#15202b99" + }, + "peacock.color": "#f9e64f" } diff --git a/@types/lib/Builder.d.ts b/@types/lib/Builder.d.ts new file mode 100644 index 000000000..c489f19ae --- /dev/null +++ b/@types/lib/Builder.d.ts @@ -0,0 +1,111 @@ +export default Builder; +export type BuObject = import("../types/mcdev.d.js").BuObject; +export type CodeExtract = import("../types/mcdev.d.js").CodeExtract; +export type CodeExtractItem = import("../types/mcdev.d.js").CodeExtractItem; +export type Mcdevrc = import("../types/mcdev.d.js").Mcdevrc; +export type MetadataTypeItem = import("../types/mcdev.d.js").MetadataTypeItem; +export type MetadataTypeItemDiff = import("../types/mcdev.d.js").MetadataTypeItemDiff; +export type MetadataTypeItemObj = import("../types/mcdev.d.js").MetadataTypeItemObj; +export type MetadataTypeMap = import("../types/mcdev.d.js").MetadataTypeMap; +export type MetadataTypeMapObj = import("../types/mcdev.d.js").MetadataTypeMapObj; +export type MultiMetadataTypeList = import("../types/mcdev.d.js").MultiMetadataTypeList; +export type SoapRequestParams = import("../types/mcdev.d.js").SoapRequestParams; +export type TemplateMap = import("../types/mcdev.d.js").TemplateMap; +/** + * @typedef {import('../types/mcdev.d.js').BuObject} BuObject + * @typedef {import('../types/mcdev.d.js').CodeExtract} CodeExtract + * @typedef {import('../types/mcdev.d.js').CodeExtractItem} CodeExtractItem + * @typedef {import('../types/mcdev.d.js').Mcdevrc} Mcdevrc + * @typedef {import('../types/mcdev.d.js').MetadataTypeItem} MetadataTypeItem + * @typedef {import('../types/mcdev.d.js').MetadataTypeItemDiff} MetadataTypeItemDiff + * @typedef {import('../types/mcdev.d.js').MetadataTypeItemObj} MetadataTypeItemObj + * @typedef {import('../types/mcdev.d.js').MetadataTypeMap} MetadataTypeMap + * @typedef {import('../types/mcdev.d.js').MetadataTypeMapObj} MetadataTypeMapObj + * @typedef {import('../types/mcdev.d.js').MultiMetadataTypeList} MultiMetadataTypeList + * @typedef {import('../types/mcdev.d.js').SoapRequestParams} SoapRequestParams + * @typedef {import('../types/mcdev.d.js').TemplateMap} TemplateMap + */ +/** + * Builds metadata from a template using market specific customisation + */ +declare class Builder { + /** + * Build a template based on a list of metadata files in the retrieve folder. + * + * @param {string} businessUnit references credentials from properties.json + * @param {string} selectedType supported metadata type + * @param {string[]} keyArr customerkey of the metadata + * @param {string[]} marketArr market localizations + * @returns {Promise.<MultiMetadataTypeList>} - + */ + static buildTemplate(businessUnit: string, selectedType: string, keyArr: string[], marketArr: string[]): Promise<MultiMetadataTypeList>; + /** + * Build a specific metadata file based on a template. + * + * @param {string} businessUnit references credentials from properties.json + * @param {string} selectedType supported metadata type + * @param {string[]} nameArr name of the metadata + * @param {string[]} marketArr market localizations + * @returns {Promise.<MultiMetadataTypeList>} - + */ + static buildDefinition(businessUnit: string, selectedType: string, nameArr: string[], marketArr: string[]): Promise<MultiMetadataTypeList>; + /** + * Build a specific metadata file based on a template using a list of bu-market combos + * + * @param {string} listName name of list of BU-market combos + * @param {string} type supported metadata type + * @param {string[]} nameArr name of the metadata + * @returns {Promise.<object>} - + */ + static buildDefinitionBulk(listName: string, type: string, nameArr: string[]): Promise<object>; + /** + * helper for buildDefinitionBulk, createDeltaPkg + * + * @param {string} listName market list name + * @returns {Promise.<void>} - + */ + static purgeDeployFolderList(listName: string): Promise<void>; + /** + * helper for buildDefiniton, purgeDeployFolderList + * + * @param {string} businessUnit cred/bu combo + * @returns {Promise.<void>} - + */ + static purgeDeployFolder(businessUnit: string): Promise<void>; + /** + * Creates a Builder, uses v2 auth if v2AuthOptions are passed. + * + * @param {Mcdevrc} properties properties for auth +saved + * @param {BuObject} buObject properties for auth + */ + constructor(properties: Mcdevrc, buObject: BuObject); + properties: import("../types/mcdev.d.js").Mcdevrc; + templateDir: string; + retrieveDir: string; + buObject: import("../types/mcdev.d.js").BuObject; + targetDir: string[]; + /** + * @type {MultiMetadataTypeList} + */ + metadata: MultiMetadataTypeList; + /** + * Builds a specific metadata file by name + * + * @param {string} metadataType metadata type to build + * @param {string[]} nameArr name of metadata to build + * @param {TemplateMap} templateVariables variables to be replaced in the metadata + * @returns {Promise.<MultiMetadataTypeList>} Promise + */ + _buildDefinition(metadataType: string, nameArr: string[], templateVariables: TemplateMap): Promise<MultiMetadataTypeList>; + /** + * Build a template based on a list of metadata files in the retrieve folder. + * + * @param {string} metadataType metadata type to create a template of + * @param {string[]} keyArr customerkey of metadata to create a template of + * @param {TemplateMap} templateVariables variables to be replaced in the metadata + * @returns {Promise.<MultiMetadataTypeList>} Promise + */ + _buildTemplate(metadataType: string, keyArr: string[], templateVariables: TemplateMap): Promise<MultiMetadataTypeList>; +} +//# sourceMappingURL=Builder.d.ts.map \ No newline at end of file diff --git a/@types/lib/Builder.d.ts.map b/@types/lib/Builder.d.ts.map new file mode 100644 index 000000000..93c42539c --- /dev/null +++ b/@types/lib/Builder.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"Builder.d.ts","sourceRoot":"","sources":["../../lib/Builder.js"],"names":[],"mappings":";uBAUa,OAAO,qBAAqB,EAAE,QAAQ;0BACtC,OAAO,qBAAqB,EAAE,WAAW;8BACzC,OAAO,qBAAqB,EAAE,eAAe;sBAC7C,OAAO,qBAAqB,EAAE,OAAO;+BACrC,OAAO,qBAAqB,EAAE,gBAAgB;mCAC9C,OAAO,qBAAqB,EAAE,oBAAoB;kCAClD,OAAO,qBAAqB,EAAE,mBAAmB;8BACjD,OAAO,qBAAqB,EAAE,eAAe;iCAC7C,OAAO,qBAAqB,EAAE,kBAAkB;oCAChD,OAAO,qBAAqB,EAAE,qBAAqB;gCACnD,OAAO,qBAAqB,EAAE,iBAAiB;0BAC/C,OAAO,qBAAqB,EAAE,WAAW;AAZtD;;;;;;;;;;;;;GAaG;AAEH;;GAEG;AACH;IA4EI;;;;;;;;OAQG;IACH,mCANW,MAAM,gBACN,MAAM,UACN,MAAM,EAAE,aACR,MAAM,EAAE,GACN,OAAO,CAAE,qBAAqB,CAAC,CAkC3C;IAoDD;;;;;;;;OAQG;IACH,qCANW,MAAM,gBACN,MAAM,WACN,MAAM,EAAE,aACR,MAAM,EAAE,GACN,OAAO,CAAE,qBAAqB,CAAC,CAmC3C;IAED;;;;;;;OAOG;IACH,qCALW,MAAM,QACN,MAAM,WACN,MAAM,EAAE,GACN,OAAO,CAAE,MAAM,CAAC,CAuD5B;IACD;;;;;OAKG;IACH,uCAHW,MAAM,GACJ,OAAO,CAAE,IAAI,CAAC,CAiB1B;IACD;;;;;OAKG;IACH,uCAHW,MAAM,GACJ,OAAO,CAAE,IAAI,CAAC,CAuB1B;IAnUD;;;;;;OAMG;IACH,wBAJW,OAAO,YAEP,QAAQ,EA4BlB;IAzBG,kDAA4B;IAC5B,oBAAkD;IAClD,oBAIE;IACF,iDAAwB;IAMxB,oBAMC;IAED;;OAEG;IACH,UAFU,qBAAqB,CAEb;IAGtB;;;;;;;OAOG;IACH,+BALW,MAAM,WACN,MAAM,EAAE,qBACR,WAAW,GACT,OAAO,CAAE,qBAAqB,CAAC,CAgC3C;IA6CD;;;;;;;OAOG;IACH,6BALW,MAAM,UACN,MAAM,EAAE,qBACR,WAAW,GACT,OAAO,CAAE,qBAAqB,CAAC,CA0C3C;CA8JJ"} \ No newline at end of file diff --git a/@types/lib/Deployer.d.ts b/@types/lib/Deployer.d.ts new file mode 100644 index 000000000..a74fb1468 --- /dev/null +++ b/@types/lib/Deployer.d.ts @@ -0,0 +1,102 @@ +export default Deployer; +export type BuObject = import("../types/mcdev.d.js").BuObject; +export type CodeExtract = import("../types/mcdev.d.js").CodeExtract; +export type CodeExtractItem = import("../types/mcdev.d.js").CodeExtractItem; +export type Mcdevrc = import("../types/mcdev.d.js").Mcdevrc; +export type MetadataTypeItem = import("../types/mcdev.d.js").MetadataTypeItem; +export type MetadataTypeItemDiff = import("../types/mcdev.d.js").MetadataTypeItemDiff; +export type MetadataTypeItemObj = import("../types/mcdev.d.js").MetadataTypeItemObj; +export type MetadataTypeMap = import("../types/mcdev.d.js").MetadataTypeMap; +export type MetadataTypeMapObj = import("../types/mcdev.d.js").MetadataTypeMapObj; +export type MultiMetadataTypeList = import("../types/mcdev.d.js").MultiMetadataTypeList; +export type SoapRequestParams = import("../types/mcdev.d.js").SoapRequestParams; +export type TemplateMap = import("../types/mcdev.d.js").TemplateMap; +export type MultiMetadataTypeMap = import("../types/mcdev.d.js").MultiMetadataTypeMap; +export type TypeKeyCombo = import("../types/mcdev.d.js").TypeKeyCombo; +export type ListMap = import("../types/mcdev.d.js").ListMap; +/** + * @typedef {import('../types/mcdev.d.js').BuObject} BuObject + * @typedef {import('../types/mcdev.d.js').CodeExtract} CodeExtract + * @typedef {import('../types/mcdev.d.js').CodeExtractItem} CodeExtractItem + * @typedef {import('../types/mcdev.d.js').Mcdevrc} Mcdevrc + * @typedef {import('../types/mcdev.d.js').MetadataTypeItem} MetadataTypeItem + * @typedef {import('../types/mcdev.d.js').MetadataTypeItemDiff} MetadataTypeItemDiff + * @typedef {import('../types/mcdev.d.js').MetadataTypeItemObj} MetadataTypeItemObj + * @typedef {import('../types/mcdev.d.js').MetadataTypeMap} MetadataTypeMap + * @typedef {import('../types/mcdev.d.js').MetadataTypeMapObj} MetadataTypeMapObj + * @typedef {import('../types/mcdev.d.js').MultiMetadataTypeList} MultiMetadataTypeList + * @typedef {import('../types/mcdev.d.js').SoapRequestParams} SoapRequestParams + * @typedef {import('../types/mcdev.d.js').TemplateMap} TemplateMap + * @typedef {import('../types/mcdev.d.js').MultiMetadataTypeMap} MultiMetadataTypeMap + * @typedef {import('../types/mcdev.d.js').TypeKeyCombo} TypeKeyCombo + * + * @typedef {import('../types/mcdev.d.js').ListMap} ListMap + */ +/** + * Reads metadata from local directory and deploys it to specified target business unit. + * Source and target business units are also compared before the deployment to apply metadata specific patches. + */ +declare class Deployer { + /** + * Deploys all metadata located in the 'deploy' directory to the specified business unit + * + * @param {string} businessUnit references credentials from properties.json + * @param {string[] | TypeKeyCombo} [selectedTypesArr] limit deployment to given metadata type + * @param {string[]} [keyArr] limit deployment to given metadata keys + * @returns {Promise.<Object.<string, MultiMetadataTypeMap>>} deployed metadata per BU (first key: bu name, second key: metadata type) + */ + static deploy(businessUnit: string, selectedTypesArr?: string[] | TypeKeyCombo, keyArr?: string[]): Promise<{ + [x: string]: MultiMetadataTypeMap; + }>; + /** + * helper for {@link Deployer.deploy} + * + * @param {string} cred name of Credential + * @param {string} bu name of BU + * @param {Mcdevrc} properties General configuration to be used in retrieve + * @param {string[] | TypeKeyCombo} [typeArr] limit deployment to given metadata type + * @param {string[]} [keyArr] limit deployment to given metadata keys + * @returns {Promise.<MultiMetadataTypeMap>} ensure that BUs are worked on sequentially + */ + static _deployBU(cred: string, bu: string, properties: Mcdevrc, typeArr?: string[] | TypeKeyCombo, keyArr?: string[]): Promise<MultiMetadataTypeMap>; + /** + * Returns metadata of a business unit that is saved locally + * + * @param {string} deployDir root directory of metadata. + * @param {string[]} [typeArr] limit deployment to given metadata type + * @param {boolean} [listBadKeys] do not print errors, used for badKeys() + * @returns {Promise.<MultiMetadataTypeMap>} Metadata of BU in local directory + */ + static readBUMetadata(deployDir: string, typeArr?: string[], listBadKeys?: boolean): Promise<MultiMetadataTypeMap>; + /** + * parses asset metadata to auto-create folders in target folder + * + * @param {string} deployDir root directory of metadata. + * @param {MultiMetadataTypeMap} metadata list of metadata + * @param {string[]} metadataTypeArr list of metadata types + * @returns {Promise.<object>} folder metadata + */ + static createFolderDefinitions(deployDir: string, metadata: MultiMetadataTypeMap, metadataTypeArr: string[]): Promise<object>; + /** + * Creates a Deployer, uses v2 auth if v2AuthOptions are passed. + * + * @param {Mcdevrc} properties General configuration to be used in retrieve + * @param {BuObject} buObject properties for auth + */ + constructor(properties: Mcdevrc, buObject: BuObject); + buObject: import("../types/mcdev.d.js").BuObject; + properties: import("../types/mcdev.d.js").Mcdevrc; + deployDir: string; + retrieveDir: string; + /** + * Deploy all metadata that is located in the deployDir + * + * @param {string[] | TypeKeyCombo} [types] limit deployment to given metadata type (can include subtype) + * @param {string[]} [keyArr] limit deployment to given metadata keys + * @returns {Promise.<MultiMetadataTypeMap>} Promise of all deployed metadata + */ + _deploy(types?: string[] | TypeKeyCombo, keyArr?: string[]): Promise<MultiMetadataTypeMap>; + /** @type {MultiMetadataTypeMap} */ + metadata: MultiMetadataTypeMap; +} +//# sourceMappingURL=Deployer.d.ts.map \ No newline at end of file diff --git a/@types/lib/Deployer.d.ts.map b/@types/lib/Deployer.d.ts.map new file mode 100644 index 000000000..5587dc0cf --- /dev/null +++ b/@types/lib/Deployer.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"Deployer.d.ts","sourceRoot":"","sources":["../../lib/Deployer.js"],"names":[],"mappings":";uBAYa,OAAO,qBAAqB,EAAE,QAAQ;0BACtC,OAAO,qBAAqB,EAAE,WAAW;8BACzC,OAAO,qBAAqB,EAAE,eAAe;sBAC7C,OAAO,qBAAqB,EAAE,OAAO;+BACrC,OAAO,qBAAqB,EAAE,gBAAgB;mCAC9C,OAAO,qBAAqB,EAAE,oBAAoB;kCAClD,OAAO,qBAAqB,EAAE,mBAAmB;8BACjD,OAAO,qBAAqB,EAAE,eAAe;iCAC7C,OAAO,qBAAqB,EAAE,kBAAkB;oCAChD,OAAO,qBAAqB,EAAE,qBAAqB;gCACnD,OAAO,qBAAqB,EAAE,iBAAiB;0BAC/C,OAAO,qBAAqB,EAAE,WAAW;mCACzC,OAAO,qBAAqB,EAAE,oBAAoB;2BAClD,OAAO,qBAAqB,EAAE,YAAY;sBAE1C,OAAO,qBAAqB,EAAE,OAAO;AAhBlD;;;;;;;;;;;;;;;;;GAiBG;AAEH;;;GAGG;AACH;IA0BI;;;;;;;OAOG;IACH,4BALW,MAAM,qBACN,MAAM,EAAE,GAAG,YAAY,WACvB,MAAM,EAAE,GACN,OAAO,CAAE;YAAQ,MAAM,GAAE,oBAAoB;KAAC,CAAC,CA2J3D;IAED;;;;;;;;;OASG;IACH,uBAPW,MAAM,MACN,MAAM,cACN,OAAO,YACP,MAAM,EAAE,GAAG,YAAY,WACvB,MAAM,EAAE,GACN,OAAO,CAAE,oBAAoB,CAAC,CAsB1C;IA8HD;;;;;;;OAOG;IACH,iCALW,MAAM,YACN,MAAM,EAAE,gBACR,OAAO,GACL,OAAO,CAAE,oBAAoB,CAAC,CA4B1C;IAED;;;;;;;OAOG;IACH,0CALW,MAAM,YACN,oBAAoB,mBACpB,MAAM,EAAE,GACN,OAAO,CAAE,MAAM,CAAC,CAkH5B;IApfD;;;;;OAKG;IACH,wBAHW,OAAO,YACP,QAAQ,EAmBlB;IAhBG,iDAAwB;IACxB,kDAA4B;IAC5B,kBAIE;IACF,oBAIE;IA0MN;;;;;;OAMG;IACH,gBAJW,MAAM,EAAE,GAAG,YAAY,WACvB,MAAM,EAAE,GACN,OAAO,CAAE,oBAAoB,CAAC,CAqH1C;IA7GO,mCAAmC;IACnC,UADW,oBAAoB,CACuC;CA2QjF"} \ No newline at end of file diff --git a/@types/lib/MetadataTypeDefinitions.d.ts b/@types/lib/MetadataTypeDefinitions.d.ts new file mode 100644 index 000000000..4c7a73663 --- /dev/null +++ b/@types/lib/MetadataTypeDefinitions.d.ts @@ -0,0 +1,88 @@ +declare namespace _default { + export { asset }; + export { attributeGroup }; + export { attributeSet }; + export { automation }; + export { campaign }; + export { contentArea }; + export { dataFilter }; + export { dataFilterHidden }; + export { dataExtension }; + export { dataExtensionField }; + export { dataExtensionTemplate }; + export { dataExtract }; + export { dataExtractType }; + export { deliveryProfile }; + export { discovery }; + export { domainVerification }; + export { email }; + export { emailSend }; + export { event }; + export { fileLocation }; + export { fileTransfer }; + export { filter }; + export { folder }; + export { importFile }; + export { journey }; + export { list }; + export { mobileCode }; + export { mobileKeyword }; + export { mobileMessage }; + export { query }; + export { role }; + export { script }; + export { sendClassification }; + export { senderProfile }; + export { transactionalMessage }; + export { transactionalEmail }; + export { transactionalPush }; + export { transactionalSMS }; + export { triggeredSend }; + export { triggeredSendSummary }; + export { user }; + export { verification }; +} +export default _default; +import asset from './metadataTypes/definitions/Asset.definition.js'; +import attributeGroup from './metadataTypes/definitions/AttributeGroup.definition.js'; +import attributeSet from './metadataTypes/definitions/AttributeSet.definition.js'; +import automation from './metadataTypes/definitions/Automation.definition.js'; +import campaign from './metadataTypes/definitions/Campaign.definition.js'; +import contentArea from './metadataTypes/definitions/ContentArea.definition.js'; +import dataFilter from './metadataTypes/definitions/DataFilter.definition.js'; +import dataFilterHidden from './metadataTypes/definitions/DataFilterHidden.definition.js'; +import dataExtension from './metadataTypes/definitions/DataExtension.definition.js'; +import dataExtensionField from './metadataTypes/definitions/DataExtensionField.definition.js'; +import dataExtensionTemplate from './metadataTypes/definitions/DataExtensionTemplate.definition.js'; +import dataExtract from './metadataTypes/definitions/DataExtract.definition.js'; +import dataExtractType from './metadataTypes/definitions/DataExtractType.definition.js'; +import deliveryProfile from './metadataTypes/definitions/DeliveryProfile.definition.js'; +import discovery from './metadataTypes/definitions/Discovery.definition.js'; +import domainVerification from './metadataTypes/definitions/DomainVerification.definition.js'; +import email from './metadataTypes/definitions/Email.definition.js'; +import emailSend from './metadataTypes/definitions/EmailSend.definition.js'; +import event from './metadataTypes/definitions/Event.definition.js'; +import fileLocation from './metadataTypes/definitions/FileLocation.definition.js'; +import fileTransfer from './metadataTypes/definitions/FileTransfer.definition.js'; +import filter from './metadataTypes/definitions/Filter.definition.js'; +import folder from './metadataTypes/definitions/Folder.definition.js'; +import importFile from './metadataTypes/definitions/ImportFile.definition.js'; +import journey from './metadataTypes/definitions/Journey.definition.js'; +import list from './metadataTypes/definitions/List.definition.js'; +import mobileCode from './metadataTypes/definitions/MobileCode.definition.js'; +import mobileKeyword from './metadataTypes/definitions/MobileKeyword.definition.js'; +import mobileMessage from './metadataTypes/definitions/MobileMessage.definition.js'; +import query from './metadataTypes/definitions/Query.definition.js'; +import role from './metadataTypes/definitions/Role.definition.js'; +import script from './metadataTypes/definitions/Script.definition.js'; +import sendClassification from './metadataTypes/definitions/SendClassification.definition.js'; +import senderProfile from './metadataTypes/definitions/SenderProfile.definition.js'; +import transactionalMessage from './metadataTypes/definitions/TransactionalMessage.definition.js'; +import transactionalEmail from './metadataTypes/definitions/TransactionalEmail.definition.js'; +import transactionalPush from './metadataTypes/definitions/TransactionalPush.definition.js'; +import transactionalSMS from './metadataTypes/definitions/TransactionalSMS.definition.js'; +import triggeredSend from './metadataTypes/definitions/TriggeredSend.definition.js'; +import triggeredSendSummary from './metadataTypes/definitions/TriggeredSendSummary.definition.js'; +import user from './metadataTypes/definitions/User.definition.js'; +import verification from './metadataTypes/definitions/Verification.definition.js'; +//# sourceMappingURL=MetadataTypeDefinitions.d.ts.map \ No newline at end of file diff --git a/@types/lib/MetadataTypeDefinitions.d.ts.map b/@types/lib/MetadataTypeDefinitions.d.ts.map new file mode 100644 index 000000000..ec5eb8fbf --- /dev/null +++ b/@types/lib/MetadataTypeDefinitions.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"MetadataTypeDefinitions.d.ts","sourceRoot":"","sources":["../../lib/MetadataTypeDefinitions.js"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;kBAEkB,iDAAiD;2BACxC,0DAA0D;yBAC5D,wDAAwD;uBAC1D,sDAAsD;qBACxD,oDAAoD;wBACjD,uDAAuD;uBACxD,sDAAsD;6BAChD,4DAA4D;0BAC/D,yDAAyD;+BACpD,8DAA8D;kCAC3D,iEAAiE;wBAC3E,uDAAuD;4BACnD,2DAA2D;4BAC3D,2DAA2D;sBACjE,qDAAqD;+BAC5C,8DAA8D;kBAC3E,iDAAiD;sBAC7C,qDAAqD;kBACzD,iDAAiD;yBAC1C,wDAAwD;yBACxD,wDAAwD;mBAC9D,kDAAkD;mBAClD,kDAAkD;uBAC9C,sDAAsD;oBACzD,mDAAmD;iBACtD,gDAAgD;uBAC1C,sDAAsD;0BACnD,yDAAyD;0BACzD,yDAAyD;kBACjE,iDAAiD;iBAClD,gDAAgD;mBAC9C,kDAAkD;+BACtC,8DAA8D;0BACnE,yDAAyD;iCAClD,gEAAgE;+BAClE,8DAA8D;8BAC/D,6DAA6D;6BAC9D,4DAA4D;0BAC/D,yDAAyD;iCAClD,gEAAgE;iBAChF,gDAAgD;yBACxC,wDAAwD"} \ No newline at end of file diff --git a/@types/lib/MetadataTypeInfo.d.ts b/@types/lib/MetadataTypeInfo.d.ts new file mode 100644 index 000000000..be56e5279 --- /dev/null +++ b/@types/lib/MetadataTypeInfo.d.ts @@ -0,0 +1,86 @@ +declare namespace _default { + export { asset }; + export { attributeGroup }; + export { attributeSet }; + export { automation }; + export { campaign }; + export { contentArea }; + export { dataExtension }; + export { dataExtensionField }; + export { dataExtensionTemplate }; + export { dataExtract }; + export { dataExtractType }; + export { dataFilter }; + export { dataFilterHidden }; + export { deliveryProfile }; + export { discovery }; + export { domainVerification }; + export { email }; + export { emailSend }; + export { event }; + export { fileLocation }; + export { fileTransfer }; + export { filter }; + export { folder }; + export { importFile }; + export { journey }; + export { list }; + export { mobileCode }; + export { mobileKeyword }; + export { mobileMessage }; + export { query }; + export { role }; + export { script }; + export { sendClassification }; + export { senderProfile }; + export { transactionalEmail }; + export { transactionalPush }; + export { transactionalSMS }; + export { triggeredSend }; + export { triggeredSendSummary }; + export { user }; + export { verification }; +} +export default _default; +import asset from './metadataTypes/Asset.js'; +import attributeGroup from './metadataTypes/AttributeGroup.js'; +import attributeSet from './metadataTypes/AttributeSet.js'; +import automation from './metadataTypes/Automation.js'; +import campaign from './metadataTypes/Campaign.js'; +import contentArea from './metadataTypes/ContentArea.js'; +import dataExtension from './metadataTypes/DataExtension.js'; +import dataExtensionField from './metadataTypes/DataExtensionField.js'; +import dataExtensionTemplate from './metadataTypes/DataExtensionTemplate.js'; +import dataExtract from './metadataTypes/DataExtract.js'; +import dataExtractType from './metadataTypes/DataExtractType.js'; +import dataFilter from './metadataTypes/DataFilter.js'; +import dataFilterHidden from './metadataTypes/DataFilterHidden.js'; +import deliveryProfile from './metadataTypes/DeliveryProfile.js'; +import discovery from './metadataTypes/Discovery.js'; +import domainVerification from './metadataTypes/DomainVerification.js'; +import email from './metadataTypes/Email.js'; +import emailSend from './metadataTypes/EmailSend.js'; +import event from './metadataTypes/Event.js'; +import fileLocation from './metadataTypes/FileLocation.js'; +import fileTransfer from './metadataTypes/FileTransfer.js'; +import filter from './metadataTypes/Filter.js'; +import folder from './metadataTypes/Folder.js'; +import importFile from './metadataTypes/ImportFile.js'; +import journey from './metadataTypes/Journey.js'; +import list from './metadataTypes/List.js'; +import mobileCode from './metadataTypes/MobileCode.js'; +import mobileKeyword from './metadataTypes/MobileKeyword.js'; +import mobileMessage from './metadataTypes/MobileMessage.js'; +import query from './metadataTypes/Query.js'; +import role from './metadataTypes/Role.js'; +import script from './metadataTypes/Script.js'; +import sendClassification from './metadataTypes/SendClassification.js'; +import senderProfile from './metadataTypes/SenderProfile.js'; +import transactionalEmail from './metadataTypes/TransactionalEmail.js'; +import transactionalPush from './metadataTypes/TransactionalPush.js'; +import transactionalSMS from './metadataTypes/TransactionalSMS.js'; +import triggeredSend from './metadataTypes/TriggeredSend.js'; +import triggeredSendSummary from './metadataTypes/TriggeredSendSummary.js'; +import user from './metadataTypes/User.js'; +import verification from './metadataTypes/Verification.js'; +//# sourceMappingURL=MetadataTypeInfo.d.ts.map \ No newline at end of file diff --git a/@types/lib/MetadataTypeInfo.d.ts.map b/@types/lib/MetadataTypeInfo.d.ts.map new file mode 100644 index 000000000..089c125be --- /dev/null +++ b/@types/lib/MetadataTypeInfo.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"MetadataTypeInfo.d.ts","sourceRoot":"","sources":["../../lib/MetadataTypeInfo.js"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;kBAEkB,0BAA0B;2BACjB,mCAAmC;yBACrC,iCAAiC;uBACnC,+BAA+B;qBACjC,6BAA6B;wBAC1B,gCAAgC;0BAG9B,kCAAkC;+BAC7B,uCAAuC;kCACpC,0CAA0C;wBACpD,gCAAgC;4BAC5B,oCAAoC;uBANzC,+BAA+B;6BACzB,qCAAqC;4BAMtC,oCAAoC;sBAC1C,8BAA8B;+BACrB,uCAAuC;kBACpD,0BAA0B;sBACtB,8BAA8B;kBAClC,0BAA0B;yBACnB,iCAAiC;yBACjC,iCAAiC;mBACvC,2BAA2B;mBAC3B,2BAA2B;uBACvB,+BAA+B;oBAClC,4BAA4B;iBAC/B,yBAAyB;uBACnB,+BAA+B;0BAC5B,kCAAkC;0BAClC,kCAAkC;kBAC1C,0BAA0B;iBAC3B,yBAAyB;mBACvB,2BAA2B;+BACf,uCAAuC;0BAC5C,kCAAkC;+BAC7B,uCAAuC;8BACxC,sCAAsC;6BACvC,qCAAqC;0BACxC,kCAAkC;iCAC3B,yCAAyC;iBACzD,yBAAyB;yBACjB,iCAAiC"} \ No newline at end of file diff --git a/@types/lib/Retriever.d.ts b/@types/lib/Retriever.d.ts new file mode 100644 index 000000000..e7b6ab8e2 --- /dev/null +++ b/@types/lib/Retriever.d.ts @@ -0,0 +1,66 @@ +export default Retriever; +export type BuObject = import("../types/mcdev.d.js").BuObject; +export type CodeExtract = import("../types/mcdev.d.js").CodeExtract; +export type CodeExtractItem = import("../types/mcdev.d.js").CodeExtractItem; +export type Mcdevrc = import("../types/mcdev.d.js").Mcdevrc; +export type MetadataTypeItem = import("../types/mcdev.d.js").MetadataTypeItem; +export type MetadataTypeItemDiff = import("../types/mcdev.d.js").MetadataTypeItemDiff; +export type MetadataTypeItemObj = import("../types/mcdev.d.js").MetadataTypeItemObj; +export type MetadataTypeMap = import("../types/mcdev.d.js").MetadataTypeMap; +export type MetadataTypeMapObj = import("../types/mcdev.d.js").MetadataTypeMapObj; +export type MultiMetadataTypeList = import("../types/mcdev.d.js").MultiMetadataTypeList; +export type MultiMetadataTypeMap = import("../types/mcdev.d.js").MultiMetadataTypeMap; +export type SoapRequestParams = import("../types/mcdev.d.js").SoapRequestParams; +export type TemplateMap = import("../types/mcdev.d.js").TemplateMap; +export type TypeKeyCombo = import("../types/mcdev.d.js").TypeKeyCombo; +/** + * @typedef {import('../types/mcdev.d.js').BuObject} BuObject + * @typedef {import('../types/mcdev.d.js').CodeExtract} CodeExtract + * @typedef {import('../types/mcdev.d.js').CodeExtractItem} CodeExtractItem + * @typedef {import('../types/mcdev.d.js').Mcdevrc} Mcdevrc + * @typedef {import('../types/mcdev.d.js').MetadataTypeItem} MetadataTypeItem + * @typedef {import('../types/mcdev.d.js').MetadataTypeItemDiff} MetadataTypeItemDiff + * @typedef {import('../types/mcdev.d.js').MetadataTypeItemObj} MetadataTypeItemObj + * @typedef {import('../types/mcdev.d.js').MetadataTypeMap} MetadataTypeMap + * @typedef {import('../types/mcdev.d.js').MetadataTypeMapObj} MetadataTypeMapObj + * @typedef {import('../types/mcdev.d.js').MultiMetadataTypeList} MultiMetadataTypeList + * @typedef {import('../types/mcdev.d.js').MultiMetadataTypeMap} MultiMetadataTypeMap + * @typedef {import('../types/mcdev.d.js').SoapRequestParams} SoapRequestParams + * @typedef {import('../types/mcdev.d.js').TemplateMap} TemplateMap + * @typedef {import('../types/mcdev.d.js').TypeKeyCombo} TypeKeyCombo + */ +/** + * Retrieves metadata from a business unit and saves it to the local filesystem. + */ +declare class Retriever { + /** + * Creates a Retriever, uses v2 auth if v2AuthOptions are passed. + * + * @param {Mcdevrc} properties General configuration to be used in retrieve + * @param {BuObject} buObject properties for auth + */ + constructor(properties: Mcdevrc, buObject: BuObject); + buObject: import("../types/mcdev.d.js").BuObject; + properties: import("../types/mcdev.d.js").Mcdevrc; + retrieveDir: string; + templateDir: string; + savePath: string; + /** + * Retrieve metadata of specified types into local file system and Retriever.metadata + * + * @param {string[]} metadataTypes list of metadata types to retrieve; can include subtypes! + * @param {string[] | TypeKeyCombo} [namesOrKeys] name of Metadata to retrieveAsTemplate or list of keys for normal retrieval + * @param {TemplateMap} [templateVariables] Object of values which can be replaced (in case of templating) + * @param {boolean} [changelogOnly] skip saving, only create json in memory + * @returns {Promise.<MultiMetadataTypeList>} Promise of a list of retrieved items grouped by type {automation:[...], query:[...]} + */ + retrieve(metadataTypes: string[], namesOrKeys?: string[] | TypeKeyCombo, templateVariables?: TemplateMap, changelogOnly?: boolean): Promise<MultiMetadataTypeList>; + /** + * helper for Retriever.retrieve to get all dependencies of the given types + * + * @param {string[]} metadataTypes list of metadata types to retrieve; can include subtypes! + * @returns {string[]} unique list dependent metadata types + */ + _getTypeDependencies(metadataTypes: string[]): string[]; +} +//# sourceMappingURL=Retriever.d.ts.map \ No newline at end of file diff --git a/@types/lib/Retriever.d.ts.map b/@types/lib/Retriever.d.ts.map new file mode 100644 index 000000000..f176853fa --- /dev/null +++ b/@types/lib/Retriever.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"Retriever.d.ts","sourceRoot":"","sources":["../../lib/Retriever.js"],"names":[],"mappings":";uBAUa,OAAO,qBAAqB,EAAE,QAAQ;0BACtC,OAAO,qBAAqB,EAAE,WAAW;8BACzC,OAAO,qBAAqB,EAAE,eAAe;sBAC7C,OAAO,qBAAqB,EAAE,OAAO;+BACrC,OAAO,qBAAqB,EAAE,gBAAgB;mCAC9C,OAAO,qBAAqB,EAAE,oBAAoB;kCAClD,OAAO,qBAAqB,EAAE,mBAAmB;8BACjD,OAAO,qBAAqB,EAAE,eAAe;iCAC7C,OAAO,qBAAqB,EAAE,kBAAkB;oCAChD,OAAO,qBAAqB,EAAE,qBAAqB;mCACnD,OAAO,qBAAqB,EAAE,oBAAoB;gCAClD,OAAO,qBAAqB,EAAE,iBAAiB;0BAC/C,OAAO,qBAAqB,EAAE,WAAW;2BACzC,OAAO,qBAAqB,EAAE,YAAY;AAdvD;;;;;;;;;;;;;;;GAeG;AAEH;;GAEG;AACH;IACI;;;;;OAKG;IACH,wBAHW,OAAO,YACP,QAAQ,EAYlB;IATG,iDAAwB;IACxB,kDAA4B;IAC5B,oBAAkD;IAClD,oBAAkD;IAClD,iBAIE;IAGN;;;;;;;;OAQG;IACH,wBANW,MAAM,EAAE,gBACR,MAAM,EAAE,GAAG,YAAY,sBACvB,WAAW,kBACX,OAAO,GACL,OAAO,CAAE,qBAAqB,CAAC,CAmK3C;IAED;;;;;OAKG;IACH,oCAHW,MAAM,EAAE,GACN,MAAM,EAAE,CAepB;CACJ"} \ No newline at end of file diff --git a/@types/lib/cli.d.ts b/@types/lib/cli.d.ts new file mode 100644 index 000000000..ee415fc4c --- /dev/null +++ b/@types/lib/cli.d.ts @@ -0,0 +1,3 @@ +#!/usr/bin/env node +export type TypeKeyCombo = import("../types/mcdev.d.js").TypeKeyCombo; +//# sourceMappingURL=cli.d.ts.map \ No newline at end of file diff --git a/@types/lib/cli.d.ts.map b/@types/lib/cli.d.ts.map new file mode 100644 index 000000000..2bf1d954a --- /dev/null +++ b/@types/lib/cli.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../../lib/cli.js"],"names":[],"mappings":";2BAgBa,OAAO,qBAAqB,EAAE,YAAY"} \ No newline at end of file diff --git a/@types/lib/index.d.ts b/@types/lib/index.d.ts new file mode 100644 index 000000000..294aa1516 --- /dev/null +++ b/@types/lib/index.d.ts @@ -0,0 +1,500 @@ +export default Mcdev; +export type BuObject = import("../types/mcdev.d.js").BuObject; +export type CodeExtract = import("../types/mcdev.d.js").CodeExtract; +export type CodeExtractItem = import("../types/mcdev.d.js").CodeExtractItem; +export type DeltaPkgItem = import("../types/mcdev.d.js").DeltaPkgItem; +export type Mcdevrc = import("../types/mcdev.d.js").Mcdevrc; +export type MetadataTypeItem = import("../types/mcdev.d.js").MetadataTypeItem; +export type MetadataTypeItemDiff = import("../types/mcdev.d.js").MetadataTypeItemDiff; +export type MetadataTypeItemObj = import("../types/mcdev.d.js").MetadataTypeItemObj; +export type MetadataTypeMap = import("../types/mcdev.d.js").MetadataTypeMap; +export type MetadataTypeMapObj = import("../types/mcdev.d.js").MetadataTypeMapObj; +export type MultiMetadataTypeList = import("../types/mcdev.d.js").MultiMetadataTypeList; +export type MultiMetadataTypeMap = import("../types/mcdev.d.js").MultiMetadataTypeMap; +export type SkipInteraction = import("../types/mcdev.d.js").SkipInteraction; +export type SoapRequestParams = import("../types/mcdev.d.js").SoapRequestParams; +export type TemplateMap = import("../types/mcdev.d.js").TemplateMap; +export type TypeKeyCombo = import("../types/mcdev.d.js").TypeKeyCombo; +export type ExplainType = import("../types/mcdev.d.js").ExplainType; +export type ContentBlockConversionTypes = import("../types/mcdev.d.js").ContentBlockConversionTypes; +export type BuildFilter = import("../types/mcdev.d.js").BuildFilter; +/** + * @typedef {import('../types/mcdev.d.js').BuObject} BuObject + * @typedef {import('../types/mcdev.d.js').CodeExtract} CodeExtract + * @typedef {import('../types/mcdev.d.js').CodeExtractItem} CodeExtractItem + * @typedef {import('../types/mcdev.d.js').DeltaPkgItem} DeltaPkgItem + * @typedef {import('../types/mcdev.d.js').Mcdevrc} Mcdevrc + * @typedef {import('../types/mcdev.d.js').MetadataTypeItem} MetadataTypeItem + * @typedef {import('../types/mcdev.d.js').MetadataTypeItemDiff} MetadataTypeItemDiff + * @typedef {import('../types/mcdev.d.js').MetadataTypeItemObj} MetadataTypeItemObj + * @typedef {import('../types/mcdev.d.js').MetadataTypeMap} MetadataTypeMap + * @typedef {import('../types/mcdev.d.js').MetadataTypeMapObj} MetadataTypeMapObj + * @typedef {import('../types/mcdev.d.js').MultiMetadataTypeList} MultiMetadataTypeList + * @typedef {import('../types/mcdev.d.js').MultiMetadataTypeMap} MultiMetadataTypeMap + * @typedef {import('../types/mcdev.d.js').SkipInteraction} SkipInteraction + * @typedef {import('../types/mcdev.d.js').SoapRequestParams} SoapRequestParams + * @typedef {import('../types/mcdev.d.js').TemplateMap} TemplateMap + * @typedef {import('../types/mcdev.d.js').TypeKeyCombo} TypeKeyCombo + * @typedef {import('../types/mcdev.d.js').ExplainType} ExplainType + * @typedef {import('../types/mcdev.d.js').ContentBlockConversionTypes} ContentBlockConversionTypes + * @typedef {import('../types/mcdev.d.js').BuildFilter} BuildFilter + */ +/** + * main class + */ +declare class Mcdev { + /** + * @returns {string} current version of mcdev + */ + static version(): string; + /** + * helper method to use unattended mode when including mcdev as a package + * + * @param {SkipInteraction} [skipInteraction] signals what to insert automatically for things usually asked via wizard + * @returns {void} + */ + static setSkipInteraction(skipInteraction?: SkipInteraction): void; + /** + * configures what is displayed in the console + * + * @param {object} argv list of command line parameters given by user + * @param {boolean} [argv.silent] only errors printed to CLI + * @param {boolean} [argv.verbose] chatty user CLI output + * @param {boolean} [argv.debug] enables developer output & features + * @returns {void} + */ + static setLoggingLevel(argv: { + silent?: boolean; + verbose?: boolean; + debug?: boolean; + }): void; + static knownOptions: string[]; + /** + * allows setting system wide / command related options + * + * @param {object} argv list of command line parameters given by user + * @returns {void} + */ + static setOptions(argv: object): void; + /** + * handler for 'mcdev createDeltaPkg + * + * @param {object} argv yargs parameters + * @param {string} [argv.commitrange] git commit range via positional + * @param {string} [argv.range] git commit range via option + * @param {string} [argv.filter] filter file paths that start with any + * @param {number} [argv.commitHistory] filter file paths that start with any + * @param {DeltaPkgItem[]} [argv.diffArr] list of files to include in delta package (skips git diff when provided) + * @returns {Promise.<DeltaPkgItem[]>} list of changed items + */ + static createDeltaPkg(argv: { + commitrange?: string; + range?: string; + filter?: string; + commitHistory?: number; + diffArr?: DeltaPkgItem[]; + }): Promise<DeltaPkgItem[]>; + /** + * @returns {Promise} . + */ + static selectTypes(): Promise<any>; + /** + * @returns {ExplainType[]} list of supported types with their apiNames + */ + static explainTypes(): ExplainType[]; + /** + * @returns {Promise.<boolean>} success flag + */ + static upgrade(): Promise<boolean>; + /** + * helper to show an off-the-logs message to users + */ + static "__#private@#welcomeMessage"(): void; + /** + * Retrieve all metadata from the specified business unit into the local file system. + * + * @param {string} businessUnit references credentials from properties.json + * @param {string[] | TypeKeyCombo} [selectedTypesArr] limit retrieval to given metadata type + * @param {string[]} [keys] limit retrieval to given metadata key + * @param {boolean} [changelogOnly] skip saving, only create json in memory + * @returns {Promise.<object>} - + */ + static retrieve(businessUnit: string, selectedTypesArr?: string[] | TypeKeyCombo, keys?: string[], changelogOnly?: boolean): Promise<object>; + /** + * helper for {@link Mcdev.retrieve} + * + * @param {string} cred name of Credential + * @param {string} bu name of BU + * @param {string[] | TypeKeyCombo} [selectedTypesArr] limit retrieval to given metadata type/subtype + * @param {string[]} [keys] limit retrieval to given metadata key + * @param {boolean} [changelogOnly] skip saving, only create json in memory + * @returns {Promise.<object>} ensure that BUs are worked on sequentially + */ + static "__#private@#retrieveBU"(cred: string, bu: string, selectedTypesArr?: string[] | TypeKeyCombo, keys?: string[], changelogOnly?: boolean): Promise<object>; + /** + * Deploys all metadata located in the 'deploy' directory to the specified business unit + * + * @param {string} businessUnit references credentials from properties.json + * @param {string[] | TypeKeyCombo} [selectedTypesArr] limit deployment to given metadata type + * @param {string[]} [keyArr] limit deployment to given metadata keys + * @returns {Promise.<Object.<string, MultiMetadataTypeMap>>} deployed metadata per BU (first key: bu name, second key: metadata type) + */ + static deploy(businessUnit: string, selectedTypesArr?: string[] | TypeKeyCombo, keyArr?: string[]): Promise<{ + [x: string]: MultiMetadataTypeMap; + }>; + /** + * Creates template file for properties.json + * + * @param {string} [credentialsName] identifying name of the installed package / project + * @returns {Promise.<void>} - + */ + static initProject(credentialsName?: string): Promise<void>; + /** + * Clones an existing project from git repository and installs it + * + * @returns {Promise.<void>} - + */ + static joinProject(): Promise<void>; + /** + * Refreshes BU names and ID's from MC instance + * + * @param {string} credentialsName identifying name of the installed package / project + * @returns {Promise.<void>} - + */ + static findBUs(credentialsName: string): Promise<void>; + /** + * Creates docs for supported metadata types in Markdown and/or HTML format + * + * @param {string} businessUnit references credentials from properties.json + * @param {string} type metadata type + * @returns {Promise.<void>} - + */ + static document(businessUnit: string, type: string): Promise<void>; + /** + * deletes metadata from MC instance by key + * + * @param {string} businessUnit references credentials from properties.json + * @param {string | TypeKeyCombo} selectedTypes supported metadata type (single) or complex object + * @param {string[] | string} [keys] Identifier of metadata + * @returns {Promise.<boolean>} true if successful, false otherwise + */ + static deleteByKey(businessUnit: string, selectedTypes: string | TypeKeyCombo, keys?: string[] | string): Promise<boolean>; + /** + * get name & key for provided id + * + * @param {string} businessUnit references credentials from properties.json + * @param {string} type supported metadata type + * @param {string} id Identifier of metadata + * @returns {Promise.<{key:string, name:string, path:string}>} key, name and path of metadata; null if not found + */ + static resolveId(businessUnit: string, type: string, id: string): Promise<{ + key: string; + name: string; + path: string; + }>; + /** + * ensures triggered sends are restarted to ensure they pick up on changes of the underlying emails + * + * @param {string} businessUnit references credentials from properties.json + * @param {string[] | TypeKeyCombo} selectedTypes limit to given metadata types + * @param {string[]} [keys] customerkey of the metadata + * @returns {Promise.<Object.<string, Object.<string, string[]>>>} key: business unit name, key2: type, value: list of affected item keys + */ + static refresh(businessUnit: string, selectedTypes: string[] | TypeKeyCombo, keys?: string[]): Promise<{ + [x: string]: { + [x: string]: string[]; + }; + }>; + /** + * method for contributors to get details on SOAP objects + * + * @param {string} type references credentials from properties.json + * @param {string} [businessUnit] defaults to first credential's ParentBU + * @returns {Promise.<void>} - + */ + static describeSoap(type: string, businessUnit?: string): Promise<void>; + /** + * Converts metadata to legacy format. Output is saved in 'converted' directory + * + * @param {string} businessUnit references credentials from properties.json + * @returns {Promise.<void>} - + */ + static badKeys(businessUnit: string): Promise<void>; + /** + * Retrieve a specific metadata file and templatise. + * + * @deprecated Use `retrieve` followed by `build` instead. `retrieveAsTemplate` will be removed in a future version. + * @param {string} businessUnit references credentials from properties.json + * @param {string} selectedType supported metadata type + * @param {string[]} name name of the metadata + * @param {string} market market which should be used to revert template + * @returns {Promise.<MultiMetadataTypeList>} - + */ + static retrieveAsTemplate(businessUnit: string, selectedType: string, name: string[], market: string): Promise<MultiMetadataTypeList>; + /** + * @param {string} businessUnit references credentials from properties.json + * @param {TypeKeyCombo} typeKeyList limit retrieval to given metadata type + * @returns {Promise.<TypeKeyCombo>} selected types including dependencies + */ + static addDependentCbReferences(businessUnit: string, typeKeyList: TypeKeyCombo): Promise<TypeKeyCombo>; + /** + * + * @param {string} businessUnit references credentials from properties.json + * @param {TypeKeyCombo} typeKeyList limit retrieval to given metadata type + * @returns {Promise.<TypeKeyCombo>} dependencies + */ + static addDependencies(businessUnit: string, typeKeyList: TypeKeyCombo): Promise<TypeKeyCombo>; + /** + * Build a template based on a list of metadata files in the retrieve folder. + * + * @param {string} businessUnitTemplate references credentials from properties.json + * @param {string} businessUnitDefinition references credentials from properties.json + * @param {TypeKeyCombo} typeKeyCombo limit retrieval to given metadata type + * @returns {Promise.<MultiMetadataTypeList | object>} response from buildDefinition + */ + static clone(businessUnitTemplate: string, businessUnitDefinition: string, typeKeyCombo: TypeKeyCombo): Promise<MultiMetadataTypeList | object>; + /** + * Build a template based on a list of metadata files in the retrieve folder. + * + * @param {string} businessUnitTemplate references credentials from properties.json + * @param {string} businessUnitDefinition references credentials from properties.json + * @param {TypeKeyCombo} typeKeyCombo limit retrieval to given metadata type + * @param {string[]} marketTemplate market localizations + * @param {string[]} marketDefinition market localizations + * @param {boolean} [bulk] runs buildDefinitionBulk instead of buildDefinition; requires marketList to be defined and given via marketDefinition + * @param {BuildFilter} [filter] market list specific filter for buildTemplate + * @returns {Promise.<MultiMetadataTypeList | object>} response from buildDefinition + */ + static build(businessUnitTemplate: string, businessUnitDefinition: string, typeKeyCombo: TypeKeyCombo, marketTemplate: string[], marketDefinition: string[], bulk?: boolean, filter?: BuildFilter): Promise<MultiMetadataTypeList | object>; + /** + * Build a template based on a list of metadata files in the retrieve folder. + * + * @param {string} businessUnit references credentials from properties.json + * @param {string | TypeKeyCombo} selectedTypes limit retrieval to given metadata type + * @param {string[] | undefined} keyArr customerkey of the metadata + * @param {string[]} marketArr market localizations + * @param {BuildFilter} [filter] market list specific filter + * @returns {Promise.<MultiMetadataTypeList>} - + */ + static buildTemplate(businessUnit: string, selectedTypes: string | TypeKeyCombo, keyArr: string[] | undefined, marketArr: string[], filter?: BuildFilter): Promise<MultiMetadataTypeList>; + /** + * helper for {@link buildTemplate} to apply include/exclude key filters + * + * @param {TypeKeyCombo | undefined} typeKeyList supported metadata type + * @param {BuildFilter} filter market list specific filter for buildTemplate + */ + static applyKeyFilters(typeKeyList: TypeKeyCombo | undefined, filter: BuildFilter): void; + /** + * Build a specific metadata file based on a template. + * + * @param {string} businessUnit references credentials from properties.json + * @param {boolean} [alwaysAsk] by default this code only runs if --retrieve is set; this flag allows to always ask + * @param {TypeKeyCombo} [selectedTypes] limit retrieval to given metadata type + * @param {TypeKeyCombo} [defaultPlusTheseTypes] if we run build for a non-standard type we need to tell it what to download on top + * @returns {Promise.<void>} - + */ + static _reRetrieve(businessUnit: string, alwaysAsk?: boolean, selectedTypes?: TypeKeyCombo, defaultPlusTheseTypes?: TypeKeyCombo): Promise<void>; + /** + * Build a specific metadata file based on a template. + * + * @param {string} businessUnit references credentials from properties.json + * @param {string | TypeKeyCombo} selectedTypes limit retrieval to given metadata type + * @param {string[] | undefined} nameArr name of the metadata + * @param {string[]} marketArr market localizations + * @returns {Promise.<MultiMetadataTypeList>} - + */ + static buildDefinition(businessUnit: string, selectedTypes: string | TypeKeyCombo, nameArr: string[] | undefined, marketArr: string[]): Promise<MultiMetadataTypeList>; + /** + * Build a specific metadata file based on a template using a list of bu-market combos + * + * @param {string} listName name of list of BU-market combos + * @param {string | TypeKeyCombo} selectedTypes supported metadata type + * @param {string[]} [nameArr] name of the metadata + * @returns {Promise.<object>} - + */ + static buildDefinitionBulk(listName: string, selectedTypes: string | TypeKeyCombo, nameArr?: string[]): Promise<object>; + /** + * + * @param {string} businessUnit references credentials from properties.json + * @param {string} selectedType supported metadata type + * @param {string[]} keyArr customerkey of the metadata + * @returns {Promise.<string[]>} list of all files that need to be committed in a flat array ['path/file1.ext', 'path/file2.ext'] + */ + static getFilesToCommit(businessUnit: string, selectedType: string, keyArr: string[]): Promise<string[]>; + /** + * Publish an item + * + * @param {string} businessUnit name of BU + * @param {string[] | TypeKeyCombo} selectedTypes limit to given metadata types + * @param {string[]} [keys] customerkey of the metadata + * @returns {Promise.<Object.<string, Object.<string, string[]>>>} key: business unit name, key2: type, value: list of affected item keys + */ + static publish(businessUnit: string, selectedTypes: string[] | TypeKeyCombo, keys?: string[]): Promise<{ + [x: string]: { + [x: string]: string[]; + }; + }>; + /** + * Publish an item + * + * @param {string} businessUnit name of BU + * @param {string[] | TypeKeyCombo} selectedTypes limit to given metadata types + * @param {string[]} [keys] customerkey of the metadata + * @returns {Promise.<Object.<string, Object.<string, string[]>>>} key: business unit name, key2: type, value: list of affected item keys + */ + static validate(businessUnit: string, selectedTypes: string[] | TypeKeyCombo, keys?: string[]): Promise<{ + [x: string]: { + [x: string]: string[]; + }; + }>; + /** + * Start/execute an item + * + * @param {string} businessUnit name of BU + * @param {string[] | TypeKeyCombo} selectedTypes limit to given metadata types + * @param {string[]} [keys] customerkey of the metadata + * @returns {Promise.<Object.<string, Object.<string, string[]>>>} key: business unit name, key2: type, value: list of affected item keys + */ + static execute(businessUnit: string, selectedTypes: string[] | TypeKeyCombo, keys?: string[]): Promise<{ + [x: string]: { + [x: string]: string[]; + }; + }>; + /** + * Schedule an item (shortcut for execute --schedule) + * + * @param {string} businessUnit name of BU + * @param {string[] | TypeKeyCombo} selectedTypes limit to given metadata types + * @param {string[]} [keys] customerkey of the metadata + * @returns {Promise.<Object.<string, Object.<string, string[]>>>} key: business unit name, key2: type, value: list of affected item keys + */ + static schedule(businessUnit: string, selectedTypes: string[] | TypeKeyCombo, keys?: string[]): Promise<{ + [x: string]: { + [x: string]: string[]; + }; + }>; + /** + * pause an item + * + * @param {string} businessUnit name of BU + * @param {string[] | TypeKeyCombo} selectedTypes limit to given metadata types + * @param {string[]} [keys] customerkey of the metadata + * @returns {Promise.<Object.<string, Object.<string, string[]>>>} key: business unit name, key2: type, value: list of affected item keys + */ + static pause(businessUnit: string, selectedTypes: string[] | TypeKeyCombo, keys?: string[]): Promise<{ + [x: string]: { + [x: string]: string[]; + }; + }>; + /** + * stop an item + * + * @param {string} businessUnit name of BU + * @param {string[] | TypeKeyCombo} selectedTypes limit to given metadata types + * @param {string[]} [keys] customerkey of the metadata + * @returns {Promise.<Object.<string, Object.<string, string[]>>>} key: business unit name, key2: type, value: list of affected item keys + */ + static stop(businessUnit: string, selectedTypes: string[] | TypeKeyCombo, keys?: string[]): Promise<{ + [x: string]: { + [x: string]: string[]; + }; + }>; + /** + * stop an item + * + * @param {string} businessUnit name of BU + * @param {TypeKeyCombo} selectedTypes limit to given metadata types + * @returns {Promise.<Object.<string, Object.<string, string[]>>>} key: business unit name, key2: type, value: list of affected item keys + */ + static audit(businessUnit: string, selectedTypes: TypeKeyCombo): Promise<{ + [x: string]: { + [x: string]: string[]; + }; + }>; + /** + * Updates the key to match the name field + * + * @param {string} businessUnit name of BU + * @param {TypeKeyCombo | undefined} selectedTypesObj limit retrieval to given metadata type + * @param {string} to what to replace with + * @param {string[]} [fromList] what to replace + * @returns {Promise.<Object.<string, object>>} key1: business unit name, key2:type value: list of fixed item keys + */ + static replaceCbReference(businessUnit: string, selectedTypesObj: TypeKeyCombo | undefined, to: string, fromList?: string[]): Promise<{ + [x: string]: object; + }>; + /** + * Updates the key to match the name field + * + * @param {string} businessUnit name of BU + * @param {string[] | TypeKeyCombo} selectedTypes limit retrieval to given metadata type + * @param {string[]} [keys] customerkey of the metadata + * @returns {Promise.<Object.<string, object>>} key1: business unit name, key2:type value: list of fixed item keys + */ + static fixKeys(businessUnit: string, selectedTypes: string[] | TypeKeyCombo, keys?: string[]): Promise<{ + [x: string]: object; + }>; + /** + * run a method across BUs + * + * @param {'schedule'|'execute'|'pause'|'stop'|'publish'|'validate'|'fixKeys'|'replaceCbReference'|'refresh'|'audit'} methodName what to run + * @param {string} businessUnit name of BU + * @param {string[] | TypeKeyCombo} [selectedTypes] limit to given metadata types + * @param {string[]} [keys] customerkey of the metadata + * @returns {Promise.<Object.<string, Object.<string, string[]>>>} key: business unit name, key2: type, value: list of affected item keys + */ + static "__#private@#runMethod"(methodName: "schedule" | "execute" | "pause" | "stop" | "publish" | "validate" | "fixKeys" | "replaceCbReference" | "refresh" | "audit", businessUnit: string, selectedTypes?: string[] | TypeKeyCombo, keys?: string[]): Promise<{ + [x: string]: { + [x: string]: string[]; + }; + }>; + /** + * helper for Mcdev.#runMethod + * + * @param {'schedule'|'execute'|'pause'|'stop'|'publish'|'validate'|'fixKeys'|'replaceCbReference'|'refresh'|'audit'} methodName what to run + * @param {string} cred name of Credential + * @param {string} bu name of BU + * @param {string} [type] limit execution to given metadata type + * @param {string[]} [keyArr] customerkey of the metadata + * @returns {Promise.<string[]>} list of keys that were affected + */ + static "__#private@#runOnBU"(methodName: "schedule" | "execute" | "pause" | "stop" | "publish" | "validate" | "fixKeys" | "replaceCbReference" | "refresh" | "audit", cred: string, bu: string, type?: string, keyArr?: string[]): Promise<string[]>; + /** + * helper for Mcdev.#runOnBU + * + * @param {string} selectedType limit execution to given metadata type + * @param {BuObject} buObject properties for auth + * @returns {Promise.<string[]>} keyArr + */ + static "__#private@#retrieveKeysWithLike"(selectedType: string, buObject: BuObject): Promise<string[]>; + /** + * Updates the key to match the name field + * + * @param {string} cred name of Credential + * @param {string} bu name of BU + * @param {string} type limit execution to given metadata type + * @param {string[]} [keyArr] customerkey of the metadata + * @returns {Promise.<string[]>} list of keys that were affected + */ + static "__#private@#fixKeys"(cred: string, bu: string, type: string, keyArr?: string[]): Promise<string[]>; + /** + * Updates the key to match the name field + * + * @param {string} cred name of Credential + * @param {string} bu name of BU + * @param {string} type limit execution to given metadata type + * @param {string[]} [keyArr] customerkey of the metadata + * @returns {Promise.<string[]>} list of keys that were affected + */ + static "__#private@#replaceCbReference"(cred: string, bu: string, type: string, keyArr?: string[]): Promise<string[]>; + /** + * helper to convert CSVs into an array. if only one value was given, it's also returned as an array + * + * @param {string|string[]|undefined} metadataOption potentially comma-separated value or null + * @param {string[]} [allowedIdentifiers] 'key', 'id', 'name' + * @param {boolean} [firstOnly] removes all but the first entry if enabled + * @returns {TypeKeyCombo} values split into an array. + */ + static metadataToTypeKey(metadataOption: string | string[] | undefined, allowedIdentifiers?: string[], firstOnly?: boolean): TypeKeyCombo; +} +//# sourceMappingURL=index.d.ts.map \ No newline at end of file diff --git a/@types/lib/index.d.ts.map b/@types/lib/index.d.ts.map new file mode 100644 index 000000000..0780d40b4 --- /dev/null +++ b/@types/lib/index.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../lib/index.js"],"names":[],"mappings":";uBAwBa,OAAO,qBAAqB,EAAE,QAAQ;0BACtC,OAAO,qBAAqB,EAAE,WAAW;8BACzC,OAAO,qBAAqB,EAAE,eAAe;2BAC7C,OAAO,qBAAqB,EAAE,YAAY;sBAC1C,OAAO,qBAAqB,EAAE,OAAO;+BACrC,OAAO,qBAAqB,EAAE,gBAAgB;mCAC9C,OAAO,qBAAqB,EAAE,oBAAoB;kCAClD,OAAO,qBAAqB,EAAE,mBAAmB;8BACjD,OAAO,qBAAqB,EAAE,eAAe;iCAC7C,OAAO,qBAAqB,EAAE,kBAAkB;oCAChD,OAAO,qBAAqB,EAAE,qBAAqB;mCACnD,OAAO,qBAAqB,EAAE,oBAAoB;8BAClD,OAAO,qBAAqB,EAAE,eAAe;gCAC7C,OAAO,qBAAqB,EAAE,iBAAiB;0BAC/C,OAAO,qBAAqB,EAAE,WAAW;2BACzC,OAAO,qBAAqB,EAAE,YAAY;0BAC1C,OAAO,qBAAqB,EAAE,WAAW;0CACzC,OAAO,qBAAqB,EAAE,2BAA2B;0BACzD,OAAO,qBAAqB,EAAE,WAAW;AAnBtD;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH;;GAEG;AACH;IACI;;OAEG;IACH,kBAFa,MAAM,CAKlB;IAED;;;;;OAKG;IACH,4CAHW,eAAe,GACb,IAAI,CAIhB;IAED;;;;;;;;OAQG;IACH,6BALG;QAAuB,MAAM,GAArB,OAAO;QACQ,OAAO,GAAtB,OAAO;QACQ,KAAK,GAApB,OAAO;KACf,GAAU,IAAI,CAIhB;IACD,8BAwCE;IAEF;;;;;OAKG;IACH,wBAHW,MAAM,GACJ,IAAI,CAoBhB;IAED;;;;;;;;;;OAUG;IACH,4BAPG;QAAsB,WAAW,GAAzB,MAAM;QACQ,KAAK,GAAnB,MAAM;QACQ,MAAM,GAApB,MAAM;QACQ,aAAa,GAA3B,MAAM;QACgB,OAAO,GAA7B,YAAY,EAAE;KACtB,GAAU,OAAO,CAAE,YAAY,EAAE,CAAC,CA6BpC;IAED;;OAEG;IACH,mCAQC;IAED;;OAEG;IACH,uBAFa,WAAW,EAAE,CAIzB;IAED;;OAEG;IACH,kBAFa,OAAO,CAAE,OAAO,CAAC,CAc7B;IAED;;OAEG;IACH,4CA6BC;IAED;;;;;;;;OAQG;IACH,8BANW,MAAM,qBACN,MAAM,EAAE,GAAG,YAAY,SACvB,MAAM,EAAE,kBACR,OAAO,GACL,OAAO,CAAE,MAAM,CAAC,CAsH5B;IAED;;;;;;;;;OASG;IACH,sCAPW,MAAM,MACN,MAAM,qBACN,MAAM,EAAE,GAAG,YAAY,SACvB,MAAM,EAAE,kBACR,OAAO,GACL,OAAO,CAAE,MAAM,CAAC,CA2G5B;IAED;;;;;;;OAOG;IACH,4BALW,MAAM,qBACN,MAAM,EAAE,GAAG,YAAY,WACvB,MAAM,EAAE,GACN,OAAO,CAAE;YAAQ,MAAM,GAAE,oBAAoB;KAAC,CAAC,CAS3D;IAED;;;;;OAKG;IACH,qCAHW,MAAM,GACJ,OAAO,CAAE,IAAI,CAAC,CAW1B;IAED;;;;OAIG;IACH,sBAFa,OAAO,CAAE,IAAI,CAAC,CAU1B;IAED;;;;;OAKG;IACH,gCAHW,MAAM,GACJ,OAAO,CAAE,IAAI,CAAC,CAc1B;IAED;;;;;;OAMG;IACH,8BAJW,MAAM,QACN,MAAM,GACJ,OAAO,CAAE,IAAI,CAAC,CAiC1B;IAED;;;;;;;OAOG;IACH,iCALW,MAAM,iBACN,MAAM,GAAG,YAAY,SACrB,MAAM,EAAE,GAAG,MAAM,GACf,OAAO,CAAE,OAAO,CAAC,CA+E7B;IAED;;;;;;;OAOG;IACH,+BALW,MAAM,QACN,MAAM,MACN,MAAM,GACJ,OAAO,CAAE;QAAC,GAAG,EAAC,MAAM,CAAC;QAAC,IAAI,EAAC,MAAM,CAAC;QAAC,IAAI,EAAC,MAAM,CAAA;KAAC,CAAC,CAoC5D;IAED;;;;;;;OAOG;IACH,6BALW,MAAM,iBACN,MAAM,EAAE,GAAG,YAAY,SACvB,MAAM,EAAE,GACN,OAAO,CAAE;YAAQ,MAAM,GAAE;gBAAQ,MAAM,GAAE,MAAM,EAAE;SAAC;KAAC,CAAC,CAIhE;IAED;;;;;;OAMG;IACH,0BAJW,MAAM,iBACN,MAAM,GACJ,OAAO,CAAE,IAAI,CAAC,CA2C1B;IAED;;;;;OAKG;IACH,6BAHW,MAAM,GACJ,OAAO,CAAE,IAAI,CAAC,CAkE1B;IAED;;;;;;;;;OASG;IACH,wCANW,MAAM,gBACN,MAAM,QACN,MAAM,EAAE,UACR,MAAM,GACJ,OAAO,CAAE,qBAAqB,CAAC,CAkC3C;IAED;;;;OAIG;IACH,8CAJW,MAAM,eACN,YAAY,GACV,OAAO,CAAE,YAAY,CAAC,CA2FlC;IAED;;;;;OAKG;IACH,qCAJW,MAAM,eACN,YAAY,GACV,OAAO,CAAE,YAAY,CAAC,CAwElC;IAED;;;;;;;OAOG;IACH,mCALW,MAAM,0BACN,MAAM,gBACN,YAAY,GACV,OAAO,CAAE,qBAAqB,GAAG,MAAM,CAAC,CAUpD;IAED;;;;;;;;;;;OAWG;IACH,mCATW,MAAM,0BACN,MAAM,gBACN,YAAY,kBACZ,MAAM,EAAE,oBACR,MAAM,EAAE,SACR,OAAO,WACP,WAAW,GACT,OAAO,CAAE,qBAAqB,GAAG,MAAM,CAAC,CAiFpD;IAED;;;;;;;;;OASG;IACH,mCAPW,MAAM,iBACN,MAAM,GAAG,YAAY,UACrB,MAAM,EAAE,GAAG,SAAS,aACpB,MAAM,EAAE,WACR,WAAW,GACT,OAAO,CAAE,qBAAqB,CAAC,CAkG3C;IAED;;;;;OAKG;IACH,oCAHW,YAAY,GAAG,SAAS,UACxB,WAAW,QAwErB;IAED;;;;;;;;OAQG;IACH,iCANW,MAAM,cACN,OAAO,kBACP,YAAY,0BACZ,YAAY,GACV,OAAO,CAAE,IAAI,CAAC,CAwC1B;IAED;;;;;;;;OAQG;IACH,qCANW,MAAM,iBACN,MAAM,GAAG,YAAY,WACrB,MAAM,EAAE,GAAG,SAAS,aACpB,MAAM,EAAE,GACN,OAAO,CAAE,qBAAqB,CAAC,CA0C3C;IAED;;;;;;;OAOG;IACH,qCALW,MAAM,iBACN,MAAM,GAAG,YAAY,YACrB,MAAM,EAAE,GACN,OAAO,CAAE,MAAM,CAAC,CAwC5B;IAED;;;;;;OAMG;IACH,sCALW,MAAM,gBACN,MAAM,UACN,MAAM,EAAE,GACN,OAAO,CAAE,MAAM,EAAE,CAAC,CAsB9B;IAED;;;;;;;OAOG;IACH,6BALW,MAAM,iBACN,MAAM,EAAE,GAAG,YAAY,SACvB,MAAM,EAAE,GACN,OAAO,CAAE;YAAQ,MAAM,GAAE;gBAAQ,MAAM,GAAE,MAAM,EAAE;SAAC;KAAC,CAAC,CAIhE;IACD;;;;;;;OAOG;IACH,8BALW,MAAM,iBACN,MAAM,EAAE,GAAG,YAAY,SACvB,MAAM,EAAE,GACN,OAAO,CAAE;YAAQ,MAAM,GAAE;gBAAQ,MAAM,GAAE,MAAM,EAAE;SAAC;KAAC,CAAC,CAIhE;IAED;;;;;;;OAOG;IACH,6BALW,MAAM,iBACN,MAAM,EAAE,GAAG,YAAY,SACvB,MAAM,EAAE,GACN,OAAO,CAAE;YAAQ,MAAM,GAAE;gBAAQ,MAAM,GAAE,MAAM,EAAE;SAAC;KAAC,CAAC,CAIhE;IAED;;;;;;;OAOG;IACH,8BALW,MAAM,iBACN,MAAM,EAAE,GAAG,YAAY,SACvB,MAAM,EAAE,GACN,OAAO,CAAE;YAAQ,MAAM,GAAE;gBAAQ,MAAM,GAAE,MAAM,EAAE;SAAC;KAAC,CAAC,CAIhE;IAED;;;;;;;OAOG;IACH,2BALW,MAAM,iBACN,MAAM,EAAE,GAAG,YAAY,SACvB,MAAM,EAAE,GACN,OAAO,CAAE;YAAQ,MAAM,GAAE;gBAAQ,MAAM,GAAE,MAAM,EAAE;SAAC;KAAC,CAAC,CAIhE;IAED;;;;;;;OAOG;IACH,0BALW,MAAM,iBACN,MAAM,EAAE,GAAG,YAAY,SACvB,MAAM,EAAE,GACN,OAAO,CAAE;YAAQ,MAAM,GAAE;gBAAQ,MAAM,GAAE,MAAM,EAAE;SAAC;KAAC,CAAC,CAIhE;IAED;;;;;;OAMG;IACH,2BAJW,MAAM,iBACN,YAAY,GACV,OAAO,CAAE;YAAQ,MAAM,GAAE;gBAAQ,MAAM,GAAE,MAAM,EAAE;SAAC;KAAC,CAAC,CAIhE;IAED;;;;;;;;OAQG;IACH,wCANW,MAAM,oBACN,YAAY,GAAG,SAAS,MACxB,MAAM,aACN,MAAM,EAAE,GACN,OAAO,CAAE;YAAQ,MAAM,GAAE,MAAM;KAAC,CAAC,CAmF7C;IAED;;;;;;;OAOG;IACH,6BALW,MAAM,iBACN,MAAM,EAAE,GAAG,YAAY,SACvB,MAAM,EAAE,GACN,OAAO,CAAE;YAAQ,MAAM,GAAE,MAAM;KAAC,CAAC,CA8E7C;IAED;;;;;;;;OAQG;IACH,2CANW,UAAU,GAAC,SAAS,GAAC,OAAO,GAAC,MAAM,GAAC,SAAS,GAAC,UAAU,GAAC,SAAS,GAAC,oBAAoB,GAAC,SAAS,GAAC,OAAO,gBACzG,MAAM,kBACN,MAAM,EAAE,GAAG,YAAY,SACvB,MAAM,EAAE,GACN,OAAO,CAAE;YAAQ,MAAM,GAAE;gBAAQ,MAAM,GAAE,MAAM,EAAE;SAAC;KAAC,CAAC,CAwPhE;IAED;;;;;;;;;OASG;IACH,yCAPW,UAAU,GAAC,SAAS,GAAC,OAAO,GAAC,MAAM,GAAC,SAAS,GAAC,UAAU,GAAC,SAAS,GAAC,oBAAoB,GAAC,SAAS,GAAC,OAAO,QACzG,MAAM,MACN,MAAM,SACN,MAAM,WACN,MAAM,EAAE,GACN,OAAO,CAAE,MAAM,EAAE,CAAC,CAuD9B;IAED;;;;;;OAMG;IACH,wDAJW,MAAM,YACN,QAAQ,GACN,OAAO,CAAE,MAAM,EAAE,CAAC,CA8D9B;IAED;;;;;;;;OAQG;IACH,mCANW,MAAM,MACN,MAAM,QACN,MAAM,WACN,MAAM,EAAE,GACN,OAAO,CAAE,MAAM,EAAE,CAAC,CA8E9B;IAED;;;;;;;;OAQG;IACH,8CANW,MAAM,MACN,MAAM,QACN,MAAM,WACN,MAAM,EAAE,GACN,OAAO,CAAE,MAAM,EAAE,CAAC,CA6E9B;IAED;;;;;;;OAOG;IACH,yCALW,MAAM,GAAC,MAAM,EAAE,GAAC,SAAS,uBACzB,MAAM,EAAE,cACR,OAAO,GACL,YAAY,CA4FxB;CACJ"} \ No newline at end of file diff --git a/@types/lib/metadataTypes/Asset.d.ts b/@types/lib/metadataTypes/Asset.d.ts new file mode 100644 index 000000000..43c32a558 --- /dev/null +++ b/@types/lib/metadataTypes/Asset.d.ts @@ -0,0 +1,1220 @@ +export default Asset; +export type BuObject = import("../../types/mcdev.d.js").BuObject; +export type CodeExtract = import("../../types/mcdev.d.js").CodeExtract; +export type CodeExtractItem = import("../../types/mcdev.d.js").CodeExtractItem; +export type MetadataTypeItem = import("../../types/mcdev.d.js").MetadataTypeItem; +export type MetadataTypeItemDiff = import("../../types/mcdev.d.js").MetadataTypeItemDiff; +export type MetadataTypeMap = import("../../types/mcdev.d.js").MetadataTypeMap; +export type SoapRequestParams = import("../../types/mcdev.d.js").SoapRequestParams; +export type TemplateMap = import("../../types/mcdev.d.js").TemplateMap; +export type TypeKeyCombo = import("../../types/mcdev.d.js").TypeKeyCombo; +export type AssetSubType = import("../../types/mcdev.d.js").AssetSubType; +export type AssetMap = import("../../types/mcdev.d.js").AssetMap; +export type AssetItem = import("../../types/mcdev.d.js").AssetItem; +export type AssetRequestParams = import("../../types/mcdev.d.js").AssetRequestParams; +export type ContentBlockConversionTypes = import("../../types/mcdev.d.js").ContentBlockConversionTypes; +/** + * @typedef {import('../../types/mcdev.d.js').BuObject} BuObject + * @typedef {import('../../types/mcdev.d.js').CodeExtract} CodeExtract + * @typedef {import('../../types/mcdev.d.js').CodeExtractItem} CodeExtractItem + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItem} MetadataTypeItem + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItemDiff} MetadataTypeItemDiff + * @typedef {import('../../types/mcdev.d.js').MetadataTypeMap} MetadataTypeMap + * @typedef {import('../../types/mcdev.d.js').SoapRequestParams} SoapRequestParams + * @typedef {import('../../types/mcdev.d.js').TemplateMap} TemplateMap + * @typedef {import('../../types/mcdev.d.js').TypeKeyCombo} TypeKeyCombo + */ +/** + * @typedef {import('../../types/mcdev.d.js').AssetSubType} AssetSubType + * @typedef {import('../../types/mcdev.d.js').AssetMap} AssetMap + * @typedef {import('../../types/mcdev.d.js').AssetItem} AssetItem + * @typedef {import('../../types/mcdev.d.js').AssetRequestParams} AssetRequestParams + * @typedef {import('../../types/mcdev.d.js').ContentBlockConversionTypes} ContentBlockConversionTypes + */ +/** + * FileTransfer MetadataType + * + * @augments MetadataType + */ +declare class Asset extends MetadataType { + /** + * Retrieves Metadata of Asset + * + * @param {string} retrieveDir Directory where retrieved metadata directory will be saved + * @param {void | string[]} _ unused parameter + * @param {string[]} [subTypeArr] optionally limit to a single AssetSubType + * @param {string} [key] customer key + * @param {boolean} [loadShared] optionally retrieve assets from other BUs that were shared with the current + * @returns {Promise.<{metadata: AssetMap, type: string}>} Promise + */ + static retrieve(retrieveDir: string, _: void | string[], subTypeArr?: string[], key?: string, loadShared?: boolean): Promise<{ + metadata: AssetMap; + type: string; + }>; + /** + * Retrieves asset metadata for caching + * + * @param {void | string[]} [_] parameter not used + * @param {string[]} [subTypeArr] optionally limit to a single subtype + * @param {void | string} [__] parameter not used + * @param {boolean} [loadShared] optionally retrieve assets from other BUs that were shared with the current + * @returns {Promise.<{metadata: AssetMap, type: string}>} Promise + */ + static retrieveForCache(_?: void | string[], subTypeArr?: string[], __?: void | string, loadShared?: boolean): Promise<{ + metadata: AssetMap; + type: string; + }>; + /** + * Retrieves asset metadata for templating + * + * @deprecated Use `retrieve` followed by `build` instead. `retrieveAsTemplate` will be removed in a future version. + * @param {string} templateDir Directory where retrieved metadata directory will be saved + * @param {string} name name of the metadata file + * @param {TemplateMap} templateVariables variables to be replaced in the metadata + * @param {AssetSubType} [selectedSubType] optionally limit to a single subtype + * @returns {Promise.<{metadata: AssetItem, type: string}>} Promise + */ + static retrieveAsTemplate(templateDir: string, name: string, templateVariables: TemplateMap, selectedSubType?: AssetSubType): Promise<{ + metadata: AssetItem; + type: string; + }>; + /** + * helper for {@link Asset.retrieve} + {@link Asset.retrieveAsTemplate} + * + * @private + * @returns {string[]} AssetSubType array + */ + private static _getSubTypes; + /** + * Returns Order in which metadata needs to be retrieved/deployed and skips components with missing components + * + * @param {AssetMap} metadataMap metadata thats about to be deployed + * @param {string} deployDir directory where deploy metadata are saved + * @returns {Promise.<AssetMap>} keyField => metadata map but sorted to ensure dependencies are deployed in correct order + */ + static _getUpsertOrderAndSkipMissing(metadataMap: AssetMap, deployDir: string): Promise<AssetMap>; + /** + * MetadataType upsert, after retrieving from target and comparing to check if create or update operation is needed. + * + * @param {AssetMap} metadataMap metadata mapped by their keyField + * @param {string} deployDir directory where deploy metadata are saved + * @returns {Promise.<AssetMap>} keyField => metadata map + */ + static upsert(metadataMap: AssetMap, deployDir: string): Promise<AssetMap>; + /** + * helper for {@link MetadataType.updateREST} and {@link MetadataType.updateSOAP} + * + * @param {MetadataTypeItem} metadataEntry a single metadata Entry + * @param {object} apiResponse varies depending on the API call + * @returns {Promise.<object>} apiResponse, potentially modified + */ + static postUpdateTasks(metadataEntry: MetadataTypeItem, apiResponse: object): Promise<object>; + /** + * Creates a single asset + * + * @param {AssetItem} metadata a single asset + * @returns {Promise} Promise + */ + static create(metadata: AssetItem): Promise<any>; + /** + * helper for {@link MetadataType.createREST} + * + * @param {MetadataTypeItem} metadataEntry a single metadata Entry + * @param {object} apiResponse varies depending on the API call + * @returns {Promise.<object>} apiResponse, potentially modified + */ + static postCreateTasks(metadataEntry: MetadataTypeItem, apiResponse: object): Promise<object>; + /** + * Updates a single asset + * + * @param {AssetItem} metadata a single asset + * @returns {Promise} Promise + */ + static update(metadata: AssetItem): Promise<any>; + /** + * Retrieves Metadata of a specific asset type + * + * @param {string|string[]} subType group of similar assets to put in a folder (ie. images) + * @param {string} [retrieveDir] target directory for saving assets + * @param {string} [key] key/id/name to filter by + * @param {TemplateMap} [templateVariables] variables to be replaced in the metadata + * @param {boolean} [loadShared] optionally retrieve assets from other BUs that were shared with the current + * @returns {Promise.<object[]>} Promise + */ + static requestSubType(subType: string | string[], retrieveDir?: string, key?: string, templateVariables?: TemplateMap, loadShared?: boolean): Promise<object[]>; + /** + * Retrieves extended metadata (files or extended content) of asset + * + * @param {Array} items array of items to retrieve + * @param {string} subType group of similar assets to put in a folder (ie. images) + * @param {string} retrieveDir target directory for saving assets + * @param {TemplateMap} [templateVariables] variables to be replaced in the metadata + * @returns {Promise.<MetadataTypeMap>} Promise + */ + static requestAndSaveExtended(items: any[], subType: string, retrieveDir: string, templateVariables?: TemplateMap): Promise<MetadataTypeMap>; + /** + * helper that reset the log level and prints errors + * + * @private + * @param {'info'|'verbose'|'debug'|'error'} loggerLevelBak original logger level + * @param {object[]} failed array of failed items + */ + private static _resetLogLevel; + /** + * Some metadata types store their actual content as a separate file, e.g. images + * This method retrieves these and saves them alongside the metadata json + * + * @param {AssetItem} metadata a single asset + * @param {string} subType group of similar assets to put in a folder (ie. images) + * @param {string} retrieveDir target directory for saving assets + * @returns {Promise.<void>} - + */ + static _retrieveExtendedFile(metadata: AssetItem, subType: string, retrieveDir: string): Promise<void>; + /** + * helper for {@link Asset.preDeployTasks} + * Some metadata types store their actual content as a separate file, e.g. images + * This method reads these from the local FS stores them in the metadata object allowing to deploy it + * + * @param {AssetItem} metadata a single asset + * @param {string} subType group of similar assets to put in a folder (ie. images) + * @param {string} deployDir directory of deploy files + * @param {boolean} [pathOnly] used by getFilesToCommit which does not need the binary file to be actually read + * @returns {Promise.<string>} if found will return the path of the binary file + */ + static _readExtendedFileFromFS(metadata: AssetItem, subType: string, deployDir: string, pathOnly?: boolean): Promise<string>; + /** + * manages post retrieve steps + * + * @param {AssetItem} metadata a single asset + * @returns {CodeExtractItem} metadata + */ + static postRetrieveTasks(metadata: AssetItem): CodeExtractItem; + /** + * helper for {@link Asset.postDeployTasks}. triggers a refresh of active triggerredSendDefinitions associated with the updated asset-message items. Gets executed if refresh option has been set. + * + * @private + * @param {MetadataTypeMap} metadata metadata mapped by their keyField + * @returns {Promise.<void>} - + */ + private static _refreshTriggeredSend; + /** + * prepares an asset definition for deployment + * + * @param {AssetItem} metadata a single asset + * @param {string} deployDir directory of deploy files + * @returns {Promise.<AssetItem>} Promise + */ + static preDeployTasks(metadata: AssetItem, deployDir: string): Promise<AssetItem>; + /** + * find the subType matching the extendedSubType + * + * @param {string} extendedSubType webpage, htmlblock, etc + * @returns {string} subType: block, message, other, etc + */ + static "__#private@#getMainSubtype"(extendedSubType: string): string; + /** + * determines the subtype of the current asset + * + * @private + * @param {AssetItem} metadata a single asset + * @returns {string} subtype + */ + private static _getSubtype; + /** + * helper for {@link MetadataType.buildDefinition} + * handles extracted code if any are found for complex types + * + * @param {string} templateDir Directory where metadata templates are stored + * @param {string} targetDir Directory where built definitions will be saved + * @param {AssetItem} metadata main JSON file that was read from file system + * @param {TemplateMap} templateVariables variables to be replaced in the metadata + * @param {string} templateName name of the template to be built + * @returns {Promise.<string[][]>} list of extracted files with path-parts provided as an array + */ + static buildDefinitionForNested(templateDir: string, targetDir: string, metadata: AssetItem, templateVariables: TemplateMap, templateName: string): Promise<string[][]>; + /** + * helper for {@link MetadataType.buildTemplate} + * handles extracted code if any are found for complex types + * + * @example assets of type codesnippetblock will result in 1 json and 1 amp/html file. both files need to be run through templating + * @param {string} templateDir Directory where metadata templates are stored + * @param {string|string[]} targetDir (List of) Directory where built definitions will be saved + * @param {AssetItem} metadata main JSON file that was read from file system + * @param {TemplateMap} templateVariables variables to be replaced in the metadata + * @param {string} templateName name of the template to be built + * @returns {Promise.<string[][]>} list of extracted files with path-parts provided as an array + */ + static buildTemplateForNested(templateDir: string, targetDir: string | string[], metadata: AssetItem, templateVariables: TemplateMap, templateName: string): Promise<string[][]>; + /** + * helper for {@link MetadataType.buildDefinition} + * handles extracted code if any are found for complex types + * + * @param {string} templateDir Directory where metadata templates are stored + * @param {string|string[]} targetDir (List of) Directory where built definitions will be saved + * @param {AssetItem} metadata main JSON file that was read from file system + * @param {TemplateMap} templateVariables variables to be replaced in the metadata + * @param {string} templateName name of the template to be built + * @param {'definition'|'template'} mode defines what we use this helper for + * @returns {Promise.<string[][]>} list of extracted files with path-parts provided as an array + */ + static _buildForNested(templateDir: string, targetDir: string | string[], metadata: AssetItem, templateVariables: TemplateMap, templateName: string, mode: "definition" | "template"): Promise<string[][]>; + /** + * generic script that retrieves the folder path from cache and updates the given metadata with it after retrieve + * + * @param {MetadataTypeItem} metadata a single script activity definition + * @param {boolean} [hideWarning] when checking content blocks we do want to set the folder path but if we cant, lets not cludder the log with warnings about it + */ + static setFolderPath(metadata: MetadataTypeItem, hideWarning?: boolean): void; + /** + * helper for {@link Asset.preDeployTasks} that loads extracted code content back into JSON + * + * @param {AssetItem} metadata a single asset definition + * @returns {Promise.<void>} fileList for templating (disregarded during deployment) + */ + static _preDeployTasksBocks(metadata: AssetItem): Promise<void>; + /** + * helper for {@link Asset.preDeployTasks} that loads extracted code content back into JSON + * + * @param {object} metadataSlots metadata.views.html.slots or deeper slots.<>.blocks.<>.slots + * @returns {Promise.<void>} - + */ + static _preDeployTasksBocks_slots(metadataSlots: object): Promise<void>; + /** + * helper for {@link Asset.preDeployTasks} that loads extracted code content back into JSON + * + * @param {AssetItem} metadata a single asset definition + * @param {string} deployDir directory of deploy files + * @param {string} subType asset-subtype name; full list in AssetSubType + * @param {string} [templateName] name of the template used to built defintion (prior applying templating) + * @param {boolean} [fileListOnly] does not read file contents nor update metadata if true + * @returns {Promise.<CodeExtract[]>} fileList for templating (disregarded during deployment) + */ + static _mergeCode(metadata: AssetItem, deployDir: string, subType: string, templateName?: string, fileListOnly?: boolean): Promise<CodeExtract[]>; + /** + * helper for {@link Asset.preDeployTasks} that loads extracted code content back into JSON + * + * @param {string} prefix usually the customerkey + * @param {object} metadataSlots metadata.views.html.slots or deeper slots.<>.blocks.<>.slots + * @param {string[]} readDirArr directory of deploy files + * @param {string} subtypeExtension asset-subtype name ending on -meta + * @param {string[]} subDirArr directory of files w/o leading deploy dir + * @param {object[]} fileList directory of files w/o leading deploy dir + * @param {string} customerKey external key of template (could have been changed if used during templating) + * @param {string} [templateName] name of the template used to built defintion (prior applying templating) + * @param {boolean} [fileListOnly] does not read file contents nor update metadata if true + * @returns {Promise.<void>} - + */ + static _mergeCode_slots(prefix: string, metadataSlots: object, readDirArr: string[], subtypeExtension: string, subDirArr: string[], fileList: object[], customerKey: string, templateName?: string, fileListOnly?: boolean): Promise<void>; + /** + * helper for {@link Asset.postRetrieveTasks} that finds code content in JSON and extracts it + * to allow saving that separately and formatted + * + * @param {AssetItem} metadata a single asset definition + * @returns {CodeExtractItem} { json: metadata, codeArr: object[], subFolder: string[] } + */ + static _extractCode(metadata: AssetItem): CodeExtractItem; + /** + * helper for {@link Asset.postRetrieveTasks} via {@link Asset._extractCode} + * + * @param {string} prefix usually the customerkey + * @param {object} metadataSlots metadata.views.html.slots or deeper slots.<>.blocks.<>.slots + * @param {object[]} codeArr to be extended array for extracted code + * @returns {void} + */ + static _extractCode_slots(prefix: string, metadataSlots: object, codeArr: object[]): void; + /** + * helper for {@link Asset.getJsonFromFS} that reads the file system for metadata files + * + * @param {string} currentdir directory to scan + * @param {string} subtype single subtype of asset + * @param {MetadataTypeMap} fileName2FileContent fileName => fileContent map + */ + static _getJsonFromFS(currentdir: string, subtype: string, fileName2FileContent: MetadataTypeMap): Promise<void>; + /** + * optional method used for some types to try a different folder structure + * + * @param {string} templateDir Directory where metadata templates are stored + * @param {string[]} typeDirArr current subdir for this type + * @param {string} templateName name of the metadata template + * @param {string} fileName name of the metadata template file w/o extension + * @returns {Promise.<string>} metadata in string form + */ + static readSecondaryFolder(templateDir: string, typeDirArr: string[], templateName: string, fileName: string): Promise<string>; + /** + * helper to allow us to select single metadata entries via REST + * + * @private + * @param {string} key customer key + * @returns {Promise.<string>} id value or null + */ + private static _getIdForSingleRetrieve; + /** + * helper to allow us to select single metadata entries via REST + * + * @private + * @param {string} id id field + * @returns {Promise.<string>} key value or null + */ + private static _getKeyForSingleRetrieve; + /** + * clean up after deleting a metadata item + * cannot use the generic method due to the complexity of how assets are saved to disk + * + * @param {string} key Identifier of metadata item + * @returns {Promise.<void>} - + */ + static postDeleteTasks(key: string): Promise<void>; + /** + * get name & key for provided id + * + * @param {string} id Identifier of metadata + * @returns {Promise.<{key:string, name:string, path:string, folder:string, mid:number, error:string, isShared:boolean}>} key, name and path of metadata; null if not found + */ + static resolveId(id: string): Promise<{ + key: string; + name: string; + path: string; + folder: string; + mid: number; + error: string; + isShared: boolean; + }>; + /** + * helper for {@link Asset.resolveId} that finds the path to the asset's code + * + * @param {string} subType asset subtype + * @param {object} item api response for metadata + * @param {string} buName owner business unit name + * @returns {Promise.<string>} path to the asset's code + */ + static "__#private@#getPath"(subType: string, item: object, buName: string): Promise<string>; + /** + * helper for {@link Asset.resolveId} that loads the JSON file for the asset + * + * @param {string} subType asset subtype + * @param {object} item api response for metadata + * @returns {Promise.<object>} JS object of the asset we loaded from disk + */ + static "__#private@#getJson"(subType: string, item: object): Promise<object>; + /** + * + * @param {MetadataTypeItem} item single metadata item + * @param {string} retrieveDir directory where metadata is saved + * @param {Set.<string>} [findAssetKeys] list of keys that were found referenced via ContentBlockByX; if set, method only gets keys and runs no updates + * @returns {Promise.<MetadataTypeItem>} key of the item that was updated + */ + static replaceCbReference(item: MetadataTypeItem, retrieveDir: string, findAssetKeys?: Set<string>): Promise<MetadataTypeItem>; + /** + * + * @param {string[]} keyArr limit retrieval to given metadata type + * @param {string} retrieveDir retrieve dir including cred and bu + * @param {Set.<string>} findAssetKeys list of keys that were found referenced via ContentBlockByX; if set, method only gets keys and runs no updates + * @returns {Promise.<Set.<string>>} found asset keys + */ + static getCbReferenceKeys(keyArr: string[], retrieveDir: string, findAssetKeys: Set<string>): Promise<Set<string>>; + /** + * @param {object} slots metadata.views.html.slots or deeper slots.<>.blocks.<>.slots + * @param {string[]} dependentKeyArr list of found keys + */ + static _getDependentFilesExtra(slots: object, dependentKeyArr: string[]): void; +} +declare namespace Asset { + let getJsonFromFSCache: { + [x: string]: any; + }; + let definition: { + bodyIteratorField: string; + dependencies: string[]; + dependencyGraph: { + asset: string[]; + }; + folderType: string; + hasExtended: boolean; + idField: string; + keyIsFixed: boolean; + keyField: string; + nameField: string; + folderIdField: string; + createdDateField: string; + createdNameField: string; + lastmodDateField: string; + lastmodNameField: string; + restPagination: boolean; + maxKeyLength: number; + type: string; + typeDescription: string; + typeRetrieveByDefault: string[]; + typeCdpByDefault: boolean; + typeName: string; + stringifyFieldsBeforeTemplate: string[]; + allowMatchingByName: boolean; + fields: { + activeDate: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + allowedBlocks: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + assetType: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'assetType.displayName': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'assetType.id': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'assetType.name': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + availableViews: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + modelVersion: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + blocks: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + businessUnitAvailability: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'businessUnitAvailability.%': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'businessUnitAvailability.%.view': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'businessUnitAvailability.%.update': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'businessUnitAvailability.%.delete': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'businessUnitAvailability.%.memberId': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'businessUnitAvailability.%.transferOwnership': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + category: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'category.id': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'category.name': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'category.parentId': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + channels: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + content: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'content.url': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + contentType: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'createdBy.email': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'createdBy.id': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'createdBy.name': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'createdBy.userId': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + createdDate: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + customerKey: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + customFields: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'data.campaigns': { + skipValidation: boolean; + }; + 'data.approvals': { + skipValidation: boolean; + }; + 'data.email': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'data.email.attributes': { + skipValidation: boolean; + }; + 'data.email.legacy': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'data.email.options': { + skipValidation: boolean; + }; + 'data.portfolio': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'data.site': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'data.site.content': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'data.site.content.url': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + description: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + design: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + enterpriseId: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + file: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'fileProperties.fileName': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'fileProperties.extension': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'fileProperties.externalUrl': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'fileProperties.fileSize': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'fileProperties.fileCreatedDate': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'fileProperties.width': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'fileProperties.height': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'fileProperties.publishedURL': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + id: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + legacyData: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + locked: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + maxBlocks: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + memberId: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + meta: { + skipValidation: boolean; + }; + minBlocks: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'modifiedBy.email': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'modifiedBy.id': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'modifiedBy.name': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'modifiedBy.userId': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + modifiedDate: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + name: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + objectID: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + owner: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'owner.email': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'owner.id': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'owner.name': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'owner.userId': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + sharingProperties: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'sharingProperties.localAssets': { + skipValidation: boolean; + }; + 'sharingProperties.sharedWith': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'sharingProperties.sharedFrom': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'sharingProperties.sharedFromMID': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'sharingProperties.sharingType': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + slots: { + skipValidation: boolean; + }; + 'status.id': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'status.name': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + superContent: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + tags: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + template: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + thumbnail: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + version: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + views: { + skipValidation: boolean; + }; + r__folder_Path: { + skipValidation: boolean; + }; + }; + subTypes: string[]; + crosslinkedSubTypes: string[]; + selflinkedSubTypes: string[]; + binarySubtypes: string[]; + extendedSubTypes: { + archive: string[]; + asset: string[]; + audio: string[]; + block: string[]; + cloudpage: string[]; + code: string[]; + coderesource: string[]; + document: string[]; + image: string[]; + message: string[]; + other: string[]; + rawimage: string[]; + template: string[]; + textfile: string[]; + video: string[]; + }; + typeMapping: { + asset: number; + file: number; + block: number; + template: number; + message: number; + custom: number; + default: number; + image: number; + rawimage: number; + video: number; + document: number; + audio: number; + archive: number; + code: number; + textfile: number; + ai: number; + psd: number; + pdd: number; + eps: number; + gif: number; + jpe: number; + jpeg: number; + jpg: number; + jp2: number; + jpx: number; + pict: number; + pct: number; + png: number; + tif: number; + tiff: number; + tga: number; + bmp: number; + wmf: number; + vsd: number; + pnm: number; + pgm: number; + pbm: number; + ppm: number; + svg: number; + '3fr': number; + ari: number; + arw: number; + bay: number; + cap: number; + crw: number; + cr2: number; + dcr: number; + dcs: number; + dng: number; + drf: number; + eip: number; + erf: number; + fff: number; + iiq: number; + k25: number; + kdc: number; + mef: number; + mos: number; + mrw: number; + nef: number; + nrw: number; + orf: number; + pef: number; + ptx: number; + pxn: number; + raf: number; + raw: number; + rw2: number; + rwl: number; + rwz: number; + srf: number; + sr2: number; + srw: number; + x3f: number; + '3gp': number; + '3gpp': number; + '3g2': number; + '3gp2': number; + asf: number; + avi: number; + m2ts: number; + mts: number; + dif: number; + dv: number; + mkv: number; + mpg: number; + f4v: number; + flv: number; + mjpg: number; + mjpeg: number; + mxf: number; + mpeg: number; + mp4: number; + m4v: number; + mp4v: number; + mov: number; + swf: number; + wmv: number; + rm: number; + ogv: number; + indd: number; + indt: number; + incx: number; + wwcx: number; + doc: number; + docx: number; + dot: number; + dotx: number; + mdb: number; + mpp: number; + ics: number; + xls: number; + xlsx: number; + xlk: number; + xlsm: number; + xlt: number; + xltm: number; + csv: number; + tsv: number; + tab: number; + pps: number; + ppsx: number; + ppt: number; + pptx: number; + pot: number; + thmx: number; + pdf: number; + ps: number; + qxd: number; + rtf: number; + sxc: number; + sxi: number; + sxw: number; + odt: number; + ods: number; + ots: number; + odp: number; + otp: number; + epub: number; + dvi: number; + key: number; + keynote: number; + pez: number; + aac: number; + m4a: number; + au: number; + aif: number; + aiff: number; + aifc: number; + mp3: number; + wav: number; + wma: number; + midi: number; + oga: number; + ogg: number; + ra: number; + vox: number; + voc: number; + '7z': number; + arj: number; + bz2: number; + cab: number; + gz: number; + gzip: number; + iso: number; + lha: number; + sit: number; + tgz: number; + jar: number; + rar: number; + tar: number; + zip: number; + gpg: number; + htm: number; + html: number; + xhtml: number; + xht: number; + css: number; + less: number; + sass: number; + js: number; + json: number; + atom: number; + rss: number; + xml: number; + xsl: number; + xslt: number; + md: number; + markdown: number; + as: number; + fla: number; + eml: number; + text: number; + txt: number; + freeformblock: number; + textblock: number; + htmlblock: number; + textplusimageblock: number; + imageblock: number; + abtestblock: number; + dynamicblock: number; + stylingblock: number; + einsteincontentblock: number; + webpage: number; + webtemplate: number; + templatebasedemail: number; + htmlemail: number; + textonlyemail: number; + socialshareblock: number; + socialfollowblock: number; + buttonblock: number; + layoutblock: number; + defaulttemplate: number; + smartcaptureblock: number; + smartcaptureformfieldblock: number; + smartcapturesubmitoptionsblock: number; + slotpropertiesblock: number; + externalcontentblock: number; + codesnippetblock: number; + rssfeedblock: number; + formstylingblock: number; + referenceblock: number; + imagecarouselblock: number; + customblock: number; + liveimageblock: number; + livesettingblock: number; + contentmap: number; + jsonmessage: number; + icemailformblock: number; + coderesource: number; + jscoderesource: number; + csscoderesource: number; + jsoncoderesource: number; + rsscoderesource: number; + textcoderesource: number; + xmlcoderesource: number; + cloudpages: number; + landingpage: number; + microsite: number; + interactivecontent: number; + }; + }; +} +import MetadataType from './MetadataType.js'; +//# sourceMappingURL=Asset.d.ts.map \ No newline at end of file diff --git a/@types/lib/metadataTypes/Asset.d.ts.map b/@types/lib/metadataTypes/Asset.d.ts.map new file mode 100644 index 000000000..82bfbc36e --- /dev/null +++ b/@types/lib/metadataTypes/Asset.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"Asset.d.ts","sourceRoot":"","sources":["../../../lib/metadataTypes/Asset.js"],"names":[],"mappings":";uBAca,OAAO,wBAAwB,EAAE,QAAQ;0BACzC,OAAO,wBAAwB,EAAE,WAAW;8BAC5C,OAAO,wBAAwB,EAAE,eAAe;+BAChD,OAAO,wBAAwB,EAAE,gBAAgB;mCACjD,OAAO,wBAAwB,EAAE,oBAAoB;8BACrD,OAAO,wBAAwB,EAAE,eAAe;gCAChD,OAAO,wBAAwB,EAAE,iBAAiB;0BAClD,OAAO,wBAAwB,EAAE,WAAW;2BAC5C,OAAO,wBAAwB,EAAE,YAAY;2BAI7C,OAAO,wBAAwB,EAAE,YAAY;uBAC7C,OAAO,wBAAwB,EAAE,QAAQ;wBACzC,OAAO,wBAAwB,EAAE,SAAS;iCAC1C,OAAO,wBAAwB,EAAE,kBAAkB;0CACnD,OAAO,wBAAwB,EAAE,2BAA2B;AAjBzE;;;;;;;;;;GAUG;AAEH;;;;;;GAMG;AAEH;;;;GAIG;AACH;IACI;;;;;;;;;OASG;IACH,6BAPW,MAAM,KACN,IAAI,GAAG,MAAM,EAAE,eACf,MAAM,EAAE,QACR,MAAM,eACN,OAAO,GACL,OAAO,CAAE;QAAC,QAAQ,EAAE,QAAQ,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAC,CAAC,CAuExD;IAED;;;;;;;;OAQG;IACH,4BANW,IAAI,GAAG,MAAM,EAAE,eACf,MAAM,EAAE,OACR,IAAI,GAAG,MAAM,eACb,OAAO,GACL,OAAO,CAAE;QAAC,QAAQ,EAAE,QAAQ,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAC,CAAC,CAIxD;IAED;;;;;;;;;OASG;IACH,uCANW,MAAM,QACN,MAAM,qBACN,WAAW,oBACX,YAAY,GACV,OAAO,CAAE;QAAC,QAAQ,EAAE,SAAS,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAC,CAAC,CA2BzD;IAED;;;;;OAKG;IACH,4BAeC;IAED;;;;;;OAMG;IACH,kDAJW,QAAQ,aACR,MAAM,GACJ,OAAO,CAAE,QAAQ,CAAC,CAoE9B;IAED;;;;;;OAMG;IACH,2BAJW,QAAQ,aACR,MAAM,GACJ,OAAO,CAAE,QAAQ,CAAC,CAW9B;IAED;;;;;;OAMG;IACH,sCAJW,gBAAgB,eAChB,MAAM,GACJ,OAAO,CAAE,MAAM,CAAC,CAM5B;IAED;;;;;OAKG;IACH,wBAHW,SAAS,gBAOnB;IAED;;;;;;OAMG;IACH,sCAJW,gBAAgB,eAChB,MAAM,GACJ,OAAO,CAAE,MAAM,CAAC,CAkB5B;IAED;;;;;OAKG;IACH,wBAHW,SAAS,gBAMnB;IAED;;;;;;;;;OASG;IACH,+BAPW,MAAM,GAAC,MAAM,EAAE,gBACf,MAAM,QACN,MAAM,sBACN,WAAW,eACX,OAAO,GACL,OAAO,CAAE,MAAM,EAAE,CAAC,CAuK9B;IAED;;;;;;;;OAQG;IACH,qDALW,MAAM,eACN,MAAM,sBACN,WAAW,GACT,OAAO,CAAE,eAAe,CAAC,CA2GrC;IAED;;;;;;OAMG;IACH,8BA+CC;IAED;;;;;;;;OAQG;IACH,uCALW,SAAS,WACT,MAAM,eACN,MAAM,GACJ,OAAO,CAAE,IAAI,CAAC,CAgB1B;IAED;;;;;;;;;;OAUG;IACH,yCANW,SAAS,WACT,MAAM,aACN,MAAM,aACN,OAAO,GACL,OAAO,CAAE,MAAM,CAAC,CA2B5B;IAED;;;;;OAKG;IACH,mCAHW,SAAS,GACP,eAAe,CAyE3B;IAuBD;;;;;;OAMG;IACH,qCAwCC;IAED;;;;;;OAMG;IACH,gCAJW,SAAS,aACT,MAAM,GACJ,OAAO,CAAE,SAAS,CAAC,CA4I/B;IAED;;;;;OAKG;IACH,qDAHW,MAAM,GACJ,MAAM,CAMlB;IAED;;;;;;OAMG;IACH,2BAOC;IAED;;;;;;;;;;OAUG;IACH,6CAPW,MAAM,aACN,MAAM,YACN,SAAS,qBACT,WAAW,gBACX,MAAM,GACJ,OAAO,CAAE,MAAM,EAAE,EAAE,CAAC,CAiBhC;IAED;;;;;;;;;;;OAWG;IACH,2CAPW,MAAM,aACN,MAAM,GAAC,MAAM,EAAE,YACf,SAAS,qBACT,WAAW,gBACX,MAAM,GACJ,OAAO,CAAE,MAAM,EAAE,EAAE,CAAC,CAiBhC;IAED;;;;;;;;;;;OAWG;IACH,oCARW,MAAM,aACN,MAAM,GAAC,MAAM,EAAE,YACf,SAAS,qBACT,WAAW,gBACX,MAAM,QACN,YAAY,GAAC,UAAU,GACrB,OAAO,CAAE,MAAM,EAAE,EAAE,CAAC,CA6GhC;IAED;;;;;OAKG;IACH,+BAHW,gBAAgB,gBAChB,OAAO,QAwCjB;IAmBD;;;;;OAKG;IACH,sCAHW,SAAS,GACP,OAAO,CAAE,IAAI,CAAC,CAsB1B;IAED;;;;;OAKG;IACH,iDAHW,MAAM,GACJ,OAAO,CAAE,IAAI,CAAC,CAyC1B;IAED;;;;;;;;;OASG;IACH,4BAPW,SAAS,aACT,MAAM,WACN,MAAM,iBACN,MAAM,iBACN,OAAO,GACL,OAAO,CAAE,WAAW,EAAE,CAAC,CAqWnC;IAED;;;;;;;;;;;;;OAaG;IACH,gCAXW,MAAM,iBACN,MAAM,cACN,MAAM,EAAE,oBACR,MAAM,aACN,MAAM,EAAE,YACR,MAAM,EAAE,eACR,MAAM,iBACN,MAAM,iBACN,OAAO,GACL,OAAO,CAAE,IAAI,CAAC,CAoF1B;IAED;;;;;;OAMG;IACH,8BAHW,SAAS,GACP,eAAe,CAsM3B;IAED;;;;;;;OAOG;IACH,kCALW,MAAM,iBACN,MAAM,WACN,MAAM,EAAE,GACN,IAAI,CA0DhB;IAgCD;;;;;;OAMG;IACH,kCAJW,MAAM,WACN,MAAM,wBACN,eAAe,iBAmDzB;IA6BD;;;;;;;;OAQG;IACH,wCANW,MAAM,cACN,MAAM,EAAE,gBACR,MAAM,YACN,MAAM,GACJ,OAAO,CAAE,MAAM,CAAC,CAM5B;IAoGD;;;;;;OAMG;IACH,uCAYC;IAED;;;;;;OAMG;IACH,wCAGC;IA0BD;;;;;;OAMG;IACH,4BAHW,MAAM,GACJ,OAAO,CAAE,IAAI,CAAC,CAwB1B;IAED;;;;;OAKG;IACH,qBAHW,MAAM,GACJ,OAAO,CAAE;QAAC,GAAG,EAAC,MAAM,CAAC;QAAC,IAAI,EAAC,MAAM,CAAC;QAAC,IAAI,EAAC,MAAM,CAAC;QAAC,MAAM,EAAC,MAAM,CAAC;QAAC,GAAG,EAAC,MAAM,CAAC;QAAC,KAAK,EAAC,MAAM,CAAC;QAAC,QAAQ,EAAC,OAAO,CAAA;KAAC,CAAC,CA0KvH;IAED;;;;;;;OAOG;IACH,sCALW,MAAM,QACN,MAAM,UACN,MAAM,GACJ,OAAO,CAAE,MAAM,CAAC,CAW5B;IAED;;;;;;OAMG;IACH,sCAJW,MAAM,QACN,MAAM,GACJ,OAAO,CAAE,MAAM,CAAC,CAwB5B;IAED;;;;;;OAMG;IACH,gCALW,gBAAgB,eAChB,MAAM,kBACN,GAAG,CAAE,MAAM,CAAC,GACV,OAAO,CAAE,gBAAgB,CAAC,CA8DtC;IA+ED;;;;;;OAMG;IACH,kCALW,MAAM,EAAE,eACR,MAAM,iBACN,GAAG,CAAE,MAAM,CAAC,GACV,OAAO,CAAE,GAAG,CAAE,MAAM,CAAC,CAAC,CAoClC;IAyBD;;;OAGG;IACH,sCAHW,MAAM,mBACN,MAAM,EAAE,QAmBlB;CAwEJ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;yBAp6FwB,mBAAmB"} \ No newline at end of file diff --git a/@types/lib/metadataTypes/AttributeGroup.d.ts b/@types/lib/metadataTypes/AttributeGroup.d.ts new file mode 100644 index 000000000..1cb11affe --- /dev/null +++ b/@types/lib/metadataTypes/AttributeGroup.d.ts @@ -0,0 +1,289 @@ +export default AttributeGroup; +export type MetadataTypeItem = import("../../types/mcdev.d.js").MetadataTypeItem; +export type MetadataTypeMapObj = import("../../types/mcdev.d.js").MetadataTypeMapObj; +/** + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItem} MetadataTypeItem + * @typedef {import('../../types/mcdev.d.js').MetadataTypeMapObj} MetadataTypeMapObj + */ +/** + * AttributeGroup MetadataType + * + * @augments MetadataType + */ +declare class AttributeGroup extends MetadataType { + /** + * Retrieves Metadata of schema attribute groups. + * + * @param {string} retrieveDir Directory where retrieved metadata directory will be saved + * @param {void | string[]} [_] unused parameter + * @param {void | string[]} [__] unused parameter + * @param {string} [key] customer key of single item to retrieve + * @returns {Promise.<MetadataTypeMapObj>} Promise of metadata + */ + static retrieve(retrieveDir: string, _?: void | string[], __?: void | string[], key?: string): Promise<MetadataTypeMapObj>; + /** + * Retrieves Metadata of schema attribute groups for caching. + * + * @returns {Promise.<MetadataTypeMapObj>} Promise of metadata + */ + static retrieveForCache(): Promise<MetadataTypeMapObj>; + /** + * manages post retrieve steps + * + * @param {MetadataTypeItem} metadata a single metadata + * @returns {MetadataTypeItem} metadata + */ + static postRetrieveTasks(metadata: MetadataTypeItem): MetadataTypeItem; +} +declare namespace AttributeGroup { + let definition: { + bodyIteratorField: string; + dependencies: string[]; + dependencyGraph: { + attributeSet: string[]; + }; + hasExtended: boolean; + idField: string; + keyIsFixed: boolean; + keyField: string; + nameField: string; + restPagination: boolean; + type: string; + typeDescription: string; + typeRetrieveByDefault: boolean; + typeCdpByDefault: boolean; + typeName: string; + fields: { + applicationID: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + applicationKey: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + attributeCount: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + attributeGroupIconKey: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + attributeGroupType: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + attributeSetIdentifiers: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'attributeSetIdentifiers[].connectingID.identifierType': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: boolean; + }; + 'attributeSetIdentifiers[].definitionID': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: boolean; + }; + 'attributeSetIdentifiers[].definitionKey': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: boolean; + }; + 'attributeSetIdentifiers[].definitionName.value': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: boolean; + }; + 'attributeSetIdentifiers[].namespace': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: boolean; + }; + canAddProperties: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + canAddRelationships: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + canChangeProperties: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + canModify: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + canRemove: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + connectingID: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'connectingID.identifierType': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + containsSchemaAttributes: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + definitionID: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + definitionKey: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'definitionName.value': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + description: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + displayOrder: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + fullyQualifiedName: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + isHidden: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + isOwner: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + isPrimary: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + isSystemDefined: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + localizedDescription: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'localizedDescription.resourceSetKey': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: boolean; + }; + 'localizedDescription.resourceValueKey': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: boolean; + }; + 'localizedDescription.value': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: boolean; + }; + mID: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + namespace: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + objectState: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + requiredRelationships: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + r__attributeSet_key: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + }; + }; +} +import MetadataType from './MetadataType.js'; +//# sourceMappingURL=AttributeGroup.d.ts.map \ No newline at end of file diff --git a/@types/lib/metadataTypes/AttributeGroup.d.ts.map b/@types/lib/metadataTypes/AttributeGroup.d.ts.map new file mode 100644 index 000000000..18623b364 --- /dev/null +++ b/@types/lib/metadataTypes/AttributeGroup.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"AttributeGroup.d.ts","sourceRoot":"","sources":["../../../lib/metadataTypes/AttributeGroup.js"],"names":[],"mappings":";+BAOa,OAAO,wBAAwB,EAAE,gBAAgB;iCACjD,OAAO,wBAAwB,EAAE,kBAAkB;AAFhE;;;GAGG;AAEH;;;;GAIG;AACH;IACI;;;;;;;;OAQG;IACH,6BANW,MAAM,MACN,IAAI,GAAG,MAAM,EAAE,OACf,IAAI,GAAG,MAAM,EAAE,QACf,MAAM,GACJ,OAAO,CAAE,kBAAkB,CAAC,CASxC;IAED;;;;OAIG;IACH,2BAFa,OAAO,CAAE,kBAAkB,CAAC,CAIxC;IAED;;;;;OAKG;IACH,mCAHW,gBAAgB,GACd,gBAAgB,CA6D5B;CAQJ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;yBAnHwB,mBAAmB"} \ No newline at end of file diff --git a/@types/lib/metadataTypes/AttributeSet.d.ts b/@types/lib/metadataTypes/AttributeSet.d.ts new file mode 100644 index 000000000..9024a8dfe --- /dev/null +++ b/@types/lib/metadataTypes/AttributeSet.d.ts @@ -0,0 +1,1033 @@ +export default AttributeSet; +export type MetadataTypeItem = import("../../types/mcdev.d.js").MetadataTypeItem; +export type MetadataTypeMap = import("../../types/mcdev.d.js").MetadataTypeMap; +export type MetadataTypeMapObj = import("../../types/mcdev.d.js").MetadataTypeMapObj; +/** + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItem} MetadataTypeItem + * @typedef {import('../../types/mcdev.d.js').MetadataTypeMap} MetadataTypeMap + * @typedef {import('../../types/mcdev.d.js').MetadataTypeMapObj} MetadataTypeMapObj + */ +/** + * AttributeSet MetadataType + * + * @augments MetadataType + */ +declare class AttributeSet extends MetadataType { + static systemValueDefinitions: any; + /** + * Retrieves Metadata of schema set Definitions. + * + * @param {string} retrieveDir Directory where retrieved metadata directory will be saved + * @param {void | string[]} [_] unused parameter + * @param {void | string[]} [__] unused parameter + * @param {string} [key] customer key of single item to retrieve + * @returns {Promise.<MetadataTypeMapObj>} Promise + */ + static retrieve(retrieveDir: string, _?: void | string[], __?: void | string[], key?: string): Promise<MetadataTypeMapObj>; + /** + * Retrieves Metadata of schema set definitions for caching. + * + * @returns {Promise.<MetadataTypeMapObj>} Promise + */ + static retrieveForCache(): Promise<MetadataTypeMapObj>; + /** + * used to identify updated shared data extensions that are used in attributeSets. + * helper for DataExtension.#fixShared_onBU + * + * @param {Object.<string, string>} sharedDataExtensionMap ID-Key relationship of shared data extensions + * @param {object} fixShared_fields DataExtensionField.fixShared_fields + * @returns {Promise.<string[]>} Promise of list of shared dataExtension IDs + */ + static fixShared_retrieve(sharedDataExtensionMap: { + [x: string]: string; + }, fixShared_fields: object): Promise<string[]>; + /** + * manages post retrieve steps + * + * @param {MetadataTypeItem} metadata a single metadata + * @returns {MetadataTypeItem} metadata + */ + static postRetrieveTasks(metadata: MetadataTypeItem): MetadataTypeItem; + /** + * helper for {@link AttributeSet.postRetrieveTasks} + * + * @returns {object[]} all system value definitions + */ + static _getSystemValueDefinitions(): object[]; +} +declare namespace AttributeSet { + let definition: { + bodyIteratorField: string; + dependencies: string[]; + dependencyGraph: { + dataExtension: string[]; + attributeSet: string[]; + attributeGroup: string[]; + }; + hasExtended: boolean; + idField: string; + keyIsFixed: boolean; + keyField: string; + nameField: string; + folderIdField: string; + createdDateField: string; + createdNameField: string; + lastmodDateField: any; + lastmodNameField: any; + restPagination: boolean; + type: string; + typeDescription: string; + typeRetrieveByDefault: boolean; + typeCdpByDefault: boolean; + typeName: string; + fields: { + applicationID: { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + applicationKey: { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + attributeCount: { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + canAddValues: { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + canChangeValues: { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + canModify: { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + canRemove: { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + categoryID: { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + 'connectingID.identifierType': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + createDate: { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + createdBy: { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + customObjectOwnerMID: { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + 'dataRetentionProperties.isDeleteAtEndOfRetentionPeriod': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + 'dataRetentionProperties.isResetRetentionPeriodOnImport': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + 'dataRetentionProperties.isRowBasedRetention': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + 'dataRetentionProperties.periodUnitOfMeasure': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + 'dataRetentionProperties.setDefinitionID': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + 'dataRetentionProperties.periodLength': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + definitionID: { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + definitionKey: { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + definitionName: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'definitionName.value': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + fullyQualifiedName: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + isCustomObjectBacked: { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + isEvent: { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + isHidden: { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + isReadOnly: { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + isRoot: { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + isSendable: { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + isShared: { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + isSystemDefined: { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + isTestaable: { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + 'leftConnectingID.identifierType': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + 'leftItem.cardinality': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + 'leftItem.cardinality ': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + 'leftItem.connectingID.identifierType': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + 'leftItem.identifier': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + 'leftItem.relationshipType': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + localizedDescription: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'localizedDescription.resourceSetKey': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'localizedDescription.resourceValueKey': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'localizedDescription.value': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + name: { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + nonStandardAttributeGroupReferences: { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + 'nonStandardAttributeGroupReferences[].attributeGroupType': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + 'nonStandardAttributeGroupReferences[].attributeGroupID': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + 'nonStandardAttributeGroupReferences[].definitionKey': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + 'obfuscationProperties.maskType': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + 'obfuscationProperties.maskTypeID': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + 'obfuscationProperties.storageType': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + 'obfuscationProperties.storageTypeID': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + 'obfuscationProperties.valueDefinitionID': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + 'parentDefinition.connectingID.identifierType': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + 'parentDefinition.definitionID': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + 'parentDefinition.definitionKey': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + 'parentDefinition.definitionName.value': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + parentID: { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + relationshipCount: { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + relationships: { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + 'relationships[].canModify': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + 'relationships[].canRemove': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + 'relationships[].isGroupToSetRelationship': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + 'relationships[].isHidden': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + 'relationships[].isSystemDefined': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + 'relationships[].leftRelationshipID': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + 'relationships[].leftRelationshipIDs': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + 'relationships[].leftItem.cardinality': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + 'relationships[].leftItem.relationshipType': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + 'relationships[].leftItem.r__attributeSet_key': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + 'relationships[].leftItem.r__attributeGroup_key': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + 'relationships[].rightItem.cardinality': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + 'relationships[].rightItem.relationshipType': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + 'relationships[].rightItem.r__attributeSet_key': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + 'relationships[].rightItem.r__attributeGroup_key': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + 'relationships[].leftRelationshipIDs[].type': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + 'relationships[].leftRelationshipIDs[].value': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + 'relationships[].leftRelationshipReferenceType': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + 'relationships[].relationshipAttributes': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + 'relationships[].relationshipAttributes[].leftAttributeID': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + 'relationships[].relationshipAttributes[].rightAttributeID': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + 'relationships[].relationshipAttributes[].c__leftFullyQualifiedName': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + 'relationships[].relationshipAttributes[].c__rightFullyQualifiedName': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + 'relationships[].relationshipID': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + 'rightConnectingID.identifierType': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + 'rightItem.cardinality': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + 'rightItem.connectingID.identifierType': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + 'rightItem.identifier': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + 'rightItem.relationshipType': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + sendAttributeStorageName: { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + sendContactKeyStorageName: { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + setDefinitionID: { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + setDefinitionKey: { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + 'setDefinitionName.value': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + 'storageFieldReferenceID.type': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + 'storageFieldReferenceID.value': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + storageLogicalType: { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + storageName: { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + 'storageObjectFieldInformation.externalIsRowIdentifier': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + 'storageObjectFieldInformation.externalObjectFieldAPIName': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + 'storageObjectFieldInformation.externalObjectFieldDataTypeName': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + 'storageObjectFieldInformation.externalObjectFieldLength': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + storageObjectIDs: { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + 'storageObjectInformation.externalObjectAPIName': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + 'storageReferenceID.type': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + 'storageReferenceID.value': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + valueDefinitions: { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + 'valueDefinitions[].baseType': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + 'valueDefinitions[].customerDataID': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + 'valueDefinitions[].connectingID': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + 'valueDefinitions[].dataSourceID': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + 'valueDefinitions[].dataSourceName': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + 'valueDefinitions[].dataType': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + 'valueDefinitions[].defaultValue': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + 'valueDefinitions[].definitionID': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + 'valueDefinitions[].definitionKey': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + 'valueDefinitions[].definitionName': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + 'valueDefinitions[].description': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + 'valueDefinitions[].displayOrder': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + 'valueDefinitions[].fullyQualifiedName': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + 'valueDefinitions[].identifierType': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + 'valueDefinitions[].isHidden': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + 'valueDefinitions[].isIdentityValue': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + 'valueDefinitions[].isNullable': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + 'valueDefinitions[].isPrimaryKey': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + 'valueDefinitions[].isReadOnly': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + 'valueDefinitions[].isSystemDefined': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + 'valueDefinitions[].isUpdateable': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + 'valueDefinitions[].length': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + 'valueDefinitions[].localizedDescription': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + 'valueDefinitions[].name': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + 'valueDefinitions[].obfuscationProperties': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + 'valueDefinitions[].obfuscationProperties.maskType': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + 'valueDefinitions[].obfuscationProperties.maskTypeID': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + 'valueDefinitions[].obfuscationProperties.storageType': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + 'valueDefinitions[].obfuscationProperties.storageTypeID': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + 'valueDefinitions[].obfuscationProperties.valueDefinitionID': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + 'valueDefinitions[].ordinal': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + 'valueDefinitions[].parentDefinition': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + 'valueDefinitions[].parentIdentifier': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + 'valueDefinitions[].parentType': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + 'valueDefinitions[].restrictionLookupListID': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + 'valueDefinitions[].scale': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + 'valueDefinitions[].setDefinitionID': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + 'valueDefinitions[].setDefinitionKey': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + 'valueDefinitions[].setDefinitionName': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + 'valueDefinitions[].storageFieldReferenceID': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + 'valueDefinitions[].storageFieldReferenceID.type': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + 'valueDefinitions[].storageFieldReferenceID.value': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + 'valueDefinitions[].storageFieldValueID.type': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + 'valueDefinitions[].storageFieldValueID.value': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + 'valueDefinitions[].storageName': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + 'valueDefinitions[].storageObjectFieldInformation': { + skipValidation: boolean; + }; + 'valueDefinitions[].storageObjectFieldInformation.externalObjectFieldAPIName': { + skipValidation: boolean; + }; + 'valueDefinitions[].storageObjectFieldInformation.externalObjectFieldDataTypeName': { + skipValidation: boolean; + }; + 'valueDefinitions[].storageObjectFieldInformation.externalObjectFieldLength': { + skipValidation: boolean; + }; + 'valueDefinitions[].storageObjectFieldInformation.externalIsRowIdentifier': { + skipValidation: boolean; + }; + 'valueDefinitions[].valueDefinitionID': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + 'valueDefinitions[].valueDefinitionKey': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + r__folder_Path: { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + r__dataExtension_key: { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + }; + }; +} +import MetadataType from './MetadataType.js'; +//# sourceMappingURL=AttributeSet.d.ts.map \ No newline at end of file diff --git a/@types/lib/metadataTypes/AttributeSet.d.ts.map b/@types/lib/metadataTypes/AttributeSet.d.ts.map new file mode 100644 index 000000000..4b6d4ae5d --- /dev/null +++ b/@types/lib/metadataTypes/AttributeSet.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"AttributeSet.d.ts","sourceRoot":"","sources":["../../../lib/metadataTypes/AttributeSet.js"],"names":[],"mappings":";+BAQa,OAAO,wBAAwB,EAAE,gBAAgB;8BACjD,OAAO,wBAAwB,EAAE,eAAe;iCAChD,OAAO,wBAAwB,EAAE,kBAAkB;AAHhE;;;;GAIG;AAEH;;;;GAIG;AACH;IACI,mCAA8B;IAE9B;;;;;;;;OAQG;IACH,6BANW,MAAM,MACN,IAAI,GAAG,MAAM,EAAE,OACf,IAAI,GAAG,MAAM,EAAE,QACf,MAAM,GACJ,OAAO,CAAE,kBAAkB,CAAC,CAaxC;IAED;;;;OAIG;IACH,2BAFa,OAAO,CAAE,kBAAkB,CAAC,CAIxC;IAED;;;;;;;OAOG;IACH;;yBAHW,MAAM,GACJ,OAAO,CAAE,MAAM,EAAE,CAAC,CAiG9B;IAoBD;;;;;OAKG;IACH,mCAHW,gBAAgB,GACd,gBAAgB,CAwK5B;IAED;;;;OAIG;IACH,qCAFa,MAAM,EAAE,CAgBpB;CACJ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;yBA9WwB,mBAAmB"} \ No newline at end of file diff --git a/@types/lib/metadataTypes/Automation.d.ts b/@types/lib/metadataTypes/Automation.d.ts new file mode 100644 index 000000000..40772e4c6 --- /dev/null +++ b/@types/lib/metadataTypes/Automation.d.ts @@ -0,0 +1,962 @@ +export default Automation; +export type BuObject = import("../../types/mcdev.d.js").BuObject; +export type CodeExtract = import("../../types/mcdev.d.js").CodeExtract; +export type CodeExtractItem = import("../../types/mcdev.d.js").CodeExtractItem; +export type MetadataTypeItem = import("../../types/mcdev.d.js").MetadataTypeItem; +export type MetadataTypeItemDiff = import("../../types/mcdev.d.js").MetadataTypeItemDiff; +export type MetadataTypeItemObj = import("../../types/mcdev.d.js").MetadataTypeItemObj; +export type MetadataTypeMap = import("../../types/mcdev.d.js").MetadataTypeMap; +export type MetadataTypeMapObj = import("../../types/mcdev.d.js").MetadataTypeMapObj; +export type SDKError = import("../../types/mcdev.d.js").SDKError; +export type SoapRequestParams = import("../../types/mcdev.d.js").SoapRequestParams; +export type TemplateMap = import("../../types/mcdev.d.js").TemplateMap; +export type TypeKeyCombo = import("../../types/mcdev.d.js").TypeKeyCombo; +export type AutomationItem = import("../../types/mcdev.d.js").AutomationItem; +export type AutomationItemObj = import("../../types/mcdev.d.js").AutomationItemObj; +export type AutomationMap = import("../../types/mcdev.d.js").AutomationMap; +export type AutomationMapObj = import("../../types/mcdev.d.js").AutomationMapObj; +export type AutomationSchedule = import("../../types/mcdev.d.js").AutomationSchedule; +export type AutomationScheduleSoap = import("../../types/mcdev.d.js").AutomationScheduleSoap; +/** + * @typedef {import('../../types/mcdev.d.js').BuObject} BuObject + * @typedef {import('../../types/mcdev.d.js').CodeExtract} CodeExtract + * @typedef {import('../../types/mcdev.d.js').CodeExtractItem} CodeExtractItem + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItem} MetadataTypeItem + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItemDiff} MetadataTypeItemDiff + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItemObj} MetadataTypeItemObj + * @typedef {import('../../types/mcdev.d.js').MetadataTypeMap} MetadataTypeMap + * @typedef {import('../../types/mcdev.d.js').MetadataTypeMapObj} MetadataTypeMapObj + * @typedef {import('../../types/mcdev.d.js').SDKError} SDKError + * @typedef {import('../../types/mcdev.d.js').SoapRequestParams} SoapRequestParams + * @typedef {import('../../types/mcdev.d.js').TemplateMap} TemplateMap + * @typedef {import('../../types/mcdev.d.js').TypeKeyCombo} TypeKeyCombo + */ +/** + * @typedef {import('../../types/mcdev.d.js').AutomationItem} AutomationItem + * @typedef {import('../../types/mcdev.d.js').AutomationItemObj} AutomationItemObj + * @typedef {import('../../types/mcdev.d.js').AutomationMap} AutomationMap + * @typedef {import('../../types/mcdev.d.js').AutomationMapObj} AutomationMapObj + * @typedef {import('../../types/mcdev.d.js').AutomationSchedule} AutomationSchedule + * @typedef {import('../../types/mcdev.d.js').AutomationScheduleSoap} AutomationScheduleSoap + */ +/** + * Automation MetadataType + * + * @augments MetadataType + */ +declare class Automation extends MetadataType { + static notificationUpdates: {}; + static createdKeyMap: any; + static _skipNotificationRetrieve: boolean; + /** @type {AutomationMap} */ + static _cachedMetadataMap: AutomationMap; + /** + * Retrieves Metadata of Automation + * + * @param {string} [retrieveDir] Directory where retrieved metadata directory will be saved + * @param {void | string[]} [_] unused parameter + * @param {void | string[]} [__] unused parameter + * @param {string} [key] customer key of single item to retrieve + * @returns {Promise.<AutomationMapObj>} Promise of metadata + */ + static retrieve(retrieveDir?: string, _?: void | string[], __?: void | string[], key?: string): Promise<AutomationMapObj>; + /** + * helper for {@link this.retrieveRESTcollection} + * + * @param {SDKError} ex exception + * @param {string} key id or key of item + * @param {string} url url to call for retry + * @returns {Promise.<any>} can return retry-result + */ + static handleRESTErrors(ex: SDKError, key: string, url: string): Promise<any>; + /** + * helper for {@link Automation.retrieve} to get Automation Notifications + * + * @param {MetadataTypeMap} metadataMap keyField => metadata map + * @param {boolean} [skipNotification] skip notification retrieval + * @returns {Promise.<object>} Promise of automation legacy api response + */ + static "__#private@#getAutomationLegacyREST"(metadataMap: MetadataTypeMap, skipNotification?: boolean): Promise<object>; + /** + * Retrieves Metadata of Automation + * + * @returns {Promise.<AutomationMapObj>} Promise of metadata + */ + static retrieveChangelog(): Promise<AutomationMapObj>; + /** + * Retrieves automation metadata for caching + * + * @returns {Promise.<AutomationMapObj>} Promise of metadata + */ + static retrieveForCache(): Promise<AutomationMapObj>; + /** + * Retrieve a specific Automation Definition by Name + * + * @deprecated Use `retrieve` followed by `build` instead. `retrieveAsTemplate` will be removed in a future version. + * @param {string} templateDir Directory where retrieved metadata directory will be saved + * @param {string} name name of the metadata file + * @param {TemplateMap} templateVariables variables to be replaced in the metadata + * @returns {Promise.<AutomationItemObj>} Promise of metadata + */ + static retrieveAsTemplate(templateDir: string, name: string, templateVariables: TemplateMap): Promise<AutomationItemObj>; + /** + * helper for {@link Automation.postRetrieveTasks} and {@link Automation.execute} + * + * @param {AutomationItem} metadata a single automation + * @returns {boolean} true if the automation schedule is valid + */ + static "__#private@#isValidSchedule"(metadata: AutomationItem): boolean; + /** + * manages post retrieve steps + * + * @param {AutomationItem} metadata a single automation + * @returns {AutomationItem | void} parsed item + */ + static postRetrieveTasks(metadata: AutomationItem): AutomationItem | void; + /** + * a function to active the schedule of an automation + * + * @param {string[]} keyArr customerkey of the metadata + * @returns {Promise.<string[]>} Returns list of keys that were executed + */ + static schedule(keyArr: string[]): Promise<string[]>; + /** + * a function to pause the schedule of an automation + * + * @param {string[]} keyArr customerkey of the metadata + * @returns {Promise.<string[]>} Returns list of keys that were executed + */ + static pause(keyArr: string[]): Promise<string[]>; + /** + * a function to active the schedule of an automation + * + * @param {'schedule'|'pause'} mode what to do + * @param {string[]} keyArr customerkey of the metadata + * @returns {Promise.<string[]>} Returns list of keys that were executed + */ + static "__#private@#schedulePause"(mode: "schedule" | "pause", keyArr: string[]): Promise<string[]>; + /** + * helper for {@link Automation.schedule} + * + * @param {'schedule'|'pause'} mode what to do + * @param {string} key automation key + * @param {string} automationLegacyId automation id + * @param {string} [scheduleLegacyId] schedule id + * @param {string} [description] schedule description + * @returns {Promise.<{key:string, response:object}>} metadata key and API response + */ + static "__#private@#schedulePauseItem"(mode: "schedule" | "pause", key: string, automationLegacyId: string, scheduleLegacyId?: string, description?: string): Promise<{ + key: string; + response: object; + }>; + /** + * a function to start query execution via API + * + * @param {string[]} keyArr customerkey of the metadata + * @returns {Promise.<string[]>} Returns list of keys that were executed + */ + static execute(keyArr: string[]): Promise<string[]>; + /** + * Creates a single automation + * + * @param {AutomationItem} metadata single metadata entry + * @returns {Promise} Promise + */ + static create(metadata: AutomationItem): Promise<any>; + /** + * Updates a single automation + * + * @param {AutomationItem} metadata single metadata entry + * @param {AutomationItem} metadataBefore metadata mapped by their keyField + * @returns {Promise} Promise + */ + static update(metadata: AutomationItem, metadataBefore: AutomationItem): Promise<any>; + /** + * helper for {@link Automation.preDeployTasks} and {@link Automation.execute} + * + * @param {AutomationItem} metadata metadata mapped by their keyField + */ + static "__#private@#preDeploySchedule"(metadata: AutomationItem): void; + /** + * Gets executed before deploying metadata + * + * @param {AutomationItem} metadata metadata mapped by their keyField + * @returns {Promise.<AutomationItem>} Promise + */ + static preDeployTasks(metadata: AutomationItem): Promise<AutomationItem>; + /** + * Validates the automation to be sure it can be deployed. + * Whitelisted Activites are deployed but require configuration + * + * @param {AutomationItem} metadata single automation record + * @returns {boolean} result if automation can be deployed based on steps + */ + static validateDeployMetadata(metadata: AutomationItem): boolean; + /** + * helper for {@link MetadataType.updateREST} and {@link MetadataType.updateSOAP} that removes old files after the key was changed + * + * @param {MetadataTypeItem} metadataEntry a single metadata Entry + * @returns {Promise.<void>} - + */ + static _postChangeKeyTasks(metadataEntry: MetadataTypeItem): Promise<void>; + /** + * Gets executed after deployment of metadata type + * + * @param {AutomationMap} metadataMap metadata mapped by their keyField + * @returns {Promise.<void>} - + */ + static postDeployTasks(metadataMap: AutomationMap): Promise<void>; + /** + * helper for {@link Automation.postDeployTasks} + * + * @param {AutomationMap} metadataMap metadata mapped by their keyField + * @param {string} key current customer key + * @returns {Promise.<void>} - + */ + static "__#private@#updateNotificationInfoREST"(metadataMap: AutomationMap, key: string): Promise<void>; + /** + * Builds a schedule object to be used for scheduling an automation + * based on combination of ical string and start/end dates. + * + * @param {AutomationSchedule} scheduleObject child of automation metadata used for scheduling + * @param {boolean} [errorOnNotSchedulable] used if run for schedule command + * @returns {void} throws and error in case of problems + */ + static _checkSchedule(scheduleObject: AutomationSchedule, errorOnNotSchedulable?: boolean): void; + /** + * used to convert dates to the system timezone required for startDate + * + * @param {number} offsetServer stack4: US Mountain time (UTC-7); other stacks: US Central (UTC-6) + * @param {string|Date} dateInput date in ISO format (2021-12-05T20:00:00.983) + * @param {string} [offsetInput] timzone difference (+02:00) + * @returns {string} date in server + */ + static _calcTime(offsetServer: number, dateInput: string | Date, offsetInput?: string): string; + /** + * Experimental: Only working for DataExtensions: + * Saves json content to a html table in the local file system. Will create the parent directory if it does not exist. + * The json's first level of keys must represent the rows and the secend level the columns + * + * @private + * @param {AutomationItem} json dataextension + * @param {object[][]} tabled prepped array for output in tabular format + * @returns {string} file content + */ + private static _generateDocMd; + /** + * Saves json content to a html table in the local file system. Will create the parent directory if it does not exist. + * The json's first level of keys must represent the rows and the secend level the columns + * + * @private + * @param {string} directory directory the file will be written to + * @param {string} filename name of the file without '.json' ending + * @param {AutomationItem} json dataextension.columns + * @param {'html'|'md'} mode html or md + * @returns {Promise.<void>} Promise of success of saving the file + */ + private static _writeDoc; + /** + * Parses metadata into a readable Markdown/HTML format then saves it + * + * @param {AutomationMap} [metadata] a list of dataExtension definitions + * @returns {Promise.<void>} - + */ + static document(metadata?: AutomationMap): Promise<void>; + /** + * helper to allow us to select single metadata entries via REST + * + * @param {string} key customer key + * @returns {Promise.<string>} objectId or enpty string + */ + static "__#private@#getObjectIdForSingleRetrieve"(key: string): Promise<string>; + /** + * clean up after deleting a metadata item + * + * @param {string} customerKey Identifier of metadata item + * @returns {Promise.<void>} - + */ + static postDeleteTasks(customerKey: string): Promise<void>; +} +declare namespace Automation { + let retrieveDir: string; + let definition: { + activityTypeMapping: { + dataExtract: number; + dataFactoryUtility: number; + emailSend: number; + fileTransfer: number; + filter: number; + fireEvent: number; + importFile: number; + journeyEntry: number; + journeyEntryOld: number; + query: number; + script: number; + verification: number; + wait: number; + push: number; + sms: number; + reportDefinition: number; + refreshMobileFilteredList: number; + refreshGroup: number; + interactions: number; + interactionStudioData: number; + importMobileContact: number; + }; + bodyIteratorField: string; + dependencies: string[]; + dependencyGraph: { + dataExtract: string[]; + emailSend: string[]; + fileTransfer: string[]; + importFile: string[]; + query: string[]; + script: string[]; + verification: string[]; + }; + folderType: string; + hasExtended: boolean; + filter: { + description: string[]; + }; + idField: string; + keyIsFixed: boolean; + keyField: string; + nameField: string; + folderIdField: string; + createdDateField: string; + createdNameField: string; + lastmodDateField: string; + lastmodNameField: string; + restPagination: boolean; + maxKeyLength: number; + scheduleTypeMapping: { + MINUTELY: number; + HOURLY: number; + DAILY: number; + WEEKLY: number; + MONTHLY: number; + }; + statusMapping: { + AwaitingTrigger: number; + Building: number; + BuildingError: number; + Error: number; + InactiveTrigger: number; + PausedSchedule: number; + Ready: number; + Running: number; + Scheduled: number; + Stopped: number; + }; + fileNameOperatorMapping: { + Equals: number; + Contains: number; + 'Begins with': number; + 'Ends with': number; + }; + timeZoneMapping: { + 'Afghanistan Standard Time': number; + 'Alaskan Standard Time': number; + 'Arab Standard Time': number; + 'Arabian Standard Time': number; + 'Arabic Standard Time': number; + 'Argentina Standard Time': number; + 'Atlantic Standard Time': number; + 'AUS Central Standard Time': number; + 'AUS Eastern Standard Time': number; + 'Azerbaijan Standard Time': number; + 'Azores Standard Time': number; + 'Canada Central Standard Time': number; + 'Cape Verde Standard Time': number; + 'Caucasus Standard Time': number; + 'Cen. Australia Standard Time': number; + 'Central America Standard Time': number; + 'Central Asia Standard Time': number; + 'Central Brazilian Standard Time': number; + 'Central Europe Standard Time': number; + 'Central European Standard Time': number; + 'Central Pacific Standard Time': number; + 'Central Standard Time': number; + 'Central Standard Time (Mexico)': number; + 'Central Standard Time (no DST)': number; + 'China Standard Time': number; + 'Dateline Standard Time': number; + 'E. Africa Standard Time': number; + 'E. Australia Standard Time': number; + 'E. Europe Standard Time': number; + 'E. South America Standard Time': number; + 'Eastern Standard Time': number; + 'Egypt Standard Time': number; + 'Ekaterinburg Standard Time': number; + 'Fiji Standard Time': number; + 'FLE Standard Time': number; + 'Georgian Standard Time': number; + 'GMT Standard Time': number; + 'Greenland Standard Time': number; + 'Greenwich Standard Time': number; + 'GTB Standard Time': number; + 'Hawaiian Standard Time': number; + 'India Standard Time': number; + 'Iran Standard Time': number; + 'Israel Standard Time': number; + 'Jordan Standard Time': number; + 'Korea Standard Time': number; + 'Mauritius Standard Time': number; + 'Mid-Atlantic Standard Time': number; + 'Middle East Standard Time': number; + 'Montevideo Standard Time': number; + 'Morocco Standard Time': number; + 'Mountain Standard Time': number; + 'Mountain Standard Time (Mexico)': number; + 'Myanmar Standard Time': number; + 'N. Central Asia Standard Time': number; + 'Namibia Standard Time': number; + 'Nepal Standard Time': number; + 'New Zealand Standard Time': number; + 'Newfoundland Standard Time': number; + 'North Asia East Standard Time': number; + 'North Asia Standard Time': number; + 'Pacific SA Standard Time': number; + 'Pacific Standard Time': number; + 'Pacific Standard Time (Mexico)': number; + 'Pakistan Standard Time': number; + 'Romance Standard Time': number; + 'Russian Standard Time': number; + 'SA Pacific Standard Time': number; + 'SA Western Standard Time': number; + 'Samoa Standard Time': number; + 'SE Asia Standard Time': number; + 'Singapore Standard Time': number; + 'South Africa Standard Time': number; + 'Sri Lanka Standard Time': number; + 'Taipei Standard Time': number; + 'Tasmania Standard Time': number; + 'Tokyo Standard Time': number; + 'Tonga Standard Time': number; + 'US Eastern Standard Time': number; + 'US Mountain Standard Time': number; + 'Venezuela Standard Time': number; + 'Vladivostok Standard Time': number; + 'W. Australia Standard Time': number; + 'W. Central Africa Standard Time': number; + 'W. Europe Standard Time': number; + 'West Asia Standard Time': number; + 'West Pacific Standard Time': number; + 'Yakutsk Standard Time': number; + }; + timeZoneDifference: { + 1: string; + 2: string; + 3: string; + 4: string; + 5: string; + 6: string; + 7: string; + 8: string; + 9: string; + 10: string; + 11: string; + 12: string; + 13: string; + 14: string; + 15: string; + 16: string; + 17: string; + 18: string; + 19: string; + 20: string; + 21: string; + 22: string; + 23: string; + 24: string; + 25: string; + 26: string; + 27: string; + 28: string; + 29: string; + 30: string; + 31: string; + 32: string; + 33: string; + 34: string; + 35: string; + 36: string; + 37: string; + 38: string; + 39: string; + 40: string; + 41: string; + 42: string; + 43: string; + 44: string; + 45: string; + 46: string; + 47: string; + 48: string; + 49: string; + 50: string; + 51: string; + 52: string; + 53: string; + 54: string; + 55: string; + 56: string; + 57: string; + 58: string; + 59: string; + 60: string; + 61: string; + 62: string; + 63: string; + 64: string; + 65: string; + 66: string; + 67: string; + 68: string; + 69: string; + 70: string; + 71: string; + 72: string; + 73: string; + 74: string; + 75: string; + 76: string; + 77: string; + 78: string; + 79: string; + 80: string; + 81: string; + 82: string; + 83: string; + 84: string; + 85: string; + 86: string; + 87: string; + 88: string; + 89: string; + 90: string; + 91: string; + 92: string; + }; + type: string; + typeDescription: string; + typeRetrieveByDefault: boolean; + typeCdpByDefault: boolean; + typeName: string; + customDeployTypes: string[]; + manualDeployTypes: any[]; + fields: { + categoryId: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + description: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'fileTrigger.fileNamePatternTypeId': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'fileTrigger.fileNamingPattern': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'fileTrigger.folderLocationText': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'fileTrigger.isPublished': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'fileTrigger.queueFiles': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'fileTrigger.triggerActive': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + id: { + isCreateable: boolean; + isUpdateable: any; + retrieving: boolean; + template: boolean; + }; + key: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + lastRunInstanceId: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + lastRunTime: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + legacyId: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + lastSavedDate: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + lastSavedByName: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + createdByName: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + createdDate: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + createdName: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + modifiedDate: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + modifiedName: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + pausedDate: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + pausedName: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + updateInProgress: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + name: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + notifications: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'notifications[].email': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'notifications[].message': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'notifications[].channelType': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'notifications[].type': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'notifications[].notificationType': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + startSource: { + skipValidation: boolean; + }; + 'schedule.endDate': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'schedule.icalRecur': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'schedule.id': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'schedule.occurrences': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'schedule.pattern': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'schedule.rangeTypeId': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'schedule.scheduledTime': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'schedule.scheduleStatus': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'schedule.startDate': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'schedule.statusId': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'schedule.timezoneId': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'schedule.timezoneName': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'schedule.typeId': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'schedule.scheduleTypeId': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'schedule.description': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + status: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + statusId: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + steps: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'steps[].activities': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'steps[].activities[].activityObjectId': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'steps[].activities[].displayOrder': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'steps[].activities[].id': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'steps[].activities[].name': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'steps[].activities[].objectTypeId': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'steps[].activities[].targetDataExtensions': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'steps[].activities[].description': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'steps[].activities[].serializedObject': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'steps[].activities[].r__type': { + skipValidation: boolean; + }; + 'steps[].activities[].r__key': { + skipValidation: boolean; + }; + 'steps[].activities[].timeZone': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'steps[].description': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'steps[].annotation': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'steps[].id': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'steps[].name': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'steps[].step': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'steps[].stepNumber': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + type: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + typeId: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + r__folder_Path: { + skipValidation: boolean; + }; + }; + }; +} +import MetadataType from './MetadataType.js'; +//# sourceMappingURL=Automation.d.ts.map \ No newline at end of file diff --git a/@types/lib/metadataTypes/Automation.d.ts.map b/@types/lib/metadataTypes/Automation.d.ts.map new file mode 100644 index 000000000..e99e5a044 --- /dev/null +++ b/@types/lib/metadataTypes/Automation.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"Automation.d.ts","sourceRoot":"","sources":["../../../lib/metadataTypes/Automation.js"],"names":[],"mappings":";uBAWa,OAAO,wBAAwB,EAAE,QAAQ;0BACzC,OAAO,wBAAwB,EAAE,WAAW;8BAC5C,OAAO,wBAAwB,EAAE,eAAe;+BAChD,OAAO,wBAAwB,EAAE,gBAAgB;mCACjD,OAAO,wBAAwB,EAAE,oBAAoB;kCACrD,OAAO,wBAAwB,EAAE,mBAAmB;8BACpD,OAAO,wBAAwB,EAAE,eAAe;iCAChD,OAAO,wBAAwB,EAAE,kBAAkB;uBACnD,OAAO,wBAAwB,EAAE,QAAQ;gCACzC,OAAO,wBAAwB,EAAE,iBAAiB;0BAClD,OAAO,wBAAwB,EAAE,WAAW;2BAC5C,OAAO,wBAAwB,EAAE,YAAY;6BAI7C,OAAO,wBAAwB,EAAE,cAAc;gCAC/C,OAAO,wBAAwB,EAAE,iBAAiB;4BAClD,OAAO,wBAAwB,EAAE,aAAa;+BAC9C,OAAO,wBAAwB,EAAE,gBAAgB;iCACjD,OAAO,wBAAwB,EAAE,kBAAkB;qCACnD,OAAO,wBAAwB,EAAE,sBAAsB;AArBpE;;;;;;;;;;;;;GAaG;AAEH;;;;;;;GAOG;AAEH;;;;GAIG;AACH;IACI,+BAAgC;IAChC,0BAAqB;IACrB,0CAAyC;IACzC,4BAA4B;IAC5B,2BADW,aAAa,CACE;IAE1B;;;;;;;;OAQG;IACH,8BANW,MAAM,MACN,IAAI,GAAG,MAAM,EAAE,OACf,IAAI,GAAG,MAAM,EAAE,QACf,MAAM,GACJ,OAAO,CAAE,gBAAgB,CAAC,CAoEtC;IAED;;;;;;;OAOG;IACH,4BALW,QAAQ,OACR,MAAM,OACN,MAAM,GACJ,OAAO,CAAE,GAAG,CAAC,CAyBzB;IAED;;;;;;OAMG;IACH,0DAJW,eAAe,qBACf,OAAO,GACL,OAAO,CAAE,MAAM,CAAC,CAgK5B;IAED;;;;OAIG;IACH,4BAFa,OAAO,CAAE,gBAAgB,CAAC,CAwCtC;IAED;;;;OAIG;IACH,2BAFa,OAAO,CAAE,gBAAgB,CAAC,CA2CtC;IAED;;;;;;;;OAQG;IACH,uCALW,MAAM,QACN,MAAM,qBACN,WAAW,GACT,OAAO,CAAE,iBAAiB,CAAC,CA+DvC;IAED;;;;;OAKG;IACH,+CAHW,cAAc,GACZ,OAAO,CAkBnB;IAED;;;;;OAKG;IACH,mCAHW,cAAc,GACZ,cAAc,GAAG,IAAI,CAiKjC;IACD;;;;;OAKG;IACH,wBAHW,MAAM,EAAE,GACN,OAAO,CAAE,MAAM,EAAE,CAAC,CAI9B;IACD;;;;;OAKG;IACH,qBAHW,MAAM,EAAE,GACN,OAAO,CAAE,MAAM,EAAE,CAAC,CAI9B;IACD;;;;;;OAMG;IACH,yCAJW,UAAU,GAAC,OAAO,UAClB,MAAM,EAAE,GACN,OAAO,CAAE,MAAM,EAAE,CAAC,CAuF9B;IAED;;;;;;;;;OASG;IACH,6CAPW,UAAU,GAAC,OAAO,OAClB,MAAM,sBACN,MAAM,qBACN,MAAM,gBACN,MAAM,GACJ,OAAO,CAAE;QAAC,GAAG,EAAC,MAAM,CAAC;QAAC,QAAQ,EAAC,MAAM,CAAA;KAAC,CAAC,CAgEnD;IACD;;;;;OAKG;IACH,uBAHW,MAAM,EAAE,GACN,OAAO,CAAE,MAAM,EAAE,CAAC,CA8B9B;IAoBD;;;;;OAKG;IACH,wBAHW,cAAc,gBAMxB;IAED;;;;;;OAMG;IACH,wBAJW,cAAc,kBACd,cAAc,gBAgBxB;IAED;;;;OAIG;IACH,iDAFW,cAAc,QAsBxB;IAED;;;;;OAKG;IACH,gCAHW,cAAc,GACZ,OAAO,CAAE,cAAc,CAAC,CA0JpC;IAED;;;;;;OAMG;IACH,wCAHW,cAAc,GACZ,OAAO,CA2CnB;IAED;;;;;OAKG;IACH,0CAHW,gBAAgB,GACd,OAAO,CAAE,IAAI,CAAC,CAI1B;IAED;;;;;OAKG;IACH,oCAHW,aAAa,GACX,OAAO,CAAE,IAAI,CAAC,CA2E1B;IAED;;;;;;OAMG;IACH,6DAJW,aAAa,OACb,MAAM,GACJ,OAAO,CAAE,IAAI,CAAC,CAwC1B;IA4BD;;;;;;;OAOG;IACH,sCAJW,kBAAkB,0BAClB,OAAO,GACL,IAAI,CAiDhB;IAED;;;;;;;OAOG;IACH,+BALW,MAAM,aACN,MAAM,GAAC,IAAI,gBACX,MAAM,GACJ,MAAM,CAclB;IAED;;;;;;;;;OASG;IACH,8BA0GC;IAED;;;;;;;;;;OAUG;IACH,yBA6CC;IAED;;;;;OAKG;IACH,2BAHW,aAAa,GACX,OAAO,CAAE,IAAI,CAAC,CAkC1B;IA8BD;;;;;OAKG;IACH,uDAHW,MAAM,GACJ,OAAO,CAAE,MAAM,CAAC,CAW5B;IAkBD;;;;;OAKG;IACH,oCAHW,MAAM,GACJ,OAAO,CAAE,IAAI,CAAC,CAM1B;CAkCJ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;yBArtDwB,mBAAmB"} \ No newline at end of file diff --git a/@types/lib/metadataTypes/Campaign.d.ts b/@types/lib/metadataTypes/Campaign.d.ts new file mode 100644 index 000000000..b61d75226 --- /dev/null +++ b/@types/lib/metadataTypes/Campaign.d.ts @@ -0,0 +1,185 @@ +export default Campaign; +export type BuObject = import("../../types/mcdev.d.js").BuObject; +export type CodeExtract = import("../../types/mcdev.d.js").CodeExtract; +export type CodeExtractItem = import("../../types/mcdev.d.js").CodeExtractItem; +export type MetadataTypeItem = import("../../types/mcdev.d.js").MetadataTypeItem; +export type MetadataTypeItemDiff = import("../../types/mcdev.d.js").MetadataTypeItemDiff; +export type MetadataTypeItemObj = import("../../types/mcdev.d.js").MetadataTypeItemObj; +export type MetadataTypeMap = import("../../types/mcdev.d.js").MetadataTypeMap; +export type MetadataTypeMapObj = import("../../types/mcdev.d.js").MetadataTypeMapObj; +export type SoapRequestParams = import("../../types/mcdev.d.js").SoapRequestParams; +export type TemplateMap = import("../../types/mcdev.d.js").TemplateMap; +/** + * @typedef {import('../../types/mcdev.d.js').BuObject} BuObject + * @typedef {import('../../types/mcdev.d.js').CodeExtract} CodeExtract + * @typedef {import('../../types/mcdev.d.js').CodeExtractItem} CodeExtractItem + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItem} MetadataTypeItem + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItemDiff} MetadataTypeItemDiff + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItemObj} MetadataTypeItemObj + * @typedef {import('../../types/mcdev.d.js').MetadataTypeMap} MetadataTypeMap + * @typedef {import('../../types/mcdev.d.js').MetadataTypeMapObj} MetadataTypeMapObj + * @typedef {import('../../types/mcdev.d.js').SoapRequestParams} SoapRequestParams + * @typedef {import('../../types/mcdev.d.js').TemplateMap} TemplateMap + */ +/** + * Campaign MetadataType + * + * @augments MetadataType + */ +declare class Campaign extends MetadataType { + /** + * Retrieves Metadata of campaigns. Afterwards, starts metadata retrieval for their campaign assets + * + * @param {string} retrieveDir Directory where retrieved metadata directory will be saved + * @param {void | string[]} [_] unused parameter + * @param {void | string[]} [__] unused parameter + * @param {string} [key] customer key of single item to retrieve + * @returns {Promise.<MetadataTypeMapObj>} Promise + */ + static retrieve(retrieveDir: string, _?: void | string[], __?: void | string[], key?: string): Promise<MetadataTypeMapObj>; + /** + * Retrieves event definition metadata for caching + * + * @returns {Promise.<MetadataTypeMapObj>} Promise of metadata + */ + static retrieveForCache(): Promise<MetadataTypeMapObj>; + /** + * Parses campaign asset response body and returns metadata entries mapped to their id + * + * @param {string} retrieveDir folder where to save + * @param {string} campaignId of camapaign to retrieve + * @param {string} name of camapaign for saving + * @returns {Promise.<MetadataTypeMapObj>} Campaign Asset Object + */ + static getAssetTags(retrieveDir: string, campaignId: string, name: string): Promise<MetadataTypeMapObj>; +} +declare namespace Campaign { + let definition: { + bodyIteratorField: string; + dependencies: any[]; + dependencyGraph: any; + hasExtended: boolean; + idField: string; + keepId: boolean; + keyIsFixed: boolean; + keyField: string; + nameField: string; + createdDateField: string; + createdNameField: any; + lastmodDateField: string; + lastmodNameField: any; + restPagination: boolean; + restPageSize: number; + type: string; + typeDescription: string; + typeRetrieveByDefault: boolean; + typeCdpByDefault: boolean; + typeName: string; + fields: { + id: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + campaignId: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + type: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + createdDate: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + createdBy: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + ownerId: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + lastUpdated: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + name: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + description: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + externalKey: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + campaignCode: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + 'display.name': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + 'display.value': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + isFavorite: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + campaignOwnerName: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + campaignOwner: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + campaignStatus: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + }; + }; +} +import MetadataType from './MetadataType.js'; +//# sourceMappingURL=Campaign.d.ts.map \ No newline at end of file diff --git a/@types/lib/metadataTypes/Campaign.d.ts.map b/@types/lib/metadataTypes/Campaign.d.ts.map new file mode 100644 index 000000000..fa04fe7c0 --- /dev/null +++ b/@types/lib/metadataTypes/Campaign.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"Campaign.d.ts","sourceRoot":"","sources":["../../../lib/metadataTypes/Campaign.js"],"names":[],"mappings":";uBAOa,OAAO,wBAAwB,EAAE,QAAQ;0BACzC,OAAO,wBAAwB,EAAE,WAAW;8BAC5C,OAAO,wBAAwB,EAAE,eAAe;+BAChD,OAAO,wBAAwB,EAAE,gBAAgB;mCACjD,OAAO,wBAAwB,EAAE,oBAAoB;kCACrD,OAAO,wBAAwB,EAAE,mBAAmB;8BACpD,OAAO,wBAAwB,EAAE,eAAe;iCAChD,OAAO,wBAAwB,EAAE,kBAAkB;gCACnD,OAAO,wBAAwB,EAAE,iBAAiB;0BAClD,OAAO,wBAAwB,EAAE,WAAW;AAVzD;;;;;;;;;;;GAWG;AAEH;;;;GAIG;AACH;IACI;;;;;;;;OAQG;IACH,6BANW,MAAM,MACN,IAAI,GAAG,MAAM,EAAE,OACf,IAAI,GAAG,MAAM,EAAE,QACf,MAAM,GACJ,OAAO,CAAE,kBAAkB,CAAC,CAqBxC;IAED;;;;OAIG;IACH,2BAFa,OAAO,CAAE,kBAAkB,CAAC,CAIxC;IAED;;;;;;;OAOG;IACH,iCALW,MAAM,cACN,MAAM,QACN,MAAM,GACJ,OAAO,CAAE,kBAAkB,CAAC,CAaxC;CACJ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;yBAlFwB,mBAAmB"} \ No newline at end of file diff --git a/@types/lib/metadataTypes/ContentArea.d.ts b/@types/lib/metadataTypes/ContentArea.d.ts new file mode 100644 index 000000000..820d0d52a --- /dev/null +++ b/@types/lib/metadataTypes/ContentArea.d.ts @@ -0,0 +1,233 @@ +export default ContentArea; +export type BuObject = import("../../types/mcdev.d.js").BuObject; +export type CodeExtract = import("../../types/mcdev.d.js").CodeExtract; +export type CodeExtractItem = import("../../types/mcdev.d.js").CodeExtractItem; +export type MetadataTypeItem = import("../../types/mcdev.d.js").MetadataTypeItem; +export type MetadataTypeItemDiff = import("../../types/mcdev.d.js").MetadataTypeItemDiff; +export type MetadataTypeItemObj = import("../../types/mcdev.d.js").MetadataTypeItemObj; +export type MetadataTypeMap = import("../../types/mcdev.d.js").MetadataTypeMap; +export type MetadataTypeMapObj = import("../../types/mcdev.d.js").MetadataTypeMapObj; +export type SoapRequestParams = import("../../types/mcdev.d.js").SoapRequestParams; +export type TemplateMap = import("../../types/mcdev.d.js").TemplateMap; +/** + * @typedef {import('../../types/mcdev.d.js').BuObject} BuObject + * @typedef {import('../../types/mcdev.d.js').CodeExtract} CodeExtract + * @typedef {import('../../types/mcdev.d.js').CodeExtractItem} CodeExtractItem + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItem} MetadataTypeItem + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItemDiff} MetadataTypeItemDiff + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItemObj} MetadataTypeItemObj + * @typedef {import('../../types/mcdev.d.js').MetadataTypeMap} MetadataTypeMap + * @typedef {import('../../types/mcdev.d.js').MetadataTypeMapObj} MetadataTypeMapObj + * @typedef {import('../../types/mcdev.d.js').SoapRequestParams} SoapRequestParams + * @typedef {import('../../types/mcdev.d.js').TemplateMap} TemplateMap + */ +/** + * ContentArea MetadataType + * + * @augments MetadataType + */ +declare class ContentArea extends MetadataType { + /** + * Retrieves SOAP based metadata of metadata type into local filesystem. executes callback with retrieved metadata + * + * @param {string} retrieveDir Directory where retrieved metadata directory will be saved + * @param {void | string[]} [_] unused parameter + * @param {void | string[]} [__] unused parameter + * @param {string} [key] customer key of single item to retrieve + * @returns {Promise.<MetadataTypeMapObj>} Promise of metadata + */ + static retrieve(retrieveDir: string, _?: void | string[], __?: void | string[], key?: string): Promise<MetadataTypeMapObj>; + /** + * parses retrieved Metadata before saving + * + * @param {MetadataTypeItem} metadata a single item + * @returns {MetadataTypeItem} parsed item + */ + static postRetrieveTasks(metadata: MetadataTypeItem): MetadataTypeItem; +} +declare namespace ContentArea { + let definition: { + bodyIteratorField: string; + dependencies: string[]; + dependencyGraph: any; + hasExtended: boolean; + idField: string; + keepId: boolean; + keyIsFixed: boolean; + keyField: string; + nameField: string; + folderIdField: string; + restPagination: any; + type: string; + typeDescription: string; + typeRetrieveByDefault: boolean; + typeCdpByDefault: boolean; + typeName: string; + fields: { + BackgroundColor: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + BorderColor: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + BorderWidth: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + CategoryID: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + Cellpadding: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + Cellspacing: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + 'Client.ID': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + Content: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + CorrelationID: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + CreatedDate: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + CustomerKey: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + FontFamily: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + HasFontSize: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + ID: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + IsBlank: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + IsDynamicContent: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + IsLocked: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + IsSurvey: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + Key: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + Layout: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + ModifiedDate: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + Name: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + ObjectID: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + Owner: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + PartnerKey: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + PartnerProperties: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + Width: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + }; + }; +} +import MetadataType from './MetadataType.js'; +//# sourceMappingURL=ContentArea.d.ts.map \ No newline at end of file diff --git a/@types/lib/metadataTypes/ContentArea.d.ts.map b/@types/lib/metadataTypes/ContentArea.d.ts.map new file mode 100644 index 000000000..652180604 --- /dev/null +++ b/@types/lib/metadataTypes/ContentArea.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"ContentArea.d.ts","sourceRoot":"","sources":["../../../lib/metadataTypes/ContentArea.js"],"names":[],"mappings":";uBAOa,OAAO,wBAAwB,EAAE,QAAQ;0BACzC,OAAO,wBAAwB,EAAE,WAAW;8BAC5C,OAAO,wBAAwB,EAAE,eAAe;+BAChD,OAAO,wBAAwB,EAAE,gBAAgB;mCACjD,OAAO,wBAAwB,EAAE,oBAAoB;kCACrD,OAAO,wBAAwB,EAAE,mBAAmB;8BACpD,OAAO,wBAAwB,EAAE,eAAe;iCAChD,OAAO,wBAAwB,EAAE,kBAAkB;gCACnD,OAAO,wBAAwB,EAAE,iBAAiB;0BAClD,OAAO,wBAAwB,EAAE,WAAW;AAVzD;;;;;;;;;;;GAWG;AAEH;;;;GAIG;AACH;IACI;;;;;;;;OAQG;IACH,6BANW,MAAM,MACN,IAAI,GAAG,MAAM,EAAE,OACf,IAAI,GAAG,MAAM,EAAE,QACf,MAAM,GACJ,OAAO,CAAE,kBAAkB,CAAC,CAmBxC;IA6BD;;;;;OAKG;IACH,mCAHW,gBAAgB,GACd,gBAAgB,CAkB5B;CACJ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;yBArGwB,mBAAmB"} \ No newline at end of file diff --git a/@types/lib/metadataTypes/DataExtension.d.ts b/@types/lib/metadataTypes/DataExtension.d.ts new file mode 100644 index 000000000..62969af95 --- /dev/null +++ b/@types/lib/metadataTypes/DataExtension.d.ts @@ -0,0 +1,571 @@ +export default DataExtension; +export type BuObject = import("../../types/mcdev.d.js").BuObject; +export type MetadataTypeItem = import("../../types/mcdev.d.js").MetadataTypeItem; +export type MetadataTypeItemDiff = import("../../types/mcdev.d.js").MetadataTypeItemDiff; +export type MetadataTypeMap = import("../../types/mcdev.d.js").MetadataTypeMap; +export type SoapRequestParams = import("../../types/mcdev.d.js").SoapRequestParams; +export type TemplateMap = import("../../types/mcdev.d.js").TemplateMap; +export type DataExtensionFieldItem = import("../../types/mcdev.d.js").DataExtensionFieldItem; +export type DataExtensionFieldMap = import("../../types/mcdev.d.js").DataExtensionFieldMap; +export type DataExtensionItem = import("../../types/mcdev.d.js").DataExtensionItem; +export type DataExtensionMap = import("../../types/mcdev.d.js").DataExtensionMap; +/** + * @typedef {import('../../types/mcdev.d.js').BuObject} BuObject + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItem} MetadataTypeItem + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItemDiff} MetadataTypeItemDiff + * @typedef {import('../../types/mcdev.d.js').MetadataTypeMap} MetadataTypeMap + * @typedef {import('../../types/mcdev.d.js').SoapRequestParams} SoapRequestParams + * @typedef {import('../../types/mcdev.d.js').TemplateMap} TemplateMap + */ +/** + * @typedef {import('../../types/mcdev.d.js').DataExtensionFieldItem} DataExtensionFieldItem + * @typedef {import('../../types/mcdev.d.js').DataExtensionFieldMap} DataExtensionFieldMap + * @typedef {import('../../types/mcdev.d.js').DataExtensionItem} DataExtensionItem + * @typedef {import('../../types/mcdev.d.js').DataExtensionMap} DataExtensionMap + */ +/** + * DataExtension MetadataType + * + * @augments MetadataType + */ +declare class DataExtension extends MetadataType { + /** @type {Object.<string, DataExtensionFieldMap>} key: deKey, value: deFieldMap */ + static oldFields: { + [x: string]: { + [x: string]: import("../../types/mcdev.d.js").DataExtensionFieldItem; + }; + }; + /** + * Upserts dataExtensions after retrieving them from source and target to compare + * if create or update operation is needed. + * + * @param {DataExtensionMap} metadataMap dataExtensions mapped by their customerKey + * @param {string} deployDir directory where deploy metadata are saved + * @returns {Promise.<MetadataTypeMap>} keyField => metadata map + */ + static upsert(metadataMap: DataExtensionMap, deployDir: string): Promise<MetadataTypeMap>; + /** + * helper for {@link DataExtension.upsert} + * + * @param {object} res - + * @returns {boolean} true: keep, false: discard + */ + static "__#private@#filterUpsertResults"(res: object): boolean; + /** + * Create a single dataExtension. Also creates their columns in 'dataExtension.columns' + * + * @param {DataExtensionItem} metadata single metadata entry + * @returns {Promise} Promise + */ + static create(metadata: DataExtensionItem): Promise<any>; + /** + * SFMC saves a date in "RetainUntil" under certain circumstances even + * if that field duplicates whats in the period fields + * during deployment, that extra value is not accepted by the APIs which is why it needs to be removed + * + * @param {DataExtensionItem} metadata single metadata entry + * @returns {void} + */ + static "__#private@#cleanupRetentionPolicyFields"(metadata: DataExtensionItem): void; + /** + * Updates a single dataExtension. Also updates their columns in 'dataExtension.columns' + * + * @param {DataExtensionItem} metadata single metadata entry + * @param {boolean} [handleOutside] if the API reponse is irregular this allows you to handle it outside of this generic method + * @returns {Promise} Promise + */ + static update(metadata: DataExtensionItem, handleOutside?: boolean): Promise<any>; + /** + * Gets executed after deployment of metadata type + * + * @param {DataExtensionMap} upsertedMetadata metadata mapped by their keyField + * @param {DataExtensionMap} originalMetadata metadata to be updated (contains additioanl fields) + * @param {{created: number, updated: number}} createdUpdated counter representing successful creates/updates + * @returns {Promise.<void>} - + */ + static postDeployTasks(upsertedMetadata: DataExtensionMap, originalMetadata: DataExtensionMap, createdUpdated: { + created: number; + updated: number; + }): Promise<void>; + /** + * takes care of updating attribute groups on child BUs after an update to Shared DataExtensions + * helper for {@link DataExtension.postDeployTasks} + * fixes an issue where shared data extensions are not visible in data designer on child BU; SF known issue: https://issues.salesforce.com/#q=W-11031095 + * + * @param {DataExtensionMap} upsertedMetadata metadata mapped by their keyField + * @param {DataExtensionMap} originalMetadata metadata to be updated (contains additioanl fields) + * @param {{created: number, updated: number}} createdUpdated counter representing successful creates/updates + * @returns {Promise.<void>} - + */ + static "__#private@#fixShared"(upsertedMetadata: DataExtensionMap, originalMetadata: DataExtensionMap, createdUpdated: { + created: number; + updated: number; + }): Promise<void>; + /** + * helper for {@link DataExtension.#fixShared} + * + * @returns {Promise.<string[]>} list of selected BU names + */ + static "__#private@#fixShared_getBUs"(): Promise<string[]>; + /** + * helper for {@link DataExtension.#fixShared} + * + * @param {string} childBuName name of child BU to fix + * @param {BuObject} buObjectParent bu object for parent BU + * @param {object} clientParent SDK for parent BU + * @param {Object.<string, string>} sharedDataExtensionMap ID-Key relationship of shared data extensions + * @returns {Promise.<string[]>} updated shared DE keys on BU + */ + static "__#private@#fixShared_onBU"(childBuName: string, buObjectParent: BuObject, clientParent: object, sharedDataExtensionMap: { + [x: string]: string; + }): Promise<string[]>; + /** + * method that actually takes care of triggering the update for a particular BU-sharedDe combo + * helper for {@link DataExtension.#fixShared_onBU} + * + * @param {string} deId data extension ObjectID + * @param {string} deKey dataExtension key + * @param {BuObject} buObjectChildBu BU object for Child BU + * @param {object} clientChildBu SDK for child BU + * @param {BuObject} buObjectParent BU object for Parent BU + * @param {object} clientParent SDK for parent BU + * @returns {Promise.<boolean>} flag that signals if the fix was successful + */ + static "__#private@#fixShared_item"(deId: string, deKey: string, buObjectChildBu: BuObject, clientChildBu: object, buObjectParent: BuObject, clientParent: object): Promise<boolean>; + /** + * add a new field to the shared DE to trigger an update to the data model + * helper for {@link DataExtension.#fixShared_item} + * + * @param {BuObject} buObjectChildBu BU object for Child BU + * @param {object} clientChildBu SDK for child BU + * @param {string} deKey dataExtension key + * @param {string} deId dataExtension ObjectID + * @returns {Promise.<string>} randomSuffix + */ + static "__#private@#fixShared_item_addField"(buObjectChildBu: BuObject, clientChildBu: object, deKey: string, deId: string): Promise<string>; + /** + * get ID of the field added by {@link DataExtension.#fixShared_item_addField} on the shared DE via parent BU + * helper for {@link DataExtension.#fixShared_item} + * + * @param {string} randomSuffix - + * @param {BuObject} buObjectParent BU object for Parent BU + * @param {object} clientParent SDK for parent BU + * @param {string} deKey dataExtension key + * @returns {Promise.<string>} fieldObjectID + */ + static "__#private@#fixShared_item_getFieldId"(randomSuffix: string, buObjectParent: BuObject, clientParent: object, deKey: string): Promise<string>; + /** + * delete the field added by {@link DataExtension.#fixShared_item_addField} + * helper for {@link DataExtension.#fixShared_item} + * + * @param {string} randomSuffix - + * @param {BuObject} buObjectChildBu BU object for Child BU + * @param {object} clientChildBu SDK for child BU + * @param {string} deKey dataExtension key + * @param {string} fieldObjectID field ObjectID + * @returns {Promise} - + */ + static "__#private@#fixShared_item_deleteField"(randomSuffix: string, buObjectChildBu: BuObject, clientChildBu: object, deKey: string, fieldObjectID: string): Promise<any>; + /** + * Retrieves dataExtension metadata. Afterwards starts retrieval of dataExtensionColumn metadata retrieval + * + * @param {string} retrieveDir Directory where retrieved metadata directory will be saved + * @param {string[]} [additionalFields] Returns specified fields even if their retrieve definition is not set to true + * @param {void | string[]} [_] unused parameter + * @param {string} [key] customer key of single item to retrieve + * @returns {Promise.<{metadata: DataExtensionMap, type: string}>} Promise of item map + */ + static retrieve(retrieveDir: string, additionalFields?: string[], _?: void | string[], key?: string): Promise<{ + metadata: DataExtensionMap; + type: string; + }>; + /** + * get shared dataExtensions from parent BU and merge them into the cache + * helper for {@link DataExtension.retrieve} and for AttributeSet.fixShared_retrieve + * + * @param {string[]} [additionalFields] Returns specified fields even if their retrieve definition is not set to true + * @returns {Promise.<DataExtensionMap>} keyField => metadata map + */ + static retrieveSharedForCache(additionalFields?: string[]): Promise<DataExtensionMap>; + /** + * helper to retrieve all dataExtension fields and attach them to the dataExtension metadata + * + * @param {DataExtensionMap} metadata already cached dataExtension metadata + * @param {SoapRequestParams} [fieldOptions] optionally filter results + * @param {string[]} [additionalFields] Returns specified fields even if their retrieve definition is not set to true + * @returns {Promise.<void>} - + */ + static attachFields(metadata: DataExtensionMap, fieldOptions?: SoapRequestParams, additionalFields?: string[]): Promise<void>; + /** + * Retrieves dataExtension metadata. Afterwards starts retrieval of dataExtensionColumn metadata retrieval + * + * @param {string[]} [additionalFields] Returns specified fields even if their retrieve definition is not set to true + * @returns {Promise.<{metadata: DataExtensionMap, type: string}>} Promise of item map + */ + static retrieveChangelog(additionalFields?: string[]): Promise<{ + metadata: DataExtensionMap; + type: string; + }>; + /** + * manages post retrieve steps + * + * @param {DataExtensionItem} metadata a single dataExtension + * @returns {Promise.<DataExtensionItem>} metadata + */ + static postRetrieveTasks(metadata: DataExtensionItem): Promise<DataExtensionItem>; + /** + * Helper to retrieve Data Extension Fields + * + * @private + * @param {SoapRequestParams} [options] options (e.g. continueRequest) + * @param {string[]} [additionalFields] Returns specified fields even if their retrieve definition is not set to true + * @returns {Promise.<DataExtensionFieldMap>} Promise of items + */ + private static _retrieveFields; + /** + * helps retrieving fields during templating and deploy where we dont want the full list + * + * @private + * @param {DataExtensionMap} metadata list of DEs + * @param {string} customerKey external key of single DE + * @returns {Promise.<void>} - + */ + private static _retrieveFieldsForSingleDe; + /** + * helper for {@link MetadataType.updateREST} and {@link MetadataType.updateSOAP} that removes old files after the key was changed + * + * @param {MetadataTypeItem} metadataEntry a single metadata Entry + * @returns {Promise.<void>} - + */ + static _postChangeKeyTasks(metadataEntry: MetadataTypeItem): Promise<void>; + /** + * prepares a DataExtension for deployment + * + * @param {DataExtensionItem} metadata a single data Extension + * @returns {Promise.<DataExtensionItem>} Promise of updated single DE + */ + static preDeployTasks(metadata: DataExtensionItem): Promise<DataExtensionItem>; + /** + * Saves json content to a html table in the local file system. Will create the parent directory if it does not exist. + * The json's first level of keys must represent the rows and the secend level the columns + * + * @private + * @param {DataExtensionItem} json single dataextension + * @param {object[][]} tabled prepped array for output in tabular format + * @returns {string} file content + */ + private static _generateDocHtml; + /** + * Experimental: Only working for DataExtensions: + * Saves json content to a html table in the local file system. Will create the parent directory if it does not exist. + * The json's first level of keys must represent the rows and the secend level the columns + * + * @private + * @param {DataExtensionItem} json dataextension + * @param {object[][]} tabled prepped array for output in tabular format + * @returns {string} file content + */ + private static _generateDocMd; + /** + * Saves json content to a html table in the local file system. Will create the parent directory if it does not exist. + * The json's first level of keys must represent the rows and the secend level the columns + * + * @private + * @param {string} directory directory the file will be written to + * @param {string} filename name of the file without '.json' ending + * @param {DataExtensionItem} json dataextension.columns + * @param {'html'|'md'} mode html or md + * @param {string[]} [fieldsToKeep] list of keys(columns) to show. This will also specify + * @returns {Promise.<void>} Promise of success of saving the file + */ + private static _writeDoc; + /** + * Parses metadata into a readable Markdown/HTML format then saves it + * + * @param {DataExtensionMap} [metadataMap] a list of dataExtension definitions + * @returns {Promise.<any>} - + */ + static document(metadataMap?: DataExtensionMap): Promise<any>; + /** + * clean up after deleting a metadata item + * + * @param {string} customerKey Identifier of metadata item + * @returns {Promise.<void>} - promise + */ + static postDeleteTasks(customerKey: string): Promise<void>; + /** + * Retrieves folder metadata into local filesystem. Also creates a uniquePath attribute for each folder. + * + * @returns {Promise.<{metadata: DataExtensionMap, type: string}>} Promise + */ + static retrieveForCache(): Promise<{ + metadata: DataExtensionMap; + type: string; + }>; + /** + * Retrieves dataExtension metadata in template format. + * + * @deprecated Use `retrieve` followed by `build` instead. `retrieveAsTemplate` will be removed in a future version. + * @param {string} templateDir Directory where retrieved metadata directory will be saved + * @param {string} name name of the metadata item + * @param {TemplateMap} templateVariables variables to be replaced in the metadata + * @returns {Promise.<{metadata: DataExtensionItem, type: string}>} Promise of items + */ + static retrieveAsTemplate(templateDir: string, name: string, templateVariables: TemplateMap): Promise<{ + metadata: DataExtensionItem; + type: string; + }>; + /** + * Retrieves dataExtension metadata and cleans it + * + * @private + * @param {string[]} [additionalFields] Returns specified fields even if their retrieve definition is not set to true + * @param {SoapRequestParams} [options] e.g. filter + * @returns {Promise.<DataExtensionMap>} keyField => metadata map + */ + private static _retrieveAll; +} +declare namespace DataExtension { + let deployedSharedKeys: any; + let buObject: import("../../types/mcdev.d.js").BuObject; + let client: any; + let definition: { + bodyIteratorField: string; + dependencies: string[]; + dependencyGraph: any; + folderType: string; + filter: { + CustomerKey: string[]; + Name: string[]; + }; + templateFields: { + AudienceBuilderResult: string[]; + CONTEXTUAL_SUPPRESSION_LISTS: string[]; + DomainExclusion: string[]; + 'Event DE Template': string[]; + PushSendLog: string[]; + SendLog: string[]; + 'SmartCapture - Contacts Template Extension': string[]; + SmsSendLog: string[]; + SMSMessageTracking: any; + SMSSubscriptionLog: any; + TriggeredSendDataExtension: string[]; + }; + dataRetentionPeriodUnitOfMeasureMapping: { + Days: number; + Weeks: number; + Months: number; + Years: number; + }; + hasExtended: boolean; + idField: string; + keyIsFixed: boolean; + keyField: string; + nameField: string; + folderIdField: string; + createdDateField: string; + createdNameField: any; + lastmodDateField: string; + lastmodNameField: any; + restPagination: boolean; + maxKeyLength: number; + type: string; + typeDescription: string; + typeRetrieveByDefault: boolean; + typeCdpByDefault: boolean; + typeName: string; + fields: { + CategoryID: { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: boolean; + }; + 'Client.ID': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + CreatedDate: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + CustomerKey: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + DataRetentionPeriod: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + DataRetentionPeriodLength: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + DataRetentionPeriodUnitOfMeasure: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + DeleteAtEndOfRetentionPeriod: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + Description: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + Fields: { + skipValidation: boolean; + }; + folderContentType: { + skipValidation: boolean; + }; + IsPlatformObject: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + IsSendable: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + IsTestable: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + ModifiedDate: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + Name: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + ObjectID: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + PartnerKey: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + ResetRetentionPeriodOnImport: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + RetainUntil: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + RowBasedRetention: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'SendableDataExtensionField.Name': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'SendableDataExtensionField.ObjectID': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'SendableDataExtensionField.PartnerKey': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + SendableSubscriberField: { + skipValidation: boolean; + }; + 'SendableSubscriberField.Name': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + Status: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'Template.CustomerKey': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'Template.ObjectID': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'Template.PartnerKey': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + r__folder_ContentType: { + skipValidation: boolean; + }; + r__folder_Path: { + skipValidation: boolean; + }; + r__dataExtensionTemplate_name: { + skipValidation: boolean; + }; + c__retentionPolicy: { + skipValidation: boolean; + }; + c__retainUntil: { + skipValidation: boolean; + }; + c__dataRetentionPeriodUnitOfMeasure: { + skipValidation: boolean; + }; + }; + }; +} +import MetadataType from './MetadataType.js'; +//# sourceMappingURL=DataExtension.d.ts.map \ No newline at end of file diff --git a/@types/lib/metadataTypes/DataExtension.d.ts.map b/@types/lib/metadataTypes/DataExtension.d.ts.map new file mode 100644 index 000000000..5b63fb471 --- /dev/null +++ b/@types/lib/metadataTypes/DataExtension.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"DataExtension.d.ts","sourceRoot":"","sources":["../../../lib/metadataTypes/DataExtension.js"],"names":[],"mappings":";uBAea,OAAO,wBAAwB,EAAE,QAAQ;+BACzC,OAAO,wBAAwB,EAAE,gBAAgB;mCACjD,OAAO,wBAAwB,EAAE,oBAAoB;8BACrD,OAAO,wBAAwB,EAAE,eAAe;gCAChD,OAAO,wBAAwB,EAAE,iBAAiB;0BAClD,OAAO,wBAAwB,EAAE,WAAW;qCAI5C,OAAO,wBAAwB,EAAE,sBAAsB;oCACvD,OAAO,wBAAwB,EAAE,qBAAqB;gCACtD,OAAO,wBAAwB,EAAE,iBAAiB;+BAClD,OAAO,wBAAwB,EAAE,gBAAgB;AAb9D;;;;;;;GAOG;AAEH;;;;;GAKG;AAEH;;;;GAIG;AACH;IACI,mFAAmF;IACnF;;;;MAAiB;IAEjB;;;;;;;OAOG;IACH,2BAJW,gBAAgB,aAChB,MAAM,GACJ,OAAO,CAAE,eAAe,CAAC,CAqGrC;IAyED;;;;;OAKG;IACH,8CAHW,MAAM,GACJ,OAAO,CA0BnB;IAED;;;;;OAKG;IACH,wBAHW,iBAAiB,gBAK3B;IAED;;;;;;;OAOG;IACH,4DAHW,iBAAiB,GACf,IAAI,CAahB;IAED;;;;;;OAMG;IACH,wBAJW,iBAAiB,kBACjB,OAAO,gBAKjB;IAED;;;;;;;OAOG;IACH,yCALW,gBAAgB,oBAChB,gBAAgB,kBAChB;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAC,GAChC,OAAO,CAAE,IAAI,CAAC,CAsE1B;IAED;;;;;;;;;OASG;IACH,iDALW,gBAAgB,oBAChB,gBAAgB,kBAChB;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAC,GAChC,OAAO,CAAE,IAAI,CAAC,CAyE1B;IAED;;;;OAIG;IACH,yCAFa,OAAO,CAAE,MAAM,EAAE,CAAC,CA8C9B;IAED;;;;;;;;OAQG;IACH,iDANW,MAAM,kBACN,QAAQ,gBACR,MAAM;;QAEJ,OAAO,CAAE,MAAM,EAAE,CAAC,CAwE9B;IAED;;;;;;;;;;;OAWG;IACH,0CARW,MAAM,SACN,MAAM,mBACN,QAAQ,iBACR,MAAM,kBACN,QAAQ,gBACR,MAAM,GACJ,OAAO,CAAE,OAAO,CAAC,CA+C7B;IAED;;;;;;;;;OASG;IACH,8DANW,QAAQ,iBACR,MAAM,SACN,MAAM,QACN,MAAM,GACJ,OAAO,CAAE,MAAM,CAAC,CA2B5B;IAED;;;;;;;;;OASG;IACH,6DANW,MAAM,kBACN,QAAQ,gBACR,MAAM,SACN,MAAM,GACJ,OAAO,CAAE,MAAM,CAAC,CAkB5B;IAED;;;;;;;;;;OAUG;IACH,8DAPW,MAAM,mBACN,QAAQ,iBACR,MAAM,SACN,MAAM,iBACN,MAAM,gBAgBhB;IAED;;;;;;;;OAQG;IACH,6BANW,MAAM,qBACN,MAAM,EAAE,MACR,IAAI,GAAG,MAAM,EAAE,QACf,MAAM,GACJ,OAAO,CAAE;QAAC,QAAQ,EAAE,gBAAgB,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAC,CAAC,CAgDhE;IAED;;;;;;OAMG;IACH,iDAHW,MAAM,EAAE,GACN,OAAO,CAAE,gBAAgB,CAAC,CAqEtC;IAED;;;;;;;OAOG;IACH,8BALW,gBAAgB,iBAChB,iBAAiB,qBACjB,MAAM,EAAE,GACN,OAAO,CAAE,IAAI,CAAC,CA0B1B;IAED;;;;;OAKG;IACH,4CAHW,MAAM,EAAE,GACN,OAAO,CAAE;QAAC,QAAQ,EAAE,gBAAgB,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAC,CAAC,CAKhE;IAED;;;;;OAKG;IACH,mCAHW,iBAAiB,GACf,OAAO,CAAE,iBAAiB,CAAC,CAoFvC;IAED;;;;;;;OAOG;IACH,+BAUC;IAED;;;;;;;OAOG;IACH,0CAsBC;IAED;;;;;OAKG;IACH,0CAHW,gBAAgB,GACd,OAAO,CAAE,IAAI,CAAC,CAI1B;IAED;;;;;OAKG;IACH,gCAHW,iBAAiB,GACf,OAAO,CAAE,iBAAiB,CAAC,CAiIvC;IAED;;;;;;;;OAQG;IACH,gCA2CC;IAED;;;;;;;;;OASG;IACH,8BAqEC;IAED;;;;;;;;;;;OAWG;IACH,yBAgCC;IAED;;;;;OAKG;IACH,8BAHW,gBAAgB,GACd,OAAO,CAAE,GAAG,CAAC,CAiFzB;IAYD;;;;;OAKG;IACH,oCAHW,MAAM,GACJ,OAAO,CAAE,IAAI,CAAC,CAM1B;IAED;;;;OAIG;IACH,2BAFa,OAAO,CAAE;QAAC,QAAQ,EAAE,gBAAgB,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAC,CAAC,CAIhE;IAED;;;;;;;;OAQG;IACH,uCALW,MAAM,QACN,MAAM,qBACN,WAAW,GACT,OAAO,CAAE;QAAC,QAAQ,EAAE,iBAAiB,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAC,CAAC,CAiDjE;IA6DD;;;;;;;OAOG;IACH,4BAWC;CAgHJ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;yBAjtDwB,mBAAmB"} \ No newline at end of file diff --git a/@types/lib/metadataTypes/DataExtensionField.d.ts b/@types/lib/metadataTypes/DataExtensionField.d.ts new file mode 100644 index 000000000..56f41aad3 --- /dev/null +++ b/@types/lib/metadataTypes/DataExtensionField.d.ts @@ -0,0 +1,237 @@ +export default DataExtensionField; +export type BuObject = import("../../types/mcdev.d.js").BuObject; +export type CodeExtract = import("../../types/mcdev.d.js").CodeExtract; +export type CodeExtractItem = import("../../types/mcdev.d.js").CodeExtractItem; +export type MetadataTypeItem = import("../../types/mcdev.d.js").MetadataTypeItem; +export type MetadataTypeItemDiff = import("../../types/mcdev.d.js").MetadataTypeItemDiff; +export type MetadataTypeItemObj = import("../../types/mcdev.d.js").MetadataTypeItemObj; +export type MetadataTypeMap = import("../../types/mcdev.d.js").MetadataTypeMap; +export type MetadataTypeMapObj = import("../../types/mcdev.d.js").MetadataTypeMapObj; +export type SoapRequestParams = import("../../types/mcdev.d.js").SoapRequestParams; +export type TemplateMap = import("../../types/mcdev.d.js").TemplateMap; +export type DataExtensionFieldMap = import("../../types/mcdev.d.js").DataExtensionFieldMap; +export type DataExtensionFieldItem = import("../../types/mcdev.d.js").DataExtensionFieldItem; +/** + * @typedef {import('../../types/mcdev.d.js').BuObject} BuObject + * @typedef {import('../../types/mcdev.d.js').CodeExtract} CodeExtract + * @typedef {import('../../types/mcdev.d.js').CodeExtractItem} CodeExtractItem + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItem} MetadataTypeItem + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItemDiff} MetadataTypeItemDiff + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItemObj} MetadataTypeItemObj + * @typedef {import('../../types/mcdev.d.js').MetadataTypeMap} MetadataTypeMap + * @typedef {import('../../types/mcdev.d.js').MetadataTypeMapObj} MetadataTypeMapObj + * @typedef {import('../../types/mcdev.d.js').SoapRequestParams} SoapRequestParams + * @typedef {import('../../types/mcdev.d.js').TemplateMap} TemplateMap + */ +/** + * @typedef {import('../../types/mcdev.d.js').DataExtensionFieldMap} DataExtensionFieldMap + * @typedef {import('../../types/mcdev.d.js').DataExtensionFieldItem} DataExtensionFieldItem + */ +/** + * DataExtensionField MetadataType + * + * @augments MetadataType + */ +declare class DataExtensionField extends MetadataType { + static fixShared_fields: any; + /** + * Retrieves all records and saves it to disk + * + * @param {string} retrieveDir Directory where retrieved metadata directory will be saved + * @param {string[]} [additionalFields] Returns specified fields even if their retrieve definition is not set to true + * @returns {Promise.<{metadata: DataExtensionFieldMap, type: string}>} Promise of items + */ + static retrieve(retrieveDir: string, additionalFields?: string[]): Promise<{ + metadata: DataExtensionFieldMap; + type: string; + }>; + /** + * Retrieves all records and saves it to disk + * + * @returns {Promise.<MetadataTypeMapObj>} Promise of items + */ + static retrieveForCache(): Promise<MetadataTypeMapObj>; + /** + * helps retrieving fields for a single DE. Use when needing field data for one DE only. + * + * @param {string} customerKey external key of single DE + * @returns {Promise.<object>} Promise of items + */ + static retrieveFieldsForSingleDe(customerKey: string): Promise<object>; + /** + * Retrieves all records for caching + * + * @param {SoapRequestParams} [requestParams] required for the specific request (filter for example) + * @param {string[]} [additionalFields] Returns specified fields even if their retrieve definition is not set to true + * @returns {Promise.<{metadata: DataExtensionFieldMap, type: string}>} Promise of items + */ + static retrieveForCacheDE(requestParams?: SoapRequestParams, additionalFields?: string[]): Promise<{ + metadata: DataExtensionFieldMap; + type: string; + }>; + /** + * helper for DataExtension.retrieveFieldsForSingleDe that sorts the fields into an array + * + * @param {DataExtensionFieldMap} fieldsObj customerKey-based list of fields for one dataExtension + * @returns {DataExtensionFieldItem[]} sorted array of field objects + */ + static convertToSortedArray(fieldsObj: DataExtensionFieldMap): DataExtensionFieldItem[]; + /** + * sorting method to ensure `Ordinal` is respected + * + * @param {DataExtensionFieldItem} a - + * @param {DataExtensionFieldItem} b - + * @returns {number} sorting based on Ordinal + */ + static sortDeFields(a: DataExtensionFieldItem, b: DataExtensionFieldItem): number; + /** + * manages post retrieve steps; only used by DataExtension class + * + * @param {DataExtensionFieldItem} metadata a single item + * @returns {DataExtensionFieldItem} metadata + */ + static postRetrieveTasksDE(metadata: DataExtensionFieldItem): DataExtensionFieldItem; + /** + * Mofifies passed deployColumns for update by mapping ObjectID to their target column's values. + * Removes FieldType field if its the same in deploy and target column, because it results in an error even if its of the same type + * + * @param {DataExtensionFieldItem[]} deployColumns Columns of data extension that will be deployed + * @param {string} deKey external/customer key of Data Extension + * @returns {Promise.<DataExtensionFieldMap>} existing fields by their original name to allow re-adding FieldType after update + */ + static prepareDeployColumnsOnUpdate(deployColumns: DataExtensionFieldItem[], deKey: string): Promise<DataExtensionFieldMap>; + /** + * Delete a data extension from the specified business unit + * + * @param {string} customerKey Identifier of metadata + * @param {string} [fieldId] for programmatic deletes only one can pass in the ID directly + * @returns {Promise.<boolean>} deletion success flag + */ + static deleteByKeySOAP(customerKey: string, fieldId?: string): Promise<boolean>; +} +declare namespace DataExtensionField { + let definition: { + bodyIteratorField: string; + dependencies: string[]; + dependencyGraph: any; + filter: {}; + hasExtended: boolean; + idField: string; + keyIsFixed: boolean; + keyField: string; + nameField: string; + restPagination: boolean; + type: string; + typeDescription: string; + typeRetrieveByDefault: boolean; + typeCdpByDefault: boolean; + typeName: string; + deleteSynchronously: boolean; + fields: { + 'Client.ID': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + CreatedDate: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + CustomerKey: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'DataExtension.CustomerKey': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'DataExtension.PartnerKey': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'DataExtension.ObjectID': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + DefaultValue: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + FieldType: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + IsPrimaryKey: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + IsRequired: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + MaxLength: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + ModifiedDate: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + Name: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + ObjectID: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + Ordinal: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + PartnerKey: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + Scale: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + }; + }; +} +import MetadataType from './MetadataType.js'; +//# sourceMappingURL=DataExtensionField.d.ts.map \ No newline at end of file diff --git a/@types/lib/metadataTypes/DataExtensionField.d.ts.map b/@types/lib/metadataTypes/DataExtensionField.d.ts.map new file mode 100644 index 000000000..4f7cac940 --- /dev/null +++ b/@types/lib/metadataTypes/DataExtensionField.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"DataExtensionField.d.ts","sourceRoot":"","sources":["../../../lib/metadataTypes/DataExtensionField.js"],"names":[],"mappings":";uBAQa,OAAO,wBAAwB,EAAE,QAAQ;0BACzC,OAAO,wBAAwB,EAAE,WAAW;8BAC5C,OAAO,wBAAwB,EAAE,eAAe;+BAChD,OAAO,wBAAwB,EAAE,gBAAgB;mCACjD,OAAO,wBAAwB,EAAE,oBAAoB;kCACrD,OAAO,wBAAwB,EAAE,mBAAmB;8BACpD,OAAO,wBAAwB,EAAE,eAAe;iCAChD,OAAO,wBAAwB,EAAE,kBAAkB;gCACnD,OAAO,wBAAwB,EAAE,iBAAiB;0BAClD,OAAO,wBAAwB,EAAE,WAAW;oCAI5C,OAAO,wBAAwB,EAAE,qBAAqB;qCACtD,OAAO,wBAAwB,EAAE,sBAAsB;AAfpE;;;;;;;;;;;GAWG;AAEH;;;GAGG;AAEH;;;;GAIG;AACH;IACI,6BAAwB;IAExB;;;;;;OAMG;IACH,6BAJW,MAAM,qBACN,MAAM,EAAE,GACN,OAAO,CAAE;QAAC,QAAQ,EAAE,qBAAqB,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAC,CAAC,CAIrE;IACD;;;;OAIG;IACH,2BAFa,OAAO,CAAE,kBAAkB,CAAC,CAQxC;IACD;;;;;OAKG;IACH,8CAHW,MAAM,GACJ,OAAO,CAAE,MAAM,CAAC,CAgB5B;IAED;;;;;;OAMG;IACH,0CAJW,iBAAiB,qBACjB,MAAM,EAAE,GACN,OAAO,CAAE;QAAC,QAAQ,EAAE,qBAAqB,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAC,CAAC,CAUrE;IAED;;;;;OAKG;IACH,uCAHW,qBAAqB,GACnB,sBAAsB,EAAE,CASpC;IAED;;;;;;OAMG;IACH,uBAJW,sBAAsB,KACtB,sBAAsB,GACpB,MAAM,CAIlB;IAED;;;;;OAKG;IACH,qCAHW,sBAAsB,GACpB,sBAAsB,CAelC;IAED;;;;;;;OAOG;IACH,mDAJW,sBAAsB,EAAE,SACxB,MAAM,GACJ,OAAO,CAAE,qBAAqB,CAAC,CAgK3C;IAYD;;;;;;OAMG;IACH,oCAJW,MAAM,YACN,MAAM,GACJ,OAAO,CAAE,OAAO,CAAC,CAwH7B;CACJ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;yBA3bwB,mBAAmB"} \ No newline at end of file diff --git a/@types/lib/metadataTypes/DataExtensionTemplate.d.ts b/@types/lib/metadataTypes/DataExtensionTemplate.d.ts new file mode 100644 index 000000000..83a6da2e3 --- /dev/null +++ b/@types/lib/metadataTypes/DataExtensionTemplate.d.ts @@ -0,0 +1,177 @@ +export default DataExtensionTemplate; +export type BuObject = import("../../types/mcdev.d.js").BuObject; +export type CodeExtract = import("../../types/mcdev.d.js").CodeExtract; +export type CodeExtractItem = import("../../types/mcdev.d.js").CodeExtractItem; +export type MetadataTypeItem = import("../../types/mcdev.d.js").MetadataTypeItem; +export type MetadataTypeItemDiff = import("../../types/mcdev.d.js").MetadataTypeItemDiff; +export type MetadataTypeItemObj = import("../../types/mcdev.d.js").MetadataTypeItemObj; +export type MetadataTypeMap = import("../../types/mcdev.d.js").MetadataTypeMap; +export type MetadataTypeMapObj = import("../../types/mcdev.d.js").MetadataTypeMapObj; +export type SoapRequestParams = import("../../types/mcdev.d.js").SoapRequestParams; +export type TemplateMap = import("../../types/mcdev.d.js").TemplateMap; +/** + * @typedef {import('../../types/mcdev.d.js').BuObject} BuObject + * @typedef {import('../../types/mcdev.d.js').CodeExtract} CodeExtract + * @typedef {import('../../types/mcdev.d.js').CodeExtractItem} CodeExtractItem + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItem} MetadataTypeItem + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItemDiff} MetadataTypeItemDiff + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItemObj} MetadataTypeItemObj + * @typedef {import('../../types/mcdev.d.js').MetadataTypeMap} MetadataTypeMap + * @typedef {import('../../types/mcdev.d.js').MetadataTypeMapObj} MetadataTypeMapObj + * @typedef {import('../../types/mcdev.d.js').SoapRequestParams} SoapRequestParams + * @typedef {import('../../types/mcdev.d.js').TemplateMap} TemplateMap + */ +/** + * DataExtensionTemplate MetadataType + * + * @augments MetadataType + */ +declare class DataExtensionTemplate extends MetadataType { + /** + * Retrieves SOAP based metadata of metadata type into local filesystem. executes callback with retrieved metadata + * + * @param {string} retrieveDir Directory where retrieved metadata directory will be saved + * @param {void | string[]} [_] unused parameter + * @param {void | string[]} [__] unused parameter + * @param {string} [key] customer key of single item to retrieve + * @returns {Promise.<MetadataTypeMapObj>} Promise of metadata + */ + static retrieve(retrieveDir: string, _?: void | string[], __?: void | string[], key?: string): Promise<MetadataTypeMapObj>; +} +declare namespace DataExtensionTemplate { + let definition: { + bodyIteratorField: string; + dependencies: any[]; + dependencyGraph: any; + filter: {}; + hasExtended: boolean; + idField: string; + keyIsFixed: boolean; + keyField: string; + nameField: string; + restPagination: boolean; + type: string; + typeDescription: string; + typeRetrieveByDefault: boolean; + typeCdpByDefault: boolean; + typeName: string; + fields: { + 'Client.ID': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + CreatedDate: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + ModifiedDate: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + CustomerKey: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + ObjectID: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + Name: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + Description: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + PartnerKey: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + PartnerProperties: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + IsSendable: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + IsTestable: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + SendableCustomObjectField: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + SendableSubscriberField: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + DataRetentionPeriodLength: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + DataRetentionPeriodUnitOfMeasure: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + RowBasedRetention: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + ResetRetentionPeriodOnImport: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + DeleteAtEndOfRetentionPeriod: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + RetainUntil: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + }; + }; +} +import MetadataType from './MetadataType.js'; +//# sourceMappingURL=DataExtensionTemplate.d.ts.map \ No newline at end of file diff --git a/@types/lib/metadataTypes/DataExtensionTemplate.d.ts.map b/@types/lib/metadataTypes/DataExtensionTemplate.d.ts.map new file mode 100644 index 000000000..50b93be84 --- /dev/null +++ b/@types/lib/metadataTypes/DataExtensionTemplate.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"DataExtensionTemplate.d.ts","sourceRoot":"","sources":["../../../lib/metadataTypes/DataExtensionTemplate.js"],"names":[],"mappings":";uBAKa,OAAO,wBAAwB,EAAE,QAAQ;0BACzC,OAAO,wBAAwB,EAAE,WAAW;8BAC5C,OAAO,wBAAwB,EAAE,eAAe;+BAChD,OAAO,wBAAwB,EAAE,gBAAgB;mCACjD,OAAO,wBAAwB,EAAE,oBAAoB;kCACrD,OAAO,wBAAwB,EAAE,mBAAmB;8BACpD,OAAO,wBAAwB,EAAE,eAAe;iCAChD,OAAO,wBAAwB,EAAE,kBAAkB;gCACnD,OAAO,wBAAwB,EAAE,iBAAiB;0BAClD,OAAO,wBAAwB,EAAE,WAAW;AAVzD;;;;;;;;;;;GAWG;AAEH;;;;GAIG;AACH;IACI;;;;;;;;OAQG;IACH,6BANW,MAAM,MACN,IAAI,GAAG,MAAM,EAAE,OACf,IAAI,GAAG,MAAM,EAAE,QACf,MAAM,GACJ,OAAO,CAAE,kBAAkB,CAAC,CAexC;CACJ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;yBA5CwB,mBAAmB"} \ No newline at end of file diff --git a/@types/lib/metadataTypes/DataExtract.d.ts b/@types/lib/metadataTypes/DataExtract.d.ts new file mode 100644 index 000000000..b0b99fbf7 --- /dev/null +++ b/@types/lib/metadataTypes/DataExtract.d.ts @@ -0,0 +1,222 @@ +export default DataExtract; +export type BuObject = import("../../types/mcdev.d.js").BuObject; +export type CodeExtract = import("../../types/mcdev.d.js").CodeExtract; +export type CodeExtractItem = import("../../types/mcdev.d.js").CodeExtractItem; +export type MetadataTypeItem = import("../../types/mcdev.d.js").MetadataTypeItem; +export type MetadataTypeItemDiff = import("../../types/mcdev.d.js").MetadataTypeItemDiff; +export type MetadataTypeItemObj = import("../../types/mcdev.d.js").MetadataTypeItemObj; +export type MetadataTypeMap = import("../../types/mcdev.d.js").MetadataTypeMap; +export type MetadataTypeMapObj = import("../../types/mcdev.d.js").MetadataTypeMapObj; +export type SoapRequestParams = import("../../types/mcdev.d.js").SoapRequestParams; +export type TemplateMap = import("../../types/mcdev.d.js").TemplateMap; +/** + * @typedef {import('../../types/mcdev.d.js').BuObject} BuObject + * @typedef {import('../../types/mcdev.d.js').CodeExtract} CodeExtract + * @typedef {import('../../types/mcdev.d.js').CodeExtractItem} CodeExtractItem + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItem} MetadataTypeItem + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItemDiff} MetadataTypeItemDiff + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItemObj} MetadataTypeItemObj + * @typedef {import('../../types/mcdev.d.js').MetadataTypeMap} MetadataTypeMap + * @typedef {import('../../types/mcdev.d.js').MetadataTypeMapObj} MetadataTypeMapObj + * @typedef {import('../../types/mcdev.d.js').SoapRequestParams} SoapRequestParams + * @typedef {import('../../types/mcdev.d.js').TemplateMap} TemplateMap + */ +/** + * DataExtract MetadataType + * + * @augments MetadataType + */ +declare class DataExtract extends MetadataType { + /** + * Retrieves Metadata of Data Extract Activity. + * Endpoint /automation/v1/dataextracts/ returns all Data Extracts + * + * @param {string} retrieveDir Directory where retrieved metadata directory will be saved + * @param {void | string[]} [_] unused parameter + * @param {void | string[]} [__] unused parameter + * @param {string} [key] customer key of single item to retrieve + * @returns {Promise.<MetadataTypeMapObj>} Promise of metadata + */ + static retrieve(retrieveDir: string, _?: void | string[], __?: void | string[], key?: string): Promise<MetadataTypeMapObj>; + /** + * Retrieves Metadata of Data Extract Activity for caching + * + * @returns {Promise.<MetadataTypeMapObj>} Promise of metadata + */ + static retrieveForCache(): Promise<MetadataTypeMapObj>; + /** + * Retrieve a specific dataExtract Definition by Name + * + * @deprecated Use `retrieve` followed by `build` instead. `retrieveAsTemplate` will be removed in a future version. + * @param {string} templateDir Directory where retrieved metadata directory will be saved + * @param {string} name name of the metadata file + * @param {TemplateMap} templateVariables variables to be replaced in the metadata + * @returns {Promise.<MetadataTypeItemObj>} Promise of metadata + */ + static retrieveAsTemplate(templateDir: string, name: string, templateVariables: TemplateMap): Promise<MetadataTypeItemObj>; + /** + * Creates a single Data Extract + * + * @param {MetadataTypeItem} dataExtract a single Data Extract + * @returns {Promise} Promise + */ + static create(dataExtract: MetadataTypeItem): Promise<any>; + /** + * Updates a single Data Extract + * + * @param {MetadataTypeItem} dataExtract a single Data Extract + * @returns {Promise} Promise + */ + static update(dataExtract: MetadataTypeItem): Promise<any>; + /** + * prepares a dataExtract for deployment + * + * @param {MetadataTypeItem} metadata a single dataExtract activity definition + * @returns {MetadataTypeItem} metadata object + */ + static preDeployTasks(metadata: MetadataTypeItem): MetadataTypeItem; + /** + * Gets executed after deployment of metadata type + * + * @param {MetadataTypeMap} upsertResults metadata mapped by their keyField as returned by update/create + * @returns {Promise.<void>} - + */ + static postDeployTasks(upsertResults: MetadataTypeMap): Promise<void>; + /** + * manages post retrieve steps + * + * @param {MetadataTypeItem} metadata a single item + * @returns {MetadataTypeItem} metadata + */ + static postRetrieveTasks(metadata: MetadataTypeItem): MetadataTypeItem; + /** + * helper to allow us to select single metadata entries via REST + * + * @private + * @param {string} key customer key + * @returns {Promise.<string>} objectId or enpty string + */ + private static _getObjectIdForSingleRetrieve; +} +declare namespace DataExtract { + let definition: { + bodyIteratorField: string; + dependencies: string[]; + dependencyGraph: { + dataExtension: string[]; + }; + hasExtended: boolean; + idField: string; + keyIsFixed: boolean; + keyField: string; + createdDateField: string; + createdNameField: string; + lastmodDateField: string; + lastmodNameField: string; + nameField: string; + restPagination: boolean; + maxKeyLength: number; + type: string; + typeDescription: string; + typeRetrieveByDefault: boolean; + typeCdpByDefault: boolean; + typeName: string; + fields: { + createdBy: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + createdDate: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + dataExtractDefinitionId: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + dataExtractTypeId: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + dataFields: { + skipValidation: boolean; + }; + description: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + endDate: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + fileSpec: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + intervalType: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + key: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + modifiedBy: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + modifiedDate: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + name: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + startDate: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + r__dataExtractType_name: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + r__dataExtension_key: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + }; + }; +} +import MetadataType from './MetadataType.js'; +//# sourceMappingURL=DataExtract.d.ts.map \ No newline at end of file diff --git a/@types/lib/metadataTypes/DataExtract.d.ts.map b/@types/lib/metadataTypes/DataExtract.d.ts.map new file mode 100644 index 000000000..ed551028b --- /dev/null +++ b/@types/lib/metadataTypes/DataExtract.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"DataExtract.d.ts","sourceRoot":"","sources":["../../../lib/metadataTypes/DataExtract.js"],"names":[],"mappings":";uBAQa,OAAO,wBAAwB,EAAE,QAAQ;0BACzC,OAAO,wBAAwB,EAAE,WAAW;8BAC5C,OAAO,wBAAwB,EAAE,eAAe;+BAChD,OAAO,wBAAwB,EAAE,gBAAgB;mCACjD,OAAO,wBAAwB,EAAE,oBAAoB;kCACrD,OAAO,wBAAwB,EAAE,mBAAmB;8BACpD,OAAO,wBAAwB,EAAE,eAAe;iCAChD,OAAO,wBAAwB,EAAE,kBAAkB;gCACnD,OAAO,wBAAwB,EAAE,iBAAiB;0BAClD,OAAO,wBAAwB,EAAE,WAAW;AAVzD;;;;;;;;;;;GAWG;AAEH;;;;GAIG;AACH;IACI;;;;;;;;;OASG;IACH,6BANW,MAAM,MACN,IAAI,GAAG,MAAM,EAAE,OACf,IAAI,GAAG,MAAM,EAAE,QACf,MAAM,GACJ,OAAO,CAAE,kBAAkB,CAAC,CAIxC;IAED;;;;OAIG;IACH,2BAFa,OAAO,CAAE,kBAAkB,CAAC,CAIxC;IAED;;;;;;;;OAQG;IACH,uCALW,MAAM,QACN,MAAM,qBACN,WAAW,GACT,OAAO,CAAE,mBAAmB,CAAC,CA6CzC;IAED;;;;;OAKG;IACH,2BAHW,gBAAgB,gBAK1B;IAED;;;;;OAKG;IACH,2BAHW,gBAAgB,gBAQ1B;IAED;;;;;OAKG;IACH,gCAHW,gBAAgB,GACd,gBAAgB,CA0B5B;IAED;;;;;OAKG;IACH,sCAHW,eAAe,GACb,OAAO,CAAE,IAAI,CAAC,CAc1B;IAED;;;;;OAKG;IACH,mCAHW,gBAAgB,GACd,gBAAgB,CAkE5B;IAED;;;;;;OAMG;IACH,6CASC;CAiBJ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;yBAzRwB,mBAAmB"} \ No newline at end of file diff --git a/@types/lib/metadataTypes/DataExtractType.d.ts b/@types/lib/metadataTypes/DataExtractType.d.ts new file mode 100644 index 000000000..86f97ac24 --- /dev/null +++ b/@types/lib/metadataTypes/DataExtractType.d.ts @@ -0,0 +1,82 @@ +export default DataExtractType; +export type BuObject = import("../../types/mcdev.d.js").BuObject; +export type CodeExtract = import("../../types/mcdev.d.js").CodeExtract; +export type CodeExtractItem = import("../../types/mcdev.d.js").CodeExtractItem; +export type MetadataTypeItem = import("../../types/mcdev.d.js").MetadataTypeItem; +export type MetadataTypeItemDiff = import("../../types/mcdev.d.js").MetadataTypeItemDiff; +export type MetadataTypeItemObj = import("../../types/mcdev.d.js").MetadataTypeItemObj; +export type MetadataTypeMap = import("../../types/mcdev.d.js").MetadataTypeMap; +export type MetadataTypeMapObj = import("../../types/mcdev.d.js").MetadataTypeMapObj; +export type SoapRequestParams = import("../../types/mcdev.d.js").SoapRequestParams; +export type TemplateMap = import("../../types/mcdev.d.js").TemplateMap; +/** + * @typedef {import('../../types/mcdev.d.js').BuObject} BuObject + * @typedef {import('../../types/mcdev.d.js').CodeExtract} CodeExtract + * @typedef {import('../../types/mcdev.d.js').CodeExtractItem} CodeExtractItem + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItem} MetadataTypeItem + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItemDiff} MetadataTypeItemDiff + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItemObj} MetadataTypeItemObj + * @typedef {import('../../types/mcdev.d.js').MetadataTypeMap} MetadataTypeMap + * @typedef {import('../../types/mcdev.d.js').MetadataTypeMapObj} MetadataTypeMapObj + * @typedef {import('../../types/mcdev.d.js').SoapRequestParams} SoapRequestParams + * @typedef {import('../../types/mcdev.d.js').TemplateMap} TemplateMap + */ +/** + * DataExtractType MetadataType + * Only for Caching No retrieve/upsert is required + * as this is a configuration in the EID + * + * @augments MetadataType + */ +declare class DataExtractType extends MetadataType { + /** + * Retrieves Metadata of Data Extract Type. + * + * @param {string} retrieveDir Directory where retrieved metadata directory will be saved + * @param {void | string[]} [_] unused parameter + * @param {void | string[]} [__] unused parameter + * @param {string} [key] customer key of single item to retrieve + * @returns {Promise.<MetadataTypeMapObj>} Promise of metadata + */ + static retrieve(retrieveDir: string, _?: void | string[], __?: void | string[], key?: string): Promise<MetadataTypeMapObj>; + /** + * Retrieves Metadata of Data Extract Type for caching. + * + * @returns {Promise.<MetadataTypeMapObj>} Promise of metadata + */ + static retrieveForCache(): Promise<MetadataTypeMapObj>; +} +declare namespace DataExtractType { + let definition: { + bodyIteratorField: string; + dependencies: any[]; + dependencyGraph: any; + hasExtended: boolean; + idField: string; + keyIsFixed: boolean; + keyField: string; + nameField: string; + restPagination: boolean; + type: string; + typeDescription: string; + typeRetrieveByDefault: boolean; + typeCdpByDefault: boolean; + typeName: string; + fields: { + name: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + extractId: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + }; + }; +} +import MetadataType from './MetadataType.js'; +//# sourceMappingURL=DataExtractType.d.ts.map \ No newline at end of file diff --git a/@types/lib/metadataTypes/DataExtractType.d.ts.map b/@types/lib/metadataTypes/DataExtractType.d.ts.map new file mode 100644 index 000000000..a72ce5b12 --- /dev/null +++ b/@types/lib/metadataTypes/DataExtractType.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"DataExtractType.d.ts","sourceRoot":"","sources":["../../../lib/metadataTypes/DataExtractType.js"],"names":[],"mappings":";uBAKa,OAAO,wBAAwB,EAAE,QAAQ;0BACzC,OAAO,wBAAwB,EAAE,WAAW;8BAC5C,OAAO,wBAAwB,EAAE,eAAe;+BAChD,OAAO,wBAAwB,EAAE,gBAAgB;mCACjD,OAAO,wBAAwB,EAAE,oBAAoB;kCACrD,OAAO,wBAAwB,EAAE,mBAAmB;8BACpD,OAAO,wBAAwB,EAAE,eAAe;iCAChD,OAAO,wBAAwB,EAAE,kBAAkB;gCACnD,OAAO,wBAAwB,EAAE,iBAAiB;0BAClD,OAAO,wBAAwB,EAAE,WAAW;AAVzD;;;;;;;;;;;GAWG;AAEH;;;;;;GAMG;AACH;IACI;;;;;;;;OAQG;IACH,6BANW,MAAM,MACN,IAAI,GAAG,MAAM,EAAE,OACf,IAAI,GAAG,MAAM,EAAE,QACf,MAAM,GACJ,OAAO,CAAE,kBAAkB,CAAC,CAIxC;IAED;;;;OAIG;IACH,2BAFa,OAAO,CAAE,kBAAkB,CAAC,CAIxC;CACJ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;yBA5CwB,mBAAmB"} \ No newline at end of file diff --git a/@types/lib/metadataTypes/DataFilter.d.ts b/@types/lib/metadataTypes/DataFilter.d.ts new file mode 100644 index 000000000..0b0a9ad8d --- /dev/null +++ b/@types/lib/metadataTypes/DataFilter.d.ts @@ -0,0 +1,336 @@ +export default DataFilter; +export type BuObject = import("../../types/mcdev.d.js").BuObject; +export type CodeExtract = import("../../types/mcdev.d.js").CodeExtract; +export type CodeExtractItem = import("../../types/mcdev.d.js").CodeExtractItem; +export type MetadataTypeItem = import("../../types/mcdev.d.js").MetadataTypeItem; +export type MetadataTypeItemDiff = import("../../types/mcdev.d.js").MetadataTypeItemDiff; +export type MetadataTypeItemObj = import("../../types/mcdev.d.js").MetadataTypeItemObj; +export type MetadataTypeMap = import("../../types/mcdev.d.js").MetadataTypeMap; +export type MetadataTypeMapObj = import("../../types/mcdev.d.js").MetadataTypeMapObj; +export type SoapRequestParams = import("../../types/mcdev.d.js").SoapRequestParams; +export type TemplateMap = import("../../types/mcdev.d.js").TemplateMap; +export type DataFilterItem = import("../../types/mcdev.d.js").DataFilterItem; +export type DataExtensionFieldMap = import("../../types/mcdev.d.js").DataExtensionFieldMap; +export type DataExtensionFieldItem = import("../../types/mcdev.d.js").DataExtensionFieldItem; +export type DataFilterMap = import("../../types/mcdev.d.js").DataFilterMap; +export type MultiMetadataTypeMap = import("../../types/mcdev.d.js").MultiMetadataTypeMap; +export type FilterConditionSet = import("../../types/mcdev.d.js").FilterConditionSet; +export type FilterCondition = import("../../types/mcdev.d.js").FilterCondition; +/** + * @typedef {import('../../types/mcdev.d.js').BuObject} BuObject + * @typedef {import('../../types/mcdev.d.js').CodeExtract} CodeExtract + * @typedef {import('../../types/mcdev.d.js').CodeExtractItem} CodeExtractItem + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItem} MetadataTypeItem + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItemDiff} MetadataTypeItemDiff + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItemObj} MetadataTypeItemObj + * @typedef {import('../../types/mcdev.d.js').MetadataTypeMap} MetadataTypeMap + * @typedef {import('../../types/mcdev.d.js').MetadataTypeMapObj} MetadataTypeMapObj + * @typedef {import('../../types/mcdev.d.js').SoapRequestParams} SoapRequestParams + * @typedef {import('../../types/mcdev.d.js').TemplateMap} TemplateMap + * @typedef {import('../../types/mcdev.d.js').DataFilterItem} DataFilterItem + * @typedef {import('../../types/mcdev.d.js').DataExtensionFieldMap} DataExtensionFieldMap + * @typedef {import('../../types/mcdev.d.js').DataExtensionFieldItem} DataExtensionFieldItem + * @typedef {import('../../types/mcdev.d.js').DataFilterMap} DataFilterMap + * @typedef {import('../../types/mcdev.d.js').MultiMetadataTypeMap} MultiMetadataTypeMap + * @typedef {import('../../types/mcdev.d.js').FilterConditionSet} FilterConditionSet + * @typedef {import('../../types/mcdev.d.js').FilterCondition} FilterCondition + */ +/** + * DataFilter (FilterDefinition) MetadataType + * + * @augments MetadataType + */ +declare class DataFilter extends MetadataType { + static cache: {}; + static deIdKeyMap: any; + static hidden: boolean; + /** + * Retrieves all records and saves it to disk + * + * @param {string} retrieveDir Directory where retrieved metadata directory will be saved + * @param {string[]} [_] unused parameter + * @param {string[]} [__] unused parameter + * @param {string} [key] customer key of single item to retrieve + * @returns {Promise.<{metadata: DataFilterMap, type: string}>} Promise of items + */ + static retrieve(retrieveDir: string, _?: string[], __?: string[], key?: string): Promise<{ + metadata: DataFilterMap; + type: string; + }>; + /** + * helper for {@link DataFilter.retrieve} + * + * @param {boolean} [recached] indicates if this is a recursive call after cache refresh + * @returns {Promise.<number[]>} Array of folder IDs + */ + static _getFilterFolderIds(recached?: boolean): Promise<number[]>; + /** + * helper for {@link DataFilter._cacheMeasures} + * + * @returns {Promise.<number[]>} Array of folder IDs + */ + static _getMeasureFolderIds(): Promise<number[]>; + /** + * helper for {@link DataFilter.retrieve}. uses cached dataExtensions to resolve dataExtensionFields + * + * @param {DataFilterMap} metadataTypeMap - + * @param {'retrieve'|'deploy'} [mode] - + */ + static _cacheDeFields(metadataTypeMap: DataFilterMap, mode?: "retrieve" | "deploy"): Promise<void>; + /** + * helper for {@link DataFilter._cacheDeFields} + * + * @param {DataExtensionFieldMap} deFieldCache - + */ + static saveDataExtensionFieldCacheToMap(deFieldCache: DataExtensionFieldMap): void; + /** + * helper for {@link DataFilter.retrieve} + * + * @param {DataFilterMap} metadataTypeMap - + */ + static _cacheContactAttributes(metadataTypeMap: DataFilterMap): Promise<void>; + /** + * helper for {@link DataFilter.retrieve} + * + * @param {DataFilterMap} metadataTypeMap - + */ + static _cacheMeasures(metadataTypeMap: DataFilterMap): Promise<void>; + /** + * Retrieves all records for caching + * + * @returns {Promise.<{metadata: DataFilterMap, type: string}>} Promise of items + */ + static retrieveForCache(): Promise<{ + metadata: DataFilterMap; + type: string; + }>; + /** + * parses retrieved Metadata before saving + * + * @param {DataFilterItem} metadata a single record + * @returns {Promise.<DataFilterItem>} parsed metadata definition + */ + static postRetrieveTasks(metadata: DataFilterItem): Promise<DataFilterItem>; + /** + * helper for {@link postRetrieveTasks} + * + * @param {DataFilterItem} metadata - + * @param {'postRetrieve'|'preDeploy'} mode - + * @param {DataExtensionFieldItem[]} [fieldCache] - + * @param {FilterConditionSet} [filter] - + * @returns {void} + */ + static _resolveFields(metadata: DataFilterItem, mode: "postRetrieve" | "preDeploy", fieldCache?: DataExtensionFieldItem[], filter?: FilterConditionSet): void; + /** + * helper for {@link _resolveFields} + * + * @param {DataFilterItem} metadata - + * @param {FilterCondition} condition - + * @param {DataExtensionFieldItem[]} fieldCache - + * @returns {void} + */ + static _postRetrieve_resolveFieldIdsCondition(metadata: DataFilterItem, condition: FilterCondition, fieldCache: DataExtensionFieldItem[]): void; + /** + * helper for {@link _resolveFields} + * + * @param {DataFilterItem} metadata - + * @param {FilterCondition} condition - + * @param {DataExtensionFieldItem[]} fieldCache - + * @returns {void} + */ + static _preDeploy_resolveFieldNamesCondition(metadata: DataFilterItem, condition: FilterCondition, fieldCache: DataExtensionFieldItem[]): void; + /** + * helper for {@link postRetrieveTasks} + * + * @param {DataFilterItem} metadata - + * @param {object} [filter] - + * @returns {void} + */ + static _postRetrieve_resolveAttributeIds(metadata: DataFilterItem, filter?: object): void; + /** + * prepares a item for deployment + * + * @param {DataFilterItem} metadata a single record + * @returns {Promise.<DataFilterItem>} Promise of updated single item + */ + static preDeployTasks(metadata: DataFilterItem): Promise<DataFilterItem>; + /** + * Creates a single item + * + * @param {DataFilterItem} metadata a single item + * @returns {Promise.<DataFilterItem>} Promise + */ + static create(metadata: DataFilterItem): Promise<DataFilterItem>; + /** + * Updates a single item + * + * @param {DataFilterItem} metadata a single item + * @returns {Promise.<DataFilterItem>} Promise + */ + static update(metadata: DataFilterItem): Promise<DataFilterItem>; + /** + * helper to allow us to select single metadata entries via REST + * + * @private + * @param {string} key customer key + * @returns {Promise.<string>} objectId or empty string + */ + private static _getObjectIdForSingleRetrieve; +} +declare namespace DataFilter { + let definition: { + bodyIteratorField: string; + dependencies: string[]; + dependencyGraph: { + dataExtension: string[]; + }; + filter: {}; + hasExtended: boolean; + idField: string; + keyIsFixed: boolean; + keyField: string; + nameField: string; + folderType: string; + folderIdField: string; + createdDateField: string; + createdNameField: string; + lastmodDateField: string; + lastmodNameField: string; + restPagination: boolean; + restPageSize: number; + maxKeyLength: number; + type: string; + soapType: string; + typeDescription: string; + typeRetrieveByDefault: boolean; + typeCdpByDefault: boolean; + typeName: string; + fields: { + id: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + key: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + createdDate: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + createdBy: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + owner: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + createdByName: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + lastUpdated: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + lastUpdatedBy: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + lastUpdatedByName: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + name: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + categoryId: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + description: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + filterDefinitionXml: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + derivedFromType: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + derivedFromObjectId: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + derivedFromObjectTypeName: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + derivedFromObjectName: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + isSendable: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + r__source_dataExtension_key: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + c__filterDefinition: { + skipValidation: boolean; + }; + r__folder_Path: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + }; + }; +} +import MetadataType from './MetadataType.js'; +//# sourceMappingURL=DataFilter.d.ts.map \ No newline at end of file diff --git a/@types/lib/metadataTypes/DataFilter.d.ts.map b/@types/lib/metadataTypes/DataFilter.d.ts.map new file mode 100644 index 000000000..5e96a4339 --- /dev/null +++ b/@types/lib/metadataTypes/DataFilter.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"DataFilter.d.ts","sourceRoot":"","sources":["../../../lib/metadataTypes/DataFilter.js"],"names":[],"mappings":";uBAWa,OAAO,wBAAwB,EAAE,QAAQ;0BACzC,OAAO,wBAAwB,EAAE,WAAW;8BAC5C,OAAO,wBAAwB,EAAE,eAAe;+BAChD,OAAO,wBAAwB,EAAE,gBAAgB;mCACjD,OAAO,wBAAwB,EAAE,oBAAoB;kCACrD,OAAO,wBAAwB,EAAE,mBAAmB;8BACpD,OAAO,wBAAwB,EAAE,eAAe;iCAChD,OAAO,wBAAwB,EAAE,kBAAkB;gCACnD,OAAO,wBAAwB,EAAE,iBAAiB;0BAClD,OAAO,wBAAwB,EAAE,WAAW;6BAC5C,OAAO,wBAAwB,EAAE,cAAc;oCAC/C,OAAO,wBAAwB,EAAE,qBAAqB;qCACtD,OAAO,wBAAwB,EAAE,sBAAsB;4BACvD,OAAO,wBAAwB,EAAE,aAAa;mCAC9C,OAAO,wBAAwB,EAAE,oBAAoB;iCACrD,OAAO,wBAAwB,EAAE,kBAAkB;8BACnD,OAAO,wBAAwB,EAAE,eAAe;AAjB7D;;;;;;;;;;;;;;;;;;GAkBG;AAEH;;;;GAIG;AACH;IACI,iBAAkB;IAClB,uBAAkB;IAClB,uBAAsB;IACtB;;;;;;;;OAQG;IACH,6BANW,MAAM,MACN,MAAM,EAAE,OACR,MAAM,EAAE,QACR,MAAM,GACJ,OAAO,CAAE;QAAC,QAAQ,EAAE,aAAa,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAC,CAAC,CAyD7D;IACD;;;;;OAKG;IACH,sCAHW,OAAO,GACL,OAAO,CAAE,MAAM,EAAE,CAAC,CAoC9B;IACD;;;;OAIG;IACH,+BAFa,OAAO,CAAE,MAAM,EAAE,CAAC,CA4B9B;IAED;;;;;OAKG;IACH,uCAHW,aAAa,SACb,UAAU,GAAC,QAAQ,iBAiE7B;IACD;;;;OAIG;IACH,sDAFW,qBAAqB,QAwB/B;IACD;;;;OAIG;IACH,gDAFW,aAAa,iBAkBvB;IACD;;;;OAIG;IACH,uCAFW,aAAa,iBA6BvB;IAED;;;;OAIG;IACH,2BAFa,OAAO,CAAE;QAAC,QAAQ,EAAE,aAAa,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAC,CAAC,CAI7D;IAED;;;;;OAKG;IACH,mCAHW,cAAc,GACZ,OAAO,CAAE,cAAc,CAAC,CA4FpC;IAED;;;;;;;;OAQG;IACH,gCANW,cAAc,QACd,cAAc,GAAC,WAAW,eAC1B,sBAAsB,EAAE,WACxB,kBAAkB,GAChB,IAAI,CAmChB;IACD;;;;;;;OAOG;IACH,wDALW,cAAc,aACd,eAAe,cACf,sBAAsB,EAAE,GACtB,IAAI,CAgBhB;IACD;;;;;;;OAOG;IACH,uDALW,cAAc,aACd,eAAe,cACf,sBAAsB,EAAE,GACtB,IAAI,CAoBhB;IACD;;;;;;OAMG;IACH,mDAJW,cAAc,WACd,MAAM,GACJ,IAAI,CAiChB;IAED;;;;;OAKG;IACH,gCAHW,cAAc,GACZ,OAAO,CAAE,cAAc,CAAC,CAuDpC;IAeD;;;;;OAKG;IACH,wBAHW,cAAc,GACZ,OAAO,CAAE,cAAc,CAAC,CAIpC;IACD;;;;;OAKG;IACH,wBAHW,cAAc,GACZ,OAAO,CAAE,cAAc,CAAC,CAOpC;IAED;;;;;;OAMG;IACH,6CAUC;CAiBJ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;yBA5rBwB,mBAAmB"} \ No newline at end of file diff --git a/@types/lib/metadataTypes/DataFilterHidden.d.ts b/@types/lib/metadataTypes/DataFilterHidden.d.ts new file mode 100644 index 000000000..312698353 --- /dev/null +++ b/@types/lib/metadataTypes/DataFilterHidden.d.ts @@ -0,0 +1,165 @@ +export default DataFilterHidden; +/** + * DataFilterHidden (FilterDefinitionHidden) MetadataType + * + * @augments DataFilter + */ +declare class DataFilterHidden extends DataFilter { +} +declare namespace DataFilterHidden { + let definition: { + bodyIteratorField: string; + dependencies: string[]; + dependencyGraph: { + dataExtension: string[]; + }; + filter: {}; + hasExtended: boolean; + idField: string; + keyIsFixed: boolean; + keyField: string; + nameField: string; + folderType: string; + folderIdField: string; + createdDateField: string; + createdNameField: string; + lastmodDateField: string; + lastmodNameField: string; + restPagination: boolean; + restPageSize: number; + maxKeyLength: number; + type: string; + soapType: string; + typeDescription: string; + typeRetrieveByDefault: boolean; + typeCdpByDefault: boolean; + typeName: string; + fields: { + id: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + key: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + createdDate: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + createdBy: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + owner: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + createdByName: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + lastUpdated: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + lastUpdatedBy: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + lastUpdatedByName: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + name: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + categoryId: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + description: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + filterDefinitionXml: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + derivedFromType: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + derivedFromObjectId: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + derivedFromObjectTypeName: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + derivedFromObjectName: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + isSendable: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + r__source_dataExtension_key: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + c__filterDefinition: { + skipValidation: boolean; + }; + r__folder_Path: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + }; + }; +} +import DataFilter from './DataFilter.js'; +//# sourceMappingURL=DataFilterHidden.d.ts.map \ No newline at end of file diff --git a/@types/lib/metadataTypes/DataFilterHidden.d.ts.map b/@types/lib/metadataTypes/DataFilterHidden.d.ts.map new file mode 100644 index 000000000..181dc05d3 --- /dev/null +++ b/@types/lib/metadataTypes/DataFilterHidden.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"DataFilterHidden.d.ts","sourceRoot":"","sources":["../../../lib/metadataTypes/DataFilterHidden.js"],"names":[],"mappings":";AAKA;;;;GAIG;AACH;CAEC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;uBATsB,iBAAiB"} \ No newline at end of file diff --git a/@types/lib/metadataTypes/DeliveryProfile.d.ts b/@types/lib/metadataTypes/DeliveryProfile.d.ts new file mode 100644 index 000000000..9770a3f6b --- /dev/null +++ b/@types/lib/metadataTypes/DeliveryProfile.d.ts @@ -0,0 +1,104 @@ +export default DeliveryProfile; +export type BuObject = import("../../types/mcdev.d.js").BuObject; +export type CodeExtract = import("../../types/mcdev.d.js").CodeExtract; +export type CodeExtractItem = import("../../types/mcdev.d.js").CodeExtractItem; +export type MetadataTypeItem = import("../../types/mcdev.d.js").MetadataTypeItem; +export type MetadataTypeItemDiff = import("../../types/mcdev.d.js").MetadataTypeItemDiff; +export type MetadataTypeItemObj = import("../../types/mcdev.d.js").MetadataTypeItemObj; +export type MetadataTypeMap = import("../../types/mcdev.d.js").MetadataTypeMap; +export type MetadataTypeMapObj = import("../../types/mcdev.d.js").MetadataTypeMapObj; +export type SoapRequestParams = import("../../types/mcdev.d.js").SoapRequestParams; +export type TemplateMap = import("../../types/mcdev.d.js").TemplateMap; +/** + * @typedef {import('../../types/mcdev.d.js').BuObject} BuObject + * @typedef {import('../../types/mcdev.d.js').CodeExtract} CodeExtract + * @typedef {import('../../types/mcdev.d.js').CodeExtractItem} CodeExtractItem + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItem} MetadataTypeItem + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItemDiff} MetadataTypeItemDiff + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItemObj} MetadataTypeItemObj + * @typedef {import('../../types/mcdev.d.js').MetadataTypeMap} MetadataTypeMap + * @typedef {import('../../types/mcdev.d.js').MetadataTypeMapObj} MetadataTypeMapObj + * @typedef {import('../../types/mcdev.d.js').SoapRequestParams} SoapRequestParams + * @typedef {import('../../types/mcdev.d.js').TemplateMap} TemplateMap + */ +/** + * DeliveryProfile MetadataType + * + * @augments MetadataType + */ +declare class DeliveryProfile extends MetadataType { + /** + * Retrieves SOAP based metadata of metadata type into local filesystem. executes callback with retrieved metadata + * + * @param {string} retrieveDir Directory where retrieved metadata directory will be saved + * @param {void | string[]} [_] not used + * @param {void | string[]} [__] unused parameter + * @param {string} [key] customer key of single item to retrieve + * @returns {Promise.<MetadataTypeMapObj>} Promise of metadata + */ + static retrieve(retrieveDir: string, _?: void | string[], __?: void | string[], key?: string): Promise<MetadataTypeMapObj>; +} +declare namespace DeliveryProfile { + let definition: { + bodyIteratorField: string; + dependencies: any[]; + dependencyGraph: any; + filter: {}; + hasExtended: boolean; + idField: string; + keyField: string; + keyIsFixed: boolean; + maxKeyLength: number; + nameField: string; + createdDateField: string; + createdNameField: any; + lastmodDateField: string; + lastmodNameField: any; + restPagination: boolean; + type: string; + typeDescription: string; + typeRetrieveByDefault: boolean; + typeCdpByDefault: boolean; + typeName: string; + fields: { + id: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + key: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + name: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + description: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + createdDate: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + lastUpdated: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + }; + }; +} +import MetadataType from './MetadataType.js'; +//# sourceMappingURL=DeliveryProfile.d.ts.map \ No newline at end of file diff --git a/@types/lib/metadataTypes/DeliveryProfile.d.ts.map b/@types/lib/metadataTypes/DeliveryProfile.d.ts.map new file mode 100644 index 000000000..c12da3c9d --- /dev/null +++ b/@types/lib/metadataTypes/DeliveryProfile.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"DeliveryProfile.d.ts","sourceRoot":"","sources":["../../../lib/metadataTypes/DeliveryProfile.js"],"names":[],"mappings":";uBAKa,OAAO,wBAAwB,EAAE,QAAQ;0BACzC,OAAO,wBAAwB,EAAE,WAAW;8BAC5C,OAAO,wBAAwB,EAAE,eAAe;+BAChD,OAAO,wBAAwB,EAAE,gBAAgB;mCACjD,OAAO,wBAAwB,EAAE,oBAAoB;kCACrD,OAAO,wBAAwB,EAAE,mBAAmB;8BACpD,OAAO,wBAAwB,EAAE,eAAe;iCAChD,OAAO,wBAAwB,EAAE,kBAAkB;gCACnD,OAAO,wBAAwB,EAAE,iBAAiB;0BAClD,OAAO,wBAAwB,EAAE,WAAW;AAVzD;;;;;;;;;;;GAWG;AAEH;;;;GAIG;AACH;IACI;;;;;;;;OAQG;IACH,6BANW,MAAM,MACN,IAAI,GAAG,MAAM,EAAE,OACf,IAAI,GAAG,MAAM,EAAE,QACf,MAAM,GACJ,OAAO,CAAE,kBAAkB,CAAC,CASxC;CACJ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;yBAtCwB,mBAAmB"} \ No newline at end of file diff --git a/@types/lib/metadataTypes/Discovery.d.ts b/@types/lib/metadataTypes/Discovery.d.ts new file mode 100644 index 000000000..56b3108be --- /dev/null +++ b/@types/lib/metadataTypes/Discovery.d.ts @@ -0,0 +1,191 @@ +export default Discovery; +export type BuObject = import("../../types/mcdev.d.js").BuObject; +export type CodeExtract = import("../../types/mcdev.d.js").CodeExtract; +export type CodeExtractItem = import("../../types/mcdev.d.js").CodeExtractItem; +export type MetadataTypeItem = import("../../types/mcdev.d.js").MetadataTypeItem; +export type MetadataTypeItemDiff = import("../../types/mcdev.d.js").MetadataTypeItemDiff; +export type MetadataTypeItemObj = import("../../types/mcdev.d.js").MetadataTypeItemObj; +export type MetadataTypeMap = import("../../types/mcdev.d.js").MetadataTypeMap; +export type MetadataTypeMapObj = import("../../types/mcdev.d.js").MetadataTypeMapObj; +export type SoapRequestParams = import("../../types/mcdev.d.js").SoapRequestParams; +export type TemplateMap = import("../../types/mcdev.d.js").TemplateMap; +/** + * @typedef {import('../../types/mcdev.d.js').BuObject} BuObject + * @typedef {import('../../types/mcdev.d.js').CodeExtract} CodeExtract + * @typedef {import('../../types/mcdev.d.js').CodeExtractItem} CodeExtractItem + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItem} MetadataTypeItem + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItemDiff} MetadataTypeItemDiff + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItemObj} MetadataTypeItemObj + * @typedef {import('../../types/mcdev.d.js').MetadataTypeMap} MetadataTypeMap + * @typedef {import('../../types/mcdev.d.js').MetadataTypeMapObj} MetadataTypeMapObj + * @typedef {import('../../types/mcdev.d.js').SoapRequestParams} SoapRequestParams + * @typedef {import('../../types/mcdev.d.js').TemplateMap} TemplateMap + */ +/** + * ImportFile MetadataType + * + * @augments MetadataType + */ +declare class Discovery extends MetadataType { + /** + * Retrieves API endpoint + * documentation: https://developer.salesforce.com/docs/atlas.en-us.noversion.mc-apis.meta/mc-apis/routes.htm + * + * @param {string} retrieveDir Directory where retrieved metadata directory will be saved + * @param {void | string[]} [_] not used + * @param {void | string[]} [__] unused parameter + * @param {string} [key] customer key of single item to retrieve + * @returns {Promise.<MetadataTypeMapObj>} Promise + */ + static retrieve(retrieveDir: string, _?: void | string[], __?: void | string[], key?: string): Promise<MetadataTypeMapObj>; +} +declare namespace Discovery { + let definition: { + bodyIteratorField: any; + dependencies: any[]; + dependencyGraph: any; + endPointMapping: { + Address: string; + Asset: string; + Automation: string; + Contacts: string; + Data: string; + Device: string; + Email: string; + Guide: string; + Hub: string; + Interaction: string; + 'Interaction-Experimental': string; + Legacy: string; + Messaging: string; + 'Messaging-Experimental': string; + OTT: string; + 'OTT-Experimental': string; + Platform: string; + 'Platform-Experimental': string; + Provisioning: string; + Push: string; + SMS: string; + }; + hasExtended: boolean; + idField: string; + keyIsFixed: boolean; + keyField: string; + nameField: string; + restPagination: boolean; + type: string; + typeDescription: string; + typeRetrieveByDefault: boolean; + typeCdpByDefault: boolean; + typeName: string; + fields: { + basePath: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + baseUrl: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + description: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + discoveryVersion: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + documentationLink: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + id: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + key: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + kind: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + methods: { + skipValidation: boolean; + }; + metadata: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'metadata.supportsResponseEncoding': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + name: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + protocol: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + resources: { + skipValidation: boolean; + }; + rootUrl: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + schemas: { + skipValidation: boolean; + }; + servicePath: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + title: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + version: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + }; + }; +} +import MetadataType from './MetadataType.js'; +//# sourceMappingURL=Discovery.d.ts.map \ No newline at end of file diff --git a/@types/lib/metadataTypes/Discovery.d.ts.map b/@types/lib/metadataTypes/Discovery.d.ts.map new file mode 100644 index 000000000..30cf9ad7b --- /dev/null +++ b/@types/lib/metadataTypes/Discovery.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"Discovery.d.ts","sourceRoot":"","sources":["../../../lib/metadataTypes/Discovery.js"],"names":[],"mappings":";uBAMa,OAAO,wBAAwB,EAAE,QAAQ;0BACzC,OAAO,wBAAwB,EAAE,WAAW;8BAC5C,OAAO,wBAAwB,EAAE,eAAe;+BAChD,OAAO,wBAAwB,EAAE,gBAAgB;mCACjD,OAAO,wBAAwB,EAAE,oBAAoB;kCACrD,OAAO,wBAAwB,EAAE,mBAAmB;8BACpD,OAAO,wBAAwB,EAAE,eAAe;iCAChD,OAAO,wBAAwB,EAAE,kBAAkB;gCACnD,OAAO,wBAAwB,EAAE,iBAAiB;0BAClD,OAAO,wBAAwB,EAAE,WAAW;AAVzD;;;;;;;;;;;GAWG;AAEH;;;;GAIG;AACH;IACI;;;;;;;;;OASG;IACH,6BANW,MAAM,MACN,IAAI,GAAG,MAAM,EAAE,OACf,IAAI,GAAG,MAAM,EAAE,QACf,MAAM,GACJ,OAAO,CAAE,kBAAkB,CAAC,CA0BxC;CACJ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;yBAzDwB,mBAAmB"} \ No newline at end of file diff --git a/@types/lib/metadataTypes/DomainVerification.d.ts b/@types/lib/metadataTypes/DomainVerification.d.ts new file mode 100644 index 000000000..31d9ebc0b --- /dev/null +++ b/@types/lib/metadataTypes/DomainVerification.d.ts @@ -0,0 +1,189 @@ +export default DomainVerification; +export type BuObject = import("../../types/mcdev.d.js").BuObject; +export type CodeExtract = import("../../types/mcdev.d.js").CodeExtract; +export type CodeExtractItem = import("../../types/mcdev.d.js").CodeExtractItem; +export type MetadataTypeItem = import("../../types/mcdev.d.js").MetadataTypeItem; +export type MetadataTypeItemDiff = import("../../types/mcdev.d.js").MetadataTypeItemDiff; +export type MetadataTypeItemObj = import("../../types/mcdev.d.js").MetadataTypeItemObj; +export type MetadataTypeMap = import("../../types/mcdev.d.js").MetadataTypeMap; +export type MetadataTypeMapObj = import("../../types/mcdev.d.js").MetadataTypeMapObj; +export type SoapRequestParams = import("../../types/mcdev.d.js").SoapRequestParams; +export type TemplateMap = import("../../types/mcdev.d.js").TemplateMap; +export type DomainVerificationItem = import("../../types/mcdev.d.js").DomainVerificationItem; +/** + * @typedef {import('../../types/mcdev.d.js').BuObject} BuObject + * @typedef {import('../../types/mcdev.d.js').CodeExtract} CodeExtract + * @typedef {import('../../types/mcdev.d.js').CodeExtractItem} CodeExtractItem + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItem} MetadataTypeItem + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItemDiff} MetadataTypeItemDiff + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItemObj} MetadataTypeItemObj + * @typedef {import('../../types/mcdev.d.js').MetadataTypeMap} MetadataTypeMap + * @typedef {import('../../types/mcdev.d.js').MetadataTypeMapObj} MetadataTypeMapObj + * @typedef {import('../../types/mcdev.d.js').SoapRequestParams} SoapRequestParams + * @typedef {import('../../types/mcdev.d.js').TemplateMap} TemplateMap + * @typedef {import('../../types/mcdev.d.js').DomainVerificationItem} DomainVerificationItem + */ +/** + * DomainVerification MetadataType + * + * @augments MetadataType + */ +declare class DomainVerification extends MetadataType { + /** + * Retrieves Metadata ofDomainVerification. + * Endpoint /automation/v1/dataextracts/ returns all items + * + * @param {string} retrieveDir Directory where retrieved metadata directory will be saved + * @param {void | string[]} [_] unused parameter + * @param {void | string[]} [__] unused parameter + * @param {string} [key] customer key of single item to retrieve + * @returns {Promise.<MetadataTypeMapObj>} Promise of metadata + */ + static retrieve(retrieveDir: string, _?: void | string[], __?: void | string[], key?: string): Promise<MetadataTypeMapObj>; + /** + * Retrieves Metadata of DomainVerification for caching + * + * @returns {Promise.<MetadataTypeMapObj>} Promise of metadata + */ + static retrieveForCache(): Promise<MetadataTypeMapObj>; + /** + * Creates a single item + * + * @param {DomainVerificationItem} metadataItem a single item + * @returns {Promise} Promise + */ + static create(metadataItem: DomainVerificationItem): Promise<any>; + /** + * Creates a multiple metadata entries via REST + * + * @param {MetadataTypeItem} metadataEntry a single metadata Entry + * @param {string} uri rest endpoint for POST + * @returns {Promise.<object> | null} Promise of API response or null in case of an error + */ + static createRESTBulk(metadataEntry: MetadataTypeItem, uri: string): Promise<object> | null; + /** + * helper for {@link MetadataType.createREST} + * + * @param {DomainVerificationItem} metadataEntry a single metadata Entry + * @param {object} apiResponse varies depending on the API call + * @returns {Promise.<DomainVerificationItem>} apiResponse + */ + static postCreateTasks(metadataEntry: DomainVerificationItem, apiResponse: object): Promise<DomainVerificationItem>; + /** + * helper for {@link update} + * + * @param {DomainVerificationItem} metadataEntry a single metadata Entry + * @param {object} apiResponse varies depending on the API call + * @returns {Promise.<DomainVerificationItem>} apiResponse, potentially modified + */ + static postUpdateTasks(metadataEntry: DomainVerificationItem, apiResponse: object): Promise<DomainVerificationItem>; + /** + * Updates a single item; replaces super.updateREST because we need to send metadataItem as an array for some reason and also get an array back + * + * @param {DomainVerificationItem} metadataItem a single item + * @returns {Promise.<DomainVerificationItem>} Promise + */ + static update(metadataItem: DomainVerificationItem): Promise<DomainVerificationItem>; + /** + * manages post retrieve steps + * + * @param {DomainVerificationItem} metadataItem a single item + * @returns {DomainVerificationItem|void} metadata + */ + static postRetrieveTasks(metadataItem: DomainVerificationItem): DomainVerificationItem | void; + /** + * Gets executed after deployment of metadata type + * + * @param {MetadataTypeMap} upsertResults metadata mapped by their keyField as returned by update/create + * @returns {Promise.<void>} - + */ + static postDeployTasks(upsertResults: MetadataTypeMap): Promise<void>; + /** + * prepares a single item for deployment + * + * @param {DomainVerificationItem} metadata a single item + * @returns {Promise.<DomainVerificationItem>} Promise + */ + static preDeployTasks(metadata: DomainVerificationItem): Promise<DomainVerificationItem>; + /** + * Gets executed before deleting a list of keys for the current type + * + * @returns {Promise.<void>} - + */ + static preDeleteTasks(): Promise<void>; +} +declare namespace DomainVerification { + let definition: { + bodyIteratorField: string; + dependencies: any[]; + dependencyGraph: any; + hasExtended: boolean; + idField: string; + keyIsFixed: boolean; + keyField: string; + createdDateField: any; + createdNameField: any; + lastmodDateField: any; + lastmodNameField: any; + nameField: string; + restPagination: boolean; + maxKeyLength: number; + type: string; + typeDescription: string; + typeRetrieveByDefault: boolean; + typeCdpByDefault: boolean; + typeName: string; + fields: { + domain: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + emailAddress: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + enterpriseId: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + memberId: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + domainType: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + isSendable: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + status: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + emailSendTime: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + }; + }; +} +import MetadataType from './MetadataType.js'; +//# sourceMappingURL=DomainVerification.d.ts.map \ No newline at end of file diff --git a/@types/lib/metadataTypes/DomainVerification.d.ts.map b/@types/lib/metadataTypes/DomainVerification.d.ts.map new file mode 100644 index 000000000..c862ea76a --- /dev/null +++ b/@types/lib/metadataTypes/DomainVerification.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"DomainVerification.d.ts","sourceRoot":"","sources":["../../../lib/metadataTypes/DomainVerification.js"],"names":[],"mappings":";uBAOa,OAAO,wBAAwB,EAAE,QAAQ;0BACzC,OAAO,wBAAwB,EAAE,WAAW;8BAC5C,OAAO,wBAAwB,EAAE,eAAe;+BAChD,OAAO,wBAAwB,EAAE,gBAAgB;mCACjD,OAAO,wBAAwB,EAAE,oBAAoB;kCACrD,OAAO,wBAAwB,EAAE,mBAAmB;8BACpD,OAAO,wBAAwB,EAAE,eAAe;iCAChD,OAAO,wBAAwB,EAAE,kBAAkB;gCACnD,OAAO,wBAAwB,EAAE,iBAAiB;0BAClD,OAAO,wBAAwB,EAAE,WAAW;qCAC5C,OAAO,wBAAwB,EAAE,sBAAsB;AAXpE;;;;;;;;;;;;GAYG;AAEH;;;;GAIG;AACH;IACI;;;;;;;;;OASG;IACH,6BANW,MAAM,MACN,IAAI,GAAG,MAAM,EAAE,OACf,IAAI,GAAG,MAAM,EAAE,QACf,MAAM,GACJ,OAAO,CAAE,kBAAkB,CAAC,CAIxC;IAED;;;;OAIG;IACH,2BAFa,OAAO,CAAE,kBAAkB,CAAC,CAIxC;IAED;;;;;OAKG;IACH,4BAHW,sBAAsB,gBAShC;IAED;;;;;;OAMG;IACH,qCAJW,gBAAgB,OAChB,MAAM,GACJ,OAAO,CAAE,MAAM,CAAC,GAAG,IAAI,CA0CnC;IAED;;;;;;OAMG;IACH,sCAJW,sBAAsB,eACtB,MAAM,GACJ,OAAO,CAAE,sBAAsB,CAAC,CAQ5C;IAED;;;;;;OAMG;IACH,sCAJW,sBAAsB,eACtB,MAAM,GACJ,OAAO,CAAE,sBAAsB,CAAC,CAS5C;IAED;;;;;OAKG;IACH,4BAHW,sBAAsB,GACpB,OAAO,CAAE,sBAAsB,CAAC,CAwB5C;IACD;;;;;OAKG;IACH,uCAHW,sBAAsB,GACpB,sBAAsB,GAAC,IAAI,CAmBvC;IAED;;;;;OAKG;IACH,sCAHW,eAAe,GACb,OAAO,CAAE,IAAI,CAAC,CAiB1B;IAED;;;;;OAKG;IACH,gCAHW,sBAAsB,GACpB,OAAO,CAAE,sBAAsB,CAAC,CAY5C;IAED;;;;OAIG;IACH,yBAFa,OAAO,CAAE,IAAI,CAAC,CAY1B;CA8CJ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;yBAzSwB,mBAAmB"} \ No newline at end of file diff --git a/@types/lib/metadataTypes/Email.d.ts b/@types/lib/metadataTypes/Email.d.ts new file mode 100644 index 000000000..24ef9d01b --- /dev/null +++ b/@types/lib/metadataTypes/Email.d.ts @@ -0,0 +1,365 @@ +export default Email; +export type BuObject = import("../../types/mcdev.d.js").BuObject; +export type CodeExtract = import("../../types/mcdev.d.js").CodeExtract; +export type CodeExtractItem = import("../../types/mcdev.d.js").CodeExtractItem; +export type MetadataTypeItem = import("../../types/mcdev.d.js").MetadataTypeItem; +export type MetadataTypeItemDiff = import("../../types/mcdev.d.js").MetadataTypeItemDiff; +export type MetadataTypeItemObj = import("../../types/mcdev.d.js").MetadataTypeItemObj; +export type MetadataTypeMap = import("../../types/mcdev.d.js").MetadataTypeMap; +export type MetadataTypeMapObj = import("../../types/mcdev.d.js").MetadataTypeMapObj; +export type SoapRequestParams = import("../../types/mcdev.d.js").SoapRequestParams; +export type TemplateMap = import("../../types/mcdev.d.js").TemplateMap; +/** + * @typedef {import('../../types/mcdev.d.js').BuObject} BuObject + * @typedef {import('../../types/mcdev.d.js').CodeExtract} CodeExtract + * @typedef {import('../../types/mcdev.d.js').CodeExtractItem} CodeExtractItem + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItem} MetadataTypeItem + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItemDiff} MetadataTypeItemDiff + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItemObj} MetadataTypeItemObj + * @typedef {import('../../types/mcdev.d.js').MetadataTypeMap} MetadataTypeMap + * @typedef {import('../../types/mcdev.d.js').MetadataTypeMapObj} MetadataTypeMapObj + * @typedef {import('../../types/mcdev.d.js').SoapRequestParams} SoapRequestParams + * @typedef {import('../../types/mcdev.d.js').TemplateMap} TemplateMap + */ +/** + * Email MetadataType + * + * @augments MetadataType + */ +declare class Email extends MetadataType { + /** + * Retrieves SOAP based metadata of metadata type into local filesystem. executes callback with retrieved metadata + * + * @param {string} retrieveDir Directory where retrieved metadata directory will be saved + * @param {void | string[]} [_] unused parameter + * @param {void | string[]} [__] unused parameter + * @param {string} [key] customer key of single item to retrieve + * @returns {Promise.<MetadataTypeMapObj>} Promise of metadata + */ + static retrieve(retrieveDir: string, _?: void | string[], __?: void | string[], key?: string): Promise<MetadataTypeMapObj>; + /** + * manages post retrieve steps + * + * @param {MetadataTypeItem} metadata a single query + * @returns {MetadataTypeItem} Array with one metadata object and one query string + */ + static postRetrieveTasks(metadata: MetadataTypeItem): MetadataTypeItem; +} +declare namespace Email { + let definition: { + bodyIteratorField: string; + dependencies: string[]; + dependencyGraph: any; + hasExtended: boolean; + idField: string; + keepId: boolean; + keyIsFixed: boolean; + keyField: string; + nameField: string; + folderIdField: string; + restPagination: any; + type: string; + typeDescription: string; + typeRetrieveByDefault: boolean; + typeCdpByDefault: boolean; + typeName: string; + fields: { + CategoryID: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + CharacterSet: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + 'Client.ID': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + 'Client.PartnerClientKey': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + ClonedFromID: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + ContentAreas: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + 'ContentAreas.CategoryID': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + 'ContentAreas.Content': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + 'ContentAreas.CustomerKey': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + 'ContentAreas.ID': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + 'ContentAreas.IsBlank': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + 'ContentAreas.IsDynamicContent': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + 'ContentAreas.IsLocked': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + 'ContentAreas.IsSurvey': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + 'ContentAreas.Key': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + 'ContentAreas.Name': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + 'ContentAreas.ObjectID': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + 'ContentAreas.PartnerKey': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + 'ContentAreas[].CategoryID': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + 'ContentAreas[].Content': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + 'ContentAreas[].CustomerKey': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + 'ContentAreas[].ID': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + 'ContentAreas[].IsBlank': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + 'ContentAreas[].IsDynamicContent': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + 'ContentAreas[].IsLocked': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + 'ContentAreas[].IsSurvey': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + 'ContentAreas[].Key': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + 'ContentAreas[].Name': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + 'ContentAreas[].ObjectID': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + 'ContentAreas[].PartnerKey': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + ContentCheckStatus: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + CreatedDate: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + CustomerKey: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + EmailType: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + Folder: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + HasDynamicSubjectLine: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + HTMLBody: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + ID: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + IsActive: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + IsHTMLPaste: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + ModifiedDate: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + Name: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + ObjectID: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + PartnerKey: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + PreHeader: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + Status: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + Subject: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + SyncTextWithHTML: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + TextBody: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + }; + }; +} +import MetadataType from './MetadataType.js'; +//# sourceMappingURL=Email.d.ts.map \ No newline at end of file diff --git a/@types/lib/metadataTypes/Email.d.ts.map b/@types/lib/metadataTypes/Email.d.ts.map new file mode 100644 index 000000000..137d7c2c7 --- /dev/null +++ b/@types/lib/metadataTypes/Email.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"Email.d.ts","sourceRoot":"","sources":["../../../lib/metadataTypes/Email.js"],"names":[],"mappings":";uBAMa,OAAO,wBAAwB,EAAE,QAAQ;0BACzC,OAAO,wBAAwB,EAAE,WAAW;8BAC5C,OAAO,wBAAwB,EAAE,eAAe;+BAChD,OAAO,wBAAwB,EAAE,gBAAgB;mCACjD,OAAO,wBAAwB,EAAE,oBAAoB;kCACrD,OAAO,wBAAwB,EAAE,mBAAmB;8BACpD,OAAO,wBAAwB,EAAE,eAAe;iCAChD,OAAO,wBAAwB,EAAE,kBAAkB;gCACnD,OAAO,wBAAwB,EAAE,iBAAiB;0BAClD,OAAO,wBAAwB,EAAE,WAAW;AAVzD;;;;;;;;;;;GAWG;AAEH;;;;GAIG;AACH;IACI;;;;;;;;OAQG;IACH,6BANW,MAAM,MACN,IAAI,GAAG,MAAM,EAAE,OACf,IAAI,GAAG,MAAM,EAAE,QACf,MAAM,GACJ,OAAO,CAAE,kBAAkB,CAAC,CAgBxC;IAqBD;;;;;OAKG;IACH,mCAHW,gBAAgB,GACd,gBAAgB,CAkB5B;CACJ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;yBAzFwB,mBAAmB"} \ No newline at end of file diff --git a/@types/lib/metadataTypes/EmailSend.d.ts b/@types/lib/metadataTypes/EmailSend.d.ts new file mode 100644 index 000000000..c1ea0c3d8 --- /dev/null +++ b/@types/lib/metadataTypes/EmailSend.d.ts @@ -0,0 +1,661 @@ +export default EmailSend; +export type BuObject = import("../../types/mcdev.d.js").BuObject; +export type CodeExtract = import("../../types/mcdev.d.js").CodeExtract; +export type CodeExtractItem = import("../../types/mcdev.d.js").CodeExtractItem; +export type MetadataTypeItem = import("../../types/mcdev.d.js").MetadataTypeItem; +export type MetadataTypeItemDiff = import("../../types/mcdev.d.js").MetadataTypeItemDiff; +export type MetadataTypeItemObj = import("../../types/mcdev.d.js").MetadataTypeItemObj; +export type MetadataTypeMap = import("../../types/mcdev.d.js").MetadataTypeMap; +export type MetadataTypeMapObj = import("../../types/mcdev.d.js").MetadataTypeMapObj; +export type SoapRequestParams = import("../../types/mcdev.d.js").SoapRequestParams; +export type TemplateMap = import("../../types/mcdev.d.js").TemplateMap; +/** + * @typedef {import('../../types/mcdev.d.js').BuObject} BuObject + * @typedef {import('../../types/mcdev.d.js').CodeExtract} CodeExtract + * @typedef {import('../../types/mcdev.d.js').CodeExtractItem} CodeExtractItem + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItem} MetadataTypeItem + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItemDiff} MetadataTypeItemDiff + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItemObj} MetadataTypeItemObj + * @typedef {import('../../types/mcdev.d.js').MetadataTypeMap} MetadataTypeMap + * @typedef {import('../../types/mcdev.d.js').MetadataTypeMapObj} MetadataTypeMapObj + * @typedef {import('../../types/mcdev.d.js').SoapRequestParams} SoapRequestParams + * @typedef {import('../../types/mcdev.d.js').TemplateMap} TemplateMap + */ +/** + * MessageSendActivity MetadataType + * + * @augments MetadataType + */ +declare class EmailSend extends MetadataType { + /** + * Retrieves SOAP based metadata of metadata type into local filesystem. executes callback with retrieved metadata + * + * @param {string} [retrieveDir] Directory where retrieved metadata directory will be saved + * @param {void | string[]} [_] unused parameter + * @param {void | string[]} [__] unused parameter + * @param {string} [key] customer key of single item to retrieve + * @returns {Promise.<MetadataTypeMapObj>} Promise of metadata + */ + static retrieve(retrieveDir?: string, _?: void | string[], __?: void | string[], key?: string): Promise<MetadataTypeMapObj>; + /** + * Updates a single item + * + * @param {MetadataTypeItem} metadataItem a single item + * @returns {Promise} Promise + */ + static update(metadataItem: MetadataTypeItem): Promise<any>; + /** + * Creates a single item + * + * @param {MetadataTypeItem} metadataItem a single item + * @returns {Promise} Promise + */ + static create(metadataItem: MetadataTypeItem): Promise<any>; + /** + * prepares a single item for deployment + * + * @param {MetadataTypeItem} metadata a single script activity definition + * @returns {Promise.<MetadataTypeItem>} Promise + */ + static preDeployTasks(metadata: MetadataTypeItem): Promise<MetadataTypeItem>; + /** + * manages post retrieve steps + * + * @param {MetadataTypeItem} metadata a single query + * @returns {MetadataTypeItem} Array with one metadata object and one query string + */ + static postRetrieveTasks(metadata: MetadataTypeItem): MetadataTypeItem; +} +declare namespace EmailSend { + let definition: { + bodyIteratorField: string; + dependencies: string[]; + dependencyGraph: { + asset: string[]; + dataExtension: string[]; + deliveryProfile: string[]; + list: string[]; + sendClassification: string[]; + senderProfile: string[]; + }; + folderType: string; + hasExtended: boolean; + idField: string; + keepId: boolean; + keyIsFixed: boolean; + keyField: string; + nameField: string; + folderIdField: string; + createdDateField: string; + createdNameField: any; + lastmodDateField: string; + lastmodNameField: any; + restPagination: any; + maxKeyLength: number; + type: string; + soapType: string; + typeDescription: string; + typeRetrieveByDefault: boolean; + typeCdpByDefault: boolean; + typeName: string; + fields: { + Additional: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + AutoBccEmail: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + BccEmail: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + CategoryID: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + CCEmail: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + 'Client.ID': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + CorrelationID: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + CreatedDate: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + CustomerKey: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + DeduplicateByEmail: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + 'DeliveryProfile.CustomerKey': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + 'DeliveryProfile.DomainType': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + 'DeliveryProfile.FooterContentArea.ID': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + 'DeliveryProfile.FooterSalutationSource': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + 'DeliveryProfile.HeaderContentArea.ID': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + 'DeliveryProfile.HeaderSalutationSource': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + 'DeliveryProfile.ObjectID': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + 'DeliveryProfile.PartnerKey': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + 'DeliveryProfile.PrivateDomain': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + 'DeliveryProfile.PrivateIP': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + 'DeliveryProfile.SourceAddressType': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + DeliveryScheduledTime: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + Description: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + DomainType: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + DynamicEmailSubject: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + 'Email.ID': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + 'Email.ObjectID': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + 'Email.PartnerKey': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + 'Email.Name': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + 'Email.Subject': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + 'Email.Status': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + EmailSubject: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + ExclusionFilter: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + FooterContentArea: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + FooterSalutationSource: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + FromAddress: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + FromName: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + HeaderContentArea: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + HeaderSalutationSource: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + ID: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + IntegratedTracking: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + InteractionObjectID: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + IsMultipart: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + IsPlatformObject: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + IsSeedListSend: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + IsSendLogging: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + IsWrapped: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + Keyword: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + MessageDeliveryType: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + ModifiedDate: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + Name: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + ObjectID: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + ObjectState: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + Owner: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + PartnerKey: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + PartnerProperties: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + PreHeader: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + PrivateDomain: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + PrivateIP: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + ReplyToAddress: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + ReplyToDisplayName: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + SeedListOccurance: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + 'SendClassification.CustomerKey': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + 'SendClassification.ObjectID': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + 'SendClassification.PartnerKey': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + 'SendDefinitionList.CustomObjectID': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + SendDefinitionList: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + 'SendDefinitionList[].ObjectID': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + 'SendDefinitionList[].PartnerKey': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + 'SendDefinitionList[].CustomObjectID': { + skipValidation: boolean; + }; + 'SendDefinitionList[].SendDefinitionListType': { + skipValidation: boolean; + }; + 'SendDefinitionList[].DataSourceTypeID': { + skipValidation: boolean; + }; + 'SendDefinitionList[].IsTestObject': { + skipValidation: boolean; + }; + 'SendDefinitionList[].SalesForceObjectID': { + skipValidation: boolean; + }; + 'SendDefinitionList[].Name': { + skipValidation: boolean; + }; + 'SendDefinitionList[].r__dataExtension_key': { + skipValidation: boolean; + }; + 'SendDefinitionList[].List.ObjectID': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + 'SendDefinitionList[].List.PartnerKey': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + 'SendDefinitionList[].r__list_PathName': { + skipValidation: boolean; + }; + 'SenderProfile.CustomerKey': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + 'SenderProfile.FromAddress': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + 'SenderProfile.FromName': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + 'SenderProfile.ObjectID': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + 'SenderProfile.PartnerKey': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + SendLimit: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + SendWindowClose: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + SendWindowDelete: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + SendWindowOpen: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + SourceAddressType: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + SuppressTracking: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + TestEmailAddr: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + TimeZone: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + TrackingUsers: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + r__asset_name_readOnly: { + skipValidation: boolean; + }; + r__asset_key: { + skipValidation: boolean; + }; + r__email_name: { + skipValidation: boolean; + }; + r__folder_Path: { + skipValidation: boolean; + }; + r__senderProfile_key: { + skipValidation: boolean; + }; + r__sendClassification_key: { + skipValidation: boolean; + }; + r__deliveryProfile_key: { + skipValidation: boolean; + }; + }; + }; +} +import MetadataType from './MetadataType.js'; +//# sourceMappingURL=EmailSend.d.ts.map \ No newline at end of file diff --git a/@types/lib/metadataTypes/EmailSend.d.ts.map b/@types/lib/metadataTypes/EmailSend.d.ts.map new file mode 100644 index 000000000..3a09deb0d --- /dev/null +++ b/@types/lib/metadataTypes/EmailSend.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"EmailSend.d.ts","sourceRoot":"","sources":["../../../lib/metadataTypes/EmailSend.js"],"names":[],"mappings":";uBAOa,OAAO,wBAAwB,EAAE,QAAQ;0BACzC,OAAO,wBAAwB,EAAE,WAAW;8BAC5C,OAAO,wBAAwB,EAAE,eAAe;+BAChD,OAAO,wBAAwB,EAAE,gBAAgB;mCACjD,OAAO,wBAAwB,EAAE,oBAAoB;kCACrD,OAAO,wBAAwB,EAAE,mBAAmB;8BACpD,OAAO,wBAAwB,EAAE,eAAe;iCAChD,OAAO,wBAAwB,EAAE,kBAAkB;gCACnD,OAAO,wBAAwB,EAAE,iBAAiB;0BAClD,OAAO,wBAAwB,EAAE,WAAW;AAVzD;;;;;;;;;;;GAWG;AAEH;;;;GAIG;AACH;IACI;;;;;;;;OAQG;IACH,8BANW,MAAM,MACN,IAAI,GAAG,MAAM,EAAE,OACf,IAAI,GAAG,MAAM,EAAE,QACf,MAAM,GACJ,OAAO,CAAE,kBAAkB,CAAC,CAmCxC;IAED;;;;;OAKG;IACH,4BAHW,gBAAgB,gBAK1B;IAED;;;;;OAKG;IACH,4BAHW,gBAAgB,gBAK1B;IAYD;;;;;OAKG;IACH,gCAHW,gBAAgB,GACd,OAAO,CAAE,gBAAgB,CAAC,CAuJtC;IAED;;;;;OAKG;IACH,mCAHW,gBAAgB,GACd,gBAAgB,CAsJ5B;CACJ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;yBAzZwB,mBAAmB"} \ No newline at end of file diff --git a/@types/lib/metadataTypes/Event.d.ts b/@types/lib/metadataTypes/Event.d.ts new file mode 100644 index 000000000..8f50cc67c --- /dev/null +++ b/@types/lib/metadataTypes/Event.d.ts @@ -0,0 +1,1224 @@ +export default Event; +export type BuObject = import("../../types/mcdev.d.js").BuObject; +export type CodeExtract = import("../../types/mcdev.d.js").CodeExtract; +export type CodeExtractItem = import("../../types/mcdev.d.js").CodeExtractItem; +export type MetadataTypeItem = import("../../types/mcdev.d.js").MetadataTypeItem; +export type MetadataTypeItemDiff = import("../../types/mcdev.d.js").MetadataTypeItemDiff; +export type MetadataTypeItemObj = import("../../types/mcdev.d.js").MetadataTypeItemObj; +export type MetadataTypeMap = import("../../types/mcdev.d.js").MetadataTypeMap; +export type MetadataTypeMapObj = import("../../types/mcdev.d.js").MetadataTypeMapObj; +export type SoapRequestParams = import("../../types/mcdev.d.js").SoapRequestParams; +export type TemplateMap = import("../../types/mcdev.d.js").TemplateMap; +export type ReferenceObject = import("../../types/mcdev.d.js").ReferenceObject; +export type SfObjectField = import("../../types/mcdev.d.js").SfObjectField; +export type configurationArguments = import("../../types/mcdev.d.js").configurationArguments; +export type Conditions = import("../../types/mcdev.d.js").Conditions; +export type DataExtensionItem = import("../../types/mcdev.d.js").DataExtensionItem; +/** + * @typedef {import('../../types/mcdev.d.js').BuObject} BuObject + * @typedef {import('../../types/mcdev.d.js').CodeExtract} CodeExtract + * @typedef {import('../../types/mcdev.d.js').CodeExtractItem} CodeExtractItem + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItem} MetadataTypeItem + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItemDiff} MetadataTypeItemDiff + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItemObj} MetadataTypeItemObj + * @typedef {import('../../types/mcdev.d.js').MetadataTypeMap} MetadataTypeMap + * @typedef {import('../../types/mcdev.d.js').MetadataTypeMapObj} MetadataTypeMapObj + * @typedef {import('../../types/mcdev.d.js').SoapRequestParams} SoapRequestParams + * @typedef {import('../../types/mcdev.d.js').TemplateMap} TemplateMap + * + * @typedef {import('../../types/mcdev.d.js').ReferenceObject} ReferenceObject + * @typedef {import('../../types/mcdev.d.js').SfObjectField} SfObjectField + * @typedef {import('../../types/mcdev.d.js').configurationArguments} configurationArguments + * @typedef {import('../../types/mcdev.d.js').Conditions} Conditions + * @typedef {import('../../types/mcdev.d.js').DataExtensionItem} DataExtensionItem + */ +/** + * Event MetadataType + * + * @augments MetadataType + */ +declare class Event extends MetadataType { + static reCacheDataExtensions: any[]; + static createdKeys: any[]; + /** + * Retrieves Metadata of Event Definition. + * Endpoint /interaction/v1/eventDefinitions return all Event Definitions with all details. + * Currently it is not needed to loop over Imports with endpoint /interaction/v1/eventDefinitions/{id} + * + * @param {string} retrieveDir Directory where retrieved metadata directory will be saved + * @param {void | string[]} [_] unused parameter + * @param {void | string[]} [__] unused parameter + * @param {string} [key] customer key of single item to retrieve + * @returns {Promise.<MetadataTypeMapObj>} Promise of metadata + */ + static retrieve(retrieveDir: string, _?: void | string[], __?: void | string[], key?: string): Promise<MetadataTypeMapObj>; + /** + * Retrieves event definition metadata for caching + * + * @returns {Promise.<MetadataTypeMapObj>} Promise of metadata + */ + static retrieveForCache(): Promise<MetadataTypeMapObj>; + /** + * Retrieve a specific Event Definition by Name + * + * @deprecated Use `retrieve` followed by `build` instead. `retrieveAsTemplate` will be removed in a future version. + * @param {string} templateDir Directory where retrieved metadata directory will be saved + * @param {string} name name of the metadata file + * @param {TemplateMap} templateVariables variables to be replaced in the metadata + * @returns {Promise.<MetadataTypeItemObj>} Promise of metadata + */ + static retrieveAsTemplate(templateDir: string, name: string, templateVariables: TemplateMap): Promise<MetadataTypeItemObj>; + /** + * Creates a single Event Definition + * + * @param {MetadataTypeItem} metadata a single Event Definition + * @returns {Promise} Promise + */ + static create(metadata: MetadataTypeItem): Promise<any>; + /** + * Updates a single Event Definition (using PUT method since PATCH isn't supported) + * + * @param {MetadataTypeItem} metadataEntry a single Event Definition + * @returns {Promise} Promise + */ + static update(metadataEntry: MetadataTypeItem): Promise<any>; + /** + * prepares an event definition for deployment + * + * @param {MetadataTypeItem} metadata a single eventDefinition + * @returns {Promise.<MetadataTypeItem>} parsed version + */ + static preDeployTasks(metadata: MetadataTypeItem): Promise<MetadataTypeItem>; + /** + * helper for {@link createOrUpdate} + * + * @param {string} metadataKey key of item we are looking at + * @param {MetadataTypeItemDiff[]} metadataToUpdate list of items to update + * @param {MetadataTypeItem[]} metadataToCreate list of items to create + */ + static removeFromDeployment(metadataKey: string, metadataToUpdate: MetadataTypeItemDiff[], metadataToCreate: MetadataTypeItem[]): void; + /** + * parses retrieved Metadata before saving + * + * @param {MetadataTypeItem} metadata a single event definition + * @returns {Promise.<MetadataTypeItem>} parsed metadata + */ + static postRetrieveTasks(metadata: MetadataTypeItem): Promise<MetadataTypeItem>; + static sfObjects: { + /** @type {string[]} */ + workflowObjects: string[]; + /** @type {Object.<string, ReferenceObject[]>} object-name > object data */ + referencedObjects: { + [x: string]: import("../../types/mcdev.d.js").ReferenceObject[]; + }; + /** @type {Object.<string, Object.<string, SfObjectField>>} object-name > field-name > field data */ + objectFields: { + [x: string]: { + [x: string]: import("../../types/mcdev.d.js").SfObjectField; + }; + }; + /** @type {Object.<string, Promise.<any>>} */ + loadingFields: { + [x: string]: Promise<any>; + }; + /** @type {Object.<string, Promise.<any>>} */ + loadingRelatedObjects: { + [x: string]: Promise<any>; + }; + /** @type {Promise.<any>} */ + loadingWorkflowObjects: Promise<any>; + }; + /** + * helper for {@link checkSalesforceEntryEvents} that retrieves information about SF object fields + * + * @param {string} objectAPIName salesforce object api name + */ + static getSalesforceObjects(objectAPIName: string): Promise<void>; + /** + * helper that allows skipping to run this again in multi-key retrieval + */ + static _getWorkflowObjects(): Promise<void>; + /** + * helper that allows skipping to run this again in multi-key retrieval + * + * @param {string} objectAPIName SF entry object of the current event + */ + static _getRelatedSfObjects(objectAPIName: string): Promise<void>; + /** + * helper that allows skipping to run this again in multi-key retrieval + * + * @param {string} objectAPIName SF object for which to get the fields + */ + static _getSalesforceObjectFields(objectAPIName: string): Promise<void>; + static defaultSalesforceFields: string[]; + /** + * + * @param {configurationArguments} ca trigger[0].configurationArguments + * @param {boolean} isPublished if the current item is published it means we do not need to do contact vs common checks + * @returns {string} warnings or null + */ + static checkSalesforceEntryEvents(ca: configurationArguments, isPublished: boolean): string; + /** + * + * @param {object[]} conditions - + * @param {string[]} errors list of errors + * @param {'primaryObjectFilterCriteria'|'relatedObjectFilterCriteria'} context used to improve error logs + */ + static checkSfFilterFieldsExist(conditions: object[], errors: string[], context: "primaryObjectFilterCriteria" | "relatedObjectFilterCriteria"): void; + static requiredConfigurationArguments: string[]; + /** + * + * @param {string} triggerType e.g. SalesforceObjectTriggerV2, APIEvent, ... + * @param {configurationArguments} ca trigger[0].configurationArguments + * @param {string} key of event / journey + * @param {boolean} isPublished if the current item is published it means we do not need to do contact vs common checks + * @param {string} [type] optionally provide metadatype for error on missing configurationArguments attributes + * @returns {Promise.<void>} - + */ + static postRetrieveTasks_SalesforceEntryEvents(triggerType: string, ca: configurationArguments, key: string, isPublished: boolean, type?: string): Promise<void>; + /** + * + * @param {string} triggerType e.g. SalesforceObjectTriggerV2, APIEvent, ... + * @param {string[]} eventDataSummary eventDataConfig in simplified string-form + * @param {string} deKey key of associated dataExtension + * @returns {Promise.<void>} - + */ + static compareSalesforceEntryEvents_dataExtension(triggerType: string, eventDataSummary: string[], deKey: string): Promise<void>; + /** + * + * @param {string} triggerType e.g. SalesforceObjectTriggerV2, APIEvent, ... + * @param {configurationArguments} ca trigger[0].configurationArguments + * @returns {Promise.<string>} - + */ + static preDeployTasks_SalesforceEntryEvents(triggerType: string, ca: configurationArguments): Promise<string>; +} +declare namespace Event { + let definition: { + bodyIteratorField: string; + dependencies: string[]; + dependencyGraph: { + automation: string[]; + dataExtension: string[]; + }; + hasExtended: boolean; + idField: string; + keyIsFixed: boolean; + keyField: string; + nameField: string; + createdDateField: string; + createdNameField: string; + lastmodDateField: string; + lastmodNameField: string; + restPagination: boolean; + maxKeyLength: number; + type: string; + typeDescription: string; + typeRetrieveByDefault: boolean; + typeCdpByDefault: boolean; + typeName: string; + validTypes: string[]; + fields: { + 'arguments.audienceCount': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'arguments.audienceDefinitionID': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'arguments.audienceDescription': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'arguments.audienceSource': { + skipValidation: boolean; + }; + 'arguments.audienceName': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'arguments.automationId': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'arguments.buildAudienceDefinitionID': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'arguments.contactAttributeGroup': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'arguments.contactAttributeId': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'arguments.contactAttributeName': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'arguments.criteria': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'arguments.dataExtensionId': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'arguments.dataTargetName': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'arguments.formName': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'arguments.dateOffset': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'arguments.dateOffsetUnit': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'arguments.dateType': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'arguments.eid': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'arguments.eventDefinitionId': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'arguments.eventDefinitionKey': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'arguments.mid': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'arguments.resetHighWatermark': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'arguments.serializedObjectType': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'arguments.transactionKeyDataExtension': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'arguments.transactionKeyEvent': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'arguments.useHighWatermark': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + automationId: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + category: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + configurationArguments: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'configurationArguments.applicationExtensionKey': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'configurationArguments.contactKey': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'configurationArguments.contactKey.relationshipIdName': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'configurationArguments.contactKey.relationshipName': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'configurationArguments.contactKey.isPolymorphic': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'configurationArguments.contactKey.referenceObjectName': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'configurationArguments.contactPersonType': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'configurationArguments.dataExtensionId': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'configurationArguments.evaluationCriteriaSummary': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'configurationArguments.eventDataConfig': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'configurationArguments.eventDataConfig.objects': { + skipValidation: boolean; + }; + 'configurationArguments.eventDataSummary': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'configurationArguments.objectAPIName': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'configurationArguments.passThroughArgument': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'configurationArguments.passThroughArgument.fields': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'configurationArguments.passThroughArgument.fields.ContactKey': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'configurationArguments.passThroughArgument.fields.Email': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'configurationArguments.primaryObjectFilterCriteria': { + skipValidation: boolean; + }; + 'configurationArguments.primaryObjectFilterSummary': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'configurationArguments.relatedObjectFilterCriteria': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'configurationArguments.relatedObjectFilterSummary': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'configurationArguments.salesforceTriggerCriteria': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'configurationArguments.unconfigured': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'configurationArguments.version': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'configurationArguments.whoToInject': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + createdBy: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + createdDate: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + dataExtensionId: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + dataExtensionName: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + description: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + disableDEDataLogging: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + eventDefinitionKey: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + filterDefinitionId: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + filterDefinitionTemplate: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + iconUrl: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + id: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + interactionCount: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + isPlatformObject: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + isVisibleInPicker: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'metaData.attributeName': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'metaData.automationData.automationType': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'metaData.automationData.categoryId': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'metaData.automationData.createdBy.email': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'metaData.automationData.createdBy.id': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'metaData.automationData.createdBy.name': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'metaData.automationData.createdDate': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'metaData.automationData.description': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'metaData.automationData.folderPath': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'metaData.automationData.guidId': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'metaData.automationData.id': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'metaData.automationData.isPlatformObject': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'metaData.automationData.key': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'metaData.automationData.lastRunInstance': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'metaData.automationData.lastRunTime': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'metaData.automationData.lastSaveDate': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'metaData.automationData.lastSavedBy.email': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'metaData.automationData.lastSavedBy.id': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'metaData.automationData.lastSavedBy.name': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'metaData.automationData.memberId': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'metaData.automationData.modifiedDate': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'metaData.automationData.name': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'metaData.automationData.notifications': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'metaData.automationData.processes': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'metaData.automationData.schedule': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'metaData.automationData.scheduleObject.createdBy': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'metaData.automationData.scheduleObject.createdDate': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'metaData.automationData.scheduleObject.description': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'metaData.automationData.scheduleObject.iCalRecur': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'metaData.automationData.scheduleObject.id': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'metaData.automationData.scheduleObject.key': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'metaData.automationData.scheduleObject.lastUpdated': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'metaData.automationData.scheduleObject.lastUpdatedBy': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'metaData.automationData.scheduleObject.name': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'metaData.automationData.scheduleObject.scheduleState': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'metaData.automationData.scheduleObject.scheduleStatus': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'metaData.automationData.scheduleObject.startDate': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'metaData.automationData.scheduleObject.timeZone': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'metaData.automationData.scheduleObject.timeZoneId': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'metaData.automationData.scheduledTime': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'metaData.automationData.selectedCategoryId': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'metaData.automationData.selectedCategoryId[]': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'metaData.automationData.status': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'metaData.automationData.updateInProgress': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'metaData.criteriaDescription': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'metaData.customAttributeName': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'metaData.formattedDate': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'metaData.formattedTime': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'metaData.icon': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'metaData.original_icon': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'metaData.isConfigured': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'metaData.runOnceScheduleMode': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'metaData.scheduleFlowMode': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'metaData.scheduleState': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'metaData.timeZone': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'metaData.transactionKeys': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'metaData.transactionKeys.0': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'metaData.transactionKeys.0.from': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'metaData.transactionKeys.0.to': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + mode: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + modifiedBy: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + modifiedDate: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + name: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + publishedInteractionCount: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'schedule.scheduledDayOfWeek': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'schedule.scheduledWeek': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'schedule.endDateTime': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'schedule.endType': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'schedule.frequency': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'schedule.interval': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'schedule.occurrences': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'schedule.recurrencePattern': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'schedule.scheduledDay': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'schedule.startDateTime': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'schedule.timeZone': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'schedule.monday': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'schedule.tuesday': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'schedule.wednesday': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'schedule.thursday': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'schedule.friday': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'schedule.saturday': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'schedule.sunday': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'schema.fields': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'schema.fields[].dataType': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'schema.fields[].defaultValue': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'schema.fields[].isDevicePreference': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'schema.fields[].isNullable': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'schema.fields[].isPrimaryKey': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'schema.fields[].maxLength': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'schema.fields[].name': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'schema.id': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'schema.name': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'schema.sendableCustomObjectField': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'schema.sendableSubscriberField': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'schema.isPlatformObject': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + sourceApplicationExtensionId: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + entrySourceGroupConfigUrl: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + type: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + r__dataExtension_key: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + r__automation_key: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + }; + }; +} +import MetadataType from './MetadataType.js'; +//# sourceMappingURL=Event.d.ts.map \ No newline at end of file diff --git a/@types/lib/metadataTypes/Event.d.ts.map b/@types/lib/metadataTypes/Event.d.ts.map new file mode 100644 index 000000000..45d7571fa --- /dev/null +++ b/@types/lib/metadataTypes/Event.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"Event.d.ts","sourceRoot":"","sources":["../../../lib/metadataTypes/Event.js"],"names":[],"mappings":";uBAUa,OAAO,wBAAwB,EAAE,QAAQ;0BACzC,OAAO,wBAAwB,EAAE,WAAW;8BAC5C,OAAO,wBAAwB,EAAE,eAAe;+BAChD,OAAO,wBAAwB,EAAE,gBAAgB;mCACjD,OAAO,wBAAwB,EAAE,oBAAoB;kCACrD,OAAO,wBAAwB,EAAE,mBAAmB;8BACpD,OAAO,wBAAwB,EAAE,eAAe;iCAChD,OAAO,wBAAwB,EAAE,kBAAkB;gCACnD,OAAO,wBAAwB,EAAE,iBAAiB;0BAClD,OAAO,wBAAwB,EAAE,WAAW;8BAE5C,OAAO,wBAAwB,EAAE,eAAe;4BAChD,OAAO,wBAAwB,EAAE,aAAa;qCAC9C,OAAO,wBAAwB,EAAE,sBAAsB;yBACvD,OAAO,wBAAwB,EAAE,UAAU;gCAC3C,OAAO,wBAAwB,EAAE,iBAAiB;AAhB/D;;;;;;;;;;;;;;;;;GAiBG;AAEH;;;;GAIG;AACH;IACI,oCAAkC;IAClC,0BAAwB;IAExB;;;;;;;;;;OAUG;IACH,6BANW,MAAM,MACN,IAAI,GAAG,MAAM,EAAE,OACf,IAAI,GAAG,MAAM,EAAE,QACf,MAAM,GACJ,OAAO,CAAE,kBAAkB,CAAC,CAwBxC;IAED;;;;OAIG;IACH,2BAFa,OAAO,CAAE,kBAAkB,CAAC,CAIxC;IAED;;;;;;;;OAQG;IACH,uCALW,MAAM,QACN,MAAM,qBACN,WAAW,GACT,OAAO,CAAE,mBAAmB,CAAC,CAiDzC;IAgCD;;;;;OAKG;IACH,wBAHW,gBAAgB,gBAM1B;IAED;;;;;OAKG;IACH,6BAHW,gBAAgB,gBAU1B;IAED;;;;;OAKG;IACH,gCAHW,gBAAgB,GACd,OAAO,CAAE,gBAAgB,CAAC,CA8EtC;IA2HD;;;;;;OAMG;IACH,yCAJW,MAAM,oBACN,oBAAoB,EAAE,oBACtB,gBAAgB,EAAE,QAe5B;IA2FD;;;;;OAKG;IACH,mCAHW,gBAAgB,GACd,OAAO,CAAE,gBAAgB,CAAC,CAmItC;IACD;QACI,uBAAuB;yBAAZ,MAAM,EAAE;QAEnB,2EAA2E;;;;QAE3E,oGAAoG;;;;;;QAEpG,6CAA6C;;;;QAE7C,6CAA6C;;;;QAE7C,4BAA4B;gCAAjB,OAAO,CAAE,GAAG,CAAC;MAE1B;IAEF;;;;OAIG;IACH,2CAFW,MAAM,iBAgFhB;IACD;;OAEG;IACH,4CAQC;IACD;;;;OAIG;IACH,2CAFW,MAAM,iBAuChB;IACD;;;;OAIG;IACH,iDAFW,MAAM,iBAoChB;IAED,yCAYE;IAEF;;;;;OAKG;IACH,sCAJW,sBAAsB,eACtB,OAAO,GACL,MAAM,CA6NlB;IAED;;;;;OAKG;IACH,4CAJW,MAAM,EAAE,UACR,MAAM,EAAE,WACR,6BAA6B,GAAC,6BAA6B,QAerE;IAED,gDAYE;IACF;;;;;;;;OAQG;IACH,4DAPW,MAAM,MACN,sBAAsB,OACtB,MAAM,eACN,OAAO,SACP,MAAM,GACJ,OAAO,CAAE,IAAI,CAAC,CAwD1B;IACD;;;;;;OAMG;IACH,+DALW,MAAM,oBACN,MAAM,EAAE,SACR,MAAM,GACJ,OAAO,CAAE,IAAI,CAAC,CAuC1B;IAED;;;;;OAKG;IACH,yDAJW,MAAM,MACN,sBAAsB,GACpB,OAAO,CAAE,MAAM,CAAC,CAoE5B;CACJ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;yBAlxCwB,mBAAmB"} \ No newline at end of file diff --git a/@types/lib/metadataTypes/FileLocation.d.ts b/@types/lib/metadataTypes/FileLocation.d.ts new file mode 100644 index 000000000..18e5847b3 --- /dev/null +++ b/@types/lib/metadataTypes/FileLocation.d.ts @@ -0,0 +1,211 @@ +export default FileLocation; +export type BuObject = import("../../types/mcdev.d.js").BuObject; +export type CodeExtract = import("../../types/mcdev.d.js").CodeExtract; +export type CodeExtractItem = import("../../types/mcdev.d.js").CodeExtractItem; +export type MetadataTypeItem = import("../../types/mcdev.d.js").MetadataTypeItem; +export type MetadataTypeItemDiff = import("../../types/mcdev.d.js").MetadataTypeItemDiff; +export type MetadataTypeItemObj = import("../../types/mcdev.d.js").MetadataTypeItemObj; +export type MetadataTypeMap = import("../../types/mcdev.d.js").MetadataTypeMap; +export type MetadataTypeMapObj = import("../../types/mcdev.d.js").MetadataTypeMapObj; +export type SoapRequestParams = import("../../types/mcdev.d.js").SoapRequestParams; +export type TemplateMap = import("../../types/mcdev.d.js").TemplateMap; +/** + * @typedef {import('../../types/mcdev.d.js').BuObject} BuObject + * @typedef {import('../../types/mcdev.d.js').CodeExtract} CodeExtract + * @typedef {import('../../types/mcdev.d.js').CodeExtractItem} CodeExtractItem + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItem} MetadataTypeItem + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItemDiff} MetadataTypeItemDiff + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItemObj} MetadataTypeItemObj + * @typedef {import('../../types/mcdev.d.js').MetadataTypeMap} MetadataTypeMap + * @typedef {import('../../types/mcdev.d.js').MetadataTypeMapObj} MetadataTypeMapObj + * @typedef {import('../../types/mcdev.d.js').SoapRequestParams} SoapRequestParams + * @typedef {import('../../types/mcdev.d.js').TemplateMap} TemplateMap + */ +/** + * ImportFile MetadataType + * + * @augments MetadataType + */ +declare class FileLocation extends MetadataType { + static cache: {}; + /** + * Retrieves Metadata of FileLocation + * Endpoint /automation/v1/ftplocations/ return all FileLocations + * + * @param {string} retrieveDir Directory where retrieved metadata directory will be saved + * @param {void | string[]} [_] unused parameter + * @param {void | string[]} [__] unused parameter + * @param {string} [key] customer key of single item to retrieve + * @returns {Promise.<MetadataTypeMapObj>} Promise + */ + static retrieve(retrieveDir: string, _?: void | string[], __?: void | string[], key?: string): Promise<MetadataTypeMapObj>; + /** + * Retrieves folder metadata into local filesystem. Also creates a uniquePath attribute for each folder. + * + * @returns {Promise.<MetadataTypeMapObj>} Promise + */ + static retrieveForCache(): Promise<MetadataTypeMapObj>; + /** + * Creates a single item + * + * @param {MetadataTypeItem} metadata a single item + * @returns {Promise.<MetadataTypeItem>} Promise + */ + static create(metadata: MetadataTypeItem): Promise<MetadataTypeItem>; + /** + * Updates a single item + * + * @param {MetadataTypeItem} metadata a single item + * @returns {Promise.<MetadataTypeItem>} Promise + */ + static update(metadata: MetadataTypeItem): Promise<MetadataTypeItem>; + /** + * helper for {@link MetadataType.createREST} + * + * @param {MetadataTypeItem} _ a single metadata Entry + * @param {object} apiResponse varies depending on the API call + * @returns {Promise.<object>} apiResponse, potentially modified + */ + static postCreateTasks(_: MetadataTypeItem, apiResponse: object): Promise<object>; + /** + * helper for {@link MetadataType.updateREST} and {@link MetadataType.updateSOAP} + * + * @param {MetadataTypeItem} _ a single metadata Entry + * @param {object} apiResponse varies depending on the API call + * @returns {Promise.<object>} apiResponse, potentially modified + */ + static postUpdateTasks(_: MetadataTypeItem, apiResponse: object): Promise<object>; + /** + * prepares a import definition for deployment + * + * @param {MetadataTypeItem} metadata a single importDef + * @returns {Promise.<MetadataTypeItem>} Promise + */ + static preDeployTasks(metadata: MetadataTypeItem): Promise<MetadataTypeItem>; + /** + * manages post retrieve steps + * + * @param {MetadataTypeItem} metadata a single item + * @returns {MetadataTypeItem} parsed metadata + */ + static postRetrieveTasks(metadata: MetadataTypeItem): MetadataTypeItem; +} +declare namespace FileLocation { + let definition: { + bodyIteratorField: string; + dependencies: any[]; + dependencyGraph: any; + hasExtended: boolean; + idField: string; + keyIsFixed: boolean; + keyField: string; + nameField: string; + createdDateField: any; + createdNameField: any; + lastmodDateField: any; + lastmodNameField: any; + restPagination: boolean; + maxKeyLength: number; + type: string; + typeDescription: string; + typeRetrieveByDefault: boolean; + typeCdpByDefault: boolean; + typeName: string; + locationTypeMapping: { + 'Enhanced FTP Site Import Directory': number; + 'External FTP Site': number; + 'External SFTP Site': number; + 'External FTPS Site': number; + 'Salesforce Objects and Reports': number; + Safehouse: number; + 'Enhanced FTP Site Export Directory': number; + 'Legacy Import Directory': number; + 'Relative location under FTP Site': number; + 'Amazon Simple Storage Service': number; + 'Azure Blob Storage': number; + 'Google Cloud Storage': number; + }; + locationTypeMappingDeployable: { + 'External SFTP Site': string; + 'Amazon Simple Storage Service': string; + 'Azure Blob Storage': string; + 'Google Cloud Storage': string; + }; + locationTypeIdMappingDeployable: { + 2: string; + 13: string; + 15: string; + 16: string; + }; + fields: { + id: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + locationTypeId: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + locationType: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + locationUrl: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + name: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + customerKey: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + description: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + relPath: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + awsFileTransferLocation: { + skipValidation: boolean; + }; + azureFileTransferLocation: { + skipValidation: boolean; + }; + gcpFileTransferLocation: { + skipValidation: boolean; + }; + sFtpFileTransferLocation: { + skipValidation: boolean; + }; + c__locationType: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + }; + }; +} +import MetadataType from './MetadataType.js'; +//# sourceMappingURL=FileLocation.d.ts.map \ No newline at end of file diff --git a/@types/lib/metadataTypes/FileLocation.d.ts.map b/@types/lib/metadataTypes/FileLocation.d.ts.map new file mode 100644 index 000000000..00200d338 --- /dev/null +++ b/@types/lib/metadataTypes/FileLocation.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"FileLocation.d.ts","sourceRoot":"","sources":["../../../lib/metadataTypes/FileLocation.js"],"names":[],"mappings":";uBAMa,OAAO,wBAAwB,EAAE,QAAQ;0BACzC,OAAO,wBAAwB,EAAE,WAAW;8BAC5C,OAAO,wBAAwB,EAAE,eAAe;+BAChD,OAAO,wBAAwB,EAAE,gBAAgB;mCACjD,OAAO,wBAAwB,EAAE,oBAAoB;kCACrD,OAAO,wBAAwB,EAAE,mBAAmB;8BACpD,OAAO,wBAAwB,EAAE,eAAe;iCAChD,OAAO,wBAAwB,EAAE,kBAAkB;gCACnD,OAAO,wBAAwB,EAAE,iBAAiB;0BAClD,OAAO,wBAAwB,EAAE,WAAW;AAVzD;;;;;;;;;;;GAWG;AAEH;;;;GAIG;AACH;IACI,iBAAkB;IAClB;;;;;;;;;OASG;IACH,6BANW,MAAM,MACN,IAAI,GAAG,MAAM,EAAE,OACf,IAAI,GAAG,MAAM,EAAE,QACf,MAAM,GACJ,OAAO,CAAE,kBAAkB,CAAC,CA4BxC;IAED;;;;OAIG;IACH,2BAFa,OAAO,CAAE,kBAAkB,CAAC,CAIxC;IAED;;;;;OAKG;IACH,wBAHW,gBAAgB,GACd,OAAO,CAAE,gBAAgB,CAAC,CAItC;IACD;;;;;OAKG;IACH,wBAHW,gBAAgB,GACd,OAAO,CAAE,gBAAgB,CAAC,CAQtC;IAoED;;;;;;OAMG;IACH,0BAJW,gBAAgB,eAChB,MAAM,GACJ,OAAO,CAAE,MAAM,CAAC,CAI5B;IAuCD;;;;;;OAMG;IACH,0BAJW,gBAAgB,eAChB,MAAM,GACJ,OAAO,CAAE,MAAM,CAAC,CAI5B;IACD;;;;;OAKG;IACH,gCAHW,gBAAgB,GACd,OAAO,CAAE,gBAAgB,CAAC,CAetC;IAED;;;;;OAKG;IACH,mCAHW,gBAAgB,GACd,gBAAgB,CAwB5B;CAeJ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;yBAzRwB,mBAAmB"} \ No newline at end of file diff --git a/@types/lib/metadataTypes/FileTransfer.d.ts b/@types/lib/metadataTypes/FileTransfer.d.ts new file mode 100644 index 000000000..cef627ec0 --- /dev/null +++ b/@types/lib/metadataTypes/FileTransfer.d.ts @@ -0,0 +1,224 @@ +export default FileTransfer; +export type BuObject = import("../../types/mcdev.d.js").BuObject; +export type CodeExtract = import("../../types/mcdev.d.js").CodeExtract; +export type CodeExtractItem = import("../../types/mcdev.d.js").CodeExtractItem; +export type MetadataTypeItem = import("../../types/mcdev.d.js").MetadataTypeItem; +export type MetadataTypeItemDiff = import("../../types/mcdev.d.js").MetadataTypeItemDiff; +export type MetadataTypeItemObj = import("../../types/mcdev.d.js").MetadataTypeItemObj; +export type MetadataTypeMap = import("../../types/mcdev.d.js").MetadataTypeMap; +export type MetadataTypeMapObj = import("../../types/mcdev.d.js").MetadataTypeMapObj; +export type SoapRequestParams = import("../../types/mcdev.d.js").SoapRequestParams; +export type TemplateMap = import("../../types/mcdev.d.js").TemplateMap; +/** + * @typedef {import('../../types/mcdev.d.js').BuObject} BuObject + * @typedef {import('../../types/mcdev.d.js').CodeExtract} CodeExtract + * @typedef {import('../../types/mcdev.d.js').CodeExtractItem} CodeExtractItem + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItem} MetadataTypeItem + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItemDiff} MetadataTypeItemDiff + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItemObj} MetadataTypeItemObj + * @typedef {import('../../types/mcdev.d.js').MetadataTypeMap} MetadataTypeMap + * @typedef {import('../../types/mcdev.d.js').MetadataTypeMapObj} MetadataTypeMapObj + * @typedef {import('../../types/mcdev.d.js').SoapRequestParams} SoapRequestParams + * @typedef {import('../../types/mcdev.d.js').TemplateMap} TemplateMap + */ +/** + * FileTransfer MetadataType + * + * @augments MetadataType + */ +declare class FileTransfer extends MetadataType { + /** + * Retrieves Metadata of FileTransfer Activity. + * Endpoint /automation/v1/filetransfers/ returns all File Transfers + * + * @param {string} retrieveDir Directory where retrieved metadata directory will be saved + * @param {void | string[]} [_] unused parameter + * @param {void | string[]} [__] unused parameter + * @param {string} [key] customer key of single item to retrieve + * @returns {Promise.<MetadataTypeMapObj>} Promise + */ + static retrieve(retrieveDir: string, _?: void | string[], __?: void | string[], key?: string): Promise<MetadataTypeMapObj>; + /** + * Retrieves Metadata of FileTransfer Activity for caching + * + * @returns {Promise.<MetadataTypeMapObj>} Promise + */ + static retrieveForCache(): Promise<MetadataTypeMapObj>; + /** + * Retrieve a specific File Transfer Definition by Name + * + * @deprecated Use `retrieve` followed by `build` instead. `retrieveAsTemplate` will be removed in a future version. + * @param {string} templateDir Directory where retrieved metadata directory will be saved + * @param {string} name name of the metadata file + * @param {TemplateMap} templateVariables variables to be replaced in the metadata + * @returns {Promise.<MetadataTypeItemObj>} Promise + */ + static retrieveAsTemplate(templateDir: string, name: string, templateVariables: TemplateMap): Promise<MetadataTypeItemObj>; + /** + * Creates a single File Transfer + * + * @param {MetadataTypeItem} fileTransfer a single File Transfer + * @returns {Promise} Promise + */ + static create(fileTransfer: MetadataTypeItem): Promise<any>; + /** + * Updates a single File Transfer + * + * @param {MetadataTypeItem} fileTransfer a single File Transfer + * @returns {Promise} Promise + */ + static update(fileTransfer: MetadataTypeItem): Promise<any>; + /** + * prepares a fileTransfer for deployment + * + * @param {MetadataTypeItem} metadata a single fileTransfer activity definition + * @returns {Promise} Promise + */ + static preDeployTasks(metadata: MetadataTypeItem): Promise<any>; + /** + * manages post retrieve steps + * + * @param {MetadataTypeItem} metadata a single fileTransfer activity definition + * @returns {MetadataTypeItem} parsed metadata + */ + static postRetrieveTasks(metadata: MetadataTypeItem): MetadataTypeItem; + /** + * helper to allow us to select single metadata entries via REST + * + * @private + * @param {string} key customer key + * @returns {Promise.<string>} objectId or enpty string + */ + private static _getObjectIdForSingleRetrieve; +} +declare namespace FileTransfer { + let definition: { + bodyIteratorField: string; + dependencies: string[]; + dependencyGraph: {}; + hasExtended: boolean; + idField: string; + keyIsFixed: boolean; + keyField: string; + nameField: string; + createdDateField: string; + createdNameField: any; + lastmodDateField: string; + lastmodNameField: any; + restPagination: boolean; + type: string; + typeDescription: string; + typeRetrieveByDefault: boolean; + typeCdpByDefault: boolean; + typeName: string; + fields: { + createdDate: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + customerKey: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + description: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + fileSpec: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + fileTransferLocationId: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + id: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + isCompressed: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + isEncrypted: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + isFileSpecLocalized: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + isPgp: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + isUpload: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + maxFileAge: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + maxFileAgeScheduleOffset: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + maxImportFrequency: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + modifiedDate: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + name: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + publicKeyManagementId: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + r__fileLocation_name: { + skipValidation: boolean; + }; + }; + }; +} +import MetadataType from './MetadataType.js'; +//# sourceMappingURL=FileTransfer.d.ts.map \ No newline at end of file diff --git a/@types/lib/metadataTypes/FileTransfer.d.ts.map b/@types/lib/metadataTypes/FileTransfer.d.ts.map new file mode 100644 index 000000000..f577dce43 --- /dev/null +++ b/@types/lib/metadataTypes/FileTransfer.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"FileTransfer.d.ts","sourceRoot":"","sources":["../../../lib/metadataTypes/FileTransfer.js"],"names":[],"mappings":";uBAQa,OAAO,wBAAwB,EAAE,QAAQ;0BACzC,OAAO,wBAAwB,EAAE,WAAW;8BAC5C,OAAO,wBAAwB,EAAE,eAAe;+BAChD,OAAO,wBAAwB,EAAE,gBAAgB;mCACjD,OAAO,wBAAwB,EAAE,oBAAoB;kCACrD,OAAO,wBAAwB,EAAE,mBAAmB;8BACpD,OAAO,wBAAwB,EAAE,eAAe;iCAChD,OAAO,wBAAwB,EAAE,kBAAkB;gCACnD,OAAO,wBAAwB,EAAE,iBAAiB;0BAClD,OAAO,wBAAwB,EAAE,WAAW;AAVzD;;;;;;;;;;;GAWG;AAEH;;;;GAIG;AACH;IACI;;;;;;;;;OASG;IACH,6BANW,MAAM,MACN,IAAI,GAAG,MAAM,EAAE,OACf,IAAI,GAAG,MAAM,EAAE,QACf,MAAM,GACJ,OAAO,CAAE,kBAAkB,CAAC,CAIxC;IAED;;;;OAIG;IACH,2BAFa,OAAO,CAAE,kBAAkB,CAAC,CAIxC;IAED;;;;;;;;OAQG;IACH,uCALW,MAAM,QACN,MAAM,qBACN,WAAW,GACT,OAAO,CAAE,mBAAmB,CAAC,CA6CzC;IAED;;;;;OAKG;IACH,4BAHW,gBAAgB,gBAK1B;IAED;;;;;OAKG;IACH,4BAHW,gBAAgB,gBAK1B;IAED;;;;;OAKG;IACH,gCAHW,gBAAgB,gBAkB1B;IAED;;;;;OAKG;IACH,mCAHW,gBAAgB,GACd,gBAAgB,CAkB5B;IAED;;;;;;OAMG;IACH,6CASC;CAiBJ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;yBAzMwB,mBAAmB"} \ No newline at end of file diff --git a/@types/lib/metadataTypes/Filter.d.ts b/@types/lib/metadataTypes/Filter.d.ts new file mode 100644 index 000000000..fd703fa1c --- /dev/null +++ b/@types/lib/metadataTypes/Filter.d.ts @@ -0,0 +1,322 @@ +export default Filter; +export type BuObject = import("../../types/mcdev.d.js").BuObject; +export type CodeExtract = import("../../types/mcdev.d.js").CodeExtract; +export type CodeExtractItem = import("../../types/mcdev.d.js").CodeExtractItem; +export type MetadataTypeItem = import("../../types/mcdev.d.js").MetadataTypeItem; +export type MetadataTypeItemDiff = import("../../types/mcdev.d.js").MetadataTypeItemDiff; +export type MetadataTypeItemObj = import("../../types/mcdev.d.js").MetadataTypeItemObj; +export type MetadataTypeMap = import("../../types/mcdev.d.js").MetadataTypeMap; +export type MetadataTypeMapObj = import("../../types/mcdev.d.js").MetadataTypeMapObj; +export type SoapRequestParams = import("../../types/mcdev.d.js").SoapRequestParams; +export type TemplateMap = import("../../types/mcdev.d.js").TemplateMap; +export type FilterItem = import("../../types/mcdev.d.js").FilterItem; +/** + * @typedef {import('../../types/mcdev.d.js').BuObject} BuObject + * @typedef {import('../../types/mcdev.d.js').CodeExtract} CodeExtract + * @typedef {import('../../types/mcdev.d.js').CodeExtractItem} CodeExtractItem + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItem} MetadataTypeItem + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItemDiff} MetadataTypeItemDiff + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItemObj} MetadataTypeItemObj + * @typedef {import('../../types/mcdev.d.js').MetadataTypeMap} MetadataTypeMap + * @typedef {import('../../types/mcdev.d.js').MetadataTypeMapObj} MetadataTypeMapObj + * @typedef {import('../../types/mcdev.d.js').SoapRequestParams} SoapRequestParams + * @typedef {import('../../types/mcdev.d.js').TemplateMap} TemplateMap + * @typedef {import('../../types/mcdev.d.js').FilterItem} FilterItem + */ +/** + * Filter MetadataType + * + * @augments MetadataType + */ +declare class Filter extends MetadataType { + /** + * Retrieves Metadata of Filter. + * Endpoint /automation/v1/filters/ returns all Filters, + * but only with some of the fields. So it is needed to loop over + * Filters with the endpoint /automation/v1/filters/{id} + * + * @param {string} retrieveDir Directory where retrieved metadata directory will be saved + * @param {void | string[]} [_] unused parameter + * @param {void | string[]} [__] unused parameter + * @param {string} [key] customer key of single item to retrieve + * @returns {Promise.<MetadataTypeMapObj>} Promise + */ + static retrieve(retrieveDir: string, _?: void | string[], __?: void | string[], key?: string): Promise<MetadataTypeMapObj>; + /** + * parses retrieved Metadata before saving + * + * @param {FilterItem} metadata a single record + * @returns {FilterItem} parsed metadata definition + */ + static postRetrieveTasks(metadata: FilterItem): FilterItem; + /** + * helper for postRetrieveTasks to map data types + * + * @param {'source'|'destination'} target we are processing source and destinations + * @param {FilterItem} metadata single record + */ + static _postRetrieve_dataTypeMapping(target: "source" | "destination", metadata: FilterItem): void; + /** + * helper for preDeployTasks to map data types + * + * @param {'source'|'destination'} target we are processing source and destinations + * @param {FilterItem} metadata single record + * @param {FilterItem} cachedVersion cached version of the metadata + */ + static _preDeploy_dataTypeMapping(target: "source" | "destination", metadata: FilterItem, cachedVersion: FilterItem): void; + /** + * Creates a single item + * this uses soap API because the rest api does not allow hotlinking to an existing target DE + * + * @param {FilterItem} item a single item + * @returns {Promise} Promise + */ + static create(item: FilterItem): Promise<any>; + /** + * helper that converts the rest item into a soap item + * + * @param {FilterItem} item a single item + * @returns {object} SOAP formatted filter item + */ + static preCreateSOAPItem(item: FilterItem): object; + /** + * helper that runs update on all create calls to ensure all fields are set + * + * @param {FilterItem} restItem original rest item + * @param {object} response SOAP response + * @returns {Promise.<FilterItem>} created item + */ + static postCreateTasks(restItem: FilterItem, response: object): Promise<FilterItem>; + /** + * Updates a single item + * + * @param {MetadataTypeItem} item a single item + * @returns {Promise} Promise + */ + static update(item: MetadataTypeItem): Promise<any>; + /** + * prepares a record for deployment + * + * @param {FilterItem} metadata a single record + * @returns {Promise.<FilterItem>} Promise of updated single record + */ + static preDeployTasks(metadata: FilterItem): Promise<FilterItem>; + /** + * helper to allow us to select single metadata entries via REST + * + * @private + * @param {string} key customer key + * @returns {Promise.<string>} objectId or empty string + */ + private static _getObjectIdForSingleRetrieve; +} +declare namespace Filter { + let definition: { + bodyIteratorField: string; + dependencies: string[]; + dependencyGraph: { + filterDefinition: string[]; + dataExtension: string[]; + }; + hasExtended: boolean; + idField: string; + keyIsFixed: boolean; + keyField: string; + nameField: string; + folderType: string; + folderIdField: string; + filter: { + statusId: number; + }; + createdDateField: string; + createdNameField: any; + lastmodDateField: string; + lastmodNameField: any; + restPagination: boolean; + maxKeyLength: number; + type: string; + soapType: string; + typeDescription: string; + typeRetrieveByDefault: boolean; + typeCdpByDefault: boolean; + typeName: string; + fields: { + categoryId: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + createdDate: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + customerKey: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + CustomerKey: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + description: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + Description: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + destinationObjectId: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + DestinationObjectID: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + destinationTypeId: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + DestinationTypeID: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + filterActivityId: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + filterDefinitionId: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + FilterDefinitionID: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + modifiedDate: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + name: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + Name: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + sourceObjectId: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + SourceObjectID: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + sourceTypeId: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + SourceTypeID: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + filterDefinitionSourceTypeId: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + statusId: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + resultDEName: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + resultDEKey: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + resultDEDescription: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + r__folder_Path: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + r__dataFilter_key: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + r__source_dataExtension_key: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + r__destination_dataExtension_key: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + }; + }; +} +import MetadataType from './MetadataType.js'; +//# sourceMappingURL=Filter.d.ts.map \ No newline at end of file diff --git a/@types/lib/metadataTypes/Filter.d.ts.map b/@types/lib/metadataTypes/Filter.d.ts.map new file mode 100644 index 000000000..8e18ef5cc --- /dev/null +++ b/@types/lib/metadataTypes/Filter.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"Filter.d.ts","sourceRoot":"","sources":["../../../lib/metadataTypes/Filter.js"],"names":[],"mappings":";uBAea,OAAO,wBAAwB,EAAE,QAAQ;0BACzC,OAAO,wBAAwB,EAAE,WAAW;8BAC5C,OAAO,wBAAwB,EAAE,eAAe;+BAChD,OAAO,wBAAwB,EAAE,gBAAgB;mCACjD,OAAO,wBAAwB,EAAE,oBAAoB;kCACrD,OAAO,wBAAwB,EAAE,mBAAmB;8BACpD,OAAO,wBAAwB,EAAE,eAAe;iCAChD,OAAO,wBAAwB,EAAE,kBAAkB;gCACnD,OAAO,wBAAwB,EAAE,iBAAiB;0BAClD,OAAO,wBAAwB,EAAE,WAAW;yBAC5C,OAAO,wBAAwB,EAAE,UAAU;AAXxD;;;;;;;;;;;;GAYG;AAEH;;;;GAIG;AACH;IACI;;;;;;;;;;;OAWG;IACH,6BANW,MAAM,MACN,IAAI,GAAG,MAAM,EAAE,OACf,IAAI,GAAG,MAAM,EAAE,QACf,MAAM,GACJ,OAAO,CAAE,kBAAkB,CAAC,CAKxC;IACD;;;;;OAKG;IACH,mCAHW,UAAU,GACR,UAAU,CAoCtB;IAED;;;;;OAKG;IACH,6CAHW,QAAQ,GAAC,aAAa,YACtB,UAAU,QA4CpB;IACD;;;;;;OAMG;IACH,0CAJW,QAAQ,GAAC,aAAa,YACtB,UAAU,iBACV,UAAU,QA8CpB;IAED;;;;;;OAMG;IACH,oBAHW,UAAU,gBAiBpB;IAED;;;;;OAKG;IACH,+BAHW,UAAU,GACR,MAAM,CAclB;IAED;;;;;;OAMG;IACH,iCAJW,UAAU,YACV,MAAM,GACJ,OAAO,CAAE,UAAU,CAAC,CAiBhC;IAED;;;;;OAKG;IACH,oBAHW,gBAAgB,gBAK1B;IAED;;;;;OAKG;IACH,gCAHW,UAAU,GACR,OAAO,CAAE,UAAU,CAAC,CAyChC;IAED;;;;;;OAMG;IACH,6CAUC;CAiBJ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;yBA9VwB,mBAAmB"} \ No newline at end of file diff --git a/@types/lib/metadataTypes/FilterDefinition.d.ts b/@types/lib/metadataTypes/FilterDefinition.d.ts new file mode 100644 index 000000000..640659c52 --- /dev/null +++ b/@types/lib/metadataTypes/FilterDefinition.d.ts @@ -0,0 +1,318 @@ +export default FilterDefinition; +export type BuObject = import("../../types/mcdev.d.js").BuObject; +export type CodeExtract = import("../../types/mcdev.d.js").CodeExtract; +export type CodeExtractItem = import("../../types/mcdev.d.js").CodeExtractItem; +export type MetadataTypeItem = import("../../types/mcdev.d.js").MetadataTypeItem; +export type MetadataTypeItemDiff = import("../../types/mcdev.d.js").MetadataTypeItemDiff; +export type MetadataTypeItemObj = import("../../types/mcdev.d.js").MetadataTypeItemObj; +export type MetadataTypeMap = import("../../types/mcdev.d.js").MetadataTypeMap; +export type MetadataTypeMapObj = import("../../types/mcdev.d.js").MetadataTypeMapObj; +export type SoapRequestParams = import("../../types/mcdev.d.js").SoapRequestParams; +export type TemplateMap = import("../../types/mcdev.d.js").TemplateMap; +export type FilterDefinitionItem = import("../../types/mcdev.d.js").FilterDefinitionItem; +export type FilterDefinitionMap = import("../../types/mcdev.d.js").FilterDefinitionMap; +export type MultiMetadataTypeMap = import("../../types/mcdev.d.js").MultiMetadataTypeMap; +export type FilterConditionSet = import("../../types/mcdev.d.js").FilterConditionSet; +export type FilterCondition = import("../../types/mcdev.d.js").FilterCondition; +/** + * @typedef {import('../../types/mcdev.d.js').BuObject} BuObject + * @typedef {import('../../types/mcdev.d.js').CodeExtract} CodeExtract + * @typedef {import('../../types/mcdev.d.js').CodeExtractItem} CodeExtractItem + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItem} MetadataTypeItem + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItemDiff} MetadataTypeItemDiff + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItemObj} MetadataTypeItemObj + * @typedef {import('../../types/mcdev.d.js').MetadataTypeMap} MetadataTypeMap + * @typedef {import('../../types/mcdev.d.js').MetadataTypeMapObj} MetadataTypeMapObj + * @typedef {import('../../types/mcdev.d.js').SoapRequestParams} SoapRequestParams + * @typedef {import('../../types/mcdev.d.js').TemplateMap} TemplateMap + * @typedef {import('../../types/mcdev.d.js').FilterDefinitionItem} FilterDefinitionItem + * @typedef {import('../../types/mcdev.d.js').FilterDefinitionMap} FilterDefinitionMap + * @typedef {import('../../types/mcdev.d.js').MultiMetadataTypeMap} MultiMetadataTypeMap + * @typedef {import('../../types/mcdev.d.js').FilterConditionSet} FilterConditionSet + * @typedef {import('../../types/mcdev.d.js').FilterCondition} FilterCondition + */ +/** + * FilterDefinition MetadataType + * + * @augments MetadataType + */ +declare class FilterDefinition extends MetadataType { + static cache: {}; + static deIdKeyMap: any; + static hidden: boolean; + /** + * Retrieves all records and saves it to disk + * + * @param {string} retrieveDir Directory where retrieved metadata directory will be saved + * @param {string[]} [_] unused parameter + * @param {string[]} [__] unused parameter + * @param {string} [key] customer key of single item to retrieve + * @returns {Promise.<{metadata: FilterDefinitionMap, type: string}>} Promise of items + */ + static retrieve(retrieveDir: string, _?: string[], __?: string[], key?: string): Promise<{ + metadata: FilterDefinitionMap; + type: string; + }>; + /** + * helper for {@link FilterDefinition.retrieve} + * + * @param {boolean} [recached] indicates if this is a recursive call after cache refresh + * @returns {Promise.<number[]>} Array of folder IDs + */ + static _getFilterFolderIds(recached?: boolean): Promise<number[]>; + /** + * helper for {@link FilterDefinition._cacheMeasures} + * + * @returns {Promise.<number[]>} Array of folder IDs + */ + static _getMeasureFolderIds(): Promise<number[]>; + /** + * helper for {@link FilterDefinition.retrieve}. uses cached dataExtensions to resolve dataExtensionFields + * + * @param {FilterDefinitionMap} metadataTypeMap - + * @param {'retrieve'|'deploy'} [mode] - + */ + static _cacheDeFields(metadataTypeMap: FilterDefinitionMap, mode?: "retrieve" | "deploy"): Promise<void>; + /** + * helper for {@link FilterDefinition.retrieve} + * + * @param {FilterDefinitionMap} metadataTypeMap - + */ + static _cacheContactAttributes(metadataTypeMap: FilterDefinitionMap): Promise<void>; + /** + * helper for {@link FilterDefinition.retrieve} + * + * @param {FilterDefinitionMap} metadataTypeMap - + */ + static _cacheMeasures(metadataTypeMap: FilterDefinitionMap): Promise<void>; + /** + * Retrieves all records for caching + * + * @returns {Promise.<{metadata: FilterDefinitionMap, type: string}>} Promise of items + */ + static retrieveForCache(): Promise<{ + metadata: FilterDefinitionMap; + type: string; + }>; + /** + * parses retrieved Metadata before saving + * + * @param {FilterDefinitionItem} metadata a single record + * @returns {Promise.<FilterDefinitionItem>} parsed metadata definition + */ + static postRetrieveTasks(metadata: FilterDefinitionItem): Promise<FilterDefinitionItem>; + /** + * helper for {@link postRetrieveTasks} + * + * @param {FilterDefinitionItem} metadata - + * @param {'postRetrieve'|'preDeploy'} mode - + * @param {object[]} [fieldCache] - + * @param {FilterConditionSet} [filter] - + * @returns {void} + */ + static _resolveFields(metadata: FilterDefinitionItem, mode: "postRetrieve" | "preDeploy", fieldCache?: object[], filter?: FilterConditionSet): void; + /** + * helper for {@link _resolveFields} + * + * @param {FilterCondition} condition - + * @param {object[]} fieldCache - + * @returns {void} + */ + static _postRetrieve_resolveFieldIdsCondition(condition: FilterCondition, fieldCache: object[]): void; + /** + * helper for {@link _resolveFields} + * + * @param {FilterCondition} condition - + * @param {object[]} fieldCache - + * @returns {void} + */ + static _preDeploy_resolveFieldNamesCondition(condition: FilterCondition, fieldCache: object[]): void; + /** + * helper for {@link postRetrieveTasks} + * + * @param {FilterDefinitionItem} metadata - + * @param {object} [filter] - + * @returns {void} + */ + static _postRetrieve_resolveAttributeIds(metadata: FilterDefinitionItem, filter?: object): void; + /** + * prepares a item for deployment + * + * @param {FilterDefinitionItem} metadata a single record + * @returns {Promise.<FilterDefinitionItem>} Promise of updated single item + */ + static preDeployTasks(metadata: FilterDefinitionItem): Promise<FilterDefinitionItem>; + /** + * Creates a single item + * + * @param {FilterDefinitionItem} metadata a single item + * @returns {Promise.<FilterDefinitionItem>} Promise + */ + static create(metadata: FilterDefinitionItem): Promise<FilterDefinitionItem>; + /** + * Updates a single item + * + * @param {FilterDefinitionItem} metadata a single item + * @returns {Promise.<FilterDefinitionItem>} Promise + */ + static update(metadata: FilterDefinitionItem): Promise<FilterDefinitionItem>; + /** + * helper to allow us to select single metadata entries via REST + * + * @private + * @param {string} key customer key + * @returns {Promise.<string>} objectId or enpty string + */ + private static _getObjectIdForSingleRetrieve; +} +declare namespace FilterDefinition { + let dataExtensionFieldCache: { + [x: string]: import("../../types/mcdev.d.js").DataExtensionFieldItem; + }; + let definition: { + bodyIteratorField: string; + dependencies: string[]; + dependencyGraph: { + dataExtension: string[]; + }; + filter: {}; + hasExtended: boolean; + idField: string; + keyField: string; + nameField: string; + folderType: string; + folderIdField: string; + createdDateField: string; + createdNameField: string; + lastmodDateField: string; + lastmodNameField: string; + restPagination: boolean; + restPageSize: number; + type: string; + soapType: string; + typeDescription: string; + typeRetrieveByDefault: boolean; + typeName: string; + fields: { + id: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + key: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + createdDate: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + createdBy: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + createdByName: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + lastUpdated: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + lastUpdatedBy: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + lastUpdatedByName: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + name: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + categoryId: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + description: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + filterDefinitionXml: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + derivedFromType: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + derivedFromObjectId: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + derivedFromObjectTypeName: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + derivedFromObjectName: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + isSendable: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + r__source_dataExtension_key: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + c__filterDefinition: { + skipValidation: boolean; + }; + r__folder_Path: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + }; + }; +} +import MetadataType from './MetadataType.js'; +//# sourceMappingURL=FilterDefinition.d.ts.map \ No newline at end of file diff --git a/@types/lib/metadataTypes/FilterDefinition.d.ts.map b/@types/lib/metadataTypes/FilterDefinition.d.ts.map new file mode 100644 index 000000000..9240900f0 --- /dev/null +++ b/@types/lib/metadataTypes/FilterDefinition.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"FilterDefinition.d.ts","sourceRoot":"","sources":["../../../lib/metadataTypes/FilterDefinition.js"],"names":[],"mappings":";uBAUa,OAAO,wBAAwB,EAAE,QAAQ;0BACzC,OAAO,wBAAwB,EAAE,WAAW;8BAC5C,OAAO,wBAAwB,EAAE,eAAe;+BAChD,OAAO,wBAAwB,EAAE,gBAAgB;mCACjD,OAAO,wBAAwB,EAAE,oBAAoB;kCACrD,OAAO,wBAAwB,EAAE,mBAAmB;8BACpD,OAAO,wBAAwB,EAAE,eAAe;iCAChD,OAAO,wBAAwB,EAAE,kBAAkB;gCACnD,OAAO,wBAAwB,EAAE,iBAAiB;0BAClD,OAAO,wBAAwB,EAAE,WAAW;mCAC5C,OAAO,wBAAwB,EAAE,oBAAoB;kCACrD,OAAO,wBAAwB,EAAE,mBAAmB;mCACpD,OAAO,wBAAwB,EAAE,oBAAoB;iCACrD,OAAO,wBAAwB,EAAE,kBAAkB;8BACnD,OAAO,wBAAwB,EAAE,eAAe;AAf7D;;;;;;;;;;;;;;;;GAgBG;AAEH;;;;GAIG;AACH;IACI,iBAAkB;IAClB,uBAAkB;IAClB,uBAAsB;IACtB;;;;;;;;OAQG;IACH,6BANW,MAAM,MACN,MAAM,EAAE,OACR,MAAM,EAAE,QACR,MAAM,GACJ,OAAO,CAAE;QAAC,QAAQ,EAAE,mBAAmB,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAC,CAAC,CAiDnE;IACD;;;;;OAKG;IACH,sCAHW,OAAO,GACL,OAAO,CAAE,MAAM,EAAE,CAAC,CA+B9B;IACD;;;;OAIG;IACH,+BAFa,OAAO,CAAE,MAAM,EAAE,CAAC,CA2B9B;IAED;;;;;OAKG;IACH,uCAHW,mBAAmB,SACnB,UAAU,GAAC,QAAQ,iBA0D7B;IACD;;;;OAIG;IACH,gDAFW,mBAAmB,iBAkB7B;IACD;;;;OAIG;IACH,uCAFW,mBAAmB,iBA6B7B;IAED;;;;OAIG;IACH,2BAFa,OAAO,CAAE;QAAC,QAAQ,EAAE,mBAAmB,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAC,CAAC,CAInE;IAED;;;;;OAKG;IACH,mCAHW,oBAAoB,GAClB,OAAO,CAAE,oBAAoB,CAAC,CA4F1C;IAED;;;;;;;;OAQG;IACH,gCANW,oBAAoB,QACpB,cAAc,GAAC,WAAW,eAC1B,MAAM,EAAE,WACR,kBAAkB,GAChB,IAAI,CAiChB;IACD;;;;;;OAMG;IACH,yDAJW,eAAe,cACf,MAAM,EAAE,GACN,IAAI,CAYhB;IACD;;;;;;OAMG;IACH,wDAJW,eAAe,cACf,MAAM,EAAE,GACN,IAAI,CAgBhB;IACD;;;;;;OAMG;IACH,mDAJW,oBAAoB,WACpB,MAAM,GACJ,IAAI,CAiChB;IAED;;;;;OAKG;IACH,gCAHW,oBAAoB,GAClB,OAAO,CAAE,oBAAoB,CAAC,CAuC1C;IAeD;;;;;OAKG;IACH,wBAHW,oBAAoB,GAClB,OAAO,CAAE,oBAAoB,CAAC,CAK1C;IACD;;;;;OAKG;IACH,wBAHW,oBAAoB,GAClB,OAAO,CAAE,oBAAoB,CAAC,CAQ1C;IAED;;;;;;OAMG;IACH,6CAUC;CAiBJ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;yBA9mBwB,mBAAmB"} \ No newline at end of file diff --git a/@types/lib/metadataTypes/FilterDefinitionHidden.d.ts b/@types/lib/metadataTypes/FilterDefinitionHidden.d.ts new file mode 100644 index 000000000..9249a43f9 --- /dev/null +++ b/@types/lib/metadataTypes/FilterDefinitionHidden.d.ts @@ -0,0 +1,156 @@ +export default FilterDefinitionHidden; +/** + * FilterDefinitionHidden MetadataType + * + * @augments FilterDefinition + */ +declare class FilterDefinitionHidden extends FilterDefinition { +} +declare namespace FilterDefinitionHidden { + let definition: { + bodyIteratorField: string; + dependencies: string[]; + dependencyGraph: { + dataExtension: string[]; + }; + filter: {}; + hasExtended: boolean; + idField: string; + keyField: string; + nameField: string; + folderType: string; + folderIdField: string; + createdDateField: string; + createdNameField: string; + lastmodDateField: string; + lastmodNameField: string; + restPagination: boolean; + restPageSize: number; + type: string; + soapType: string; + typeDescription: string; + typeRetrieveByDefault: boolean; + typeName: string; + fields: { + id: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + key: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + createdDate: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + createdBy: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + createdByName: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + lastUpdated: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + lastUpdatedBy: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + lastUpdatedByName: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + name: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + categoryId: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + description: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + filterDefinitionXml: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + derivedFromType: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + derivedFromObjectId: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + derivedFromObjectTypeName: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + derivedFromObjectName: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + isSendable: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + r__source_dataExtension_key: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + c__filterDefinition: { + skipValidation: boolean; + }; + r__folder_Path: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + }; + }; +} +import FilterDefinition from './FilterDefinition.js'; +//# sourceMappingURL=FilterDefinitionHidden.d.ts.map \ No newline at end of file diff --git a/@types/lib/metadataTypes/FilterDefinitionHidden.d.ts.map b/@types/lib/metadataTypes/FilterDefinitionHidden.d.ts.map new file mode 100644 index 000000000..be296aadd --- /dev/null +++ b/@types/lib/metadataTypes/FilterDefinitionHidden.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"FilterDefinitionHidden.d.ts","sourceRoot":"","sources":["../../../lib/metadataTypes/FilterDefinitionHidden.js"],"names":[],"mappings":";AAKA;;;;GAIG;AACH;CAEC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;6BAT4B,uBAAuB"} \ No newline at end of file diff --git a/@types/lib/metadataTypes/Folder.d.ts b/@types/lib/metadataTypes/Folder.d.ts new file mode 100644 index 000000000..fba565191 --- /dev/null +++ b/@types/lib/metadataTypes/Folder.d.ts @@ -0,0 +1,339 @@ +export default Folder; +export type BuObject = import("../../types/mcdev.d.js").BuObject; +export type CodeExtract = import("../../types/mcdev.d.js").CodeExtract; +export type CodeExtractItem = import("../../types/mcdev.d.js").CodeExtractItem; +export type MetadataTypeItem = import("../../types/mcdev.d.js").MetadataTypeItem; +export type MetadataTypeItemDiff = import("../../types/mcdev.d.js").MetadataTypeItemDiff; +export type MetadataTypeItemObj = import("../../types/mcdev.d.js").MetadataTypeItemObj; +export type MetadataTypeMap = import("../../types/mcdev.d.js").MetadataTypeMap; +export type MetadataTypeMapObj = import("../../types/mcdev.d.js").MetadataTypeMapObj; +export type SoapRequestParams = import("../../types/mcdev.d.js").SoapRequestParams; +export type TemplateMap = import("../../types/mcdev.d.js").TemplateMap; +export type ListItem = import("../../types/mcdev.d.js").ListItem; +export type ListMap = import("../../types/mcdev.d.js").ListMap; +export type ListIdMap = import("../../types/mcdev.d.js").ListIdMap; +/** + * @typedef {import('../../types/mcdev.d.js').BuObject} BuObject + * @typedef {import('../../types/mcdev.d.js').CodeExtract} CodeExtract + * @typedef {import('../../types/mcdev.d.js').CodeExtractItem} CodeExtractItem + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItem} MetadataTypeItem + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItemDiff} MetadataTypeItemDiff + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItemObj} MetadataTypeItemObj + * @typedef {import('../../types/mcdev.d.js').MetadataTypeMap} MetadataTypeMap + * @typedef {import('../../types/mcdev.d.js').MetadataTypeMapObj} MetadataTypeMapObj + * @typedef {import('../../types/mcdev.d.js').SoapRequestParams} SoapRequestParams + * @typedef {import('../../types/mcdev.d.js').TemplateMap} TemplateMap + * + * @typedef {import('../../types/mcdev.d.js').ListItem} ListItem + * @typedef {import('../../types/mcdev.d.js').ListMap} ListMap + * @typedef {import('../../types/mcdev.d.js').ListIdMap} ListIdMap + */ +/** + * Folder MetadataType + * + * @augments MetadataType + */ +declare class Folder extends MetadataType { + /** + * Retrieves metadata of metadata type into local filesystem. executes callback with retrieved metadata + * + * @param {string} retrieveDir Directory where retrieved metadata directory will be saved + * @param {string[]} [additionalFields] Returns specified fields even if their retrieve definition is not set to true + * @param {string[]} [subTypeArr] content type of folder + * @param {string} [key] customer key of single item to retrieve + * @returns {Promise.<{metadata: ListMap, type: string}>} Promise + */ + static retrieve(retrieveDir: string, additionalFields?: string[], subTypeArr?: string[], key?: string): Promise<{ + metadata: ListMap; + type: string; + }>; + /** + * Retrieves folder metadata for caching + * + * @param {void | string[]} [_] parameter not used + * @param {string[]} [subTypeArr] content type of folder + * @returns {Promise.<{metadata: ListMap, type: string}>} Promise + */ + static retrieveForCache(_?: void | string[], subTypeArr?: string[]): Promise<{ + metadata: ListMap; + type: string; + }>; + /** + * Folder upsert (copied from Metadata Upsert), after retrieving from target + * and comparing to check if create or update operation is needed. + * Copied due to having a dependency on itself, meaning the created need to be serial + * + * @param {ListMap} metadata metadata mapped by their keyField + * @returns {Promise.<ListMap>} Promise of saved metadata + */ + static upsert(metadata: ListMap): Promise<ListMap>; + /** + * creates a folder based on metatadata + * + * @param {ListItem} metadataEntry metadata of the folder + * @returns {Promise.<any>} Promise of api response + */ + static create(metadataEntry: ListItem): Promise<any>; + /** + * Updates a single Folder. + * + * @param {MetadataTypeItem} metadataEntry single metadata entry + * @returns {Promise.<any>} Promise of api response + */ + static update(metadataEntry: MetadataTypeItem): Promise<any>; + /** + * prepares a folder for deployment + * + * @param {ListItem} metadata a single folder definition + * @returns {Promise.<ListItem>} Promise of parsed folder metadata + */ + static preDeployTasks(metadata: ListItem): Promise<ListItem>; + /** + * Returns file contents mapped to their filename without '.json' ending + * + * @param {string} dir directory with json files, e.g. /retrieve/cred/bu/folder, /deploy/cred/bu/folder, /template/folder + * @param {boolean} [listBadKeys] do not print errors, used for badKeys() + * @returns {Promise.<ListMap>} fileName => fileContent map + */ + static getJsonFromFS(dir: string, listBadKeys?: boolean): Promise<ListMap>; + /** + * Helper to retrieve the folders as promise + * + * @param {string[]} [additionalFields] Returns specified fields even if their retrieve definition is not set to true + * @param {boolean} [queryAllAccounts] which queryAllAccounts setting to use + * @param {string[]} [contentTypeList] content type of folder + * @returns {Promise.<ListItem[]>} soap object + */ + static retrieveHelper(additionalFields?: string[], queryAllAccounts?: boolean, contentTypeList?: string[]): Promise<ListItem[]>; + /** + * Gets executed after retreive of metadata type + * + * @param {ListItem} metadata metadata mapped by their keyField + * @returns {ListItem} cloned metadata + */ + static postRetrieveTasks(metadata: ListItem): ListItem; + /** + * Helper for writing Metadata to disk, used for Retrieve and deploy + * + * @param {ListMap} results metadata results from deploy + * @param {string} retrieveDir directory where metadata should be stored after deploy/retrieve + * @returns {Promise.<ListMap>} Promise of saved metadata + */ + static saveResults(results: ListMap, retrieveDir: string): Promise<ListMap>; +} +declare namespace Folder { + let definition: { + bodyIteratorField: string; + dependencies: any[]; + dependencyGraph: any; + subTypes: string[]; + deployFolderTypes: string[]; + deployFolderTypesEmailRest: string[]; + deployFolderTypesAssetRest: string[]; + deployFolderBlacklist: string[]; + folderTypesFromParent: string[]; + hasExtended: boolean; + idField: string; + keepId: boolean; + keyIsFixed: boolean; + keyField: string; + nameField: string; + restPagination: boolean; + type: string; + soapType: string; + typeDescription: string; + typeRetrieveByDefault: boolean; + typeCdpByDefault: boolean; + typeName: string; + fields: { + $: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + '@_xsi:type': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + ID: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'Client.ID': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + CustomerKey: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + Description: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + description: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + CreatedDate: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + ModifiedDate: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + ContentType: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + categoryType: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + catType: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + IsActive: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + IsEditable: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + editable: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + AllowChildren: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + extendable: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + ObjectID: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + objectId: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + Name: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + name: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'ParentFolder.CustomerKey': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'ParentFolder.ID': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + parentCatId: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + parentId: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'ParentFolder.PartnerKey': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'ParentFolder.ObjectID': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'ParentFolder.Path': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + PartnerKey: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + Path: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + _generated: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + }; + }; +} +import MetadataType from './MetadataType.js'; +//# sourceMappingURL=Folder.d.ts.map \ No newline at end of file diff --git a/@types/lib/metadataTypes/Folder.d.ts.map b/@types/lib/metadataTypes/Folder.d.ts.map new file mode 100644 index 000000000..c40254667 --- /dev/null +++ b/@types/lib/metadataTypes/Folder.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"Folder.d.ts","sourceRoot":"","sources":["../../../lib/metadataTypes/Folder.js"],"names":[],"mappings":";uBASa,OAAO,wBAAwB,EAAE,QAAQ;0BACzC,OAAO,wBAAwB,EAAE,WAAW;8BAC5C,OAAO,wBAAwB,EAAE,eAAe;+BAChD,OAAO,wBAAwB,EAAE,gBAAgB;mCACjD,OAAO,wBAAwB,EAAE,oBAAoB;kCACrD,OAAO,wBAAwB,EAAE,mBAAmB;8BACpD,OAAO,wBAAwB,EAAE,eAAe;iCAChD,OAAO,wBAAwB,EAAE,kBAAkB;gCACnD,OAAO,wBAAwB,EAAE,iBAAiB;0BAClD,OAAO,wBAAwB,EAAE,WAAW;uBAE5C,OAAO,wBAAwB,EAAE,QAAQ;sBACzC,OAAO,wBAAwB,EAAE,OAAO;wBACxC,OAAO,wBAAwB,EAAE,SAAS;AAdvD;;;;;;;;;;;;;;;GAeG;AAEH;;;;GAIG;AACH;IACI;;;;;;;;OAQG;IACH,6BANW,MAAM,qBACN,MAAM,EAAE,eACR,MAAM,EAAE,QACR,MAAM,GACJ,OAAO,CAAE;QAAC,QAAQ,EAAE,OAAO,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAC,CAAC,CAgJvD;IAED;;;;;;OAMG;IACH,4BAJW,IAAI,GAAG,MAAM,EAAE,eACf,MAAM,EAAE,GACN,OAAO,CAAE;QAAC,QAAQ,EAAE,OAAO,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAC,CAAC,CAIvD;IAED;;;;;;;OAOG;IACH,wBAHW,OAAO,GACL,OAAO,CAAE,OAAO,CAAC,CA+J7B;IAED;;;;;OAKG;IACH,6BAHW,QAAQ,GACN,OAAO,CAAE,GAAG,CAAC,CAoHzB;IAED;;;;;OAKG;IACH,6BAHW,gBAAgB,GACd,OAAO,CAAE,GAAG,CAAC,CA6EzB;IAED;;;;;OAKG;IACH,gCAHW,QAAQ,GACN,OAAO,CAAE,QAAQ,CAAC,CAgD9B;IAED;;;;;;OAMG;IACH,0BAJW,MAAM,gBACN,OAAO,GACL,OAAO,CAAE,OAAO,CAAC,CAsE7B;IAED;;;;;;;OAOG;IACH,yCALW,MAAM,EAAE,qBACR,OAAO,oBACP,MAAM,EAAE,GACN,OAAO,CAAE,QAAQ,EAAE,CAAC,CA2BhC;IAED;;;;;OAKG;IACH,mCAHW,QAAQ,GACN,QAAQ,CAIpB;IAED;;;;;;OAMG;IACH,4BAJW,OAAO,eACP,MAAM,GACJ,OAAO,CAAE,OAAO,CAAC,CA4D7B;CACJ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;yBAvyBwB,mBAAmB"} \ No newline at end of file diff --git a/@types/lib/metadataTypes/ImportFile.d.ts b/@types/lib/metadataTypes/ImportFile.d.ts new file mode 100644 index 000000000..aba9b07f5 --- /dev/null +++ b/@types/lib/metadataTypes/ImportFile.d.ts @@ -0,0 +1,450 @@ +export default ImportFile; +export type BuObject = import("../../types/mcdev.d.js").BuObject; +export type CodeExtract = import("../../types/mcdev.d.js").CodeExtract; +export type CodeExtractItem = import("../../types/mcdev.d.js").CodeExtractItem; +export type MetadataTypeItem = import("../../types/mcdev.d.js").MetadataTypeItem; +export type MetadataTypeItemDiff = import("../../types/mcdev.d.js").MetadataTypeItemDiff; +export type MetadataTypeItemObj = import("../../types/mcdev.d.js").MetadataTypeItemObj; +export type MetadataTypeMap = import("../../types/mcdev.d.js").MetadataTypeMap; +export type MetadataTypeMapObj = import("../../types/mcdev.d.js").MetadataTypeMapObj; +export type SoapRequestParams = import("../../types/mcdev.d.js").SoapRequestParams; +export type TemplateMap = import("../../types/mcdev.d.js").TemplateMap; +export type SDKError = import("../../types/mcdev.d.js").SDKError; +/** + * @typedef {import('../../types/mcdev.d.js').BuObject} BuObject + * @typedef {import('../../types/mcdev.d.js').CodeExtract} CodeExtract + * @typedef {import('../../types/mcdev.d.js').CodeExtractItem} CodeExtractItem + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItem} MetadataTypeItem + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItemDiff} MetadataTypeItemDiff + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItemObj} MetadataTypeItemObj + * @typedef {import('../../types/mcdev.d.js').MetadataTypeMap} MetadataTypeMap + * @typedef {import('../../types/mcdev.d.js').MetadataTypeMapObj} MetadataTypeMapObj + * @typedef {import('../../types/mcdev.d.js').SoapRequestParams} SoapRequestParams + * @typedef {import('../../types/mcdev.d.js').TemplateMap} TemplateMap + * @typedef {import('../../types/mcdev.d.js').SDKError} SDKError + */ +/** + * ImportFile MetadataType + * + * @augments MetadataType + */ +declare class ImportFile extends MetadataType { + /** + * Retrieves Metadata of Import File. + * Endpoint /automation/v1/imports/ return all Import Files with all details. + * Currently it is not needed to loop over Imports with endpoint /automation/v1/imports/{id} + * + * @param {string} [retrieveDir] Directory where retrieved metadata directory will be saved + * @param {void | string[]} [_] unused parameter + * @param {void | string[]} [__] unused parameter + * @param {string} [key] customer key of single item to retrieve + * @returns {Promise.<MetadataTypeMapObj>} Promise + */ + static retrieve(retrieveDir?: string, _?: void | string[], __?: void | string[], key?: string): Promise<MetadataTypeMapObj>; + /** + * helper for {@link MetadataType.retrieveRESTcollection} + * + * @param {SDKError} ex exception + * @param {string} key id or key of item + * @param {string} url url to call for retry + * @returns {Promise.<any>} can return retry-result + */ + static handleRESTErrors(ex: SDKError, key: string, url: string): Promise<any>; + /** + * Retrieves import definition metadata for caching + * + * @param {void | string[]} [_] parameter not used + * @param {void | string[]} [__] parameter not used + * @param {string} [key] customer key of single item to retrieve + * @returns {Promise.<MetadataTypeMapObj>} Promise + */ + static retrieveForCache(_?: void | string[], __?: void | string[], key?: string): Promise<MetadataTypeMapObj>; + /** + * Retrieve a specific Import Definition by Name + * + * @deprecated Use `retrieve` followed by `build` instead. `retrieveAsTemplate` will be removed in a future version. + * @param {string} templateDir Directory where retrieved metadata directory will be saved + * @param {string} name name of the metadata file + * @param {TemplateMap} templateVariables variables to be replaced in the metadata + * @returns {Promise.<MetadataTypeItemObj>} Promise + */ + static retrieveAsTemplate(templateDir: string, name: string, templateVariables: TemplateMap): Promise<MetadataTypeItemObj>; + /** + * helper to allow us to select single metadata entries via REST + * + * @private + * @param {string} key customer key + * @returns {Promise.<string>} objectId or enpty string + */ + private static _getObjectIdForSingleRetrieve; + /** + * Creates a single Import File + * + * @param {MetadataTypeItem} importFile a single Import File + * @returns {Promise} Promise + */ + static create(importFile: MetadataTypeItem): Promise<any>; + /** + * Updates a single Import File + * + * @param {MetadataTypeItem} importFile a single Import File + * @returns {Promise} Promise + */ + static update(importFile: MetadataTypeItem): Promise<any>; + /** + * prepares a import definition for deployment + * + * @param {MetadataTypeItem} metadata a single importDef + * @returns {Promise.<MetadataTypeItem>} Promise + */ + static preDeployTasks(metadata: MetadataTypeItem): Promise<MetadataTypeItem>; + /** + * manages post retrieve steps + * + * @param {MetadataTypeItem} metadata a single item + * @returns {MetadataTypeItem} parsed metadata + */ + static postRetrieveTasks(metadata: MetadataTypeItem): MetadataTypeItem; +} +declare namespace ImportFile { + let smsImports: {}; + let dataExtensionsLegacy: {}; + let definition: { + bodyIteratorField: string; + dependencies: string[]; + dependencyGraph: { + dataExtension: string[]; + list: string[]; + mobileKeyword: string[]; + }; + destinationObjectTypeMapping: { + unknown: number; + DataExtension: number; + List: number; + SMS: number; + Push: number; + WhatsApp: number; + }; + hasExtended: boolean; + idField: string; + keyIsFixed: boolean; + keyField: string; + nameField: string; + createdDateField: string; + createdNameField: any; + lastmodDateField: string; + lastmodNameField: any; + restPagination: boolean; + restPageSize: number; + restConcurrentLimit: number; + subscriberImportTypeMapping: { + DataExtension: number; + Email: number; + }; + maxKeyLength: number; + type: string; + typeDescription: string; + typeRetrieveByDefault: boolean; + typeCdpByDefault: boolean; + typeName: string; + updateTypeMapping: { + Add: number; + AddUpdate: number; + Overwrite: number; + Update: number; + }; + blankFileProcessingTypeMapping: { + Fail: number; + Process: number; + Skip: number; + }; + fields: { + allowErrors: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + blankFileProcessingType: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + createdDate: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + customerKey: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + dateFormatLocale: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + deleteFile: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + description: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + destinationId: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + destinationName: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + destinationObjectId: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + destinationObjectTypeId: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + encodingName: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + fieldMappingType: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + fieldMappings: { + skipValidation: boolean; + }; + fileNamingPattern: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + fileSpec: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + fileTransferLocationId: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + fileTransferLocationName: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + fileTransferLocationTypeId: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + fileType: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + filter: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + hasColumnHeader: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + importDefinitionId: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + isOrderedImport: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + isSequential: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + maxFileAgeHours: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + maxFileAgeScheduleOffsetHours: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + maxImportFrequencyHours: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + modifiedDate: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + name: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + }; + notificationEmailAddress: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + otherDelimiter: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + sendEmailNotification: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + standardQuotedStrings: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + subscriberImportTypeId: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + updateTypeId: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + sourceCustomObjectId: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + sourceDataExtensionName: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + c__dataAction: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'destination.r__mobileKeyword_key': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'source.r__dataExtension_key': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'destination.r__dataExtension_key': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'source.c__type': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'destination.c__type': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'destination.r__list_PathName': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'source.r__fileLocation_name': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + c__subscriberImportType: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + c__blankFileProcessing: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + }; + }; +} +import MetadataType from './MetadataType.js'; +//# sourceMappingURL=ImportFile.d.ts.map \ No newline at end of file diff --git a/@types/lib/metadataTypes/ImportFile.d.ts.map b/@types/lib/metadataTypes/ImportFile.d.ts.map new file mode 100644 index 000000000..ed5ddd590 --- /dev/null +++ b/@types/lib/metadataTypes/ImportFile.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"ImportFile.d.ts","sourceRoot":"","sources":["../../../lib/metadataTypes/ImportFile.js"],"names":[],"mappings":";uBAQa,OAAO,wBAAwB,EAAE,QAAQ;0BACzC,OAAO,wBAAwB,EAAE,WAAW;8BAC5C,OAAO,wBAAwB,EAAE,eAAe;+BAChD,OAAO,wBAAwB,EAAE,gBAAgB;mCACjD,OAAO,wBAAwB,EAAE,oBAAoB;kCACrD,OAAO,wBAAwB,EAAE,mBAAmB;8BACpD,OAAO,wBAAwB,EAAE,eAAe;iCAChD,OAAO,wBAAwB,EAAE,kBAAkB;gCACnD,OAAO,wBAAwB,EAAE,iBAAiB;0BAClD,OAAO,wBAAwB,EAAE,WAAW;uBAC5C,OAAO,wBAAwB,EAAE,QAAQ;AAXtD;;;;;;;;;;;;GAYG;AAEH;;;;GAIG;AACH;IACI;;;;;;;;;;OAUG;IACH,8BANW,MAAM,MACN,IAAI,GAAG,MAAM,EAAE,OACf,IAAI,GAAG,MAAM,EAAE,QACf,MAAM,GACJ,OAAO,CAAE,kBAAkB,CAAC,CA4DxC;IAED;;;;;;;OAOG;IACH,4BALW,QAAQ,OACR,MAAM,OACN,MAAM,GACJ,OAAO,CAAE,GAAG,CAAC,CAwBzB;IAED;;;;;;;OAOG;IACH,4BALW,IAAI,GAAG,MAAM,EAAE,OACf,IAAI,GAAG,MAAM,EAAE,QACf,MAAM,GACJ,OAAO,CAAE,kBAAkB,CAAC,CAIxC;IAED;;;;;;;;OAQG;IACH,uCALW,MAAM,QACN,MAAM,qBACN,WAAW,GACT,OAAO,CAAE,mBAAmB,CAAC,CAwCzC;IAED;;;;;;OAMG;IACH,6CAeC;IAED;;;;;OAKG;IACH,0BAHW,gBAAgB,gBAK1B;IAED;;;;;OAKG;IACH,0BAHW,gBAAgB,gBAQ1B;IAgCD;;;;;OAKG;IACH,gCAHW,gBAAgB,GACd,OAAO,CAAE,gBAAgB,CAAC,CA0ItC;IAED;;;;;OAKG;IACH,mCAHW,gBAAgB,GACd,gBAAgB,CAwK5B;CAiBJ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;yBAvlBwB,mBAAmB"} \ No newline at end of file diff --git a/@types/lib/metadataTypes/Journey.d.ts b/@types/lib/metadataTypes/Journey.d.ts new file mode 100644 index 000000000..2f113cd1b --- /dev/null +++ b/@types/lib/metadataTypes/Journey.d.ts @@ -0,0 +1,1343 @@ +export default Journey; +export type BuObject = import("../../types/mcdev.d.js").BuObject; +export type CodeExtract = import("../../types/mcdev.d.js").CodeExtract; +export type CodeExtractItem = import("../../types/mcdev.d.js").CodeExtractItem; +export type MetadataTypeItem = import("../../types/mcdev.d.js").MetadataTypeItem; +export type MetadataTypeItemDiff = import("../../types/mcdev.d.js").MetadataTypeItemDiff; +export type MetadataTypeItemObj = import("../../types/mcdev.d.js").MetadataTypeItemObj; +export type MetadataTypeMap = import("../../types/mcdev.d.js").MetadataTypeMap; +export type MetadataTypeMapObj = import("../../types/mcdev.d.js").MetadataTypeMapObj; +export type SoapRequestParams = import("../../types/mcdev.d.js").SoapRequestParams; +export type TemplateMap = import("../../types/mcdev.d.js").TemplateMap; +export type TypeKeyCombo = import("../../types/mcdev.d.js").TypeKeyCombo; +/** + * @typedef {import('../../types/mcdev.d.js').BuObject} BuObject + * @typedef {import('../../types/mcdev.d.js').CodeExtract} CodeExtract + * @typedef {import('../../types/mcdev.d.js').CodeExtractItem} CodeExtractItem + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItem} MetadataTypeItem + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItemDiff} MetadataTypeItemDiff + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItemObj} MetadataTypeItemObj + * @typedef {import('../../types/mcdev.d.js').MetadataTypeMap} MetadataTypeMap + * @typedef {import('../../types/mcdev.d.js').MetadataTypeMapObj} MetadataTypeMapObj + * @typedef {import('../../types/mcdev.d.js').SoapRequestParams} SoapRequestParams + * @typedef {import('../../types/mcdev.d.js').TemplateMap} TemplateMap + * @typedef {import('../../types/mcdev.d.js').TypeKeyCombo} TypeKeyCombo + */ +/** + * Journey MetadataType + * id: A unique id of the journey assigned by the journey’s API during its creation + * key: A unique id of the journey within the MID. Can be generated by the developer + * definitionId: A unique UUID provided by Salesforce Marketing Cloud. Each version of a journey has a unique DefinitionID while the Id and Key remain the same. Version 1 will have id == definitionId + * + * @augments MetadataType + */ +declare class Journey extends MetadataType { + /** + * Retrieves Metadata of Journey + * + * @param {string} retrieveDir Directory where retrieved metadata directory will be saved + * @param {void | string[]} [_] unused parameter + * @param {void | string[]} [__] unused parameter + * @param {string} [key] customer key of single item to retrieve + * @returns {Promise.<MetadataTypeMapObj>} Promise + */ + static retrieve(retrieveDir: string, _?: void | string[], __?: void | string[], key?: string): Promise<MetadataTypeMapObj>; + /** + * Updates a single item + * + * @param {MetadataTypeItem} metadata a single item + * @returns {Promise} Promise + */ + static update(metadata: MetadataTypeItem): Promise<any>; + /** + * Creates a single item + * + * @param {MetadataTypeItem} metadata a single item + * @returns {Promise} Promise + */ + static create(metadata: MetadataTypeItem): Promise<any>; + /** + * helper for Journey's {@link Journey.saveResults}. Gets executed after retreive of metadata type and + * + * @param {MetadataTypeMap} metadataMap key=customer key, value=metadata + */ + static _postRetrieveTasksBulk(metadataMap: MetadataTypeMap): Promise<void>; + /** + * manages post retrieve steps + * + * @param {MetadataTypeItem} metadata a single item + * @returns {Promise.<MetadataTypeItem>} Array with one metadata object + */ + static postRetrieveTasks(metadata: MetadataTypeItem): Promise<MetadataTypeItem>; + /** + * helper for {@link Journey.postRetrieveTasks} + * + * @private + * @param {MetadataTypeItem} metadata a single item + */ + private static _postRetrieveTasks_activities; + /** + * prepares a TSD for deployment + * ! BETA RELEASE of journey support (v4.3.0); it so far only resolves a limited amount of dependencies and will likely break during cross-BU deployments! + * + * @param {MetadataTypeItem} metadata of a single TSD + * @returns {Promise.<MetadataTypeItem>} metadata object + */ + static preDeployTasks(metadata: MetadataTypeItem): Promise<MetadataTypeItem>; + /** + * helper for {@link Journey.preDeployTasks} + * + * @private + * @param {MetadataTypeItem} metadata a single item + */ + private static _preDeployTasks_activities; + /** + * Gets executed after deployment of metadata type + * + * @param {MetadataTypeMap} upsertResults metadata mapped by their keyField as returned by update/create + */ + static postDeployTasks(upsertResults: MetadataTypeMap): Promise<void>; + /** + * a function to publish the journey via API + * + * @param {string[]} keyArr keys or ids of the metadata + * @param {MetadataTypeMap} [upsertResults] metadata mapped by their keyField as returned by update/create; needs to be refreshed after publish + * @returns {Promise.<string[]>} Returns list of updated keys/ids that were published. Success could only be seen with a delay in the UI because the publish-endpoint is async + */ + static publish(keyArr: string[], upsertResults?: MetadataTypeMap): Promise<string[]>; + /** + * + * @param {string[]} executedKeyArr list of journey keys + * @param {number} transactionalCounter how many transactiona-send journeys did we expect to refresh + * @param {number} multiStepCounter how many multi-step journeys did we expect to refresh + * @param {MetadataTypeMap} [upsertResults] metadata mapped by their keyField returned by update/create; needs to be refreshed after publish + * @returns {Promise.<void>} - + */ + static _reRetrieve(executedKeyArr: string[], transactionalCounter: number, multiStepCounter: number, upsertResults?: MetadataTypeMap): Promise<void>; + /** + * helper for {@link Journey.publish} and {@link Journey.validate} + * + * @param {string} statusUrl URL to check the status of the publish request + * @param {string} key journey-key or id for log messages + * @param {string} name journey-name for log messages + * @param {import('yocto-spinner').Spinner} spinner reference to spinner to allow stopping it when done + * @param {number} [tries] number of tries used to check the status + * @returns {Promise.<string>} key of the item that was published successfully + */ + static _checkPublishStatus(statusUrl: string, key: string, name: string, spinner: import("yocto-spinner").Spinner, tries?: number): Promise<string>; + /** + * helper for {@link Journey._checkPublishStatus} + * + * @param {{status:string, errors:Array, warnings:Array}} response publishStatus response + */ + static _showPublishStatusDetails(response: { + status: string; + errors: any[]; + warnings: any[]; + }): void; + /** + * a function to validate the journey via API + * + * @param {string[]} keyArr keys or ids of the metadata + * @returns {Promise.<string[]>} Returns list of updated keys/ids that were published. Success could only be seen with a delay in the UI because the publish-endpoint is async + */ + static validate(keyArr: string[]): Promise<string[]>; + /** + * audit latest or given journey version + * + * @param {string[]} keyArr customerkey of the metadata + * @returns {Promise.<string[]>} Returns list of keys that were paused + */ + static audit(keyArr: string[]): Promise<string[]>; + /** + * TSD-specific refresh method that finds active TSDs and refreshes them + * + * @param {string[]} keyArr metadata keys + * @param {boolean} [_] whether to check if the key is valid + * @param {MetadataTypeMap} [upsertResults] metadata mapped by their keyField as returned by update/create; needs to be refreshed after publish + * @returns {Promise.<string[]>} Returns list of keys that were refreshed + */ + static refresh(keyArr: string[], _?: boolean, upsertResults?: MetadataTypeMap): Promise<string[]>; + /** + * helper for {@link Journey.refresh} that pauses, publishes and starts a triggered send + * + * @param {string} key external key of triggered send item + * @param {MetadataTypeMapObj} journeyCache metadata cache + * @returns {Promise.<boolean>} true if refresh was successful + */ + static _refreshItem(key: string, journeyCache: MetadataTypeMapObj): Promise<boolean>; +} +declare namespace Journey { + let definition: { + folderType: string; + bodyIteratorField: string; + dependencies: string[]; + dependencyGraph: { + event: string[]; + dataExtension: string[]; + deliveryProfile: string[]; + list: string[]; + senderProfile: string[]; + sendClassification: string[]; + asset: string[]; + mobileMessage: string[]; + mobileKeyword: string[]; + mobileCode: string[]; + }; + folderIdField: string; + hasExtended: boolean; + idField: string; + keyIsFixed: boolean; + keyField: string; + nameField: string; + createdDateField: string; + createdNameField: any; + lastmodDateField: string; + lastmodNameField: any; + restPagination: boolean; + restPageSize: number; + maxKeyLength: number; + type: string; + typeDescription: string; + typeRetrieveByDefault: boolean; + typeCdpByDefault: boolean; + typeName: string; + priorityMapping: { + High: number; + Medium: number; + Low: number; + }; + fields: { + activities: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'activities[].id': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'activities[].key': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'activities[].name': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'activities[].description': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'activities[].type': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'activities[].outcomes': { + skipValidation: boolean; + }; + 'activities[].arguments': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'activities[].arguments.waitEndDateAttributeDataBound': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'activities[].arguments.waitDefinitionId': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'activities[].arguments.waitForEventId': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'activities[].arguments.executionMode': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'activities[].arguments.startActivityKey': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'activities[].arguments.waitQueueId': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'activities[].arguments.activityId': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'activities[].arguments.definitionId': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'activities[].arguments.emailSubjectDataBound': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'activities[].arguments.contactId': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'activities[].arguments.contactKey': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'activities[].arguments.emailAddress': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'activities[].arguments.sourceCustomObjectId': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'activities[].arguments.sourceCustomObjectKey': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'activities[].arguments.fieldType': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'activities[].arguments.eventData': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'activities[].arguments.obfuscationProperties': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'activities[].arguments.customObjectKey': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'activities[].arguments.definitionInstanceId': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'activities[].arguments.filterResult': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'activities[].arguments.version': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'activities[].arguments.requestObjectId': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'activities[].arguments.activityData': { + skipValidation: boolean; + }; + 'activities[].arguments.objectMap': { + skipValidation: boolean; + }; + 'activities[].configurationArguments': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'activities[].configurationArguments.isReconcilable': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'activities[].configurationArguments.isActivityBatchValidated': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'activities[].configurationArguments.triggeredSendKey': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'activities[].configurationArguments.triggeredSendId': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'activities[].configurationArguments.triggeredSend': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'activities[].configurationArguments.triggeredSend.id': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'activities[].configurationArguments.triggeredSend.key': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'activities[].configurationArguments.triggeredSend.campaigns': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'activities[].configurationArguments.triggeredSend.suppressionLists': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'activities[].configurationArguments.triggeredSend.autoAddSubscribers': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'activities[].configurationArguments.triggeredSend.autoUpdateSubscribers': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'activities[].configurationArguments.triggeredSend.bccEmail': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'activities[].configurationArguments.triggeredSend.categoryId': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'activities[].configurationArguments.triggeredSend.ccEmail': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'activities[].configurationArguments.triggeredSend.created': { + skipValidation: boolean; + }; + 'activities[].configurationArguments.triggeredSend.description': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'activities[].configurationArguments.triggeredSend.domainExclusions': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'activities[].configurationArguments.triggeredSend.dynamicEmailSubject': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'activities[].configurationArguments.triggeredSend.emailSubject': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'activities[].configurationArguments.triggeredSend.exclusionFilter': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'activities[].configurationArguments.triggeredSend.isSalesforceTracking': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'activities[].configurationArguments.triggeredSend.isMultipart': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'activities[].configurationArguments.triggeredSend.isSendLogging': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'activities[].configurationArguments.triggeredSend.isStoppedOnJobError': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'activities[].configurationArguments.triggeredSend.keyword': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'activities[].configurationArguments.triggeredSend.modified': { + skipValidation: boolean; + }; + 'activities[].configurationArguments.triggeredSend.name': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'activities[].configurationArguments.triggeredSend.preHeader': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'activities[].configurationArguments.triggeredSend.replyToAddress': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'activities[].configurationArguments.triggeredSend.replyToDisplayName': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'activities[].configurationArguments.triggeredSend.suppressTracking': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'activities[].configurationArguments.triggeredSend.triggeredSendStatus': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'activities[].configurationArguments.triggeredSend.version': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'activities[].configurationArguments.triggeredSend.throttleOpens': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'activities[].configurationArguments.triggeredSend.throttleCloses': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'activities[].configurationArguments.triggeredSend.throttleLimit': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'activities[].configurationArguments.triggeredSend.isTrackingClicks': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'activities[].configurationArguments.triggeredSend.emailId': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'activities[].configurationArguments.triggeredSend.r__triggeredSend_key': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'activities[].configurationArguments.triggeredSend.senderProfileId': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'activities[].configurationArguments.triggeredSend.deliveryProfileId': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'activities[].configurationArguments.triggeredSend.r__senderProfile_key': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'activities[].configurationArguments.triggeredSend.sendClassificationId': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'activities[].configurationArguments.triggeredSend.r__deliveryProfile_key': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'activities[].configurationArguments.triggeredSend.r__sendClassification_key': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'activities[].configurationArguments.triggeredSend.r__list_PathName': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'activities[].configurationArguments.triggeredSend.publicationListId': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'activities[].configurationArguments.triggeredSend.r__list_PathName.publicationList': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'activities[].configurationArguments.triggeredSend.r__list_PathName.suppressionLists': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'activities[].configurationArguments.triggeredSend.r__dataExtension_key': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'activities[].configurationArguments.triggeredSend.r__dataExtension_key.domainExclusions': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'activities[].configurationArguments.triggeredSend.priority': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'activities[].configurationArguments.triggeredSend.c__priority': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'activities[].configurationArguments.triggeredSend.r__asset_name_readOnly': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'activities[].configurationArguments.triggeredSend.r__asset_key': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'activities[].configurationArguments.triggeredSend.updateSubscriber': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'activities[].configurationArguments.applicationExtensionKey': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'activities[].configurationArguments.r__transactionalEmail_key': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'activities[].configurationArguments.applicationExtensionId': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'activities[].configurationArguments.isModified': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'activities[].configurationArguments.isSimulation': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'activities[].configurationArguments.googleAnalyticsCampaignName': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'activities[].configurationArguments.useLLTS': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'activities[].configurationArguments.fuelAgentRequested': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'activities[].configurationArguments.r__triggeredSend_key': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'activities[].configurationArguments.waitDuration': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'activities[].configurationArguments.waitUnit': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'activities[].configurationArguments.specifiedTime': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'activities[].configurationArguments.timeZone': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'activities[].configurationArguments.description': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'activities[].configurationArguments.waitEndDateAttributeExpression': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'activities[].configurationArguments.specificDate': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'activities[].configurationArguments.waitForEventKey': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'activities[].configurationArguments.schemaVersionId': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'activities[].configurationArguments.criteria': { + skipValidation: boolean; + }; + 'activities[].configurationArguments.eventDataConfig': { + skipValidation: boolean; + }; + 'activities[].metaData': { + skipValidation: boolean; + }; + 'activities[].schema': { + skipValidation: boolean; + }; + 'activities[].arguments.activityData.updateContactFields[].r__dataExtension_key': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'activities[].arguments.activityData.updateContactFields[].r__dataExtensionField_name': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'activities[].arguments.activityData.updateContactFields[].field': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + categoryId: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + channel: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + createdDate: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'defaults.email': { + skipValidation: boolean; + }; + 'defaults.mobileNumber': { + skipValidation: boolean; + }; + 'defaults.properties.analyticsTracking.enabled': { + isCreateable: any; + isUpdateable: any; + retrieving: any; + template: any; + }; + 'defaults.properties': { + skipValidation: boolean; + }; + 'defaults.properties.analyticsTracking.analyticsType': { + isCreateable: any; + isUpdateable: any; + retrieving: any; + template: any; + }; + 'defaults.properties.analyticsTracking.urlDomainsToTrack': { + isCreateable: any; + isUpdateable: any; + retrieving: any; + template: any; + }; + definitionId: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + definitionType: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + description: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + entryMode: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + executionMode: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + exits: { + skipValidation: boolean; + }; + goals: { + skipValidation: boolean; + }; + healthStats: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + id: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + key: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + lastPublishedDate: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'metaData.templateId': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + modifiedDate: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + name: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + scheduledStatus: { + isCreateable: any; + isUpdateable: any; + retrieving: any; + template: any; + }; + stats: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + status: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + triggers: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'triggers[].id': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'triggers[].key': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'triggers[].name': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'triggers[].description': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'triggers[].type': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'triggers[].outcomes': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'triggers[].arguments': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'triggers[].arguments.startActivityKey': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'triggers[].arguments.dequeueReason': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'triggers[].arguments.lastExecutedActivityKey': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'triggers[].arguments.filterResult': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'triggers[].arguments.serializedObjectType': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'triggers[].arguments.eventDefinitionId': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'triggers[].arguments.eventDefinitionKey': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'triggers[].arguments.dataExtensionId': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'triggers[].arguments.automationId': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'triggers[].arguments.r__event_key': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'triggers[].arguments.r__dataExtension_key': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'triggers[].configurationArguments': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'triggers[].configurationArguments.eventDataConfig': { + skipValidation: boolean; + }; + 'triggers[].configurationArguments.primaryObjectFilterCriteria': { + skipValidation: boolean; + }; + 'triggers[].configurationArguments.relatedObjectFilterCriteria': { + skipValidation: boolean; + }; + 'triggers[].configurationArguments.salesforceTriggerCriteria': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'triggers[].configurationArguments.objectApiName': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'triggers[].configurationArguments.objectAPIName': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'triggers[].configurationArguments.version': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'triggers[].configurationArguments.contactKey': { + skipValidation: boolean; + }; + 'triggers[].configurationArguments.contactPersonType': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'triggers[].configurationArguments.primaryObjectFilterSummary': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'triggers[].configurationArguments.relatedObjectFilterSummary': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'triggers[].configurationArguments.eventDataSummary': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'triggers[].configurationArguments.evaluationCriteriaSummary': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'triggers[].configurationArguments.applicationExtensionKey': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'triggers[].configurationArguments.passThroughArgument': { + skipValidation: boolean; + }; + 'triggers[].configurationArguments.filterDefinitionId': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'triggers[].configurationArguments.criteria': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'triggers[].configurationArguments.schemaVersionId': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'triggers[].configurationArguments.whoToInject': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'triggers[].configurationArguments.additionalObjectFilterCriteria': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'triggers[].metaData': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'triggers[].metaData.sourceInteractionId': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'triggers[].metaData.entrySourceGroupConfigUrl': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'triggers[].metaData.r__event_key': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'triggers[].metaData.category': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'triggers[].metaData.eventDefinitionId': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'triggers[].metaData.eventDefinitionKey': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'triggers[].metaData.chainType': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'triggers[].metaData.configurationRequired': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'triggers[].metaData.iconUrl': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'triggers[].metaData.title': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'triggers[].metaData.scheduleState': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + version: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + workflowApiVersion: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + campaigns: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + metaData: { + skipValidation: boolean; + }; + notifiers: { + skipValidation: boolean; + }; + tags: { + skipValidation: boolean; + }; + r__folder_Path: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + }; + }; +} +import MetadataType from './MetadataType.js'; +//# sourceMappingURL=Journey.d.ts.map \ No newline at end of file diff --git a/@types/lib/metadataTypes/Journey.d.ts.map b/@types/lib/metadataTypes/Journey.d.ts.map new file mode 100644 index 000000000..74345e9c7 --- /dev/null +++ b/@types/lib/metadataTypes/Journey.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"Journey.d.ts","sourceRoot":"","sources":["../../../lib/metadataTypes/Journey.js"],"names":[],"mappings":";uBAgBa,OAAO,wBAAwB,EAAE,QAAQ;0BACzC,OAAO,wBAAwB,EAAE,WAAW;8BAC5C,OAAO,wBAAwB,EAAE,eAAe;+BAChD,OAAO,wBAAwB,EAAE,gBAAgB;mCACjD,OAAO,wBAAwB,EAAE,oBAAoB;kCACrD,OAAO,wBAAwB,EAAE,mBAAmB;8BACpD,OAAO,wBAAwB,EAAE,eAAe;iCAChD,OAAO,wBAAwB,EAAE,kBAAkB;gCACnD,OAAO,wBAAwB,EAAE,iBAAiB;0BAClD,OAAO,wBAAwB,EAAE,WAAW;2BAC5C,OAAO,wBAAwB,EAAE,YAAY;AAX1D;;;;;;;;;;;;GAYG;AAEH;;;;;;;GAOG;AACH;IACI;;;;;;;;OAQG;IACH,6BANW,MAAM,MACN,IAAI,GAAG,MAAM,EAAE,OACf,IAAI,GAAG,MAAM,EAAE,QACf,MAAM,GACJ,OAAO,CAAE,kBAAkB,CAAC,CA0LxC;IA6JD;;;;;OAKG;IACH,wBAHW,gBAAgB,gBAS1B;IAED;;;;;OAKG;IACH,wBAHW,gBAAgB,gBAK1B;IAmBD;;;;OAIG;IACH,2CAFW,eAAe,iBAmBzB;IAED;;;;;OAKG;IACH,mCAHW,gBAAgB,GACd,OAAO,CAAE,gBAAgB,CAAC,CA4MtC;IAED;;;;;OAKG;IACH,6CAipBC;IAED;;;;;;OAMG;IACH,gCAHW,gBAAgB,GACd,OAAO,CAAE,gBAAgB,CAAC,CA8KtC;IAED;;;;;OAKG;IACH,0CA8RC;IA8MD;;;;OAIG;IACH,sCAFW,eAAe,iBA0CzB;IAED;;;;;;OAMG;IACH,uBAJW,MAAM,EAAE,kBACR,eAAe,GACb,OAAO,CAAE,MAAM,EAAE,CAAC,CAkT9B;IAED;;;;;;;OAOG;IACH,mCANW,MAAM,EAAE,wBACR,MAAM,oBACN,MAAM,kBACN,eAAe,GACb,OAAO,CAAE,IAAI,CAAC,CA+E1B;IAED;;;;;;;;;OASG;IACH,sCAPW,MAAM,OACN,MAAM,QACN,MAAM,WACN,OAAO,eAAe,EAAE,OAAO,UAC/B,MAAM,GACJ,OAAO,CAAE,MAAM,CAAC,CAiD5B;IAED;;;;OAIG;IACH,2CAFW;QAAC,MAAM,EAAC,MAAM,CAAC;QAAC,MAAM,QAAO;QAAC,QAAQ,QAAM;KAAC,QAiCvD;IAED;;;;;OAKG;IACH,wBAHW,MAAM,EAAE,GACN,OAAO,CAAE,MAAM,EAAE,CAAC,CAyJ9B;IAED;;;;;OAKG;IACH,qBAHW,MAAM,EAAE,GACN,OAAO,CAAE,MAAM,EAAE,CAAC,CAmJ9B;IAyTD;;;;;;;OAOG;IACH,uBALW,MAAM,EAAE,MACR,OAAO,kBACP,eAAe,GACb,OAAO,CAAE,MAAM,EAAE,CAAC,CAgJ9B;IACD;;;;;;OAMG;IACH,yBAJW,MAAM,gBACN,kBAAkB,GAChB,OAAO,CAAE,OAAO,CAAC,CAqB7B;CACJ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;yBAtxGwB,mBAAmB"} \ No newline at end of file diff --git a/@types/lib/metadataTypes/List.d.ts b/@types/lib/metadataTypes/List.d.ts new file mode 100644 index 000000000..fba8bac5d --- /dev/null +++ b/@types/lib/metadataTypes/List.d.ts @@ -0,0 +1,193 @@ +export default List; +export type BuObject = import("../../types/mcdev.d.js").BuObject; +export type CodeExtract = import("../../types/mcdev.d.js").CodeExtract; +export type CodeExtractItem = import("../../types/mcdev.d.js").CodeExtractItem; +export type MetadataTypeItem = import("../../types/mcdev.d.js").MetadataTypeItem; +export type MetadataTypeItemDiff = import("../../types/mcdev.d.js").MetadataTypeItemDiff; +export type MetadataTypeItemObj = import("../../types/mcdev.d.js").MetadataTypeItemObj; +export type MetadataTypeMap = import("../../types/mcdev.d.js").MetadataTypeMap; +export type MetadataTypeMapObj = import("../../types/mcdev.d.js").MetadataTypeMapObj; +export type SoapRequestParams = import("../../types/mcdev.d.js").SoapRequestParams; +export type TemplateMap = import("../../types/mcdev.d.js").TemplateMap; +/** + * @typedef {import('../../types/mcdev.d.js').BuObject} BuObject + * @typedef {import('../../types/mcdev.d.js').CodeExtract} CodeExtract + * @typedef {import('../../types/mcdev.d.js').CodeExtractItem} CodeExtractItem + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItem} MetadataTypeItem + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItemDiff} MetadataTypeItemDiff + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItemObj} MetadataTypeItemObj + * @typedef {import('../../types/mcdev.d.js').MetadataTypeMap} MetadataTypeMap + * @typedef {import('../../types/mcdev.d.js').MetadataTypeMapObj} MetadataTypeMapObj + * @typedef {import('../../types/mcdev.d.js').SoapRequestParams} SoapRequestParams + * @typedef {import('../../types/mcdev.d.js').TemplateMap} TemplateMap + */ +/** + * List MetadataType + * + * @augments MetadataType + */ +declare class List extends MetadataType { + /** + * Retrieves Metadata of Lists + * + * @param {string} [retrieveDir] Directory where retrieved metadata directory will be saved + * @param {void | string[]} [_] unused parameter + * @param {void | string[]} [__] unused parameter + * @param {string} [key] customer key of single item to retrieve + * @returns {Promise.<MetadataTypeMapObj>} Promise + */ + static retrieve(retrieveDir?: string, _?: void | string[], __?: void | string[], key?: string): Promise<MetadataTypeMapObj>; + /** + * Gets metadata cache with limited fields and does not store value to disk + * + * @returns {Promise.<MetadataTypeMapObj>} Promise of metadata + */ + static retrieveForCache(): Promise<MetadataTypeMapObj>; + /** + * helper for {@link retrieveForCache} and {@link retrieve} + * + * @private + * @param {MetadataTypeMapObj} results metadata from retrieve for current BU + * @returns {Promise.<MetadataTypeMapObj>} Promise + */ + private static _retrieveParentAllSubs; + /** + * manages post retrieve steps + * + * @param {MetadataTypeItem} list a single list + * @returns {MetadataTypeItem} metadata + */ + static postRetrieveTasks(list: MetadataTypeItem): MetadataTypeItem; + /** + * parses retrieved Metadata before saving + * + * @param {MetadataTypeItem} metadata a single list definition + * @param {boolean} [parseForCache] if set to true, the Category ID is kept + * @returns {MetadataTypeItem} Array with one metadata object and one sql string + */ + static parseMetadata(metadata: MetadataTypeItem, parseForCache?: boolean): MetadataTypeItem; +} +declare namespace List { + let client: import("sfmc-sdk").default; + let buObject: import("../../types/mcdev.d.js").BuObject; + let definition: { + bodyIteratorField: string; + dependencies: string[]; + dependencyGraph: any; + folderType: string; + hasExtended: boolean; + idField: string; + keyIsFixed: boolean; + keyField: string; + nameField: string; + restPagination: any; + type: string; + typeDescription: string; + typeRetrieveByDefault: boolean; + typeCdpByDefault: boolean; + typeName: string; + fields: { + 'AutomatedEmail.ID': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'AutomatedEmail.PartnerKey': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'AutomatedEmail.ObjectID': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + Category: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'Client.ID': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'Client.PartnerClientKey': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + CreatedDate: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + CustomerKey: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + Description: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + ID: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + ListClassification: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + ListName: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + ModifiedDate: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + ObjectID: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + PartnerKey: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + Type: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + r__folder_Path: { + skipValidation: boolean; + }; + }; + }; +} +import MetadataType from './MetadataType.js'; +//# sourceMappingURL=List.d.ts.map \ No newline at end of file diff --git a/@types/lib/metadataTypes/List.d.ts.map b/@types/lib/metadataTypes/List.d.ts.map new file mode 100644 index 000000000..10a0ea843 --- /dev/null +++ b/@types/lib/metadataTypes/List.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"List.d.ts","sourceRoot":"","sources":["../../../lib/metadataTypes/List.js"],"names":[],"mappings":";uBASa,OAAO,wBAAwB,EAAE,QAAQ;0BACzC,OAAO,wBAAwB,EAAE,WAAW;8BAC5C,OAAO,wBAAwB,EAAE,eAAe;+BAChD,OAAO,wBAAwB,EAAE,gBAAgB;mCACjD,OAAO,wBAAwB,EAAE,oBAAoB;kCACrD,OAAO,wBAAwB,EAAE,mBAAmB;8BACpD,OAAO,wBAAwB,EAAE,eAAe;iCAChD,OAAO,wBAAwB,EAAE,kBAAkB;gCACnD,OAAO,wBAAwB,EAAE,iBAAiB;0BAClD,OAAO,wBAAwB,EAAE,WAAW;AAVzD;;;;;;;;;;;GAWG;AAEH;;;;GAIG;AACH;IACI;;;;;;;;OAQG;IACH,8BANW,MAAM,MACN,IAAI,GAAG,MAAM,EAAE,OACf,IAAI,GAAG,MAAM,EAAE,QACf,MAAM,GACJ,OAAO,CAAE,kBAAkB,CAAC,CAyBxC;IAED;;;;OAIG;IACH,2BAFa,OAAO,CAAE,kBAAkB,CAAC,CA2BxC;IAED;;;;;;OAMG;IACH,sCAqEC;IAYD;;;;;OAKG;IACH,+BAHW,gBAAgB,GACd,gBAAgB,CAI5B;IAED;;;;;;OAMG;IACH,+BAJW,gBAAgB,kBAChB,OAAO,GACL,gBAAgB,CAsB5B;CACJ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;yBAzNwB,mBAAmB"} \ No newline at end of file diff --git a/@types/lib/metadataTypes/MetadataType.d.ts b/@types/lib/metadataTypes/MetadataType.d.ts new file mode 100644 index 000000000..c8c3fa4d1 --- /dev/null +++ b/@types/lib/metadataTypes/MetadataType.d.ts @@ -0,0 +1,819 @@ +export default MetadataType; +export type BuObject = import("../../types/mcdev.d.js").BuObject; +export type CodeExtract = import("../../types/mcdev.d.js").CodeExtract; +export type CodeExtractItem = import("../../types/mcdev.d.js").CodeExtractItem; +export type Mcdevrc = import("../../types/mcdev.d.js").Mcdevrc; +export type MetadataTypeItem = import("../../types/mcdev.d.js").MetadataTypeItem; +export type MetadataTypeItemDiff = import("../../types/mcdev.d.js").MetadataTypeItemDiff; +export type MetadataTypeItemObj = import("../../types/mcdev.d.js").MetadataTypeItemObj; +export type MetadataTypeMap = import("../../types/mcdev.d.js").MetadataTypeMap; +export type MetadataTypeMapObj = import("../../types/mcdev.d.js").MetadataTypeMapObj; +export type MultiMetadataTypeList = import("../../types/mcdev.d.js").MultiMetadataTypeList; +export type SoapRequestParams = import("../../types/mcdev.d.js").SoapRequestParams; +export type TemplateMap = import("../../types/mcdev.d.js").TemplateMap; +export type TypeKeyCombo = import("../../types/mcdev.d.js").TypeKeyCombo; +export type SDK = import("sfmc-sdk").default; +export type SDKError = import("../../types/mcdev.d.js").SDKError; +export type SOAPError = import("../../types/mcdev.d.js").SOAPError; +export type RestError = import("../../types/mcdev.d.js").RestError; +export type ContentBlockConversionTypes = import("../../types/mcdev.d.js").ContentBlockConversionTypes; +/** + * MetadataType class that gets extended by their specific metadata type class. + * Provides default functionality that can be overwritten by child metadata type classes + * + */ +declare class MetadataType { + /** + * Returns file contents mapped to their filename without '.json' ending + * + * @param {string} dir directory with json files, e.g. /retrieve/cred/bu/event, /deploy/cred/bu/event, /template/event + * @param {boolean} [listBadKeys] do not print errors, used for badKeys() + * @param {string[]} [selectedSubType] asset, message, ... + * @returns {Promise.<MetadataTypeMap>} fileName => fileContent map + */ + static getJsonFromFS(dir: string, listBadKeys?: boolean, selectedSubType?: string[]): Promise<MetadataTypeMap>; + /** + * Returns fieldnames of Metadata Type. 'this.definition.fields' variable only set in child classes. + * + * @param {string[]} [additionalFields] Returns specified fields even if their retrieve definition is not set to true + * @param {boolean} [isCaching] if true, then check if field should be skipped for caching + * @returns {string[]} Fieldnames + */ + static getFieldNamesToRetrieve(additionalFields?: string[], isCaching?: boolean): string[]; + /** + * Deploys metadata + * + * @param {MetadataTypeMap} metadataMap metadata mapped by their keyField + * @param {string} deployDir directory where deploy metadata are saved, ending on cred/bu + * @param {string} retrieveDir directory where metadata after deploy should be saved, ending on cred/bu + * @returns {Promise.<MetadataTypeMap>} Promise of keyField => metadata map + */ + static deploy(metadataMap: MetadataTypeMap, deployDir: string, retrieveDir: string): Promise<MetadataTypeMap>; + /** + * Gets executed after deployment of metadata type + * + * @param {MetadataTypeMap} upsertResults metadata mapped by their keyField as returned by update/create + * @param {MetadataTypeMap} originalMetadata metadata to be updated (contains additioanl fields) + * @param {{created: number, updated: number}} createdUpdated counter representing successful creates/updates + * @returns {Promise.<void>} - + */ + static postDeployTasks(upsertResults: MetadataTypeMap, originalMetadata: MetadataTypeMap, createdUpdated: { + created: number; + updated: number; + }): Promise<void>; + /** + * Gets executed before deleting a list of keys for the current type + * + * @param {string} keyArr metadata keys + * @returns {Promise.<void>} - + */ + static preDeleteTasks(keyArr: string): Promise<void>; + /** + * helper for {@link MetadataType.createREST} + * + * @param {MetadataTypeItem} metadataEntry a single metadata Entry + * @param {object} apiResponse varies depending on the API call + * @param {MetadataTypeItem} metadataEntryWithAllFields like metadataEntry but before non-creatable fields were stripped + * @returns {Promise.<object>} apiResponse, potentially modified + */ + static postCreateTasks(metadataEntry: MetadataTypeItem, apiResponse: object, metadataEntryWithAllFields: MetadataTypeItem): Promise<object>; + /** + * helper for {@link MetadataType.updateREST} and {@link MetadataType.updateSOAP} + * + * @param {MetadataTypeItem} metadataEntry a single metadata Entry + * @param {object} apiResponse varies depending on the API call + * @param {MetadataTypeItem} metadataEntryWithAllFields like metadataEntry but before non-creatable fields were stripped + * @returns {Promise.<object>} apiResponse, potentially modified + */ + static postUpdateTasks(metadataEntry: MetadataTypeItem, apiResponse: object, metadataEntryWithAllFields: MetadataTypeItem): Promise<object>; + /** + * helper for {@link MetadataType.createREST} when legacy API endpoints as these do not return the created item but only their new id + * + * @param {MetadataTypeItem} metadataEntry a single metadata Entry + * @param {object} apiResponse varies depending on the API call + * @returns {Promise.<void>} - + */ + static postDeployTasks_legacyApi(metadataEntry: MetadataTypeItem, apiResponse: object): Promise<void>; + /** + * Gets executed after retreive of metadata type + * + * @param {MetadataTypeItem} metadata a single item + * @param {string} targetDir folder where retrieves should be saved + * @param {boolean} [isTemplating] signals that we are retrieving templates + * @returns {MetadataTypeItem} cloned metadata + */ + static postRetrieveTasks(metadata: MetadataTypeItem, targetDir: string, isTemplating?: boolean): MetadataTypeItem; + /** + * generic script that retrieves the folder path from cache and updates the given metadata with it after retrieve + * + * @param {MetadataTypeItem} metadata a single item + */ + static setFolderPath(metadata: MetadataTypeItem): void; + /** + * generic script that retrieves the folder ID from cache and updates the given metadata with it before deploy + * + * @param {MetadataTypeItem} metadata a single item + */ + static setFolderId(metadata: MetadataTypeItem): void; + /** + * Gets metadata from Marketing Cloud + * + * @param {string} retrieveDir Directory where retrieved metadata directory will be saved + * @param {string[]} [additionalFields] Returns specified fields even if their retrieve definition is not set to true + * @param {string[]} [subTypeArr] optionally limit to a single subtype + * @param {string} [key] customer key of single item to retrieve + * @returns {Promise.<MetadataTypeMapObj>} metadata + */ + static retrieve(retrieveDir: string, additionalFields?: string[], subTypeArr?: string[], key?: string): Promise<MetadataTypeMapObj>; + /** + * Gets metadata from Marketing Cloud + * + * @param {string[]} [additionalFields] Returns specified fields even if their retrieve definition is not set to true + * @param {string[]} [subTypeArr] optionally limit to a single subtype + * @returns {Promise.<MetadataTypeMapObj>} metadata + */ + static retrieveChangelog(additionalFields?: string[], subTypeArr?: string[]): Promise<MetadataTypeMapObj>; + /** + * Gets metadata cache with limited fields and does not store value to disk + * + * @param {string[]} [additionalFields] Returns specified fields even if their retrieve definition is not set to true + * @param {string[]} [subTypeArr] optionally limit to a single subtype + * @param {string} [key] customer key of single item to retrieve + * @returns {Promise.<MetadataTypeMapObj>} metadata + */ + static retrieveForCache(additionalFields?: string[], subTypeArr?: string[], key?: string): Promise<MetadataTypeMapObj>; + /** + * Gets metadata cache with limited fields and does not store value to disk + * + * @deprecated Use `retrieve` followed by `build` instead. `retrieveAsTemplate` will be removed in a future version. + * @param {string} templateDir Directory where retrieved metadata directory will be saved + * @param {string} name name of the metadata file + * @param {TemplateMap} templateVariables variables to be replaced in the metadata + * @param {string} [subType] optionally limit to a single subtype + * @returns {Promise.<MetadataTypeItemObj>} metadata + */ + static retrieveAsTemplate(templateDir: string, name: string, templateVariables: TemplateMap, subType?: string): Promise<MetadataTypeItemObj>; + /** + * Retrieve a specific Script by Name + * + * @param {string} templateDir Directory where retrieved metadata directory will be saved + * @param {string} uri rest endpoint for GET + * @param {TemplateMap} templateVariables variables to be replaced in the metadata + * @param {string} name name (not key) of the metadata item + * @returns {Promise.<{metadata: MetadataTypeItem, type: string}>} Promise + */ + static retrieveTemplateREST(templateDir: string, uri: string, templateVariables: TemplateMap, name: string): Promise<{ + metadata: MetadataTypeItem; + type: string; + }>; + /** + * Gets metadata cache with limited fields and does not store value to disk + * + * @param {string} retrieveDir Directory where retrieved metadata directory will be saved + * @param {string} templateDir (List of) Directory where built definitions will be saved + * @param {string} key name of the metadata file + * @param {TemplateMap} templateVariables variables to be replaced in the metadata + * @returns {Promise.<MetadataTypeItemObj>} single metadata + */ + static buildTemplate(retrieveDir: string, templateDir: string, key: string, templateVariables: TemplateMap): Promise<MetadataTypeItemObj>; + /** + * Gets executed before deploying metadata + * + * @param {MetadataTypeItem} metadata a single metadata item + * @param {string} deployDir folder where files for deployment are stored + * @returns {Promise.<MetadataTypeItem>} Promise of a single metadata item + */ + static preDeployTasks(metadata: MetadataTypeItem, deployDir: string): Promise<MetadataTypeItem>; + /** + * helper to find a new unique name during item creation + * + * @param {string} key key of the item + * @param {string} name name of the item + * @param {{ type: string; key: string; name: any; }[]} namesInFolder names of the items in the same folder + * @param {string} [subtype] itemType-name + * @returns {string} new name + */ + static findUniqueName(key: string, name: string, namesInFolder: { + type: string; + key: string; + name: any; + }[], subtype?: string): string; + /** + * Abstract create method that needs to be implemented in child metadata type + * + * @param {MetadataTypeItem} metadata single metadata entry + * @param {string} deployDir directory where deploy metadata are saved + * @returns {Promise.<object> | null} Promise of API response or null in case of an error + */ + static create(metadata: MetadataTypeItem, deployDir: string): Promise<object> | null; + /** + * Abstract update method that needs to be implemented in child metadata type + * + * @param {MetadataTypeItem} metadata single metadata entry + * @param {MetadataTypeItem} [metadataBefore] metadata mapped by their keyField + * @returns {Promise.<object> | null} Promise of API response or null in case of an error + */ + static update(metadata: MetadataTypeItem, metadataBefore?: MetadataTypeItem): Promise<object> | null; + /** + * Abstract refresh method that needs to be implemented in child metadata type + * + * @param {string[]} [keyArr] metadata keys + * @param {boolean} [checkKey] whether to check if the key is valid + * @param {MetadataTypeMap} [upsertResults] metadata mapped by their keyField as returned by update/create; needs to be refreshed after publish + * @returns {Promise.<string[]>} Returns list of keys that were refreshed + */ + static refresh(keyArr?: string[], checkKey?: boolean, upsertResults?: MetadataTypeMap): Promise<string[]>; + /** + * + * @param {string[]} keyArr limit retrieval to given metadata type + * @param {string} retrieveDir retrieve dir including cred and bu + * @param {Set.<string>} [findAssetKeys] list of keys that were found referenced via ContentBlockByX; if set, method only gets keys and runs no updates + * @returns {Promise.<Set.<string>>} found asset keys + */ + static getCbReferenceKeys(keyArr: string[], retrieveDir: string, findAssetKeys?: Set<string>): Promise<Set<string>>; + /** + * this iterates over all items found in the retrieve folder and executes the type-specific method for replacing references + * + * @param {MetadataTypeMap} metadataMap list of metadata (keyField => metadata) + * @param {string} retrieveDir retrieve dir including cred and bu + * @param {Set.<string>} [findAssetKeys] list of keys that were found referenced via ContentBlockByX; if set, method only gets keys and runs no updates + * @returns {Promise.<string[]>} Returns list of keys for which references were replaced + */ + static replaceCbReferenceLoop(metadataMap: MetadataTypeMap, retrieveDir: string, findAssetKeys?: Set<string>): Promise<string[]>; + /** + * Abstract execute method that needs to be implemented in child metadata type + * + * @param {MetadataTypeItem} item single metadata item + * @param {string} [retrieveDir] directory where metadata is saved + * @param {Set.<string>} [findAssetKeys] list of keys that were found referenced via ContentBlockByX; if set, method only gets keys and runs no updates + * @returns {Promise.<MetadataTypeItem | CodeExtractItem>} key of the item that was updated + */ + static replaceCbReference(item: MetadataTypeItem, retrieveDir?: string, findAssetKeys?: Set<string>): Promise<MetadataTypeItem | CodeExtractItem>; + /** + * Abstract execute method that needs to be implemented in child metadata type + * + * @param {string[]} keyArr customerkey of the metadata + * @param {MetadataTypeMapObj} [cache] metadata cache used by refresh to avoid recaching + * @returns {Promise.<string[]>} Returns list of keys that were executed + */ + static execute(keyArr: string[], cache?: MetadataTypeMapObj): Promise<string[]>; + /** + * Abstract schedule method that needs to be implemented in child metadata type + * + * @param {string[]} keyArr customerkey of the metadata + * @param {MetadataTypeMapObj} [cache] metadata cache used by refresh to avoid recaching + * @returns {Promise.<string[]>} Returns list of keys that were executed + */ + static schedule(keyArr: string[], cache?: MetadataTypeMapObj): Promise<string[]>; + /** + * Abstract pause method that needs to be implemented in child metadata type + * + * @param {string[]} keyArr customerkey of the metadata + * @param {MetadataTypeMapObj} [cache] metadata cache used by refresh to avoid recaching + * @returns {Promise.<string[]>} Returns list of keys that were paused + */ + static pause(keyArr: string[], cache?: MetadataTypeMapObj): Promise<string[]>; + /** + * Abstract stop method that needs to be implemented in child metadata type + * + * @param {string[]} keyArr customerkey of the metadata + * @returns {Promise.<string[]>} Returns list of keys that were stopped + */ + static stop(keyArr: string[]): Promise<string[]>; + /** + * test if metadata was actually changed or not to potentially skip it during deployment + * + * @param {MetadataTypeItem} cachedVersion cached version from the server + * @param {MetadataTypeItem} metadata item to upload + * @param {string} [fieldName] optional field name to use for identifying the record in logs + * @returns {boolean} true if metadata was changed + */ + static hasChanged(cachedVersion: MetadataTypeItem, metadata: MetadataTypeItem, fieldName?: string): boolean; + /** + * test if metadata was actually changed or not to potentially skip it during deployment + * + * @param {MetadataTypeItem} cachedVersion cached version from the server + * @param {MetadataTypeItem} metadataItem item to upload + * @param {string} [fieldName] optional field name to use for identifying the record in logs + * @param {boolean} [silent] optionally suppress logging + * @returns {boolean} true on first identified deviation or false if none are found + */ + static hasChangedGeneric(cachedVersion: MetadataTypeItem, metadataItem: MetadataTypeItem, fieldName?: string, silent?: boolean): boolean; + /** + * helper for {@link MetadataType.upsert} to enforce max key length + * + * @param {string} metadataKey key of metadata + */ + static enforceMaxKeyLength(metadataKey: string): void; + /** + * MetadataType upsert, after retrieving from target and comparing to check if create or update operation is needed. + * + * @param {MetadataTypeMap} metadataMap metadata mapped by their keyField + * @param {string} deployDir directory where deploy metadata are saved + * @param {boolean} [runUpsertSequentially] when a type has self-dependencies creates need to run one at a time and created/changed keys need to be cached to ensure following creates/updates have thoses keys available + * @returns {Promise.<MetadataTypeMap>} keyField => metadata map + */ + static upsert(metadataMap: MetadataTypeMap, deployDir: string, runUpsertSequentially?: boolean): Promise<MetadataTypeMap>; + /** + * helper for {@link MetadataType.upsert} + * + * @param {MetadataTypeMap} metadataMap list of metadata + * @param {string} metadataKey key of item we are looking at + * @param {boolean} hasError error flag from previous code + * @param {MetadataTypeItemDiff[]} metadataToUpdate list of items to update + * @param {MetadataTypeItem[]} metadataToCreate list of items to create + * @returns {Promise.<'create' | 'update' | 'skip'>} action to take + */ + static createOrUpdate(metadataMap: MetadataTypeMap, metadataKey: string, hasError: boolean, metadataToUpdate: MetadataTypeItemDiff[], metadataToCreate: MetadataTypeItem[]): Promise<"create" | "update" | "skip">; + /** + * helper for {@link MetadataType.createOrUpdate} + * + * @param {MetadataTypeItem} metadataItem to be deployed item + * @returns {MetadataTypeItem} cached item or undefined + */ + static getCacheMatchedByName(metadataItem: MetadataTypeItem): MetadataTypeItem; + /** + * Creates a single metadata entry via REST + * + * @param {MetadataTypeItem} metadataEntry a single metadata Entry + * @param {string} uri rest endpoint for POST + * @param {boolean} [handleOutside] if the API reponse is irregular this allows you to handle it outside of this generic method + * @returns {Promise.<object> | null} Promise of API response or null in case of an error + */ + static createREST(metadataEntry: MetadataTypeItem, uri: string, handleOutside?: boolean): Promise<object> | null; + /** + * Creates a single metadata entry via fuel-soap (generic lib not wrapper) + * + * @param {MetadataTypeItem} metadataEntry single metadata entry + * @param {boolean} [handleOutside] if the API reponse is irregular this allows you to handle it outside of this generic method + * @returns {Promise.<object> | null} Promise of API response or null in case of an error + */ + static createSOAP(metadataEntry: MetadataTypeItem, handleOutside?: boolean): Promise<object> | null; + /** + * Updates a single metadata entry via REST + * + * @param {MetadataTypeItem} metadataEntry a single metadata Entry + * @param {string} uri rest endpoint for PATCH + * @param {'patch'|'post'|'put'} [httpMethod] defaults to 'patch'; some update requests require PUT instead of PATCH + * @param {boolean} [handleOutside] if the API reponse is irregular this allows you to handle it outside of this generic method + * @returns {Promise.<object> | null} Promise of API response or null in case of an error + */ + static updateREST(metadataEntry: MetadataTypeItem, uri: string, httpMethod?: "patch" | "post" | "put", handleOutside?: boolean): Promise<object> | null; + /** + * helper for {@link MetadataType.updateREST} and {@link MetadataType.updateSOAP} that removes old files after the key was changed + * + * @param {MetadataTypeItem} metadataEntry a single metadata Entry + * @param {boolean} [keepMap] some types require to check the old-key new-key relationship in their postDeployTasks; currently used by dataExtension only + * @returns {Promise.<void>} - + */ + static _postChangeKeyTasks(metadataEntry: MetadataTypeItem, keepMap?: boolean): Promise<void>; + /** + * Updates a single metadata entry via fuel-soap (generic lib not wrapper) + * + * @param {MetadataTypeItem} metadataEntry single metadata entry + * @param {boolean} [handleOutside] if the API reponse is irregular this allows you to handle it outside of this generic method + * @returns {Promise.<object> | null} Promise of API response or null in case of an error + */ + static updateSOAP(metadataEntry: MetadataTypeItem, handleOutside?: boolean): Promise<object> | null; + /** + * + * @param {SOAPError} ex error that occured + * @param {'creating'|'updating'|'retrieving'|'executing'|'pausing'} msg what to print in the log + * @param {MetadataTypeItem} [metadataEntry] single metadata entry + * @param {boolean} [handleOutside] if the API reponse is irregular this allows you to handle it outside of this generic method + * @param {string} [nameAttribute] name attribute to use in the error message instead of keyField + */ + static _handleSOAPErrors(ex: SOAPError, msg: "creating" | "updating" | "retrieving" | "executing" | "pausing", metadataEntry?: MetadataTypeItem, handleOutside?: boolean, nameAttribute?: string): void; + /** + * helper for {@link MetadataType._handleSOAPErrors} + * + * @param {SOAPError} ex error that occured + * @returns {string} error message + */ + static getSOAPErrorMsg(ex: SOAPError): string; + /** + * Retrieves SOAP via generic fuel-soap wrapper based metadata of metadata type into local filesystem. executes callback with retrieved metadata + * + * @param {string} [retrieveDir] Directory where retrieved metadata directory will be saved + * @param {SoapRequestParams} [requestParams] required for the specific request (filter for example) + * @param {string} [singleRetrieve] key of single item to filter by + * @param {string[]} [additionalFields] Returns specified fields even if their retrieve definition is not set to true + * @returns {Promise.<MetadataTypeMapObj>} Promise of item map + */ + static retrieveSOAP(retrieveDir?: string, requestParams?: SoapRequestParams, singleRetrieve?: string, additionalFields?: string[]): Promise<MetadataTypeMapObj>; + /** + * Retrieves Metadata for Rest Types + * + * @param {string} retrieveDir Directory where retrieved metadata directory will be saved + * @param {string} uri rest endpoint for GET + * @param {TemplateMap} [templateVariables] variables to be replaced in the metadata + * @param {string} [singleRetrieve] key of single item to filter by + * @returns {Promise.<{metadata: (MetadataTypeMap | MetadataTypeItem), type: string}>} Promise of item map (single item for templated result) + */ + static retrieveREST(retrieveDir: string, uri: string, templateVariables?: TemplateMap, singleRetrieve?: string): Promise<{ + metadata: (MetadataTypeMap | MetadataTypeItem); + type: string; + }>; + /** + * + * @param {object[]} urlArray {uri: string, id: string} combo of URL and ID/key of metadata + * @param {number} [concurrentRequests] optionally set a different amount of concurrent requests + * @param {boolean} [logAmountOfUrls] if true, prints an info message about to-be loaded amount of metadata + * @returns {Promise.<{metadata: (MetadataTypeMap | MetadataTypeItem), type: string}>} Promise of item map (single item for templated result) + */ + static retrieveRESTcollection(urlArray: object[], concurrentRequests?: number, logAmountOfUrls?: boolean): Promise<{ + metadata: (MetadataTypeMap | MetadataTypeItem); + type: string; + }>; + /** + * helper for {@link this.retrieveRESTcollection} + * + * @param {RestError} ex exception + * @param {string} key id or key of item + * @param {string} url url to call for retry + * @returns {Promise.<any>} - + */ + static handleRESTErrors(ex: RestError, key: string, url: string): Promise<any>; + /** + * Used to execute a query/automation etc. + * + * @param {string} uri REST endpoint where the POST request should be sent + * @param {string} key item key + * @returns {Promise.<{key:string, response:string}>} metadata key and API response (OK or error) + */ + static executeREST(uri: string, key: string): Promise<{ + key: string; + response: string; + }>; + /** + * Used to execute a query/automation etc. + * + * @param {MetadataTypeItem} [metadataEntry] single metadata entry + * @returns {Promise.<{key:string, response:object}>} metadata key and API response + */ + static executeSOAP(metadataEntry?: MetadataTypeItem): Promise<{ + key: string; + response: object; + }>; + /** + * helper for {@link MetadataType.retrieveREST} and {@link MetadataType.retrieveSOAP} + * + * @param {string|number} singleRetrieve key of single item to filter by + * @param {MetadataTypeMap} metadataMap saved metadata + * @returns {Promise.<void>} - + */ + static runDocumentOnRetrieve(singleRetrieve: string | number, metadataMap: MetadataTypeMap): Promise<void>; + /** + * helper for {@link parseResponseBody} that creates a custom key field for this type based on mobileCode and keyword + * + * @param {MetadataTypeItem} metadata single item + */ + static createCustomKeyField(metadata: MetadataTypeItem): void; + /** + * Builds map of metadata entries mapped to their keyfields + * + * @param {object} body json of response body + * @param {string} [singleRetrieve] key of single item to filter by + * @returns {MetadataTypeMap} keyField => metadata map + */ + static parseResponseBody(body: object, singleRetrieve?: string): MetadataTypeMap; + /** + * Deletes a field in a metadata entry if the selected definition property equals false. + * + * @example + * Removes field (or nested fields childs) that are not updateable + * deleteFieldByDefinition(metadataEntry, 'CustomerKey', 'isUpdateable'); + * @param {MetadataTypeItem} metadataEntry One entry of a metadataType + * @param {string} fieldPath field path to be checked if it conforms to the definition (dot seperated if nested): 'fuu.bar' + * @param {'isCreateable'|'isUpdateable'|'retrieving'|'template'} definitionProperty delete field if definitionProperty equals false for specified field. Options: [isCreateable | isUpdateable] + * @param {string} origin string of parent object, required when using arrays as these are parsed slightly differently. + * @returns {void} + */ + static deleteFieldByDefinition(metadataEntry: MetadataTypeItem, fieldPath: string, definitionProperty: "isCreateable" | "isUpdateable" | "retrieving" | "template", origin: string): void; + /** + * Remove fields from metadata entry that are not createable + * + * @param {MetadataTypeItem} metadataEntry metadata entry + * @returns {void} + */ + static removeNotCreateableFields(metadataEntry: MetadataTypeItem): void; + /** + * Remove fields from metadata entry that are not updateable + * + * @param {MetadataTypeItem} metadataEntry metadata entry + * @returns {void} + */ + static removeNotUpdateableFields(metadataEntry: MetadataTypeItem): void; + /** + * Remove fields from metadata entry that are not needed in the template + * + * @param {MetadataTypeItem} metadataEntry metadata entry + * @returns {void} + */ + static keepTemplateFields(metadataEntry: MetadataTypeItem): void; + /** + * Remove fields from metadata entry that are not needed in the stored metadata + * + * @param {MetadataTypeItem} metadataEntry metadata entry + * @returns {void} + */ + static keepRetrieveFields(metadataEntry: MetadataTypeItem): void; + /** + * checks if the current metadata entry should be saved on retrieve or not + * + * @static + * @param {MetadataTypeItem} metadataEntry metadata entry + * @param {boolean} [include] true: use definition.include / options.include; false=exclude: use definition.filter / options.exclude + * @returns {boolean} true: skip saving == filtered; false: continue with saving + * @memberof MetadataType + */ + static isFiltered(metadataEntry: MetadataTypeItem, include?: boolean): boolean; + /** + * optionally filter by what folder something is in + * + * @static + * @param {object} metadataEntry metadata entry + * @param {boolean} [include] true: use definition.include / options.include; false=exclude: use definition.filter / options.exclude + * @returns {boolean} true: filtered == do NOT save; false: not filtered == do save + * @memberof MetadataType + */ + static isFilteredFolder(metadataEntry: object, include?: boolean): boolean; + /** + * internal helper + * + * @private + * @param {object} myFilter include/exclude filter object + * @param {string} r__folder_Path already determined folder path + * @returns {?boolean} true: filter value found; false: filter value not found; null: no filter defined + */ + private static _filterFolder; + /** + * internal helper + * + * @private + * @param {object} myFilter include/exclude filter object + * @param {object} metadataEntry metadata entry + * @returns {?boolean} true: filter value found; false: filter value not found; null: no filter defined + */ + private static _filterOther; + /** + * Helper for writing Metadata to disk, used for Retrieve and deploy + * + * @param {MetadataTypeMap} results metadata results from deploy + * @param {string} retrieveDir directory where metadata should be stored after deploy/retrieve + * @param {string} [overrideType] for use when there is a subtype (such as folder-queries) + * @param {TemplateMap} [templateVariables] variables to be replaced in the metadata + * @returns {Promise.<MetadataTypeMap>} Promise of saved metadata + */ + static saveResults(results: MetadataTypeMap, retrieveDir: string, overrideType?: string, templateVariables?: TemplateMap): Promise<MetadataTypeMap>; + /** + * + * @param {MetadataTypeMap} results metadata results from deploy + * @param {string} originalKey key of metadata + * @param {string[]} baseDir [retrieveDir, ...overrideType.split('-')] + * @param {string} [subtypeExtension] e.g. ".asset-meta" or ".query-meta" + * @param {TemplateMap} [templateVariables] variables to be replaced in the metadata + * @returns {Promise.<MetadataTypeItem>} saved metadata + */ + static saveToDisk(results: MetadataTypeMap, originalKey: string, baseDir: string[], subtypeExtension?: string, templateVariables?: TemplateMap): Promise<MetadataTypeItem>; + /** + * helper for {@link MetadataType.buildDefinitionForNested} + * searches extracted file for template variable names and applies the market values + * + * @param {string} code code from extracted code + * @param {TemplateMap} templateVariables variables to be replaced in the metadata + * @returns {string} code with markets applied + */ + static applyTemplateValues(code: string, templateVariables: TemplateMap): string; + /** + * helper for {@link MetadataType.buildTemplateForNested} + * searches extracted file for template variable values and applies the market variable names + * + * @param {string} code code from extracted code + * @param {TemplateMap} templateVariables variables to be replaced in the metadata + * @returns {string} code with markets applied + */ + static applyTemplateNames(code: string, templateVariables: TemplateMap): string; + /** + * helper for {@link MetadataType.buildDefinition} + * handles extracted code if any are found for complex types (e.g script, asset, query) + * + * @param {string} templateDir Directory where metadata templates are stored + * @param {string | string[]} targetDir Directory where built definitions will be saved + * @param {MetadataTypeItem} metadata main JSON file that was read from file system + * @param {TemplateMap} variables variables to be replaced in the metadata + * @param {string} templateName name of the template to be built + * @returns {Promise.<string[][]>} list of extracted files with path-parts provided as an array + */ + static buildDefinitionForNested(templateDir: string, targetDir: string | string[], metadata: MetadataTypeItem, variables: TemplateMap, templateName: string): Promise<string[][]>; + /** + * helper for {@link MetadataType.buildTemplate} + * handles extracted code if any are found for complex types + * + * @param {string} templateDir Directory where metadata templates are stored + * @param {string|string[]} targetDir (List of) Directory where built definitions will be saved + * @param {MetadataTypeItem} metadata main JSON file that was read from file system + * @param {TemplateMap} templateVariables variables to be replaced in the metadata + * @param {string} templateName name of the template to be built + * @returns {Promise.<string[][]>} list of extracted files with path-parts provided as an array + */ + static buildTemplateForNested(templateDir: string, targetDir: string | string[], metadata: MetadataTypeItem, templateVariables: TemplateMap, templateName: string): Promise<string[][]>; + /** + * check template directory for complex types that open subfolders for their subtypes + * + * @param {string} templateDir Directory where metadata templates are stored + * @param {string} templateName name of the metadata file + * @returns {Promise.<string>} subtype name + */ + static findSubType(templateDir: string, templateName: string): Promise<string>; + /** + * optional method used for some types to try a different folder structure + * + * @param {string} templateDir Directory where metadata templates are stored + * @param {string[]} typeDirArr current subdir for this type + * @param {string} templateName name of the metadata template + * @param {string} fileName name of the metadata template file w/o extension + * @param {Error} ex error from first attempt + * @returns {Promise.<string>} metadata in string form + */ + static readSecondaryFolder(templateDir: string, typeDirArr: string[], templateName: string, fileName: string, ex: Error): Promise<string>; + /** + * Builds definition based on template + * NOTE: Most metadata files should use this generic method, unless custom + * parsing is required (for example scripts & queries) + * + * @param {string} templateDir Directory where metadata templates are stored + * @param {string | string[]} targetDir (List of) Directory where built definitions will be saved + * @param {string} templateName name of the metadata file + * @param {TemplateMap} variables variables to be replaced in the metadata + * @returns {Promise.<MetadataTypeMapObj>} Promise of item map + */ + static buildDefinition(templateDir: string, targetDir: string | string[], templateName: string, variables: TemplateMap): Promise<MetadataTypeMapObj>; + /** + * Standardizes a check for multiple messages + * + * @param {object} ex response payload from REST API + * @returns {string[]} formatted Error Message + */ + static getErrorsREST(ex: object): string[]; + /** + * Gets metadata cache with limited fields and does not store value to disk + * + * @param {MetadataTypeMap} [metadata] a list of type definitions + * @param {boolean} [isDeploy] used to skip non-supported message during deploy + * @returns {void} + */ + static document(metadata?: MetadataTypeMap, isDeploy?: boolean): void; + /** + * get name & key for provided id + * + * @param {string} id Identifier of metadata + * @returns {Promise.<{key:string, name:string}>} key, name and path of metadata; null if not found + */ + static resolveId(id: string): Promise<{ + key: string; + name: string; + }>; + /** + * Delete a metadata item from the specified business unit + * + * @param {string} customerKey Identifier of data extension + * @returns {Promise.<boolean>} deletion success status + */ + static deleteByKey(customerKey: string): Promise<boolean>; + /** + * clean up after deleting a metadata item + * + * @param {string} customerKey Identifier of metadata item + * @param {string[]} [additionalExtensions] additional file extensions to delete on top of `${this.definition.type}-meta.json` + * @returns {Promise.<void>} - Promise + */ + static postDeleteTasks(customerKey: string, additionalExtensions?: string[]): Promise<void>; + /** + * Delete a data extension from the specified business unit + * + * @param {string} key Identifier of metadata + * @param {string} [overrideKeyField] optionally change the name of the key field if the api uses a different name + * @param {number} [codeNotFound] error code that is responded with if the item was not found + * @param {boolean} [handleOutside] if the API reponse is irregular this allows you to handle it outside of this generic method + * @returns {Promise.<boolean>} deletion success flag + */ + static deleteByKeySOAP(key: string, overrideKeyField?: string, codeNotFound?: number, handleOutside?: boolean): Promise<boolean>; + /** + * Delete a data extension from the specified business unit + * + * @param {string} url endpoint + * @param {string} key Identifier of metadata + * @param {number} [codeNotFound] error code that is responded with if the item was not found + * @param {boolean} [handleOutside] if the API reponse is irregular this allows you to handle it outside of this generic method + * @returns {Promise.<boolean>} deletion success flag + */ + static deleteByKeyREST(url: string, key: string, codeNotFound?: number, handleOutside?: boolean): Promise<boolean>; + /** + * helper for {@link deleteByKey}, {@link deleteByKeyREST}, {@link deleteByKeySOAP} + * + * @param {string} key Identifier of metadata + */ + static deleteNotFound(key: string): Promise<void>; + /** + * Returns metadata of a business unit that is saved locally + * + * @param {string} readDir root directory of metadata. + * @param {boolean} [listBadKeys] do not print errors, used for badKeys() + * @param {object} [buMetadata] Metadata of BU in local directory + * @returns {Promise.<object>} Metadata of BU in local directory + */ + static readBUMetadataForType(readDir: string, listBadKeys?: boolean, buMetadata?: object): Promise<object>; + /** + * should return only the json for all but asset, query and script that are saved as multiple files + * additionally, the documentation for dataExtension and automation should be returned + * + * @param {string[]} keyArr customerkey of the metadata + * @returns {Promise.<string[]>} list of all files that need to be committed in a flat array ['path/file1.ext', 'path/file2.ext'] + */ + static getFilesToCommit(keyArr: string[]): Promise<string[]>; + /** + * + * @param {string[]} keyArr customerkey of the metadata + * @param {TypeKeyCombo} multiTypeKeyList list of all keys that need to be deployed + * @param {TypeKeyCombo} notFoundList list of all keys that were not found + * @param {boolean} isFirstCall will not gray out the log message for type/keys that you initially selected but only for their dependencies + * @returns {Promise.<TypeKeyCombo>} list of all keys that need to be deployed + */ + static getDependentFiles(keyArr: string[], multiTypeKeyList?: TypeKeyCombo, notFoundList?: TypeKeyCombo, isFirstCall?: boolean): Promise<TypeKeyCombo>; + /** + * optional helper for {@link this.getDependentTypes} + * + * @param {object} metadataItem metadata json read from filesystem + * @param {TypeKeyCombo} dependentTypeKeyCombo list started in this.getDependentTypes + */ + static getDependentFilesExtra(metadataItem: object, dependentTypeKeyCombo: TypeKeyCombo): void; + /** + * helper for {@link MetadataType.getDependentFiles} + * + * @param {MetadataTypeItem} obj the metadataItem to search in + * @param {string} nestedKey e.g "my.field.here" + * @param {string} dependentType used for types that need custom handling + * @returns {(string)[]} result array or null if nothing was found + */ + static getNestedValue(obj: MetadataTypeItem, nestedKey: string, dependentType: string): (string)[]; + /** + * helper for {@link MetadataType.getNestedValue} + * + * @param {any} obj the metadataItem to search in (or the result) + * @param {string[]} nestedKeyParts key in dot-notation split into parts + * @param {string} dependentType used for types that need custom handling + * @returns {(string) | (string)[]} result + */ + static getNestedValueHelper(obj: any, nestedKeyParts: string[], dependentType: string): (string) | (string)[]; + /** + * + * @param {MetadataTypeMap} metadataMap metadata mapped by their keyField + * @returns {string[]} list of keys + */ + static getKeysForFixing(metadataMap: MetadataTypeMap): string[]; + /** + * helper for getKeysForFixing and createOrUpdate + * + * @param {string} baseField name of the field to start the new key with + * @param {MetadataTypeItem} metadataItem - + * @param {number} maxKeyLength - + * @returns {string} newKey + */ + static getNewKey(baseField: string, metadataItem: MetadataTypeItem, maxKeyLength: number): string; + /** + * @typedef {'off'|'warn'|'error'} ValidationLevel + */ + /** + * @typedef {object} ValidationRules + * @property {ValidationLevel} [noGuidKeys] flags metadata that did not get a proper key + * @property {ValidationLevel} [noRootFolder] flags metadata that did not get a proper key + * @property {{type:string[], options: ValidationRules}[]} [overrides] flags metadata that did not get a proper key + */ + /** + * Gets executed before deploying metadata + * + * @param {'retrieve'|'buildDefinition'|'deploy'} method used to select the right config + * @param {MetadataTypeItem | CodeExtractItem} originalItem a single metadata item + * @param {string} targetDir folder where files for deployment are stored + * @returns {Promise.<MetadataTypeItem | CodeExtractItem>} Promise of a single metadata item + */ + static validation(method: "retrieve" | "buildDefinition" | "deploy", originalItem: MetadataTypeItem | CodeExtractItem, targetDir: string): Promise<MetadataTypeItem | CodeExtractItem>; +} +declare namespace MetadataType { + namespace definition { + let bodyIteratorField: string; + let dependencies: any[]; + let fields: any; + let hasExtended: any; + let idField: string; + let keyField: string; + let nameField: string; + let type: string; + } + let client: SDK; + let properties: Mcdevrc; + let subType: string; + let buObject: BuObject; +} +//# sourceMappingURL=MetadataType.d.ts.map \ No newline at end of file diff --git a/@types/lib/metadataTypes/MetadataType.d.ts.map b/@types/lib/metadataTypes/MetadataType.d.ts.map new file mode 100644 index 000000000..f246f1e83 --- /dev/null +++ b/@types/lib/metadataTypes/MetadataType.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"MetadataType.d.ts","sourceRoot":"","sources":["../../../lib/metadataTypes/MetadataType.js"],"names":[],"mappings":";uBAmBa,OAAO,wBAAwB,EAAE,QAAQ;0BACzC,OAAO,wBAAwB,EAAE,WAAW;8BAC5C,OAAO,wBAAwB,EAAE,eAAe;sBAChD,OAAO,wBAAwB,EAAE,OAAO;+BACxC,OAAO,wBAAwB,EAAE,gBAAgB;mCACjD,OAAO,wBAAwB,EAAE,oBAAoB;kCACrD,OAAO,wBAAwB,EAAE,mBAAmB;8BACpD,OAAO,wBAAwB,EAAE,eAAe;iCAChD,OAAO,wBAAwB,EAAE,kBAAkB;oCACnD,OAAO,wBAAwB,EAAE,qBAAqB;gCACtD,OAAO,wBAAwB,EAAE,iBAAiB;0BAClD,OAAO,wBAAwB,EAAE,WAAW;2BAC5C,OAAO,wBAAwB,EAAE,YAAY;kBAC7C,OAAO,UAAU,EAAE,OAAO;uBAC1B,OAAO,wBAAwB,EAAE,QAAQ;wBACzC,OAAO,wBAAwB,EAAE,SAAS;wBAC1C,OAAO,wBAAwB,EAAE,SAAS;0CAC1C,OAAO,wBAAwB,EAAE,2BAA2B;AAazE;;;;GAIG;AACH;IACI;;;;;;;OAOG;IACH,0BALW,MAAM,gBACN,OAAO,oBACP,MAAM,EAAE,GACN,OAAO,CAAE,eAAe,CAAC,CAoDrC;IAED;;;;;;OAMG;IACH,kDAJW,MAAM,EAAE,cACR,OAAO,GACL,MAAM,EAAE,CAkBpB;IAED;;;;;;;OAOG;IACH,2BALW,eAAe,aACf,MAAM,eACN,MAAM,GACJ,OAAO,CAAE,eAAe,CAAC,CAiBrC;IAED;;;;;;;OAOG;IACH,sCALW,eAAe,oBACf,eAAe,kBACf;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAC,GAChC,OAAO,CAAE,IAAI,CAAC,CAEqD;IAEhF;;;;;OAKG;IACH,8BAHW,MAAM,GACJ,OAAO,CAAE,IAAI,CAAC,CAEW;IAEtC;;;;;;;OAOG;IACH,sCALW,gBAAgB,eAChB,MAAM,8BACN,gBAAgB,GACd,OAAO,CAAE,MAAM,CAAC,CAI5B;IAED;;;;;;;OAOG;IACH,sCALW,gBAAgB,eAChB,MAAM,8BACN,gBAAgB,GACd,OAAO,CAAE,MAAM,CAAC,CAI5B;IAED;;;;;;OAMG;IACH,gDAJW,gBAAgB,eAChB,MAAM,GACJ,OAAO,CAAE,IAAI,CAAC,CAuB1B;IAED;;;;;;;OAOG;IACH,mCALW,gBAAgB,aAChB,MAAM,iBACN,OAAO,GACL,gBAAgB,CAI5B;IAED;;;;OAIG;IACH,+BAFW,gBAAgB,QAoB1B;IAED;;;;OAIG;IACH,6BAFW,gBAAgB,QAa1B;IAED;;;;;;;;OAQG;IACH,6BANW,MAAM,qBACN,MAAM,EAAE,eACR,MAAM,EAAE,QACR,MAAM,GACJ,OAAO,CAAE,kBAAkB,CAAC,CAKxC;IAED;;;;;;OAMG;IACH,4CAJW,MAAM,EAAE,eACR,MAAM,EAAE,GACN,OAAO,CAAE,kBAAkB,CAAC,CAIxC;IAED;;;;;;;OAOG;IACH,2CALW,MAAM,EAAE,eACR,MAAM,EAAE,QACR,MAAM,GACJ,OAAO,CAAE,kBAAkB,CAAC,CAIxC;IAED;;;;;;;;;OASG;IACH,uCANW,MAAM,QACN,MAAM,qBACN,WAAW,YACX,MAAM,GACJ,OAAO,CAAE,mBAAmB,CAAC,CAMzC;IAED;;;;;;;;OAQG;IACH,yCANW,MAAM,OACN,MAAM,qBACN,WAAW,QACX,MAAM,GACJ,OAAO,CAAE;QAAC,QAAQ,EAAE,gBAAgB,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAC,CAAC,CAIhE;IAED;;;;;;;;OAQG;IACH,kCANW,MAAM,eACN,MAAM,OACN,MAAM,qBACN,WAAW,GACT,OAAO,CAAE,mBAAmB,CAAC,CA2FzC;IAED;;;;;;OAMG;IACH,gCAJW,gBAAgB,aAChB,MAAM,GACJ,OAAO,CAAE,gBAAgB,CAAC,CAItC;IAED;;;;;;;;OAQG;IACH,2BANW,MAAM,QACN,MAAM,iBACN;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,GAAG,CAAC;KAAE,EAAE,YAC3C,MAAM,GACJ,MAAM,CAkBlB;IAED;;;;;;OAMG;IACH,wBAJW,gBAAgB,aAChB,MAAM,GACJ,OAAO,CAAE,MAAM,CAAC,GAAG,IAAI,CAKnC;IAED;;;;;;OAMG;IACH,wBAJW,gBAAgB,mBAChB,gBAAgB,GACd,OAAO,CAAE,MAAM,CAAC,GAAG,IAAI,CAKnC;IAED;;;;;;;OAOG;IACH,wBALW,MAAM,EAAE,aACR,OAAO,kBACP,eAAe,GACb,OAAO,CAAE,MAAM,EAAE,CAAC,CAK9B;IAED;;;;;;OAMG;IACH,kCALW,MAAM,EAAE,eACR,MAAM,kBACN,GAAG,CAAE,MAAM,CAAC,GACV,OAAO,CAAE,GAAG,CAAE,MAAM,CAAC,CAAC,CAclC;IAED;;;;;;;OAOG;IACH,2CALW,eAAe,eACf,MAAM,kBACN,GAAG,CAAE,MAAM,CAAC,GACV,OAAO,CAAE,MAAM,EAAE,CAAC,CAgE9B;IAED;;;;;;;OAOG;IACH,gCALW,gBAAgB,gBAChB,MAAM,kBACN,GAAG,CAAE,MAAM,CAAC,GACV,OAAO,CAAE,gBAAgB,GAAG,eAAe,CAAC,CAKxD;IAED;;;;;;OAMG;IACH,uBAJW,MAAM,EAAE,UACR,kBAAkB,GAChB,OAAO,CAAE,MAAM,EAAE,CAAC,CAK9B;IAED;;;;;;OAMG;IACH,wBAJW,MAAM,EAAE,UACR,kBAAkB,GAChB,OAAO,CAAE,MAAM,EAAE,CAAC,CAK9B;IAED;;;;;;OAMG;IACH,qBAJW,MAAM,EAAE,UACR,kBAAkB,GAChB,OAAO,CAAE,MAAM,EAAE,CAAC,CAK9B;IAED;;;;;OAKG;IACH,oBAHW,MAAM,EAAE,GACN,OAAO,CAAE,MAAM,EAAE,CAAC,CAK9B;IAED;;;;;;;OAOG;IACH,iCALW,gBAAgB,YAChB,gBAAgB,cAChB,MAAM,GACJ,OAAO,CAKnB;IAED;;;;;;;;OAQG;IACH,wCANW,gBAAgB,gBAChB,gBAAgB,cAChB,MAAM,WACN,OAAO,GACL,OAAO,CAgDnB;IAED;;;;OAIG;IACH,wCAFW,MAAM,QAQhB;IAED;;;;;;;OAOG;IACH,2BALW,eAAe,aACf,MAAM,0BACN,OAAO,GACL,OAAO,CAAE,eAAe,CAAC,CA8LrC;IAED;;;;;;;;;OASG;IACH,mCAPW,eAAe,eACf,MAAM,YACN,OAAO,oBACP,oBAAoB,EAAE,oBACtB,gBAAgB,EAAE,GAChB,OAAO,CAAE,QAAQ,GAAG,QAAQ,GAAG,MAAM,CAAC,CAmNlD;IAED;;;;;OAKG;IACH,2CAHW,gBAAgB,GACd,gBAAgB,CAK5B;IAED;;;;;;;OAOG;IACH,iCALW,gBAAgB,OAChB,MAAM,kBACN,OAAO,GACL,OAAO,CAAE,MAAM,CAAC,GAAG,IAAI,CA6BnC;IAED;;;;;;OAMG;IACH,iCAJW,gBAAgB,kBAChB,OAAO,GACL,OAAO,CAAE,MAAM,CAAC,GAAG,IAAI,CAsBnC;IAED;;;;;;;;OAQG;IACH,iCANW,gBAAgB,OAChB,MAAM,eACN,OAAO,GAAC,MAAM,GAAC,KAAK,kBACpB,OAAO,GACL,OAAO,CAAE,MAAM,CAAC,GAAG,IAAI,CA4BnC;IAED;;;;;;OAMG;IACH,0CAJW,gBAAgB,YAChB,OAAO,GACL,OAAO,CAAE,IAAI,CAAC,CA2B1B;IAED;;;;;;OAMG;IACH,iCAJW,gBAAgB,kBAChB,OAAO,GACL,OAAO,CAAE,MAAM,CAAC,GAAG,IAAI,CAyBnC;IAED;;;;;;;OAOG;IACH,6BANW,SAAS,OACT,UAAU,GAAC,UAAU,GAAC,YAAY,GAAC,WAAW,GAAC,SAAS,kBACxD,gBAAgB,kBAChB,OAAO,kBACP,MAAM,QAYhB;IAED;;;;;OAKG;IACH,2BAHW,SAAS,GACP,MAAM,CAWlB;IAED;;;;;;;;OAQG;IACH,kCANW,MAAM,kBACN,iBAAiB,mBACjB,MAAM,qBACN,MAAM,EAAE,GACN,OAAO,CAAE,kBAAkB,CAAC,CAgCxC;IAED;;;;;;;;OAQG;IACH,iCANW,MAAM,OACN,MAAM,sBACN,WAAW,mBACX,MAAM,GACJ,OAAO,CAAE;QAAC,QAAQ,EAAE,CAAC,eAAe,GAAG,gBAAgB,CAAC,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAC,CAAC,CAoEpF;IAED;;;;;;OAMG;IACH,wCALW,MAAM,EAAE,uBACR,MAAM,oBACN,OAAO,GACL,OAAO,CAAE;QAAC,QAAQ,EAAE,CAAC,eAAe,GAAG,gBAAgB,CAAC,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAC,CAAC,CAqCpF;IAED;;;;;;;OAOG;IACH,4BALW,SAAS,OACT,MAAM,OACN,MAAM,GACJ,OAAO,CAAE,GAAG,CAAC,CAOzB;IAED;;;;;;OAMG;IACH,wBAJW,MAAM,OACN,MAAM,GACJ,OAAO,CAAE;QAAC,GAAG,EAAC,MAAM,CAAC;QAAC,QAAQ,EAAC,MAAM,CAAA;KAAC,CAAC,CAcnD;IAED;;;;;OAKG;IACH,mCAHW,gBAAgB,GACd,OAAO,CAAE;QAAC,GAAG,EAAC,MAAM,CAAC;QAAC,QAAQ,EAAC,MAAM,CAAA;KAAC,CAAC,CAwBnD;IAED;;;;;;OAMG;IACH,6CAJW,MAAM,GAAC,MAAM,eACb,eAAe,GACb,OAAO,CAAE,IAAI,CAAC,CAqB1B;IAED;;;;OAIG;IACH,sCAFW,gBAAgB,QAEa;IAExC;;;;;;OAMG;IACH,+BAJW,MAAM,mBACN,MAAM,GACJ,eAAe,CA0C3B;IAED;;;;;;;;;;;OAWG;IACH,8CANW,gBAAgB,aAChB,MAAM,sBACN,cAAc,GAAC,cAAc,GAAC,YAAY,GAAC,UAAU,UACrD,MAAM,GACJ,IAAI,CAwEhB;IAED;;;;;OAKG;IACH,gDAHW,gBAAgB,GACd,IAAI,CAMhB;IAED;;;;;OAKG;IACH,gDAHW,gBAAgB,GACd,IAAI,CAMhB;IAED;;;;;OAKG;IACH,yCAHW,gBAAgB,GACd,IAAI,CAMhB;IAED;;;;;OAKG;IACH,yCAHW,gBAAgB,GACd,IAAI,CAMhB;IAED;;;;;;;;OAQG;IACH,iCALW,gBAAgB,YAChB,OAAO,GACL,OAAO,CAkCnB;IAED;;;;;;;;OAQG;IACH,uCALW,MAAM,YACN,OAAO,GACL,OAAO,CA2DnB;IAED;;;;;;;OAOG;IACH,6BAqBC;IAED;;;;;;;OAOG;IACH,4BAsBC;IAED;;;;;;;;OAQG;IACH,4BANW,eAAe,eACf,MAAM,iBACN,MAAM,sBACN,WAAW,GACT,OAAO,CAAE,eAAe,CAAC,CA0FrC;IAED;;;;;;;;OAQG;IACH,2BAPW,eAAe,eACf,MAAM,WACN,MAAM,EAAE,qBACR,MAAM,sBACN,WAAW,GACT,OAAO,CAAE,gBAAgB,CAAC,CA2FtC;IAED;;;;;;;OAOG;IACH,iCAJW,MAAM,qBACN,WAAW,GACT,MAAM,CAKlB;IAED;;;;;;;OAOG;IACH,gCAJW,MAAM,qBACN,WAAW,GACT,MAAM,CAKlB;IAED;;;;;;;;;;OAUG;IACH,6CAPW,MAAM,aACN,MAAM,GAAG,MAAM,EAAE,YACjB,gBAAgB,aAChB,WAAW,gBACX,MAAM,GACJ,OAAO,CAAE,MAAM,EAAE,EAAE,CAAC,CAWhC;IAED;;;;;;;;;;OAUG;IACH,2CAPW,MAAM,aACN,MAAM,GAAC,MAAM,EAAE,YACf,gBAAgB,qBAChB,WAAW,gBACX,MAAM,GACJ,OAAO,CAAE,MAAM,EAAE,EAAE,CAAC,CAWhC;IAED;;;;;;OAMG;IACH,gCAJW,MAAM,gBACN,MAAM,GACJ,OAAO,CAAE,MAAM,CAAC,CAI5B;IAED;;;;;;;;;OASG;IACH,wCAPW,MAAM,cACN,MAAM,EAAE,gBACR,MAAM,YACN,MAAM,MACN,KAAK,GACH,OAAO,CAAE,MAAM,CAAC,CAK5B;IAED;;;;;;;;;;OAUG;IACH,oCANW,MAAM,aACN,MAAM,GAAG,MAAM,EAAE,gBACjB,MAAM,aACN,WAAW,GACT,OAAO,CAAE,kBAAkB,CAAC,CAoHxC;IAED;;;;;OAKG;IACH,yBAHW,MAAM,GACJ,MAAM,EAAE,CAkCpB;IAED;;;;;;OAMG;IACH,2BAJW,eAAe,aACf,OAAO,GACL,IAAI,CAMhB;IAED;;;;;OAKG;IACH,qBAHW,MAAM,GACJ,OAAO,CAAE;QAAC,GAAG,EAAC,MAAM,CAAC;QAAC,IAAI,EAAC,MAAM,CAAA;KAAC,CAAC,CAK/C;IAED;;;;;OAKG;IACH,gCAHW,MAAM,GACJ,OAAO,CAAE,OAAO,CAAC,CAK7B;IAED;;;;;;OAMG;IACH,oCAJW,MAAM,yBACN,MAAM,EAAE,GACN,OAAO,CAAE,IAAI,CAAC,CAe1B;IAED;;;;;;;;OAQG;IACH,4BANW,MAAM,qBACN,MAAM,iBACN,MAAM,kBACN,OAAO,GACL,OAAO,CAAE,OAAO,CAAC,CAmC7B;IAED;;;;;;;;OAQG;IACH,4BANW,MAAM,OACN,MAAM,iBACN,MAAM,kBACN,OAAO,GACL,OAAO,CAAE,OAAO,CAAC,CAyB7B;IAED;;;;OAIG;IACH,2BAFW,MAAM,iBAOhB;IAED;;;;;;;OAOG;IACH,sCALW,MAAM,gBACN,OAAO,eACP,MAAM,GACJ,OAAO,CAAE,MAAM,CAAC,CAY5B;IAED;;;;;;OAMG;IACH,gCAHW,MAAM,EAAE,GACN,OAAO,CAAE,MAAM,EAAE,CAAC,CAe9B;IAED;;;;;;;OAOG;IACH,iCANW,MAAM,EAAE,qBACR,YAAY,iBACZ,YAAY,gBACZ,OAAO,GACL,OAAO,CAAE,YAAY,CAAC,CAuHlC;IAED;;;;;OAKG;IACH,4CAHW,MAAM,yBACN,YAAY,QAE8C;IAErE;;;;;;;OAOG;IACH,2BALW,gBAAgB,aAChB,MAAM,iBACN,MAAM,GACJ,CAAC,MAAM,CAAC,EAAE,CAUtB;IAED;;;;;;;OAOG;IACH,iCALW,GAAG,kBACH,MAAM,EAAE,iBACR,MAAM,GACJ,CAAC,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAkBjC;IAED;;;;OAIG;IACH,qCAHW,eAAe,GACb,MAAM,EAAE,CA2DpB;IAED;;;;;;;OAOG;IACH,4BALW,MAAM,gBACN,gBAAgB,gBAChB,MAAM,GACJ,MAAM,CAelB;IAED;;OAEG;IACH;;;;;OAKG;IAEH;;;;;;;OAOG;IACH,0BALW,UAAU,GAAC,iBAAiB,GAAC,QAAQ,gBACrC,gBAAgB,GAAG,eAAe,aAClC,MAAM,GACJ,OAAO,CAAE,gBAAgB,GAAG,eAAe,CAAC,CAsHxD;CACJ;;;;;;;;;;;;gBAaS,GAAG;oBAIH,OAAO;iBAIP,MAAM;kBAIN,QAAQ"} \ No newline at end of file diff --git a/@types/lib/metadataTypes/MobileCode.d.ts b/@types/lib/metadataTypes/MobileCode.d.ts new file mode 100644 index 000000000..45ff78824 --- /dev/null +++ b/@types/lib/metadataTypes/MobileCode.d.ts @@ -0,0 +1,218 @@ +export default MobileCode; +export type BuObject = import("../../types/mcdev.d.js").BuObject; +export type CodeExtract = import("../../types/mcdev.d.js").CodeExtract; +export type CodeExtractItem = import("../../types/mcdev.d.js").CodeExtractItem; +export type MetadataTypeItem = import("../../types/mcdev.d.js").MetadataTypeItem; +export type MetadataTypeItemDiff = import("../../types/mcdev.d.js").MetadataTypeItemDiff; +export type MetadataTypeItemObj = import("../../types/mcdev.d.js").MetadataTypeItemObj; +export type MetadataTypeMap = import("../../types/mcdev.d.js").MetadataTypeMap; +export type MetadataTypeMapObj = import("../../types/mcdev.d.js").MetadataTypeMapObj; +export type SoapRequestParams = import("../../types/mcdev.d.js").SoapRequestParams; +export type TemplateMap = import("../../types/mcdev.d.js").TemplateMap; +/** + * @typedef {import('../../types/mcdev.d.js').BuObject} BuObject + * @typedef {import('../../types/mcdev.d.js').CodeExtract} CodeExtract + * @typedef {import('../../types/mcdev.d.js').CodeExtractItem} CodeExtractItem + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItem} MetadataTypeItem + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItemDiff} MetadataTypeItemDiff + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItemObj} MetadataTypeItemObj + * @typedef {import('../../types/mcdev.d.js').MetadataTypeMap} MetadataTypeMap + * @typedef {import('../../types/mcdev.d.js').MetadataTypeMapObj} MetadataTypeMapObj + * @typedef {import('../../types/mcdev.d.js').SoapRequestParams} SoapRequestParams + * @typedef {import('../../types/mcdev.d.js').TemplateMap} TemplateMap + */ +/** + * MobileCode MetadataType + * + * @augments MetadataType + */ +declare class MobileCode extends MetadataType { + /** + * Retrieves Metadata of Mobile Keywords + * Endpoint /legacy/v1/beta/mobile/code/ return all Mobile Codes with all details. + * + * @param {string} retrieveDir Directory where retrieved metadata directory will be saved + * @param {void | string[]} [_] unused parameter + * @param {void | string[]} [__] unused parameter + * @param {string} [key] customer key of single item to retrieve + * @returns {Promise.<MetadataTypeMapObj>} Promise of metadata + */ + static retrieve(retrieveDir: string, _?: void | string[], __?: void | string[], key?: string): Promise<MetadataTypeMapObj>; + /** + * Retrieves event definition metadata for caching + * + * @returns {Promise.<MetadataTypeMapObj>} Promise of metadata + */ + static retrieveForCache(): Promise<MetadataTypeMapObj>; +} +declare namespace MobileCode { + let definition: { + bodyIteratorField: string; + dependencies: any[]; + dependencyGraph: any; + hasExtended: boolean; + idField: string; + keyIsFixed: boolean; + keyField: string; + nameField: string; + createdDateField: string; + createdNameField: any; + lastmodDateField: string; + lastmodNameField: any; + restPagination: boolean; + restPageSize: number; + type: string; + typeDescription: string; + typeRetrieveByDefault: boolean; + typeCdpByDefault: boolean; + typeName: string; + fields: { + id: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + createdDate: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + lastUpdated: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + startDate: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + endDate: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + keywordLimit: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + keywordsUsed: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + code: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + codeType: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + isShortCode: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + keywordsUsedOther: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + isGsmCharacterSetOnly: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + isMms: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + isStackIndependant: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + supportsConcatenation: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + isClientOwned: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + isOwner: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + dipSwitches: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + sendableCountries: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'sendableCountries[].countryCode': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'sendableCountries[].vendor': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'sendableCountries[].fromNameSupported': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + countryCode: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + moEngineVersion: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + }; + }; +} +import MetadataType from './MetadataType.js'; +//# sourceMappingURL=MobileCode.d.ts.map \ No newline at end of file diff --git a/@types/lib/metadataTypes/MobileCode.d.ts.map b/@types/lib/metadataTypes/MobileCode.d.ts.map new file mode 100644 index 000000000..f2a719431 --- /dev/null +++ b/@types/lib/metadataTypes/MobileCode.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"MobileCode.d.ts","sourceRoot":"","sources":["../../../lib/metadataTypes/MobileCode.js"],"names":[],"mappings":";uBAKa,OAAO,wBAAwB,EAAE,QAAQ;0BACzC,OAAO,wBAAwB,EAAE,WAAW;8BAC5C,OAAO,wBAAwB,EAAE,eAAe;+BAChD,OAAO,wBAAwB,EAAE,gBAAgB;mCACjD,OAAO,wBAAwB,EAAE,oBAAoB;kCACrD,OAAO,wBAAwB,EAAE,mBAAmB;8BACpD,OAAO,wBAAwB,EAAE,eAAe;iCAChD,OAAO,wBAAwB,EAAE,kBAAkB;gCACnD,OAAO,wBAAwB,EAAE,iBAAiB;0BAClD,OAAO,wBAAwB,EAAE,WAAW;AAVzD;;;;;;;;;;;GAWG;AAEH;;;;GAIG;AACH;IACI;;;;;;;;;OASG;IACH,6BANW,MAAM,MACN,IAAI,GAAG,MAAM,EAAE,OACf,IAAI,GAAG,MAAM,EAAE,QACf,MAAM,GACJ,OAAO,CAAE,kBAAkB,CAAC,CASxC;IAED;;;;OAIG;IACH,2BAFa,OAAO,CAAE,kBAAkB,CAAC,CAIxC;CACJ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;yBAhDwB,mBAAmB"} \ No newline at end of file diff --git a/@types/lib/metadataTypes/MobileKeyword.d.ts b/@types/lib/metadataTypes/MobileKeyword.d.ts new file mode 100644 index 000000000..329e256b6 --- /dev/null +++ b/@types/lib/metadataTypes/MobileKeyword.d.ts @@ -0,0 +1,437 @@ +export default MobileKeyword; +export type BuObject = import("../../types/mcdev.d.js").BuObject; +export type CodeExtract = import("../../types/mcdev.d.js").CodeExtract; +export type CodeExtractItem = import("../../types/mcdev.d.js").CodeExtractItem; +export type MetadataTypeItem = import("../../types/mcdev.d.js").MetadataTypeItem; +export type MetadataTypeItemDiff = import("../../types/mcdev.d.js").MetadataTypeItemDiff; +export type MetadataTypeItemObj = import("../../types/mcdev.d.js").MetadataTypeItemObj; +export type MetadataTypeMap = import("../../types/mcdev.d.js").MetadataTypeMap; +export type MetadataTypeMapObj = import("../../types/mcdev.d.js").MetadataTypeMapObj; +export type SoapRequestParams = import("../../types/mcdev.d.js").SoapRequestParams; +export type TemplateMap = import("../../types/mcdev.d.js").TemplateMap; +/** + * @typedef {import('../../types/mcdev.d.js').BuObject} BuObject + * @typedef {import('../../types/mcdev.d.js').CodeExtract} CodeExtract + * @typedef {import('../../types/mcdev.d.js').CodeExtractItem} CodeExtractItem + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItem} MetadataTypeItem + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItemDiff} MetadataTypeItemDiff + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItemObj} MetadataTypeItemObj + * @typedef {import('../../types/mcdev.d.js').MetadataTypeMap} MetadataTypeMap + * @typedef {import('../../types/mcdev.d.js').MetadataTypeMapObj} MetadataTypeMapObj + * @typedef {import('../../types/mcdev.d.js').SoapRequestParams} SoapRequestParams + * @typedef {import('../../types/mcdev.d.js').TemplateMap} TemplateMap + */ +/** + * MobileKeyword MetadataType + * + * @augments MetadataType + */ +declare class MobileKeyword extends MetadataType { + /** + * Retrieves Metadata of Mobile Keywords + * Endpoint /legacy/v1/beta/mobile/keyword/ return all Mobile Keywords with all details. + * + * @param {string} retrieveDir Directory where retrieved metadata directory will be saved + * @param {void | string[]} [_] unused parameter + * @param {void | string[]} [__] unused parameter + * @param {string} [key] customer key of single item to retrieve + * @returns {Promise.<MetadataTypeMapObj>} Promise of metadata + */ + static retrieve(retrieveDir: string, _?: void | string[], __?: void | string[], key?: string): Promise<MetadataTypeMapObj>; + /** + * helper for {@link MobileKeyword.preDeployTasks} and {@link MobileKeyword.createOrUpdate} to ensure we have code & keyword properly set + * + * @param {MetadataTypeItem} metadata single item + */ + static "__#private@#setCodeAndKeyword"(metadata: MetadataTypeItem): void; + /** + * Retrieves event definition metadata for caching + * + * @param {void | string[]} [_] parameter not used + * @param {void | string[]} [__] parameter not used + * @param {string} [key] customer key of single item to retrieve + * @returns {Promise.<MetadataTypeMapObj>} Promise of metadata + */ + static retrieveForCache(_?: void | string[], __?: void | string[], key?: string): Promise<MetadataTypeMapObj>; + /** + * retrieve an item and create a template from it + * + * @deprecated Use `retrieve` followed by `build` instead. `retrieveAsTemplate` will be removed in a future version. + * @param {string} templateDir Directory where retrieved metadata directory will be saved + * @param {string} key name of the metadata file + * @param {TemplateMap} templateVariables variables to be replaced in the metadata + * @returns {Promise.<MetadataTypeItemObj>} Promise of metadata + */ + static retrieveAsTemplate(templateDir: string, key: string, templateVariables: TemplateMap): Promise<MetadataTypeItemObj>; + /** + * helper for {@link MobileKeyword.retrieve} and {@link MobileKeyword.retrieveAsTemplate} + * + * @param {string} key customer key of single item to retrieve / name of the metadata file + * @returns {Array} key, queryParams + */ + static "__#private@#getRetrieveKeyAndUrl"(key: string): any[]; + /** + * Creates a single item + * + * @param {MetadataTypeItem} metadata a single item + * @returns {Promise} Promise + */ + static create(metadata: MetadataTypeItem): Promise<any>; + /** + * Updates a single item + * + * @param {MetadataTypeItem} metadata a single item + * @returns {Promise} Promise + */ + static update(metadata: MetadataTypeItem): Promise<any>; + /** + * manages post retrieve steps + * + * @param {MetadataTypeItem} metadata a single item + * @returns {CodeExtractItem | MetadataTypeItem | void} Array with one metadata object and one ssjs string; or single metadata object; nothing if filtered + */ + static postRetrieveTasks(metadata: MetadataTypeItem): CodeExtractItem | MetadataTypeItem | void; + /** + * helper for {@link MobileKeyword.postRetrieveTasks} and {@link MobileKeyword._buildForNested} + * + * @param {string} metadataScript the code of the file + * @returns {{fileExt:string,code:string}} returns found extension and file content + */ + static prepExtractedCode(metadataScript: string): { + fileExt: string; + code: string; + }; + /** + * helper for {@link MobileKeyword.buildTemplateForNested} / {@link MobileKeyword.buildDefinitionForNested} + * handles extracted code if any are found for complex types + * + * @param {string} templateDir Directory where metadata templates are stored + * @param {string|string[]} targetDir (List of) Directory where built definitions will be saved + * @param {MetadataTypeItem} metadata main JSON file that was read from file system + * @param {TemplateMap} templateVariables variables to be replaced in the metadata + * @param {string} templateName name of the template to be built + * @param {'definition'|'template'} mode defines what we use this helper for + * @returns {Promise.<string[][]>} list of extracted files with path-parts provided as an array + */ + static _buildForNested(templateDir: string, targetDir: string | string[], metadata: MetadataTypeItem, templateVariables: TemplateMap, templateName: string, mode: "definition" | "template"): Promise<string[][]>; + /** + * helper for {@link MetadataType.createREST} + * + * @param {MetadataTypeItem} metadataEntry a single metadata Entry + * @param {object} apiResponse varies depending on the API call + * @returns {Promise.<object>} apiResponse + */ + static postCreateTasks(metadataEntry: MetadataTypeItem, apiResponse: object): Promise<object>; + /** + * helper for {@link MetadataType.updateREST} + * + * @param {MetadataTypeItem} metadataEntry a single metadata Entry + * @param {object} apiResponse varies depending on the API call + * @returns {Promise.<object>} apiResponse, potentially modified + */ + static postUpdateTasks(metadataEntry: MetadataTypeItem, apiResponse: object): Promise<object>; + /** + * helper for {@link MobileKeyword.preDeployTasks} that loads extracted code content back into JSON + * + * @param {MetadataTypeItem} metadata a single definition + * @param {string} deployDir directory of deploy files + * @param {string} [templateName] name of the template used to built defintion (prior applying templating) + * @returns {Promise.<string>} content for metadata.script + */ + static _mergeCode(metadata: MetadataTypeItem, deployDir: string, templateName?: string): Promise<string>; + /** + * clean up after deleting a metadata item + * + * @param {string} customerKey Identifier of metadata item + * @returns {Promise.<void>} - + */ + static postDeleteTasks(customerKey: string): Promise<void>; +} +declare namespace MobileKeyword { + let definition: { + bodyIteratorField: string; + dependencies: string[]; + dependencyGraph: { + mobileCode: string[]; + }; + hasExtended: boolean; + idField: string; + keyIsFixed: boolean; + keyField: string; + nameField: string; + createdDateField: string; + createdNameField: string; + lastmodDateField: string; + lastmodNameField: any; + restPagination: boolean; + restPageSize: number; + maxKeyLength: number; + type: string; + typeDescription: string; + typeRetrieveByDefault: boolean; + typeCdpByDefault: boolean; + typeName: string; + fields: { + id: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + c__codeKeyword: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + r__mobileCode_key: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + keyword: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + createdDate: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + lastUpdated: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + startDate: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + endDate: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + createdBy: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'createdBy.id': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'createdBy.name': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'createdBy.lastUpdated': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + dipSwitches: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + isInherited: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + decodedId: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + restriction: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + keywordType: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + companyName: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + responseMessage: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + status: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + messages: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + code: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'code.code': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'code.id': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'code.createdDate': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'code.lastUpdated': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'code.startDate': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'code.endDate': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'code.keywordLimit': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'code.keywordsUsed': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'code.codeType': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'code.isShortCode': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'code.keywordsUsedOther': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'code.isGsmCharacterSetOnly': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'code.isMms': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'code.isStackIndependant': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'code.supportsConcatenation': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'code.isClientOwned': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'code.isOwner': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'code.dipSwitches': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'code.sendableCountries': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'code.countryCode': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'code.moEngineVersion': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + }; + }; +} +import MetadataType from './MetadataType.js'; +//# sourceMappingURL=MobileKeyword.d.ts.map \ No newline at end of file diff --git a/@types/lib/metadataTypes/MobileKeyword.d.ts.map b/@types/lib/metadataTypes/MobileKeyword.d.ts.map new file mode 100644 index 000000000..bcab6dac2 --- /dev/null +++ b/@types/lib/metadataTypes/MobileKeyword.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"MobileKeyword.d.ts","sourceRoot":"","sources":["../../../lib/metadataTypes/MobileKeyword.js"],"names":[],"mappings":";uBAQa,OAAO,wBAAwB,EAAE,QAAQ;0BACzC,OAAO,wBAAwB,EAAE,WAAW;8BAC5C,OAAO,wBAAwB,EAAE,eAAe;+BAChD,OAAO,wBAAwB,EAAE,gBAAgB;mCACjD,OAAO,wBAAwB,EAAE,oBAAoB;kCACrD,OAAO,wBAAwB,EAAE,mBAAmB;8BACpD,OAAO,wBAAwB,EAAE,eAAe;iCAChD,OAAO,wBAAwB,EAAE,kBAAkB;gCACnD,OAAO,wBAAwB,EAAE,iBAAiB;0BAClD,OAAO,wBAAwB,EAAE,WAAW;AAVzD;;;;;;;;;;;GAWG;AAEH;;;;GAIG;AACH;IACI;;;;;;;;;OASG;IACH,6BANW,MAAM,MACN,IAAI,GAAG,MAAM,EAAE,OACf,IAAI,GAAG,MAAM,EAAE,QACf,MAAM,GACJ,OAAO,CAAE,kBAAkB,CAAC,CAyBxC;IAWD;;;;OAIG;IACH,iDAFW,gBAAgB,QAkB1B;IAiCD;;;;;;;OAOG;IACH,4BALW,IAAI,GAAG,MAAM,EAAE,OACf,IAAI,GAAG,MAAM,EAAE,QACf,MAAM,GACJ,OAAO,CAAE,kBAAkB,CAAC,CAIxC;IAED;;;;;;;;OAQG;IACH,uCALW,MAAM,OACN,MAAM,qBACN,WAAW,GACT,OAAO,CAAE,mBAAmB,CAAC,CAwBzC;IAED;;;;;OAKG;IACH,+CAHW,MAAM,SAwBhB;IAED;;;;;OAKG;IACH,wBAHW,gBAAgB,gBAK1B;IAED;;;;;OAKG;IACH,wBAHW,gBAAgB,gBAS1B;IAED;;;;;OAKG;IACH,mCAHW,gBAAgB,GACd,eAAe,GAAG,gBAAgB,GAAG,IAAI,CAoCrD;IAED;;;;;OAKG;IACH,yCAHW,MAAM,GACJ;QAAC,OAAO,EAAC,MAAM,CAAC;QAAA,IAAI,EAAC,MAAM,CAAA;KAAC,CAOxC;IA2DD;;;;;;;;;;;OAWG;IACH,oCARW,MAAM,aACN,MAAM,GAAC,MAAM,EAAE,YACf,gBAAgB,qBAChB,WAAW,gBACX,MAAM,QACN,YAAY,GAAC,UAAU,GACrB,OAAO,CAAE,MAAM,EAAE,EAAE,CAAC,CAwDhC;IA+BD;;;;;;OAMG;IACH,sCAJW,gBAAgB,eAChB,MAAM,GACJ,OAAO,CAAE,MAAM,CAAC,CAM5B;IAED;;;;;;OAMG;IACH,sCAJW,gBAAgB,eAChB,MAAM,GACJ,OAAO,CAAE,MAAM,CAAC,CAK5B;IAED;;;;;;;OAOG;IACH,4BALW,gBAAgB,aAChB,MAAM,iBACN,MAAM,GACJ,OAAO,CAAE,MAAM,CAAC,CAqB5B;IAuBD;;;;;OAKG;IACH,oCAHW,MAAM,GACJ,OAAO,CAAE,IAAI,CAAC,CAM1B;CAuBJ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;yBAzhBwB,mBAAmB"} \ No newline at end of file diff --git a/@types/lib/metadataTypes/MobileMessage.d.ts b/@types/lib/metadataTypes/MobileMessage.d.ts new file mode 100644 index 000000000..ab1bfeab6 --- /dev/null +++ b/@types/lib/metadataTypes/MobileMessage.d.ts @@ -0,0 +1,908 @@ +export default MobileMessage; +export type BuObject = import("../../types/mcdev.d.js").BuObject; +export type CodeExtract = import("../../types/mcdev.d.js").CodeExtract; +export type CodeExtractItem = import("../../types/mcdev.d.js").CodeExtractItem; +export type MetadataTypeItem = import("../../types/mcdev.d.js").MetadataTypeItem; +export type MetadataTypeItemDiff = import("../../types/mcdev.d.js").MetadataTypeItemDiff; +export type MetadataTypeItemObj = import("../../types/mcdev.d.js").MetadataTypeItemObj; +export type MetadataTypeMap = import("../../types/mcdev.d.js").MetadataTypeMap; +export type MetadataTypeMapObj = import("../../types/mcdev.d.js").MetadataTypeMapObj; +export type SoapRequestParams = import("../../types/mcdev.d.js").SoapRequestParams; +export type TemplateMap = import("../../types/mcdev.d.js").TemplateMap; +/** + * @typedef {import('../../types/mcdev.d.js').BuObject} BuObject + * @typedef {import('../../types/mcdev.d.js').CodeExtract} CodeExtract + * @typedef {import('../../types/mcdev.d.js').CodeExtractItem} CodeExtractItem + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItem} MetadataTypeItem + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItemDiff} MetadataTypeItemDiff + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItemObj} MetadataTypeItemObj + * @typedef {import('../../types/mcdev.d.js').MetadataTypeMap} MetadataTypeMap + * @typedef {import('../../types/mcdev.d.js').MetadataTypeMapObj} MetadataTypeMapObj + * @typedef {import('../../types/mcdev.d.js').SoapRequestParams} SoapRequestParams + * @typedef {import('../../types/mcdev.d.js').TemplateMap} TemplateMap + */ +/** + * MobileMessage MetadataType + * + * @augments MetadataType + */ +declare class MobileMessage extends MetadataType { + /** + * Retrieves Metadata of Mobile Keywords + * + * @param {string} retrieveDir Directory where retrieved metadata directory will be saved + * @param {void | string[]} [_] unused parameter + * @param {void | string[]} [__] unused parameter + * @param {string} [key] customer key of single item to retrieve + * @returns {Promise.<MetadataTypeMapObj>} Promise of metadata + */ + static retrieve(retrieveDir: string, _?: void | string[], __?: void | string[], key?: string): Promise<MetadataTypeMapObj>; + /** + * Retrieves event definition metadata for caching + * + * @param {void | string[]} [_] parameter not used + * @param {void | string[]} [__] parameter not used + * @param {string} [key] customer key of single item to retrieve + * @returns {Promise.<MetadataTypeMapObj>} Promise of metadata + */ + static retrieveForCache(_?: void | string[], __?: void | string[], key?: string): Promise<MetadataTypeMapObj>; + /** + * Updates a single item + * + * @param {MetadataTypeItem} metadata a single item + * @returns {Promise} Promise + */ + static update(metadata: MetadataTypeItem): Promise<any>; + /** + * Creates a single item + * + * @param {MetadataTypeItem} metadata a single item + * @returns {Promise} Promise + */ + static create(metadata: MetadataTypeItem): Promise<any>; + /** + * helper for {@link MobileMessage.preDeployTasks} that loads extracted code content back into JSON + * + * @param {MetadataTypeItem} metadata a single definition + * @param {string} deployDir directory of deploy files + * @param {string} [templateName] name of the template used to built defintion (prior applying templating) + * @returns {Promise.<string>} code + */ + static _mergeCode(metadata: MetadataTypeItem, deployDir: string, templateName?: string): Promise<string>; + /** + * helper for {@link MobileMessage.postRetrieveTasks} and {@link MobileMessage._buildForNested} + * + * @param {string} code the code of the file + * @returns {{fileExt:string,code:string}} returns found extension and file content + */ + static prepExtractedCode(code: string): { + fileExt: string; + code: string; + }; + /** + * manages post retrieve steps + * + * @param {MetadataTypeItem} metadata a single query + * @returns {CodeExtractItem} Array with one metadata object and one query string + */ + static postRetrieveTasks(metadata: MetadataTypeItem): CodeExtractItem; + /** + * helper for {@link MetadataType.createREST} + * + * @param {MetadataTypeItem} metadataEntry a single metadata Entry + * @param {object} apiResponse varies depending on the API call + * @returns {Promise.<object>} apiResponse + */ + static postCreateTasks(metadataEntry: MetadataTypeItem, apiResponse: object): Promise<object>; + /** + * helper for {@link MetadataType.updateREST} + * + * @param {MetadataTypeItem} metadataEntry a single metadata Entry + * @param {object} apiResponse varies depending on the API call + * @returns {Promise.<object>} apiResponse, potentially modified + */ + static postUpdateTasks(metadataEntry: MetadataTypeItem, apiResponse: object): Promise<object>; + /** + * helper for {@link MobileMessage.buildTemplateForNested} / {@link MobileMessage.buildDefinitionForNested} + * handles extracted code if any are found for complex types + * + * @param {string} templateDir Directory where metadata templates are stored + * @param {string|string[]} targetDir (List of) Directory where built definitions will be saved + * @param {MetadataTypeItem} metadata main JSON file that was read from file system + * @param {TemplateMap} templateVariables variables to be replaced in the metadata + * @param {string} templateName name of the template to be built + * @param {'definition'|'template'} mode defines what we use this helper for + * @returns {Promise.<string[][]>} list of extracted files with path-parts provided as an array + */ + static _buildForNested(templateDir: string, targetDir: string | string[], metadata: MetadataTypeItem, templateVariables: TemplateMap, templateName: string, mode: "definition" | "template"): Promise<string[][]>; +} +declare namespace MobileMessage { + let definition: { + bodyIteratorField: string; + dependencies: string[]; + dependencyGraph: { + mobileCode: string[]; + mobileKeyword: string[]; + }; + hasExtended: boolean; + idField: string; + keepId: boolean; + keyIsFixed: boolean; + keyField: string; + nameField: string; + createdDateField: any; + createdNameField: any; + lastmodDateField: string; + lastmodNameField: any; + restPagination: boolean; + restPageSize: number; + type: string; + typeDescription: string; + typeRetrieveByDefault: boolean; + typeCdpByDefault: boolean; + typeName: string; + fields: { + allowSingleOptin: { + isCreatable: boolean; + isUpdatable: boolean; + retrieving: boolean; + template: boolean; + }; + audience: { + skipValidation: boolean; + }; + 'audience[]': { + skipValidation: boolean; + }; + campaigns: { + skipValidation: boolean; + }; + 'campaigns[]': { + skipValidation: boolean; + }; + r__mobileCode_key: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'code.code': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'code.codeType': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'code.countryCode': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'code.createdDate': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'code.dipSwitches': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'code.endDate': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'code.id': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'code.isClientOwned': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'code.isGsmCharacterSetOnly': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'code.isMms': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'code.isOwner': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'code.isShortCode': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'code.isStackIndependant': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'code.keywordLimit': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'code.keywordsUsed': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'code.keywordsUsedOther': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'code.lastUpdated': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'code.moEngineVersion': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'code.sendableCountries': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'code.sendableCountries[]': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'code.sendableCountries[].countryCode': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'code.sendableCountries[].vendor': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'code.sendableCountries[].fromNameSupported': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'code.startDate': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'code.supportsConcatenation': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + concatenateMessage: { + isCreatable: boolean; + isUpdatable: boolean; + retrieving: boolean; + template: boolean; + }; + currentEditStep: { + isCreatable: boolean; + isUpdatable: boolean; + retrieving: boolean; + template: boolean; + }; + doubleOptinConfirmMessage: { + isCreatable: boolean; + isUpdatable: boolean; + retrieving: boolean; + template: boolean; + }; + doubleOptinInitialMessage: { + isCreatable: boolean; + isUpdatable: boolean; + retrieving: boolean; + template: boolean; + }; + doubleOptinValidResponses: { + isCreatable: boolean; + isUpdatable: boolean; + retrieving: boolean; + template: boolean; + }; + duplicateOptInResponseMessage: { + isCreatable: boolean; + isUpdatable: boolean; + retrieving: boolean; + template: boolean; + }; + expireHours: { + isCreatable: boolean; + isUpdatable: boolean; + retrieving: boolean; + template: boolean; + }; + fromName: { + isCreatable: boolean; + isUpdatable: boolean; + retrieving: boolean; + template: boolean; + }; + id: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + invalidMessage: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + isCertified: { + isCreatable: boolean; + isUpdatable: boolean; + retrieving: boolean; + template: boolean; + }; + isDuplicationAllowed: { + isCreatable: boolean; + isUpdatable: boolean; + retrieving: boolean; + template: boolean; + }; + isExpireSet: { + isCreatable: boolean; + isUpdatable: boolean; + retrieving: boolean; + template: boolean; + }; + isFromNameCertificationAccepted: { + isCreatable: boolean; + isUpdatable: boolean; + retrieving: boolean; + template: boolean; + }; + isSentImmediately: { + isCreatable: boolean; + isUpdatable: boolean; + retrieving: boolean; + template: boolean; + }; + isSubscriberResponseToAnySubscriptionForShortCode: { + isCreatable: boolean; + isUpdatable: boolean; + retrieving: boolean; + template: boolean; + }; + isSuppressMt: { + isCreatable: boolean; + isUpdatable: boolean; + retrieving: boolean; + template: boolean; + }; + isTest: { + isCreatable: boolean; + isUpdatable: boolean; + retrieving: boolean; + template: boolean; + }; + isTimeZoneBased: { + isCreatable: boolean; + isUpdatable: boolean; + retrieving: boolean; + template: boolean; + }; + 'keyword.id': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'keyword.isInherited': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'keyword.keyword': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'keyword.r__mobileKeyword_key': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'keyword.keywordType': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'keyword.restriction': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + lastUpdated: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + messageObjectId: { + isCreatable: boolean; + isUpdatable: boolean; + retrieving: boolean; + template: boolean; + }; + messagesPerPeriod: { + isCreatable: boolean; + isUpdatable: boolean; + retrieving: boolean; + template: boolean; + }; + minutesPerPeriod: { + isCreatable: boolean; + isUpdatable: boolean; + retrieving: boolean; + template: boolean; + }; + moStartDate: { + isCreatable: boolean; + isUpdatable: boolean; + retrieving: boolean; + template: boolean; + }; + moEndDate: { + isCreatable: boolean; + isUpdatable: boolean; + retrieving: boolean; + template: boolean; + }; + 'moTimezone.name': { + isCreatable: boolean; + isUpdatable: boolean; + retrieving: boolean; + template: boolean; + }; + 'moTimezone.offset': { + isCreatable: boolean; + isUpdatable: boolean; + retrieving: boolean; + template: boolean; + }; + 'mtRecurrence.id': { + isCreatable: boolean; + isUpdatable: boolean; + retrieving: boolean; + template: boolean; + }; + 'mtRecurrence.key': { + isCreatable: boolean; + isUpdatable: boolean; + retrieving: boolean; + template: boolean; + }; + 'mtRecurrence.createdDate': { + isCreatable: boolean; + isUpdatable: boolean; + retrieving: boolean; + template: boolean; + }; + 'mtRecurrence.createdBy': { + isCreatable: boolean; + isUpdatable: boolean; + retrieving: boolean; + template: boolean; + }; + 'mtRecurrence.lastUpdated': { + isCreatable: boolean; + isUpdatable: boolean; + retrieving: boolean; + template: boolean; + }; + 'mtRecurrence.lastUpdatedBy': { + isCreatable: boolean; + isUpdatable: boolean; + retrieving: boolean; + template: boolean; + }; + 'mtRecurrence.name': { + isCreatable: boolean; + isUpdatable: boolean; + retrieving: boolean; + template: boolean; + }; + 'mtRecurrence.description': { + isCreatable: boolean; + isUpdatable: boolean; + retrieving: boolean; + template: boolean; + }; + 'mtRecurrence.startDate': { + isCreatable: boolean; + isUpdatable: boolean; + retrieving: boolean; + template: boolean; + }; + 'mtRecurrence.iCalRecur': { + isCreatable: boolean; + isUpdatable: boolean; + retrieving: boolean; + template: boolean; + }; + 'mtRecurrence.timeZone': { + isCreatable: boolean; + isUpdatable: boolean; + retrieving: boolean; + template: boolean; + }; + 'mtRecurrence.timeZoneId': { + isCreatable: boolean; + isUpdatable: boolean; + retrieving: boolean; + template: boolean; + }; + mtSendDate: { + isCreatable: boolean; + isUpdatable: boolean; + retrieving: boolean; + template: boolean; + }; + name: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + nextJob: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + nextKeyword: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + numberMessagesPerPeriod: { + isCreatable: boolean; + isUpdatable: boolean; + retrieving: boolean; + template: boolean; + }; + optinErrorMessage: { + isCreatable: boolean; + isUpdatable: boolean; + retrieving: boolean; + template: boolean; + }; + optinInvalidAgeMessage: { + isCreatable: boolean; + isUpdatable: boolean; + retrieving: boolean; + template: boolean; + }; + optinMinimumAge: { + isCreatable: boolean; + isUpdatable: boolean; + retrieving: boolean; + template: boolean; + }; + optinType: { + isCreatable: boolean; + isUpdatable: boolean; + retrieving: boolean; + template: boolean; + }; + origin: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + outboundSendBehaviorFlag: { + isCreatable: boolean; + isUpdatable: boolean; + retrieving: boolean; + template: boolean; + }; + outboundSendTypeFlag: { + isCreatable: boolean; + isUpdatable: boolean; + retrieving: boolean; + template: boolean; + }; + periodType: { + isCreatable: boolean; + isUpdatable: boolean; + retrieving: boolean; + template: boolean; + }; + programId: { + isCreatable: boolean; + isUpdatable: boolean; + retrieving: boolean; + template: boolean; + }; + publishedMessage: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + responseMessage: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + sendMethod: { + isCreatable: boolean; + isUpdatable: boolean; + retrieving: boolean; + template: boolean; + }; + smsTriggeredSendDefinitionId: { + isCreatable: boolean; + isUpdatable: boolean; + retrieving: boolean; + template: boolean; + }; + statistics: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'statistics.outbound': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'statistics.outbound.sent': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'statistics.outbound.delivered': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'statistics.outbound.undelivered': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'statistics.outbound.unknown': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + status: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + statusId: { + isCreatable: boolean; + isUpdatable: boolean; + retrieving: boolean; + template: boolean; + }; + 'subscriptionKeyword.id': { + isCreatable: boolean; + isUpdatable: boolean; + retrieving: boolean; + template: boolean; + }; + 'subscriptionKeyword.keyword': { + isCreatable: boolean; + isUpdatable: boolean; + retrieving: boolean; + template: boolean; + }; + 'subscriptionKeyword.r__mobileKeyword_key': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'subscriptionKeyword.restriction': { + isCreatable: boolean; + isUpdatable: boolean; + retrieving: boolean; + template: boolean; + }; + 'subscriptionKeyword.isInherited': { + isCreatable: boolean; + isUpdatable: boolean; + retrieving: boolean; + template: boolean; + }; + 'nextKeyword.id': { + isCreatable: boolean; + isUpdatable: boolean; + retrieving: boolean; + template: boolean; + }; + 'nextKeyword.keyword': { + isCreatable: boolean; + isUpdatable: boolean; + retrieving: boolean; + template: boolean; + }; + 'nextKeyword.r__mobileKeyword_key': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'nextKeyword.restriction': { + isCreatable: boolean; + isUpdatable: boolean; + retrieving: boolean; + template: boolean; + }; + 'nextKeyword.isInherited': { + isCreatable: boolean; + isUpdatable: boolean; + retrieving: boolean; + template: boolean; + }; + subscriberResponseMessage: { + isCreatable: boolean; + isUpdatable: boolean; + retrieving: boolean; + template: boolean; + }; + surveyCorrectResponseMessage: { + isCreatable: boolean; + isUpdatable: boolean; + retrieving: boolean; + template: boolean; + }; + surveyIncorrectResponseMessage: { + isCreatable: boolean; + isUpdatable: boolean; + retrieving: boolean; + template: boolean; + }; + surveyResponsesAllowed: { + isCreatable: boolean; + isUpdatable: boolean; + retrieving: boolean; + template: boolean; + }; + surveyTooManyEntriesMessage: { + isCreatable: boolean; + isUpdatable: boolean; + retrieving: boolean; + template: boolean; + }; + surveyType: { + isCreatable: boolean; + isUpdatable: boolean; + retrieving: boolean; + template: boolean; + }; + 'template.description': { + isCreatable: boolean; + isUpdatable: boolean; + retrieving: boolean; + template: boolean; + }; + 'template.icon': { + isCreatable: boolean; + isUpdatable: boolean; + retrieving: boolean; + template: boolean; + }; + 'template.id': { + isCreatable: boolean; + isUpdatable: boolean; + retrieving: boolean; + template: boolean; + }; + 'template.lastUpdated': { + isCreatable: boolean; + isUpdatable: boolean; + retrieving: boolean; + template: boolean; + }; + 'template.name': { + isCreatable: boolean; + isUpdatable: boolean; + retrieving: boolean; + template: boolean; + }; + text: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + triggeredSendId: { + isCreatable: boolean; + isUpdatable: boolean; + retrieving: boolean; + template: boolean; + }; + triggeredSendName: { + isCreatable: boolean; + isUpdatable: boolean; + retrieving: boolean; + template: boolean; + }; + type: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + r__campaign_key: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'r__campaign_key[]': { + skipValidation: boolean; + }; + }; + }; +} +import MetadataType from './MetadataType.js'; +//# sourceMappingURL=MobileMessage.d.ts.map \ No newline at end of file diff --git a/@types/lib/metadataTypes/MobileMessage.d.ts.map b/@types/lib/metadataTypes/MobileMessage.d.ts.map new file mode 100644 index 000000000..fae7593f4 --- /dev/null +++ b/@types/lib/metadataTypes/MobileMessage.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"MobileMessage.d.ts","sourceRoot":"","sources":["../../../lib/metadataTypes/MobileMessage.js"],"names":[],"mappings":";uBAQa,OAAO,wBAAwB,EAAE,QAAQ;0BACzC,OAAO,wBAAwB,EAAE,WAAW;8BAC5C,OAAO,wBAAwB,EAAE,eAAe;+BAChD,OAAO,wBAAwB,EAAE,gBAAgB;mCACjD,OAAO,wBAAwB,EAAE,oBAAoB;kCACrD,OAAO,wBAAwB,EAAE,mBAAmB;8BACpD,OAAO,wBAAwB,EAAE,eAAe;iCAChD,OAAO,wBAAwB,EAAE,kBAAkB;gCACnD,OAAO,wBAAwB,EAAE,iBAAiB;0BAClD,OAAO,wBAAwB,EAAE,WAAW;AAVzD;;;;;;;;;;;GAWG;AAEH;;;;GAIG;AACH;IACI;;;;;;;;OAQG;IACH,6BANW,MAAM,MACN,IAAI,GAAG,MAAM,EAAE,OACf,IAAI,GAAG,MAAM,EAAE,QACf,MAAM,GACJ,OAAO,CAAE,kBAAkB,CAAC,CA4BxC;IAED;;;;;;;OAOG;IACH,4BALW,IAAI,GAAG,MAAM,EAAE,OACf,IAAI,GAAG,MAAM,EAAE,QACf,MAAM,GACJ,OAAO,CAAE,kBAAkB,CAAC,CAIxC;IAED;;;;;OAKG;IACH,wBAHW,gBAAgB,gBAS1B;IAED;;;;;OAKG;IACH,wBAHW,gBAAgB,gBAK1B;IAED;;;;;;;OAOG;IACH,4BALW,gBAAgB,aAChB,MAAM,iBACN,MAAM,GACJ,OAAO,CAAE,MAAM,CAAC,CAoB5B;IAED;;;;;OAKG;IACH,+BAHW,MAAM,GACJ;QAAC,OAAO,EAAC,MAAM,CAAC;QAAA,IAAI,EAAC,MAAM,CAAA;KAAC,CAMxC;IAwBD;;;;;OAKG;IACH,mCAHW,gBAAgB,GACd,eAAe,CAuG3B;IAoED;;;;;;OAMG;IACH,sCAJW,gBAAgB,eAChB,MAAM,GACJ,OAAO,CAAE,MAAM,CAAC,CAM5B;IAED;;;;;;OAMG;IACH,sCAJW,gBAAgB,eAChB,MAAM,GACJ,OAAO,CAAE,MAAM,CAAC,CAK5B;IA2DD;;;;;;;;;;;OAWG;IACH,oCARW,MAAM,aACN,MAAM,GAAC,MAAM,EAAE,YACf,gBAAgB,qBAChB,WAAW,gBACX,MAAM,QACN,YAAY,GAAC,UAAU,GACrB,OAAO,CAAE,MAAM,EAAE,EAAE,CAAC,CAsDhC;CAiBJ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;yBAjfwB,mBAAmB"} \ No newline at end of file diff --git a/@types/lib/metadataTypes/Query.d.ts b/@types/lib/metadataTypes/Query.d.ts new file mode 100644 index 000000000..a9e0dec03 --- /dev/null +++ b/@types/lib/metadataTypes/Query.d.ts @@ -0,0 +1,311 @@ +export default Query; +export type BuObject = import("../../types/mcdev.d.js").BuObject; +export type CodeExtract = import("../../types/mcdev.d.js").CodeExtract; +export type CodeExtractItem = import("../../types/mcdev.d.js").CodeExtractItem; +export type MetadataTypeItem = import("../../types/mcdev.d.js").MetadataTypeItem; +export type MetadataTypeItemDiff = import("../../types/mcdev.d.js").MetadataTypeItemDiff; +export type MetadataTypeItemObj = import("../../types/mcdev.d.js").MetadataTypeItemObj; +export type MetadataTypeMap = import("../../types/mcdev.d.js").MetadataTypeMap; +export type MetadataTypeMapObj = import("../../types/mcdev.d.js").MetadataTypeMapObj; +export type SoapRequestParams = import("../../types/mcdev.d.js").SoapRequestParams; +export type TemplateMap = import("../../types/mcdev.d.js").TemplateMap; +export type QueryItem = import("../../types/mcdev.d.js").QueryItem; +export type QueryMap = import("../../types/mcdev.d.js").QueryMap; +/** + * @typedef {import('../../types/mcdev.d.js').BuObject} BuObject + * @typedef {import('../../types/mcdev.d.js').CodeExtract} CodeExtract + * @typedef {import('../../types/mcdev.d.js').CodeExtractItem} CodeExtractItem + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItem} MetadataTypeItem + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItemDiff} MetadataTypeItemDiff + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItemObj} MetadataTypeItemObj + * @typedef {import('../../types/mcdev.d.js').MetadataTypeMap} MetadataTypeMap + * @typedef {import('../../types/mcdev.d.js').MetadataTypeMapObj} MetadataTypeMapObj + * @typedef {import('../../types/mcdev.d.js').SoapRequestParams} SoapRequestParams + * @typedef {import('../../types/mcdev.d.js').TemplateMap} TemplateMap + */ +/** + * @typedef {import('../../types/mcdev.d.js').QueryItem} QueryItem + * @typedef {import('../../types/mcdev.d.js').QueryMap} QueryMap + */ +/** + * Query MetadataType + * + * @augments MetadataType + */ +declare class Query extends MetadataType { + /** + * Retrieves Metadata of queries + * + * @param {string} retrieveDir Directory where retrieved metadata directory will be saved + * @param {void | string[]} [_] unused parameter + * @param {void | string[]} [__] unused parameter + * @param {string} [key] customer key of single item to retrieve + * @returns {Promise.<{metadata: QueryMap, type: string}>} Promise of metadata + */ + static retrieve(retrieveDir: string, _?: void | string[], __?: void | string[], key?: string): Promise<{ + metadata: QueryMap; + type: string; + }>; + /** + * a function to start query execution via API + * + * @param {string[]} keyArr customerkey of the metadata + * @returns {Promise.<string[]>} Returns list of keys that were executed successfully + */ + static execute(keyArr: string[]): Promise<string[]>; + /** + * helper to allow us to select single metadata entries via REST + * + * @private + * @param {string} key customer key + * @returns {Promise.<string>} objectId or enpty string + */ + private static _getObjectIdForSingleRetrieve; + /** + * Retrieves query metadata for caching + * + * @returns {Promise.<{metadata: QueryMap, type: string}>} Promise of metadata + */ + static retrieveForCache(): Promise<{ + metadata: QueryMap; + type: string; + }>; + /** + * Retrieve a specific Query by Name + * + * @deprecated Use `retrieve` followed by `build` instead. `retrieveAsTemplate` will be removed in a future version. + * @param {string} templateDir Directory where retrieved metadata directory will be saved + * @param {string} name name of the metadata file + * @param {TemplateMap} templateVariables variables to be replaced in the metadata + * @returns {Promise.<{metadata: Query, type: string}>} Promise of metadata + */ + static retrieveAsTemplate(templateDir: string, name: string, templateVariables: TemplateMap): Promise<{ + metadata: Query; + type: string; + }>; + /** + * manages post retrieve steps + * + * @param {QueryItem} metadata a single query + * @returns {CodeExtractItem} Array with one metadata object and one query string + */ + static postRetrieveTasks(metadata: QueryItem): CodeExtractItem; + /** + * Creates a single query + * + * @param {QueryItem} query a single query + * @returns {Promise} Promise + */ + static create(query: QueryItem): Promise<any>; + /** + * Updates a single query + * + * @param {QueryItem} query a single query + * @returns {Promise} Promise + */ + static update(query: QueryItem): Promise<any>; + /** + * prepares a Query for deployment + * + * @param {QueryItem} metadata a single query activity + * @param {string} deployDir directory of deploy files + * @returns {Promise.<QueryItem>} Promise + */ + static preDeployTasks(metadata: QueryItem, deployDir: string): Promise<QueryItem>; + /** + * helper for {@link MetadataType.buildDefinition} + * handles extracted code if any are found for complex types + * + * @param {string} templateDir Directory where metadata templates are stored + * @param {string|string[]} targetDir (List of) Directory where built definitions will be saved + * @param {QueryItem} metadata main JSON file that was read from file system + * @param {TemplateMap} templateVariables variables to be replaced in the metadata + * @param {string} templateName name of the template to be built + * @returns {Promise.<string[][]>} list of extracted files with path-parts provided as an array + */ + static buildDefinitionForNested(templateDir: string, targetDir: string | string[], metadata: QueryItem, templateVariables: TemplateMap, templateName: string): Promise<string[][]>; + /** + * helper for {@link MetadataType.buildTemplate} + * handles extracted code if any are found for complex types + * + * @example queries are saved as 1 json and 1 sql file. both files need to be run through templating + * @param {string} templateDir Directory where metadata templates are stored + * @param {string|string[]} targetDir (List of) Directory where built definitions will be saved + * @param {QueryItem} metadata main JSON file that was read from file system + * @param {TemplateMap} templateVariables variables to be replaced in the metadata + * @param {string} templateName name of the template to be built + * @returns {Promise.<string[][]>} list of extracted files with path-parts provided as an array + */ + static buildTemplateForNested(templateDir: string, targetDir: string | string[], metadata: QueryItem, templateVariables: TemplateMap, templateName: string): Promise<string[][]>; + /** + * helper for {@link Query.buildTemplateForNested} / {@link Query.buildDefinitionForNested} + * handles extracted code if any are found for complex types + * + * @private + * @param {string} templateDir Directory where metadata templates are stored + * @param {string|string[]} targetDir (List of) Directory where built definitions will be saved + * @param {QueryItem} metadata main JSON file that was read from file system + * @param {TemplateMap} templateVariables variables to be replaced in the metadata + * @param {string} templateName name of the template to be built + * @param {'definition'|'template'} mode defines what we use this helper for + * @returns {Promise.<string[][]>} list of extracted files with path-parts provided as an array + */ + private static _buildForNested; + /** + * clean up after deleting a metadata item + * + * @param {string} customerKey Identifier of metadata item + * @returns {Promise.<void>} - + */ + static postDeleteTasks(customerKey: string): Promise<void>; + /** + * Gets executed after deployment of metadata type + * + * @param {MetadataTypeMap} upsertResults metadata mapped by their keyField as returned by update/create + */ + static postDeployTasks(upsertResults: MetadataTypeMap): Promise<void>; +} +declare namespace Query { + let definition: { + bodyIteratorField: string; + dependencies: string[]; + dependencyGraph: { + dataExtension: string[]; + }; + folderType: string; + filter: { + description: string[]; + }; + hasExtended: boolean; + idField: string; + keyIsFixed: boolean; + keyField: string; + nameField: string; + folderIdField: string; + createdDateField: string; + createdNameField: any; + lastmodDateField: string; + lastmodNameField: any; + restPagination: boolean; + targetUpdateTypeMapping: { + Append: number; + Overwrite: number; + Update: number; + }; + maxKeyLength: number; + type: string; + typeDescription: string; + typeRetrieveByDefault: boolean; + typeCdpByDefault: boolean; + typeName: string; + fields: { + categoryId: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + createdDate: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + description: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + isFrozen: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + key: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + modifiedDate: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + name: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + queryDefinitionId: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + queryText: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + targetDescription: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + targetId: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + targetKey: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + targetName: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + targetUpdateTypeId: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + targetUpdateTypeName: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + validatedQueryText: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + r__dataExtension_key: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + r__folder_Path: { + skipValidation: boolean; + }; + }; + }; +} +import MetadataType from './MetadataType.js'; +//# sourceMappingURL=Query.d.ts.map \ No newline at end of file diff --git a/@types/lib/metadataTypes/Query.d.ts.map b/@types/lib/metadataTypes/Query.d.ts.map new file mode 100644 index 000000000..dc30fbb57 --- /dev/null +++ b/@types/lib/metadataTypes/Query.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"Query.d.ts","sourceRoot":"","sources":["../../../lib/metadataTypes/Query.js"],"names":[],"mappings":";uBAQa,OAAO,wBAAwB,EAAE,QAAQ;0BACzC,OAAO,wBAAwB,EAAE,WAAW;8BAC5C,OAAO,wBAAwB,EAAE,eAAe;+BAChD,OAAO,wBAAwB,EAAE,gBAAgB;mCACjD,OAAO,wBAAwB,EAAE,oBAAoB;kCACrD,OAAO,wBAAwB,EAAE,mBAAmB;8BACpD,OAAO,wBAAwB,EAAE,eAAe;iCAChD,OAAO,wBAAwB,EAAE,kBAAkB;gCACnD,OAAO,wBAAwB,EAAE,iBAAiB;0BAClD,OAAO,wBAAwB,EAAE,WAAW;wBAI5C,OAAO,wBAAwB,EAAE,SAAS;uBAC1C,OAAO,wBAAwB,EAAE,QAAQ;AAftD;;;;;;;;;;;GAWG;AAEH;;;GAGG;AAEH;;;;GAIG;AACH;IACI;;;;;;;;OAQG;IACH,6BANW,MAAM,MACN,IAAI,GAAG,MAAM,EAAE,OACf,IAAI,GAAG,MAAM,EAAE,QACf,MAAM,GACJ,OAAO,CAAE;QAAC,QAAQ,EAAE,QAAQ,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAC,CAAC,CAsBxD;IAED;;;;;OAKG;IACH,uBAHW,MAAM,EAAE,GACN,OAAO,CAAE,MAAM,EAAE,CAAC,CAuB9B;IAED;;;;;;OAMG;IACH,6CAiBC;IAED;;;;OAIG;IACH,2BAFa,OAAO,CAAE;QAAC,QAAQ,EAAE,QAAQ,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAC,CAAC,CAIxD;IAED;;;;;;;;OAQG;IACH,uCALW,MAAM,QACN,MAAM,qBACN,WAAW,GACT,OAAO,CAAE;QAAC,QAAQ,EAAE,KAAK,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAC,CAAC,CAUrD;IAED;;;;;OAKG;IACH,mCAHW,SAAS,GACP,eAAe,CAwD3B;IAED;;;;;OAKG;IACH,qBAHW,SAAS,gBAMnB;IAED;;;;;OAKG;IACH,qBAHW,SAAS,gBAMnB;IAED;;;;;;OAMG;IACH,gCAJW,SAAS,aACT,MAAM,GACJ,OAAO,CAAE,SAAS,CAAC,CAiD/B;IA0BD;;;;;;;;;;OAUG;IACH,6CAPW,MAAM,aACN,MAAM,GAAC,MAAM,EAAE,YACf,SAAS,qBACT,WAAW,gBACX,MAAM,GACJ,OAAO,CAAE,MAAM,EAAE,EAAE,CAAC,CAiBhC;IAED;;;;;;;;;;;OAWG;IACH,2CAPW,MAAM,aACN,MAAM,GAAC,MAAM,EAAE,YACf,SAAS,qBACT,WAAW,gBACX,MAAM,GACJ,OAAO,CAAE,MAAM,EAAE,EAAE,CAAC,CAiBhC;IAED;;;;;;;;;;;;OAYG;IACH,+BAkDC;IAsDD;;;;;OAKG;IACH,oCAHW,MAAM,GACJ,OAAO,CAAE,IAAI,CAAC,CAM1B;IAED;;;;OAIG;IACH,sCAFW,eAAe,iBAOzB;CACJ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;yBAvfwB,mBAAmB"} \ No newline at end of file diff --git a/@types/lib/metadataTypes/Role.d.ts b/@types/lib/metadataTypes/Role.d.ts new file mode 100644 index 000000000..14751cc91 --- /dev/null +++ b/@types/lib/metadataTypes/Role.d.ts @@ -0,0 +1,173 @@ +export default Role; +export type BuObject = import("../../types/mcdev.d.js").BuObject; +export type CodeExtract = import("../../types/mcdev.d.js").CodeExtract; +export type CodeExtractItem = import("../../types/mcdev.d.js").CodeExtractItem; +export type MetadataTypeItem = import("../../types/mcdev.d.js").MetadataTypeItem; +export type MetadataTypeItemDiff = import("../../types/mcdev.d.js").MetadataTypeItemDiff; +export type MetadataTypeItemObj = import("../../types/mcdev.d.js").MetadataTypeItemObj; +export type MetadataTypeMap = import("../../types/mcdev.d.js").MetadataTypeMap; +export type MetadataTypeMapObj = import("../../types/mcdev.d.js").MetadataTypeMapObj; +export type SoapRequestParams = import("../../types/mcdev.d.js").SoapRequestParams; +export type SoapSDKFilterSimple = import("../../types/mcdev.d.js").SoapSDKFilterSimple; +export type TemplateMap = import("../../types/mcdev.d.js").TemplateMap; +/** + * @typedef {import('../../types/mcdev.d.js').BuObject} BuObject + * @typedef {import('../../types/mcdev.d.js').CodeExtract} CodeExtract + * @typedef {import('../../types/mcdev.d.js').CodeExtractItem} CodeExtractItem + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItem} MetadataTypeItem + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItemDiff} MetadataTypeItemDiff + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItemObj} MetadataTypeItemObj + * @typedef {import('../../types/mcdev.d.js').MetadataTypeMap} MetadataTypeMap + * @typedef {import('../../types/mcdev.d.js').MetadataTypeMapObj} MetadataTypeMapObj + * @typedef {import('../../types/mcdev.d.js').SoapRequestParams} SoapRequestParams + * @typedef {import('../../types/mcdev.d.js').SoapSDKFilterSimple} SoapSDKFilterSimple + * @typedef {import('../../types/mcdev.d.js').TemplateMap} TemplateMap + */ +/** + * ImportFile MetadataType + * + * @augments MetadataType + */ +declare class Role extends MetadataType { + /** + * Gets metadata from Marketing Cloud + * + * @param {string} retrieveDir Directory where retrieved metadata directory will be saved + * @param {void | string[]} [_] Returns specified fields even if their retrieve definition is not set to true + * @param {void | string[]} [___] unused parameter + * @param {string} [key] customer key of single item to retrieve + * @returns {Promise.<MetadataTypeMapObj>} Metadata store object + */ + static retrieve(retrieveDir: string, _?: void | string[], ___?: void | string[], key?: string): Promise<MetadataTypeMapObj>; + /** + * adds default roles to the list of retrieved roles for proper caching (but not storing) + * also caches available timezones for retrieve-user + * + * @param {MetadataTypeMap} parsed list or previously retrieved items as reference + */ + static cacheDefaultRolesAndTimezones(parsed: MetadataTypeMap): Promise<void>; + /** + * Gets executed before deploying metadata + * + * @param {MetadataTypeItem} metadata a single metadata item + * @returns {MetadataTypeItem} Promise of a single metadata item + */ + static preDeployTasks(metadata: MetadataTypeItem): MetadataTypeItem; + /** + * Create a single Role. + * + * @param {MetadataTypeItem} metadata single metadata entry + * @returns {Promise} Promise + */ + static create(metadata: MetadataTypeItem): Promise<any>; + /** + * Updates a single Role. + * + * @param {MetadataTypeItem} metadata single metadata entry + * @returns {Promise} Promise + */ + static update(metadata: MetadataTypeItem): Promise<any>; + /** + * Creates markdown documentation of all roles + * + * @param {MetadataTypeMap} [metadata] role definitions + * @returns {Promise.<void>} - + */ + static document(metadata?: MetadataTypeMap): Promise<void>; + /** + * iterates through permissions to output proper row-names for nested permissionss + * + * @static + * @param {string} role name of the user role + * @param {object} element data of the permission + * @param {string} [permission] name of the permission + * @param {string} [isAllowed] "true" / "false" from the parent + * @memberof Role + * @returns {void} + */ + static _traverseRoles(role: string, element: object, permission?: string, isAllowed?: string): void; +} +declare namespace Role { + let allPermissions: {}; + let definition: { + bodyIteratorField: string; + dependencies: any[]; + dependencyGraph: any; + deployBlacklist: string[]; + documentInOneFile: boolean; + hasExtended: boolean; + idField: string; + keyIsFixed: boolean; + keyField: string; + nameField: string; + createdDateField: string; + createdNameField: any; + lastmodDateField: string; + lastmodNameField: any; + maxKeyLength: number; + type: string; + typeDescription: string; + typeRetrieveByDefault: boolean; + typeCdpByDefault: boolean; + typeName: string; + fields: { + CreatedDate: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + CustomerKey: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + Description: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + ModifiedDate: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + Name: { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + }; + ObjectID: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + PartnerKey: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + IsSystemDefined: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + PermissionSets: { + retrieving: boolean; + skipCache: boolean; + skipValidation: boolean; + }; + c__notAssignable: { + skipValidation: boolean; + }; + }; + }; +} +import MetadataType from './MetadataType.js'; +//# sourceMappingURL=Role.d.ts.map \ No newline at end of file diff --git a/@types/lib/metadataTypes/Role.d.ts.map b/@types/lib/metadataTypes/Role.d.ts.map new file mode 100644 index 000000000..8b9aabd42 --- /dev/null +++ b/@types/lib/metadataTypes/Role.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"Role.d.ts","sourceRoot":"","sources":["../../../lib/metadataTypes/Role.js"],"names":[],"mappings":";uBAQa,OAAO,wBAAwB,EAAE,QAAQ;0BACzC,OAAO,wBAAwB,EAAE,WAAW;8BAC5C,OAAO,wBAAwB,EAAE,eAAe;+BAChD,OAAO,wBAAwB,EAAE,gBAAgB;mCACjD,OAAO,wBAAwB,EAAE,oBAAoB;kCACrD,OAAO,wBAAwB,EAAE,mBAAmB;8BACpD,OAAO,wBAAwB,EAAE,eAAe;iCAChD,OAAO,wBAAwB,EAAE,kBAAkB;gCACnD,OAAO,wBAAwB,EAAE,iBAAiB;kCAClD,OAAO,wBAAwB,EAAE,mBAAmB;0BACpD,OAAO,wBAAwB,EAAE,WAAW;AAXzD;;;;;;;;;;;;GAYG;AAEH;;;;GAIG;AACH;IACI;;;;;;;;OAQG;IACH,6BANW,MAAM,MACN,IAAI,GAAG,MAAM,EAAE,QACf,IAAI,GAAG,MAAM,EAAE,QACf,MAAM,GACJ,OAAO,CAAE,kBAAkB,CAAC,CAsDxC;IAED;;;;;OAKG;IACH,6CAFW,eAAe,iBAsCzB;IAED;;;;;OAKG;IACH,gCAHW,gBAAgB,GACd,gBAAgB,CAS5B;IAED;;;;;OAKG;IACH,wBAHW,gBAAgB,gBAK1B;IAED;;;;;OAKG;IACH,wBAHW,gBAAgB,gBAK1B;IAED;;;;;OAKG;IACH,2BAHW,eAAe,GACb,OAAO,CAAE,IAAI,CAAC,CA4G1B;IAED;;;;;;;;;;OAUG;IACH,4BAPW,MAAM,WACN,MAAM,eACN,MAAM,cACN,MAAM,GAEJ,IAAI,CAyDhB;CACJ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;yBA5VwB,mBAAmB"} \ No newline at end of file diff --git a/@types/lib/metadataTypes/Script.d.ts b/@types/lib/metadataTypes/Script.d.ts new file mode 100644 index 000000000..1db5d36b2 --- /dev/null +++ b/@types/lib/metadataTypes/Script.d.ts @@ -0,0 +1,314 @@ +export default Script; +export type BuObject = import("../../types/mcdev.d.js").BuObject; +export type CodeExtract = import("../../types/mcdev.d.js").CodeExtract; +export type CodeExtractItem = import("../../types/mcdev.d.js").CodeExtractItem; +export type MetadataTypeItem = import("../../types/mcdev.d.js").MetadataTypeItem; +export type MetadataTypeItemDiff = import("../../types/mcdev.d.js").MetadataTypeItemDiff; +export type MetadataTypeItemObj = import("../../types/mcdev.d.js").MetadataTypeItemObj; +export type MetadataTypeMap = import("../../types/mcdev.d.js").MetadataTypeMap; +export type MetadataTypeMapObj = import("../../types/mcdev.d.js").MetadataTypeMapObj; +export type SoapRequestParams = import("../../types/mcdev.d.js").SoapRequestParams; +export type TemplateMap = import("../../types/mcdev.d.js").TemplateMap; +export type ContentBlockConversionTypes = import("../../types/mcdev.d.js").ContentBlockConversionTypes; +export type ScriptItem = import("../../types/mcdev.d.js").ScriptItem; +export type ScriptMap = import("../../types/mcdev.d.js").ScriptMap; +/** + * @typedef {import('../../types/mcdev.d.js').BuObject} BuObject + * @typedef {import('../../types/mcdev.d.js').CodeExtract} CodeExtract + * @typedef {import('../../types/mcdev.d.js').CodeExtractItem} CodeExtractItem + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItem} MetadataTypeItem + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItemDiff} MetadataTypeItemDiff + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItemObj} MetadataTypeItemObj + * @typedef {import('../../types/mcdev.d.js').MetadataTypeMap} MetadataTypeMap + * @typedef {import('../../types/mcdev.d.js').MetadataTypeMapObj} MetadataTypeMapObj + * @typedef {import('../../types/mcdev.d.js').SoapRequestParams} SoapRequestParams + * @typedef {import('../../types/mcdev.d.js').TemplateMap} TemplateMap + * @typedef {import('../../types/mcdev.d.js').ContentBlockConversionTypes} ContentBlockConversionTypes + */ +/** + * @typedef {import('../../types/mcdev.d.js').ScriptItem} ScriptItem + * @typedef {import('../../types/mcdev.d.js').ScriptMap} ScriptMap + */ +/** + * Script MetadataType + * + * @augments MetadataType + */ +declare class Script extends MetadataType { + /** + * Retrieves Metadata of Script + * Endpoint /automation/v1/scripts/ return all Scripts with all details. + * + * @param {string} [retrieveDir] Directory where retrieved metadata directory will be saved + * @param {void | string[]} [_] unused parameter + * @param {void | string[]} [__] unused parameter + * @param {string} [key] customer key of single item to retrieve + * @returns {Promise.<{metadata: ScriptMap, type: string}>} Promise + */ + static retrieve(retrieveDir?: string, _?: void | string[], __?: void | string[], key?: string): Promise<{ + metadata: ScriptMap; + type: string; + }>; + /** + * Retrieves script metadata for caching + * + * @returns {Promise.<{metadata: ScriptMap, type: string}>} Promise + */ + static retrieveForCache(): Promise<{ + metadata: ScriptMap; + type: string; + }>; + /** + * Retrieve a specific Script by Name + * + * @deprecated Use `retrieve` followed by `build` instead. `retrieveAsTemplate` will be removed in a future version. + * @param {string} templateDir Directory where retrieved metadata directory will be saved + * @param {string} name name of the metadata file + * @param {TemplateMap} templateVariables variables to be replaced in the metadata + * @returns {Promise.<{metadata: ScriptItem, type: string}>} Promise + */ + static retrieveAsTemplate(templateDir: string, name: string, templateVariables: TemplateMap): Promise<{ + metadata: ScriptItem; + type: string; + }>; + /** + * Updates a single Script + * + * @param {MetadataTypeItem} script a single Script + * @returns {Promise} Promise + */ + static update(script: MetadataTypeItem): Promise<any>; + /** + * helper for {@link MetadataType.updateREST} and {@link MetadataType.updateSOAP} + * + * @param {MetadataTypeItem} metadataEntry a single metadata Entry + * @param {object} apiResponse varies depending on the API call + * @returns {Promise.<object>} apiResponse, potentially modified + */ + static postUpdateTasks(metadataEntry: MetadataTypeItem, apiResponse: object): Promise<object>; + /** + * Creates a single Script + * + * @param {MetadataTypeItem} script a single Script + * @returns {Promise} Promise + */ + static create(script: MetadataTypeItem): Promise<any>; + /** + * helper for {@link Script.preDeployTasks} that loads extracted code content back into JSON + * + * @param {ScriptItem} metadata a single asset definition + * @param {string} deployDir directory of deploy files + * @param {string} [templateName] name of the template used to built defintion (prior applying templating) + * @returns {Promise.<string>} content for metadata.script + */ + static _mergeCode(metadata: ScriptItem, deployDir: string, templateName?: string): Promise<string>; + /** + * prepares a Script for deployment + * + * @param {ScriptItem} metadata a single script activity definition + * @param {string} dir directory of deploy files + * @returns {Promise.<ScriptItem>} Promise + */ + static preDeployTasks(metadata: ScriptItem, dir: string): Promise<ScriptItem>; + /** + * helper for {@link MetadataType.buildDefinition} + * handles extracted code if any are found for complex types + * + * @param {string} templateDir Directory where metadata templates are stored + * @param {string|string[]} targetDir (List of) Directory where built definitions will be saved + * @param {ScriptItem} metadata main JSON file that was read from file system + * @param {TemplateMap} templateVariables variables to be replaced in the metadata + * @param {string} templateName name of the template to be built + * @returns {Promise.<string[][]>} list of extracted files with path-parts provided as an array + */ + static buildDefinitionForNested(templateDir: string, targetDir: string | string[], metadata: ScriptItem, templateVariables: TemplateMap, templateName: string): Promise<string[][]>; + /** + * helper for {@link MetadataType.buildTemplate} + * handles extracted code if any are found for complex types + * + * @example scripts are saved as 1 json and 1 ssjs file. both files need to be run through templating + * @param {string} templateDir Directory where metadata templates are stored + * @param {string|string[]} targetDir (List of) Directory where built definitions will be saved + * @param {ScriptItem} metadata main JSON file that was read from file system + * @param {TemplateMap} templateVariables variables to be replaced in the metadata + * @param {string} templateName name of the template to be built + * @returns {Promise.<string[][]>} list of extracted files with path-parts provided as an array + */ + static buildTemplateForNested(templateDir: string, targetDir: string | string[], metadata: ScriptItem, templateVariables: TemplateMap, templateName: string): Promise<string[][]>; + /** + * helper for {@link Script.buildTemplateForNested} / {@link Script.buildDefinitionForNested} + * handles extracted code if any are found for complex types + * + * @param {string} templateDir Directory where metadata templates are stored + * @param {string|string[]} targetDir (List of) Directory where built definitions will be saved + * @param {ScriptItem} metadata main JSON file that was read from file system + * @param {TemplateMap} templateVariables variables to be replaced in the metadata + * @param {string} templateName name of the template to be built + * @param {'definition'|'template'} mode defines what we use this helper for + * @returns {Promise.<string[][]>} list of extracted files with path-parts provided as an array + */ + static _buildForNested(templateDir: string, targetDir: string | string[], metadata: ScriptItem, templateVariables: TemplateMap, templateName: string, mode: "definition" | "template"): Promise<string[][]>; + /** + * manages post retrieve steps + * + * @param {ScriptItem} metadata a single item + * @returns {CodeExtractItem} a single item with code parts extracted + */ + static postRetrieveTasks(metadata: ScriptItem): CodeExtractItem; + /** + * manages post retrieve steps + * + * @param {ScriptItem} metadata a single item + * @returns {CodeExtractItem} a single item with code parts extracted + */ + static getCodeExtractItem(metadata: ScriptItem): CodeExtractItem; + /** + * helper for {@link Script.postRetrieveTasks} and {@link Script._buildForNested} + * + * @param {string} metadataScript the code of the file + * @param {string} metadataName the name of the metadata + * @returns {{fileExt:string,code:string}} returns found extension and file content + */ + static prepExtractedCode(metadataScript: string, metadataName: string): { + fileExt: string; + code: string; + }; + /** + * helper to allow us to select single metadata entries via REST + * + * @private + * @param {string} key customer key + * @returns {Promise.<string>} objectId or enpty string + */ + private static _getObjectIdForSingleRetrieve; + /** + * clean up after deleting a metadata item + * + * @param {string} customerKey Identifier of metadata item + * @returns {Promise.<void>} - + */ + static postDeleteTasks(customerKey: string): Promise<void>; + /** + * + * @param {MetadataTypeItem} item single metadata item + * @param {string} retrieveDir directory where metadata is saved + * @param {Set.<string>} [findAssetKeys] list of keys that were found referenced via ContentBlockByX; if set, method only gets keys and runs no updates + * @returns {Promise.<CodeExtractItem>} key of the item that was updated + */ + static replaceCbReference(item: MetadataTypeItem, retrieveDir: string, findAssetKeys?: Set<string>): Promise<CodeExtractItem>; +} +declare namespace Script { + let definition: { + bodyIteratorField: string; + dependencies: string[]; + dependencyGraph: any; + folderType: string; + hasExtended: boolean; + idField: string; + keyIsFixed: boolean; + keyField: string; + nameField: string; + folderIdField: string; + createdDateField: string; + createdNameField: any; + lastmodDateField: string; + lastmodNameField: any; + restPagination: boolean; + type: string; + typeDescription: string; + typeRetrieveByDefault: boolean; + typeCdpByDefault: boolean; + typeName: string; + fields: { + categoryId: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + createdBy: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + createdDate: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + description: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + folderLocationText: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + key: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + modifiedBy: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + modifiedDate: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + name: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + script: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + ssjsActivityId: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + status: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + statusId: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + parentCategoryId: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + r__folder_Path: { + skipValidation: boolean; + }; + }; + }; +} +import MetadataType from './MetadataType.js'; +//# sourceMappingURL=Script.d.ts.map \ No newline at end of file diff --git a/@types/lib/metadataTypes/Script.d.ts.map b/@types/lib/metadataTypes/Script.d.ts.map new file mode 100644 index 000000000..9cf9d52cf --- /dev/null +++ b/@types/lib/metadataTypes/Script.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"Script.d.ts","sourceRoot":"","sources":["../../../lib/metadataTypes/Script.js"],"names":[],"mappings":";uBAQa,OAAO,wBAAwB,EAAE,QAAQ;0BACzC,OAAO,wBAAwB,EAAE,WAAW;8BAC5C,OAAO,wBAAwB,EAAE,eAAe;+BAChD,OAAO,wBAAwB,EAAE,gBAAgB;mCACjD,OAAO,wBAAwB,EAAE,oBAAoB;kCACrD,OAAO,wBAAwB,EAAE,mBAAmB;8BACpD,OAAO,wBAAwB,EAAE,eAAe;iCAChD,OAAO,wBAAwB,EAAE,kBAAkB;gCACnD,OAAO,wBAAwB,EAAE,iBAAiB;0BAClD,OAAO,wBAAwB,EAAE,WAAW;0CAC5C,OAAO,wBAAwB,EAAE,2BAA2B;yBAI5D,OAAO,wBAAwB,EAAE,UAAU;wBAC3C,OAAO,wBAAwB,EAAE,SAAS;AAhBvD;;;;;;;;;;;;GAYG;AAEH;;;GAGG;AAEH;;;;GAIG;AACH;IACI;;;;;;;;;OASG;IACH,8BANW,MAAM,MACN,IAAI,GAAG,MAAM,EAAE,OACf,IAAI,GAAG,MAAM,EAAE,QACf,MAAM,GACJ,OAAO,CAAE;QAAC,QAAQ,EAAE,SAAS,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAC,CAAC,CAKzD;IAED;;;;OAIG;IACH,2BAFa,OAAO,CAAE;QAAC,QAAQ,EAAE,SAAS,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAC,CAAC,CAIzD;IAED;;;;;;;;OAQG;IACH,uCALW,MAAM,QACN,MAAM,qBACN,WAAW,GACT,OAAO,CAAE;QAAC,QAAQ,EAAE,UAAU,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAC,CAAC,CAU1D;IAED;;;;;OAKG;IACH,sBAHW,gBAAgB,gBAK1B;IAED;;;;;;OAMG;IACH,sCAJW,gBAAgB,eAChB,MAAM,GACJ,OAAO,CAAE,MAAM,CAAC,CAS5B;IAED;;;;;OAKG;IACH,sBAHW,gBAAgB,gBAK1B;IAED;;;;;;;OAOG;IACH,4BALW,UAAU,aACV,MAAM,iBACN,MAAM,GACJ,OAAO,CAAE,MAAM,CAAC,CA4B5B;IAED;;;;;;OAMG;IACH,gCAJW,UAAU,OACV,MAAM,GACJ,OAAO,CAAE,UAAU,CAAC,CAUhC;IAED;;;;;;;;;;OAUG;IACH,6CAPW,MAAM,aACN,MAAM,GAAC,MAAM,EAAE,YACf,UAAU,qBACV,WAAW,gBACX,MAAM,GACJ,OAAO,CAAE,MAAM,EAAE,EAAE,CAAC,CAiBhC;IAED;;;;;;;;;;;OAWG;IACH,2CAPW,MAAM,aACN,MAAM,GAAC,MAAM,EAAE,YACf,UAAU,qBACV,WAAW,gBACX,MAAM,GACJ,OAAO,CAAE,MAAM,EAAE,EAAE,CAAC,CAiBhC;IAED;;;;;;;;;;;OAWG;IACH,oCARW,MAAM,aACN,MAAM,GAAC,MAAM,EAAE,YACf,UAAU,qBACV,WAAW,gBACX,MAAM,QACN,YAAY,GAAC,UAAU,GACrB,OAAO,CAAE,MAAM,EAAE,EAAE,CAAC,CAsDhC;IAED;;;;;OAKG;IACH,mCAHW,UAAU,GACR,eAAe,CAO3B;IAED;;;;;OAKG;IACH,oCAHW,UAAU,GACR,eAAe,CAgB3B;IAED;;;;;;OAMG;IACH,yCAJW,MAAM,gBACN,MAAM,GACJ;QAAC,OAAO,EAAC,MAAM,CAAC;QAAA,IAAI,EAAC,MAAM,CAAA;KAAC,CAiBxC;IAyBD;;;;;;OAMG;IACH,6CAWC;IAkBD;;;;;OAKG;IACH,oCAHW,MAAM,GACJ,OAAO,CAAE,IAAI,CAAC,CAU1B;IAED;;;;;;OAMG;IACH,gCALW,gBAAgB,eAChB,MAAM,kBACN,GAAG,CAAE,MAAM,CAAC,GACV,OAAO,CAAE,eAAe,CAAC,CAarC;CACJ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;yBAtbwB,mBAAmB"} \ No newline at end of file diff --git a/@types/lib/metadataTypes/SendClassification.d.ts b/@types/lib/metadataTypes/SendClassification.d.ts new file mode 100644 index 000000000..211298ae1 --- /dev/null +++ b/@types/lib/metadataTypes/SendClassification.d.ts @@ -0,0 +1,244 @@ +export default SendClassification; +export type BuObject = import("../../types/mcdev.d.js").BuObject; +export type CodeExtract = import("../../types/mcdev.d.js").CodeExtract; +export type CodeExtractItem = import("../../types/mcdev.d.js").CodeExtractItem; +export type MetadataTypeItem = import("../../types/mcdev.d.js").MetadataTypeItem; +export type MetadataTypeItemDiff = import("../../types/mcdev.d.js").MetadataTypeItemDiff; +export type MetadataTypeItemObj = import("../../types/mcdev.d.js").MetadataTypeItemObj; +export type MetadataTypeMap = import("../../types/mcdev.d.js").MetadataTypeMap; +export type MetadataTypeMapObj = import("../../types/mcdev.d.js").MetadataTypeMapObj; +export type SoapRequestParams = import("../../types/mcdev.d.js").SoapRequestParams; +export type TemplateMap = import("../../types/mcdev.d.js").TemplateMap; +/** + * @typedef {import('../../types/mcdev.d.js').BuObject} BuObject + * @typedef {import('../../types/mcdev.d.js').CodeExtract} CodeExtract + * @typedef {import('../../types/mcdev.d.js').CodeExtractItem} CodeExtractItem + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItem} MetadataTypeItem + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItemDiff} MetadataTypeItemDiff + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItemObj} MetadataTypeItemObj + * @typedef {import('../../types/mcdev.d.js').MetadataTypeMap} MetadataTypeMap + * @typedef {import('../../types/mcdev.d.js').MetadataTypeMapObj} MetadataTypeMapObj + * @typedef {import('../../types/mcdev.d.js').SoapRequestParams} SoapRequestParams + * @typedef {import('../../types/mcdev.d.js').TemplateMap} TemplateMap + */ +/** + * SendClassification MetadataType + * + * @augments MetadataType + */ +declare class SendClassification extends MetadataType { + /** + * Retrieves SOAP based metadata of metadata type into local filesystem. executes callback with retrieved metadata + * + * @param {string} retrieveDir Directory where retrieved metadata directory will be saved + * @param {void | string[]} [_] unused parameter + * @param {void | string[]} [__] unused parameter + * @param {string} [key] customer key of single item to retrieve + * @returns {Promise.<MetadataTypeMapObj>} Promise of metadata + */ + static retrieve(retrieveDir: string, _?: void | string[], __?: void | string[], key?: string): Promise<MetadataTypeMapObj>; + /** + * Retrieves event definition metadata for caching + * + * @returns {Promise.<MetadataTypeMapObj>} Promise of metadata + */ + static retrieveForCache(): Promise<MetadataTypeMapObj>; + /** + * Updates a single item + * + * @param {MetadataTypeItem} metadataItem a single item + * @returns {Promise} Promise + */ + static update(metadataItem: MetadataTypeItem): Promise<any>; + /** + * Creates a single item + * + * @param {MetadataTypeItem} metadataItem a single item + * @returns {Promise} Promise + */ + static create(metadataItem: MetadataTypeItem): Promise<any>; + /** + * prepares a import definition for deployment + * + * @param {MetadataTypeItem} metadata a single importDef + * @returns {Promise.<MetadataTypeItem>} Promise + */ + static preDeployTasks(metadata: MetadataTypeItem): Promise<MetadataTypeItem>; + /** + * Gets executed after deployment of metadata type + * + * @param {MetadataTypeMap} upsertResults metadata mapped by their keyField as returned by update/create + * @returns {Promise.<void>} - + */ + static postDeployTasks(upsertResults: MetadataTypeMap): Promise<void>; + /** + * manages post retrieve steps + * + * @param {MetadataTypeItem} metadata a single item + * @returns {MetadataTypeItem} parsed metadata + */ + static postRetrieveTasks(metadata: MetadataTypeItem): MetadataTypeItem; + /** + * this is the only known way to get the object ID for a deliveryProfile + * + * @param {MetadataTypeItem} metadata a single sendClassification item + */ + static updateDeliveryProfileIdInCache(metadata: MetadataTypeItem): void; +} +declare namespace SendClassification { + let definition: { + bodyIteratorField: string; + dependencies: string[]; + dependencyGraph: { + senderProfile: string[]; + }; + filter: {}; + hasExtended: boolean; + idField: string; + keyField: string; + keyIsFixed: boolean; + maxKeyLength: number; + nameField: string; + createdDateField: string; + createdNameField: any; + lastmodDateField: string; + lastmodNameField: any; + restPagination: boolean; + type: string; + typeDescription: string; + typeRetrieveByDefault: boolean; + typeCdpByDefault: boolean; + typeName: string; + sendClassificationTypeMapping: { + Commercial: string; + Transactional: string; + }; + fields: { + 'Client.ID': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + CreatedDate: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + ModifiedDate: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + CustomerKey: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + ObjectID: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + Name: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + Description: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + PartnerKey: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + PartnerProperties: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + ArchiveEmail: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'DeliveryProfile.CustomerKey': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'DeliveryProfile.PartnerKey': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'DeliveryProfile.ObjectID': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + HonorPublicationListOptOutsForTransactionalSends: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + SendClassificationType: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'SenderProfile.CustomerKey': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'SenderProfile.PartnerKey': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'SenderProfile.ObjectID': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + SendPriority: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + c__classification: { + skipValidation: boolean; + }; + r__deliveryProfile_key: { + skipValidation: boolean; + }; + r__senderProfile_key: { + skipValidation: boolean; + }; + }; + }; +} +import MetadataType from './MetadataType.js'; +//# sourceMappingURL=SendClassification.d.ts.map \ No newline at end of file diff --git a/@types/lib/metadataTypes/SendClassification.d.ts.map b/@types/lib/metadataTypes/SendClassification.d.ts.map new file mode 100644 index 000000000..16465304d --- /dev/null +++ b/@types/lib/metadataTypes/SendClassification.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"SendClassification.d.ts","sourceRoot":"","sources":["../../../lib/metadataTypes/SendClassification.js"],"names":[],"mappings":";uBAQa,OAAO,wBAAwB,EAAE,QAAQ;0BACzC,OAAO,wBAAwB,EAAE,WAAW;8BAC5C,OAAO,wBAAwB,EAAE,eAAe;+BAChD,OAAO,wBAAwB,EAAE,gBAAgB;mCACjD,OAAO,wBAAwB,EAAE,oBAAoB;kCACrD,OAAO,wBAAwB,EAAE,mBAAmB;8BACpD,OAAO,wBAAwB,EAAE,eAAe;iCAChD,OAAO,wBAAwB,EAAE,kBAAkB;gCACnD,OAAO,wBAAwB,EAAE,iBAAiB;0BAClD,OAAO,wBAAwB,EAAE,WAAW;AAVzD;;;;;;;;;;;GAWG;AAEH;;;;GAIG;AACH;IACI;;;;;;;;OAQG;IACH,6BANW,MAAM,MACN,IAAI,GAAG,MAAM,EAAE,OACf,IAAI,GAAG,MAAM,EAAE,QACf,MAAM,GACJ,OAAO,CAAE,kBAAkB,CAAC,CAexC;IAED;;;;OAIG;IACH,2BAFa,OAAO,CAAE,kBAAkB,CAAC,CAWxC;IAED;;;;;OAKG;IACH,4BAHW,gBAAgB,gBAK1B;IAED;;;;;OAKG;IACH,4BAHW,gBAAgB,gBAK1B;IAYD;;;;;OAKG;IACH,gCAHW,gBAAgB,GACd,OAAO,CAAE,gBAAgB,CAAC,CAkCtC;IAED;;;;;OAKG;IACH,sCAHW,eAAe,GACb,OAAO,CAAE,IAAI,CAAC,CAc1B;IAED;;;;;OAKG;IACH,mCAHW,gBAAgB,GACd,gBAAgB,CAuC5B;IAED;;;;OAIG;IACH,gDAFW,gBAAgB,QAW1B;CACJ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;yBAtNwB,mBAAmB"} \ No newline at end of file diff --git a/@types/lib/metadataTypes/SenderProfile.d.ts b/@types/lib/metadataTypes/SenderProfile.d.ts new file mode 100644 index 000000000..d325021e0 --- /dev/null +++ b/@types/lib/metadataTypes/SenderProfile.d.ts @@ -0,0 +1,304 @@ +export default SenderProfile; +export type BuObject = import("../../types/mcdev.d.js").BuObject; +export type CodeExtract = import("../../types/mcdev.d.js").CodeExtract; +export type CodeExtractItem = import("../../types/mcdev.d.js").CodeExtractItem; +export type MetadataTypeItem = import("../../types/mcdev.d.js").MetadataTypeItem; +export type MetadataTypeItemDiff = import("../../types/mcdev.d.js").MetadataTypeItemDiff; +export type MetadataTypeItemObj = import("../../types/mcdev.d.js").MetadataTypeItemObj; +export type MetadataTypeMap = import("../../types/mcdev.d.js").MetadataTypeMap; +export type MetadataTypeMapObj = import("../../types/mcdev.d.js").MetadataTypeMapObj; +export type SoapRequestParams = import("../../types/mcdev.d.js").SoapRequestParams; +export type TemplateMap = import("../../types/mcdev.d.js").TemplateMap; +/** + * @typedef {import('../../types/mcdev.d.js').BuObject} BuObject + * @typedef {import('../../types/mcdev.d.js').CodeExtract} CodeExtract + * @typedef {import('../../types/mcdev.d.js').CodeExtractItem} CodeExtractItem + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItem} MetadataTypeItem + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItemDiff} MetadataTypeItemDiff + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItemObj} MetadataTypeItemObj + * @typedef {import('../../types/mcdev.d.js').MetadataTypeMap} MetadataTypeMap + * @typedef {import('../../types/mcdev.d.js').MetadataTypeMapObj} MetadataTypeMapObj + * @typedef {import('../../types/mcdev.d.js').SoapRequestParams} SoapRequestParams + * @typedef {import('../../types/mcdev.d.js').TemplateMap} TemplateMap + */ +/** + * SenderProfile MetadataType + * + * @augments MetadataType + */ +declare class SenderProfile extends MetadataType { + /** + * Retrieves SOAP based metadata of metadata type into local filesystem. executes callback with retrieved metadata + * + * @param {string} [retrieveDir] Directory where retrieved metadata directory will be saved + * @param {void | string[]} [_] unused parameter + * @param {void | string[]} [__] unused parameter + * @param {string} [key] customer key of single item to retrieve + * @returns {Promise.<MetadataTypeMapObj>} Promise of metadata + */ + static retrieve(retrieveDir?: string, _?: void | string[], __?: void | string[], key?: string): Promise<MetadataTypeMapObj>; + /** + * Updates a single item + * + * @param {MetadataTypeItem} metadataItem a single item + * @returns {Promise} Promise + */ + static update(metadataItem: MetadataTypeItem): Promise<any>; + /** + * Creates a single item + * + * @param {MetadataTypeItem} metadataItem a single item + * @returns {Promise} Promise + */ + static create(metadataItem: MetadataTypeItem): Promise<any>; + /** + * manages post retrieve steps + * + * @param {MetadataTypeItem} metadata a single item + * @returns {MetadataTypeItem} a single item + */ + static postRetrieveTasks(metadata: MetadataTypeItem): MetadataTypeItem; + /** + * + * @param {MetadataTypeItem} metadata a single item + * @param {MetadataTypeItem} [metadataCaller] if called from SendClassification this can be used to adjust logs + * @param {any} [definition] type defintiion from SendClassification + */ + static verifySenderEmailAddresses(metadata: MetadataTypeItem, metadataCaller?: MetadataTypeItem, definition?: any): void; + /** + * prepares a single item for deployment + * + * @param {MetadataTypeItem} metadata a single query activity + * @returns {Promise.<MetadataTypeItem>} Promise + */ + static preDeployTasks(metadata: MetadataTypeItem): Promise<MetadataTypeItem>; + /** + * Gets executed after deployment of metadata type + * + * @param {MetadataTypeMap} upsertResults metadata mapped by their keyField as returned by update/create + * @returns {Promise.<void>} - + */ + static postDeployTasks(upsertResults: MetadataTypeMap): Promise<void>; +} +declare namespace SenderProfile { + let definition: { + bodyIteratorField: string; + dependencies: string[]; + dependencyGraph: { + domainVerification: string[]; + }; + filter: {}; + hasExtended: boolean; + idField: string; + keyField: string; + keyIsFixed: boolean; + maxKeyLength: number; + nameField: string; + createdDateField: string; + createdNameField: string; + lastmodDateField: string; + lastmodNameField: string; + restPagination: boolean; + type: string; + typeDescription: string; + typeRetrieveByDefault: boolean; + typeCdpByDefault: boolean; + typeName: string; + fields: { + 'Client.ID': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'Client.CreatedBy': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'Client.ModifiedBy': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + createdBy: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: any; + template: boolean; + }; + modifiedBy: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: any; + template: boolean; + }; + CreatedDate: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + ModifiedDate: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + CustomerKey: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + ObjectID: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + Name: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + Description: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + PartnerKey: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + PartnerProperties: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + AutoForwardToEmailAddress: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + AutoForwardToName: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'AutoForwardTriggeredSend.ObjectID': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + AutoReply: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'AutoReplyTriggeredSend.ObjectID': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + DataRetentionPeriodLength: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + DataRetentionPeriodUnitOfMeasure: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + DirectForward: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + FallbackFromAddress: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + FromAddress: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + FromName: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + ID: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'ReplyManagementRuleSet.ObjectID': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'RMMRuleCollection.ObjectID': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + ReplyToAddress: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + ReplyToDisplayName: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + SenderHeaderEmailAddress: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + SenderHeaderName: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + UseDefaultRMMRules: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + }; + }; +} +import MetadataType from './MetadataType.js'; +//# sourceMappingURL=SenderProfile.d.ts.map \ No newline at end of file diff --git a/@types/lib/metadataTypes/SenderProfile.d.ts.map b/@types/lib/metadataTypes/SenderProfile.d.ts.map new file mode 100644 index 000000000..75f8f5983 --- /dev/null +++ b/@types/lib/metadataTypes/SenderProfile.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"SenderProfile.d.ts","sourceRoot":"","sources":["../../../lib/metadataTypes/SenderProfile.js"],"names":[],"mappings":";uBAUa,OAAO,wBAAwB,EAAE,QAAQ;0BACzC,OAAO,wBAAwB,EAAE,WAAW;8BAC5C,OAAO,wBAAwB,EAAE,eAAe;+BAChD,OAAO,wBAAwB,EAAE,gBAAgB;mCACjD,OAAO,wBAAwB,EAAE,oBAAoB;kCACrD,OAAO,wBAAwB,EAAE,mBAAmB;8BACpD,OAAO,wBAAwB,EAAE,eAAe;iCAChD,OAAO,wBAAwB,EAAE,kBAAkB;gCACnD,OAAO,wBAAwB,EAAE,iBAAiB;0BAClD,OAAO,wBAAwB,EAAE,WAAW;AAVzD;;;;;;;;;;;GAWG;AAEH;;;;GAIG;AACH;IACI;;;;;;;;OAQG;IACH,8BANW,MAAM,MACN,IAAI,GAAG,MAAM,EAAE,OACf,IAAI,GAAG,MAAM,EAAE,QACf,MAAM,GACJ,OAAO,CAAE,kBAAkB,CAAC,CAexC;IAED;;;;;OAKG;IACH,4BAHW,gBAAgB,gBAK1B;IAED;;;;;OAKG;IACH,4BAHW,gBAAgB,gBAK1B;IAYD;;;;;OAKG;IACH,mCAHW,gBAAgB,GACd,gBAAgB,CA0C5B;IAED;;;;;OAKG;IACH,4CAJW,gBAAgB,mBAChB,gBAAgB,eAChB,GAAG,QAqCb;IAED;;;;;OAKG;IACH,gCAHW,gBAAgB,GACd,OAAO,CAAE,gBAAgB,CAAC,CAiCtC;IAED;;;;;OAKG;IACH,sCAHW,eAAe,GACb,OAAO,CAAE,IAAI,CAAC,CAiE1B;CA+EJ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;yBAtWwB,mBAAmB"} \ No newline at end of file diff --git a/@types/lib/metadataTypes/TransactionalEmail.d.ts b/@types/lib/metadataTypes/TransactionalEmail.d.ts new file mode 100644 index 000000000..019406128 --- /dev/null +++ b/@types/lib/metadataTypes/TransactionalEmail.d.ts @@ -0,0 +1,245 @@ +export default TransactionalEmail; +export type BuObject = import("../../types/mcdev.d.js").BuObject; +export type CodeExtract = import("../../types/mcdev.d.js").CodeExtract; +export type CodeExtractItem = import("../../types/mcdev.d.js").CodeExtractItem; +export type MetadataTypeItem = import("../../types/mcdev.d.js").MetadataTypeItem; +export type MetadataTypeItemDiff = import("../../types/mcdev.d.js").MetadataTypeItemDiff; +export type MetadataTypeItemObj = import("../../types/mcdev.d.js").MetadataTypeItemObj; +export type MetadataTypeMap = import("../../types/mcdev.d.js").MetadataTypeMap; +export type MetadataTypeMapObj = import("../../types/mcdev.d.js").MetadataTypeMapObj; +export type SoapRequestParams = import("../../types/mcdev.d.js").SoapRequestParams; +export type TemplateMap = import("../../types/mcdev.d.js").TemplateMap; +/** + * @typedef {import('../../types/mcdev.d.js').BuObject} BuObject + * @typedef {import('../../types/mcdev.d.js').CodeExtract} CodeExtract + * @typedef {import('../../types/mcdev.d.js').CodeExtractItem} CodeExtractItem + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItem} MetadataTypeItem + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItemDiff} MetadataTypeItemDiff + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItemObj} MetadataTypeItemObj + * @typedef {import('../../types/mcdev.d.js').MetadataTypeMap} MetadataTypeMap + * @typedef {import('../../types/mcdev.d.js').MetadataTypeMapObj} MetadataTypeMapObj + * @typedef {import('../../types/mcdev.d.js').SoapRequestParams} SoapRequestParams + * @typedef {import('../../types/mcdev.d.js').TemplateMap} TemplateMap + */ +/** + * TransactionalEmail MetadataType + * + * @augments TransactionalMessage + */ +declare class TransactionalEmail extends TransactionalMessage { + static subType: string; + /** @type {Array} */ + static _createdJourneyKeys: any[]; + /** + * prepares for deployment + * + * @param {MetadataTypeItem} metadata a single item + * @returns {Promise.<MetadataTypeItem>} - + */ + static preDeployTasks(metadata: MetadataTypeItem): Promise<MetadataTypeItem>; + /** + * helper for {@link TransactionalEmail.createREST} + * + * @param {MetadataTypeItem} _ not used + * @param {object} apiResponse varies depending on the API call + * @returns {Promise.<object>} apiResponse + */ + static postCreateTasks(_: MetadataTypeItem, apiResponse: object): Promise<object>; + /** + * Gets executed after deployment of metadata type + * + * @returns {Promise.<void>} - + */ + static postDeployTasks(): Promise<void>; + /** + * manages post retrieve steps + * + * @param {MetadataTypeItem} metadata a single item + * @returns {MetadataTypeItem} a single item + */ + static postRetrieveTasks(metadata: MetadataTypeItem): MetadataTypeItem; +} +declare namespace TransactionalEmail { + let definition: { + bodyIteratorField: string; + dependencies: string[]; + dependencyGraph: { + asset: string[]; + dataExtension: string[]; + list: string[]; + journey: string[]; + sendClassification: string[]; + }; + hasExtended: boolean; + idField: string; + keyIsFixed: boolean; + keyField: string; + nameField: string; + createdDateField: string; + createdNameField: any; + lastmodDateField: string; + lastmodNameField: any; + restPagination: boolean; + restPageSize: number; + maxKeyLength: number; + type: string; + typeDescription: string; + typeRetrieveByDefault: boolean; + typeCdpByDefault: boolean; + typeName: string; + fields: { + name: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + definitionKey: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + description: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + requestId: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + definitionId: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + status: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + createdDate: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + modifiedDate: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + classification: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'content.customerKey': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'subscriptions.dataExtension': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'subscriptions.r__dataExtension_key': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'subscriptions.list': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'subscriptions.r__list_PathName': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'subscriptions.autoAddSubscriber': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'subscriptions.updateSubscriber': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'options.trackLinks': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'options.cc': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'options.bcc': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'options.createJourney': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + journey: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'journey.interactionKey': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + r__asset_key: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + r__journey_key: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + r__sendClassification_key: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + }; + }; +} +import TransactionalMessage from './TransactionalMessage.js'; +//# sourceMappingURL=TransactionalEmail.d.ts.map \ No newline at end of file diff --git a/@types/lib/metadataTypes/TransactionalEmail.d.ts.map b/@types/lib/metadataTypes/TransactionalEmail.d.ts.map new file mode 100644 index 000000000..6f835ce7a --- /dev/null +++ b/@types/lib/metadataTypes/TransactionalEmail.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"TransactionalEmail.d.ts","sourceRoot":"","sources":["../../../lib/metadataTypes/TransactionalEmail.js"],"names":[],"mappings":";uBAQa,OAAO,wBAAwB,EAAE,QAAQ;0BACzC,OAAO,wBAAwB,EAAE,WAAW;8BAC5C,OAAO,wBAAwB,EAAE,eAAe;+BAChD,OAAO,wBAAwB,EAAE,gBAAgB;mCACjD,OAAO,wBAAwB,EAAE,oBAAoB;kCACrD,OAAO,wBAAwB,EAAE,mBAAmB;8BACpD,OAAO,wBAAwB,EAAE,eAAe;iCAChD,OAAO,wBAAwB,EAAE,kBAAkB;gCACnD,OAAO,wBAAwB,EAAE,iBAAiB;0BAClD,OAAO,wBAAwB,EAAE,WAAW;AAVzD;;;;;;;;;;;GAWG;AAEH;;;;GAIG;AACH;IACI,uBAAyB;IACzB,oBAAoB;IACpB,kCAA2B;IAuC3B;;;;;OAKG;IACH,gCAHW,gBAAgB,GACd,OAAO,CAAE,gBAAgB,CAAC,CAqDtC;IAED;;;;;;OAMG;IACH,0BAJW,gBAAgB,eAChB,MAAM,GACJ,OAAO,CAAE,MAAM,CAAC,CAiB5B;IAED;;;;OAIG;IACH,0BAFa,OAAO,CAAE,IAAI,CAAC,CAU1B;IAED;;;;;OAKG;IACH,mCAHW,gBAAgB,GACd,gBAAgB,CAuG5B;CA4BJ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iCA1SgC,2BAA2B"} \ No newline at end of file diff --git a/@types/lib/metadataTypes/TransactionalMessage.d.ts b/@types/lib/metadataTypes/TransactionalMessage.d.ts new file mode 100644 index 000000000..3cda4e89a --- /dev/null +++ b/@types/lib/metadataTypes/TransactionalMessage.d.ts @@ -0,0 +1,139 @@ +export default TransactionalMessage; +export type BuObject = import("../../types/mcdev.d.js").BuObject; +export type CodeExtract = import("../../types/mcdev.d.js").CodeExtract; +export type CodeExtractItem = import("../../types/mcdev.d.js").CodeExtractItem; +export type MetadataTypeItem = import("../../types/mcdev.d.js").MetadataTypeItem; +export type MetadataTypeItemDiff = import("../../types/mcdev.d.js").MetadataTypeItemDiff; +export type MetadataTypeItemObj = import("../../types/mcdev.d.js").MetadataTypeItemObj; +export type MetadataTypeMap = import("../../types/mcdev.d.js").MetadataTypeMap; +export type MetadataTypeMapObj = import("../../types/mcdev.d.js").MetadataTypeMapObj; +export type SoapRequestParams = import("../../types/mcdev.d.js").SoapRequestParams; +export type TemplateMap = import("../../types/mcdev.d.js").TemplateMap; +/** + * @typedef {import('../../types/mcdev.d.js').BuObject} BuObject + * @typedef {import('../../types/mcdev.d.js').CodeExtract} CodeExtract + * @typedef {import('../../types/mcdev.d.js').CodeExtractItem} CodeExtractItem + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItem} MetadataTypeItem + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItemDiff} MetadataTypeItemDiff + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItemObj} MetadataTypeItemObj + * @typedef {import('../../types/mcdev.d.js').MetadataTypeMap} MetadataTypeMap + * @typedef {import('../../types/mcdev.d.js').MetadataTypeMapObj} MetadataTypeMapObj + * @typedef {import('../../types/mcdev.d.js').SoapRequestParams} SoapRequestParams + * @typedef {import('../../types/mcdev.d.js').TemplateMap} TemplateMap + */ +/** + * TransactionalMessage MetadataType + * + * @augments MetadataType + */ +declare class TransactionalMessage extends MetadataType { + static subType: any; + /** + * Retrieves Metadata + * + * @param {string} [retrieveDir] Directory where retrieved metadata directory will be saved + * @param {void | string[]} [_] unused parameter + * @param {void | string[]} [__] unused parameter + * @param {string} [key] customer key of single item to retrieve + * @returns {Promise.<MetadataTypeMapObj>} Promise of metadata + */ + static retrieve(retrieveDir?: string, _?: void | string[], __?: void | string[], key?: string): Promise<MetadataTypeMapObj>; + /** + * Retrieves event definition metadata for caching + * + * @param {void | string[]} [_] parameter not used + * @param {void | string[]} [__] parameter not used + * @param {string} [key] customer key of single item to cache + * @returns {Promise.<MetadataTypeMapObj>} Promise of metadata + */ + static retrieveForCache(_?: void | string[], __?: void | string[], key?: string): Promise<MetadataTypeMapObj>; + /** + * Updates a single item + * + * @param {MetadataTypeItem} metadata a single item + * @returns {Promise} Promise + */ + static update(metadata: MetadataTypeItem): Promise<any>; + /** + * Creates a single item + * + * @param {MetadataTypeItem} metadata a single item + * @returns {Promise} Promise + */ + static create(metadata: MetadataTypeItem): Promise<any>; +} +declare namespace TransactionalMessage { + let definition: { + bodyIteratorField: string; + dependencies: any[]; + dependencyGraph: any; + hasExtended: boolean; + idField: string; + keyIsFixed: boolean; + keyField: string; + nameField: string; + createdDateField: string; + createdNameField: any; + lastmodDateField: string; + lastmodNameField: any; + restPagination: boolean; + restPageSize: number; + type: string; + typeDescription: string; + typeRetrieveByDefault: boolean; + typeCdpByDefault: boolean; + typeName: string; + fields: { + name: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + definitionKey: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + description: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + requestId: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + definitionId: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + status: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + createdDate: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + modifiedDate: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + }; + }; +} +import MetadataType from './MetadataType.js'; +//# sourceMappingURL=TransactionalMessage.d.ts.map \ No newline at end of file diff --git a/@types/lib/metadataTypes/TransactionalMessage.d.ts.map b/@types/lib/metadataTypes/TransactionalMessage.d.ts.map new file mode 100644 index 000000000..25ae5446c --- /dev/null +++ b/@types/lib/metadataTypes/TransactionalMessage.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"TransactionalMessage.d.ts","sourceRoot":"","sources":["../../../lib/metadataTypes/TransactionalMessage.js"],"names":[],"mappings":";uBAMa,OAAO,wBAAwB,EAAE,QAAQ;0BACzC,OAAO,wBAAwB,EAAE,WAAW;8BAC5C,OAAO,wBAAwB,EAAE,eAAe;+BAChD,OAAO,wBAAwB,EAAE,gBAAgB;mCACjD,OAAO,wBAAwB,EAAE,oBAAoB;kCACrD,OAAO,wBAAwB,EAAE,mBAAmB;8BACpD,OAAO,wBAAwB,EAAE,eAAe;iCAChD,OAAO,wBAAwB,EAAE,kBAAkB;gCACnD,OAAO,wBAAwB,EAAE,iBAAiB;0BAClD,OAAO,wBAAwB,EAAE,WAAW;AAVzD;;;;;;;;;;;GAWG;AAEH;;;;GAIG;AACH;IAEI,oBAAe;IAEf;;;;;;;;OAQG;IACH,8BANW,MAAM,MACN,IAAI,GAAG,MAAM,EAAE,OACf,IAAI,GAAG,MAAM,EAAE,QACf,MAAM,GACJ,OAAO,CAAE,kBAAkB,CAAC,CA8CxC;IAED;;;;;;;OAOG;IACH,4BALW,IAAI,GAAG,MAAM,EAAE,OACf,IAAI,GAAG,MAAM,EAAE,QACf,MAAM,GACJ,OAAO,CAAE,kBAAkB,CAAC,CAOxC;IAED;;;;;OAKG;IACH,wBAHW,gBAAgB,gBAQ1B;IAED;;;;;OAKG;IACH,wBAHW,gBAAgB,gBAK1B;CAeJ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;yBAnIwB,mBAAmB"} \ No newline at end of file diff --git a/@types/lib/metadataTypes/TransactionalPush.d.ts b/@types/lib/metadataTypes/TransactionalPush.d.ts new file mode 100644 index 000000000..a5fa255aa --- /dev/null +++ b/@types/lib/metadataTypes/TransactionalPush.d.ts @@ -0,0 +1,170 @@ +export default TransactionalPush; +export type BuObject = import("../../types/mcdev.d.js").BuObject; +export type CodeExtract = import("../../types/mcdev.d.js").CodeExtract; +export type CodeExtractItem = import("../../types/mcdev.d.js").CodeExtractItem; +export type MetadataTypeItem = import("../../types/mcdev.d.js").MetadataTypeItem; +export type MetadataTypeItemDiff = import("../../types/mcdev.d.js").MetadataTypeItemDiff; +export type MetadataTypeItemObj = import("../../types/mcdev.d.js").MetadataTypeItemObj; +export type MetadataTypeMap = import("../../types/mcdev.d.js").MetadataTypeMap; +export type MetadataTypeMapObj = import("../../types/mcdev.d.js").MetadataTypeMapObj; +export type SoapRequestParams = import("../../types/mcdev.d.js").SoapRequestParams; +export type TemplateMap = import("../../types/mcdev.d.js").TemplateMap; +/** + * @typedef {import('../../types/mcdev.d.js').BuObject} BuObject + * @typedef {import('../../types/mcdev.d.js').CodeExtract} CodeExtract + * @typedef {import('../../types/mcdev.d.js').CodeExtractItem} CodeExtractItem + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItem} MetadataTypeItem + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItemDiff} MetadataTypeItemDiff + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItemObj} MetadataTypeItemObj + * @typedef {import('../../types/mcdev.d.js').MetadataTypeMap} MetadataTypeMap + * @typedef {import('../../types/mcdev.d.js').MetadataTypeMapObj} MetadataTypeMapObj + * @typedef {import('../../types/mcdev.d.js').SoapRequestParams} SoapRequestParams + * @typedef {import('../../types/mcdev.d.js').TemplateMap} TemplateMap + */ +/** + * TransactionalPush TransactionalMessage + * + * @augments TransactionalMessage + */ +declare class TransactionalPush extends TransactionalMessage { + static subType: string; + /** + * prepares for deployment + * + * @param {MetadataTypeItem} metadata a single item + * @returns {Promise.<MetadataTypeItem>} - + */ + static preDeployTasks(metadata: MetadataTypeItem): Promise<MetadataTypeItem>; + /** + * manages post retrieve steps + * + * @param {MetadataTypeItem} metadata a single item + * @returns {MetadataTypeItem} a single item + */ + static postRetrieveTasks(metadata: MetadataTypeItem): MetadataTypeItem; +} +declare namespace TransactionalPush { + let definition: { + bodyIteratorField: string; + dependencies: string[]; + dependencyGraph: { + asset: string[]; + }; + hasExtended: boolean; + idField: string; + keyIsFixed: boolean; + keyField: string; + nameField: string; + createdDateField: string; + createdNameField: any; + lastmodDateField: string; + lastmodNameField: any; + restPagination: boolean; + restPageSize: number; + type: string; + typeDescription: string; + typeRetrieveByDefault: boolean; + typeCdpByDefault: boolean; + typeName: string; + fields: { + name: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + definitionKey: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + description: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + requestId: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + definitionId: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + status: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + createdDate: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + modifiedDate: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'content.customerKey': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + r__asset_key: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'options.badge': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'options.sound': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'options.customKeys': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'options.customKeys[].value': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'options.customKeys[].key': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + applicationId: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + }; + }; +} +import TransactionalMessage from './TransactionalMessage.js'; +//# sourceMappingURL=TransactionalPush.d.ts.map \ No newline at end of file diff --git a/@types/lib/metadataTypes/TransactionalPush.d.ts.map b/@types/lib/metadataTypes/TransactionalPush.d.ts.map new file mode 100644 index 000000000..cffd8f4b1 --- /dev/null +++ b/@types/lib/metadataTypes/TransactionalPush.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"TransactionalPush.d.ts","sourceRoot":"","sources":["../../../lib/metadataTypes/TransactionalPush.js"],"names":[],"mappings":";uBAOa,OAAO,wBAAwB,EAAE,QAAQ;0BACzC,OAAO,wBAAwB,EAAE,WAAW;8BAC5C,OAAO,wBAAwB,EAAE,eAAe;+BAChD,OAAO,wBAAwB,EAAE,gBAAgB;mCACjD,OAAO,wBAAwB,EAAE,oBAAoB;kCACrD,OAAO,wBAAwB,EAAE,mBAAmB;8BACpD,OAAO,wBAAwB,EAAE,eAAe;iCAChD,OAAO,wBAAwB,EAAE,kBAAkB;gCACnD,OAAO,wBAAwB,EAAE,iBAAiB;0BAClD,OAAO,wBAAwB,EAAE,WAAW;AAVzD;;;;;;;;;;;GAWG;AAEH;;;;GAIG;AACH;IACI,uBAAwB;IAExB;;;;;OAKG;IACH,gCAHW,gBAAgB,GACd,OAAO,CAAE,gBAAgB,CAAC,CAqBtC;IAED;;;;;OAKG;IACH,mCAHW,gBAAgB,GACd,gBAAgB,CA4B5B;CACJ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iCArFgC,2BAA2B"} \ No newline at end of file diff --git a/@types/lib/metadataTypes/TransactionalSMS.d.ts b/@types/lib/metadataTypes/TransactionalSMS.d.ts new file mode 100644 index 000000000..08ce91786 --- /dev/null +++ b/@types/lib/metadataTypes/TransactionalSMS.d.ts @@ -0,0 +1,204 @@ +export default TransactionalSMS; +export type BuObject = import("../../types/mcdev.d.js").BuObject; +export type CodeExtract = import("../../types/mcdev.d.js").CodeExtract; +export type CodeExtractItem = import("../../types/mcdev.d.js").CodeExtractItem; +export type MetadataTypeItem = import("../../types/mcdev.d.js").MetadataTypeItem; +export type MetadataTypeItemDiff = import("../../types/mcdev.d.js").MetadataTypeItemDiff; +export type MetadataTypeItemObj = import("../../types/mcdev.d.js").MetadataTypeItemObj; +export type MetadataTypeMap = import("../../types/mcdev.d.js").MetadataTypeMap; +export type MetadataTypeMapObj = import("../../types/mcdev.d.js").MetadataTypeMapObj; +export type SoapRequestParams = import("../../types/mcdev.d.js").SoapRequestParams; +export type TemplateMap = import("../../types/mcdev.d.js").TemplateMap; +/** + * @typedef {import('../../types/mcdev.d.js').BuObject} BuObject + * @typedef {import('../../types/mcdev.d.js').CodeExtract} CodeExtract + * @typedef {import('../../types/mcdev.d.js').CodeExtractItem} CodeExtractItem + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItem} MetadataTypeItem + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItemDiff} MetadataTypeItemDiff + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItemObj} MetadataTypeItemObj + * @typedef {import('../../types/mcdev.d.js').MetadataTypeMap} MetadataTypeMap + * @typedef {import('../../types/mcdev.d.js').MetadataTypeMapObj} MetadataTypeMapObj + * @typedef {import('../../types/mcdev.d.js').SoapRequestParams} SoapRequestParams + * @typedef {import('../../types/mcdev.d.js').TemplateMap} TemplateMap + */ +/** + * TransactionalSMS MetadataType + * + * @augments TransactionalMessage + */ +declare class TransactionalSMS extends TransactionalMessage { + static subType: string; + /** + * clean up after deleting a metadata item + * + * @param {string} customerKey Identifier of metadata item + * @returns {Promise.<void>} - + */ + static postDeleteTasks(customerKey: string): Promise<void>; + /** + * helper for {@link TransactionalSMS.preDeployTasks} that loads extracted code content back into JSON + * + * @param {MetadataTypeItem} metadata a single definition + * @param {string} deployDir directory of deploy files + * @param {string} [templateName] name of the template used to built defintion (prior applying templating) + * @returns {Promise.<string>} content for metadata.script + */ + static _mergeCode(metadata: MetadataTypeItem, deployDir: string, templateName?: string): Promise<string>; + /** + * manages post retrieve steps + * + * @param {MetadataTypeItem} metadata a single item + * @returns {Promise.<CodeExtractItem>} Array with one metadata object and one ssjs string + */ + static postRetrieveTasks(metadata: MetadataTypeItem): Promise<CodeExtractItem>; + /** + * helper for {@link TransactionalSMS.postRetrieveTasks} and {@link TransactionalSMS._buildForNested} + * + * @param {string} metadataScript the code of the file + * @returns {Promise.<{fileExt:string,code:string}>} returns found extension and file content + */ + static prepExtractedCode(metadataScript: string): Promise<{ + fileExt: string; + code: string; + }>; + /** + * helper for {@link TransactionalSMS.buildTemplateForNested} / {@link TransactionalSMS.buildDefinitionForNested} + * handles extracted code if any are found for complex types + * + * @param {string} templateDir Directory where metadata templates are stored + * @param {string|string[]} targetDir (List of) Directory where built definitions will be saved + * @param {MetadataTypeItem} metadata main JSON file that was read from file system + * @param {TemplateMap} templateVariables variables to be replaced in the metadata + * @param {string} templateName name of the template to be built + * @param {'definition'|'template'} mode defines what we use this helper for + * @returns {Promise.<string[][]>} list of extracted files with path-parts provided as an array + */ + static _buildForNested(templateDir: string, targetDir: string | string[], metadata: MetadataTypeItem, templateVariables: TemplateMap, templateName: string, mode: "definition" | "template"): Promise<string[][]>; + /** + * very simplified test for HTML code in our SMS + * + * @param {string} code sms source code + * @returns {boolean} true if HTML is found + */ + static _isHTML(code: string): boolean; +} +declare namespace TransactionalSMS { + let definition: { + bodyIteratorField: string; + dependencies: string[]; + dependencyGraph: { + mobileKeyword: string[]; + mobileCode: string[]; + }; + hasExtended: boolean; + idField: string; + keyIsFixed: boolean; + keyField: string; + nameField: string; + createdDateField: string; + createdNameField: any; + lastmodDateField: string; + lastmodNameField: any; + restPagination: boolean; + restPageSize: number; + type: string; + typeDescription: string; + typeRetrieveByDefault: boolean; + typeCdpByDefault: boolean; + typeName: string; + fields: { + name: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + definitionKey: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + description: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + requestId: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + definitionId: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + status: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + createdDate: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + modifiedDate: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'content.message': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'subscriptions.shortCode': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'subscriptions.countryCode': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'subscriptions.autoAddSubscriber': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'subscriptions.updateSubscriber': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'subscriptions.keyword': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'subscriptions.r__mobileKeyword_key': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + }; + }; +} +import TransactionalMessage from './TransactionalMessage.js'; +//# sourceMappingURL=TransactionalSMS.d.ts.map \ No newline at end of file diff --git a/@types/lib/metadataTypes/TransactionalSMS.d.ts.map b/@types/lib/metadataTypes/TransactionalSMS.d.ts.map new file mode 100644 index 000000000..8189a395c --- /dev/null +++ b/@types/lib/metadataTypes/TransactionalSMS.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"TransactionalSMS.d.ts","sourceRoot":"","sources":["../../../lib/metadataTypes/TransactionalSMS.js"],"names":[],"mappings":";uBAQa,OAAO,wBAAwB,EAAE,QAAQ;0BACzC,OAAO,wBAAwB,EAAE,WAAW;8BAC5C,OAAO,wBAAwB,EAAE,eAAe;+BAChD,OAAO,wBAAwB,EAAE,gBAAgB;mCACjD,OAAO,wBAAwB,EAAE,oBAAoB;kCACrD,OAAO,wBAAwB,EAAE,mBAAmB;8BACpD,OAAO,wBAAwB,EAAE,eAAe;iCAChD,OAAO,wBAAwB,EAAE,kBAAkB;gCACnD,OAAO,wBAAwB,EAAE,iBAAiB;0BAClD,OAAO,wBAAwB,EAAE,WAAW;AAVzD;;;;;;;;;;;GAWG;AAEH;;;;GAIG;AACH;IACI,uBAAuB;IAEvB;;;;;OAKG;IACH,oCAHW,MAAM,GACJ,OAAO,CAAE,IAAI,CAAC,CAM1B;IAsDD;;;;;;;OAOG;IACH,4BALW,gBAAgB,aAChB,MAAM,iBACN,MAAM,GACJ,OAAO,CAAE,MAAM,CAAC,CAmB5B;IAED;;;;;OAKG;IACH,mCAHW,gBAAgB,GACd,OAAO,CAAE,eAAe,CAAC,CAqErC;IAED;;;;;OAKG;IACH,yCAHW,MAAM,GACJ,OAAO,CAAE;QAAC,OAAO,EAAC,MAAM,CAAC;QAAA,IAAI,EAAC,MAAM,CAAA;KAAC,CAAC,CAOlD;IA2DD;;;;;;;;;;;OAWG;IACH,oCARW,MAAM,aACN,MAAM,GAAC,MAAM,EAAE,YACf,gBAAgB,qBAChB,WAAW,gBACX,MAAM,QACN,YAAY,GAAC,UAAU,GACrB,OAAO,CAAE,MAAM,EAAE,EAAE,CAAC,CAqDhC;IAED;;;;;OAKG;IACH,qBAHW,MAAM,GACJ,OAAO,CAInB;CAuBJ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iCAtWgC,2BAA2B"} \ No newline at end of file diff --git a/@types/lib/metadataTypes/TriggeredSend.d.ts b/@types/lib/metadataTypes/TriggeredSend.d.ts new file mode 100644 index 000000000..0a611a8e6 --- /dev/null +++ b/@types/lib/metadataTypes/TriggeredSend.d.ts @@ -0,0 +1,670 @@ +export default TriggeredSend; +export type BuObject = import("../../types/mcdev.d.js").BuObject; +export type CodeExtract = import("../../types/mcdev.d.js").CodeExtract; +export type CodeExtractItem = import("../../types/mcdev.d.js").CodeExtractItem; +export type MetadataTypeItem = import("../../types/mcdev.d.js").MetadataTypeItem; +export type MetadataTypeItemDiff = import("../../types/mcdev.d.js").MetadataTypeItemDiff; +export type MetadataTypeItemObj = import("../../types/mcdev.d.js").MetadataTypeItemObj; +export type MetadataTypeMap = import("../../types/mcdev.d.js").MetadataTypeMap; +export type MetadataTypeMapObj = import("../../types/mcdev.d.js").MetadataTypeMapObj; +export type SoapRequestParams = import("../../types/mcdev.d.js").SoapRequestParams; +export type TemplateMap = import("../../types/mcdev.d.js").TemplateMap; +/** + * @typedef {import('../../types/mcdev.d.js').BuObject} BuObject + * @typedef {import('../../types/mcdev.d.js').CodeExtract} CodeExtract + * @typedef {import('../../types/mcdev.d.js').CodeExtractItem} CodeExtractItem + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItem} MetadataTypeItem + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItemDiff} MetadataTypeItemDiff + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItemObj} MetadataTypeItemObj + * @typedef {import('../../types/mcdev.d.js').MetadataTypeMap} MetadataTypeMap + * @typedef {import('../../types/mcdev.d.js').MetadataTypeMapObj} MetadataTypeMapObj + * @typedef {import('../../types/mcdev.d.js').SoapRequestParams} SoapRequestParams + * @typedef {import('../../types/mcdev.d.js').TemplateMap} TemplateMap + */ +/** + * MessageSendActivity MetadataType + * + * @augments MetadataType + */ +declare class TriggeredSend extends MetadataType { + /** + * Retrieves SOAP based metadata of metadata type into local filesystem. executes callback with retrieved metadata + * + * @param {string} retrieveDir Directory where retrieved metadata directory will be saved + * @param {void | string[]} [_] unused parameter + * @param {void | string[]} [__] unused parameter + * @param {string} [key] customer key of single item to retrieve + * @returns {Promise.<MetadataTypeMapObj>} Promise of metadata + */ + static retrieve(retrieveDir: string, _?: void | string[], __?: void | string[], key?: string): Promise<MetadataTypeMapObj>; + /** + * Create a single TSD. + * + * @param {MetadataTypeItem} metadata single metadata entry + * @returns {Promise} Promise + */ + static create(metadata: MetadataTypeItem): Promise<any>; + /** + * Updates a single TSD. + * + * @param {MetadataTypeItem} metadata single metadata entry + * @returns {Promise} Promise + */ + static update(metadata: MetadataTypeItem): Promise<any>; + /** + * parses retrieved Metadata before saving + * + * @param {MetadataTypeItem} metadata a single item + * @returns {MetadataTypeItem | void} Array with one metadata object and one sql string + */ + static postRetrieveTasks(metadata: MetadataTypeItem): MetadataTypeItem | void; + /** + * prepares a TSD for deployment + * + * @param {MetadataTypeItem} metadata of a single TSD + * @returns {Promise.<MetadataTypeItem>} metadata object + */ + static preDeployTasks(metadata: MetadataTypeItem): Promise<MetadataTypeItem>; + /** + * TSD-specific refresh method that finds active TSDs and refreshes them + * + * @param {string[]} [keyArr] metadata keys + * @param {boolean} [checkKey] whether to check if the key is valid + * @returns {Promise.<string[]>} Returns list of keys that were refreshed + */ + static refresh(keyArr?: string[], checkKey?: boolean): Promise<string[]>; + /** + * helper for {@link TriggeredSend.refresh} that extracts the keys from the TSD item map and eli + * + * @param {MetadataTypeMap} metadata TSD item map + * @returns {Promise.<string[]>} keyArr + */ + static getKeysForValidTSDs(metadata: MetadataTypeMap): Promise<string[]>; + /** + * helper for {@link TriggeredSend.refresh} that finds active TSDs on the server and filters it by the same rules that {@link TriggeredSend.retrieve} is using to avoid refreshing TSDs with broken dependencies + * + * @param {boolean} [assetLoaded] if run after Asset.deploy via --refresh option this will skip caching assets + * @returns {Promise.<MetadataTypeMapObj>} Promise of TSD item map + */ + static findRefreshableItems(assetLoaded?: boolean): Promise<MetadataTypeMapObj>; + /** + * helper for {@link TriggeredSend.refresh} that pauses, publishes and starts a triggered send + * + * @param {string} key external key of triggered send item + * @param {boolean} checkKey whether to check if key exists on the server + * @returns {Promise.<boolean>} true if refresh was successful + */ + static _refreshItem(key: string, checkKey: boolean): Promise<boolean>; +} +declare namespace TriggeredSend { + let definition: { + bodyIteratorField: string; + dependencies: string[]; + dependencyGraph: { + asset: string[]; + list: string[]; + sendClassification: string[]; + senderProfile: string[]; + }; + filter: { + r__folder_Path: string[]; + }; + folderType: string; + hasExtended: boolean; + idField: string; + keepId: boolean; + keyIsFixed: boolean; + keyField: string; + nameField: string; + folderIdField: string; + createdDateField: string; + createdNameField: any; + lastmodDateField: string; + lastmodNameField: any; + restPagination: any; + maxKeyLength: number; + type: string; + soapType: string; + typeDescription: string; + typeRetrieveByDefault: boolean; + typeCdpByDefault: boolean; + typeName: string; + priorityMapping: { + High: number; + Medium: number; + Low: number; + }; + fields: { + AllowedSlots: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + AutoAddSubscribers: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + AutoUpdateSubscribers: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + BatchInterval: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + BccEmail: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + CategoryID: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + CCEmail: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + 'Client.ID': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + 'Client.PartnerClientKey': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + CorrelationID: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + CreatedDate: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + CustomerKey: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + DataSchemas: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + 'DeliveryProfile.CustomerKey': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + 'DeliveryProfile.ObjectID': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + Description: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + DisableOnEmailBuildError: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + DomainType: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + DynamicEmailSubject: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + 'Email.ID': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + 'Email.PartnerKey': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + 'Email.ObjectID': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + EmailSubject: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + ExclusionFilter: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + ExclusionListCollection: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + 'FooterContentArea.ID': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + FooterSalutationSource: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + FromAddress: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + FromName: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + 'HeaderContentArea.ID': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + HeaderSalutationSource: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + ID: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + InteractionObjectID: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + IsAlwaysOn: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + IsMultipart: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + IsPlatformObject: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + IsSendLogging: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + IsWrapped: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + KeepExistingEmailSubject: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + Keyword: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + 'List.ID': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + 'List.PartnerKey': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + 'List.ObjectID': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + ModifiedDate: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + Name: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + NewSlotTrigger: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + ObjectID: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + ObjectState: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + OptionFlags: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + OptionFlagsUpdateMask: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + OptionVersion: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + Owner: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + PartnerKey: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + PartnerProperties: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + PreHeader: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + Priority: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + 'PrivateDomain.ObjectID': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + 'PrivateDomain.PartnerKey': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + 'PrivateIP.ID': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + 'PrivateIP.PartnerKey': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + RefreshContent: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + ReplyToAddress: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + ReplyToDisplayName: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + RequestExpirationSeconds: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + 'SendClassification.CustomerKey': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + 'SendClassification.ObjectID': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + 'SendClassification.PartnerKey': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + 'SenderProfile.CustomerKey': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + 'SenderProfile.ObjectID': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + 'SenderProfile.PartnerKey': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + SendLimit: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + SendSourceCustomerKey: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + SendSourceDataExtension: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + SendWindowClose: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + SendWindowDelete: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + SendWindowOpen: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + SourceAddressType: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + SuppressTracking: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + TestEmailAddr: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + TriggeredSendClass: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + TriggeredSendStatus: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + TriggeredSendSubClass: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + TriggeredSendType: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + TriggeredSendVersionID: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + r__asset_name_readOnly: { + skipValidation: boolean; + }; + r__asset_key: { + skipValidation: boolean; + }; + r__email_name: { + skipValidation: boolean; + }; + r__folder_Path: { + skipValidation: boolean; + }; + r__list_PathName: { + skipValidation: boolean; + }; + c__priority: { + skipValidation: boolean; + }; + r__sendClassification_key: { + skipValidation: boolean; + }; + r__senderProfile_key: { + skipValidation: boolean; + }; + }; + }; +} +import MetadataType from './MetadataType.js'; +//# sourceMappingURL=TriggeredSend.d.ts.map \ No newline at end of file diff --git a/@types/lib/metadataTypes/TriggeredSend.d.ts.map b/@types/lib/metadataTypes/TriggeredSend.d.ts.map new file mode 100644 index 000000000..6f6c9baee --- /dev/null +++ b/@types/lib/metadataTypes/TriggeredSend.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"TriggeredSend.d.ts","sourceRoot":"","sources":["../../../lib/metadataTypes/TriggeredSend.js"],"names":[],"mappings":";uBAca,OAAO,wBAAwB,EAAE,QAAQ;0BACzC,OAAO,wBAAwB,EAAE,WAAW;8BAC5C,OAAO,wBAAwB,EAAE,eAAe;+BAChD,OAAO,wBAAwB,EAAE,gBAAgB;mCACjD,OAAO,wBAAwB,EAAE,oBAAoB;kCACrD,OAAO,wBAAwB,EAAE,mBAAmB;8BACpD,OAAO,wBAAwB,EAAE,eAAe;iCAChD,OAAO,wBAAwB,EAAE,kBAAkB;gCACnD,OAAO,wBAAwB,EAAE,iBAAiB;0BAClD,OAAO,wBAAwB,EAAE,WAAW;AAVzD;;;;;;;;;;;GAWG;AAEH;;;;GAIG;AACH;IACI;;;;;;;;OAQG;IACH,6BANW,MAAM,MACN,IAAI,GAAG,MAAM,EAAE,OACf,IAAI,GAAG,MAAM,EAAE,QACf,MAAM,GACJ,OAAO,CAAE,kBAAkB,CAAC,CA2BxC;IAED;;;;;OAKG;IACH,wBAHW,gBAAgB,gBAK1B;IAED;;;;;OAKG;IACH,wBAHW,gBAAgB,gBAO1B;IAYD;;;;;OAKG;IACH,mCAHW,gBAAgB,GACd,gBAAgB,GAAG,IAAI,CAwGnC;IAED;;;;;OAKG;IACH,gCAHW,gBAAgB,GACd,OAAO,CAAE,gBAAgB,CAAC,CAuFtC;IAED;;;;;;OAMG;IACH,wBAJW,MAAM,EAAE,aACR,OAAO,GACL,OAAO,CAAE,MAAM,EAAE,CAAC,CA0B9B;IAED;;;;;OAKG;IACH,qCAHW,eAAe,GACb,OAAO,CAAE,MAAM,EAAE,CAAC,CAS9B;IAED;;;;;OAKG;IACH,0CAHW,OAAO,GACL,OAAO,CAAE,kBAAkB,CAAC,CAyExC;IAED;;;;;;OAMG;IACH,yBAJW,MAAM,YACN,OAAO,GACL,OAAO,CAAE,OAAO,CAAC,CA8F7B;CA+EJ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;yBA9lBwB,mBAAmB"} \ No newline at end of file diff --git a/@types/lib/metadataTypes/TriggeredSendSummary.d.ts b/@types/lib/metadataTypes/TriggeredSendSummary.d.ts new file mode 100644 index 000000000..983c1d763 --- /dev/null +++ b/@types/lib/metadataTypes/TriggeredSendSummary.d.ts @@ -0,0 +1,257 @@ +export default TriggeredSendSummary; +export type BuObject = import("../../types/mcdev.d.js").BuObject; +export type CodeExtract = import("../../types/mcdev.d.js").CodeExtract; +export type CodeExtractItem = import("../../types/mcdev.d.js").CodeExtractItem; +export type MetadataTypeItem = import("../../types/mcdev.d.js").MetadataTypeItem; +export type MetadataTypeItemDiff = import("../../types/mcdev.d.js").MetadataTypeItemDiff; +export type MetadataTypeItemObj = import("../../types/mcdev.d.js").MetadataTypeItemObj; +export type MetadataTypeMap = import("../../types/mcdev.d.js").MetadataTypeMap; +export type MetadataTypeMapObj = import("../../types/mcdev.d.js").MetadataTypeMapObj; +export type SoapRequestParams = import("../../types/mcdev.d.js").SoapRequestParams; +export type TemplateMap = import("../../types/mcdev.d.js").TemplateMap; +/** + * @typedef {import('../../types/mcdev.d.js').BuObject} BuObject + * @typedef {import('../../types/mcdev.d.js').CodeExtract} CodeExtract + * @typedef {import('../../types/mcdev.d.js').CodeExtractItem} CodeExtractItem + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItem} MetadataTypeItem + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItemDiff} MetadataTypeItemDiff + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItemObj} MetadataTypeItemObj + * @typedef {import('../../types/mcdev.d.js').MetadataTypeMap} MetadataTypeMap + * @typedef {import('../../types/mcdev.d.js').MetadataTypeMapObj} MetadataTypeMapObj + * @typedef {import('../../types/mcdev.d.js').SoapRequestParams} SoapRequestParams + * @typedef {import('../../types/mcdev.d.js').TemplateMap} TemplateMap + */ +/** + * TriggeredSendSummary MetadataType + * + * @augments MetadataType + */ +declare class TriggeredSendSummary extends MetadataType { + /** + * Retrieves SOAP based metadata of metadata type into local filesystem. executes callback with retrieved metadata + * + * @param {string} retrieveDir Directory where retrieved metadata directory will be saved + * @param {void | string[]} [_] unused parameter + * @param {void | string[]} [__] unused parameter + * @param {string} [key] customer key of single item to retrieve + * @returns {Promise.<MetadataTypeMapObj>} Promise of metadata + */ + static retrieve(retrieveDir: string, _?: void | string[], __?: void | string[], key?: string): Promise<MetadataTypeMapObj>; + /** + * parses retrieved Metadata before saving + * + * @param {MetadataTypeItem} metadata a single item + * @returns {MetadataTypeItem | void} Array with one metadata object and one sql string + */ + static postRetrieveTasks(metadata: MetadataTypeItem): MetadataTypeItem | void; +} +declare namespace TriggeredSendSummary { + let definition: { + bodyIteratorField: string; + dependencies: string[]; + dependencyGraph: { + triggeredSend: string[]; + }; + filter: {}; + hasExtended: boolean; + idField: string; + keepId: boolean; + keyIsFixed: boolean; + keyField: string; + nameField: string; + folderIdField: string; + createdDateField: any; + createdNameField: any; + lastmodDateField: any; + lastmodNameField: any; + restPagination: any; + maxKeyLength: number; + type: string; + soapType: string; + typeDescription: string; + typeRetrieveByDefault: boolean; + typeCdpByDefault: boolean; + typeName: string; + fields: { + Bounces: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + Clicks: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + 'Client.ID': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + Conversions: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + CustomerKey: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + FTAFEmailsSent: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + FTAFOptIns: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + FTAFRequests: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + ID: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + InProcess: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + NotSentDueToError: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + NotSentDueToOptOut: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + NotSentDueToUndeliverable: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + ObjectID: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + Opens: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + OptOuts: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + Owner: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + PartnerKey: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + PartnerProperties: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + Queued: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + Sent: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + SurveyResponses: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + UniqueClicks: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + UniqueConversions: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + UniqueOpens: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + CorrelationID: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + CreatedDate: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + ModifiedDate: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + r__triggeredSend_name: { + skipValidation: boolean; + }; + r__triggeredSend_key: { + skipValidation: boolean; + }; + r__folder_Path: { + skipValidation: boolean; + }; + }; + }; +} +import MetadataType from './MetadataType.js'; +//# sourceMappingURL=TriggeredSendSummary.d.ts.map \ No newline at end of file diff --git a/@types/lib/metadataTypes/TriggeredSendSummary.d.ts.map b/@types/lib/metadataTypes/TriggeredSendSummary.d.ts.map new file mode 100644 index 000000000..2ddcc627b --- /dev/null +++ b/@types/lib/metadataTypes/TriggeredSendSummary.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"TriggeredSendSummary.d.ts","sourceRoot":"","sources":["../../../lib/metadataTypes/TriggeredSendSummary.js"],"names":[],"mappings":";uBAOa,OAAO,wBAAwB,EAAE,QAAQ;0BACzC,OAAO,wBAAwB,EAAE,WAAW;8BAC5C,OAAO,wBAAwB,EAAE,eAAe;+BAChD,OAAO,wBAAwB,EAAE,gBAAgB;mCACjD,OAAO,wBAAwB,EAAE,oBAAoB;kCACrD,OAAO,wBAAwB,EAAE,mBAAmB;8BACpD,OAAO,wBAAwB,EAAE,eAAe;iCAChD,OAAO,wBAAwB,EAAE,kBAAkB;gCACnD,OAAO,wBAAwB,EAAE,iBAAiB;0BAClD,OAAO,wBAAwB,EAAE,WAAW;AAVzD;;;;;;;;;;;GAWG;AAEH;;;;GAIG;AACH;IACI;;;;;;;;OAQG;IACH,6BANW,MAAM,MACN,IAAI,GAAG,MAAM,EAAE,OACf,IAAI,GAAG,MAAM,EAAE,QACf,MAAM,GACJ,OAAO,CAAE,kBAAkB,CAAC,CAiBxC;IACD;;;;;OAKG;IACH,mCAHW,gBAAgB,GACd,gBAAgB,GAAG,IAAI,CAkBnC;CAuBJ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;yBA7FwB,mBAAmB"} \ No newline at end of file diff --git a/@types/lib/metadataTypes/User.d.ts b/@types/lib/metadataTypes/User.d.ts new file mode 100644 index 000000000..293e6cb5a --- /dev/null +++ b/@types/lib/metadataTypes/User.d.ts @@ -0,0 +1,669 @@ +export default User; +export type BuObject = import("../../types/mcdev.d.js").BuObject; +export type CodeExtract = import("../../types/mcdev.d.js").CodeExtract; +export type CodeExtractItem = import("../../types/mcdev.d.js").CodeExtractItem; +export type MetadataTypeItem = import("../../types/mcdev.d.js").MetadataTypeItem; +export type MetadataTypeItemDiff = import("../../types/mcdev.d.js").MetadataTypeItemDiff; +export type MetadataTypeItemObj = import("../../types/mcdev.d.js").MetadataTypeItemObj; +export type MetadataTypeMap = import("../../types/mcdev.d.js").MetadataTypeMap; +export type MetadataTypeMapObj = import("../../types/mcdev.d.js").MetadataTypeMapObj; +export type SoapRequestParams = import("../../types/mcdev.d.js").SoapRequestParams; +export type TemplateMap = import("../../types/mcdev.d.js").TemplateMap; +export type UserDocument = import("../../types/mcdev.d.js").UserDocument; +export type UserDocumentDocument = import("../../types/mcdev.d.js").UserDocumentDocument; +export type UserDocumentDiff = import("../../types/mcdev.d.js").UserDocumentDiff; +export type UserDocumentMap = import("../../types/mcdev.d.js").UserDocumentMap; +export type AccountUserConfiguration = import("../../types/mcdev.d.js").AccountUserConfiguration; +/** + * @typedef {import('../../types/mcdev.d.js').BuObject} BuObject + * @typedef {import('../../types/mcdev.d.js').CodeExtract} CodeExtract + * @typedef {import('../../types/mcdev.d.js').CodeExtractItem} CodeExtractItem + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItem} MetadataTypeItem + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItemDiff} MetadataTypeItemDiff + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItemObj} MetadataTypeItemObj + * @typedef {import('../../types/mcdev.d.js').MetadataTypeMap} MetadataTypeMap + * @typedef {import('../../types/mcdev.d.js').MetadataTypeMapObj} MetadataTypeMapObj + * @typedef {import('../../types/mcdev.d.js').SoapRequestParams} SoapRequestParams + * @typedef {import('../../types/mcdev.d.js').TemplateMap} TemplateMap + */ +/** + * @typedef {import('../../types/mcdev.d.js').UserDocument} UserDocument + * @typedef {import('../../types/mcdev.d.js').UserDocumentDocument} UserDocumentDocument + * @typedef {import('../../types/mcdev.d.js').UserDocumentDiff} UserDocumentDiff + * @typedef {import('../../types/mcdev.d.js').UserDocumentMap} UserDocumentMap + * @typedef {import('../../types/mcdev.d.js').AccountUserConfiguration} AccountUserConfiguration + */ +/** + * MetadataType + * + * @augments MetadataType + */ +declare class User extends MetadataType { + static userBUassignments: any; + static userIdBuMap: any; + /** + * Retrieves SOAP based metadata of metadata type into local filesystem. executes callback with retrieved metadata + * + * @param {string} retrieveDir Directory where retrieved metadata directory will be saved + * @param {void | string[]} _ unused parameter + * @param {void | string[]} [__] unused parameter + * @param {string} [key] customer key of single item to retrieve + * @returns {Promise.<MetadataTypeMapObj>} Promise of metadata + */ + static retrieve(retrieveDir: string, _: void | string[], __?: void | string[], key?: string): Promise<MetadataTypeMapObj>; + /** + * Retrieves import definition metadata for caching + * + * @returns {Promise.<MetadataTypeMapObj>} Promise + */ + static retrieveForCache(): Promise<MetadataTypeMapObj>; + /** + * Create a single item. + * + * @param {MetadataTypeItem} metadata single metadata entry + * @returns {Promise} Promise + */ + static create(metadata: MetadataTypeItem): Promise<any>; + /** + * Updates a single item. + * + * @param {MetadataTypeItem} metadata single metadata entry + * @returns {Promise} Promise + */ + static update(metadata: MetadataTypeItem): Promise<any>; + /** + * prepares a item for deployment + * + * @param {UserDocument} metadata of a single item + * @returns {Promise.<UserDocument>} metadata object + */ + static preDeployTasks(metadata: UserDocument): Promise<UserDocument>; + /** + * helper for {@link MetadataType.upsert} + * + * @param {MetadataTypeMap} metadata list of metadata + * @param {string} metadataKey key of item we are looking at + * @param {boolean} hasError error flag from previous code + * @param {UserDocumentDiff[]} metadataToUpdate list of items to update + * @param {UserDocument[]} metadataToCreate list of items to create + * @returns {Promise.<'create'|'update'|'skip'>} action to take + */ + static createOrUpdate(metadata: MetadataTypeMap, metadataKey: string, hasError: boolean, metadataToUpdate: UserDocumentDiff[], metadataToCreate: UserDocument[]): Promise<"create" | "update" | "skip">; + /** + * helper for {@link createOrUpdate} + * + * @private + * @param {MetadataTypeItem} metadata single metadata itme + * @param {UserDocumentDiff} [updateItem] item to update + * @param {UserDocument} [createItem] item to create + */ + private static _prepareBuAssignments; + /** + * Gets executed after deployment of metadata type + * + * @param {UserDocumentMap} upsertResults metadata mapped by their keyField + * @returns {Promise.<void>} promise + */ + static postDeployTasks(upsertResults: UserDocumentMap): Promise<void>; + /** + * create/update business unit assignments. helper for {@link postDeployTasks} + * + * @private + * @param {UserDocumentMap} upsertResults metadata mapped by their keyField + * @returns {Promise.<void>} - + */ + private static _handleBuAssignments; + /** + * helper for {@link User.createOrUpdate} + * + * @private + * @param {UserDocument} metadata single created user + * @returns {void} + */ + private static _setPasswordForNewUser; + /** + * helper for {@link User.createOrUpdate} + * It searches for roles that were removed from the user and unassigns them; it also prints a summary of added/removed roles + * Adding roles works automatically for roles listed on the user + * + * @private + * @param {UserDocumentDiff} item updated user with before and after state + * @returns {void} + */ + private static _prepareRoleAssignments; + /** + * helper for {@link User._prepareRoleAssignments} + * + * @param {string} roleId role.ObjectID + * @param {string} roleName role.Name + * @param {number} userId user.AccountUserID + * @param {boolean} assignmentOnly if true, only assignment configuration will be returned + * @param {boolean} [isRoleRemovale] if true, role will be removed from user; otherwise added + * @returns {object} format needed by API + */ + static _getRoleObjectForDeploy(roleId: string, roleName: string, userId: number, assignmentOnly: boolean, isRoleRemovale?: boolean): object; + /** + * Retrieves SOAP based metadata of metadata type into local filesystem. executes callback with retrieved metadata + * + * @returns {Promise.<MetadataTypeMapObj>} Promise of metadata + */ + static retrieveChangelog(): Promise<MetadataTypeMapObj>; + /** + * Retrieves SOAP based metadata of metadata type into local filesystem. executes callback with retrieved metadata + * + * @private + * @param {string} [retrieveDir] Directory where retrieved metadata directory will be saved + * @param {string} [key] customer key of single item to retrieve + * @returns {Promise.<MetadataTypeMapObj>} Promise of metadata + */ + private static _retrieve; + /** + * Retrieves SOAP via generic fuel-soap wrapper based metadata of metadata type into local filesystem. executes callback with retrieved metadata + * + * @param {string} retrieveDir Directory where retrieved metadata directory will be saved + * @param {SoapRequestParams} [requestParams] required for the specific request (filter for example) + * @param {string} [singleRetrieve] key of single item to filter by + * @param {string[]} [additionalFields] Returns specified fields even if their retrieve definition is not set to true + * @returns {Promise.<MetadataTypeMapObj>} Promise of item map + */ + static retrieveSOAP(retrieveDir: string, requestParams?: SoapRequestParams, singleRetrieve?: string, additionalFields?: string[]): Promise<MetadataTypeMapObj>; + /** + * helper for {@link retrieveSOAP} and {@link upsert}; populates userIdBuMap + * + * @param {MetadataTypeItem[]} [metadataList] - + * @returns {Promise.<void>} - + */ + static cacheBusinessUnitAssignments(metadataList?: MetadataTypeItem[]): Promise<void>; + /** + * helper for {@link User.retrieveSOAP} + * + * @private + * @param {SoapRequestParams} requestParams required for the specific request (filter for example) + * @param {string} soapType e.g. AccountUser + * @param {string[]} fields list of fields to retrieve + * @param {object} resultsBulk actual return value of this method + * @returns {Promise.<boolean>} success flag + */ + private static _retrieveSOAP_installedPackage; + /** + * + * @param {string} dateStr first date + * @param {string} interval defaults to 'days' + * @returns {string} time difference + */ + static "__#private@#timeSinceDate"(dateStr: string, interval?: string): string; + /** + * helper to print bu names + * + * @private + * @param {number} id bu id + * @returns {string} "bu name (bu id)"" + */ + private static _getBuName; + /** + * helper that gets BU names from config + * + * @private + */ + private static _getBuNames; + /** + * helper for {@link User.createOrUpdate} to generate a random initial password for new users + * note: possible minimum length values in SFMC are 6, 8, 10, 15 chars. Therefore we should default here to 15 chars. + * + * @private + * @param {number} [length] length of password; defaults to 15 + * @returns {string} random password + */ + private static _generatePassword; + /** + * Creates markdown documentation of all roles + * + * @param {UserDocumentMap} [metadata] user list + * @returns {Promise.<void>} - + */ + static document(metadata?: UserDocumentMap): Promise<void>; + /** + * + * @private + * @param {object[]} users list of users and installed package + * @param {'Installed Package'|'User'|'Inactivated User'} type choose what sub type to print + * @param {Array[]} columnsToPrint helper array + * @returns {string} markdown + */ + private static _generateDocMd; + /** + * manages post retrieve steps + * + * @param {UserDocument} metadata a single item + * @returns {MetadataTypeItem | void} a single item + */ + static postRetrieveTasks(metadata: UserDocument): MetadataTypeItem | void; +} +declare namespace User { + let buIdName: {}; + let definition: { + bodyIteratorField: string; + dependencies: string[]; + dependencyGraph: {}; + folderType: any; + hasExtended: boolean; + idField: string; + keepId: boolean; + keyIsFixed: boolean; + keyField: string; + nameField: string; + createdDateField: string; + createdNameField: any; + lastmodDateField: string; + lastmodNameField: string; + maxKeyLength: number; + type: string; + soapType: string; + typeDescription: string; + typeName: string; + typeRetrieveByDefault: boolean; + typeCdpByDefault: boolean; + documentInOneFile: boolean; + stringifyFieldsBeforeTemplate: string[]; + fields: { + AccountUserID: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + ActiveFlag: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + AssociatedBusinessUnits: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + BusinessUnit: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + ChallengeAnswer: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + ChallengePhrase: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'Client.ID': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'Client.ModifiedBy': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'Client.PartnerClientKey': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + CorrelationID: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + CreatedDate: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + CustomerKey: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + DefaultApplication: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + DefaultBusinessUnit: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + DefaultBusinessUnitObject: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + Delete: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + Email: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + ID: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + IsAPIUser: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + IsLocked: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'LanguageLocale.LocaleCode': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + LastSuccessfulLogin: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'Locale.LocaleCode': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'Locale.ObjectID': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'Locale.PartnerKey': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + ModifiedDate: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + MustChangePassword: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + Name: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + NotificationEmailAddress: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + ObjectID: { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + ObjectState: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + Owner: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + PartnerKey: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + PartnerProperties: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + Password: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + Roles: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'Roles.Role': { + skipValidation: boolean; + }; + 'Roles.Role[].Client': { + skipValidation: boolean; + }; + SsoIdentities: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'SsoIdentities.SsoIdentity': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'SsoIdentities.SsoIdentity[].IsActive': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'SsoIdentities.SsoIdentity[].FederatedID': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'TimeZone.ID': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'TimeZone.Name': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'TimeZone.ObjectID': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'TimeZone.PartnerKey': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + Unlock: { + skipValidation: boolean; + isCreateable: boolean; + isUpdateable: boolean; + template: boolean; + }; + UserID: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + UserPermissions: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'UserPermissions.PartnerKey': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: boolean; + }; + 'UserPermissions.ID': { + skipValidation: boolean; + }; + 'UserPermissions.ObjectID': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: boolean; + }; + 'UserPermissions.Name': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: boolean; + }; + 'UserPermissions.Value': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: boolean; + }; + 'UserPermissions.Description': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: boolean; + }; + 'UserPermissions.Delete': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: boolean; + }; + 'UserPermissions[].PartnerKey': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: boolean; + }; + 'UserPermissions[].ID': { + skipValidation: boolean; + }; + 'UserPermissions[].ObjectID': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: boolean; + }; + 'UserPermissions[].Name': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: boolean; + }; + 'UserPermissions[].Value': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: boolean; + }; + 'UserPermissions[].Description': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: boolean; + }; + 'UserPermissions[].Delete': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: boolean; + }; + c__type: { + isCreateable: boolean; + isUpdateable: boolean; + retrieve: any; + template: boolean; + }; + c__AssociatedBusinessUnits: { + skipValidation: boolean; + }; + c__RoleNamesGlobal: { + skipValidation: boolean; + }; + c__LocaleCode: { + skipValidation: boolean; + }; + c__TimeZoneName: { + skipValidation: boolean; + }; + c__AccountUserID: { + isCreateable: boolean; + isUpdateable: boolean; + retrieve: any; + template: boolean; + }; + c__IsLocked_readOnly: { + isCreateable: boolean; + isUpdateable: boolean; + retrieve: any; + template: boolean; + }; + }; + }; +} +import MetadataType from './MetadataType.js'; +//# sourceMappingURL=User.d.ts.map \ No newline at end of file diff --git a/@types/lib/metadataTypes/User.d.ts.map b/@types/lib/metadataTypes/User.d.ts.map new file mode 100644 index 000000000..7ba8ea20b --- /dev/null +++ b/@types/lib/metadataTypes/User.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"User.d.ts","sourceRoot":"","sources":["../../../lib/metadataTypes/User.js"],"names":[],"mappings":";uBAQa,OAAO,wBAAwB,EAAE,QAAQ;0BACzC,OAAO,wBAAwB,EAAE,WAAW;8BAC5C,OAAO,wBAAwB,EAAE,eAAe;+BAChD,OAAO,wBAAwB,EAAE,gBAAgB;mCACjD,OAAO,wBAAwB,EAAE,oBAAoB;kCACrD,OAAO,wBAAwB,EAAE,mBAAmB;8BACpD,OAAO,wBAAwB,EAAE,eAAe;iCAChD,OAAO,wBAAwB,EAAE,kBAAkB;gCACnD,OAAO,wBAAwB,EAAE,iBAAiB;0BAClD,OAAO,wBAAwB,EAAE,WAAW;2BAI5C,OAAO,wBAAwB,EAAE,YAAY;mCAC7C,OAAO,wBAAwB,EAAE,oBAAoB;+BACrD,OAAO,wBAAwB,EAAE,gBAAgB;8BACjD,OAAO,wBAAwB,EAAE,eAAe;uCAChD,OAAO,wBAAwB,EAAE,wBAAwB;AAlBtE;;;;;;;;;;;GAWG;AAEH;;;;;;GAMG;AAEH;;;;GAIG;AACH;IACI,8BAAyB;IACzB,wBAAmB;IAEnB;;;;;;;;OAQG;IACH,6BANW,MAAM,KACN,IAAI,GAAG,MAAM,EAAE,OACf,IAAI,GAAG,MAAM,EAAE,QACf,MAAM,GACJ,OAAO,CAAE,kBAAkB,CAAC,CASxC;IAED;;;;OAIG;IACH,2BAFa,OAAO,CAAE,kBAAkB,CAAC,CAIxC;IAED;;;;;OAKG;IACH,wBAHW,gBAAgB,gBAS1B;IAED;;;;;OAKG;IACH,wBAHW,gBAAgB,gBAS1B;IAED;;;;;OAKG;IACH,gCAHW,YAAY,GACV,OAAO,CAAE,YAAY,CAAC,CA2HlC;IAkBD;;;;;;;;;OASG;IACH,gCAPW,eAAe,eACf,MAAM,YACN,OAAO,oBACP,gBAAgB,EAAE,oBAClB,YAAY,EAAE,GACZ,OAAO,CAAE,QAAQ,GAAC,QAAQ,GAAC,MAAM,CAAC,CA4B9C;IAED;;;;;;;OAOG;IACH,qCAoCC;IAED;;;;;OAKG;IACH,sCAHW,eAAe,GACb,OAAO,CAAE,IAAI,CAAC,CAM1B;IAED;;;;;;OAMG;IACH,oCAoGC;IAED;;;;;;OAMG;IACH,sCAYC;IAED;;;;;;;;OAQG;IACH,uCAmFC;IAED;;;;;;;;;OASG;IACH,uCAPW,MAAM,YACN,MAAM,UACN,MAAM,kBACN,OAAO,mBACP,OAAO,GACL,MAAM,CAyBlB;IAED;;;;OAIG;IACH,4BAFa,OAAO,CAAE,kBAAkB,CAAC,CAIxC;IAED;;;;;;;OAOG;IACH,yBA8BC;IAED;;;;;;;;OAQG;IACH,iCANW,MAAM,kBACN,iBAAiB,mBACjB,MAAM,qBACN,MAAM,EAAE,GACN,OAAO,CAAE,kBAAkB,CAAC,CA6GxC;IAED;;;;;OAKG;IACH,mDAHW,gBAAgB,EAAE,GAChB,OAAO,CAAE,IAAI,CAAC,CA0C1B;IAED;;;;;;;;;OASG;IACH,8CAqEC;IAED;;;;;OAKG;IACH,4CAJW,MAAM,aACN,MAAM,GACJ,MAAM,CAqDlB;IAED;;;;;;OAMG;IACH,0BAGC;IAED;;;;OAIG;IACH,2BAOC;IAED;;;;;;;OAOG;IACH,iCAmBC;IAED;;;;;OAKG;IACH,2BAHW,eAAe,GACb,OAAO,CAAE,IAAI,CAAC,CA0I1B;IAED;;;;;;;OAOG;IACH,8BAeC;IAED;;;;;OAKG;IACH,mCAHW,YAAY,GACV,gBAAgB,GAAG,IAAI,CAoEnC;CACJ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;yBA1tCwB,mBAAmB"} \ No newline at end of file diff --git a/@types/lib/metadataTypes/Verification.d.ts b/@types/lib/metadataTypes/Verification.d.ts new file mode 100644 index 000000000..bf35c3b38 --- /dev/null +++ b/@types/lib/metadataTypes/Verification.d.ts @@ -0,0 +1,190 @@ +export default Verification; +export type BuObject = import("../../types/mcdev.d.js").BuObject; +export type CodeExtract = import("../../types/mcdev.d.js").CodeExtract; +export type CodeExtractItem = import("../../types/mcdev.d.js").CodeExtractItem; +export type MetadataTypeItem = import("../../types/mcdev.d.js").MetadataTypeItem; +export type MetadataTypeItemDiff = import("../../types/mcdev.d.js").MetadataTypeItemDiff; +export type MetadataTypeItemObj = import("../../types/mcdev.d.js").MetadataTypeItemObj; +export type MetadataTypeMap = import("../../types/mcdev.d.js").MetadataTypeMap; +export type MetadataTypeMapObj = import("../../types/mcdev.d.js").MetadataTypeMapObj; +export type SoapRequestParams = import("../../types/mcdev.d.js").SoapRequestParams; +export type TemplateMap = import("../../types/mcdev.d.js").TemplateMap; +export type RestError = import("../../types/mcdev.d.js").RestError; +export type VerificationItem = import("../../types/mcdev.d.js").VerificationItem; +/** + * @typedef {import('../../types/mcdev.d.js').BuObject} BuObject + * @typedef {import('../../types/mcdev.d.js').CodeExtract} CodeExtract + * @typedef {import('../../types/mcdev.d.js').CodeExtractItem} CodeExtractItem + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItem} MetadataTypeItem + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItemDiff} MetadataTypeItemDiff + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItemObj} MetadataTypeItemObj + * @typedef {import('../../types/mcdev.d.js').MetadataTypeMap} MetadataTypeMap + * @typedef {import('../../types/mcdev.d.js').MetadataTypeMapObj} MetadataTypeMapObj + * @typedef {import('../../types/mcdev.d.js').SoapRequestParams} SoapRequestParams + * @typedef {import('../../types/mcdev.d.js').TemplateMap} TemplateMap + * @typedef {import('../../types/mcdev.d.js').RestError} RestError + */ +/** + * @typedef {import('../../types/mcdev.d.js').VerificationItem} VerificationItem + */ +/** + * Verification MetadataType + * + * @augments MetadataType + */ +declare class Verification extends MetadataType { + static verificationIdKeyMap: any; + /** + * Retrieves Metadata of Data Verification Activity. + * + * @param {string} [retrieveDir] Directory where retrieved metadata directory will be saved + * @param {void | string[]} [_] unused parameter + * @param {void | string[]} [__] unused parameter + * @param {string} [key] customer key of single item to retrieve + * @returns {Promise.<MetadataTypeMapObj>} Promise of metadata + */ + static retrieve(retrieveDir?: string, _?: void | string[], __?: void | string[], key?: string): Promise<MetadataTypeMapObj>; + /** + * helper for {@link this.retrieveRESTcollection} + * + * @param {RestError} ex exception + * @param {string} id id or key of item + * @returns {null} - + */ + static handleRESTErrors(ex: RestError, id: string): null; + /** + * Retrieves Metadata of item for caching + * + * @returns {Promise.<MetadataTypeMapObj>} Promise of metadata + */ + static retrieveForCache(): Promise<MetadataTypeMapObj>; + /** + * Creates a single item + * + * @param {VerificationItem} metadata a single item + * @returns {Promise} Promise + */ + static create(metadata: VerificationItem): Promise<any>; + /** + * Updates a single item + * + * @param {VerificationItem} metadata a single item + * @returns {Promise} Promise + */ + static update(metadata: VerificationItem): Promise<any>; + /** + * prepares a verification for deployment + * + * @param {VerificationItem} metadata a single verification activity definition + * @returns {Promise.<VerificationItem>} metadata object + */ + static preDeployTasks(metadata: VerificationItem): Promise<VerificationItem>; + /** + * parses retrieved Metadata before saving + * + * @param {VerificationItem} metadata a single verification activity definition + * @returns {VerificationItem} Array with one metadata object and one sql string + */ + static postRetrieveTasks(metadata: VerificationItem): VerificationItem; +} +declare namespace Verification { + let definition: { + bodyIteratorField: string; + dependencies: string[]; + dependencyGraph: { + dataExtension: string[]; + }; + hasExtended: boolean; + idField: string; + keyIsFixed: boolean; + keyField: string; + createdDateField: any; + createdNameField: string; + lastmodDateField: any; + lastmodNameField: any; + nameField: string; + restPagination: boolean; + maxKeyLength: number; + type: string; + typeDescription: string; + typeRetrieveByDefault: boolean; + typeCdpByDefault: boolean; + typeName: string; + fields: { + createdBy: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + dataVerificationDefinitionId: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + notificationEmailAddress: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + notificationEmailMessage: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + shouldEmailOnFailure: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + shouldStopOnFailure: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + targetObjectId: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + value1: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + value2: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + verificationType: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + r__dataExtension_key: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + c__automation_step: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + }; + }; +} +import MetadataType from './MetadataType.js'; +//# sourceMappingURL=Verification.d.ts.map \ No newline at end of file diff --git a/@types/lib/metadataTypes/Verification.d.ts.map b/@types/lib/metadataTypes/Verification.d.ts.map new file mode 100644 index 000000000..e48ef1a5c --- /dev/null +++ b/@types/lib/metadataTypes/Verification.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"Verification.d.ts","sourceRoot":"","sources":["../../../lib/metadataTypes/Verification.js"],"names":[],"mappings":";uBAQa,OAAO,wBAAwB,EAAE,QAAQ;0BACzC,OAAO,wBAAwB,EAAE,WAAW;8BAC5C,OAAO,wBAAwB,EAAE,eAAe;+BAChD,OAAO,wBAAwB,EAAE,gBAAgB;mCACjD,OAAO,wBAAwB,EAAE,oBAAoB;kCACrD,OAAO,wBAAwB,EAAE,mBAAmB;8BACpD,OAAO,wBAAwB,EAAE,eAAe;iCAChD,OAAO,wBAAwB,EAAE,kBAAkB;gCACnD,OAAO,wBAAwB,EAAE,iBAAiB;0BAClD,OAAO,wBAAwB,EAAE,WAAW;wBAC5C,OAAO,wBAAwB,EAAE,SAAS;+BAI1C,OAAO,wBAAwB,EAAE,gBAAgB;AAf9D;;;;;;;;;;;;GAYG;AAEH;;GAEG;AAEH;;;;GAIG;AACH;IACI,iCAA4B;IAC5B;;;;;;;;OAQG;IACH,8BANW,MAAM,MACN,IAAI,GAAG,MAAM,EAAE,OACf,IAAI,GAAG,MAAM,EAAE,QACf,MAAM,GACJ,OAAO,CAAE,kBAAkB,CAAC,CAkFxC;IAED;;;;;;OAMG;IACH,4BAJW,SAAS,MACT,MAAM,GACJ,IAAI,CAehB;IAED;;;;OAIG;IACH,2BAFa,OAAO,CAAE,kBAAkB,CAAC,CAIxC;IAED;;;;;OAKG;IACH,wBAHW,gBAAgB,gBAK1B;IA6CD;;;;;OAKG;IACH,wBAHW,gBAAgB,gBAQ1B;IAED;;;;;OAKG;IACH,gCAHW,gBAAgB,GACd,OAAO,CAAE,gBAAgB,CAAC,CAYtC;IAcD;;;;;OAKG;IACH,mCAHW,gBAAgB,GACd,gBAAgB,CAgC5B;CAWJ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;yBAtSwB,mBAAmB"} \ No newline at end of file diff --git a/@types/lib/metadataTypes/definitions/Asset.definition.d.ts b/@types/lib/metadataTypes/definitions/Asset.definition.d.ts new file mode 100644 index 000000000..934bea484 --- /dev/null +++ b/@types/lib/metadataTypes/definitions/Asset.definition.d.ts @@ -0,0 +1,796 @@ +declare namespace _default { + let bodyIteratorField: string; + let dependencies: string[]; + namespace dependencyGraph { + let asset: string[]; + } + let folderType: string; + let hasExtended: boolean; + let idField: string; + let keyIsFixed: boolean; + let keyField: string; + let nameField: string; + let folderIdField: string; + let createdDateField: string; + let createdNameField: string; + let lastmodDateField: string; + let lastmodNameField: string; + let restPagination: boolean; + let maxKeyLength: number; + let type: string; + let typeDescription: string; + let typeRetrieveByDefault: string[]; + let typeCdpByDefault: boolean; + let typeName: string; + let stringifyFieldsBeforeTemplate: string[]; + let allowMatchingByName: boolean; + let fields: { + activeDate: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + allowedBlocks: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + assetType: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'assetType.displayName': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'assetType.id': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'assetType.name': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + availableViews: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + modelVersion: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + blocks: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + businessUnitAvailability: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'businessUnitAvailability.%': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'businessUnitAvailability.%.view': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'businessUnitAvailability.%.update': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'businessUnitAvailability.%.delete': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'businessUnitAvailability.%.memberId': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'businessUnitAvailability.%.transferOwnership': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + category: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'category.id': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'category.name': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'category.parentId': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + channels: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + content: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'content.url': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + contentType: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'createdBy.email': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'createdBy.id': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'createdBy.name': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'createdBy.userId': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + createdDate: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + customerKey: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + customFields: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'data.campaigns': { + skipValidation: boolean; + }; + 'data.approvals': { + skipValidation: boolean; + }; + 'data.email': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'data.email.attributes': { + skipValidation: boolean; + }; + 'data.email.legacy': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'data.email.options': { + skipValidation: boolean; + }; + 'data.portfolio': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'data.site': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'data.site.content': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'data.site.content.url': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + description: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + design: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + enterpriseId: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + file: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'fileProperties.fileName': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'fileProperties.extension': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'fileProperties.externalUrl': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'fileProperties.fileSize': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'fileProperties.fileCreatedDate': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'fileProperties.width': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'fileProperties.height': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'fileProperties.publishedURL': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + id: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + legacyData: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + locked: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + maxBlocks: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + memberId: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + meta: { + skipValidation: boolean; + }; + minBlocks: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'modifiedBy.email': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'modifiedBy.id': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'modifiedBy.name': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'modifiedBy.userId': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + modifiedDate: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + name: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + objectID: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + owner: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'owner.email': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'owner.id': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'owner.name': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'owner.userId': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + sharingProperties: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'sharingProperties.localAssets': { + skipValidation: boolean; + }; + 'sharingProperties.sharedWith': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'sharingProperties.sharedFrom': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'sharingProperties.sharedFromMID': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'sharingProperties.sharingType': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + slots: { + skipValidation: boolean; + }; + 'status.id': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'status.name': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + superContent: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + tags: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + template: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + thumbnail: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + version: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + views: { + skipValidation: boolean; + }; + r__folder_Path: { + skipValidation: boolean; + }; + }; + let subTypes: string[]; + let crosslinkedSubTypes: string[]; + let selflinkedSubTypes: string[]; + let binarySubtypes: string[]; + namespace extendedSubTypes { + export let archive: string[]; + let asset_1: string[]; + export { asset_1 as asset }; + export let audio: string[]; + export let block: string[]; + export let cloudpage: string[]; + export let code: string[]; + export let coderesource: string[]; + export let document: string[]; + export let image: string[]; + export let message: string[]; + export let other: string[]; + export let rawimage: string[]; + export let template: string[]; + export let textfile: string[]; + export let video: string[]; + } + let typeMapping: { + asset: number; + file: number; + block: number; + template: number; + message: number; + custom: number; + default: number; + image: number; + rawimage: number; + video: number; + document: number; + audio: number; + archive: number; + code: number; + textfile: number; + ai: number; + psd: number; + pdd: number; + eps: number; + gif: number; + jpe: number; + jpeg: number; + jpg: number; + jp2: number; + jpx: number; + pict: number; + pct: number; + png: number; + tif: number; + tiff: number; + tga: number; + bmp: number; + wmf: number; + vsd: number; + pnm: number; + pgm: number; + pbm: number; + ppm: number; + svg: number; + '3fr': number; + ari: number; + arw: number; + bay: number; + cap: number; + crw: number; + cr2: number; + dcr: number; + dcs: number; + dng: number; + drf: number; + eip: number; + erf: number; + fff: number; + iiq: number; + k25: number; + kdc: number; + mef: number; + mos: number; + mrw: number; + nef: number; + nrw: number; + orf: number; + pef: number; + ptx: number; + pxn: number; + raf: number; + raw: number; + rw2: number; + rwl: number; + rwz: number; + srf: number; + sr2: number; + srw: number; + x3f: number; + '3gp': number; + '3gpp': number; + '3g2': number; + '3gp2': number; + asf: number; + avi: number; + m2ts: number; + mts: number; + dif: number; + dv: number; + mkv: number; + mpg: number; + f4v: number; + flv: number; + mjpg: number; + mjpeg: number; + mxf: number; + mpeg: number; + mp4: number; + m4v: number; + mp4v: number; + mov: number; + swf: number; + wmv: number; + rm: number; + ogv: number; + indd: number; + indt: number; + incx: number; + wwcx: number; + doc: number; + docx: number; + dot: number; + dotx: number; + mdb: number; + mpp: number; + ics: number; + xls: number; + xlsx: number; + xlk: number; + xlsm: number; + xlt: number; + xltm: number; + csv: number; + tsv: number; + tab: number; + pps: number; + ppsx: number; + ppt: number; + pptx: number; + pot: number; + thmx: number; + pdf: number; + ps: number; + qxd: number; + rtf: number; + sxc: number; + sxi: number; + sxw: number; + odt: number; + ods: number; + ots: number; + odp: number; + otp: number; + epub: number; + dvi: number; + key: number; + keynote: number; + pez: number; + aac: number; + m4a: number; + au: number; + aif: number; + aiff: number; + aifc: number; + mp3: number; + wav: number; + wma: number; + midi: number; + oga: number; + ogg: number; + ra: number; + vox: number; + voc: number; + '7z': number; + arj: number; + bz2: number; + cab: number; + gz: number; + gzip: number; + iso: number; + lha: number; + sit: number; + tgz: number; + jar: number; + rar: number; + tar: number; + zip: number; + gpg: number; + htm: number; + html: number; + xhtml: number; + xht: number; + css: number; + less: number; + sass: number; + js: number; + json: number; + atom: number; + rss: number; + xml: number; + xsl: number; + xslt: number; + md: number; + markdown: number; + as: number; + fla: number; + eml: number; + text: number; + txt: number; + freeformblock: number; + textblock: number; + htmlblock: number; + textplusimageblock: number; + imageblock: number; + abtestblock: number; + dynamicblock: number; + stylingblock: number; + einsteincontentblock: number; + webpage: number; + webtemplate: number; + templatebasedemail: number; + htmlemail: number; + textonlyemail: number; + socialshareblock: number; + socialfollowblock: number; + buttonblock: number; + layoutblock: number; + defaulttemplate: number; + smartcaptureblock: number; + smartcaptureformfieldblock: number; + smartcapturesubmitoptionsblock: number; + slotpropertiesblock: number; + externalcontentblock: number; + codesnippetblock: number; + rssfeedblock: number; + formstylingblock: number; + referenceblock: number; + imagecarouselblock: number; + customblock: number; + liveimageblock: number; + livesettingblock: number; + contentmap: number; + jsonmessage: number; + icemailformblock: number; + coderesource: number; + jscoderesource: number; + csscoderesource: number; + jsoncoderesource: number; + rsscoderesource: number; + textcoderesource: number; + xmlcoderesource: number; + cloudpages: number; + landingpage: number; + microsite: number; + interactivecontent: number; + }; +} +export default _default; +//# sourceMappingURL=Asset.definition.d.ts.map \ No newline at end of file diff --git a/@types/lib/metadataTypes/definitions/Asset.definition.d.ts.map b/@types/lib/metadataTypes/definitions/Asset.definition.d.ts.map new file mode 100644 index 000000000..a42902167 --- /dev/null +++ b/@types/lib/metadataTypes/definitions/Asset.definition.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"Asset.definition.d.ts","sourceRoot":"","sources":["../../../../lib/metadataTypes/definitions/Asset.definition.js"],"names":[],"mappings":""} \ No newline at end of file diff --git a/@types/lib/metadataTypes/definitions/AttributeGroup.definition.d.ts b/@types/lib/metadataTypes/definitions/AttributeGroup.definition.d.ts new file mode 100644 index 000000000..f51440c42 --- /dev/null +++ b/@types/lib/metadataTypes/definitions/AttributeGroup.definition.d.ts @@ -0,0 +1,250 @@ +declare namespace _default { + let bodyIteratorField: string; + let dependencies: string[]; + namespace dependencyGraph { + let attributeSet: string[]; + } + let hasExtended: boolean; + let idField: string; + let keyIsFixed: boolean; + let keyField: string; + let nameField: string; + let restPagination: boolean; + let type: string; + let typeDescription: string; + let typeRetrieveByDefault: boolean; + let typeCdpByDefault: boolean; + let typeName: string; + let fields: { + applicationID: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + applicationKey: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + attributeCount: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + attributeGroupIconKey: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + attributeGroupType: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + attributeSetIdentifiers: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'attributeSetIdentifiers[].connectingID.identifierType': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: boolean; + }; + 'attributeSetIdentifiers[].definitionID': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: boolean; + }; + 'attributeSetIdentifiers[].definitionKey': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: boolean; + }; + 'attributeSetIdentifiers[].definitionName.value': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: boolean; + }; + 'attributeSetIdentifiers[].namespace': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: boolean; + }; + canAddProperties: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + canAddRelationships: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + canChangeProperties: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + canModify: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + canRemove: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + connectingID: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'connectingID.identifierType': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + containsSchemaAttributes: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + definitionID: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + definitionKey: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'definitionName.value': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + description: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + displayOrder: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + fullyQualifiedName: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + isHidden: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + isOwner: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + isPrimary: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + isSystemDefined: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + localizedDescription: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'localizedDescription.resourceSetKey': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: boolean; + }; + 'localizedDescription.resourceValueKey': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: boolean; + }; + 'localizedDescription.value': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: boolean; + }; + mID: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + namespace: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + objectState: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + requiredRelationships: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + r__attributeSet_key: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + }; +} +export default _default; +//# sourceMappingURL=AttributeGroup.definition.d.ts.map \ No newline at end of file diff --git a/@types/lib/metadataTypes/definitions/AttributeGroup.definition.d.ts.map b/@types/lib/metadataTypes/definitions/AttributeGroup.definition.d.ts.map new file mode 100644 index 000000000..c2e765326 --- /dev/null +++ b/@types/lib/metadataTypes/definitions/AttributeGroup.definition.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"AttributeGroup.definition.d.ts","sourceRoot":"","sources":["../../../../lib/metadataTypes/definitions/AttributeGroup.definition.js"],"names":[],"mappings":""} \ No newline at end of file diff --git a/@types/lib/metadataTypes/definitions/AttributeSet.definition.d.ts b/@types/lib/metadataTypes/definitions/AttributeSet.definition.d.ts new file mode 100644 index 000000000..03cbda50a --- /dev/null +++ b/@types/lib/metadataTypes/definitions/AttributeSet.definition.d.ts @@ -0,0 +1,974 @@ +declare namespace _default { + let bodyIteratorField: string; + let dependencies: string[]; + namespace dependencyGraph { + let dataExtension: string[]; + let attributeSet: string[]; + let attributeGroup: string[]; + } + let hasExtended: boolean; + let idField: string; + let keyIsFixed: boolean; + let keyField: string; + let nameField: string; + let folderIdField: string; + let createdDateField: string; + let createdNameField: string; + let lastmodDateField: any; + let lastmodNameField: any; + let restPagination: boolean; + let type: string; + let typeDescription: string; + let typeRetrieveByDefault: boolean; + let typeCdpByDefault: boolean; + let typeName: string; + let fields: { + applicationID: { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + applicationKey: { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + attributeCount: { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + canAddValues: { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + canChangeValues: { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + canModify: { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + canRemove: { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + categoryID: { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + 'connectingID.identifierType': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + createDate: { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + createdBy: { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + customObjectOwnerMID: { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + 'dataRetentionProperties.isDeleteAtEndOfRetentionPeriod': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + 'dataRetentionProperties.isResetRetentionPeriodOnImport': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + 'dataRetentionProperties.isRowBasedRetention': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + 'dataRetentionProperties.periodUnitOfMeasure': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + 'dataRetentionProperties.setDefinitionID': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + 'dataRetentionProperties.periodLength': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + definitionID: { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + definitionKey: { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + definitionName: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'definitionName.value': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + fullyQualifiedName: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + isCustomObjectBacked: { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + isEvent: { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + isHidden: { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + isReadOnly: { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + isRoot: { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + isSendable: { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + isShared: { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + isSystemDefined: { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + isTestaable: { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + 'leftConnectingID.identifierType': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + 'leftItem.cardinality': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + 'leftItem.cardinality ': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + 'leftItem.connectingID.identifierType': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + 'leftItem.identifier': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + 'leftItem.relationshipType': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + localizedDescription: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'localizedDescription.resourceSetKey': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'localizedDescription.resourceValueKey': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'localizedDescription.value': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + name: { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + nonStandardAttributeGroupReferences: { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + 'nonStandardAttributeGroupReferences[].attributeGroupType': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + 'nonStandardAttributeGroupReferences[].attributeGroupID': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + 'nonStandardAttributeGroupReferences[].definitionKey': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + 'obfuscationProperties.maskType': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + 'obfuscationProperties.maskTypeID': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + 'obfuscationProperties.storageType': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + 'obfuscationProperties.storageTypeID': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + 'obfuscationProperties.valueDefinitionID': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + 'parentDefinition.connectingID.identifierType': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + 'parentDefinition.definitionID': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + 'parentDefinition.definitionKey': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + 'parentDefinition.definitionName.value': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + parentID: { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + relationshipCount: { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + relationships: { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + 'relationships[].canModify': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + 'relationships[].canRemove': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + 'relationships[].isGroupToSetRelationship': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + 'relationships[].isHidden': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + 'relationships[].isSystemDefined': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + 'relationships[].leftRelationshipID': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + 'relationships[].leftRelationshipIDs': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + 'relationships[].leftItem.cardinality': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + 'relationships[].leftItem.relationshipType': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + 'relationships[].leftItem.r__attributeSet_key': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + 'relationships[].leftItem.r__attributeGroup_key': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + 'relationships[].rightItem.cardinality': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + 'relationships[].rightItem.relationshipType': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + 'relationships[].rightItem.r__attributeSet_key': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + 'relationships[].rightItem.r__attributeGroup_key': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + 'relationships[].leftRelationshipIDs[].type': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + 'relationships[].leftRelationshipIDs[].value': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + 'relationships[].leftRelationshipReferenceType': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + 'relationships[].relationshipAttributes': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + 'relationships[].relationshipAttributes[].leftAttributeID': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + 'relationships[].relationshipAttributes[].rightAttributeID': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + 'relationships[].relationshipAttributes[].c__leftFullyQualifiedName': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + 'relationships[].relationshipAttributes[].c__rightFullyQualifiedName': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + 'relationships[].relationshipID': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + 'rightConnectingID.identifierType': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + 'rightItem.cardinality': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + 'rightItem.connectingID.identifierType': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + 'rightItem.identifier': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + 'rightItem.relationshipType': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + sendAttributeStorageName: { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + sendContactKeyStorageName: { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + setDefinitionID: { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + setDefinitionKey: { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + 'setDefinitionName.value': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + 'storageFieldReferenceID.type': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + 'storageFieldReferenceID.value': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + storageLogicalType: { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + storageName: { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + 'storageObjectFieldInformation.externalIsRowIdentifier': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + 'storageObjectFieldInformation.externalObjectFieldAPIName': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + 'storageObjectFieldInformation.externalObjectFieldDataTypeName': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + 'storageObjectFieldInformation.externalObjectFieldLength': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + storageObjectIDs: { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + 'storageObjectInformation.externalObjectAPIName': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + 'storageReferenceID.type': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + 'storageReferenceID.value': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + valueDefinitions: { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + 'valueDefinitions[].baseType': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + 'valueDefinitions[].customerDataID': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + 'valueDefinitions[].connectingID': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + 'valueDefinitions[].dataSourceID': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + 'valueDefinitions[].dataSourceName': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + 'valueDefinitions[].dataType': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + 'valueDefinitions[].defaultValue': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + 'valueDefinitions[].definitionID': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + 'valueDefinitions[].definitionKey': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + 'valueDefinitions[].definitionName': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + 'valueDefinitions[].description': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + 'valueDefinitions[].displayOrder': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + 'valueDefinitions[].fullyQualifiedName': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + 'valueDefinitions[].identifierType': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + 'valueDefinitions[].isHidden': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + 'valueDefinitions[].isIdentityValue': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + 'valueDefinitions[].isNullable': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + 'valueDefinitions[].isPrimaryKey': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + 'valueDefinitions[].isReadOnly': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + 'valueDefinitions[].isSystemDefined': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + 'valueDefinitions[].isUpdateable': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + 'valueDefinitions[].length': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + 'valueDefinitions[].localizedDescription': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + 'valueDefinitions[].name': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + 'valueDefinitions[].obfuscationProperties': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + 'valueDefinitions[].obfuscationProperties.maskType': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + 'valueDefinitions[].obfuscationProperties.maskTypeID': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + 'valueDefinitions[].obfuscationProperties.storageType': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + 'valueDefinitions[].obfuscationProperties.storageTypeID': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + 'valueDefinitions[].obfuscationProperties.valueDefinitionID': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + 'valueDefinitions[].ordinal': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + 'valueDefinitions[].parentDefinition': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + 'valueDefinitions[].parentIdentifier': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + 'valueDefinitions[].parentType': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + 'valueDefinitions[].restrictionLookupListID': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + 'valueDefinitions[].scale': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + 'valueDefinitions[].setDefinitionID': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + 'valueDefinitions[].setDefinitionKey': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + 'valueDefinitions[].setDefinitionName': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + 'valueDefinitions[].storageFieldReferenceID': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + 'valueDefinitions[].storageFieldReferenceID.type': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + 'valueDefinitions[].storageFieldReferenceID.value': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + 'valueDefinitions[].storageFieldValueID.type': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + 'valueDefinitions[].storageFieldValueID.value': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + 'valueDefinitions[].storageName': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + 'valueDefinitions[].storageObjectFieldInformation': { + skipValidation: boolean; + }; + 'valueDefinitions[].storageObjectFieldInformation.externalObjectFieldAPIName': { + skipValidation: boolean; + }; + 'valueDefinitions[].storageObjectFieldInformation.externalObjectFieldDataTypeName': { + skipValidation: boolean; + }; + 'valueDefinitions[].storageObjectFieldInformation.externalObjectFieldLength': { + skipValidation: boolean; + }; + 'valueDefinitions[].storageObjectFieldInformation.externalIsRowIdentifier': { + skipValidation: boolean; + }; + 'valueDefinitions[].valueDefinitionID': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + 'valueDefinitions[].valueDefinitionKey': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + r__folder_Path: { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + r__dataExtension_key: { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + }; +} +export default _default; +//# sourceMappingURL=AttributeSet.definition.d.ts.map \ No newline at end of file diff --git a/@types/lib/metadataTypes/definitions/AttributeSet.definition.d.ts.map b/@types/lib/metadataTypes/definitions/AttributeSet.definition.d.ts.map new file mode 100644 index 000000000..938075179 --- /dev/null +++ b/@types/lib/metadataTypes/definitions/AttributeSet.definition.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"AttributeSet.definition.d.ts","sourceRoot":"","sources":["../../../../lib/metadataTypes/definitions/AttributeSet.definition.js"],"names":[],"mappings":""} \ No newline at end of file diff --git a/@types/lib/metadataTypes/definitions/Automation.definition.d.ts b/@types/lib/metadataTypes/definitions/Automation.definition.d.ts new file mode 100644 index 000000000..bfe288252 --- /dev/null +++ b/@types/lib/metadataTypes/definitions/Automation.definition.d.ts @@ -0,0 +1,688 @@ +declare namespace _default { + export namespace activityTypeMapping { + let dataExtract: number; + let dataFactoryUtility: number; + let emailSend: number; + let fileTransfer: number; + let filter: number; + let fireEvent: number; + let importFile: number; + let journeyEntry: number; + let journeyEntryOld: number; + let query: number; + let script: number; + let verification: number; + let wait: number; + let push: number; + let sms: number; + let reportDefinition: number; + let refreshMobileFilteredList: number; + let refreshGroup: number; + let interactions: number; + let interactionStudioData: number; + let importMobileContact: number; + } + export let bodyIteratorField: string; + export let dependencies: string[]; + export namespace dependencyGraph { + let dataExtract_1: string[]; + export { dataExtract_1 as dataExtract }; + let emailSend_1: string[]; + export { emailSend_1 as emailSend }; + let fileTransfer_1: string[]; + export { fileTransfer_1 as fileTransfer }; + let importFile_1: string[]; + export { importFile_1 as importFile }; + let query_1: string[]; + export { query_1 as query }; + let script_1: string[]; + export { script_1 as script }; + let verification_1: string[]; + export { verification_1 as verification }; + } + export let folderType: string; + export let hasExtended: boolean; + export namespace filter_1 { + let description: string[]; + } + export { filter_1 as filter }; + export let idField: string; + export let keyIsFixed: boolean; + export let keyField: string; + export let nameField: string; + export let folderIdField: string; + export let createdDateField: string; + export let createdNameField: string; + export let lastmodDateField: string; + export let lastmodNameField: string; + export let restPagination: boolean; + export let maxKeyLength: number; + export namespace scheduleTypeMapping { + let MINUTELY: number; + let HOURLY: number; + let DAILY: number; + let WEEKLY: number; + let MONTHLY: number; + } + export namespace statusMapping { + let AwaitingTrigger: number; + let Building: number; + let BuildingError: number; + let Error: number; + let InactiveTrigger: number; + let PausedSchedule: number; + let Ready: number; + let Running: number; + let Scheduled: number; + let Stopped: number; + } + export let fileNameOperatorMapping: { + Equals: number; + Contains: number; + 'Begins with': number; + 'Ends with': number; + }; + export let timeZoneMapping: { + 'Afghanistan Standard Time': number; + 'Alaskan Standard Time': number; + 'Arab Standard Time': number; + 'Arabian Standard Time': number; + 'Arabic Standard Time': number; + 'Argentina Standard Time': number; + 'Atlantic Standard Time': number; + 'AUS Central Standard Time': number; + 'AUS Eastern Standard Time': number; + 'Azerbaijan Standard Time': number; + 'Azores Standard Time': number; + 'Canada Central Standard Time': number; + 'Cape Verde Standard Time': number; + 'Caucasus Standard Time': number; + 'Cen. Australia Standard Time': number; + 'Central America Standard Time': number; + 'Central Asia Standard Time': number; + 'Central Brazilian Standard Time': number; + 'Central Europe Standard Time': number; + 'Central European Standard Time': number; + 'Central Pacific Standard Time': number; + 'Central Standard Time': number; + 'Central Standard Time (Mexico)': number; + 'Central Standard Time (no DST)': number; + 'China Standard Time': number; + 'Dateline Standard Time': number; + 'E. Africa Standard Time': number; + 'E. Australia Standard Time': number; + 'E. Europe Standard Time': number; + 'E. South America Standard Time': number; + 'Eastern Standard Time': number; + 'Egypt Standard Time': number; + 'Ekaterinburg Standard Time': number; + 'Fiji Standard Time': number; + 'FLE Standard Time': number; + 'Georgian Standard Time': number; + 'GMT Standard Time': number; + 'Greenland Standard Time': number; + 'Greenwich Standard Time': number; + 'GTB Standard Time': number; + 'Hawaiian Standard Time': number; + 'India Standard Time': number; + 'Iran Standard Time': number; + 'Israel Standard Time': number; + 'Jordan Standard Time': number; + 'Korea Standard Time': number; + 'Mauritius Standard Time': number; + 'Mid-Atlantic Standard Time': number; + 'Middle East Standard Time': number; + 'Montevideo Standard Time': number; + 'Morocco Standard Time': number; + 'Mountain Standard Time': number; + 'Mountain Standard Time (Mexico)': number; + 'Myanmar Standard Time': number; + 'N. Central Asia Standard Time': number; + 'Namibia Standard Time': number; + 'Nepal Standard Time': number; + 'New Zealand Standard Time': number; + 'Newfoundland Standard Time': number; + 'North Asia East Standard Time': number; + 'North Asia Standard Time': number; + 'Pacific SA Standard Time': number; + 'Pacific Standard Time': number; + 'Pacific Standard Time (Mexico)': number; + 'Pakistan Standard Time': number; + 'Romance Standard Time': number; + 'Russian Standard Time': number; + 'SA Pacific Standard Time': number; + 'SA Western Standard Time': number; + 'Samoa Standard Time': number; + 'SE Asia Standard Time': number; + 'Singapore Standard Time': number; + 'South Africa Standard Time': number; + 'Sri Lanka Standard Time': number; + 'Taipei Standard Time': number; + 'Tasmania Standard Time': number; + 'Tokyo Standard Time': number; + 'Tonga Standard Time': number; + 'US Eastern Standard Time': number; + 'US Mountain Standard Time': number; + 'Venezuela Standard Time': number; + 'Vladivostok Standard Time': number; + 'W. Australia Standard Time': number; + 'W. Central Africa Standard Time': number; + 'W. Europe Standard Time': number; + 'West Asia Standard Time': number; + 'West Pacific Standard Time': number; + 'Yakutsk Standard Time': number; + }; + export let timeZoneDifference: { + 1: string; + 2: string; + 3: string; + 4: string; + 5: string; + 6: string; + 7: string; + 8: string; + 9: string; + 10: string; + 11: string; + 12: string; + 13: string; + 14: string; + 15: string; + 16: string; + 17: string; + 18: string; + 19: string; + 20: string; + 21: string; + 22: string; + 23: string; + 24: string; + 25: string; + 26: string; + 27: string; + 28: string; + 29: string; + 30: string; + 31: string; + 32: string; + 33: string; + 34: string; + 35: string; + 36: string; + 37: string; + 38: string; + 39: string; + 40: string; + 41: string; + 42: string; + 43: string; + 44: string; + 45: string; + 46: string; + 47: string; + 48: string; + 49: string; + 50: string; + 51: string; + 52: string; + 53: string; + 54: string; + 55: string; + 56: string; + 57: string; + 58: string; + 59: string; + 60: string; + 61: string; + 62: string; + 63: string; + 64: string; + 65: string; + 66: string; + 67: string; + 68: string; + 69: string; + 70: string; + 71: string; + 72: string; + 73: string; + 74: string; + 75: string; + 76: string; + 77: string; + 78: string; + 79: string; + 80: string; + 81: string; + 82: string; + 83: string; + 84: string; + 85: string; + 86: string; + 87: string; + 88: string; + 89: string; + 90: string; + 91: string; + 92: string; + }; + export let type: string; + export let typeDescription: string; + export let typeRetrieveByDefault: boolean; + export let typeCdpByDefault: boolean; + export let typeName: string; + export let customDeployTypes: string[]; + export let manualDeployTypes: any[]; + export let fields: { + categoryId: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + description: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'fileTrigger.fileNamePatternTypeId': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'fileTrigger.fileNamingPattern': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'fileTrigger.folderLocationText': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'fileTrigger.isPublished': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'fileTrigger.queueFiles': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'fileTrigger.triggerActive': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + id: { + isCreateable: boolean; + isUpdateable: any; + retrieving: boolean; + template: boolean; + }; + key: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + lastRunInstanceId: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + lastRunTime: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + legacyId: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + lastSavedDate: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + lastSavedByName: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + createdByName: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + createdDate: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + createdName: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + modifiedDate: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + modifiedName: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + pausedDate: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + pausedName: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + updateInProgress: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + name: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + notifications: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'notifications[].email': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'notifications[].message': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'notifications[].channelType': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'notifications[].type': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'notifications[].notificationType': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + startSource: { + skipValidation: boolean; + }; + 'schedule.endDate': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'schedule.icalRecur': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'schedule.id': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'schedule.occurrences': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'schedule.pattern': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'schedule.rangeTypeId': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'schedule.scheduledTime': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'schedule.scheduleStatus': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'schedule.startDate': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'schedule.statusId': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'schedule.timezoneId': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'schedule.timezoneName': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'schedule.typeId': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'schedule.scheduleTypeId': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'schedule.description': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + status: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + statusId: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + steps: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'steps[].activities': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'steps[].activities[].activityObjectId': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'steps[].activities[].displayOrder': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'steps[].activities[].id': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'steps[].activities[].name': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'steps[].activities[].objectTypeId': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'steps[].activities[].targetDataExtensions': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'steps[].activities[].description': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'steps[].activities[].serializedObject': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'steps[].activities[].r__type': { + skipValidation: boolean; + }; + 'steps[].activities[].r__key': { + skipValidation: boolean; + }; + 'steps[].activities[].timeZone': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'steps[].description': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'steps[].annotation': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'steps[].id': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'steps[].name': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'steps[].step': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'steps[].stepNumber': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + type: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + typeId: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + r__folder_Path: { + skipValidation: boolean; + }; + }; +} +export default _default; +//# sourceMappingURL=Automation.definition.d.ts.map \ No newline at end of file diff --git a/@types/lib/metadataTypes/definitions/Automation.definition.d.ts.map b/@types/lib/metadataTypes/definitions/Automation.definition.d.ts.map new file mode 100644 index 000000000..0651d8713 --- /dev/null +++ b/@types/lib/metadataTypes/definitions/Automation.definition.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"Automation.definition.d.ts","sourceRoot":"","sources":["../../../../lib/metadataTypes/definitions/Automation.definition.js"],"names":[],"mappings":""} \ No newline at end of file diff --git a/@types/lib/metadataTypes/definitions/Campaign.definition.d.ts b/@types/lib/metadataTypes/definitions/Campaign.definition.d.ts new file mode 100644 index 000000000..d326740bb --- /dev/null +++ b/@types/lib/metadataTypes/definitions/Campaign.definition.d.ts @@ -0,0 +1,128 @@ +declare namespace _default { + let bodyIteratorField: string; + let dependencies: any[]; + let dependencyGraph: any; + let hasExtended: boolean; + let idField: string; + let keepId: boolean; + let keyIsFixed: boolean; + let keyField: string; + let nameField: string; + let createdDateField: string; + let createdNameField: any; + let lastmodDateField: string; + let lastmodNameField: any; + let restPagination: boolean; + let restPageSize: number; + let type: string; + let typeDescription: string; + let typeRetrieveByDefault: boolean; + let typeCdpByDefault: boolean; + let typeName: string; + let fields: { + id: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + campaignId: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + type: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + createdDate: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + createdBy: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + ownerId: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + lastUpdated: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + name: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + description: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + externalKey: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + campaignCode: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + 'display.name': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + 'display.value': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + isFavorite: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + campaignOwnerName: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + campaignOwner: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + campaignStatus: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + }; +} +export default _default; +//# sourceMappingURL=Campaign.definition.d.ts.map \ No newline at end of file diff --git a/@types/lib/metadataTypes/definitions/Campaign.definition.d.ts.map b/@types/lib/metadataTypes/definitions/Campaign.definition.d.ts.map new file mode 100644 index 000000000..b1bc1b5ff --- /dev/null +++ b/@types/lib/metadataTypes/definitions/Campaign.definition.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"Campaign.definition.d.ts","sourceRoot":"","sources":["../../../../lib/metadataTypes/definitions/Campaign.definition.js"],"names":[],"mappings":""} \ No newline at end of file diff --git a/@types/lib/metadataTypes/definitions/ContentArea.definition.d.ts b/@types/lib/metadataTypes/definitions/ContentArea.definition.d.ts new file mode 100644 index 000000000..87fd1cb88 --- /dev/null +++ b/@types/lib/metadataTypes/definitions/ContentArea.definition.d.ts @@ -0,0 +1,184 @@ +declare namespace _default { + let bodyIteratorField: string; + let dependencies: string[]; + let dependencyGraph: any; + let hasExtended: boolean; + let idField: string; + let keepId: boolean; + let keyIsFixed: boolean; + let keyField: string; + let nameField: string; + let folderIdField: string; + let restPagination: any; + let type: string; + let typeDescription: string; + let typeRetrieveByDefault: boolean; + let typeCdpByDefault: boolean; + let typeName: string; + let fields: { + BackgroundColor: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + BorderColor: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + BorderWidth: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + CategoryID: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + Cellpadding: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + Cellspacing: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + 'Client.ID': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + Content: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + CorrelationID: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + CreatedDate: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + CustomerKey: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + FontFamily: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + HasFontSize: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + ID: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + IsBlank: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + IsDynamicContent: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + IsLocked: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + IsSurvey: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + Key: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + Layout: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + ModifiedDate: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + Name: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + ObjectID: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + Owner: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + PartnerKey: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + PartnerProperties: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + Width: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + }; +} +export default _default; +//# sourceMappingURL=ContentArea.definition.d.ts.map \ No newline at end of file diff --git a/@types/lib/metadataTypes/definitions/ContentArea.definition.d.ts.map b/@types/lib/metadataTypes/definitions/ContentArea.definition.d.ts.map new file mode 100644 index 000000000..63874950b --- /dev/null +++ b/@types/lib/metadataTypes/definitions/ContentArea.definition.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"ContentArea.definition.d.ts","sourceRoot":"","sources":["../../../../lib/metadataTypes/definitions/ContentArea.definition.js"],"names":[],"mappings":""} \ No newline at end of file diff --git a/@types/lib/metadataTypes/definitions/DataExtension.definition.d.ts b/@types/lib/metadataTypes/definitions/DataExtension.definition.d.ts new file mode 100644 index 000000000..7e73680f2 --- /dev/null +++ b/@types/lib/metadataTypes/definitions/DataExtension.definition.d.ts @@ -0,0 +1,239 @@ +declare namespace _default { + let bodyIteratorField: string; + let dependencies: string[]; + let dependencyGraph: any; + let folderType: string; + namespace filter { + let CustomerKey: string[]; + let Name: string[]; + } + let templateFields: { + AudienceBuilderResult: string[]; + CONTEXTUAL_SUPPRESSION_LISTS: string[]; + DomainExclusion: string[]; + 'Event DE Template': string[]; + PushSendLog: string[]; + SendLog: string[]; + 'SmartCapture - Contacts Template Extension': string[]; + SmsSendLog: string[]; + SMSMessageTracking: any; + SMSSubscriptionLog: any; + TriggeredSendDataExtension: string[]; + }; + namespace dataRetentionPeriodUnitOfMeasureMapping { + let Days: number; + let Weeks: number; + let Months: number; + let Years: number; + } + let hasExtended: boolean; + let idField: string; + let keyIsFixed: boolean; + let keyField: string; + let nameField: string; + let folderIdField: string; + let createdDateField: string; + let createdNameField: any; + let lastmodDateField: string; + let lastmodNameField: any; + let restPagination: boolean; + let maxKeyLength: number; + let type: string; + let typeDescription: string; + let typeRetrieveByDefault: boolean; + let typeCdpByDefault: boolean; + let typeName: string; + let fields: { + CategoryID: { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: boolean; + }; + 'Client.ID': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + CreatedDate: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + CustomerKey: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + DataRetentionPeriod: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + DataRetentionPeriodLength: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + DataRetentionPeriodUnitOfMeasure: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + DeleteAtEndOfRetentionPeriod: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + Description: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + Fields: { + skipValidation: boolean; + }; + folderContentType: { + skipValidation: boolean; + }; + IsPlatformObject: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + IsSendable: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + IsTestable: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + ModifiedDate: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + Name: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + ObjectID: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + PartnerKey: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + ResetRetentionPeriodOnImport: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + RetainUntil: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + RowBasedRetention: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'SendableDataExtensionField.Name': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'SendableDataExtensionField.ObjectID': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'SendableDataExtensionField.PartnerKey': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + SendableSubscriberField: { + skipValidation: boolean; + }; + 'SendableSubscriberField.Name': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + Status: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'Template.CustomerKey': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'Template.ObjectID': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'Template.PartnerKey': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + r__folder_ContentType: { + skipValidation: boolean; + }; + r__folder_Path: { + skipValidation: boolean; + }; + r__dataExtensionTemplate_name: { + skipValidation: boolean; + }; + c__retentionPolicy: { + skipValidation: boolean; + }; + c__retainUntil: { + skipValidation: boolean; + }; + c__dataRetentionPeriodUnitOfMeasure: { + skipValidation: boolean; + }; + }; +} +export default _default; +//# sourceMappingURL=DataExtension.definition.d.ts.map \ No newline at end of file diff --git a/@types/lib/metadataTypes/definitions/DataExtension.definition.d.ts.map b/@types/lib/metadataTypes/definitions/DataExtension.definition.d.ts.map new file mode 100644 index 000000000..1ed66312c --- /dev/null +++ b/@types/lib/metadataTypes/definitions/DataExtension.definition.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"DataExtension.definition.d.ts","sourceRoot":"","sources":["../../../../lib/metadataTypes/definitions/DataExtension.definition.js"],"names":[],"mappings":""} \ No newline at end of file diff --git a/@types/lib/metadataTypes/definitions/DataExtensionField.definition.d.ts b/@types/lib/metadataTypes/definitions/DataExtensionField.definition.d.ts new file mode 100644 index 000000000..be1d66fde --- /dev/null +++ b/@types/lib/metadataTypes/definitions/DataExtensionField.definition.d.ts @@ -0,0 +1,124 @@ +declare namespace _default { + let bodyIteratorField: string; + let dependencies: string[]; + let dependencyGraph: any; + let filter: {}; + let hasExtended: boolean; + let idField: string; + let keyIsFixed: boolean; + let keyField: string; + let nameField: string; + let restPagination: boolean; + let type: string; + let typeDescription: string; + let typeRetrieveByDefault: boolean; + let typeCdpByDefault: boolean; + let typeName: string; + let deleteSynchronously: boolean; + let fields: { + 'Client.ID': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + CreatedDate: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + CustomerKey: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'DataExtension.CustomerKey': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'DataExtension.PartnerKey': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'DataExtension.ObjectID': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + DefaultValue: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + FieldType: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + IsPrimaryKey: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + IsRequired: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + MaxLength: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + ModifiedDate: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + Name: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + ObjectID: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + Ordinal: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + PartnerKey: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + Scale: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + }; +} +export default _default; +//# sourceMappingURL=DataExtensionField.definition.d.ts.map \ No newline at end of file diff --git a/@types/lib/metadataTypes/definitions/DataExtensionField.definition.d.ts.map b/@types/lib/metadataTypes/definitions/DataExtensionField.definition.d.ts.map new file mode 100644 index 000000000..2a063ffae --- /dev/null +++ b/@types/lib/metadataTypes/definitions/DataExtensionField.definition.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"DataExtensionField.definition.d.ts","sourceRoot":"","sources":["../../../../lib/metadataTypes/definitions/DataExtensionField.definition.js"],"names":[],"mappings":""} \ No newline at end of file diff --git a/@types/lib/metadataTypes/definitions/DataExtensionTemplate.definition.d.ts b/@types/lib/metadataTypes/definitions/DataExtensionTemplate.definition.d.ts new file mode 100644 index 000000000..f611e6a25 --- /dev/null +++ b/@types/lib/metadataTypes/definitions/DataExtensionTemplate.definition.d.ts @@ -0,0 +1,135 @@ +declare namespace _default { + let bodyIteratorField: string; + let dependencies: any[]; + let dependencyGraph: any; + let filter: {}; + let hasExtended: boolean; + let idField: string; + let keyIsFixed: boolean; + let keyField: string; + let nameField: string; + let restPagination: boolean; + let type: string; + let typeDescription: string; + let typeRetrieveByDefault: boolean; + let typeCdpByDefault: boolean; + let typeName: string; + let fields: { + 'Client.ID': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + CreatedDate: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + ModifiedDate: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + CustomerKey: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + ObjectID: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + Name: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + Description: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + PartnerKey: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + PartnerProperties: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + IsSendable: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + IsTestable: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + SendableCustomObjectField: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + SendableSubscriberField: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + DataRetentionPeriodLength: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + DataRetentionPeriodUnitOfMeasure: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + RowBasedRetention: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + ResetRetentionPeriodOnImport: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + DeleteAtEndOfRetentionPeriod: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + RetainUntil: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + }; +} +export default _default; +//# sourceMappingURL=DataExtensionTemplate.definition.d.ts.map \ No newline at end of file diff --git a/@types/lib/metadataTypes/definitions/DataExtensionTemplate.definition.d.ts.map b/@types/lib/metadataTypes/definitions/DataExtensionTemplate.definition.d.ts.map new file mode 100644 index 000000000..250fb5823 --- /dev/null +++ b/@types/lib/metadataTypes/definitions/DataExtensionTemplate.definition.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"DataExtensionTemplate.definition.d.ts","sourceRoot":"","sources":["../../../../lib/metadataTypes/definitions/DataExtensionTemplate.definition.js"],"names":[],"mappings":""} \ No newline at end of file diff --git a/@types/lib/metadataTypes/definitions/DataExtract.definition.d.ts b/@types/lib/metadataTypes/definitions/DataExtract.definition.d.ts new file mode 100644 index 000000000..8617e2b69 --- /dev/null +++ b/@types/lib/metadataTypes/definitions/DataExtract.definition.d.ts @@ -0,0 +1,176 @@ +declare namespace _default { + let bodyIteratorField: string; + let dependencies: string[]; + namespace dependencyGraph { + let dataExtension: string[]; + } + let hasExtended: boolean; + let idField: string; + let keyIsFixed: boolean; + let keyField: string; + let createdDateField: string; + let createdNameField: string; + let lastmodDateField: string; + let lastmodNameField: string; + let nameField: string; + let restPagination: boolean; + let maxKeyLength: number; + let type: string; + let typeDescription: string; + let typeRetrieveByDefault: boolean; + let typeCdpByDefault: boolean; + let typeName: string; + namespace fields { + namespace createdBy { + let isCreateable: boolean; + let isUpdateable: boolean; + let retrieving: boolean; + let template: boolean; + } + namespace createdDate { + let isCreateable_1: boolean; + export { isCreateable_1 as isCreateable }; + let isUpdateable_1: boolean; + export { isUpdateable_1 as isUpdateable }; + let retrieving_1: boolean; + export { retrieving_1 as retrieving }; + let template_1: boolean; + export { template_1 as template }; + } + namespace dataExtractDefinitionId { + let isCreateable_2: boolean; + export { isCreateable_2 as isCreateable }; + let isUpdateable_2: boolean; + export { isUpdateable_2 as isUpdateable }; + let retrieving_2: boolean; + export { retrieving_2 as retrieving }; + let template_2: boolean; + export { template_2 as template }; + } + namespace dataExtractTypeId { + let isCreateable_3: boolean; + export { isCreateable_3 as isCreateable }; + let isUpdateable_3: boolean; + export { isUpdateable_3 as isUpdateable }; + let retrieving_3: boolean; + export { retrieving_3 as retrieving }; + let template_3: boolean; + export { template_3 as template }; + } + namespace dataFields { + let skipValidation: boolean; + } + namespace description { + let isCreateable_4: boolean; + export { isCreateable_4 as isCreateable }; + let isUpdateable_4: boolean; + export { isUpdateable_4 as isUpdateable }; + let retrieving_4: boolean; + export { retrieving_4 as retrieving }; + let template_4: boolean; + export { template_4 as template }; + } + namespace endDate { + let isCreateable_5: boolean; + export { isCreateable_5 as isCreateable }; + let isUpdateable_5: boolean; + export { isUpdateable_5 as isUpdateable }; + let retrieving_5: boolean; + export { retrieving_5 as retrieving }; + let template_5: boolean; + export { template_5 as template }; + } + namespace fileSpec { + let isCreateable_6: boolean; + export { isCreateable_6 as isCreateable }; + let isUpdateable_6: boolean; + export { isUpdateable_6 as isUpdateable }; + let retrieving_6: boolean; + export { retrieving_6 as retrieving }; + let template_6: boolean; + export { template_6 as template }; + } + namespace intervalType { + let isCreateable_7: boolean; + export { isCreateable_7 as isCreateable }; + let isUpdateable_7: boolean; + export { isUpdateable_7 as isUpdateable }; + let retrieving_7: boolean; + export { retrieving_7 as retrieving }; + let template_7: boolean; + export { template_7 as template }; + } + namespace key { + let isCreateable_8: boolean; + export { isCreateable_8 as isCreateable }; + let isUpdateable_8: boolean; + export { isUpdateable_8 as isUpdateable }; + let retrieving_8: boolean; + export { retrieving_8 as retrieving }; + let template_8: boolean; + export { template_8 as template }; + } + namespace modifiedBy { + let isCreateable_9: boolean; + export { isCreateable_9 as isCreateable }; + let isUpdateable_9: boolean; + export { isUpdateable_9 as isUpdateable }; + let retrieving_9: boolean; + export { retrieving_9 as retrieving }; + let template_9: boolean; + export { template_9 as template }; + } + namespace modifiedDate { + let isCreateable_10: boolean; + export { isCreateable_10 as isCreateable }; + let isUpdateable_10: boolean; + export { isUpdateable_10 as isUpdateable }; + let retrieving_10: boolean; + export { retrieving_10 as retrieving }; + let template_10: boolean; + export { template_10 as template }; + } + namespace name { + let isCreateable_11: boolean; + export { isCreateable_11 as isCreateable }; + let isUpdateable_11: boolean; + export { isUpdateable_11 as isUpdateable }; + let retrieving_11: boolean; + export { retrieving_11 as retrieving }; + let template_11: boolean; + export { template_11 as template }; + } + namespace startDate { + let isCreateable_12: boolean; + export { isCreateable_12 as isCreateable }; + let isUpdateable_12: boolean; + export { isUpdateable_12 as isUpdateable }; + let retrieving_12: boolean; + export { retrieving_12 as retrieving }; + let template_12: boolean; + export { template_12 as template }; + } + namespace r__dataExtractType_name { + let isCreateable_13: boolean; + export { isCreateable_13 as isCreateable }; + let isUpdateable_13: boolean; + export { isUpdateable_13 as isUpdateable }; + let retrieving_13: boolean; + export { retrieving_13 as retrieving }; + let template_13: boolean; + export { template_13 as template }; + } + namespace r__dataExtension_key { + let isCreateable_14: boolean; + export { isCreateable_14 as isCreateable }; + let isUpdateable_14: boolean; + export { isUpdateable_14 as isUpdateable }; + let retrieving_14: boolean; + export { retrieving_14 as retrieving }; + let template_14: boolean; + export { template_14 as template }; + } + } +} +export default _default; +//# sourceMappingURL=DataExtract.definition.d.ts.map \ No newline at end of file diff --git a/@types/lib/metadataTypes/definitions/DataExtract.definition.d.ts.map b/@types/lib/metadataTypes/definitions/DataExtract.definition.d.ts.map new file mode 100644 index 000000000..043d14425 --- /dev/null +++ b/@types/lib/metadataTypes/definitions/DataExtract.definition.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"DataExtract.definition.d.ts","sourceRoot":"","sources":["../../../../lib/metadataTypes/definitions/DataExtract.definition.js"],"names":[],"mappings":""} \ No newline at end of file diff --git a/@types/lib/metadataTypes/definitions/DataExtractType.definition.d.ts b/@types/lib/metadataTypes/definitions/DataExtractType.definition.d.ts new file mode 100644 index 000000000..a27e05a8f --- /dev/null +++ b/@types/lib/metadataTypes/definitions/DataExtractType.definition.d.ts @@ -0,0 +1,36 @@ +declare namespace _default { + let bodyIteratorField: string; + let dependencies: any[]; + let dependencyGraph: any; + let hasExtended: boolean; + let idField: string; + let keyIsFixed: boolean; + let keyField: string; + let nameField: string; + let restPagination: boolean; + let type: string; + let typeDescription: string; + let typeRetrieveByDefault: boolean; + let typeCdpByDefault: boolean; + let typeName: string; + namespace fields { + namespace name { + let isCreateable: boolean; + let isUpdateable: boolean; + let retrieving: boolean; + let template: boolean; + } + namespace extractId { + let isCreateable_1: boolean; + export { isCreateable_1 as isCreateable }; + let isUpdateable_1: boolean; + export { isUpdateable_1 as isUpdateable }; + let retrieving_1: boolean; + export { retrieving_1 as retrieving }; + let template_1: boolean; + export { template_1 as template }; + } + } +} +export default _default; +//# sourceMappingURL=DataExtractType.definition.d.ts.map \ No newline at end of file diff --git a/@types/lib/metadataTypes/definitions/DataExtractType.definition.d.ts.map b/@types/lib/metadataTypes/definitions/DataExtractType.definition.d.ts.map new file mode 100644 index 000000000..12479160a --- /dev/null +++ b/@types/lib/metadataTypes/definitions/DataExtractType.definition.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"DataExtractType.definition.d.ts","sourceRoot":"","sources":["../../../../lib/metadataTypes/definitions/DataExtractType.definition.js"],"names":[],"mappings":""} \ No newline at end of file diff --git a/@types/lib/metadataTypes/definitions/DataFilter.definition.d.ts b/@types/lib/metadataTypes/definitions/DataFilter.definition.d.ts new file mode 100644 index 000000000..1ee20521b --- /dev/null +++ b/@types/lib/metadataTypes/definitions/DataFilter.definition.d.ts @@ -0,0 +1,231 @@ +declare namespace _default { + let bodyIteratorField: string; + let dependencies: string[]; + namespace dependencyGraph { + let dataExtension: string[]; + } + let filter: {}; + let hasExtended: boolean; + let idField: string; + let keyIsFixed: boolean; + let keyField: string; + let nameField: string; + let folderType: string; + let folderIdField: string; + let createdDateField: string; + let createdNameField: string; + let lastmodDateField: string; + let lastmodNameField: string; + let restPagination: boolean; + let restPageSize: number; + let maxKeyLength: number; + let type: string; + let soapType: string; + let typeDescription: string; + let typeRetrieveByDefault: boolean; + let typeCdpByDefault: boolean; + let typeName: string; + namespace fields { + namespace id { + let isCreateable: boolean; + let isUpdateable: boolean; + let retrieving: boolean; + let template: boolean; + } + namespace key { + let isCreateable_1: boolean; + export { isCreateable_1 as isCreateable }; + let isUpdateable_1: boolean; + export { isUpdateable_1 as isUpdateable }; + let retrieving_1: boolean; + export { retrieving_1 as retrieving }; + let template_1: boolean; + export { template_1 as template }; + } + namespace createdDate { + let isCreateable_2: boolean; + export { isCreateable_2 as isCreateable }; + let isUpdateable_2: boolean; + export { isUpdateable_2 as isUpdateable }; + let retrieving_2: boolean; + export { retrieving_2 as retrieving }; + let template_2: boolean; + export { template_2 as template }; + } + namespace createdBy { + let isCreateable_3: boolean; + export { isCreateable_3 as isCreateable }; + let isUpdateable_3: boolean; + export { isUpdateable_3 as isUpdateable }; + let retrieving_3: boolean; + export { retrieving_3 as retrieving }; + let template_3: boolean; + export { template_3 as template }; + } + namespace owner { + let isCreateable_4: boolean; + export { isCreateable_4 as isCreateable }; + let isUpdateable_4: boolean; + export { isUpdateable_4 as isUpdateable }; + let retrieving_4: boolean; + export { retrieving_4 as retrieving }; + let template_4: boolean; + export { template_4 as template }; + } + namespace createdByName { + let isCreateable_5: boolean; + export { isCreateable_5 as isCreateable }; + let isUpdateable_5: boolean; + export { isUpdateable_5 as isUpdateable }; + let retrieving_5: boolean; + export { retrieving_5 as retrieving }; + let template_5: boolean; + export { template_5 as template }; + } + namespace lastUpdated { + let isCreateable_6: boolean; + export { isCreateable_6 as isCreateable }; + let isUpdateable_6: boolean; + export { isUpdateable_6 as isUpdateable }; + let retrieving_6: boolean; + export { retrieving_6 as retrieving }; + let template_6: boolean; + export { template_6 as template }; + } + namespace lastUpdatedBy { + let isCreateable_7: boolean; + export { isCreateable_7 as isCreateable }; + let isUpdateable_7: boolean; + export { isUpdateable_7 as isUpdateable }; + let retrieving_7: boolean; + export { retrieving_7 as retrieving }; + let template_7: boolean; + export { template_7 as template }; + } + namespace lastUpdatedByName { + let isCreateable_8: boolean; + export { isCreateable_8 as isCreateable }; + let isUpdateable_8: boolean; + export { isUpdateable_8 as isUpdateable }; + let retrieving_8: boolean; + export { retrieving_8 as retrieving }; + let template_8: boolean; + export { template_8 as template }; + } + namespace name { + let isCreateable_9: boolean; + export { isCreateable_9 as isCreateable }; + let isUpdateable_9: boolean; + export { isUpdateable_9 as isUpdateable }; + let retrieving_9: boolean; + export { retrieving_9 as retrieving }; + let template_9: boolean; + export { template_9 as template }; + } + namespace categoryId { + let isCreateable_10: boolean; + export { isCreateable_10 as isCreateable }; + let isUpdateable_10: boolean; + export { isUpdateable_10 as isUpdateable }; + let retrieving_10: boolean; + export { retrieving_10 as retrieving }; + let template_10: boolean; + export { template_10 as template }; + } + namespace description { + let isCreateable_11: boolean; + export { isCreateable_11 as isCreateable }; + let isUpdateable_11: boolean; + export { isUpdateable_11 as isUpdateable }; + let retrieving_11: boolean; + export { retrieving_11 as retrieving }; + let template_11: boolean; + export { template_11 as template }; + } + namespace filterDefinitionXml { + let isCreateable_12: boolean; + export { isCreateable_12 as isCreateable }; + let isUpdateable_12: boolean; + export { isUpdateable_12 as isUpdateable }; + let retrieving_12: boolean; + export { retrieving_12 as retrieving }; + let template_12: boolean; + export { template_12 as template }; + } + namespace derivedFromType { + let isCreateable_13: boolean; + export { isCreateable_13 as isCreateable }; + let isUpdateable_13: boolean; + export { isUpdateable_13 as isUpdateable }; + let retrieving_13: boolean; + export { retrieving_13 as retrieving }; + let template_13: boolean; + export { template_13 as template }; + } + namespace derivedFromObjectId { + let isCreateable_14: boolean; + export { isCreateable_14 as isCreateable }; + let isUpdateable_14: boolean; + export { isUpdateable_14 as isUpdateable }; + let retrieving_14: boolean; + export { retrieving_14 as retrieving }; + let template_14: boolean; + export { template_14 as template }; + } + namespace derivedFromObjectTypeName { + let isCreateable_15: boolean; + export { isCreateable_15 as isCreateable }; + let isUpdateable_15: boolean; + export { isUpdateable_15 as isUpdateable }; + let retrieving_15: boolean; + export { retrieving_15 as retrieving }; + let template_15: boolean; + export { template_15 as template }; + } + namespace derivedFromObjectName { + let isCreateable_16: boolean; + export { isCreateable_16 as isCreateable }; + let isUpdateable_16: boolean; + export { isUpdateable_16 as isUpdateable }; + let retrieving_16: boolean; + export { retrieving_16 as retrieving }; + let template_16: boolean; + export { template_16 as template }; + } + namespace isSendable { + let isCreateable_17: boolean; + export { isCreateable_17 as isCreateable }; + let isUpdateable_17: boolean; + export { isUpdateable_17 as isUpdateable }; + let retrieving_17: boolean; + export { retrieving_17 as retrieving }; + let template_17: boolean; + export { template_17 as template }; + } + namespace r__source_dataExtension_key { + let isCreateable_18: boolean; + export { isCreateable_18 as isCreateable }; + let isUpdateable_18: boolean; + export { isUpdateable_18 as isUpdateable }; + let retrieving_18: boolean; + export { retrieving_18 as retrieving }; + let template_18: boolean; + export { template_18 as template }; + } + namespace c__filterDefinition { + let skipValidation: boolean; + } + namespace r__folder_Path { + let isCreateable_19: boolean; + export { isCreateable_19 as isCreateable }; + let isUpdateable_19: boolean; + export { isUpdateable_19 as isUpdateable }; + let retrieving_19: boolean; + export { retrieving_19 as retrieving }; + let template_19: boolean; + export { template_19 as template }; + } + } +} +export default _default; +//# sourceMappingURL=DataFilter.definition.d.ts.map \ No newline at end of file diff --git a/@types/lib/metadataTypes/definitions/DataFilter.definition.d.ts.map b/@types/lib/metadataTypes/definitions/DataFilter.definition.d.ts.map new file mode 100644 index 000000000..06b36c8be --- /dev/null +++ b/@types/lib/metadataTypes/definitions/DataFilter.definition.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"DataFilter.definition.d.ts","sourceRoot":"","sources":["../../../../lib/metadataTypes/definitions/DataFilter.definition.js"],"names":[],"mappings":""} \ No newline at end of file diff --git a/@types/lib/metadataTypes/definitions/DataFilterHidden.definition.d.ts b/@types/lib/metadataTypes/definitions/DataFilterHidden.definition.d.ts new file mode 100644 index 000000000..2c97ca4c9 --- /dev/null +++ b/@types/lib/metadataTypes/definitions/DataFilterHidden.definition.d.ts @@ -0,0 +1,231 @@ +declare namespace _default { + let bodyIteratorField: string; + let dependencies: string[]; + namespace dependencyGraph { + let dataExtension: string[]; + } + let filter: {}; + let hasExtended: boolean; + let idField: string; + let keyIsFixed: boolean; + let keyField: string; + let nameField: string; + let folderType: string; + let folderIdField: string; + let createdDateField: string; + let createdNameField: string; + let lastmodDateField: string; + let lastmodNameField: string; + let restPagination: boolean; + let restPageSize: number; + let maxKeyLength: number; + let type: string; + let soapType: string; + let typeDescription: string; + let typeRetrieveByDefault: boolean; + let typeCdpByDefault: boolean; + let typeName: string; + namespace fields { + namespace id { + let isCreateable: boolean; + let isUpdateable: boolean; + let retrieving: boolean; + let template: boolean; + } + namespace key { + let isCreateable_1: boolean; + export { isCreateable_1 as isCreateable }; + let isUpdateable_1: boolean; + export { isUpdateable_1 as isUpdateable }; + let retrieving_1: boolean; + export { retrieving_1 as retrieving }; + let template_1: boolean; + export { template_1 as template }; + } + namespace createdDate { + let isCreateable_2: boolean; + export { isCreateable_2 as isCreateable }; + let isUpdateable_2: boolean; + export { isUpdateable_2 as isUpdateable }; + let retrieving_2: boolean; + export { retrieving_2 as retrieving }; + let template_2: boolean; + export { template_2 as template }; + } + namespace createdBy { + let isCreateable_3: boolean; + export { isCreateable_3 as isCreateable }; + let isUpdateable_3: boolean; + export { isUpdateable_3 as isUpdateable }; + let retrieving_3: boolean; + export { retrieving_3 as retrieving }; + let template_3: boolean; + export { template_3 as template }; + } + namespace owner { + let isCreateable_4: boolean; + export { isCreateable_4 as isCreateable }; + let isUpdateable_4: boolean; + export { isUpdateable_4 as isUpdateable }; + let retrieving_4: boolean; + export { retrieving_4 as retrieving }; + let template_4: boolean; + export { template_4 as template }; + } + namespace createdByName { + let isCreateable_5: boolean; + export { isCreateable_5 as isCreateable }; + let isUpdateable_5: boolean; + export { isUpdateable_5 as isUpdateable }; + let retrieving_5: boolean; + export { retrieving_5 as retrieving }; + let template_5: boolean; + export { template_5 as template }; + } + namespace lastUpdated { + let isCreateable_6: boolean; + export { isCreateable_6 as isCreateable }; + let isUpdateable_6: boolean; + export { isUpdateable_6 as isUpdateable }; + let retrieving_6: boolean; + export { retrieving_6 as retrieving }; + let template_6: boolean; + export { template_6 as template }; + } + namespace lastUpdatedBy { + let isCreateable_7: boolean; + export { isCreateable_7 as isCreateable }; + let isUpdateable_7: boolean; + export { isUpdateable_7 as isUpdateable }; + let retrieving_7: boolean; + export { retrieving_7 as retrieving }; + let template_7: boolean; + export { template_7 as template }; + } + namespace lastUpdatedByName { + let isCreateable_8: boolean; + export { isCreateable_8 as isCreateable }; + let isUpdateable_8: boolean; + export { isUpdateable_8 as isUpdateable }; + let retrieving_8: boolean; + export { retrieving_8 as retrieving }; + let template_8: boolean; + export { template_8 as template }; + } + namespace name { + let isCreateable_9: boolean; + export { isCreateable_9 as isCreateable }; + let isUpdateable_9: boolean; + export { isUpdateable_9 as isUpdateable }; + let retrieving_9: boolean; + export { retrieving_9 as retrieving }; + let template_9: boolean; + export { template_9 as template }; + } + namespace categoryId { + let isCreateable_10: boolean; + export { isCreateable_10 as isCreateable }; + let isUpdateable_10: boolean; + export { isUpdateable_10 as isUpdateable }; + let retrieving_10: boolean; + export { retrieving_10 as retrieving }; + let template_10: boolean; + export { template_10 as template }; + } + namespace description { + let isCreateable_11: boolean; + export { isCreateable_11 as isCreateable }; + let isUpdateable_11: boolean; + export { isUpdateable_11 as isUpdateable }; + let retrieving_11: boolean; + export { retrieving_11 as retrieving }; + let template_11: boolean; + export { template_11 as template }; + } + namespace filterDefinitionXml { + let isCreateable_12: boolean; + export { isCreateable_12 as isCreateable }; + let isUpdateable_12: boolean; + export { isUpdateable_12 as isUpdateable }; + let retrieving_12: boolean; + export { retrieving_12 as retrieving }; + let template_12: boolean; + export { template_12 as template }; + } + namespace derivedFromType { + let isCreateable_13: boolean; + export { isCreateable_13 as isCreateable }; + let isUpdateable_13: boolean; + export { isUpdateable_13 as isUpdateable }; + let retrieving_13: boolean; + export { retrieving_13 as retrieving }; + let template_13: boolean; + export { template_13 as template }; + } + namespace derivedFromObjectId { + let isCreateable_14: boolean; + export { isCreateable_14 as isCreateable }; + let isUpdateable_14: boolean; + export { isUpdateable_14 as isUpdateable }; + let retrieving_14: boolean; + export { retrieving_14 as retrieving }; + let template_14: boolean; + export { template_14 as template }; + } + namespace derivedFromObjectTypeName { + let isCreateable_15: boolean; + export { isCreateable_15 as isCreateable }; + let isUpdateable_15: boolean; + export { isUpdateable_15 as isUpdateable }; + let retrieving_15: boolean; + export { retrieving_15 as retrieving }; + let template_15: boolean; + export { template_15 as template }; + } + namespace derivedFromObjectName { + let isCreateable_16: boolean; + export { isCreateable_16 as isCreateable }; + let isUpdateable_16: boolean; + export { isUpdateable_16 as isUpdateable }; + let retrieving_16: boolean; + export { retrieving_16 as retrieving }; + let template_16: boolean; + export { template_16 as template }; + } + namespace isSendable { + let isCreateable_17: boolean; + export { isCreateable_17 as isCreateable }; + let isUpdateable_17: boolean; + export { isUpdateable_17 as isUpdateable }; + let retrieving_17: boolean; + export { retrieving_17 as retrieving }; + let template_17: boolean; + export { template_17 as template }; + } + namespace r__source_dataExtension_key { + let isCreateable_18: boolean; + export { isCreateable_18 as isCreateable }; + let isUpdateable_18: boolean; + export { isUpdateable_18 as isUpdateable }; + let retrieving_18: boolean; + export { retrieving_18 as retrieving }; + let template_18: boolean; + export { template_18 as template }; + } + namespace c__filterDefinition { + let skipValidation: boolean; + } + namespace r__folder_Path { + let isCreateable_19: boolean; + export { isCreateable_19 as isCreateable }; + let isUpdateable_19: boolean; + export { isUpdateable_19 as isUpdateable }; + let retrieving_19: boolean; + export { retrieving_19 as retrieving }; + let template_19: boolean; + export { template_19 as template }; + } + } +} +export default _default; +//# sourceMappingURL=DataFilterHidden.definition.d.ts.map \ No newline at end of file diff --git a/@types/lib/metadataTypes/definitions/DataFilterHidden.definition.d.ts.map b/@types/lib/metadataTypes/definitions/DataFilterHidden.definition.d.ts.map new file mode 100644 index 000000000..8ce82e85c --- /dev/null +++ b/@types/lib/metadataTypes/definitions/DataFilterHidden.definition.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"DataFilterHidden.definition.d.ts","sourceRoot":"","sources":["../../../../lib/metadataTypes/definitions/DataFilterHidden.definition.js"],"names":[],"mappings":""} \ No newline at end of file diff --git a/@types/lib/metadataTypes/definitions/DeliveryProfile.definition.d.ts b/@types/lib/metadataTypes/definitions/DeliveryProfile.definition.d.ts new file mode 100644 index 000000000..fc131d681 --- /dev/null +++ b/@types/lib/metadataTypes/definitions/DeliveryProfile.definition.d.ts @@ -0,0 +1,82 @@ +declare namespace _default { + let bodyIteratorField: string; + let dependencies: any[]; + let dependencyGraph: any; + let filter: {}; + let hasExtended: boolean; + let idField: string; + let keyField: string; + let keyIsFixed: boolean; + let maxKeyLength: number; + let nameField: string; + let createdDateField: string; + let createdNameField: any; + let lastmodDateField: string; + let lastmodNameField: any; + let restPagination: boolean; + let type: string; + let typeDescription: string; + let typeRetrieveByDefault: boolean; + let typeCdpByDefault: boolean; + let typeName: string; + namespace fields { + namespace id { + let isCreateable: boolean; + let isUpdateable: boolean; + let retrieving: boolean; + let template: boolean; + } + namespace key { + let isCreateable_1: boolean; + export { isCreateable_1 as isCreateable }; + let isUpdateable_1: boolean; + export { isUpdateable_1 as isUpdateable }; + let retrieving_1: boolean; + export { retrieving_1 as retrieving }; + let template_1: boolean; + export { template_1 as template }; + } + namespace name { + let isCreateable_2: boolean; + export { isCreateable_2 as isCreateable }; + let isUpdateable_2: boolean; + export { isUpdateable_2 as isUpdateable }; + let retrieving_2: boolean; + export { retrieving_2 as retrieving }; + let template_2: boolean; + export { template_2 as template }; + } + namespace description { + let isCreateable_3: boolean; + export { isCreateable_3 as isCreateable }; + let isUpdateable_3: boolean; + export { isUpdateable_3 as isUpdateable }; + let retrieving_3: boolean; + export { retrieving_3 as retrieving }; + let template_3: boolean; + export { template_3 as template }; + } + namespace createdDate { + let isCreateable_4: boolean; + export { isCreateable_4 as isCreateable }; + let isUpdateable_4: boolean; + export { isUpdateable_4 as isUpdateable }; + let retrieving_4: boolean; + export { retrieving_4 as retrieving }; + let template_4: boolean; + export { template_4 as template }; + } + namespace lastUpdated { + let isCreateable_5: boolean; + export { isCreateable_5 as isCreateable }; + let isUpdateable_5: boolean; + export { isUpdateable_5 as isUpdateable }; + let retrieving_5: boolean; + export { retrieving_5 as retrieving }; + let template_5: boolean; + export { template_5 as template }; + } + } +} +export default _default; +//# sourceMappingURL=DeliveryProfile.definition.d.ts.map \ No newline at end of file diff --git a/@types/lib/metadataTypes/definitions/DeliveryProfile.definition.d.ts.map b/@types/lib/metadataTypes/definitions/DeliveryProfile.definition.d.ts.map new file mode 100644 index 000000000..191378906 --- /dev/null +++ b/@types/lib/metadataTypes/definitions/DeliveryProfile.definition.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"DeliveryProfile.definition.d.ts","sourceRoot":"","sources":["../../../../lib/metadataTypes/definitions/DeliveryProfile.definition.js"],"names":[],"mappings":""} \ No newline at end of file diff --git a/@types/lib/metadataTypes/definitions/Discovery.definition.d.ts b/@types/lib/metadataTypes/definitions/Discovery.definition.d.ts new file mode 100644 index 000000000..2e3dbacfc --- /dev/null +++ b/@types/lib/metadataTypes/definitions/Discovery.definition.d.ts @@ -0,0 +1,148 @@ +declare namespace _default { + let bodyIteratorField: any; + let dependencies: any[]; + let dependencyGraph: any; + let endPointMapping: { + Address: string; + Asset: string; + Automation: string; + Contacts: string; + Data: string; + Device: string; + Email: string; + Guide: string; + Hub: string; + Interaction: string; + 'Interaction-Experimental': string; + Legacy: string; + Messaging: string; + 'Messaging-Experimental': string; + OTT: string; + 'OTT-Experimental': string; + Platform: string; + 'Platform-Experimental': string; + Provisioning: string; + Push: string; + SMS: string; + }; + let hasExtended: boolean; + let idField: string; + let keyIsFixed: boolean; + let keyField: string; + let nameField: string; + let restPagination: boolean; + let type: string; + let typeDescription: string; + let typeRetrieveByDefault: boolean; + let typeCdpByDefault: boolean; + let typeName: string; + let fields: { + basePath: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + baseUrl: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + description: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + discoveryVersion: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + documentationLink: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + id: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + key: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + kind: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + methods: { + skipValidation: boolean; + }; + metadata: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'metadata.supportsResponseEncoding': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + name: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + protocol: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + resources: { + skipValidation: boolean; + }; + rootUrl: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + schemas: { + skipValidation: boolean; + }; + servicePath: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + title: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + version: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + }; +} +export default _default; +//# sourceMappingURL=Discovery.definition.d.ts.map \ No newline at end of file diff --git a/@types/lib/metadataTypes/definitions/Discovery.definition.d.ts.map b/@types/lib/metadataTypes/definitions/Discovery.definition.d.ts.map new file mode 100644 index 000000000..3ad189934 --- /dev/null +++ b/@types/lib/metadataTypes/definitions/Discovery.definition.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"Discovery.definition.d.ts","sourceRoot":"","sources":["../../../../lib/metadataTypes/definitions/Discovery.definition.js"],"names":[],"mappings":""} \ No newline at end of file diff --git a/@types/lib/metadataTypes/definitions/DomainVerification.definition.d.ts b/@types/lib/metadataTypes/definitions/DomainVerification.definition.d.ts new file mode 100644 index 000000000..0914afa5d --- /dev/null +++ b/@types/lib/metadataTypes/definitions/DomainVerification.definition.d.ts @@ -0,0 +1,101 @@ +declare namespace _default { + let bodyIteratorField: string; + let dependencies: any[]; + let dependencyGraph: any; + let hasExtended: boolean; + let idField: string; + let keyIsFixed: boolean; + let keyField: string; + let createdDateField: any; + let createdNameField: any; + let lastmodDateField: any; + let lastmodNameField: any; + let nameField: string; + let restPagination: boolean; + let maxKeyLength: number; + let type: string; + let typeDescription: string; + let typeRetrieveByDefault: boolean; + let typeCdpByDefault: boolean; + let typeName: string; + namespace fields { + namespace domain { + let isCreateable: boolean; + let isUpdateable: boolean; + let retrieving: boolean; + let template: boolean; + } + namespace emailAddress { + let isCreateable_1: boolean; + export { isCreateable_1 as isCreateable }; + let isUpdateable_1: boolean; + export { isUpdateable_1 as isUpdateable }; + let retrieving_1: boolean; + export { retrieving_1 as retrieving }; + let template_1: boolean; + export { template_1 as template }; + } + namespace enterpriseId { + let isCreateable_2: boolean; + export { isCreateable_2 as isCreateable }; + let isUpdateable_2: boolean; + export { isUpdateable_2 as isUpdateable }; + let retrieving_2: boolean; + export { retrieving_2 as retrieving }; + let template_2: boolean; + export { template_2 as template }; + } + namespace memberId { + let isCreateable_3: boolean; + export { isCreateable_3 as isCreateable }; + let isUpdateable_3: boolean; + export { isUpdateable_3 as isUpdateable }; + let retrieving_3: boolean; + export { retrieving_3 as retrieving }; + let template_3: boolean; + export { template_3 as template }; + } + namespace domainType { + let isCreateable_4: boolean; + export { isCreateable_4 as isCreateable }; + let isUpdateable_4: boolean; + export { isUpdateable_4 as isUpdateable }; + let retrieving_4: boolean; + export { retrieving_4 as retrieving }; + let template_4: boolean; + export { template_4 as template }; + } + namespace isSendable { + let isCreateable_5: boolean; + export { isCreateable_5 as isCreateable }; + let isUpdateable_5: boolean; + export { isUpdateable_5 as isUpdateable }; + let retrieving_5: boolean; + export { retrieving_5 as retrieving }; + let template_5: boolean; + export { template_5 as template }; + } + namespace status { + let isCreateable_6: boolean; + export { isCreateable_6 as isCreateable }; + let isUpdateable_6: boolean; + export { isUpdateable_6 as isUpdateable }; + let retrieving_6: boolean; + export { retrieving_6 as retrieving }; + let template_6: boolean; + export { template_6 as template }; + } + namespace emailSendTime { + let isCreateable_7: boolean; + export { isCreateable_7 as isCreateable }; + let isUpdateable_7: boolean; + export { isUpdateable_7 as isUpdateable }; + let retrieving_7: boolean; + export { retrieving_7 as retrieving }; + let template_7: boolean; + export { template_7 as template }; + } + } +} +export default _default; +//# sourceMappingURL=DomainVerification.definition.d.ts.map \ No newline at end of file diff --git a/@types/lib/metadataTypes/definitions/DomainVerification.definition.d.ts.map b/@types/lib/metadataTypes/definitions/DomainVerification.definition.d.ts.map new file mode 100644 index 000000000..4a7b2e2a5 --- /dev/null +++ b/@types/lib/metadataTypes/definitions/DomainVerification.definition.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"DomainVerification.definition.d.ts","sourceRoot":"","sources":["../../../../lib/metadataTypes/definitions/DomainVerification.definition.js"],"names":[],"mappings":""} \ No newline at end of file diff --git a/@types/lib/metadataTypes/definitions/Email.definition.d.ts b/@types/lib/metadataTypes/definitions/Email.definition.d.ts new file mode 100644 index 000000000..d805ce4c1 --- /dev/null +++ b/@types/lib/metadataTypes/definitions/Email.definition.d.ts @@ -0,0 +1,316 @@ +declare namespace _default { + let bodyIteratorField: string; + let dependencies: string[]; + let dependencyGraph: any; + let hasExtended: boolean; + let idField: string; + let keepId: boolean; + let keyIsFixed: boolean; + let keyField: string; + let nameField: string; + let folderIdField: string; + let restPagination: any; + let type: string; + let typeDescription: string; + let typeRetrieveByDefault: boolean; + let typeCdpByDefault: boolean; + let typeName: string; + let fields: { + CategoryID: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + CharacterSet: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + 'Client.ID': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + 'Client.PartnerClientKey': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + ClonedFromID: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + ContentAreas: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + 'ContentAreas.CategoryID': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + 'ContentAreas.Content': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + 'ContentAreas.CustomerKey': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + 'ContentAreas.ID': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + 'ContentAreas.IsBlank': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + 'ContentAreas.IsDynamicContent': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + 'ContentAreas.IsLocked': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + 'ContentAreas.IsSurvey': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + 'ContentAreas.Key': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + 'ContentAreas.Name': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + 'ContentAreas.ObjectID': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + 'ContentAreas.PartnerKey': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + 'ContentAreas[].CategoryID': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + 'ContentAreas[].Content': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + 'ContentAreas[].CustomerKey': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + 'ContentAreas[].ID': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + 'ContentAreas[].IsBlank': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + 'ContentAreas[].IsDynamicContent': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + 'ContentAreas[].IsLocked': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + 'ContentAreas[].IsSurvey': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + 'ContentAreas[].Key': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + 'ContentAreas[].Name': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + 'ContentAreas[].ObjectID': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + 'ContentAreas[].PartnerKey': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + ContentCheckStatus: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + CreatedDate: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + CustomerKey: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + EmailType: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + Folder: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + HasDynamicSubjectLine: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + HTMLBody: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + ID: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + IsActive: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + IsHTMLPaste: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + ModifiedDate: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + Name: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + ObjectID: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + PartnerKey: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + PreHeader: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + Status: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + Subject: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + SyncTextWithHTML: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + TextBody: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + }; +} +export default _default; +//# sourceMappingURL=Email.definition.d.ts.map \ No newline at end of file diff --git a/@types/lib/metadataTypes/definitions/Email.definition.d.ts.map b/@types/lib/metadataTypes/definitions/Email.definition.d.ts.map new file mode 100644 index 000000000..3fe666023 --- /dev/null +++ b/@types/lib/metadataTypes/definitions/Email.definition.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"Email.definition.d.ts","sourceRoot":"","sources":["../../../../lib/metadataTypes/definitions/Email.definition.js"],"names":[],"mappings":""} \ No newline at end of file diff --git a/@types/lib/metadataTypes/definitions/EmailSend.definition.d.ts b/@types/lib/metadataTypes/definitions/EmailSend.definition.d.ts new file mode 100644 index 000000000..94d1798ed --- /dev/null +++ b/@types/lib/metadataTypes/definitions/EmailSend.definition.d.ts @@ -0,0 +1,591 @@ +declare namespace _default { + let bodyIteratorField: string; + let dependencies: string[]; + namespace dependencyGraph { + let asset: string[]; + let dataExtension: string[]; + let deliveryProfile: string[]; + let list: string[]; + let sendClassification: string[]; + let senderProfile: string[]; + } + let folderType: string; + let hasExtended: boolean; + let idField: string; + let keepId: boolean; + let keyIsFixed: boolean; + let keyField: string; + let nameField: string; + let folderIdField: string; + let createdDateField: string; + let createdNameField: any; + let lastmodDateField: string; + let lastmodNameField: any; + let restPagination: any; + let maxKeyLength: number; + let type: string; + let soapType: string; + let typeDescription: string; + let typeRetrieveByDefault: boolean; + let typeCdpByDefault: boolean; + let typeName: string; + let fields: { + Additional: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + AutoBccEmail: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + BccEmail: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + CategoryID: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + CCEmail: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + 'Client.ID': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + CorrelationID: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + CreatedDate: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + CustomerKey: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + DeduplicateByEmail: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + 'DeliveryProfile.CustomerKey': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + 'DeliveryProfile.DomainType': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + 'DeliveryProfile.FooterContentArea.ID': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + 'DeliveryProfile.FooterSalutationSource': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + 'DeliveryProfile.HeaderContentArea.ID': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + 'DeliveryProfile.HeaderSalutationSource': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + 'DeliveryProfile.ObjectID': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + 'DeliveryProfile.PartnerKey': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + 'DeliveryProfile.PrivateDomain': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + 'DeliveryProfile.PrivateIP': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + 'DeliveryProfile.SourceAddressType': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + DeliveryScheduledTime: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + Description: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + DomainType: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + DynamicEmailSubject: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + 'Email.ID': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + 'Email.ObjectID': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + 'Email.PartnerKey': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + 'Email.Name': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + 'Email.Subject': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + 'Email.Status': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + EmailSubject: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + ExclusionFilter: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + FooterContentArea: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + FooterSalutationSource: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + FromAddress: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + FromName: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + HeaderContentArea: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + HeaderSalutationSource: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + ID: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + IntegratedTracking: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + InteractionObjectID: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + IsMultipart: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + IsPlatformObject: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + IsSeedListSend: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + IsSendLogging: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + IsWrapped: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + Keyword: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + MessageDeliveryType: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + ModifiedDate: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + Name: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + ObjectID: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + ObjectState: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + Owner: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + PartnerKey: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + PartnerProperties: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + PreHeader: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + PrivateDomain: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + PrivateIP: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + ReplyToAddress: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + ReplyToDisplayName: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + SeedListOccurance: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + 'SendClassification.CustomerKey': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + 'SendClassification.ObjectID': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + 'SendClassification.PartnerKey': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + 'SendDefinitionList.CustomObjectID': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + SendDefinitionList: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + 'SendDefinitionList[].ObjectID': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + 'SendDefinitionList[].PartnerKey': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + 'SendDefinitionList[].CustomObjectID': { + skipValidation: boolean; + }; + 'SendDefinitionList[].SendDefinitionListType': { + skipValidation: boolean; + }; + 'SendDefinitionList[].DataSourceTypeID': { + skipValidation: boolean; + }; + 'SendDefinitionList[].IsTestObject': { + skipValidation: boolean; + }; + 'SendDefinitionList[].SalesForceObjectID': { + skipValidation: boolean; + }; + 'SendDefinitionList[].Name': { + skipValidation: boolean; + }; + 'SendDefinitionList[].r__dataExtension_key': { + skipValidation: boolean; + }; + 'SendDefinitionList[].List.ObjectID': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + 'SendDefinitionList[].List.PartnerKey': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + 'SendDefinitionList[].r__list_PathName': { + skipValidation: boolean; + }; + 'SenderProfile.CustomerKey': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + 'SenderProfile.FromAddress': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + 'SenderProfile.FromName': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + 'SenderProfile.ObjectID': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + 'SenderProfile.PartnerKey': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + SendLimit: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + SendWindowClose: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + SendWindowDelete: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + SendWindowOpen: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + SourceAddressType: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + SuppressTracking: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + TestEmailAddr: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + TimeZone: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + TrackingUsers: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + r__asset_name_readOnly: { + skipValidation: boolean; + }; + r__asset_key: { + skipValidation: boolean; + }; + r__email_name: { + skipValidation: boolean; + }; + r__folder_Path: { + skipValidation: boolean; + }; + r__senderProfile_key: { + skipValidation: boolean; + }; + r__sendClassification_key: { + skipValidation: boolean; + }; + r__deliveryProfile_key: { + skipValidation: boolean; + }; + }; +} +export default _default; +//# sourceMappingURL=EmailSend.definition.d.ts.map \ No newline at end of file diff --git a/@types/lib/metadataTypes/definitions/EmailSend.definition.d.ts.map b/@types/lib/metadataTypes/definitions/EmailSend.definition.d.ts.map new file mode 100644 index 000000000..f5e9718d2 --- /dev/null +++ b/@types/lib/metadataTypes/definitions/EmailSend.definition.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"EmailSend.definition.d.ts","sourceRoot":"","sources":["../../../../lib/metadataTypes/definitions/EmailSend.definition.js"],"names":[],"mappings":""} \ No newline at end of file diff --git a/@types/lib/metadataTypes/definitions/Event.definition.d.ts b/@types/lib/metadataTypes/definitions/Event.definition.d.ts new file mode 100644 index 000000000..bac512fdc --- /dev/null +++ b/@types/lib/metadataTypes/definitions/Event.definition.d.ts @@ -0,0 +1,1028 @@ +declare namespace _default { + let bodyIteratorField: string; + let dependencies: string[]; + namespace dependencyGraph { + let automation: string[]; + let dataExtension: string[]; + } + let hasExtended: boolean; + let idField: string; + let keyIsFixed: boolean; + let keyField: string; + let nameField: string; + let createdDateField: string; + let createdNameField: string; + let lastmodDateField: string; + let lastmodNameField: string; + let restPagination: boolean; + let maxKeyLength: number; + let type: string; + let typeDescription: string; + let typeRetrieveByDefault: boolean; + let typeCdpByDefault: boolean; + let typeName: string; + let validTypes: string[]; + let fields: { + 'arguments.audienceCount': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'arguments.audienceDefinitionID': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'arguments.audienceDescription': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'arguments.audienceSource': { + skipValidation: boolean; + }; + 'arguments.audienceName': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'arguments.automationId': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'arguments.buildAudienceDefinitionID': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'arguments.contactAttributeGroup': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'arguments.contactAttributeId': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'arguments.contactAttributeName': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'arguments.criteria': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'arguments.dataExtensionId': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'arguments.dataTargetName': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'arguments.formName': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'arguments.dateOffset': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'arguments.dateOffsetUnit': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'arguments.dateType': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'arguments.eid': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'arguments.eventDefinitionId': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'arguments.eventDefinitionKey': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'arguments.mid': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'arguments.resetHighWatermark': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'arguments.serializedObjectType': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'arguments.transactionKeyDataExtension': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'arguments.transactionKeyEvent': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'arguments.useHighWatermark': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + automationId: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + category: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + configurationArguments: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'configurationArguments.applicationExtensionKey': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'configurationArguments.contactKey': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'configurationArguments.contactKey.relationshipIdName': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'configurationArguments.contactKey.relationshipName': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'configurationArguments.contactKey.isPolymorphic': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'configurationArguments.contactKey.referenceObjectName': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'configurationArguments.contactPersonType': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'configurationArguments.dataExtensionId': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'configurationArguments.evaluationCriteriaSummary': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'configurationArguments.eventDataConfig': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'configurationArguments.eventDataConfig.objects': { + skipValidation: boolean; + }; + 'configurationArguments.eventDataSummary': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'configurationArguments.objectAPIName': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'configurationArguments.passThroughArgument': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'configurationArguments.passThroughArgument.fields': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'configurationArguments.passThroughArgument.fields.ContactKey': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'configurationArguments.passThroughArgument.fields.Email': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'configurationArguments.primaryObjectFilterCriteria': { + skipValidation: boolean; + }; + 'configurationArguments.primaryObjectFilterSummary': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'configurationArguments.relatedObjectFilterCriteria': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'configurationArguments.relatedObjectFilterSummary': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'configurationArguments.salesforceTriggerCriteria': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'configurationArguments.unconfigured': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'configurationArguments.version': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'configurationArguments.whoToInject': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + createdBy: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + createdDate: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + dataExtensionId: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + dataExtensionName: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + description: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + disableDEDataLogging: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + eventDefinitionKey: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + filterDefinitionId: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + filterDefinitionTemplate: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + iconUrl: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + id: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + interactionCount: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + isPlatformObject: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + isVisibleInPicker: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'metaData.attributeName': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'metaData.automationData.automationType': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'metaData.automationData.categoryId': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'metaData.automationData.createdBy.email': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'metaData.automationData.createdBy.id': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'metaData.automationData.createdBy.name': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'metaData.automationData.createdDate': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'metaData.automationData.description': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'metaData.automationData.folderPath': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'metaData.automationData.guidId': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'metaData.automationData.id': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'metaData.automationData.isPlatformObject': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'metaData.automationData.key': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'metaData.automationData.lastRunInstance': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'metaData.automationData.lastRunTime': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'metaData.automationData.lastSaveDate': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'metaData.automationData.lastSavedBy.email': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'metaData.automationData.lastSavedBy.id': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'metaData.automationData.lastSavedBy.name': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'metaData.automationData.memberId': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'metaData.automationData.modifiedDate': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'metaData.automationData.name': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'metaData.automationData.notifications': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'metaData.automationData.processes': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'metaData.automationData.schedule': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'metaData.automationData.scheduleObject.createdBy': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'metaData.automationData.scheduleObject.createdDate': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'metaData.automationData.scheduleObject.description': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'metaData.automationData.scheduleObject.iCalRecur': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'metaData.automationData.scheduleObject.id': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'metaData.automationData.scheduleObject.key': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'metaData.automationData.scheduleObject.lastUpdated': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'metaData.automationData.scheduleObject.lastUpdatedBy': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'metaData.automationData.scheduleObject.name': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'metaData.automationData.scheduleObject.scheduleState': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'metaData.automationData.scheduleObject.scheduleStatus': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'metaData.automationData.scheduleObject.startDate': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'metaData.automationData.scheduleObject.timeZone': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'metaData.automationData.scheduleObject.timeZoneId': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'metaData.automationData.scheduledTime': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'metaData.automationData.selectedCategoryId': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'metaData.automationData.selectedCategoryId[]': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'metaData.automationData.status': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'metaData.automationData.updateInProgress': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'metaData.criteriaDescription': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'metaData.customAttributeName': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'metaData.formattedDate': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'metaData.formattedTime': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'metaData.icon': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'metaData.original_icon': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'metaData.isConfigured': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'metaData.runOnceScheduleMode': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'metaData.scheduleFlowMode': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'metaData.scheduleState': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'metaData.timeZone': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'metaData.transactionKeys': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'metaData.transactionKeys.0': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'metaData.transactionKeys.0.from': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'metaData.transactionKeys.0.to': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + mode: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + modifiedBy: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + modifiedDate: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + name: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + publishedInteractionCount: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'schedule.scheduledDayOfWeek': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'schedule.scheduledWeek': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'schedule.endDateTime': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'schedule.endType': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'schedule.frequency': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'schedule.interval': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'schedule.occurrences': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'schedule.recurrencePattern': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'schedule.scheduledDay': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'schedule.startDateTime': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'schedule.timeZone': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'schedule.monday': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'schedule.tuesday': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'schedule.wednesday': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'schedule.thursday': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'schedule.friday': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'schedule.saturday': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'schedule.sunday': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'schema.fields': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'schema.fields[].dataType': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'schema.fields[].defaultValue': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'schema.fields[].isDevicePreference': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'schema.fields[].isNullable': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'schema.fields[].isPrimaryKey': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'schema.fields[].maxLength': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'schema.fields[].name': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'schema.id': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'schema.name': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'schema.sendableCustomObjectField': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'schema.sendableSubscriberField': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'schema.isPlatformObject': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + sourceApplicationExtensionId: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + entrySourceGroupConfigUrl: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + type: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + r__dataExtension_key: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + r__automation_key: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + }; +} +export default _default; +//# sourceMappingURL=Event.definition.d.ts.map \ No newline at end of file diff --git a/@types/lib/metadataTypes/definitions/Event.definition.d.ts.map b/@types/lib/metadataTypes/definitions/Event.definition.d.ts.map new file mode 100644 index 000000000..5e575ee49 --- /dev/null +++ b/@types/lib/metadataTypes/definitions/Event.definition.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"Event.definition.d.ts","sourceRoot":"","sources":["../../../../lib/metadataTypes/definitions/Event.definition.js"],"names":[],"mappings":""} \ No newline at end of file diff --git a/@types/lib/metadataTypes/definitions/FileLocation.definition.d.ts b/@types/lib/metadataTypes/definitions/FileLocation.definition.d.ts new file mode 100644 index 000000000..0b32c6dfa --- /dev/null +++ b/@types/lib/metadataTypes/definitions/FileLocation.definition.d.ts @@ -0,0 +1,152 @@ +declare namespace _default { + let bodyIteratorField: string; + let dependencies: any[]; + let dependencyGraph: any; + let hasExtended: boolean; + let idField: string; + let keyIsFixed: boolean; + let keyField: string; + let nameField: string; + let createdDateField: any; + let createdNameField: any; + let lastmodDateField: any; + let lastmodNameField: any; + let restPagination: boolean; + let maxKeyLength: number; + let type: string; + let typeDescription: string; + let typeRetrieveByDefault: boolean; + let typeCdpByDefault: boolean; + let typeName: string; + let locationTypeMapping: { + 'Enhanced FTP Site Import Directory': number; + 'External FTP Site': number; + 'External SFTP Site': number; + 'External FTPS Site': number; + 'Salesforce Objects and Reports': number; + Safehouse: number; + 'Enhanced FTP Site Export Directory': number; + 'Legacy Import Directory': number; + 'Relative location under FTP Site': number; + 'Amazon Simple Storage Service': number; + 'Azure Blob Storage': number; + 'Google Cloud Storage': number; + }; + let locationTypeMappingDeployable: { + 'External SFTP Site': string; + 'Amazon Simple Storage Service': string; + 'Azure Blob Storage': string; + 'Google Cloud Storage': string; + }; + let locationTypeIdMappingDeployable: { + 2: string; + 13: string; + 15: string; + 16: string; + }; + namespace fields { + namespace id { + let isCreateable: boolean; + let isUpdateable: boolean; + let retrieving: boolean; + let template: boolean; + } + namespace locationTypeId { + let isCreateable_1: boolean; + export { isCreateable_1 as isCreateable }; + let isUpdateable_1: boolean; + export { isUpdateable_1 as isUpdateable }; + let retrieving_1: boolean; + export { retrieving_1 as retrieving }; + let template_1: boolean; + export { template_1 as template }; + } + namespace locationType { + let isCreateable_2: boolean; + export { isCreateable_2 as isCreateable }; + let isUpdateable_2: boolean; + export { isUpdateable_2 as isUpdateable }; + let retrieving_2: boolean; + export { retrieving_2 as retrieving }; + let template_2: boolean; + export { template_2 as template }; + } + namespace locationUrl { + let isCreateable_3: boolean; + export { isCreateable_3 as isCreateable }; + let isUpdateable_3: boolean; + export { isUpdateable_3 as isUpdateable }; + let retrieving_3: boolean; + export { retrieving_3 as retrieving }; + let template_3: boolean; + export { template_3 as template }; + } + namespace name { + let isCreateable_4: boolean; + export { isCreateable_4 as isCreateable }; + let isUpdateable_4: boolean; + export { isUpdateable_4 as isUpdateable }; + let retrieving_4: boolean; + export { retrieving_4 as retrieving }; + let template_4: boolean; + export { template_4 as template }; + } + namespace customerKey { + let isCreateable_5: boolean; + export { isCreateable_5 as isCreateable }; + let isUpdateable_5: boolean; + export { isUpdateable_5 as isUpdateable }; + let retrieving_5: boolean; + export { retrieving_5 as retrieving }; + let template_5: boolean; + export { template_5 as template }; + } + namespace description { + let isCreateable_6: boolean; + export { isCreateable_6 as isCreateable }; + let isUpdateable_6: boolean; + export { isUpdateable_6 as isUpdateable }; + let retrieving_6: boolean; + export { retrieving_6 as retrieving }; + let template_6: boolean; + export { template_6 as template }; + } + namespace relPath { + let isCreateable_7: boolean; + export { isCreateable_7 as isCreateable }; + let isUpdateable_7: boolean; + export { isUpdateable_7 as isUpdateable }; + let retrieving_7: boolean; + export { retrieving_7 as retrieving }; + let template_7: boolean; + export { template_7 as template }; + } + namespace awsFileTransferLocation { + let skipValidation: boolean; + } + namespace azureFileTransferLocation { + let skipValidation_1: boolean; + export { skipValidation_1 as skipValidation }; + } + namespace gcpFileTransferLocation { + let skipValidation_2: boolean; + export { skipValidation_2 as skipValidation }; + } + namespace sFtpFileTransferLocation { + let skipValidation_3: boolean; + export { skipValidation_3 as skipValidation }; + } + namespace c__locationType { + let isCreateable_8: boolean; + export { isCreateable_8 as isCreateable }; + let isUpdateable_8: boolean; + export { isUpdateable_8 as isUpdateable }; + let retrieving_8: boolean; + export { retrieving_8 as retrieving }; + let template_8: boolean; + export { template_8 as template }; + } + } +} +export default _default; +//# sourceMappingURL=FileLocation.definition.d.ts.map \ No newline at end of file diff --git a/@types/lib/metadataTypes/definitions/FileLocation.definition.d.ts.map b/@types/lib/metadataTypes/definitions/FileLocation.definition.d.ts.map new file mode 100644 index 000000000..0500b8650 --- /dev/null +++ b/@types/lib/metadataTypes/definitions/FileLocation.definition.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"FileLocation.definition.d.ts","sourceRoot":"","sources":["../../../../lib/metadataTypes/definitions/FileLocation.definition.js"],"names":[],"mappings":""} \ No newline at end of file diff --git a/@types/lib/metadataTypes/definitions/FileTransfer.definition.d.ts b/@types/lib/metadataTypes/definitions/FileTransfer.definition.d.ts new file mode 100644 index 000000000..f5e8ce6a8 --- /dev/null +++ b/@types/lib/metadataTypes/definitions/FileTransfer.definition.d.ts @@ -0,0 +1,193 @@ +declare namespace _default { + let bodyIteratorField: string; + let dependencies: string[]; + let dependencyGraph: {}; + let hasExtended: boolean; + let idField: string; + let keyIsFixed: boolean; + let keyField: string; + let nameField: string; + let createdDateField: string; + let createdNameField: any; + let lastmodDateField: string; + let lastmodNameField: any; + let restPagination: boolean; + let type: string; + let typeDescription: string; + let typeRetrieveByDefault: boolean; + let typeCdpByDefault: boolean; + let typeName: string; + namespace fields { + namespace createdDate { + let isCreateable: boolean; + let isUpdateable: boolean; + let retrieving: boolean; + let template: boolean; + } + namespace customerKey { + let isCreateable_1: boolean; + export { isCreateable_1 as isCreateable }; + let isUpdateable_1: boolean; + export { isUpdateable_1 as isUpdateable }; + let retrieving_1: boolean; + export { retrieving_1 as retrieving }; + let template_1: boolean; + export { template_1 as template }; + } + namespace description { + let isCreateable_2: boolean; + export { isCreateable_2 as isCreateable }; + let isUpdateable_2: boolean; + export { isUpdateable_2 as isUpdateable }; + let retrieving_2: boolean; + export { retrieving_2 as retrieving }; + let template_2: boolean; + export { template_2 as template }; + } + namespace fileSpec { + let isCreateable_3: boolean; + export { isCreateable_3 as isCreateable }; + let isUpdateable_3: boolean; + export { isUpdateable_3 as isUpdateable }; + let retrieving_3: boolean; + export { retrieving_3 as retrieving }; + let template_3: boolean; + export { template_3 as template }; + } + namespace fileTransferLocationId { + let isCreateable_4: boolean; + export { isCreateable_4 as isCreateable }; + let isUpdateable_4: boolean; + export { isUpdateable_4 as isUpdateable }; + let retrieving_4: boolean; + export { retrieving_4 as retrieving }; + let template_4: boolean; + export { template_4 as template }; + } + namespace id { + let isCreateable_5: boolean; + export { isCreateable_5 as isCreateable }; + let isUpdateable_5: boolean; + export { isUpdateable_5 as isUpdateable }; + let retrieving_5: boolean; + export { retrieving_5 as retrieving }; + let template_5: boolean; + export { template_5 as template }; + } + namespace isCompressed { + let isCreateable_6: boolean; + export { isCreateable_6 as isCreateable }; + let isUpdateable_6: boolean; + export { isUpdateable_6 as isUpdateable }; + let retrieving_6: boolean; + export { retrieving_6 as retrieving }; + let template_6: boolean; + export { template_6 as template }; + } + namespace isEncrypted { + let isCreateable_7: boolean; + export { isCreateable_7 as isCreateable }; + let isUpdateable_7: boolean; + export { isUpdateable_7 as isUpdateable }; + let retrieving_7: boolean; + export { retrieving_7 as retrieving }; + let template_7: boolean; + export { template_7 as template }; + } + namespace isFileSpecLocalized { + let isCreateable_8: boolean; + export { isCreateable_8 as isCreateable }; + let isUpdateable_8: boolean; + export { isUpdateable_8 as isUpdateable }; + let retrieving_8: boolean; + export { retrieving_8 as retrieving }; + let template_8: boolean; + export { template_8 as template }; + } + namespace isPgp { + let isCreateable_9: boolean; + export { isCreateable_9 as isCreateable }; + let isUpdateable_9: boolean; + export { isUpdateable_9 as isUpdateable }; + let retrieving_9: boolean; + export { retrieving_9 as retrieving }; + let template_9: boolean; + export { template_9 as template }; + } + namespace isUpload { + let isCreateable_10: boolean; + export { isCreateable_10 as isCreateable }; + let isUpdateable_10: boolean; + export { isUpdateable_10 as isUpdateable }; + let retrieving_10: boolean; + export { retrieving_10 as retrieving }; + let template_10: boolean; + export { template_10 as template }; + } + namespace maxFileAge { + let isCreateable_11: boolean; + export { isCreateable_11 as isCreateable }; + let isUpdateable_11: boolean; + export { isUpdateable_11 as isUpdateable }; + let retrieving_11: boolean; + export { retrieving_11 as retrieving }; + let template_11: boolean; + export { template_11 as template }; + } + namespace maxFileAgeScheduleOffset { + let isCreateable_12: boolean; + export { isCreateable_12 as isCreateable }; + let isUpdateable_12: boolean; + export { isUpdateable_12 as isUpdateable }; + let retrieving_12: boolean; + export { retrieving_12 as retrieving }; + let template_12: boolean; + export { template_12 as template }; + } + namespace maxImportFrequency { + let isCreateable_13: boolean; + export { isCreateable_13 as isCreateable }; + let isUpdateable_13: boolean; + export { isUpdateable_13 as isUpdateable }; + let retrieving_13: boolean; + export { retrieving_13 as retrieving }; + let template_13: boolean; + export { template_13 as template }; + } + namespace modifiedDate { + let isCreateable_14: boolean; + export { isCreateable_14 as isCreateable }; + let isUpdateable_14: boolean; + export { isUpdateable_14 as isUpdateable }; + let retrieving_14: boolean; + export { retrieving_14 as retrieving }; + let template_14: boolean; + export { template_14 as template }; + } + namespace name { + let isCreateable_15: boolean; + export { isCreateable_15 as isCreateable }; + let isUpdateable_15: boolean; + export { isUpdateable_15 as isUpdateable }; + let retrieving_15: boolean; + export { retrieving_15 as retrieving }; + let template_15: boolean; + export { template_15 as template }; + } + namespace publicKeyManagementId { + let isCreateable_16: boolean; + export { isCreateable_16 as isCreateable }; + let isUpdateable_16: boolean; + export { isUpdateable_16 as isUpdateable }; + let retrieving_16: boolean; + export { retrieving_16 as retrieving }; + let template_16: boolean; + export { template_16 as template }; + } + namespace r__fileLocation_name { + let skipValidation: boolean; + } + } +} +export default _default; +//# sourceMappingURL=FileTransfer.definition.d.ts.map \ No newline at end of file diff --git a/@types/lib/metadataTypes/definitions/FileTransfer.definition.d.ts.map b/@types/lib/metadataTypes/definitions/FileTransfer.definition.d.ts.map new file mode 100644 index 000000000..b9254d252 --- /dev/null +++ b/@types/lib/metadataTypes/definitions/FileTransfer.definition.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"FileTransfer.definition.d.ts","sourceRoot":"","sources":["../../../../lib/metadataTypes/definitions/FileTransfer.definition.js"],"names":[],"mappings":""} \ No newline at end of file diff --git a/@types/lib/metadataTypes/definitions/Filter.definition.d.ts b/@types/lib/metadataTypes/definitions/Filter.definition.d.ts new file mode 100644 index 000000000..418557281 --- /dev/null +++ b/@types/lib/metadataTypes/definitions/Filter.definition.d.ts @@ -0,0 +1,321 @@ +declare namespace _default { + let bodyIteratorField: string; + let dependencies: string[]; + namespace dependencyGraph { + let filterDefinition: string[]; + let dataExtension: string[]; + } + let hasExtended: boolean; + let idField: string; + let keyIsFixed: boolean; + let keyField: string; + let nameField: string; + let folderType: string; + let folderIdField: string; + namespace filter { + let statusId: number; + } + let createdDateField: string; + let createdNameField: any; + let lastmodDateField: string; + let lastmodNameField: any; + let restPagination: boolean; + let maxKeyLength: number; + let type: string; + let soapType: string; + let typeDescription: string; + let typeRetrieveByDefault: boolean; + let typeCdpByDefault: boolean; + let typeName: string; + namespace fields { + export namespace categoryId { + let isCreateable: boolean; + let isUpdateable: boolean; + let retrieving: boolean; + let template: boolean; + } + export namespace createdDate { + let isCreateable_1: boolean; + export { isCreateable_1 as isCreateable }; + let isUpdateable_1: boolean; + export { isUpdateable_1 as isUpdateable }; + let retrieving_1: boolean; + export { retrieving_1 as retrieving }; + let template_1: boolean; + export { template_1 as template }; + } + export namespace customerKey { + let isCreateable_2: boolean; + export { isCreateable_2 as isCreateable }; + let isUpdateable_2: boolean; + export { isUpdateable_2 as isUpdateable }; + let retrieving_2: boolean; + export { retrieving_2 as retrieving }; + let template_2: boolean; + export { template_2 as template }; + } + export namespace CustomerKey { + let isCreateable_3: boolean; + export { isCreateable_3 as isCreateable }; + let isUpdateable_3: boolean; + export { isUpdateable_3 as isUpdateable }; + let retrieving_3: boolean; + export { retrieving_3 as retrieving }; + let template_3: boolean; + export { template_3 as template }; + } + export namespace description { + let isCreateable_4: boolean; + export { isCreateable_4 as isCreateable }; + let isUpdateable_4: boolean; + export { isUpdateable_4 as isUpdateable }; + let retrieving_4: boolean; + export { retrieving_4 as retrieving }; + let template_4: boolean; + export { template_4 as template }; + } + export namespace Description { + let isCreateable_5: boolean; + export { isCreateable_5 as isCreateable }; + let isUpdateable_5: boolean; + export { isUpdateable_5 as isUpdateable }; + let retrieving_5: boolean; + export { retrieving_5 as retrieving }; + let template_5: boolean; + export { template_5 as template }; + } + export namespace destinationObjectId { + let isCreateable_6: boolean; + export { isCreateable_6 as isCreateable }; + let isUpdateable_6: boolean; + export { isUpdateable_6 as isUpdateable }; + let retrieving_6: boolean; + export { retrieving_6 as retrieving }; + let template_6: boolean; + export { template_6 as template }; + } + export namespace DestinationObjectID { + let isCreateable_7: boolean; + export { isCreateable_7 as isCreateable }; + let isUpdateable_7: boolean; + export { isUpdateable_7 as isUpdateable }; + let retrieving_7: boolean; + export { retrieving_7 as retrieving }; + let template_7: boolean; + export { template_7 as template }; + } + export namespace destinationTypeId { + let isCreateable_8: boolean; + export { isCreateable_8 as isCreateable }; + let isUpdateable_8: boolean; + export { isUpdateable_8 as isUpdateable }; + let retrieving_8: boolean; + export { retrieving_8 as retrieving }; + let template_8: boolean; + export { template_8 as template }; + } + export namespace DestinationTypeID { + let isCreateable_9: boolean; + export { isCreateable_9 as isCreateable }; + let isUpdateable_9: boolean; + export { isUpdateable_9 as isUpdateable }; + let retrieving_9: boolean; + export { retrieving_9 as retrieving }; + let template_9: boolean; + export { template_9 as template }; + } + export namespace filterActivityId { + let isCreateable_10: boolean; + export { isCreateable_10 as isCreateable }; + let isUpdateable_10: boolean; + export { isUpdateable_10 as isUpdateable }; + let retrieving_10: boolean; + export { retrieving_10 as retrieving }; + let template_10: boolean; + export { template_10 as template }; + } + export namespace filterDefinitionId { + let isCreateable_11: boolean; + export { isCreateable_11 as isCreateable }; + let isUpdateable_11: boolean; + export { isUpdateable_11 as isUpdateable }; + let retrieving_11: boolean; + export { retrieving_11 as retrieving }; + let template_11: boolean; + export { template_11 as template }; + } + export namespace FilterDefinitionID { + let isCreateable_12: boolean; + export { isCreateable_12 as isCreateable }; + let isUpdateable_12: boolean; + export { isUpdateable_12 as isUpdateable }; + let retrieving_12: boolean; + export { retrieving_12 as retrieving }; + let template_12: boolean; + export { template_12 as template }; + } + export namespace modifiedDate { + let isCreateable_13: boolean; + export { isCreateable_13 as isCreateable }; + let isUpdateable_13: boolean; + export { isUpdateable_13 as isUpdateable }; + let retrieving_13: boolean; + export { retrieving_13 as retrieving }; + let template_13: boolean; + export { template_13 as template }; + } + export namespace name { + let isCreateable_14: boolean; + export { isCreateable_14 as isCreateable }; + let isUpdateable_14: boolean; + export { isUpdateable_14 as isUpdateable }; + let retrieving_14: boolean; + export { retrieving_14 as retrieving }; + let template_14: boolean; + export { template_14 as template }; + } + export namespace Name { + let isCreateable_15: boolean; + export { isCreateable_15 as isCreateable }; + let isUpdateable_15: boolean; + export { isUpdateable_15 as isUpdateable }; + let retrieving_15: boolean; + export { retrieving_15 as retrieving }; + let template_15: boolean; + export { template_15 as template }; + } + export namespace sourceObjectId { + let isCreateable_16: boolean; + export { isCreateable_16 as isCreateable }; + let isUpdateable_16: boolean; + export { isUpdateable_16 as isUpdateable }; + let retrieving_16: boolean; + export { retrieving_16 as retrieving }; + let template_16: boolean; + export { template_16 as template }; + } + export namespace SourceObjectID { + let isCreateable_17: boolean; + export { isCreateable_17 as isCreateable }; + let isUpdateable_17: boolean; + export { isUpdateable_17 as isUpdateable }; + let retrieving_17: boolean; + export { retrieving_17 as retrieving }; + let template_17: boolean; + export { template_17 as template }; + } + export namespace sourceTypeId { + let isCreateable_18: boolean; + export { isCreateable_18 as isCreateable }; + let isUpdateable_18: boolean; + export { isUpdateable_18 as isUpdateable }; + let retrieving_18: boolean; + export { retrieving_18 as retrieving }; + let template_18: boolean; + export { template_18 as template }; + } + export namespace SourceTypeID { + let isCreateable_19: boolean; + export { isCreateable_19 as isCreateable }; + let isUpdateable_19: boolean; + export { isUpdateable_19 as isUpdateable }; + let retrieving_19: boolean; + export { retrieving_19 as retrieving }; + let template_19: boolean; + export { template_19 as template }; + } + export namespace filterDefinitionSourceTypeId { + let isCreateable_20: boolean; + export { isCreateable_20 as isCreateable }; + let isUpdateable_20: boolean; + export { isUpdateable_20 as isUpdateable }; + let retrieving_20: boolean; + export { retrieving_20 as retrieving }; + let template_20: boolean; + export { template_20 as template }; + } + export namespace statusId_1 { + let isCreateable_21: boolean; + export { isCreateable_21 as isCreateable }; + let isUpdateable_21: boolean; + export { isUpdateable_21 as isUpdateable }; + let retrieving_21: boolean; + export { retrieving_21 as retrieving }; + let template_21: boolean; + export { template_21 as template }; + } + export { statusId_1 as statusId }; + export namespace resultDEName { + let isCreateable_22: boolean; + export { isCreateable_22 as isCreateable }; + let isUpdateable_22: boolean; + export { isUpdateable_22 as isUpdateable }; + let retrieving_22: boolean; + export { retrieving_22 as retrieving }; + let template_22: boolean; + export { template_22 as template }; + } + export namespace resultDEKey { + let isCreateable_23: boolean; + export { isCreateable_23 as isCreateable }; + let isUpdateable_23: boolean; + export { isUpdateable_23 as isUpdateable }; + let retrieving_23: boolean; + export { retrieving_23 as retrieving }; + let template_23: boolean; + export { template_23 as template }; + } + export namespace resultDEDescription { + let isCreateable_24: boolean; + export { isCreateable_24 as isCreateable }; + let isUpdateable_24: boolean; + export { isUpdateable_24 as isUpdateable }; + let retrieving_24: boolean; + export { retrieving_24 as retrieving }; + let template_24: boolean; + export { template_24 as template }; + } + export namespace r__folder_Path { + let isCreateable_25: boolean; + export { isCreateable_25 as isCreateable }; + let isUpdateable_25: boolean; + export { isUpdateable_25 as isUpdateable }; + let retrieving_25: boolean; + export { retrieving_25 as retrieving }; + let template_25: boolean; + export { template_25 as template }; + } + export namespace r__dataFilter_key { + let isCreateable_26: boolean; + export { isCreateable_26 as isCreateable }; + let isUpdateable_26: boolean; + export { isUpdateable_26 as isUpdateable }; + let retrieving_26: boolean; + export { retrieving_26 as retrieving }; + let template_26: boolean; + export { template_26 as template }; + } + export namespace r__source_dataExtension_key { + let isCreateable_27: boolean; + export { isCreateable_27 as isCreateable }; + let isUpdateable_27: boolean; + export { isUpdateable_27 as isUpdateable }; + let retrieving_27: boolean; + export { retrieving_27 as retrieving }; + let template_27: boolean; + export { template_27 as template }; + } + export namespace r__destination_dataExtension_key { + let isCreateable_28: boolean; + export { isCreateable_28 as isCreateable }; + let isUpdateable_28: boolean; + export { isUpdateable_28 as isUpdateable }; + let retrieving_28: boolean; + export { retrieving_28 as retrieving }; + let template_28: boolean; + export { template_28 as template }; + } + } +} +export default _default; +//# sourceMappingURL=Filter.definition.d.ts.map \ No newline at end of file diff --git a/@types/lib/metadataTypes/definitions/Filter.definition.d.ts.map b/@types/lib/metadataTypes/definitions/Filter.definition.d.ts.map new file mode 100644 index 000000000..4ec6a7e9f --- /dev/null +++ b/@types/lib/metadataTypes/definitions/Filter.definition.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"Filter.definition.d.ts","sourceRoot":"","sources":["../../../../lib/metadataTypes/definitions/Filter.definition.js"],"names":[],"mappings":""} \ No newline at end of file diff --git a/@types/lib/metadataTypes/definitions/FilterDefinition.definition.d.ts b/@types/lib/metadataTypes/definitions/FilterDefinition.definition.d.ts new file mode 100644 index 000000000..981d36d2b --- /dev/null +++ b/@types/lib/metadataTypes/definitions/FilterDefinition.definition.d.ts @@ -0,0 +1,218 @@ +declare namespace _default { + let bodyIteratorField: string; + let dependencies: string[]; + namespace dependencyGraph { + let dataExtension: string[]; + } + let filter: {}; + let hasExtended: boolean; + let idField: string; + let keyField: string; + let nameField: string; + let folderType: string; + let folderIdField: string; + let createdDateField: string; + let createdNameField: string; + let lastmodDateField: string; + let lastmodNameField: string; + let restPagination: boolean; + let restPageSize: number; + let type: string; + let soapType: string; + let typeDescription: string; + let typeRetrieveByDefault: boolean; + let typeName: string; + namespace fields { + namespace id { + let isCreateable: boolean; + let isUpdateable: boolean; + let retrieving: boolean; + let template: boolean; + } + namespace key { + let isCreateable_1: boolean; + export { isCreateable_1 as isCreateable }; + let isUpdateable_1: boolean; + export { isUpdateable_1 as isUpdateable }; + let retrieving_1: boolean; + export { retrieving_1 as retrieving }; + let template_1: boolean; + export { template_1 as template }; + } + namespace createdDate { + let isCreateable_2: boolean; + export { isCreateable_2 as isCreateable }; + let isUpdateable_2: boolean; + export { isUpdateable_2 as isUpdateable }; + let retrieving_2: boolean; + export { retrieving_2 as retrieving }; + let template_2: boolean; + export { template_2 as template }; + } + namespace createdBy { + let isCreateable_3: boolean; + export { isCreateable_3 as isCreateable }; + let isUpdateable_3: boolean; + export { isUpdateable_3 as isUpdateable }; + let retrieving_3: boolean; + export { retrieving_3 as retrieving }; + let template_3: boolean; + export { template_3 as template }; + } + namespace createdByName { + let isCreateable_4: boolean; + export { isCreateable_4 as isCreateable }; + let isUpdateable_4: boolean; + export { isUpdateable_4 as isUpdateable }; + let retrieving_4: boolean; + export { retrieving_4 as retrieving }; + let template_4: boolean; + export { template_4 as template }; + } + namespace lastUpdated { + let isCreateable_5: boolean; + export { isCreateable_5 as isCreateable }; + let isUpdateable_5: boolean; + export { isUpdateable_5 as isUpdateable }; + let retrieving_5: boolean; + export { retrieving_5 as retrieving }; + let template_5: boolean; + export { template_5 as template }; + } + namespace lastUpdatedBy { + let isCreateable_6: boolean; + export { isCreateable_6 as isCreateable }; + let isUpdateable_6: boolean; + export { isUpdateable_6 as isUpdateable }; + let retrieving_6: boolean; + export { retrieving_6 as retrieving }; + let template_6: boolean; + export { template_6 as template }; + } + namespace lastUpdatedByName { + let isCreateable_7: boolean; + export { isCreateable_7 as isCreateable }; + let isUpdateable_7: boolean; + export { isUpdateable_7 as isUpdateable }; + let retrieving_7: boolean; + export { retrieving_7 as retrieving }; + let template_7: boolean; + export { template_7 as template }; + } + namespace name { + let isCreateable_8: boolean; + export { isCreateable_8 as isCreateable }; + let isUpdateable_8: boolean; + export { isUpdateable_8 as isUpdateable }; + let retrieving_8: boolean; + export { retrieving_8 as retrieving }; + let template_8: boolean; + export { template_8 as template }; + } + namespace categoryId { + let isCreateable_9: boolean; + export { isCreateable_9 as isCreateable }; + let isUpdateable_9: boolean; + export { isUpdateable_9 as isUpdateable }; + let retrieving_9: boolean; + export { retrieving_9 as retrieving }; + let template_9: boolean; + export { template_9 as template }; + } + namespace description { + let isCreateable_10: boolean; + export { isCreateable_10 as isCreateable }; + let isUpdateable_10: boolean; + export { isUpdateable_10 as isUpdateable }; + let retrieving_10: boolean; + export { retrieving_10 as retrieving }; + let template_10: boolean; + export { template_10 as template }; + } + namespace filterDefinitionXml { + let isCreateable_11: boolean; + export { isCreateable_11 as isCreateable }; + let isUpdateable_11: boolean; + export { isUpdateable_11 as isUpdateable }; + let retrieving_11: boolean; + export { retrieving_11 as retrieving }; + let template_11: boolean; + export { template_11 as template }; + } + namespace derivedFromType { + let isCreateable_12: boolean; + export { isCreateable_12 as isCreateable }; + let isUpdateable_12: boolean; + export { isUpdateable_12 as isUpdateable }; + let retrieving_12: boolean; + export { retrieving_12 as retrieving }; + let template_12: boolean; + export { template_12 as template }; + } + namespace derivedFromObjectId { + let isCreateable_13: boolean; + export { isCreateable_13 as isCreateable }; + let isUpdateable_13: boolean; + export { isUpdateable_13 as isUpdateable }; + let retrieving_13: boolean; + export { retrieving_13 as retrieving }; + let template_13: boolean; + export { template_13 as template }; + } + namespace derivedFromObjectTypeName { + let isCreateable_14: boolean; + export { isCreateable_14 as isCreateable }; + let isUpdateable_14: boolean; + export { isUpdateable_14 as isUpdateable }; + let retrieving_14: boolean; + export { retrieving_14 as retrieving }; + let template_14: boolean; + export { template_14 as template }; + } + namespace derivedFromObjectName { + let isCreateable_15: boolean; + export { isCreateable_15 as isCreateable }; + let isUpdateable_15: boolean; + export { isUpdateable_15 as isUpdateable }; + let retrieving_15: boolean; + export { retrieving_15 as retrieving }; + let template_15: boolean; + export { template_15 as template }; + } + namespace isSendable { + let isCreateable_16: boolean; + export { isCreateable_16 as isCreateable }; + let isUpdateable_16: boolean; + export { isUpdateable_16 as isUpdateable }; + let retrieving_16: boolean; + export { retrieving_16 as retrieving }; + let template_16: boolean; + export { template_16 as template }; + } + namespace r__source_dataExtension_key { + let isCreateable_17: boolean; + export { isCreateable_17 as isCreateable }; + let isUpdateable_17: boolean; + export { isUpdateable_17 as isUpdateable }; + let retrieving_17: boolean; + export { retrieving_17 as retrieving }; + let template_17: boolean; + export { template_17 as template }; + } + namespace c__filterDefinition { + let skipValidation: boolean; + } + namespace r__folder_Path { + let isCreateable_18: boolean; + export { isCreateable_18 as isCreateable }; + let isUpdateable_18: boolean; + export { isUpdateable_18 as isUpdateable }; + let retrieving_18: boolean; + export { retrieving_18 as retrieving }; + let template_18: boolean; + export { template_18 as template }; + } + } +} +export default _default; +//# sourceMappingURL=FilterDefinition.definition.d.ts.map \ No newline at end of file diff --git a/@types/lib/metadataTypes/definitions/FilterDefinition.definition.d.ts.map b/@types/lib/metadataTypes/definitions/FilterDefinition.definition.d.ts.map new file mode 100644 index 000000000..3b02b98ad --- /dev/null +++ b/@types/lib/metadataTypes/definitions/FilterDefinition.definition.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"FilterDefinition.definition.d.ts","sourceRoot":"","sources":["../../../../lib/metadataTypes/definitions/FilterDefinition.definition.js"],"names":[],"mappings":""} \ No newline at end of file diff --git a/@types/lib/metadataTypes/definitions/FilterDefinitionHidden.definition.d.ts b/@types/lib/metadataTypes/definitions/FilterDefinitionHidden.definition.d.ts new file mode 100644 index 000000000..c3b5aec28 --- /dev/null +++ b/@types/lib/metadataTypes/definitions/FilterDefinitionHidden.definition.d.ts @@ -0,0 +1,218 @@ +declare namespace _default { + let bodyIteratorField: string; + let dependencies: string[]; + namespace dependencyGraph { + let dataExtension: string[]; + } + let filter: {}; + let hasExtended: boolean; + let idField: string; + let keyField: string; + let nameField: string; + let folderType: string; + let folderIdField: string; + let createdDateField: string; + let createdNameField: string; + let lastmodDateField: string; + let lastmodNameField: string; + let restPagination: boolean; + let restPageSize: number; + let type: string; + let soapType: string; + let typeDescription: string; + let typeRetrieveByDefault: boolean; + let typeName: string; + namespace fields { + namespace id { + let isCreateable: boolean; + let isUpdateable: boolean; + let retrieving: boolean; + let template: boolean; + } + namespace key { + let isCreateable_1: boolean; + export { isCreateable_1 as isCreateable }; + let isUpdateable_1: boolean; + export { isUpdateable_1 as isUpdateable }; + let retrieving_1: boolean; + export { retrieving_1 as retrieving }; + let template_1: boolean; + export { template_1 as template }; + } + namespace createdDate { + let isCreateable_2: boolean; + export { isCreateable_2 as isCreateable }; + let isUpdateable_2: boolean; + export { isUpdateable_2 as isUpdateable }; + let retrieving_2: boolean; + export { retrieving_2 as retrieving }; + let template_2: boolean; + export { template_2 as template }; + } + namespace createdBy { + let isCreateable_3: boolean; + export { isCreateable_3 as isCreateable }; + let isUpdateable_3: boolean; + export { isUpdateable_3 as isUpdateable }; + let retrieving_3: boolean; + export { retrieving_3 as retrieving }; + let template_3: boolean; + export { template_3 as template }; + } + namespace createdByName { + let isCreateable_4: boolean; + export { isCreateable_4 as isCreateable }; + let isUpdateable_4: boolean; + export { isUpdateable_4 as isUpdateable }; + let retrieving_4: boolean; + export { retrieving_4 as retrieving }; + let template_4: boolean; + export { template_4 as template }; + } + namespace lastUpdated { + let isCreateable_5: boolean; + export { isCreateable_5 as isCreateable }; + let isUpdateable_5: boolean; + export { isUpdateable_5 as isUpdateable }; + let retrieving_5: boolean; + export { retrieving_5 as retrieving }; + let template_5: boolean; + export { template_5 as template }; + } + namespace lastUpdatedBy { + let isCreateable_6: boolean; + export { isCreateable_6 as isCreateable }; + let isUpdateable_6: boolean; + export { isUpdateable_6 as isUpdateable }; + let retrieving_6: boolean; + export { retrieving_6 as retrieving }; + let template_6: boolean; + export { template_6 as template }; + } + namespace lastUpdatedByName { + let isCreateable_7: boolean; + export { isCreateable_7 as isCreateable }; + let isUpdateable_7: boolean; + export { isUpdateable_7 as isUpdateable }; + let retrieving_7: boolean; + export { retrieving_7 as retrieving }; + let template_7: boolean; + export { template_7 as template }; + } + namespace name { + let isCreateable_8: boolean; + export { isCreateable_8 as isCreateable }; + let isUpdateable_8: boolean; + export { isUpdateable_8 as isUpdateable }; + let retrieving_8: boolean; + export { retrieving_8 as retrieving }; + let template_8: boolean; + export { template_8 as template }; + } + namespace categoryId { + let isCreateable_9: boolean; + export { isCreateable_9 as isCreateable }; + let isUpdateable_9: boolean; + export { isUpdateable_9 as isUpdateable }; + let retrieving_9: boolean; + export { retrieving_9 as retrieving }; + let template_9: boolean; + export { template_9 as template }; + } + namespace description { + let isCreateable_10: boolean; + export { isCreateable_10 as isCreateable }; + let isUpdateable_10: boolean; + export { isUpdateable_10 as isUpdateable }; + let retrieving_10: boolean; + export { retrieving_10 as retrieving }; + let template_10: boolean; + export { template_10 as template }; + } + namespace filterDefinitionXml { + let isCreateable_11: boolean; + export { isCreateable_11 as isCreateable }; + let isUpdateable_11: boolean; + export { isUpdateable_11 as isUpdateable }; + let retrieving_11: boolean; + export { retrieving_11 as retrieving }; + let template_11: boolean; + export { template_11 as template }; + } + namespace derivedFromType { + let isCreateable_12: boolean; + export { isCreateable_12 as isCreateable }; + let isUpdateable_12: boolean; + export { isUpdateable_12 as isUpdateable }; + let retrieving_12: boolean; + export { retrieving_12 as retrieving }; + let template_12: boolean; + export { template_12 as template }; + } + namespace derivedFromObjectId { + let isCreateable_13: boolean; + export { isCreateable_13 as isCreateable }; + let isUpdateable_13: boolean; + export { isUpdateable_13 as isUpdateable }; + let retrieving_13: boolean; + export { retrieving_13 as retrieving }; + let template_13: boolean; + export { template_13 as template }; + } + namespace derivedFromObjectTypeName { + let isCreateable_14: boolean; + export { isCreateable_14 as isCreateable }; + let isUpdateable_14: boolean; + export { isUpdateable_14 as isUpdateable }; + let retrieving_14: boolean; + export { retrieving_14 as retrieving }; + let template_14: boolean; + export { template_14 as template }; + } + namespace derivedFromObjectName { + let isCreateable_15: boolean; + export { isCreateable_15 as isCreateable }; + let isUpdateable_15: boolean; + export { isUpdateable_15 as isUpdateable }; + let retrieving_15: boolean; + export { retrieving_15 as retrieving }; + let template_15: boolean; + export { template_15 as template }; + } + namespace isSendable { + let isCreateable_16: boolean; + export { isCreateable_16 as isCreateable }; + let isUpdateable_16: boolean; + export { isUpdateable_16 as isUpdateable }; + let retrieving_16: boolean; + export { retrieving_16 as retrieving }; + let template_16: boolean; + export { template_16 as template }; + } + namespace r__source_dataExtension_key { + let isCreateable_17: boolean; + export { isCreateable_17 as isCreateable }; + let isUpdateable_17: boolean; + export { isUpdateable_17 as isUpdateable }; + let retrieving_17: boolean; + export { retrieving_17 as retrieving }; + let template_17: boolean; + export { template_17 as template }; + } + namespace c__filterDefinition { + let skipValidation: boolean; + } + namespace r__folder_Path { + let isCreateable_18: boolean; + export { isCreateable_18 as isCreateable }; + let isUpdateable_18: boolean; + export { isUpdateable_18 as isUpdateable }; + let retrieving_18: boolean; + export { retrieving_18 as retrieving }; + let template_18: boolean; + export { template_18 as template }; + } + } +} +export default _default; +//# sourceMappingURL=FilterDefinitionHidden.definition.d.ts.map \ No newline at end of file diff --git a/@types/lib/metadataTypes/definitions/FilterDefinitionHidden.definition.d.ts.map b/@types/lib/metadataTypes/definitions/FilterDefinitionHidden.definition.d.ts.map new file mode 100644 index 000000000..213cdebf7 --- /dev/null +++ b/@types/lib/metadataTypes/definitions/FilterDefinitionHidden.definition.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"FilterDefinitionHidden.definition.d.ts","sourceRoot":"","sources":["../../../../lib/metadataTypes/definitions/FilterDefinitionHidden.definition.js"],"names":[],"mappings":""} \ No newline at end of file diff --git a/@types/lib/metadataTypes/definitions/Folder.definition.d.ts b/@types/lib/metadataTypes/definitions/Folder.definition.d.ts new file mode 100644 index 000000000..3df6919ee --- /dev/null +++ b/@types/lib/metadataTypes/definitions/Folder.definition.d.ts @@ -0,0 +1,214 @@ +declare namespace _default { + let bodyIteratorField: string; + let dependencies: any[]; + let dependencyGraph: any; + let subTypes: string[]; + let deployFolderTypes: string[]; + let deployFolderTypesEmailRest: string[]; + let deployFolderTypesAssetRest: string[]; + let deployFolderBlacklist: string[]; + let folderTypesFromParent: string[]; + let hasExtended: boolean; + let idField: string; + let keepId: boolean; + let keyIsFixed: boolean; + let keyField: string; + let nameField: string; + let restPagination: boolean; + let type: string; + let soapType: string; + let typeDescription: string; + let typeRetrieveByDefault: boolean; + let typeCdpByDefault: boolean; + let typeName: string; + let fields: { + $: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + '@_xsi:type': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + ID: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'Client.ID': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + CustomerKey: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + Description: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + description: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + CreatedDate: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + ModifiedDate: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + ContentType: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + categoryType: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + catType: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + IsActive: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + IsEditable: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + editable: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + AllowChildren: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + extendable: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + ObjectID: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + objectId: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + Name: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + name: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'ParentFolder.CustomerKey': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'ParentFolder.ID': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + parentCatId: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + parentId: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'ParentFolder.PartnerKey': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'ParentFolder.ObjectID': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'ParentFolder.Path': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + PartnerKey: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + Path: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + _generated: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + }; +} +export default _default; +//# sourceMappingURL=Folder.definition.d.ts.map \ No newline at end of file diff --git a/@types/lib/metadataTypes/definitions/Folder.definition.d.ts.map b/@types/lib/metadataTypes/definitions/Folder.definition.d.ts.map new file mode 100644 index 000000000..906ed18cc --- /dev/null +++ b/@types/lib/metadataTypes/definitions/Folder.definition.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"Folder.definition.d.ts","sourceRoot":"","sources":["../../../../lib/metadataTypes/definitions/Folder.definition.js"],"names":[],"mappings":""} \ No newline at end of file diff --git a/@types/lib/metadataTypes/definitions/ImportFile.definition.d.ts b/@types/lib/metadataTypes/definitions/ImportFile.definition.d.ts new file mode 100644 index 000000000..163b79a97 --- /dev/null +++ b/@types/lib/metadataTypes/definitions/ImportFile.definition.d.ts @@ -0,0 +1,339 @@ +declare namespace _default { + let bodyIteratorField: string; + let dependencies: string[]; + namespace dependencyGraph { + let dataExtension: string[]; + let list: string[]; + let mobileKeyword: string[]; + } + namespace destinationObjectTypeMapping { + let unknown: number; + let DataExtension: number; + let List: number; + let SMS: number; + let Push: number; + let WhatsApp: number; + } + let hasExtended: boolean; + let idField: string; + let keyIsFixed: boolean; + let keyField: string; + let nameField: string; + let createdDateField: string; + let createdNameField: any; + let lastmodDateField: string; + let lastmodNameField: any; + let restPagination: boolean; + let restPageSize: number; + let restConcurrentLimit: number; + namespace subscriberImportTypeMapping { + let DataExtension_1: number; + export { DataExtension_1 as DataExtension }; + export let Email: number; + } + let maxKeyLength: number; + let type: string; + let typeDescription: string; + let typeRetrieveByDefault: boolean; + let typeCdpByDefault: boolean; + let typeName: string; + namespace updateTypeMapping { + let Add: number; + let AddUpdate: number; + let Overwrite: number; + let Update: number; + } + namespace blankFileProcessingTypeMapping { + let Fail: number; + let Process: number; + let Skip: number; + } + let fields: { + allowErrors: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + blankFileProcessingType: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + createdDate: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + customerKey: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + dateFormatLocale: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + deleteFile: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + description: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + destinationId: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + destinationName: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + destinationObjectId: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + destinationObjectTypeId: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + encodingName: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + fieldMappingType: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + fieldMappings: { + skipValidation: boolean; + }; + fileNamingPattern: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + fileSpec: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + fileTransferLocationId: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + fileTransferLocationName: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + fileTransferLocationTypeId: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + fileType: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + filter: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + hasColumnHeader: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + importDefinitionId: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + isOrderedImport: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + isSequential: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + maxFileAgeHours: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + maxFileAgeScheduleOffsetHours: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + maxImportFrequencyHours: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + modifiedDate: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + name: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + }; + notificationEmailAddress: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + otherDelimiter: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + sendEmailNotification: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + standardQuotedStrings: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + subscriberImportTypeId: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + updateTypeId: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + sourceCustomObjectId: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + sourceDataExtensionName: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + c__dataAction: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'destination.r__mobileKeyword_key': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'source.r__dataExtension_key': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'destination.r__dataExtension_key': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'source.c__type': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'destination.c__type': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'destination.r__list_PathName': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'source.r__fileLocation_name': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + c__subscriberImportType: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + c__blankFileProcessing: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + }; +} +export default _default; +//# sourceMappingURL=ImportFile.definition.d.ts.map \ No newline at end of file diff --git a/@types/lib/metadataTypes/definitions/ImportFile.definition.d.ts.map b/@types/lib/metadataTypes/definitions/ImportFile.definition.d.ts.map new file mode 100644 index 000000000..162bec723 --- /dev/null +++ b/@types/lib/metadataTypes/definitions/ImportFile.definition.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"ImportFile.definition.d.ts","sourceRoot":"","sources":["../../../../lib/metadataTypes/definitions/ImportFile.definition.js"],"names":[],"mappings":""} \ No newline at end of file diff --git a/@types/lib/metadataTypes/definitions/Journey.definition.d.ts b/@types/lib/metadataTypes/definitions/Journey.definition.d.ts new file mode 100644 index 000000000..795963136 --- /dev/null +++ b/@types/lib/metadataTypes/definitions/Journey.definition.d.ts @@ -0,0 +1,1172 @@ +declare namespace _default { + let folderType: string; + let bodyIteratorField: string; + let dependencies: string[]; + namespace dependencyGraph { + let event: string[]; + let dataExtension: string[]; + let deliveryProfile: string[]; + let list: string[]; + let senderProfile: string[]; + let sendClassification: string[]; + let asset: string[]; + let mobileMessage: string[]; + let mobileKeyword: string[]; + let mobileCode: string[]; + } + let folderIdField: string; + let hasExtended: boolean; + let idField: string; + let keyIsFixed: boolean; + let keyField: string; + let nameField: string; + let createdDateField: string; + let createdNameField: any; + let lastmodDateField: string; + let lastmodNameField: any; + let restPagination: boolean; + let restPageSize: number; + let maxKeyLength: number; + let type: string; + let typeDescription: string; + let typeRetrieveByDefault: boolean; + let typeCdpByDefault: boolean; + let typeName: string; + namespace priorityMapping { + let High: number; + let Medium: number; + let Low: number; + } + let fields: { + activities: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'activities[].id': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'activities[].key': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'activities[].name': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'activities[].description': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'activities[].type': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'activities[].outcomes': { + skipValidation: boolean; + }; + 'activities[].arguments': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'activities[].arguments.waitEndDateAttributeDataBound': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'activities[].arguments.waitDefinitionId': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'activities[].arguments.waitForEventId': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'activities[].arguments.executionMode': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'activities[].arguments.startActivityKey': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'activities[].arguments.waitQueueId': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'activities[].arguments.activityId': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'activities[].arguments.definitionId': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'activities[].arguments.emailSubjectDataBound': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'activities[].arguments.contactId': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'activities[].arguments.contactKey': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'activities[].arguments.emailAddress': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'activities[].arguments.sourceCustomObjectId': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'activities[].arguments.sourceCustomObjectKey': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'activities[].arguments.fieldType': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'activities[].arguments.eventData': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'activities[].arguments.obfuscationProperties': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'activities[].arguments.customObjectKey': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'activities[].arguments.definitionInstanceId': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'activities[].arguments.filterResult': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'activities[].arguments.version': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'activities[].arguments.requestObjectId': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'activities[].arguments.activityData': { + skipValidation: boolean; + }; + 'activities[].arguments.objectMap': { + skipValidation: boolean; + }; + 'activities[].configurationArguments': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'activities[].configurationArguments.isReconcilable': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'activities[].configurationArguments.isActivityBatchValidated': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'activities[].configurationArguments.triggeredSendKey': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'activities[].configurationArguments.triggeredSendId': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'activities[].configurationArguments.triggeredSend': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'activities[].configurationArguments.triggeredSend.id': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'activities[].configurationArguments.triggeredSend.key': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'activities[].configurationArguments.triggeredSend.campaigns': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'activities[].configurationArguments.triggeredSend.suppressionLists': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'activities[].configurationArguments.triggeredSend.autoAddSubscribers': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'activities[].configurationArguments.triggeredSend.autoUpdateSubscribers': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'activities[].configurationArguments.triggeredSend.bccEmail': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'activities[].configurationArguments.triggeredSend.categoryId': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'activities[].configurationArguments.triggeredSend.ccEmail': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'activities[].configurationArguments.triggeredSend.created': { + skipValidation: boolean; + }; + 'activities[].configurationArguments.triggeredSend.description': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'activities[].configurationArguments.triggeredSend.domainExclusions': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'activities[].configurationArguments.triggeredSend.dynamicEmailSubject': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'activities[].configurationArguments.triggeredSend.emailSubject': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'activities[].configurationArguments.triggeredSend.exclusionFilter': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'activities[].configurationArguments.triggeredSend.isSalesforceTracking': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'activities[].configurationArguments.triggeredSend.isMultipart': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'activities[].configurationArguments.triggeredSend.isSendLogging': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'activities[].configurationArguments.triggeredSend.isStoppedOnJobError': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'activities[].configurationArguments.triggeredSend.keyword': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'activities[].configurationArguments.triggeredSend.modified': { + skipValidation: boolean; + }; + 'activities[].configurationArguments.triggeredSend.name': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'activities[].configurationArguments.triggeredSend.preHeader': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'activities[].configurationArguments.triggeredSend.replyToAddress': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'activities[].configurationArguments.triggeredSend.replyToDisplayName': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'activities[].configurationArguments.triggeredSend.suppressTracking': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'activities[].configurationArguments.triggeredSend.triggeredSendStatus': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'activities[].configurationArguments.triggeredSend.version': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'activities[].configurationArguments.triggeredSend.throttleOpens': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'activities[].configurationArguments.triggeredSend.throttleCloses': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'activities[].configurationArguments.triggeredSend.throttleLimit': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'activities[].configurationArguments.triggeredSend.isTrackingClicks': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'activities[].configurationArguments.triggeredSend.emailId': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'activities[].configurationArguments.triggeredSend.r__triggeredSend_key': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'activities[].configurationArguments.triggeredSend.senderProfileId': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'activities[].configurationArguments.triggeredSend.deliveryProfileId': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'activities[].configurationArguments.triggeredSend.r__senderProfile_key': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'activities[].configurationArguments.triggeredSend.sendClassificationId': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'activities[].configurationArguments.triggeredSend.r__deliveryProfile_key': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'activities[].configurationArguments.triggeredSend.r__sendClassification_key': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'activities[].configurationArguments.triggeredSend.r__list_PathName': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'activities[].configurationArguments.triggeredSend.publicationListId': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'activities[].configurationArguments.triggeredSend.r__list_PathName.publicationList': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'activities[].configurationArguments.triggeredSend.r__list_PathName.suppressionLists': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'activities[].configurationArguments.triggeredSend.r__dataExtension_key': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'activities[].configurationArguments.triggeredSend.r__dataExtension_key.domainExclusions': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'activities[].configurationArguments.triggeredSend.priority': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'activities[].configurationArguments.triggeredSend.c__priority': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'activities[].configurationArguments.triggeredSend.r__asset_name_readOnly': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'activities[].configurationArguments.triggeredSend.r__asset_key': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'activities[].configurationArguments.triggeredSend.updateSubscriber': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'activities[].configurationArguments.applicationExtensionKey': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'activities[].configurationArguments.r__transactionalEmail_key': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'activities[].configurationArguments.applicationExtensionId': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'activities[].configurationArguments.isModified': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'activities[].configurationArguments.isSimulation': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'activities[].configurationArguments.googleAnalyticsCampaignName': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'activities[].configurationArguments.useLLTS': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'activities[].configurationArguments.fuelAgentRequested': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'activities[].configurationArguments.r__triggeredSend_key': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'activities[].configurationArguments.waitDuration': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'activities[].configurationArguments.waitUnit': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'activities[].configurationArguments.specifiedTime': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'activities[].configurationArguments.timeZone': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'activities[].configurationArguments.description': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'activities[].configurationArguments.waitEndDateAttributeExpression': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'activities[].configurationArguments.specificDate': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'activities[].configurationArguments.waitForEventKey': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'activities[].configurationArguments.schemaVersionId': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'activities[].configurationArguments.criteria': { + skipValidation: boolean; + }; + 'activities[].configurationArguments.eventDataConfig': { + skipValidation: boolean; + }; + 'activities[].metaData': { + skipValidation: boolean; + }; + 'activities[].schema': { + skipValidation: boolean; + }; + 'activities[].arguments.activityData.updateContactFields[].r__dataExtension_key': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'activities[].arguments.activityData.updateContactFields[].r__dataExtensionField_name': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'activities[].arguments.activityData.updateContactFields[].field': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + categoryId: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + channel: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + createdDate: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'defaults.email': { + skipValidation: boolean; + }; + 'defaults.mobileNumber': { + skipValidation: boolean; + }; + 'defaults.properties.analyticsTracking.enabled': { + isCreateable: any; + isUpdateable: any; + retrieving: any; + template: any; + }; + 'defaults.properties': { + skipValidation: boolean; + }; + 'defaults.properties.analyticsTracking.analyticsType': { + isCreateable: any; + isUpdateable: any; + retrieving: any; + template: any; + }; + 'defaults.properties.analyticsTracking.urlDomainsToTrack': { + isCreateable: any; + isUpdateable: any; + retrieving: any; + template: any; + }; + definitionId: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + definitionType: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + description: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + entryMode: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + executionMode: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + exits: { + skipValidation: boolean; + }; + goals: { + skipValidation: boolean; + }; + healthStats: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + id: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + key: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + lastPublishedDate: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'metaData.templateId': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + modifiedDate: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + name: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + scheduledStatus: { + isCreateable: any; + isUpdateable: any; + retrieving: any; + template: any; + }; + stats: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + status: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + triggers: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'triggers[].id': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'triggers[].key': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'triggers[].name': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'triggers[].description': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'triggers[].type': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'triggers[].outcomes': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'triggers[].arguments': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'triggers[].arguments.startActivityKey': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'triggers[].arguments.dequeueReason': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'triggers[].arguments.lastExecutedActivityKey': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'triggers[].arguments.filterResult': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'triggers[].arguments.serializedObjectType': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'triggers[].arguments.eventDefinitionId': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'triggers[].arguments.eventDefinitionKey': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'triggers[].arguments.dataExtensionId': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'triggers[].arguments.automationId': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'triggers[].arguments.r__event_key': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'triggers[].arguments.r__dataExtension_key': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'triggers[].configurationArguments': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'triggers[].configurationArguments.eventDataConfig': { + skipValidation: boolean; + }; + 'triggers[].configurationArguments.primaryObjectFilterCriteria': { + skipValidation: boolean; + }; + 'triggers[].configurationArguments.relatedObjectFilterCriteria': { + skipValidation: boolean; + }; + 'triggers[].configurationArguments.salesforceTriggerCriteria': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'triggers[].configurationArguments.objectApiName': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'triggers[].configurationArguments.objectAPIName': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'triggers[].configurationArguments.version': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'triggers[].configurationArguments.contactKey': { + skipValidation: boolean; + }; + 'triggers[].configurationArguments.contactPersonType': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'triggers[].configurationArguments.primaryObjectFilterSummary': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'triggers[].configurationArguments.relatedObjectFilterSummary': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'triggers[].configurationArguments.eventDataSummary': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'triggers[].configurationArguments.evaluationCriteriaSummary': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'triggers[].configurationArguments.applicationExtensionKey': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'triggers[].configurationArguments.passThroughArgument': { + skipValidation: boolean; + }; + 'triggers[].configurationArguments.filterDefinitionId': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'triggers[].configurationArguments.criteria': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'triggers[].configurationArguments.schemaVersionId': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'triggers[].configurationArguments.whoToInject': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'triggers[].configurationArguments.additionalObjectFilterCriteria': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'triggers[].metaData': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'triggers[].metaData.sourceInteractionId': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'triggers[].metaData.entrySourceGroupConfigUrl': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'triggers[].metaData.r__event_key': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'triggers[].metaData.category': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'triggers[].metaData.eventDefinitionId': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'triggers[].metaData.eventDefinitionKey': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'triggers[].metaData.chainType': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'triggers[].metaData.configurationRequired': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'triggers[].metaData.iconUrl': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'triggers[].metaData.title': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'triggers[].metaData.scheduleState': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + version: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + workflowApiVersion: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + campaigns: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + metaData: { + skipValidation: boolean; + }; + notifiers: { + skipValidation: boolean; + }; + tags: { + skipValidation: boolean; + }; + r__folder_Path: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + }; +} +export default _default; +//# sourceMappingURL=Journey.definition.d.ts.map \ No newline at end of file diff --git a/@types/lib/metadataTypes/definitions/Journey.definition.d.ts.map b/@types/lib/metadataTypes/definitions/Journey.definition.d.ts.map new file mode 100644 index 000000000..1671e93e0 --- /dev/null +++ b/@types/lib/metadataTypes/definitions/Journey.definition.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"Journey.definition.d.ts","sourceRoot":"","sources":["../../../../lib/metadataTypes/definitions/Journey.definition.js"],"names":[],"mappings":""} \ No newline at end of file diff --git a/@types/lib/metadataTypes/definitions/List.definition.d.ts b/@types/lib/metadataTypes/definitions/List.definition.d.ts new file mode 100644 index 000000000..973935db2 --- /dev/null +++ b/@types/lib/metadataTypes/definitions/List.definition.d.ts @@ -0,0 +1,120 @@ +declare namespace _default { + let bodyIteratorField: string; + let dependencies: string[]; + let dependencyGraph: any; + let folderType: string; + let hasExtended: boolean; + let idField: string; + let keyIsFixed: boolean; + let keyField: string; + let nameField: string; + let restPagination: any; + let type: string; + let typeDescription: string; + let typeRetrieveByDefault: boolean; + let typeCdpByDefault: boolean; + let typeName: string; + let fields: { + 'AutomatedEmail.ID': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'AutomatedEmail.PartnerKey': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'AutomatedEmail.ObjectID': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + Category: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'Client.ID': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'Client.PartnerClientKey': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + CreatedDate: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + CustomerKey: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + Description: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + ID: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + ListClassification: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + ListName: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + ModifiedDate: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + ObjectID: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + PartnerKey: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + Type: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + r__folder_Path: { + skipValidation: boolean; + }; + }; +} +export default _default; +//# sourceMappingURL=List.definition.d.ts.map \ No newline at end of file diff --git a/@types/lib/metadataTypes/definitions/List.definition.d.ts.map b/@types/lib/metadataTypes/definitions/List.definition.d.ts.map new file mode 100644 index 000000000..b47c1a2f7 --- /dev/null +++ b/@types/lib/metadataTypes/definitions/List.definition.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"List.definition.d.ts","sourceRoot":"","sources":["../../../../lib/metadataTypes/definitions/List.definition.js"],"names":[],"mappings":""} \ No newline at end of file diff --git a/@types/lib/metadataTypes/definitions/MobileCode.definition.d.ts b/@types/lib/metadataTypes/definitions/MobileCode.definition.d.ts new file mode 100644 index 000000000..cfbb444a9 --- /dev/null +++ b/@types/lib/metadataTypes/definitions/MobileCode.definition.d.ts @@ -0,0 +1,169 @@ +declare namespace _default { + let bodyIteratorField: string; + let dependencies: any[]; + let dependencyGraph: any; + let hasExtended: boolean; + let idField: string; + let keyIsFixed: boolean; + let keyField: string; + let nameField: string; + let createdDateField: string; + let createdNameField: any; + let lastmodDateField: string; + let lastmodNameField: any; + let restPagination: boolean; + let restPageSize: number; + let type: string; + let typeDescription: string; + let typeRetrieveByDefault: boolean; + let typeCdpByDefault: boolean; + let typeName: string; + let fields: { + id: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + createdDate: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + lastUpdated: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + startDate: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + endDate: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + keywordLimit: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + keywordsUsed: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + code: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + codeType: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + isShortCode: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + keywordsUsedOther: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + isGsmCharacterSetOnly: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + isMms: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + isStackIndependant: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + supportsConcatenation: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + isClientOwned: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + isOwner: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + dipSwitches: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + sendableCountries: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'sendableCountries[].countryCode': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'sendableCountries[].vendor': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'sendableCountries[].fromNameSupported': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + countryCode: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + moEngineVersion: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + }; +} +export default _default; +//# sourceMappingURL=MobileCode.definition.d.ts.map \ No newline at end of file diff --git a/@types/lib/metadataTypes/definitions/MobileCode.definition.d.ts.map b/@types/lib/metadataTypes/definitions/MobileCode.definition.d.ts.map new file mode 100644 index 000000000..97b5663e0 --- /dev/null +++ b/@types/lib/metadataTypes/definitions/MobileCode.definition.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"MobileCode.definition.d.ts","sourceRoot":"","sources":["../../../../lib/metadataTypes/definitions/MobileCode.definition.js"],"names":[],"mappings":""} \ No newline at end of file diff --git a/@types/lib/metadataTypes/definitions/MobileKeyword.definition.d.ts b/@types/lib/metadataTypes/definitions/MobileKeyword.definition.d.ts new file mode 100644 index 000000000..42772246c --- /dev/null +++ b/@types/lib/metadataTypes/definitions/MobileKeyword.definition.d.ts @@ -0,0 +1,286 @@ +declare namespace _default { + let bodyIteratorField: string; + let dependencies: string[]; + namespace dependencyGraph { + let mobileCode: string[]; + } + let hasExtended: boolean; + let idField: string; + let keyIsFixed: boolean; + let keyField: string; + let nameField: string; + let createdDateField: string; + let createdNameField: string; + let lastmodDateField: string; + let lastmodNameField: any; + let restPagination: boolean; + let restPageSize: number; + let maxKeyLength: number; + let type: string; + let typeDescription: string; + let typeRetrieveByDefault: boolean; + let typeCdpByDefault: boolean; + let typeName: string; + let fields: { + id: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + c__codeKeyword: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + r__mobileCode_key: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + keyword: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + createdDate: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + lastUpdated: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + startDate: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + endDate: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + createdBy: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'createdBy.id': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'createdBy.name': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'createdBy.lastUpdated': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + dipSwitches: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + isInherited: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + decodedId: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + restriction: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + keywordType: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + companyName: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + responseMessage: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + status: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + messages: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + code: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'code.code': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'code.id': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'code.createdDate': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'code.lastUpdated': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'code.startDate': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'code.endDate': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'code.keywordLimit': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'code.keywordsUsed': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'code.codeType': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'code.isShortCode': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'code.keywordsUsedOther': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'code.isGsmCharacterSetOnly': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'code.isMms': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'code.isStackIndependant': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'code.supportsConcatenation': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'code.isClientOwned': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'code.isOwner': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'code.dipSwitches': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'code.sendableCountries': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'code.countryCode': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'code.moEngineVersion': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + }; +} +export default _default; +//# sourceMappingURL=MobileKeyword.definition.d.ts.map \ No newline at end of file diff --git a/@types/lib/metadataTypes/definitions/MobileKeyword.definition.d.ts.map b/@types/lib/metadataTypes/definitions/MobileKeyword.definition.d.ts.map new file mode 100644 index 000000000..91621d4ce --- /dev/null +++ b/@types/lib/metadataTypes/definitions/MobileKeyword.definition.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"MobileKeyword.definition.d.ts","sourceRoot":"","sources":["../../../../lib/metadataTypes/definitions/MobileKeyword.definition.js"],"names":[],"mappings":""} \ No newline at end of file diff --git a/@types/lib/metadataTypes/definitions/MobileMessage.definition.d.ts b/@types/lib/metadataTypes/definitions/MobileMessage.definition.d.ts new file mode 100644 index 000000000..228b36971 --- /dev/null +++ b/@types/lib/metadataTypes/definitions/MobileMessage.definition.d.ts @@ -0,0 +1,788 @@ +declare namespace _default { + let bodyIteratorField: string; + let dependencies: string[]; + namespace dependencyGraph { + let mobileCode: string[]; + let mobileKeyword: string[]; + } + let hasExtended: boolean; + let idField: string; + let keepId: boolean; + let keyIsFixed: boolean; + let keyField: string; + let nameField: string; + let createdDateField: any; + let createdNameField: any; + let lastmodDateField: string; + let lastmodNameField: any; + let restPagination: boolean; + let restPageSize: number; + let type: string; + let typeDescription: string; + let typeRetrieveByDefault: boolean; + let typeCdpByDefault: boolean; + let typeName: string; + let fields: { + allowSingleOptin: { + isCreatable: boolean; + isUpdatable: boolean; + retrieving: boolean; + template: boolean; + }; + audience: { + skipValidation: boolean; + }; + 'audience[]': { + skipValidation: boolean; + }; + campaigns: { + skipValidation: boolean; + }; + 'campaigns[]': { + skipValidation: boolean; + }; + r__mobileCode_key: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'code.code': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'code.codeType': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'code.countryCode': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'code.createdDate': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'code.dipSwitches': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'code.endDate': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'code.id': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'code.isClientOwned': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'code.isGsmCharacterSetOnly': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'code.isMms': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'code.isOwner': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'code.isShortCode': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'code.isStackIndependant': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'code.keywordLimit': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'code.keywordsUsed': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'code.keywordsUsedOther': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'code.lastUpdated': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'code.moEngineVersion': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'code.sendableCountries': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'code.sendableCountries[]': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'code.sendableCountries[].countryCode': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'code.sendableCountries[].vendor': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'code.sendableCountries[].fromNameSupported': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'code.startDate': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'code.supportsConcatenation': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + concatenateMessage: { + isCreatable: boolean; + isUpdatable: boolean; + retrieving: boolean; + template: boolean; + }; + currentEditStep: { + isCreatable: boolean; + isUpdatable: boolean; + retrieving: boolean; + template: boolean; + }; + doubleOptinConfirmMessage: { + isCreatable: boolean; + isUpdatable: boolean; + retrieving: boolean; + template: boolean; + }; + doubleOptinInitialMessage: { + isCreatable: boolean; + isUpdatable: boolean; + retrieving: boolean; + template: boolean; + }; + doubleOptinValidResponses: { + isCreatable: boolean; + isUpdatable: boolean; + retrieving: boolean; + template: boolean; + }; + duplicateOptInResponseMessage: { + isCreatable: boolean; + isUpdatable: boolean; + retrieving: boolean; + template: boolean; + }; + expireHours: { + isCreatable: boolean; + isUpdatable: boolean; + retrieving: boolean; + template: boolean; + }; + fromName: { + isCreatable: boolean; + isUpdatable: boolean; + retrieving: boolean; + template: boolean; + }; + id: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + invalidMessage: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + isCertified: { + isCreatable: boolean; + isUpdatable: boolean; + retrieving: boolean; + template: boolean; + }; + isDuplicationAllowed: { + isCreatable: boolean; + isUpdatable: boolean; + retrieving: boolean; + template: boolean; + }; + isExpireSet: { + isCreatable: boolean; + isUpdatable: boolean; + retrieving: boolean; + template: boolean; + }; + isFromNameCertificationAccepted: { + isCreatable: boolean; + isUpdatable: boolean; + retrieving: boolean; + template: boolean; + }; + isSentImmediately: { + isCreatable: boolean; + isUpdatable: boolean; + retrieving: boolean; + template: boolean; + }; + isSubscriberResponseToAnySubscriptionForShortCode: { + isCreatable: boolean; + isUpdatable: boolean; + retrieving: boolean; + template: boolean; + }; + isSuppressMt: { + isCreatable: boolean; + isUpdatable: boolean; + retrieving: boolean; + template: boolean; + }; + isTest: { + isCreatable: boolean; + isUpdatable: boolean; + retrieving: boolean; + template: boolean; + }; + isTimeZoneBased: { + isCreatable: boolean; + isUpdatable: boolean; + retrieving: boolean; + template: boolean; + }; + 'keyword.id': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'keyword.isInherited': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'keyword.keyword': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'keyword.r__mobileKeyword_key': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'keyword.keywordType': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'keyword.restriction': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + lastUpdated: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + messageObjectId: { + isCreatable: boolean; + isUpdatable: boolean; + retrieving: boolean; + template: boolean; + }; + messagesPerPeriod: { + isCreatable: boolean; + isUpdatable: boolean; + retrieving: boolean; + template: boolean; + }; + minutesPerPeriod: { + isCreatable: boolean; + isUpdatable: boolean; + retrieving: boolean; + template: boolean; + }; + moStartDate: { + isCreatable: boolean; + isUpdatable: boolean; + retrieving: boolean; + template: boolean; + }; + moEndDate: { + isCreatable: boolean; + isUpdatable: boolean; + retrieving: boolean; + template: boolean; + }; + 'moTimezone.name': { + isCreatable: boolean; + isUpdatable: boolean; + retrieving: boolean; + template: boolean; + }; + 'moTimezone.offset': { + isCreatable: boolean; + isUpdatable: boolean; + retrieving: boolean; + template: boolean; + }; + 'mtRecurrence.id': { + isCreatable: boolean; + isUpdatable: boolean; + retrieving: boolean; + template: boolean; + }; + 'mtRecurrence.key': { + isCreatable: boolean; + isUpdatable: boolean; + retrieving: boolean; + template: boolean; + }; + 'mtRecurrence.createdDate': { + isCreatable: boolean; + isUpdatable: boolean; + retrieving: boolean; + template: boolean; + }; + 'mtRecurrence.createdBy': { + isCreatable: boolean; + isUpdatable: boolean; + retrieving: boolean; + template: boolean; + }; + 'mtRecurrence.lastUpdated': { + isCreatable: boolean; + isUpdatable: boolean; + retrieving: boolean; + template: boolean; + }; + 'mtRecurrence.lastUpdatedBy': { + isCreatable: boolean; + isUpdatable: boolean; + retrieving: boolean; + template: boolean; + }; + 'mtRecurrence.name': { + isCreatable: boolean; + isUpdatable: boolean; + retrieving: boolean; + template: boolean; + }; + 'mtRecurrence.description': { + isCreatable: boolean; + isUpdatable: boolean; + retrieving: boolean; + template: boolean; + }; + 'mtRecurrence.startDate': { + isCreatable: boolean; + isUpdatable: boolean; + retrieving: boolean; + template: boolean; + }; + 'mtRecurrence.iCalRecur': { + isCreatable: boolean; + isUpdatable: boolean; + retrieving: boolean; + template: boolean; + }; + 'mtRecurrence.timeZone': { + isCreatable: boolean; + isUpdatable: boolean; + retrieving: boolean; + template: boolean; + }; + 'mtRecurrence.timeZoneId': { + isCreatable: boolean; + isUpdatable: boolean; + retrieving: boolean; + template: boolean; + }; + mtSendDate: { + isCreatable: boolean; + isUpdatable: boolean; + retrieving: boolean; + template: boolean; + }; + name: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + nextJob: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + nextKeyword: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + numberMessagesPerPeriod: { + isCreatable: boolean; + isUpdatable: boolean; + retrieving: boolean; + template: boolean; + }; + optinErrorMessage: { + isCreatable: boolean; + isUpdatable: boolean; + retrieving: boolean; + template: boolean; + }; + optinInvalidAgeMessage: { + isCreatable: boolean; + isUpdatable: boolean; + retrieving: boolean; + template: boolean; + }; + optinMinimumAge: { + isCreatable: boolean; + isUpdatable: boolean; + retrieving: boolean; + template: boolean; + }; + optinType: { + isCreatable: boolean; + isUpdatable: boolean; + retrieving: boolean; + template: boolean; + }; + origin: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + outboundSendBehaviorFlag: { + isCreatable: boolean; + isUpdatable: boolean; + retrieving: boolean; + template: boolean; + }; + outboundSendTypeFlag: { + isCreatable: boolean; + isUpdatable: boolean; + retrieving: boolean; + template: boolean; + }; + periodType: { + isCreatable: boolean; + isUpdatable: boolean; + retrieving: boolean; + template: boolean; + }; + programId: { + isCreatable: boolean; + isUpdatable: boolean; + retrieving: boolean; + template: boolean; + }; + publishedMessage: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + responseMessage: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + sendMethod: { + isCreatable: boolean; + isUpdatable: boolean; + retrieving: boolean; + template: boolean; + }; + smsTriggeredSendDefinitionId: { + isCreatable: boolean; + isUpdatable: boolean; + retrieving: boolean; + template: boolean; + }; + statistics: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'statistics.outbound': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'statistics.outbound.sent': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'statistics.outbound.delivered': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'statistics.outbound.undelivered': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'statistics.outbound.unknown': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + status: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + statusId: { + isCreatable: boolean; + isUpdatable: boolean; + retrieving: boolean; + template: boolean; + }; + 'subscriptionKeyword.id': { + isCreatable: boolean; + isUpdatable: boolean; + retrieving: boolean; + template: boolean; + }; + 'subscriptionKeyword.keyword': { + isCreatable: boolean; + isUpdatable: boolean; + retrieving: boolean; + template: boolean; + }; + 'subscriptionKeyword.r__mobileKeyword_key': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'subscriptionKeyword.restriction': { + isCreatable: boolean; + isUpdatable: boolean; + retrieving: boolean; + template: boolean; + }; + 'subscriptionKeyword.isInherited': { + isCreatable: boolean; + isUpdatable: boolean; + retrieving: boolean; + template: boolean; + }; + 'nextKeyword.id': { + isCreatable: boolean; + isUpdatable: boolean; + retrieving: boolean; + template: boolean; + }; + 'nextKeyword.keyword': { + isCreatable: boolean; + isUpdatable: boolean; + retrieving: boolean; + template: boolean; + }; + 'nextKeyword.r__mobileKeyword_key': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'nextKeyword.restriction': { + isCreatable: boolean; + isUpdatable: boolean; + retrieving: boolean; + template: boolean; + }; + 'nextKeyword.isInherited': { + isCreatable: boolean; + isUpdatable: boolean; + retrieving: boolean; + template: boolean; + }; + subscriberResponseMessage: { + isCreatable: boolean; + isUpdatable: boolean; + retrieving: boolean; + template: boolean; + }; + surveyCorrectResponseMessage: { + isCreatable: boolean; + isUpdatable: boolean; + retrieving: boolean; + template: boolean; + }; + surveyIncorrectResponseMessage: { + isCreatable: boolean; + isUpdatable: boolean; + retrieving: boolean; + template: boolean; + }; + surveyResponsesAllowed: { + isCreatable: boolean; + isUpdatable: boolean; + retrieving: boolean; + template: boolean; + }; + surveyTooManyEntriesMessage: { + isCreatable: boolean; + isUpdatable: boolean; + retrieving: boolean; + template: boolean; + }; + surveyType: { + isCreatable: boolean; + isUpdatable: boolean; + retrieving: boolean; + template: boolean; + }; + 'template.description': { + isCreatable: boolean; + isUpdatable: boolean; + retrieving: boolean; + template: boolean; + }; + 'template.icon': { + isCreatable: boolean; + isUpdatable: boolean; + retrieving: boolean; + template: boolean; + }; + 'template.id': { + isCreatable: boolean; + isUpdatable: boolean; + retrieving: boolean; + template: boolean; + }; + 'template.lastUpdated': { + isCreatable: boolean; + isUpdatable: boolean; + retrieving: boolean; + template: boolean; + }; + 'template.name': { + isCreatable: boolean; + isUpdatable: boolean; + retrieving: boolean; + template: boolean; + }; + text: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + triggeredSendId: { + isCreatable: boolean; + isUpdatable: boolean; + retrieving: boolean; + template: boolean; + }; + triggeredSendName: { + isCreatable: boolean; + isUpdatable: boolean; + retrieving: boolean; + template: boolean; + }; + type: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + r__campaign_key: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'r__campaign_key[]': { + skipValidation: boolean; + }; + }; +} +export default _default; +//# sourceMappingURL=MobileMessage.definition.d.ts.map \ No newline at end of file diff --git a/@types/lib/metadataTypes/definitions/MobileMessage.definition.d.ts.map b/@types/lib/metadataTypes/definitions/MobileMessage.definition.d.ts.map new file mode 100644 index 000000000..676c59a9d --- /dev/null +++ b/@types/lib/metadataTypes/definitions/MobileMessage.definition.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"MobileMessage.definition.d.ts","sourceRoot":"","sources":["../../../../lib/metadataTypes/definitions/MobileMessage.definition.js"],"names":[],"mappings":""} \ No newline at end of file diff --git a/@types/lib/metadataTypes/definitions/Query.definition.d.ts b/@types/lib/metadataTypes/definitions/Query.definition.d.ts new file mode 100644 index 000000000..80c98ab1e --- /dev/null +++ b/@types/lib/metadataTypes/definitions/Query.definition.d.ts @@ -0,0 +1,207 @@ +declare namespace _default { + let bodyIteratorField: string; + let dependencies: string[]; + namespace dependencyGraph { + let dataExtension: string[]; + } + let folderType: string; + namespace filter { + let description: string[]; + } + let hasExtended: boolean; + let idField: string; + let keyIsFixed: boolean; + let keyField: string; + let nameField: string; + let folderIdField: string; + let createdDateField: string; + let createdNameField: any; + let lastmodDateField: string; + let lastmodNameField: any; + let restPagination: boolean; + namespace targetUpdateTypeMapping { + let Append: number; + let Overwrite: number; + let Update: number; + } + let maxKeyLength: number; + let type: string; + let typeDescription: string; + let typeRetrieveByDefault: boolean; + let typeCdpByDefault: boolean; + let typeName: string; + namespace fields { + export namespace categoryId { + let isCreateable: boolean; + let isUpdateable: boolean; + let retrieving: boolean; + let template: boolean; + } + export namespace createdDate { + let isCreateable_1: boolean; + export { isCreateable_1 as isCreateable }; + let isUpdateable_1: boolean; + export { isUpdateable_1 as isUpdateable }; + let retrieving_1: boolean; + export { retrieving_1 as retrieving }; + let template_1: boolean; + export { template_1 as template }; + } + export namespace description_1 { + let isCreateable_2: boolean; + export { isCreateable_2 as isCreateable }; + let isUpdateable_2: boolean; + export { isUpdateable_2 as isUpdateable }; + let retrieving_2: boolean; + export { retrieving_2 as retrieving }; + let template_2: boolean; + export { template_2 as template }; + } + export { description_1 as description }; + export namespace isFrozen { + let isCreateable_3: boolean; + export { isCreateable_3 as isCreateable }; + let isUpdateable_3: boolean; + export { isUpdateable_3 as isUpdateable }; + let retrieving_3: boolean; + export { retrieving_3 as retrieving }; + let template_3: boolean; + export { template_3 as template }; + } + export namespace key { + let isCreateable_4: boolean; + export { isCreateable_4 as isCreateable }; + let isUpdateable_4: boolean; + export { isUpdateable_4 as isUpdateable }; + let retrieving_4: boolean; + export { retrieving_4 as retrieving }; + let template_4: boolean; + export { template_4 as template }; + } + export namespace modifiedDate { + let isCreateable_5: boolean; + export { isCreateable_5 as isCreateable }; + let isUpdateable_5: boolean; + export { isUpdateable_5 as isUpdateable }; + let retrieving_5: boolean; + export { retrieving_5 as retrieving }; + let template_5: boolean; + export { template_5 as template }; + } + export namespace name { + let isCreateable_6: boolean; + export { isCreateable_6 as isCreateable }; + let isUpdateable_6: boolean; + export { isUpdateable_6 as isUpdateable }; + let retrieving_6: boolean; + export { retrieving_6 as retrieving }; + let template_6: boolean; + export { template_6 as template }; + } + export namespace queryDefinitionId { + let isCreateable_7: boolean; + export { isCreateable_7 as isCreateable }; + let isUpdateable_7: boolean; + export { isUpdateable_7 as isUpdateable }; + let retrieving_7: boolean; + export { retrieving_7 as retrieving }; + let template_7: boolean; + export { template_7 as template }; + } + export namespace queryText { + let isCreateable_8: boolean; + export { isCreateable_8 as isCreateable }; + let isUpdateable_8: boolean; + export { isUpdateable_8 as isUpdateable }; + let retrieving_8: boolean; + export { retrieving_8 as retrieving }; + let template_8: boolean; + export { template_8 as template }; + } + export namespace targetDescription { + let isCreateable_9: boolean; + export { isCreateable_9 as isCreateable }; + let isUpdateable_9: boolean; + export { isUpdateable_9 as isUpdateable }; + let retrieving_9: boolean; + export { retrieving_9 as retrieving }; + let template_9: boolean; + export { template_9 as template }; + } + export namespace targetId { + let isCreateable_10: boolean; + export { isCreateable_10 as isCreateable }; + let isUpdateable_10: boolean; + export { isUpdateable_10 as isUpdateable }; + let retrieving_10: boolean; + export { retrieving_10 as retrieving }; + let template_10: boolean; + export { template_10 as template }; + } + export namespace targetKey { + let isCreateable_11: boolean; + export { isCreateable_11 as isCreateable }; + let isUpdateable_11: boolean; + export { isUpdateable_11 as isUpdateable }; + let retrieving_11: boolean; + export { retrieving_11 as retrieving }; + let template_11: boolean; + export { template_11 as template }; + } + export namespace targetName { + let isCreateable_12: boolean; + export { isCreateable_12 as isCreateable }; + let isUpdateable_12: boolean; + export { isUpdateable_12 as isUpdateable }; + let retrieving_12: boolean; + export { retrieving_12 as retrieving }; + let template_12: boolean; + export { template_12 as template }; + } + export namespace targetUpdateTypeId { + let isCreateable_13: boolean; + export { isCreateable_13 as isCreateable }; + let isUpdateable_13: boolean; + export { isUpdateable_13 as isUpdateable }; + let retrieving_13: boolean; + export { retrieving_13 as retrieving }; + let template_13: boolean; + export { template_13 as template }; + } + export namespace targetUpdateTypeName { + let isCreateable_14: boolean; + export { isCreateable_14 as isCreateable }; + let isUpdateable_14: boolean; + export { isUpdateable_14 as isUpdateable }; + let retrieving_14: boolean; + export { retrieving_14 as retrieving }; + let template_14: boolean; + export { template_14 as template }; + } + export namespace validatedQueryText { + let isCreateable_15: boolean; + export { isCreateable_15 as isCreateable }; + let isUpdateable_15: boolean; + export { isUpdateable_15 as isUpdateable }; + let retrieving_15: boolean; + export { retrieving_15 as retrieving }; + let template_15: boolean; + export { template_15 as template }; + } + export namespace r__dataExtension_key { + let isCreateable_16: boolean; + export { isCreateable_16 as isCreateable }; + let isUpdateable_16: boolean; + export { isUpdateable_16 as isUpdateable }; + let retrieving_16: boolean; + export { retrieving_16 as retrieving }; + let template_16: boolean; + export { template_16 as template }; + } + export namespace r__folder_Path { + let skipValidation: boolean; + } + } +} +export default _default; +//# sourceMappingURL=Query.definition.d.ts.map \ No newline at end of file diff --git a/@types/lib/metadataTypes/definitions/Query.definition.d.ts.map b/@types/lib/metadataTypes/definitions/Query.definition.d.ts.map new file mode 100644 index 000000000..87130d0a3 --- /dev/null +++ b/@types/lib/metadataTypes/definitions/Query.definition.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"Query.definition.d.ts","sourceRoot":"","sources":["../../../../lib/metadataTypes/definitions/Query.definition.js"],"names":[],"mappings":""} \ No newline at end of file diff --git a/@types/lib/metadataTypes/definitions/Role.definition.d.ts b/@types/lib/metadataTypes/definitions/Role.definition.d.ts new file mode 100644 index 000000000..a5fa53766 --- /dev/null +++ b/@types/lib/metadataTypes/definitions/Role.definition.d.ts @@ -0,0 +1,110 @@ +declare namespace _default { + let bodyIteratorField: string; + let dependencies: any[]; + let dependencyGraph: any; + let deployBlacklist: string[]; + let documentInOneFile: boolean; + let hasExtended: boolean; + let idField: string; + let keyIsFixed: boolean; + let keyField: string; + let nameField: string; + let createdDateField: string; + let createdNameField: any; + let lastmodDateField: string; + let lastmodNameField: any; + let maxKeyLength: number; + let type: string; + let typeDescription: string; + let typeRetrieveByDefault: boolean; + let typeCdpByDefault: boolean; + let typeName: string; + namespace fields { + namespace CreatedDate { + let isCreateable: boolean; + let isUpdateable: boolean; + let retrieving: boolean; + let template: boolean; + } + namespace CustomerKey { + let isCreateable_1: boolean; + export { isCreateable_1 as isCreateable }; + let isUpdateable_1: boolean; + export { isUpdateable_1 as isUpdateable }; + let retrieving_1: boolean; + export { retrieving_1 as retrieving }; + let template_1: boolean; + export { template_1 as template }; + } + namespace Description { + let isCreateable_2: boolean; + export { isCreateable_2 as isCreateable }; + let isUpdateable_2: boolean; + export { isUpdateable_2 as isUpdateable }; + let retrieving_2: boolean; + export { retrieving_2 as retrieving }; + let template_2: boolean; + export { template_2 as template }; + } + namespace ModifiedDate { + let isCreateable_3: boolean; + export { isCreateable_3 as isCreateable }; + let isUpdateable_3: boolean; + export { isUpdateable_3 as isUpdateable }; + let retrieving_3: boolean; + export { retrieving_3 as retrieving }; + let template_3: boolean; + export { template_3 as template }; + } + namespace Name { + let isCreateable_4: any; + export { isCreateable_4 as isCreateable }; + let isUpdateable_4: any; + export { isUpdateable_4 as isUpdateable }; + let retrieving_4: boolean; + export { retrieving_4 as retrieving }; + } + namespace ObjectID { + let isCreateable_5: boolean; + export { isCreateable_5 as isCreateable }; + let isUpdateable_5: boolean; + export { isUpdateable_5 as isUpdateable }; + let retrieving_5: boolean; + export { retrieving_5 as retrieving }; + let template_4: boolean; + export { template_4 as template }; + } + namespace PartnerKey { + let isCreateable_6: boolean; + export { isCreateable_6 as isCreateable }; + let isUpdateable_6: boolean; + export { isUpdateable_6 as isUpdateable }; + let retrieving_6: boolean; + export { retrieving_6 as retrieving }; + let template_5: boolean; + export { template_5 as template }; + } + namespace IsSystemDefined { + let isCreateable_7: boolean; + export { isCreateable_7 as isCreateable }; + let isUpdateable_7: boolean; + export { isUpdateable_7 as isUpdateable }; + let retrieving_7: boolean; + export { retrieving_7 as retrieving }; + let template_6: boolean; + export { template_6 as template }; + } + namespace PermissionSets { + let retrieving_8: boolean; + export { retrieving_8 as retrieving }; + export let skipCache: boolean; + export let skipValidation: boolean; + } + namespace c__notAssignable { + let skipValidation_1: boolean; + export { skipValidation_1 as skipValidation }; + } + } +} +export default _default; +//# sourceMappingURL=Role.definition.d.ts.map \ No newline at end of file diff --git a/@types/lib/metadataTypes/definitions/Role.definition.d.ts.map b/@types/lib/metadataTypes/definitions/Role.definition.d.ts.map new file mode 100644 index 000000000..d8d9b3e4e --- /dev/null +++ b/@types/lib/metadataTypes/definitions/Role.definition.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"Role.definition.d.ts","sourceRoot":"","sources":["../../../../lib/metadataTypes/definitions/Role.definition.js"],"names":[],"mappings":""} \ No newline at end of file diff --git a/@types/lib/metadataTypes/definitions/Script.definition.d.ts b/@types/lib/metadataTypes/definitions/Script.definition.d.ts new file mode 100644 index 000000000..97bf1b897 --- /dev/null +++ b/@types/lib/metadataTypes/definitions/Script.definition.d.ts @@ -0,0 +1,165 @@ +declare namespace _default { + let bodyIteratorField: string; + let dependencies: string[]; + let dependencyGraph: any; + let folderType: string; + let hasExtended: boolean; + let idField: string; + let keyIsFixed: boolean; + let keyField: string; + let nameField: string; + let folderIdField: string; + let createdDateField: string; + let createdNameField: any; + let lastmodDateField: string; + let lastmodNameField: any; + let restPagination: boolean; + let type: string; + let typeDescription: string; + let typeRetrieveByDefault: boolean; + let typeCdpByDefault: boolean; + let typeName: string; + namespace fields { + namespace categoryId { + let isCreateable: boolean; + let isUpdateable: boolean; + let retrieving: boolean; + let template: boolean; + } + namespace createdBy { + let isCreateable_1: boolean; + export { isCreateable_1 as isCreateable }; + let isUpdateable_1: boolean; + export { isUpdateable_1 as isUpdateable }; + let retrieving_1: boolean; + export { retrieving_1 as retrieving }; + let template_1: boolean; + export { template_1 as template }; + } + namespace createdDate { + let isCreateable_2: boolean; + export { isCreateable_2 as isCreateable }; + let isUpdateable_2: boolean; + export { isUpdateable_2 as isUpdateable }; + let retrieving_2: boolean; + export { retrieving_2 as retrieving }; + let template_2: boolean; + export { template_2 as template }; + } + namespace description { + let isCreateable_3: boolean; + export { isCreateable_3 as isCreateable }; + let isUpdateable_3: boolean; + export { isUpdateable_3 as isUpdateable }; + let retrieving_3: boolean; + export { retrieving_3 as retrieving }; + let template_3: boolean; + export { template_3 as template }; + } + namespace folderLocationText { + let isCreateable_4: boolean; + export { isCreateable_4 as isCreateable }; + let isUpdateable_4: boolean; + export { isUpdateable_4 as isUpdateable }; + let retrieving_4: boolean; + export { retrieving_4 as retrieving }; + let template_4: boolean; + export { template_4 as template }; + } + namespace key { + let isCreateable_5: boolean; + export { isCreateable_5 as isCreateable }; + let isUpdateable_5: boolean; + export { isUpdateable_5 as isUpdateable }; + let retrieving_5: boolean; + export { retrieving_5 as retrieving }; + let template_5: boolean; + export { template_5 as template }; + } + namespace modifiedBy { + let isCreateable_6: boolean; + export { isCreateable_6 as isCreateable }; + let isUpdateable_6: boolean; + export { isUpdateable_6 as isUpdateable }; + let retrieving_6: boolean; + export { retrieving_6 as retrieving }; + let template_6: boolean; + export { template_6 as template }; + } + namespace modifiedDate { + let isCreateable_7: boolean; + export { isCreateable_7 as isCreateable }; + let isUpdateable_7: boolean; + export { isUpdateable_7 as isUpdateable }; + let retrieving_7: boolean; + export { retrieving_7 as retrieving }; + let template_7: boolean; + export { template_7 as template }; + } + namespace name { + let isCreateable_8: boolean; + export { isCreateable_8 as isCreateable }; + let isUpdateable_8: boolean; + export { isUpdateable_8 as isUpdateable }; + let retrieving_8: boolean; + export { retrieving_8 as retrieving }; + let template_8: boolean; + export { template_8 as template }; + } + namespace script { + let isCreateable_9: boolean; + export { isCreateable_9 as isCreateable }; + let isUpdateable_9: boolean; + export { isUpdateable_9 as isUpdateable }; + let retrieving_9: boolean; + export { retrieving_9 as retrieving }; + let template_9: boolean; + export { template_9 as template }; + } + namespace ssjsActivityId { + let isCreateable_10: boolean; + export { isCreateable_10 as isCreateable }; + let isUpdateable_10: boolean; + export { isUpdateable_10 as isUpdateable }; + let retrieving_10: boolean; + export { retrieving_10 as retrieving }; + let template_10: boolean; + export { template_10 as template }; + } + namespace status { + let isCreateable_11: boolean; + export { isCreateable_11 as isCreateable }; + let isUpdateable_11: boolean; + export { isUpdateable_11 as isUpdateable }; + let retrieving_11: boolean; + export { retrieving_11 as retrieving }; + let template_11: boolean; + export { template_11 as template }; + } + namespace statusId { + let isCreateable_12: boolean; + export { isCreateable_12 as isCreateable }; + let isUpdateable_12: boolean; + export { isUpdateable_12 as isUpdateable }; + let retrieving_12: boolean; + export { retrieving_12 as retrieving }; + let template_12: boolean; + export { template_12 as template }; + } + namespace parentCategoryId { + let isCreateable_13: boolean; + export { isCreateable_13 as isCreateable }; + let isUpdateable_13: boolean; + export { isUpdateable_13 as isUpdateable }; + let retrieving_13: boolean; + export { retrieving_13 as retrieving }; + let template_13: boolean; + export { template_13 as template }; + } + namespace r__folder_Path { + let skipValidation: boolean; + } + } +} +export default _default; +//# sourceMappingURL=Script.definition.d.ts.map \ No newline at end of file diff --git a/@types/lib/metadataTypes/definitions/Script.definition.d.ts.map b/@types/lib/metadataTypes/definitions/Script.definition.d.ts.map new file mode 100644 index 000000000..49943a227 --- /dev/null +++ b/@types/lib/metadataTypes/definitions/Script.definition.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"Script.definition.d.ts","sourceRoot":"","sources":["../../../../lib/metadataTypes/definitions/Script.definition.js"],"names":[],"mappings":""} \ No newline at end of file diff --git a/@types/lib/metadataTypes/definitions/SendClassification.definition.d.ts b/@types/lib/metadataTypes/definitions/SendClassification.definition.d.ts new file mode 100644 index 000000000..d41787eb1 --- /dev/null +++ b/@types/lib/metadataTypes/definitions/SendClassification.definition.d.ts @@ -0,0 +1,155 @@ +declare namespace _default { + let bodyIteratorField: string; + let dependencies: string[]; + namespace dependencyGraph { + let senderProfile: string[]; + } + let filter: {}; + let hasExtended: boolean; + let idField: string; + let keyField: string; + let keyIsFixed: boolean; + let maxKeyLength: number; + let nameField: string; + let createdDateField: string; + let createdNameField: any; + let lastmodDateField: string; + let lastmodNameField: any; + let restPagination: boolean; + let type: string; + let typeDescription: string; + let typeRetrieveByDefault: boolean; + let typeCdpByDefault: boolean; + let typeName: string; + namespace sendClassificationTypeMapping { + let Commercial: string; + let Transactional: string; + } + let fields: { + 'Client.ID': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + CreatedDate: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + ModifiedDate: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + CustomerKey: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + ObjectID: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + Name: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + Description: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + PartnerKey: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + PartnerProperties: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + ArchiveEmail: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'DeliveryProfile.CustomerKey': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'DeliveryProfile.PartnerKey': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'DeliveryProfile.ObjectID': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + HonorPublicationListOptOutsForTransactionalSends: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + SendClassificationType: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'SenderProfile.CustomerKey': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'SenderProfile.PartnerKey': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'SenderProfile.ObjectID': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + SendPriority: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + c__classification: { + skipValidation: boolean; + }; + r__deliveryProfile_key: { + skipValidation: boolean; + }; + r__senderProfile_key: { + skipValidation: boolean; + }; + }; +} +export default _default; +//# sourceMappingURL=SendClassification.definition.d.ts.map \ No newline at end of file diff --git a/@types/lib/metadataTypes/definitions/SendClassification.definition.d.ts.map b/@types/lib/metadataTypes/definitions/SendClassification.definition.d.ts.map new file mode 100644 index 000000000..41098cc77 --- /dev/null +++ b/@types/lib/metadataTypes/definitions/SendClassification.definition.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"SendClassification.definition.d.ts","sourceRoot":"","sources":["../../../../lib/metadataTypes/definitions/SendClassification.definition.js"],"names":[],"mappings":""} \ No newline at end of file diff --git a/@types/lib/metadataTypes/definitions/SenderProfile.definition.d.ts b/@types/lib/metadataTypes/definitions/SenderProfile.definition.d.ts new file mode 100644 index 000000000..088ea032f --- /dev/null +++ b/@types/lib/metadataTypes/definitions/SenderProfile.definition.d.ts @@ -0,0 +1,220 @@ +declare namespace _default { + let bodyIteratorField: string; + let dependencies: string[]; + namespace dependencyGraph { + let domainVerification: string[]; + } + let filter: {}; + let hasExtended: boolean; + let idField: string; + let keyField: string; + let keyIsFixed: boolean; + let maxKeyLength: number; + let nameField: string; + let createdDateField: string; + let createdNameField: string; + let lastmodDateField: string; + let lastmodNameField: string; + let restPagination: boolean; + let type: string; + let typeDescription: string; + let typeRetrieveByDefault: boolean; + let typeCdpByDefault: boolean; + let typeName: string; + let fields: { + 'Client.ID': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'Client.CreatedBy': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'Client.ModifiedBy': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + createdBy: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: any; + template: boolean; + }; + modifiedBy: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: any; + template: boolean; + }; + CreatedDate: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + ModifiedDate: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + CustomerKey: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + ObjectID: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + Name: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + Description: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + PartnerKey: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + PartnerProperties: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + AutoForwardToEmailAddress: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + AutoForwardToName: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'AutoForwardTriggeredSend.ObjectID': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + AutoReply: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'AutoReplyTriggeredSend.ObjectID': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + DataRetentionPeriodLength: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + DataRetentionPeriodUnitOfMeasure: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + DirectForward: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + FallbackFromAddress: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + FromAddress: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + FromName: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + ID: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'ReplyManagementRuleSet.ObjectID': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'RMMRuleCollection.ObjectID': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + ReplyToAddress: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + ReplyToDisplayName: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + SenderHeaderEmailAddress: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + SenderHeaderName: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + UseDefaultRMMRules: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + }; +} +export default _default; +//# sourceMappingURL=SenderProfile.definition.d.ts.map \ No newline at end of file diff --git a/@types/lib/metadataTypes/definitions/SenderProfile.definition.d.ts.map b/@types/lib/metadataTypes/definitions/SenderProfile.definition.d.ts.map new file mode 100644 index 000000000..56a95021e --- /dev/null +++ b/@types/lib/metadataTypes/definitions/SenderProfile.definition.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"SenderProfile.definition.d.ts","sourceRoot":"","sources":["../../../../lib/metadataTypes/definitions/SenderProfile.definition.js"],"names":[],"mappings":""} \ No newline at end of file diff --git a/@types/lib/metadataTypes/definitions/TransactionalEmail.definition.d.ts b/@types/lib/metadataTypes/definitions/TransactionalEmail.definition.d.ts new file mode 100644 index 000000000..e8264350c --- /dev/null +++ b/@types/lib/metadataTypes/definitions/TransactionalEmail.definition.d.ts @@ -0,0 +1,182 @@ +declare namespace _default { + let bodyIteratorField: string; + let dependencies: string[]; + namespace dependencyGraph { + let asset: string[]; + let dataExtension: string[]; + let list: string[]; + let journey: string[]; + let sendClassification: string[]; + } + let hasExtended: boolean; + let idField: string; + let keyIsFixed: boolean; + let keyField: string; + let nameField: string; + let createdDateField: string; + let createdNameField: any; + let lastmodDateField: string; + let lastmodNameField: any; + let restPagination: boolean; + let restPageSize: number; + let maxKeyLength: number; + let type: string; + let typeDescription: string; + let typeRetrieveByDefault: boolean; + let typeCdpByDefault: boolean; + let typeName: string; + let fields: { + name: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + definitionKey: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + description: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + requestId: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + definitionId: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + status: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + createdDate: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + modifiedDate: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + classification: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'content.customerKey': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'subscriptions.dataExtension': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'subscriptions.r__dataExtension_key': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'subscriptions.list': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'subscriptions.r__list_PathName': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'subscriptions.autoAddSubscriber': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'subscriptions.updateSubscriber': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'options.trackLinks': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'options.cc': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'options.bcc': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'options.createJourney': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + journey: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'journey.interactionKey': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + r__asset_key: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + r__journey_key: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + r__sendClassification_key: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + }; +} +export default _default; +//# sourceMappingURL=TransactionalEmail.definition.d.ts.map \ No newline at end of file diff --git a/@types/lib/metadataTypes/definitions/TransactionalEmail.definition.d.ts.map b/@types/lib/metadataTypes/definitions/TransactionalEmail.definition.d.ts.map new file mode 100644 index 000000000..375a490ac --- /dev/null +++ b/@types/lib/metadataTypes/definitions/TransactionalEmail.definition.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"TransactionalEmail.definition.d.ts","sourceRoot":"","sources":["../../../../lib/metadataTypes/definitions/TransactionalEmail.definition.js"],"names":[],"mappings":""} \ No newline at end of file diff --git a/@types/lib/metadataTypes/definitions/TransactionalMessage.definition.d.ts b/@types/lib/metadataTypes/definitions/TransactionalMessage.definition.d.ts new file mode 100644 index 000000000..2200d917d --- /dev/null +++ b/@types/lib/metadataTypes/definitions/TransactionalMessage.definition.d.ts @@ -0,0 +1,101 @@ +declare namespace _default { + let bodyIteratorField: string; + let dependencies: any[]; + let dependencyGraph: any; + let hasExtended: boolean; + let idField: string; + let keyIsFixed: boolean; + let keyField: string; + let nameField: string; + let createdDateField: string; + let createdNameField: any; + let lastmodDateField: string; + let lastmodNameField: any; + let restPagination: boolean; + let restPageSize: number; + let type: string; + let typeDescription: string; + let typeRetrieveByDefault: boolean; + let typeCdpByDefault: boolean; + let typeName: string; + namespace fields { + namespace name { + let isCreateable: boolean; + let isUpdateable: boolean; + let retrieving: boolean; + let template: boolean; + } + namespace definitionKey { + let isCreateable_1: boolean; + export { isCreateable_1 as isCreateable }; + let isUpdateable_1: boolean; + export { isUpdateable_1 as isUpdateable }; + let retrieving_1: boolean; + export { retrieving_1 as retrieving }; + let template_1: boolean; + export { template_1 as template }; + } + namespace description { + let isCreateable_2: boolean; + export { isCreateable_2 as isCreateable }; + let isUpdateable_2: boolean; + export { isUpdateable_2 as isUpdateable }; + let retrieving_2: boolean; + export { retrieving_2 as retrieving }; + let template_2: boolean; + export { template_2 as template }; + } + namespace requestId { + let isCreateable_3: boolean; + export { isCreateable_3 as isCreateable }; + let isUpdateable_3: boolean; + export { isUpdateable_3 as isUpdateable }; + let retrieving_3: boolean; + export { retrieving_3 as retrieving }; + let template_3: boolean; + export { template_3 as template }; + } + namespace definitionId { + let isCreateable_4: boolean; + export { isCreateable_4 as isCreateable }; + let isUpdateable_4: boolean; + export { isUpdateable_4 as isUpdateable }; + let retrieving_4: boolean; + export { retrieving_4 as retrieving }; + let template_4: boolean; + export { template_4 as template }; + } + namespace status { + let isCreateable_5: boolean; + export { isCreateable_5 as isCreateable }; + let isUpdateable_5: boolean; + export { isUpdateable_5 as isUpdateable }; + let retrieving_5: boolean; + export { retrieving_5 as retrieving }; + let template_5: boolean; + export { template_5 as template }; + } + namespace createdDate { + let isCreateable_6: boolean; + export { isCreateable_6 as isCreateable }; + let isUpdateable_6: boolean; + export { isUpdateable_6 as isUpdateable }; + let retrieving_6: boolean; + export { retrieving_6 as retrieving }; + let template_6: boolean; + export { template_6 as template }; + } + namespace modifiedDate { + let isCreateable_7: boolean; + export { isCreateable_7 as isCreateable }; + let isUpdateable_7: boolean; + export { isUpdateable_7 as isUpdateable }; + let retrieving_7: boolean; + export { retrieving_7 as retrieving }; + let template_7: boolean; + export { template_7 as template }; + } + } +} +export default _default; +//# sourceMappingURL=TransactionalMessage.definition.d.ts.map \ No newline at end of file diff --git a/@types/lib/metadataTypes/definitions/TransactionalMessage.definition.d.ts.map b/@types/lib/metadataTypes/definitions/TransactionalMessage.definition.d.ts.map new file mode 100644 index 000000000..b5152e71b --- /dev/null +++ b/@types/lib/metadataTypes/definitions/TransactionalMessage.definition.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"TransactionalMessage.definition.d.ts","sourceRoot":"","sources":["../../../../lib/metadataTypes/definitions/TransactionalMessage.definition.js"],"names":[],"mappings":""} \ No newline at end of file diff --git a/@types/lib/metadataTypes/definitions/TransactionalPush.definition.d.ts b/@types/lib/metadataTypes/definitions/TransactionalPush.definition.d.ts new file mode 100644 index 000000000..1c5326970 --- /dev/null +++ b/@types/lib/metadataTypes/definitions/TransactionalPush.definition.d.ts @@ -0,0 +1,123 @@ +declare namespace _default { + let bodyIteratorField: string; + let dependencies: string[]; + namespace dependencyGraph { + let asset: string[]; + } + let hasExtended: boolean; + let idField: string; + let keyIsFixed: boolean; + let keyField: string; + let nameField: string; + let createdDateField: string; + let createdNameField: any; + let lastmodDateField: string; + let lastmodNameField: any; + let restPagination: boolean; + let restPageSize: number; + let type: string; + let typeDescription: string; + let typeRetrieveByDefault: boolean; + let typeCdpByDefault: boolean; + let typeName: string; + let fields: { + name: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + definitionKey: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + description: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + requestId: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + definitionId: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + status: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + createdDate: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + modifiedDate: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'content.customerKey': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + r__asset_key: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'options.badge': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'options.sound': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'options.customKeys': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'options.customKeys[].value': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'options.customKeys[].key': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + applicationId: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + }; +} +export default _default; +//# sourceMappingURL=TransactionalPush.definition.d.ts.map \ No newline at end of file diff --git a/@types/lib/metadataTypes/definitions/TransactionalPush.definition.d.ts.map b/@types/lib/metadataTypes/definitions/TransactionalPush.definition.d.ts.map new file mode 100644 index 000000000..e3b3bee6e --- /dev/null +++ b/@types/lib/metadataTypes/definitions/TransactionalPush.definition.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"TransactionalPush.definition.d.ts","sourceRoot":"","sources":["../../../../lib/metadataTypes/definitions/TransactionalPush.definition.js"],"names":[],"mappings":""} \ No newline at end of file diff --git a/@types/lib/metadataTypes/definitions/TransactionalSMS.definition.d.ts b/@types/lib/metadataTypes/definitions/TransactionalSMS.definition.d.ts new file mode 100644 index 000000000..9413960cf --- /dev/null +++ b/@types/lib/metadataTypes/definitions/TransactionalSMS.definition.d.ts @@ -0,0 +1,118 @@ +declare namespace _default { + let bodyIteratorField: string; + let dependencies: string[]; + namespace dependencyGraph { + let mobileKeyword: string[]; + let mobileCode: string[]; + } + let hasExtended: boolean; + let idField: string; + let keyIsFixed: boolean; + let keyField: string; + let nameField: string; + let createdDateField: string; + let createdNameField: any; + let lastmodDateField: string; + let lastmodNameField: any; + let restPagination: boolean; + let restPageSize: number; + let type: string; + let typeDescription: string; + let typeRetrieveByDefault: boolean; + let typeCdpByDefault: boolean; + let typeName: string; + let fields: { + name: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + definitionKey: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + description: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + requestId: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + definitionId: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + status: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + createdDate: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + modifiedDate: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'content.message': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'subscriptions.shortCode': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'subscriptions.countryCode': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'subscriptions.autoAddSubscriber': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'subscriptions.updateSubscriber': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'subscriptions.keyword': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'subscriptions.r__mobileKeyword_key': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + }; +} +export default _default; +//# sourceMappingURL=TransactionalSMS.definition.d.ts.map \ No newline at end of file diff --git a/@types/lib/metadataTypes/definitions/TransactionalSMS.definition.d.ts.map b/@types/lib/metadataTypes/definitions/TransactionalSMS.definition.d.ts.map new file mode 100644 index 000000000..c5da627ba --- /dev/null +++ b/@types/lib/metadataTypes/definitions/TransactionalSMS.definition.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"TransactionalSMS.definition.d.ts","sourceRoot":"","sources":["../../../../lib/metadataTypes/definitions/TransactionalSMS.definition.js"],"names":[],"mappings":""} \ No newline at end of file diff --git a/@types/lib/metadataTypes/definitions/TriggeredSend.definition.d.ts b/@types/lib/metadataTypes/definitions/TriggeredSend.definition.d.ts new file mode 100644 index 000000000..09aae4b33 --- /dev/null +++ b/@types/lib/metadataTypes/definitions/TriggeredSend.definition.d.ts @@ -0,0 +1,570 @@ +declare namespace _default { + let bodyIteratorField: string; + let dependencies: string[]; + namespace dependencyGraph { + let asset: string[]; + let list: string[]; + let sendClassification: string[]; + let senderProfile: string[]; + } + namespace filter { + let r__folder_Path: string[]; + } + let folderType: string; + let hasExtended: boolean; + let idField: string; + let keepId: boolean; + let keyIsFixed: boolean; + let keyField: string; + let nameField: string; + let folderIdField: string; + let createdDateField: string; + let createdNameField: any; + let lastmodDateField: string; + let lastmodNameField: any; + let restPagination: any; + let maxKeyLength: number; + let type: string; + let soapType: string; + let typeDescription: string; + let typeRetrieveByDefault: boolean; + let typeCdpByDefault: boolean; + let typeName: string; + namespace priorityMapping { + let High: number; + let Medium: number; + let Low: number; + } + let fields: { + AllowedSlots: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + AutoAddSubscribers: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + AutoUpdateSubscribers: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + BatchInterval: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + BccEmail: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + CategoryID: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + CCEmail: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + 'Client.ID': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + 'Client.PartnerClientKey': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + CorrelationID: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + CreatedDate: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + CustomerKey: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + DataSchemas: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + 'DeliveryProfile.CustomerKey': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + 'DeliveryProfile.ObjectID': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + Description: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + DisableOnEmailBuildError: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + DomainType: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + DynamicEmailSubject: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + 'Email.ID': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + 'Email.PartnerKey': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + 'Email.ObjectID': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + EmailSubject: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + ExclusionFilter: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + ExclusionListCollection: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + 'FooterContentArea.ID': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + FooterSalutationSource: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + FromAddress: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + FromName: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + 'HeaderContentArea.ID': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + HeaderSalutationSource: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + ID: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + InteractionObjectID: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + IsAlwaysOn: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + IsMultipart: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + IsPlatformObject: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + IsSendLogging: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + IsWrapped: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + KeepExistingEmailSubject: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + Keyword: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + 'List.ID': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + 'List.PartnerKey': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + 'List.ObjectID': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + ModifiedDate: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + Name: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + NewSlotTrigger: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + ObjectID: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + ObjectState: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + OptionFlags: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + OptionFlagsUpdateMask: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + OptionVersion: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + Owner: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + PartnerKey: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + PartnerProperties: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + PreHeader: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + Priority: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + 'PrivateDomain.ObjectID': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + 'PrivateDomain.PartnerKey': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + 'PrivateIP.ID': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + 'PrivateIP.PartnerKey': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + RefreshContent: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + ReplyToAddress: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + ReplyToDisplayName: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + RequestExpirationSeconds: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + 'SendClassification.CustomerKey': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + 'SendClassification.ObjectID': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + 'SendClassification.PartnerKey': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + 'SenderProfile.CustomerKey': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + 'SenderProfile.ObjectID': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + 'SenderProfile.PartnerKey': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + SendLimit: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + SendSourceCustomerKey: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + SendSourceDataExtension: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + SendWindowClose: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + SendWindowDelete: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + SendWindowOpen: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + SourceAddressType: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + SuppressTracking: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + TestEmailAddr: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + TriggeredSendClass: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + TriggeredSendStatus: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + TriggeredSendSubClass: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + TriggeredSendType: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + TriggeredSendVersionID: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + r__asset_name_readOnly: { + skipValidation: boolean; + }; + r__asset_key: { + skipValidation: boolean; + }; + r__email_name: { + skipValidation: boolean; + }; + r__folder_Path: { + skipValidation: boolean; + }; + r__list_PathName: { + skipValidation: boolean; + }; + c__priority: { + skipValidation: boolean; + }; + r__sendClassification_key: { + skipValidation: boolean; + }; + r__senderProfile_key: { + skipValidation: boolean; + }; + }; +} +export default _default; +//# sourceMappingURL=TriggeredSend.definition.d.ts.map \ No newline at end of file diff --git a/@types/lib/metadataTypes/definitions/TriggeredSend.definition.d.ts.map b/@types/lib/metadataTypes/definitions/TriggeredSend.definition.d.ts.map new file mode 100644 index 000000000..d95c59801 --- /dev/null +++ b/@types/lib/metadataTypes/definitions/TriggeredSend.definition.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"TriggeredSend.definition.d.ts","sourceRoot":"","sources":["../../../../lib/metadataTypes/definitions/TriggeredSend.definition.js"],"names":[],"mappings":""} \ No newline at end of file diff --git a/@types/lib/metadataTypes/definitions/TriggeredSendSummary.definition.d.ts b/@types/lib/metadataTypes/definitions/TriggeredSendSummary.definition.d.ts new file mode 100644 index 000000000..091aba4aa --- /dev/null +++ b/@types/lib/metadataTypes/definitions/TriggeredSendSummary.definition.d.ts @@ -0,0 +1,208 @@ +declare namespace _default { + let bodyIteratorField: string; + let dependencies: string[]; + namespace dependencyGraph { + let triggeredSend: string[]; + } + let filter: {}; + let hasExtended: boolean; + let idField: string; + let keepId: boolean; + let keyIsFixed: boolean; + let keyField: string; + let nameField: string; + let folderIdField: string; + let createdDateField: any; + let createdNameField: any; + let lastmodDateField: any; + let lastmodNameField: any; + let restPagination: any; + let maxKeyLength: number; + let type: string; + let soapType: string; + let typeDescription: string; + let typeRetrieveByDefault: boolean; + let typeCdpByDefault: boolean; + let typeName: string; + let fields: { + Bounces: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + Clicks: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + 'Client.ID': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + Conversions: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + CustomerKey: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + FTAFEmailsSent: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + FTAFOptIns: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + FTAFRequests: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + ID: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + InProcess: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + NotSentDueToError: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + NotSentDueToOptOut: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + NotSentDueToUndeliverable: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + ObjectID: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + Opens: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + OptOuts: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + Owner: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + PartnerKey: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + PartnerProperties: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + Queued: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + Sent: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + SurveyResponses: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + UniqueClicks: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + UniqueConversions: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + UniqueOpens: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + CorrelationID: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + templating: boolean; + }; + CreatedDate: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; /** Listed in the type documentation but not retrievable */ + templating: boolean; + }; + ModifiedDate: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; /** Listed in the type documentation but not retrievable */ + templating: boolean; + }; + r__triggeredSend_name: { + skipValidation: boolean; + }; + r__triggeredSend_key: { + skipValidation: boolean; + }; + r__folder_Path: { + skipValidation: boolean; + }; + }; +} +export default _default; +//# sourceMappingURL=TriggeredSendSummary.definition.d.ts.map \ No newline at end of file diff --git a/@types/lib/metadataTypes/definitions/TriggeredSendSummary.definition.d.ts.map b/@types/lib/metadataTypes/definitions/TriggeredSendSummary.definition.d.ts.map new file mode 100644 index 000000000..c89c66478 --- /dev/null +++ b/@types/lib/metadataTypes/definitions/TriggeredSendSummary.definition.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"TriggeredSendSummary.definition.d.ts","sourceRoot":"","sources":["../../../../lib/metadataTypes/definitions/TriggeredSendSummary.definition.js"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iCAqM8B,2DAA2D;;;;;;iCAM3D,2DAA2D"} \ No newline at end of file diff --git a/@types/lib/metadataTypes/definitions/User.definition.d.ts b/@types/lib/metadataTypes/definitions/User.definition.d.ts new file mode 100644 index 000000000..5d28fd49a --- /dev/null +++ b/@types/lib/metadataTypes/definitions/User.definition.d.ts @@ -0,0 +1,425 @@ +declare namespace _default { + let bodyIteratorField: string; + let dependencies: string[]; + let dependencyGraph: {}; + let folderType: any; + let hasExtended: boolean; + let idField: string; + let keepId: boolean; + let keyIsFixed: boolean; + let keyField: string; + let nameField: string; + let createdDateField: string; + let createdNameField: any; + let lastmodDateField: string; + let lastmodNameField: string; + let maxKeyLength: number; + let type: string; + let soapType: string; + let typeDescription: string; + let typeName: string; + let typeRetrieveByDefault: boolean; + let typeCdpByDefault: boolean; + let documentInOneFile: boolean; + let stringifyFieldsBeforeTemplate: string[]; + let fields: { + AccountUserID: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + ActiveFlag: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + AssociatedBusinessUnits: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + BusinessUnit: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + ChallengeAnswer: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + ChallengePhrase: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'Client.ID': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'Client.ModifiedBy': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'Client.PartnerClientKey': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + CorrelationID: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + CreatedDate: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + CustomerKey: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + DefaultApplication: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + DefaultBusinessUnit: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + DefaultBusinessUnitObject: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + Delete: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + Email: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + ID: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + IsAPIUser: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + IsLocked: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'LanguageLocale.LocaleCode': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + LastSuccessfulLogin: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'Locale.LocaleCode': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'Locale.ObjectID': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'Locale.PartnerKey': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + ModifiedDate: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + MustChangePassword: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + Name: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + NotificationEmailAddress: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + ObjectID: { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: any; + }; + ObjectState: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + Owner: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + PartnerKey: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + PartnerProperties: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + Password: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + Roles: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'Roles.Role': { + skipValidation: boolean; + }; + 'Roles.Role[].Client': { + skipValidation: boolean; + }; + SsoIdentities: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'SsoIdentities.SsoIdentity': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'SsoIdentities.SsoIdentity[].IsActive': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'SsoIdentities.SsoIdentity[].FederatedID': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'TimeZone.ID': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'TimeZone.Name': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'TimeZone.ObjectID': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'TimeZone.PartnerKey': { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + Unlock: { + skipValidation: boolean; + isCreateable: boolean; + isUpdateable: boolean; + template: boolean; + }; + UserID: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + UserPermissions: { + isCreateable: boolean; + isUpdateable: boolean; + retrieving: boolean; + template: boolean; + }; + 'UserPermissions.PartnerKey': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: boolean; + }; + 'UserPermissions.ID': { + skipValidation: boolean; + }; + 'UserPermissions.ObjectID': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: boolean; + }; + 'UserPermissions.Name': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: boolean; + }; + 'UserPermissions.Value': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: boolean; + }; + 'UserPermissions.Description': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: boolean; + }; + 'UserPermissions.Delete': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: boolean; + }; + 'UserPermissions[].PartnerKey': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: boolean; + }; + 'UserPermissions[].ID': { + skipValidation: boolean; + }; + 'UserPermissions[].ObjectID': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: boolean; + }; + 'UserPermissions[].Name': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: boolean; + }; + 'UserPermissions[].Value': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: boolean; + }; + 'UserPermissions[].Description': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: boolean; + }; + 'UserPermissions[].Delete': { + isCreateable: any; + isUpdateable: any; + retrieving: boolean; + template: boolean; + }; + c__type: { + isCreateable: boolean; + isUpdateable: boolean; + retrieve: any; + template: boolean; + }; + c__AssociatedBusinessUnits: { + skipValidation: boolean; + }; + c__RoleNamesGlobal: { + skipValidation: boolean; + }; + c__LocaleCode: { + skipValidation: boolean; + }; + c__TimeZoneName: { + skipValidation: boolean; + }; + c__AccountUserID: { + isCreateable: boolean; + isUpdateable: boolean; + retrieve: any; + template: boolean; + }; + c__IsLocked_readOnly: { + isCreateable: boolean; + isUpdateable: boolean; + retrieve: any; + template: boolean; + }; + }; +} +export default _default; +//# sourceMappingURL=User.definition.d.ts.map \ No newline at end of file diff --git a/@types/lib/metadataTypes/definitions/User.definition.d.ts.map b/@types/lib/metadataTypes/definitions/User.definition.d.ts.map new file mode 100644 index 000000000..3e9c3e5d8 --- /dev/null +++ b/@types/lib/metadataTypes/definitions/User.definition.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"User.definition.d.ts","sourceRoot":"","sources":["../../../../lib/metadataTypes/definitions/User.definition.js"],"names":[],"mappings":""} \ No newline at end of file diff --git a/@types/lib/metadataTypes/definitions/Verification.definition.d.ts b/@types/lib/metadataTypes/definitions/Verification.definition.d.ts new file mode 100644 index 000000000..f54f5084b --- /dev/null +++ b/@types/lib/metadataTypes/definitions/Verification.definition.d.ts @@ -0,0 +1,143 @@ +declare namespace _default { + let bodyIteratorField: string; + let dependencies: string[]; + namespace dependencyGraph { + let dataExtension: string[]; + } + let hasExtended: boolean; + let idField: string; + let keyIsFixed: boolean; + let keyField: string; + let createdDateField: any; + let createdNameField: string; + let lastmodDateField: any; + let lastmodNameField: any; + let nameField: string; + let restPagination: boolean; + let maxKeyLength: number; + let type: string; + let typeDescription: string; + let typeRetrieveByDefault: boolean; + let typeCdpByDefault: boolean; + let typeName: string; + namespace fields { + namespace createdBy { + let isCreateable: boolean; + let isUpdateable: boolean; + let retrieving: boolean; + let template: boolean; + } + namespace dataVerificationDefinitionId { + let isCreateable_1: boolean; + export { isCreateable_1 as isCreateable }; + let isUpdateable_1: boolean; + export { isUpdateable_1 as isUpdateable }; + let retrieving_1: boolean; + export { retrieving_1 as retrieving }; + let template_1: boolean; + export { template_1 as template }; + } + namespace notificationEmailAddress { + let isCreateable_2: boolean; + export { isCreateable_2 as isCreateable }; + let isUpdateable_2: boolean; + export { isUpdateable_2 as isUpdateable }; + let retrieving_2: boolean; + export { retrieving_2 as retrieving }; + let template_2: boolean; + export { template_2 as template }; + } + namespace notificationEmailMessage { + let isCreateable_3: boolean; + export { isCreateable_3 as isCreateable }; + let isUpdateable_3: boolean; + export { isUpdateable_3 as isUpdateable }; + let retrieving_3: boolean; + export { retrieving_3 as retrieving }; + let template_3: boolean; + export { template_3 as template }; + } + namespace shouldEmailOnFailure { + let isCreateable_4: boolean; + export { isCreateable_4 as isCreateable }; + let isUpdateable_4: boolean; + export { isUpdateable_4 as isUpdateable }; + let retrieving_4: boolean; + export { retrieving_4 as retrieving }; + let template_4: boolean; + export { template_4 as template }; + } + namespace shouldStopOnFailure { + let isCreateable_5: boolean; + export { isCreateable_5 as isCreateable }; + let isUpdateable_5: boolean; + export { isUpdateable_5 as isUpdateable }; + let retrieving_5: boolean; + export { retrieving_5 as retrieving }; + let template_5: boolean; + export { template_5 as template }; + } + namespace targetObjectId { + let isCreateable_6: boolean; + export { isCreateable_6 as isCreateable }; + let isUpdateable_6: boolean; + export { isUpdateable_6 as isUpdateable }; + let retrieving_6: boolean; + export { retrieving_6 as retrieving }; + let template_6: boolean; + export { template_6 as template }; + } + namespace value1 { + let isCreateable_7: boolean; + export { isCreateable_7 as isCreateable }; + let isUpdateable_7: boolean; + export { isUpdateable_7 as isUpdateable }; + let retrieving_7: boolean; + export { retrieving_7 as retrieving }; + let template_7: boolean; + export { template_7 as template }; + } + namespace value2 { + let isCreateable_8: boolean; + export { isCreateable_8 as isCreateable }; + let isUpdateable_8: boolean; + export { isUpdateable_8 as isUpdateable }; + let retrieving_8: boolean; + export { retrieving_8 as retrieving }; + let template_8: boolean; + export { template_8 as template }; + } + namespace verificationType { + let isCreateable_9: boolean; + export { isCreateable_9 as isCreateable }; + let isUpdateable_9: boolean; + export { isUpdateable_9 as isUpdateable }; + let retrieving_9: boolean; + export { retrieving_9 as retrieving }; + let template_9: boolean; + export { template_9 as template }; + } + namespace r__dataExtension_key { + let isCreateable_10: boolean; + export { isCreateable_10 as isCreateable }; + let isUpdateable_10: boolean; + export { isUpdateable_10 as isUpdateable }; + let retrieving_10: boolean; + export { retrieving_10 as retrieving }; + let template_10: boolean; + export { template_10 as template }; + } + namespace c__automation_step { + let isCreateable_11: boolean; + export { isCreateable_11 as isCreateable }; + let isUpdateable_11: boolean; + export { isUpdateable_11 as isUpdateable }; + let retrieving_11: boolean; + export { retrieving_11 as retrieving }; + let template_11: boolean; + export { template_11 as template }; + } + } +} +export default _default; +//# sourceMappingURL=Verification.definition.d.ts.map \ No newline at end of file diff --git a/@types/lib/metadataTypes/definitions/Verification.definition.d.ts.map b/@types/lib/metadataTypes/definitions/Verification.definition.d.ts.map new file mode 100644 index 000000000..8d750fb90 --- /dev/null +++ b/@types/lib/metadataTypes/definitions/Verification.definition.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"Verification.definition.d.ts","sourceRoot":"","sources":["../../../../lib/metadataTypes/definitions/Verification.definition.js"],"names":[],"mappings":""} \ No newline at end of file diff --git a/@types/lib/retrieveChangelog.d.ts b/@types/lib/retrieveChangelog.d.ts new file mode 100644 index 000000000..c1441fa8d --- /dev/null +++ b/@types/lib/retrieveChangelog.d.ts @@ -0,0 +1,3 @@ +#!/usr/bin/env node +export {}; +//# sourceMappingURL=retrieveChangelog.d.ts.map \ No newline at end of file diff --git a/@types/lib/retrieveChangelog.d.ts.map b/@types/lib/retrieveChangelog.d.ts.map new file mode 100644 index 000000000..ddb2b83b1 --- /dev/null +++ b/@types/lib/retrieveChangelog.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"retrieveChangelog.d.ts","sourceRoot":"","sources":["../../lib/retrieveChangelog.js"],"names":[],"mappings":""} \ No newline at end of file diff --git a/@types/lib/util/auth.d.ts b/@types/lib/util/auth.d.ts new file mode 100644 index 000000000..fdb865b75 --- /dev/null +++ b/@types/lib/util/auth.d.ts @@ -0,0 +1,42 @@ +export default Auth; +export type AuthObject = import("../../types/mcdev.d.js").AuthObject; +export type BuObject = import("../../types/mcdev.d.js").BuObject; +export type CodeExtract = import("../../types/mcdev.d.js").CodeExtract; +export type CodeExtractItem = import("../../types/mcdev.d.js").CodeExtractItem; +export type DeltaPkgItem = import("../../types/mcdev.d.js").DeltaPkgItem; +export type Mcdevrc = import("../../types/mcdev.d.js").Mcdevrc; +export type MetadataTypeItem = import("../../types/mcdev.d.js").MetadataTypeItem; +export type MetadataTypeItemDiff = import("../../types/mcdev.d.js").MetadataTypeItemDiff; +export type MetadataTypeItemObj = import("../../types/mcdev.d.js").MetadataTypeItemObj; +export type MetadataTypeMap = import("../../types/mcdev.d.js").MetadataTypeMap; +export type MetadataTypeMapObj = import("../../types/mcdev.d.js").MetadataTypeMapObj; +export type MultiMetadataTypeList = import("../../types/mcdev.d.js").MultiMetadataTypeList; +export type MultiMetadataTypeMap = import("../../types/mcdev.d.js").MultiMetadataTypeMap; +export type SoapRequestParams = import("../../types/mcdev.d.js").SoapRequestParams; +export type TemplateMap = import("../../types/mcdev.d.js").TemplateMap; +export type TypeKeyCombo = import("../../types/mcdev.d.js").TypeKeyCombo; +declare namespace Auth { + /** + * For each business unit, set up base credentials to be used. + * + * @param {AuthObject} authObject details for + * @param {string} credential of the instance + * @returns {Promise.<void>} - + */ + function saveCredential(authObject: AuthObject, credential: string): Promise<void>; + /** + * Returns an SDK instance to be used for API calls + * + * @param {BuObject} buObject information about current context + * @returns {SDK} auth object + */ + function getSDK(buObject: BuObject): SDK; + /** + * helper to clear all auth sessions + * + * @returns {void} + */ + function clearSessions(): void; +} +import SDK from 'sfmc-sdk'; +//# sourceMappingURL=auth.d.ts.map \ No newline at end of file diff --git a/@types/lib/util/auth.d.ts.map b/@types/lib/util/auth.d.ts.map new file mode 100644 index 000000000..5970ca91c --- /dev/null +++ b/@types/lib/util/auth.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../../../lib/util/auth.js"],"names":[],"mappings":";yBAMa,OAAO,wBAAwB,EAAE,UAAU;uBAC3C,OAAO,wBAAwB,EAAE,QAAQ;0BACzC,OAAO,wBAAwB,EAAE,WAAW;8BAC5C,OAAO,wBAAwB,EAAE,eAAe;2BAChD,OAAO,wBAAwB,EAAE,YAAY;sBAC7C,OAAO,wBAAwB,EAAE,OAAO;+BACxC,OAAO,wBAAwB,EAAE,gBAAgB;mCACjD,OAAO,wBAAwB,EAAE,oBAAoB;kCACrD,OAAO,wBAAwB,EAAE,mBAAmB;8BACpD,OAAO,wBAAwB,EAAE,eAAe;iCAChD,OAAO,wBAAwB,EAAE,kBAAkB;oCACnD,OAAO,wBAAwB,EAAE,qBAAqB;mCACtD,OAAO,wBAAwB,EAAE,oBAAoB;gCACrD,OAAO,wBAAwB,EAAE,iBAAiB;0BAClD,OAAO,wBAAwB,EAAE,WAAW;2BAC5C,OAAO,wBAAwB,EAAE,YAAY;;IAYtD;;;;;;OAMG;IACH,oCAJW,UAAU,cACV,MAAM,GACJ,OAAO,CAAE,IAAI,CAAC,CA2B1B;IAED;;;;;OAKG;IACH,0BAHW,QAAQ,GACN,GAAG,CAoBf;IAED;;;;OAIG;IACH,0BAFa,IAAI,CAKhB;;gBAnGW,UAAU"} \ No newline at end of file diff --git a/@types/lib/util/businessUnit.d.ts b/@types/lib/util/businessUnit.d.ts new file mode 100644 index 000000000..1cdb535ff --- /dev/null +++ b/@types/lib/util/businessUnit.d.ts @@ -0,0 +1,21 @@ +export default BusinessUnit; +export type AuthObject = import("../../types/mcdev.d.js").AuthObject; +export type BuObject = import("../../types/mcdev.d.js").BuObject; +export type CodeExtract = import("../../types/mcdev.d.js").CodeExtract; +export type CodeExtractItem = import("../../types/mcdev.d.js").CodeExtractItem; +export type DeltaPkgItem = import("../../types/mcdev.d.js").DeltaPkgItem; +export type Mcdevrc = import("../../types/mcdev.d.js").Mcdevrc; +export type MetadataTypeItem = import("../../types/mcdev.d.js").MetadataTypeItem; +export type MetadataTypeItemDiff = import("../../types/mcdev.d.js").MetadataTypeItemDiff; +export type MetadataTypeItemObj = import("../../types/mcdev.d.js").MetadataTypeItemObj; +export type MetadataTypeMap = import("../../types/mcdev.d.js").MetadataTypeMap; +export type MetadataTypeMapObj = import("../../types/mcdev.d.js").MetadataTypeMapObj; +export type MultiMetadataTypeList = import("../../types/mcdev.d.js").MultiMetadataTypeList; +export type MultiMetadataTypeMap = import("../../types/mcdev.d.js").MultiMetadataTypeMap; +export type SoapRequestParams = import("../../types/mcdev.d.js").SoapRequestParams; +export type TemplateMap = import("../../types/mcdev.d.js").TemplateMap; +export type TypeKeyCombo = import("../../types/mcdev.d.js").TypeKeyCombo; +declare namespace BusinessUnit { + function refreshBUProperties(properties: Mcdevrc, credentialsName: string): Promise<boolean>; +} +//# sourceMappingURL=businessUnit.d.ts.map \ No newline at end of file diff --git a/@types/lib/util/businessUnit.d.ts.map b/@types/lib/util/businessUnit.d.ts.map new file mode 100644 index 000000000..95e117c39 --- /dev/null +++ b/@types/lib/util/businessUnit.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"businessUnit.d.ts","sourceRoot":"","sources":["../../../lib/util/businessUnit.js"],"names":[],"mappings":";yBAOa,OAAO,wBAAwB,EAAE,UAAU;uBAC3C,OAAO,wBAAwB,EAAE,QAAQ;0BACzC,OAAO,wBAAwB,EAAE,WAAW;8BAC5C,OAAO,wBAAwB,EAAE,eAAe;2BAChD,OAAO,wBAAwB,EAAE,YAAY;sBAC7C,OAAO,wBAAwB,EAAE,OAAO;+BACxC,OAAO,wBAAwB,EAAE,gBAAgB;mCACjD,OAAO,wBAAwB,EAAE,oBAAoB;kCACrD,OAAO,wBAAwB,EAAE,mBAAmB;8BACpD,OAAO,wBAAwB,EAAE,eAAe;iCAChD,OAAO,wBAAwB,EAAE,kBAAkB;oCACnD,OAAO,wBAAwB,EAAE,qBAAqB;mCACtD,OAAO,wBAAwB,EAAE,oBAAoB;gCACrD,OAAO,wBAAwB,EAAE,iBAAiB;0BAClD,OAAO,wBAAwB,EAAE,WAAW;2BAC5C,OAAO,wBAAwB,EAAE,YAAY;;IAcjC,yCAJV,OAAO,mBACP,MAAM,GACJ,OAAO,CAAE,OAAO,CAAC,CAuF7B"} \ No newline at end of file diff --git a/@types/lib/util/cache.d.ts b/@types/lib/util/cache.d.ts new file mode 100644 index 000000000..a577ec760 --- /dev/null +++ b/@types/lib/util/cache.d.ts @@ -0,0 +1,77 @@ +declare namespace _default { + function initCache(buObject: BuObject): void; + function getCache(): MultiMetadataTypeMap; + function clearCache(mid?: number, type?: string): void; + function getByKey(type: string, key: string): MetadataTypeItem; + function setMetadata(type: string, metadataMap: MetadataTypeMap): void; + function mergeMetadata(type: string, metadataMap: MetadataTypeMap, overrideMID?: number): void; + /** + * standardized method for getting data from cache. + * + * @param {string} metadataType metadata type ie. query + * @param {string|number|boolean} searchValue unique identifier of metadata being looked for + * @param {string} searchField field name (key in object) which contains the unique identifer + * @param {string} returnField field which should be returned + * @param {number} [overrideMID] ignore currentMID and use alternative (for example parent MID) + * @param {boolean} caseInsensitive optional; if true, search is case insensitive + * @returns {string} value of specified field. Error is thrown if not found + */ + function searchForField(metadataType: string, searchValue: string | number | boolean, searchField: string, returnField: string, overrideMID?: number, caseInsensitive?: boolean): string; + /** + * helper for setFolderId + * + * @param {string} r__folder_Path folder path value + * @param {number} [overrideMID] ignore currentMID and use alternative (for example parent MID) + * @param {boolean} allowOtherBu getting folder from other BU; FALSE for folder parent search + * @returns {number} folder ID + */ + function getFolderId(r__folder_Path: string, overrideMID?: number, allowOtherBu?: boolean): number; + /** + * helper for setFolderId + * + * @param {string} r__folder_Path folder path value + * @param {number} [overrideMID] ignore currentMID and use alternative (for example parent MID) + * @param {boolean} allowOtherBu getting folder from other BU; FALSE for folder parent search + * @returns {object} folder item + */ + function getFolderByPath(r__folder_Path: string, overrideMID?: number, allowOtherBu?: boolean): object; + /** + * standardized method for getting data from cache - adapted for special case of lists + * ! keeping this in util/cache.js rather than in metadataTypes/List.js to avoid potential circular dependencies + * + * @param {string} searchValue unique identifier of metadata being looked for + * @param {'ObjectID'|'ID'|'CustomerKey'} searchField ObjectID:string(uuid), ID:numeric, CustomerKey:string(name + folder ID) + * @returns {string} unique folderPath/ListName combo of list + */ + function getListPathName(searchValue: string, searchField: "ObjectID" | "ID" | "CustomerKey"): string; + /** + * standardized method for getting data from cache - adapted for special case of lists + * ! keeping this in util/cache.js rather than in metadataTypes/List.js to avoid potential circular dependencies + * + * @param {string} listPathName folderPath/ListName combo of list + * @param {'ObjectID'|'ID'|'CustomerKey'|'ListName'} returnField ObjectID:string(uuid), ID:numeric, CustomerKey:string(name + folder ID) + * @returns {string} unique ObjectId of list + */ + function getListObjectId(listPathName: string, returnField: "ObjectID" | "ID" | "CustomerKey" | "ListName"): string; +} +export default _default; +export type AuthObject = import("../../types/mcdev.d.js").AuthObject; +export type BuObject = import("../../types/mcdev.d.js").BuObject; +export type Cache = import("../../types/mcdev.d.js").Cache; +export type CodeExtract = import("../../types/mcdev.d.js").CodeExtract; +export type CodeExtractItem = import("../../types/mcdev.d.js").CodeExtractItem; +export type DeltaPkgItem = import("../../types/mcdev.d.js").DeltaPkgItem; +export type Mcdevrc = import("../../types/mcdev.d.js").Mcdevrc; +export type MetadataTypeItem = import("../../types/mcdev.d.js").MetadataTypeItem; +export type MetadataTypeItemDiff = import("../../types/mcdev.d.js").MetadataTypeItemDiff; +export type MetadataTypeItemObj = import("../../types/mcdev.d.js").MetadataTypeItemObj; +export type MetadataTypeMap = import("../../types/mcdev.d.js").MetadataTypeMap; +export type MetadataTypeMapObj = import("../../types/mcdev.d.js").MetadataTypeMapObj; +export type MultiMetadataTypeList = import("../../types/mcdev.d.js").MultiMetadataTypeList; +export type MultiMetadataTypeMap = import("../../types/mcdev.d.js").MultiMetadataTypeMap; +export type SoapRequestParams = import("../../types/mcdev.d.js").SoapRequestParams; +export type TemplateMap = import("../../types/mcdev.d.js").TemplateMap; +export type TypeKeyCombo = import("../../types/mcdev.d.js").TypeKeyCombo; +export type ListItem = import("../../types/mcdev.d.js").ListItem; +export type ListMap = import("../../types/mcdev.d.js").ListMap; +//# sourceMappingURL=cache.d.ts.map \ No newline at end of file diff --git a/@types/lib/util/cache.d.ts.map b/@types/lib/util/cache.d.ts.map new file mode 100644 index 000000000..de035ff79 --- /dev/null +++ b/@types/lib/util/cache.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"cache.d.ts","sourceRoot":"","sources":["../../../lib/util/cache.js"],"names":[],"mappings":";IAqCe,6BAHA,QAAQ,GACN,IAAI,CAahB;IAOS,qBAFG,oBAAoB,CAEI;IAWzB,0BAJD,MAAM,SACN,MAAM,GACJ,IAAI,CASuD;IAU9D,wBAJC,MAAM,OACN,MAAM,GACJ,gBAAgB,CAEgC;IAShD,2BAJF,MAAM,eACN,eAAe,GACb,IAAI,CAIhB;IAUc,6BALJ,MAAM,eACN,eAAe,gBACf,MAAM,GACJ,IAAI,CAYhB;IAED;;;;;;;;;;OAUG;IACH,sCARW,MAAM,eACN,MAAM,GAAC,MAAM,GAAC,OAAO,eACrB,MAAM,eACN,MAAM,gBACN,MAAM,oBACN,OAAO,GACL,MAAM,CAoDlB;IAED;;;;;;;OAOG;IACH,qCALW,MAAM,gBACN,MAAM,iBACN,OAAO,GACL,MAAM,CAKlB;IAED;;;;;;;OAOG;IACH,yCALW,MAAM,gBACN,MAAM,iBACN,OAAO,GACL,MAAM,CAgClB;IAED;;;;;;;OAOG;IACH,sCAJW,MAAM,eACN,UAAU,GAAC,IAAI,GAAC,aAAa,GAC3B,MAAM,CA8BlB;IAED;;;;;;;OAOG;IACH,uCAJW,MAAM,eACN,UAAU,GAAC,IAAI,GAAC,aAAa,GAAC,UAAU,GACtC,MAAM,CA2BlB;;;yBA5SQ,OAAO,wBAAwB,EAAE,UAAU;uBAC3C,OAAO,wBAAwB,EAAE,QAAQ;oBACzC,OAAO,wBAAwB,EAAE,KAAK;0BACtC,OAAO,wBAAwB,EAAE,WAAW;8BAC5C,OAAO,wBAAwB,EAAE,eAAe;2BAChD,OAAO,wBAAwB,EAAE,YAAY;sBAC7C,OAAO,wBAAwB,EAAE,OAAO;+BACxC,OAAO,wBAAwB,EAAE,gBAAgB;mCACjD,OAAO,wBAAwB,EAAE,oBAAoB;kCACrD,OAAO,wBAAwB,EAAE,mBAAmB;8BACpD,OAAO,wBAAwB,EAAE,eAAe;iCAChD,OAAO,wBAAwB,EAAE,kBAAkB;oCACnD,OAAO,wBAAwB,EAAE,qBAAqB;mCACtD,OAAO,wBAAwB,EAAE,oBAAoB;gCACrD,OAAO,wBAAwB,EAAE,iBAAiB;0BAClD,OAAO,wBAAwB,EAAE,WAAW;2BAC5C,OAAO,wBAAwB,EAAE,YAAY;uBAE7C,OAAO,wBAAwB,EAAE,QAAQ;sBACzC,OAAO,wBAAwB,EAAE,OAAO"} \ No newline at end of file diff --git a/@types/lib/util/cli.d.ts b/@types/lib/util/cli.d.ts new file mode 100644 index 000000000..5ea9d7361 --- /dev/null +++ b/@types/lib/util/cli.d.ts @@ -0,0 +1,113 @@ +export default Cli; +export type AuthObject = import("../../types/mcdev.d.js").AuthObject; +export type BuObject = import("../../types/mcdev.d.js").BuObject; +export type Cache = import("../../types/mcdev.d.js").Cache; +export type CodeExtract = import("../../types/mcdev.d.js").CodeExtract; +export type CodeExtractItem = import("../../types/mcdev.d.js").CodeExtractItem; +export type DeltaPkgItem = import("../../types/mcdev.d.js").DeltaPkgItem; +export type Mcdevrc = import("../../types/mcdev.d.js").Mcdevrc; +export type MetadataTypeItem = import("../../types/mcdev.d.js").MetadataTypeItem; +export type MetadataTypeItemDiff = import("../../types/mcdev.d.js").MetadataTypeItemDiff; +export type MetadataTypeItemObj = import("../../types/mcdev.d.js").MetadataTypeItemObj; +export type MetadataTypeMap = import("../../types/mcdev.d.js").MetadataTypeMap; +export type MetadataTypeMapObj = import("../../types/mcdev.d.js").MetadataTypeMapObj; +export type MultiMetadataTypeList = import("../../types/mcdev.d.js").MultiMetadataTypeList; +export type MultiMetadataTypeMap = import("../../types/mcdev.d.js").MultiMetadataTypeMap; +export type SoapRequestParams = import("../../types/mcdev.d.js").SoapRequestParams; +export type TemplateMap = import("../../types/mcdev.d.js").TemplateMap; +export type TypeKeyCombo = import("../../types/mcdev.d.js").TypeKeyCombo; +export type ExplainType = import("../../types/mcdev.d.js").ExplainType; +declare namespace Cli { + /** + * used when initially setting up a project. + * loads default config and adds first credential + * + * @returns {Promise.<string | boolean>} success of init + */ + function initMcdevConfig(): Promise<string | boolean>; + /** + * Extends template file for properties.json + * + * @param {Mcdevrc} properties config file's json + * @returns {Promise.<boolean | string>} status + */ + function addExtraCredential(properties: Mcdevrc): Promise<boolean | string>; + /** + * + * @param {string[]} dependentTypes types that depent on type + * @returns {Promise.<boolean>} true if user wants to continue with retrieve + */ + function postFixKeysReretrieve(dependentTypes: string[]): Promise<boolean>; + /** + * helper that logs to cli which credentials are already existing in our config file + * + * @param {Mcdevrc} properties config file's json + * @returns {void} + */ + function logExistingCredentials(properties: Mcdevrc): void; + /** + * Extends template file for properties.json + * update credentials + * + * @param {Mcdevrc} properties config file's json + * @param {string} credName name of credential that needs updating + * @param {boolean} [refreshBUs] if this was triggered by mcdev join, do not refresh BUs + * @returns {Promise.<string | boolean>} success of update + */ + function updateCredential(properties: Mcdevrc, credName: string, refreshBUs?: boolean): Promise<string | boolean>; + /** + * Returns Object with parameters required for accessing API + * + * @param {Mcdevrc} properties object of all configuration including credentials + * @param {string} target code of BU to use + * @param {boolean | string} [isCredentialOnly] true:don't ask for BU | string: name of BU + * @param {boolean} [allowAll] Offer ALL as option in BU selection + * @returns {Promise.<BuObject>} credential to be used for Business Unit + */ + function getCredentialObject(properties: Mcdevrc, target: string, isCredentialOnly?: boolean | string, allowAll?: boolean): Promise<BuObject>; + /** + * helps select the right credential in case of bad initial input + * + * @param {Mcdevrc} properties config file's json + * @param {string} [credential] name of valid credential + * @param {boolean} [isCredentialOnly] don't ask for BU if true + * @param {boolean} [allowAll] Offer ALL as option in BU selection + * @returns {Promise.<{businessUnit:string, credential:string}>} selected credential/BU combo + */ + function _selectBU(properties: Mcdevrc, credential?: string, isCredentialOnly?: boolean, allowAll?: boolean): Promise<{ + businessUnit: string; + credential: string; + }>; + /** + * helper around _askCredentials + * + * @param {Mcdevrc} properties from config file + * @param {string} [credName] name of credential that needs updating + * @param {boolean} [refreshBUs] if this was triggered by mcdev join, do not refresh BUs + * @returns {Promise.<boolean | string>} success of refresh or credential name + */ + function _setCredential(properties: Mcdevrc, credName?: string, refreshBUs?: boolean): Promise<boolean | string>; + /** + * helper for {@link Cli.addExtraCredential} + * + * @param {Mcdevrc} properties from config file + * @param {string} [credName] name of credential that needs updating + * @returns {Promise.<object>} credential info + */ + function _askCredentials(properties: Mcdevrc, credName?: string): Promise<object>; + /** + * allows updating the metadata types that shall be retrieved + * + * @param {Mcdevrc} properties config file's json + * @param {string[]} [setTypesArr] skip user prompt and overwrite with this list if given + * @returns {Promise.<void>} - + */ + function selectTypes(properties: Mcdevrc, setTypesArr?: string[]): Promise<void>; + /** + * shows metadata type descriptions + * + * @returns {ExplainType[]} list of supported types with their apiNames + */ + function explainTypes(): ExplainType[]; +} +//# sourceMappingURL=cli.d.ts.map \ No newline at end of file diff --git a/@types/lib/util/cli.d.ts.map b/@types/lib/util/cli.d.ts.map new file mode 100644 index 000000000..aaf9c99b5 --- /dev/null +++ b/@types/lib/util/cli.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../../../lib/util/cli.js"],"names":[],"mappings":";yBAca,OAAO,wBAAwB,EAAE,UAAU;uBAC3C,OAAO,wBAAwB,EAAE,QAAQ;oBACzC,OAAO,wBAAwB,EAAE,KAAK;0BACtC,OAAO,wBAAwB,EAAE,WAAW;8BAC5C,OAAO,wBAAwB,EAAE,eAAe;2BAChD,OAAO,wBAAwB,EAAE,YAAY;sBAC7C,OAAO,wBAAwB,EAAE,OAAO;+BACxC,OAAO,wBAAwB,EAAE,gBAAgB;mCACjD,OAAO,wBAAwB,EAAE,oBAAoB;kCACrD,OAAO,wBAAwB,EAAE,mBAAmB;8BACpD,OAAO,wBAAwB,EAAE,eAAe;iCAChD,OAAO,wBAAwB,EAAE,kBAAkB;oCACnD,OAAO,wBAAwB,EAAE,qBAAqB;mCACtD,OAAO,wBAAwB,EAAE,oBAAoB;gCACrD,OAAO,wBAAwB,EAAE,iBAAiB;0BAClD,OAAO,wBAAwB,EAAE,WAAW;2BAC5C,OAAO,wBAAwB,EAAE,YAAY;0BAC7C,OAAO,wBAAwB,EAAE,WAAW;;IAQrD;;;;;OAKG;IACH,4BAFa,OAAO,CAAE,MAAM,GAAG,OAAO,CAAC,CAUtC;IAED;;;;;OAKG;IACH,wCAHW,OAAO,GACL,OAAO,CAAE,OAAO,GAAG,MAAM,CAAC,CAkBtC;IAED;;;;OAIG;IACH,+CAHW,MAAM,EAAE,GACN,OAAO,CAAE,OAAO,CAAC,CA0B7B;IAED;;;;;OAKG;IACH,4CAHW,OAAO,GACL,IAAI,CAShB;IAED;;;;;;;;OAQG;IACH,sCALW,OAAO,YACP,MAAM,eACN,OAAO,GACL,OAAO,CAAE,MAAM,GAAG,OAAO,CAAC,CAUtC;IAED;;;;;;;;OAQG;IACH,yCANW,OAAO,UACP,MAAM,qBACN,OAAO,GAAG,MAAM,aAChB,OAAO,GACL,OAAO,CAAE,QAAQ,CAAC,CAuE9B;IAED;;;;;;;;OAQG;IACH,+BANW,OAAO,eACP,MAAM,qBACN,OAAO,aACP,OAAO,GACL,OAAO,CAAE;QAAC,YAAY,EAAC,MAAM,CAAC;QAAC,UAAU,EAAC,MAAM,CAAA;KAAC,CAAC,CA8D9D;IAED;;;;;;;OAOG;IACH,oCALW,OAAO,aACP,MAAM,eACN,OAAO,GACL,OAAO,CAAE,OAAO,GAAG,MAAM,CAAC,CA+DtC;IAED;;;;;;OAMG;IACH,qCAJW,OAAO,aACP,MAAM,GACJ,OAAO,CAAE,MAAM,CAAC,CAwE5B;IAED;;;;;;OAMG;IACH,iCAJW,OAAO,gBACP,MAAM,EAAE,GACN,OAAO,CAAE,IAAI,CAAC,CAgG1B;IAED;;;;OAIG;IACH,yBAFa,WAAW,EAAE,CA0GzB"} \ No newline at end of file diff --git a/@types/lib/util/config.d.ts b/@types/lib/util/config.d.ts new file mode 100644 index 000000000..628ca2eb8 --- /dev/null +++ b/@types/lib/util/config.d.ts @@ -0,0 +1,45 @@ +export default config; +export type AuthObject = import("../../types/mcdev.d.js").AuthObject; +export type BuObject = import("../../types/mcdev.d.js").BuObject; +export type Cache = import("../../types/mcdev.d.js").Cache; +export type CodeExtract = import("../../types/mcdev.d.js").CodeExtract; +export type CodeExtractItem = import("../../types/mcdev.d.js").CodeExtractItem; +export type DeltaPkgItem = import("../../types/mcdev.d.js").DeltaPkgItem; +export type Mcdevrc = import("../../types/mcdev.d.js").Mcdevrc; +export type MetadataTypeItem = import("../../types/mcdev.d.js").MetadataTypeItem; +export type MetadataTypeItemDiff = import("../../types/mcdev.d.js").MetadataTypeItemDiff; +export type MetadataTypeItemObj = import("../../types/mcdev.d.js").MetadataTypeItemObj; +export type MetadataTypeMap = import("../../types/mcdev.d.js").MetadataTypeMap; +export type MetadataTypeMapObj = import("../../types/mcdev.d.js").MetadataTypeMapObj; +export type MultiMetadataTypeList = import("../../types/mcdev.d.js").MultiMetadataTypeList; +export type MultiMetadataTypeMap = import("../../types/mcdev.d.js").MultiMetadataTypeMap; +export type SoapRequestParams = import("../../types/mcdev.d.js").SoapRequestParams; +export type TemplateMap = import("../../types/mcdev.d.js").TemplateMap; +export type TypeKeyCombo = import("../../types/mcdev.d.js").TypeKeyCombo; +declare namespace config { + let properties: any; + /** + * loads central properties from config file + * + * @param {boolean} [silent] omit throwing errors and print messages; assuming not silent if not set + * @param {boolean} [isInit] don't tell the user to run init + * @returns {Promise.<Mcdevrc>} central properties object + */ + function getProperties(silent?: boolean, isInit?: boolean): Promise<Mcdevrc>; + /** + * check if the config file is correctly formatted and has values + * + * @param {Mcdevrc} properties javascript object in .mcdevrc.json + * @param {boolean} [silent] set to true for internal use w/o cli output + * @returns {Promise.<boolean | string[]>} file structure ok OR list of fields to be fixed + */ + function checkProperties(properties: Mcdevrc, silent?: boolean): Promise<boolean | string[]>; + /** + * defines how the properties.json should look like + * used for creating a template and for checking if variables are set + * + * @returns {Promise.<Mcdevrc>} default properties + */ + function getDefaultProperties(): Promise<Mcdevrc>; +} +//# sourceMappingURL=config.d.ts.map \ No newline at end of file diff --git a/@types/lib/util/config.d.ts.map b/@types/lib/util/config.d.ts.map new file mode 100644 index 000000000..1bac12994 --- /dev/null +++ b/@types/lib/util/config.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../../lib/util/config.js"],"names":[],"mappings":";yBASa,OAAO,wBAAwB,EAAE,UAAU;uBAC3C,OAAO,wBAAwB,EAAE,QAAQ;oBACzC,OAAO,wBAAwB,EAAE,KAAK;0BACtC,OAAO,wBAAwB,EAAE,WAAW;8BAC5C,OAAO,wBAAwB,EAAE,eAAe;2BAChD,OAAO,wBAAwB,EAAE,YAAY;sBAC7C,OAAO,wBAAwB,EAAE,OAAO;+BACxC,OAAO,wBAAwB,EAAE,gBAAgB;mCACjD,OAAO,wBAAwB,EAAE,oBAAoB;kCACrD,OAAO,wBAAwB,EAAE,mBAAmB;8BACpD,OAAO,wBAAwB,EAAE,eAAe;iCAChD,OAAO,wBAAwB,EAAE,kBAAkB;oCACnD,OAAO,wBAAwB,EAAE,qBAAqB;mCACtD,OAAO,wBAAwB,EAAE,oBAAoB;gCACrD,OAAO,wBAAwB,EAAE,iBAAiB;0BAClD,OAAO,wBAAwB,EAAE,WAAW;2BAC5C,OAAO,wBAAwB,EAAE,YAAY;;;IAStD;;;;;;OAMG;IACH,gCAJW,OAAO,WACP,OAAO,GACL,OAAO,CAAE,OAAO,CAAC,CAiE7B;IAED;;;;;;OAMG;IACH,qCAJW,OAAO,WACP,OAAO,GACL,OAAO,CAAE,OAAO,GAAG,MAAM,EAAE,CAAC,CAmMxC;IAED;;;;;OAKG;IACH,iCAFa,OAAO,CAAE,OAAO,CAAC,CAiB7B"} \ No newline at end of file diff --git a/@types/lib/util/devops.d.ts b/@types/lib/util/devops.d.ts new file mode 100644 index 000000000..d9f876cce --- /dev/null +++ b/@types/lib/util/devops.d.ts @@ -0,0 +1,73 @@ +export default DevOps; +export type AuthObject = import("../../types/mcdev.d.js").AuthObject; +export type BuObject = import("../../types/mcdev.d.js").BuObject; +export type Cache = import("../../types/mcdev.d.js").Cache; +export type CodeExtract = import("../../types/mcdev.d.js").CodeExtract; +export type CodeExtractItem = import("../../types/mcdev.d.js").CodeExtractItem; +export type DeltaPkgItem = import("../../types/mcdev.d.js").DeltaPkgItem; +export type Mcdevrc = import("../../types/mcdev.d.js").Mcdevrc; +export type MetadataTypeItem = import("../../types/mcdev.d.js").MetadataTypeItem; +export type MetadataTypeItemDiff = import("../../types/mcdev.d.js").MetadataTypeItemDiff; +export type MetadataTypeItemObj = import("../../types/mcdev.d.js").MetadataTypeItemObj; +export type MetadataTypeMap = import("../../types/mcdev.d.js").MetadataTypeMap; +export type MetadataTypeMapObj = import("../../types/mcdev.d.js").MetadataTypeMapObj; +export type MultiMetadataTypeList = import("../../types/mcdev.d.js").MultiMetadataTypeList; +export type MultiMetadataTypeMap = import("../../types/mcdev.d.js").MultiMetadataTypeMap; +export type SoapRequestParams = import("../../types/mcdev.d.js").SoapRequestParams; +export type TemplateMap = import("../../types/mcdev.d.js").TemplateMap; +export type TypeKeyCombo = import("../../types/mcdev.d.js").TypeKeyCombo; +export type BuildFilter = import("../../types/mcdev.d.js").BuildFilter; +declare namespace DevOps { + /** + * Extracts the delta between a commit and the current state for deployment. + * Interactive commit selection if no commits are passed. + * + * @param {Mcdevrc} properties central properties object + * @param {string} [range] git commit range + * @param {boolean} [saveToDeployDir] if true, copy metadata changes into deploy directory + * @param {string} [filterPathsCSV] filter file paths that start with any specified path (comma separated) + * @param {number} [commitHistory] cli option to override default commit history value in config + * @returns {Promise.<DeltaPkgItem[]>} - + */ + function getDeltaList(properties: Mcdevrc, range?: string, saveToDeployDir?: boolean, filterPathsCSV?: string, commitHistory?: number): Promise<DeltaPkgItem[]>; + /** + * wrapper around DevOps.getDeltaList, Builder.buildTemplate and M + * + * @param {Mcdevrc} properties project config file + * @param {string} range git commit range + * @param {DeltaPkgItem[]} [diffArr] instead of running git diff the method can also get a list of files to process + * @param {number} [commitHistory] cli option to override default commit history value in config + * @returns {Promise.<DeltaPkgItem[]>} - + */ + function buildDeltaDefinitions(properties: Mcdevrc, range: string, diffArr?: DeltaPkgItem[], commitHistory?: number): Promise<DeltaPkgItem[]>; + /** + * create markdown file for deployment listing + * + * @param {string} directory - + * @param {string} filterPathsCSV - + * @param {object} jsonReport - + * @returns {void} + */ + function document(directory: string, filterPathsCSV: string, jsonReport: object): void; + /** + * should return only the json for all but asset, query and script that are saved as multiple files + * additionally, the documentation for dataExtension and automation should be returned + * + * @param {Mcdevrc} properties central properties object + * @param {BuObject} buObject references credentials + * @param {string} metadataType metadata type to build + * @param {string[]} keyArr customerkey of the metadata + * @returns {Promise.<string[]>} list of all files that need to be committed in a flat array ['path/file1.ext', 'path/file2.ext'] + */ + function getFilesToCommit(properties: Mcdevrc, buObject: BuObject, metadataType: string, keyArr: string[]): Promise<string[]>; + /** + * helper for {@link DevOps.buildDeltaDefinitions} + * + * @param {DeltaPkgItem[]} delta git delta + * @param {string} sourceMarket market for the source BU + * @param {Mcdevrc} properties mcdev config + * @param {string} targetMlName marketList used to build for the target BU + */ + function _generateDeleteInstructions(delta: DeltaPkgItem[], sourceMarket: string, properties: Mcdevrc, targetMlName: string): void; +} +//# sourceMappingURL=devops.d.ts.map \ No newline at end of file diff --git a/@types/lib/util/devops.d.ts.map b/@types/lib/util/devops.d.ts.map new file mode 100644 index 000000000..23f3c7410 --- /dev/null +++ b/@types/lib/util/devops.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"devops.d.ts","sourceRoot":"","sources":["../../../lib/util/devops.js"],"names":[],"mappings":";yBAea,OAAO,wBAAwB,EAAE,UAAU;uBAC3C,OAAO,wBAAwB,EAAE,QAAQ;oBACzC,OAAO,wBAAwB,EAAE,KAAK;0BACtC,OAAO,wBAAwB,EAAE,WAAW;8BAC5C,OAAO,wBAAwB,EAAE,eAAe;2BAChD,OAAO,wBAAwB,EAAE,YAAY;sBAC7C,OAAO,wBAAwB,EAAE,OAAO;+BACxC,OAAO,wBAAwB,EAAE,gBAAgB;mCACjD,OAAO,wBAAwB,EAAE,oBAAoB;kCACrD,OAAO,wBAAwB,EAAE,mBAAmB;8BACpD,OAAO,wBAAwB,EAAE,eAAe;iCAChD,OAAO,wBAAwB,EAAE,kBAAkB;oCACnD,OAAO,wBAAwB,EAAE,qBAAqB;mCACtD,OAAO,wBAAwB,EAAE,oBAAoB;gCACrD,OAAO,wBAAwB,EAAE,iBAAiB;0BAClD,OAAO,wBAAwB,EAAE,WAAW;2BAC5C,OAAO,wBAAwB,EAAE,YAAY;0BAC7C,OAAO,wBAAwB,EAAE,WAAW;;IAOrD;;;;;;;;;;OAUG;IACH,kCAPW,OAAO,UACP,MAAM,oBACN,OAAO,mBACP,MAAM,kBACN,MAAM,GACJ,OAAO,CAAE,YAAY,EAAE,CAAC,CAsXpC;IAED;;;;;;;;OAQG;IACH,2CANW,OAAO,SACP,MAAM,YACN,YAAY,EAAE,kBACd,MAAM,GACJ,OAAO,CAAE,YAAY,EAAE,CAAC,CA+JpC;IAED;;;;;;;OAOG;IACH,6BALW,MAAM,kBACN,MAAM,cACN,MAAM,GACJ,IAAI,CAmChB;IAED;;;;;;;;;OASG;IACH,sCANW,OAAO,YACP,QAAQ,gBACR,MAAM,UACN,MAAM,EAAE,GACN,OAAO,CAAE,MAAM,EAAE,CAAC,CAM9B;IACD;;;;;;;OAOG;IACH,4CALW,YAAY,EAAE,gBACd,MAAM,cACN,OAAO,gBACP,MAAM,QAgGhB"} \ No newline at end of file diff --git a/@types/lib/util/file.d.ts b/@types/lib/util/file.d.ts new file mode 100644 index 000000000..3099e6085 --- /dev/null +++ b/@types/lib/util/file.d.ts @@ -0,0 +1,181 @@ +export default FileFs; +export type AuthObject = import("../../types/mcdev.d.js").AuthObject; +export type BuObject = import("../../types/mcdev.d.js").BuObject; +export type Cache = import("../../types/mcdev.d.js").Cache; +export type CodeExtract = import("../../types/mcdev.d.js").CodeExtract; +export type CodeExtractItem = import("../../types/mcdev.d.js").CodeExtractItem; +export type DeltaPkgItem = import("../../types/mcdev.d.js").DeltaPkgItem; +export type Mcdevrc = import("../../types/mcdev.d.js").Mcdevrc; +export type MetadataTypeItem = import("../../types/mcdev.d.js").MetadataTypeItem; +export type MetadataTypeItemDiff = import("../../types/mcdev.d.js").MetadataTypeItemDiff; +export type MetadataTypeItemObj = import("../../types/mcdev.d.js").MetadataTypeItemObj; +export type MetadataTypeMap = import("../../types/mcdev.d.js").MetadataTypeMap; +export type MetadataTypeMapObj = import("../../types/mcdev.d.js").MetadataTypeMapObj; +export type MultiMetadataTypeList = import("../../types/mcdev.d.js").MultiMetadataTypeList; +export type MultiMetadataTypeMap = import("../../types/mcdev.d.js").MultiMetadataTypeMap; +export type SoapRequestParams = import("../../types/mcdev.d.js").SoapRequestParams; +export type TemplateMap = import("../../types/mcdev.d.js").TemplateMap; +export type TypeKeyCombo = import("../../types/mcdev.d.js").TypeKeyCombo; +declare const FileFs: typeof fs & { + prettierConfig: any; + prettierConfigFileType: any; + /** + * copies a file from one path to another + * + * @param {string} from - full filepath including name of existing file + * @param {string} to - full filepath including name where file should go + * @returns {Promise.<{status:'ok'|'skipped'|'failed', statusMessage:string, file:string}>} - results object + */ + copyFileSimple(from: string, to: string): Promise<{ + status: "ok" | "skipped" | "failed"; + statusMessage: string; + file: string; + }>; + /** + * makes sure Windows accepts path names + * + * @param {string} path - filename or path + * @returns {string} - corrected string + */ + filterIllegalPathChars(path: string): string; + /** + * makes sure Windows accepts file names + * + * @param {string} filename - filename or path + * @returns {string} - corrected string + */ + filterIllegalFilenames(filename: string): string; + /** + * makes sure Windows accepts file names + * + * @param {string} filename - filename or path + * @returns {string} - corrected string + */ + reverseFilterIllegalFilenames(filename: string): string; + /** + * Takes various types of path strings and formats into a platform specific path + * + * @param {string|string[]} denormalizedPath directory the file will be written to + * @returns {string} Path strings + */ + normalizePath: (denormalizedPath: string | string[]) => string; + /** + * Saves json content to a file in the local file system. Will create the parent directory if it does not exist + * + * @param {string|string[]} directory directory the file will be written to + * @param {string} filename name of the file without '.json' ending + * @param {object} content filecontent + * @returns {Promise} Promise + */ + writeJSONToFile: (directory: string | string[], filename: string, content: object) => Promise<any>; + /** + * Saves beautified files in the local file system. Will create the parent directory if it does not exist + * ! Important: run 'await File.initPrettier()' in your MetadataType.retrieve() once before hitting this + * + * @param {string|string[]} directory directory the file will be written to + * @param {string} filename name of the file without suffix + * @param {string} filetype filetype ie. JSON or SSJS + * @param {string} content filecontent + * @param {TemplateMap} [templateVariables] templating variables to be replaced in the metadata + * @returns {Promise.<boolean>} Promise + */ + writePrettyToFile: (directory: string | string[], filename: string, filetype: string, content: string, templateVariables?: TemplateMap) => Promise<boolean>; + /** + * helper that applies beautyAmp onto given stringified content; strongly typed for strings only + * + * @param {string} content code + * @param {boolean} [formatHTML] applies formatting to html and ampscript if true + * @returns {Promise.<string>} formatted code + */ + _beautify_beautyAmp_beautify: (content: string, formatHTML?: boolean) => Promise<string>; + /** + * helper for {@link File.writePrettyToFile}, applying beautyAmp onto given stringified content + * + * @param {string} content filecontent + * @param {boolean} formatHTML should we format HTML or not via prettier included in beautyAmp + * @returns {Promise.<string>} original string on error; formatted string on success + */ + beautify_beautyAmp: (content: string, formatHTML?: boolean) => Promise<string>; + /** + * helper for {@link File.writePrettyToFile}, applying prettier onto given stringified content + * ! Important: run 'await File.initPrettier()' in your MetadataType.retrieve() once before hitting this + * + * @param {string|string[]} directory directory the file will be written to + * @param {string} filename name of the file without suffix + * @param {string} filetype filetype ie. JSON or SSJS + * @param {string} content filecontent + * @returns {Promise.<string>} original string on error; formatted string on success + */ + _beautify_prettier: (directory: string | string[], filename: string, filetype: string, content: string) => Promise<string>; + /** + * Saves text content to a file in the local file system. Will create the parent directory if it does not exist + * + * @param {string|string[]} directory directory the file will be written to + * @param {string} filename name of the file without '.json' ending + * @param {string} filetype filetype suffix + * @param {string} content filecontent + * @param {object} [encoding] added for certain file types (like images) + * @returns {Promise.<boolean>} Promise + */ + writeToFile: (directory: string | string[], filename: string, filetype: string, content: string, encoding?: object) => Promise<boolean>; + /** + * Saves json content to a file in the local file system. Will create the parent directory if it does not exist + * + * @param {string | string[]} directory directory where the file is stored + * @param {string} filename name of the file without '.json' ending + * @param {boolean} cleanPath filters illegal chars if true + * @returns {Promise.<object | object | void>} Promise or JSON object depending on if async or not; void on error + */ + readJSONFile: (directory: string | string[], filename: string, cleanPath: boolean) => Promise<object | object | void>; + /** + * reads file from local file system. + * + * @param {string | string[]} directory directory where the file is stored + * @param {string} filename name of the file without '.json' ending + * @param {string} filetype filetype suffix + * @param {string} [encoding] read file with encoding (defaults to utf-8) + * @returns {Promise.<string>} file contents; void on error + */ + readFilteredFilename: (directory: string | string[], filename: string, filetype: string, encoding?: string) => Promise<string>; + /** + * reads directories to a specific depth returning an array + * of file paths to be iterated over + * + * @example ['deploy/mcdev/bu1'] + * @param {string} directory directory to checkin + * @param {number} depth how many levels to check (1 base) + * @param {boolean} [includeStem] include the parent directory in the response + * @param {number} [_stemLength] set recursively for subfolders. do not set manually! + * @returns {Promise.<string[]>} array of fully defined file paths + */ + readDirectories: (directory: string, depth: number, includeStem?: boolean, _stemLength?: number) => Promise<string[]>; + /** + * reads directories to a specific depth returning an array + * of file paths to be iterated over using sync api (required in constructors) + * TODO - merge with readDirectories. so far the logic is really different + * + * @example ['deploy/mcdev/bu1'] + * @param {string} directory directory to checkin + * @param {number} [depth] how many levels to check (1 base) + * @param {boolean} [includeStem] include the parent directory in the response + * @param {number} [_stemLength] set recursively for subfolders. do not set manually! + * @returns {string[] | void} array of fully defined file paths; void on error + */ + readDirectoriesSync: (directory: string, depth?: number, includeStem?: boolean, _stemLength?: number) => string[] | void; + /** + * helper that splits the config back into auth & config parts to save them separately + * + * @param {Mcdevrc} properties central properties object + * @returns {Promise.<void>} - + */ + saveConfigFile(properties: Mcdevrc): Promise<void>; + /** + * Initalises Prettier formatting lib async. + * + * @param {string} [filetype] filetype ie. JSON or SSJS + * @returns {Promise.<boolean>} success of config load + */ + initPrettier(filetype?: string): Promise<boolean>; +}; +import fs from 'fs-extra'; +//# sourceMappingURL=file.d.ts.map \ No newline at end of file diff --git a/@types/lib/util/file.d.ts.map b/@types/lib/util/file.d.ts.map new file mode 100644 index 000000000..783bb4edc --- /dev/null +++ b/@types/lib/util/file.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"file.d.ts","sourceRoot":"","sources":["../../../lib/util/file.js"],"names":[],"mappings":";yBAWa,OAAO,wBAAwB,EAAE,UAAU;uBAC3C,OAAO,wBAAwB,EAAE,QAAQ;oBACzC,OAAO,wBAAwB,EAAE,KAAK;0BACtC,OAAO,wBAAwB,EAAE,WAAW;8BAC5C,OAAO,wBAAwB,EAAE,eAAe;2BAChD,OAAO,wBAAwB,EAAE,YAAY;sBAC7C,OAAO,wBAAwB,EAAE,OAAO;+BACxC,OAAO,wBAAwB,EAAE,gBAAgB;mCACjD,OAAO,wBAAwB,EAAE,oBAAoB;kCACrD,OAAO,wBAAwB,EAAE,mBAAmB;8BACpD,OAAO,wBAAwB,EAAE,eAAe;iCAChD,OAAO,wBAAwB,EAAE,kBAAkB;oCACnD,OAAO,wBAAwB,EAAE,qBAAqB;mCACtD,OAAO,wBAAwB,EAAE,oBAAoB;gCACrD,OAAO,wBAAwB,EAAE,iBAAiB;0BAClD,OAAO,wBAAwB,EAAE,WAAW;2BAC5C,OAAO,wBAAwB,EAAE,YAAY;AAykB1D;;;IAvjBI;;;;;;OAMG;yBAHQ,MAAM,MACN,MAAM,GACJ,OAAO,CAAE;QAAC,MAAM,EAAC,IAAI,GAAC,SAAS,GAAC,QAAQ,CAAC;QAAC,aAAa,EAAC,MAAM,CAAC;QAAC,IAAI,EAAC,MAAM,CAAA;KAAC,CAAC;IAkB1F;;;;;OAKG;iCAFQ,MAAM,GACJ,MAAM;IAiCnB;;;;;OAKG;qCAFQ,MAAM,GACJ,MAAM;IA2BnB;;;;;OAKG;4CAFQ,MAAM,GACJ,MAAM;IAMnB;;;;;OAKG;sCAFQ,MAAM,GAAC,MAAM,EAAE,KACb,MAAM;IAcnB;;;;;;;OAOG;iCAJQ,MAAM,GAAC,MAAM,EAAE,YACf,MAAM,WACN,MAAM;IAcjB;;;;;;;;;;OAUG;mCANQ,MAAM,GAAC,MAAM,EAAE,YACf,MAAM,YACN,MAAM,WACN,MAAM,sBACN,WAAW,KACT,OAAO,CAAE,OAAO,CAAC;IAuB9B;;;;;;OAMG;4CAHQ,MAAM,eACN,OAAO,KACL,OAAO,CAAE,MAAM,CAAC;IAW7B;;;;;;OAMG;kCAHQ,MAAM,eACN,OAAO,KACL,OAAO,CAAE,MAAM,CAAC;IAyB7B;;;;;;;;;OASG;oCALQ,MAAM,GAAC,MAAM,EAAE,YACf,MAAM,YACN,MAAM,WACN,MAAM,KACJ,OAAO,CAAE,MAAM,CAAC;IA+F7B;;;;;;;;;OASG;6BANQ,MAAM,GAAC,MAAM,EAAE,YACf,MAAM,YACN,MAAM,WACN,MAAM,aACN,MAAM,KACJ,OAAO,CAAE,OAAO,CAAC;IAoB9B;;;;;;;OAOG;8BAJQ,MAAM,GAAG,MAAM,EAAE,YACjB,MAAM,aACN,OAAO,KACL,OAAO,CAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAC;IA0B7C;;;;;;;;OAQG;sCALQ,MAAM,GAAG,MAAM,EAAE,YACjB,MAAM,YACN,MAAM,aACN,MAAM,KACJ,OAAO,CAAE,MAAM,CAAC;IAc7B;;;;;;;;;;OAUG;iCALQ,MAAM,SACN,MAAM,gBACN,OAAO,gBACP,MAAM,KACJ,OAAO,CAAE,MAAM,EAAE,CAAC;IA6C/B;;;;;;;;;;;OAWG;qCALQ,MAAM,UACN,MAAM,gBACN,OAAO,gBACP,MAAM,KACJ,MAAM,EAAE,GAAG,IAAI;IA4C5B;;;;;OAKG;+BAFQ,OAAO,GACL,OAAO,CAAE,IAAI,CAAC;IAU3B;;;;;OAKG;4BAFQ,MAAM,GACJ,OAAO,CAAE,OAAO,CAAC;EAyCK;eAnmBxB,UAAU"} \ No newline at end of file diff --git a/@types/lib/util/init.config.d.ts b/@types/lib/util/init.config.d.ts new file mode 100644 index 000000000..f5abfa25b --- /dev/null +++ b/@types/lib/util/init.config.d.ts @@ -0,0 +1,82 @@ +export default Init; +export type AuthObject = import("../../types/mcdev.d.js").AuthObject; +export type BuObject = import("../../types/mcdev.d.js").BuObject; +export type Cache = import("../../types/mcdev.d.js").Cache; +export type CodeExtract = import("../../types/mcdev.d.js").CodeExtract; +export type CodeExtractItem = import("../../types/mcdev.d.js").CodeExtractItem; +export type DeltaPkgItem = import("../../types/mcdev.d.js").DeltaPkgItem; +export type Mcdevrc = import("../../types/mcdev.d.js").Mcdevrc; +export type MetadataTypeItem = import("../../types/mcdev.d.js").MetadataTypeItem; +export type MetadataTypeItemDiff = import("../../types/mcdev.d.js").MetadataTypeItemDiff; +export type MetadataTypeItemObj = import("../../types/mcdev.d.js").MetadataTypeItemObj; +export type MetadataTypeMap = import("../../types/mcdev.d.js").MetadataTypeMap; +export type MetadataTypeMapObj = import("../../types/mcdev.d.js").MetadataTypeMapObj; +export type MultiMetadataTypeList = import("../../types/mcdev.d.js").MultiMetadataTypeList; +export type MultiMetadataTypeMap = import("../../types/mcdev.d.js").MultiMetadataTypeMap; +export type SoapRequestParams = import("../../types/mcdev.d.js").SoapRequestParams; +export type TemplateMap = import("../../types/mcdev.d.js").TemplateMap; +export type TypeKeyCombo = import("../../types/mcdev.d.js").TypeKeyCombo; +declare namespace Init { + /** + * helper method for this.upgradeProject that upgrades project config if needed + * + * @param {Mcdevrc} properties config file's json + * @returns {Promise.<boolean>} returns true if worked without errors + */ + function fixMcdevConfig(properties: Mcdevrc): Promise<boolean>; + /** + * handles creation/update of all config file from the boilerplate + * + * @param {string} versionBeforeUpgrade 'x.y.z' + * @returns {Promise.<boolean>} status of config file creation + */ + function createIdeConfigFiles(versionBeforeUpgrade: string): Promise<boolean>; + /** + * recursive helper for {@link Init.fixMcdevConfig} that adds missing settings + * + * @param {object} propertiersCur current sub-object of project settings + * @param {object} defaultPropsCur current sub-object of default settings + * @param {string} fieldName dot-concatenated object-path that needs adding + * @returns {boolean} was something updated or not + */ + function _updateLeaf(propertiersCur: object, defaultPropsCur: object, fieldName: string): boolean; + /** + * returns list of files that need to be updated + * + * @param {string} projectVersion version found in config file of the current project + * @returns {Promise.<{updates:string[],deletes:string[]}>} relevant files with path that need to be updated + */ + function _getForcedUpdateList(projectVersion: string): Promise<{ + updates: string[]; + deletes: string[]; + }>; + /** + * handles creation/update of one config file from the boilerplate at a time + * + * @param {string[]} fileNameArr 0: path, 1: filename, 2: extension with dot + * @param {{updates:string[],deletes:string[]}} relevantForced if fileNameArr is in this list we require an override + * @param {string} [boilerplateFileContent] in case we cannot copy files 1:1 this can be used to pass in content + * @returns {Promise.<boolean>} install successful or error occured + */ + function _createIdeConfigFile(fileNameArr: string[], relevantForced: { + updates: string[]; + deletes: string[]; + }, boilerplateFileContent?: string): Promise<boolean>; + /** + * handles deletion of no longer needed config files + * + * @param {{updates:string[],deletes:string[]}} relevantForced if file is in .deletes, we require deleting/renaming it + * @returns {Promise.<boolean>} deletion successful or error occured + */ + function _removeIdeConfigFiles(relevantForced: { + updates: string[]; + deletes: string[]; + }): Promise<boolean>; + /** + * helper method for this.upgradeProject that upgrades project config if needed + * + * @returns {Promise.<boolean>} returns true if worked without errors + */ + function upgradeAuthFile(): Promise<boolean>; +} +//# sourceMappingURL=init.config.d.ts.map \ No newline at end of file diff --git a/@types/lib/util/init.config.d.ts.map b/@types/lib/util/init.config.d.ts.map new file mode 100644 index 000000000..1977e3e00 --- /dev/null +++ b/@types/lib/util/init.config.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"init.config.d.ts","sourceRoot":"","sources":["../../../lib/util/init.config.js"],"names":[],"mappings":";yBAYa,OAAO,wBAAwB,EAAE,UAAU;uBAC3C,OAAO,wBAAwB,EAAE,QAAQ;oBACzC,OAAO,wBAAwB,EAAE,KAAK;0BACtC,OAAO,wBAAwB,EAAE,WAAW;8BAC5C,OAAO,wBAAwB,EAAE,eAAe;2BAChD,OAAO,wBAAwB,EAAE,YAAY;sBAC7C,OAAO,wBAAwB,EAAE,OAAO;+BACxC,OAAO,wBAAwB,EAAE,gBAAgB;mCACjD,OAAO,wBAAwB,EAAE,oBAAoB;kCACrD,OAAO,wBAAwB,EAAE,mBAAmB;8BACpD,OAAO,wBAAwB,EAAE,eAAe;iCAChD,OAAO,wBAAwB,EAAE,kBAAkB;oCACnD,OAAO,wBAAwB,EAAE,qBAAqB;mCACtD,OAAO,wBAAwB,EAAE,oBAAoB;gCACrD,OAAO,wBAAwB,EAAE,iBAAiB;0BAClD,OAAO,wBAAwB,EAAE,WAAW;2BAC5C,OAAO,wBAAwB,EAAE,YAAY;;IAQtD;;;;;OAKG;IACH,oCAHW,OAAO,GACL,OAAO,CAAE,OAAO,CAAC,CAmP7B;IAED;;;;;OAKG;IACH,oDAHW,MAAM,GACJ,OAAO,CAAE,OAAO,CAAC,CAmE7B;IAED;;;;;;;OAOG;IACH,qCALW,MAAM,mBACN,MAAM,aACN,MAAM,GACJ,OAAO,CAyBnB;IAED;;;;;OAKG;IACH,8CAHW,MAAM,GACJ,OAAO,CAAE;QAAC,OAAO,EAAC,MAAM,EAAE,CAAC;QAAA,OAAO,EAAC,MAAM,EAAE,CAAA;KAAC,CAAC,CA+BzD;IAED;;;;;;;OAOG;IACH,2CALW,MAAM,EAAE,kBACR;QAAC,OAAO,EAAC,MAAM,EAAE,CAAC;QAAA,OAAO,EAAC,MAAM,EAAE,CAAA;KAAC,2BACnC,MAAM,GACJ,OAAO,CAAE,OAAO,CAAC,CAwF7B;IAED;;;;;OAKG;IACH,+CAHW;QAAC,OAAO,EAAC,MAAM,EAAE,CAAC;QAAA,OAAO,EAAC,MAAM,EAAE,CAAA;KAAC,GACjC,OAAO,CAAE,OAAO,CAAC,CAc7B;IAED;;;;OAIG;IACH,4BAFa,OAAO,CAAE,OAAO,CAAC,CAyB7B"} \ No newline at end of file diff --git a/@types/lib/util/init.d.ts b/@types/lib/util/init.d.ts new file mode 100644 index 000000000..23c2e3028 --- /dev/null +++ b/@types/lib/util/init.d.ts @@ -0,0 +1,72 @@ +export default Init; +export type AuthObject = import("../../types/mcdev.d.js").AuthObject; +export type BuObject = import("../../types/mcdev.d.js").BuObject; +export type Cache = import("../../types/mcdev.d.js").Cache; +export type CodeExtract = import("../../types/mcdev.d.js").CodeExtract; +export type CodeExtractItem = import("../../types/mcdev.d.js").CodeExtractItem; +export type DeltaPkgItem = import("../../types/mcdev.d.js").DeltaPkgItem; +export type Mcdevrc = import("../../types/mcdev.d.js").Mcdevrc; +export type MetadataTypeItem = import("../../types/mcdev.d.js").MetadataTypeItem; +export type MetadataTypeItemDiff = import("../../types/mcdev.d.js").MetadataTypeItemDiff; +export type MetadataTypeItemObj = import("../../types/mcdev.d.js").MetadataTypeItemObj; +export type MetadataTypeMap = import("../../types/mcdev.d.js").MetadataTypeMap; +export type MetadataTypeMapObj = import("../../types/mcdev.d.js").MetadataTypeMapObj; +export type MultiMetadataTypeList = import("../../types/mcdev.d.js").MultiMetadataTypeList; +export type MultiMetadataTypeMap = import("../../types/mcdev.d.js").MultiMetadataTypeMap; +export type SoapRequestParams = import("../../types/mcdev.d.js").SoapRequestParams; +export type TemplateMap = import("../../types/mcdev.d.js").TemplateMap; +export type TypeKeyCombo = import("../../types/mcdev.d.js").TypeKeyCombo; +declare namespace Init { + /** + * Creates template file for properties.json + * + * @param {Mcdevrc} properties config file's json + * @param {string} [credentialName] identifying name of the installed package / project; if set, will update this credential + * @param {boolean} [refreshBUs] if this was triggered by mcdev join, do not refresh BUs + * @returns {Promise.<void>} - + */ + function initProject(properties: Mcdevrc, credentialName?: string, refreshBUs?: boolean): Promise<void>; + /** + * Creates template file for properties.json + * + * @returns {Promise.<void>} - + */ + function joinProject(): Promise<void>; + /** + * helper for {@link Init.initProject} that optionally creates markets and market lists for all BUs + */ + function _initMarkets(): Promise<void>; + /** + * helper for {@link Init.initProject} + * + * @param {string} bu cred/bu or cred/* or * + * @param {string} gitStatus signals what state the git repo is in + * @returns {Promise.<void>} - + */ + function _downloadAllBUs(bu: string, gitStatus: string): Promise<void>; + /** + * wrapper around npm dependency & configuration file setup + * + * @param {Mcdevrc} properties config file's json + * @param {boolean} [initial] print message if not part of initial setup + * @param {string} [repoName] if git URL was provided earlier, the repo name was extracted to use it for npm init + * @returns {Promise.<boolean>} success flag + */ + function upgradeProject(properties: Mcdevrc, initial?: boolean, repoName?: string): Promise<boolean>; + /** + * check if git repo is being saved on a cloud service and warn the user + * + * @private + * @returns {Promise.<boolean>} true if path is good; false if project seems to be in a cloud service folder + */ + function _checkPathForCloud(): Promise<boolean>; + /** + * finds credentials that are set up in config but not in auth file + * + * @private + * @param {Mcdevrc} properties javascript object in .mcdevrc.json + * @returns {string[]} list of credential names + */ + function _getMissingCredentials(properties: Mcdevrc): string[]; +} +//# sourceMappingURL=init.d.ts.map \ No newline at end of file diff --git a/@types/lib/util/init.d.ts.map b/@types/lib/util/init.d.ts.map new file mode 100644 index 000000000..c92f6461d --- /dev/null +++ b/@types/lib/util/init.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../../lib/util/init.js"],"names":[],"mappings":";yBAaa,OAAO,wBAAwB,EAAE,UAAU;uBAC3C,OAAO,wBAAwB,EAAE,QAAQ;oBACzC,OAAO,wBAAwB,EAAE,KAAK;0BACtC,OAAO,wBAAwB,EAAE,WAAW;8BAC5C,OAAO,wBAAwB,EAAE,eAAe;2BAChD,OAAO,wBAAwB,EAAE,YAAY;sBAC7C,OAAO,wBAAwB,EAAE,OAAO;+BACxC,OAAO,wBAAwB,EAAE,gBAAgB;mCACjD,OAAO,wBAAwB,EAAE,oBAAoB;kCACrD,OAAO,wBAAwB,EAAE,mBAAmB;8BACpD,OAAO,wBAAwB,EAAE,eAAe;iCAChD,OAAO,wBAAwB,EAAE,kBAAkB;oCACnD,OAAO,wBAAwB,EAAE,qBAAqB;mCACtD,OAAO,wBAAwB,EAAE,oBAAoB;gCACrD,OAAO,wBAAwB,EAAE,iBAAiB;0BAClD,OAAO,wBAAwB,EAAE,WAAW;2BAC5C,OAAO,wBAAwB,EAAE,YAAY;;IAQtD;;;;;;;OAOG;IACH,iCALW,OAAO,mBACP,MAAM,eACN,OAAO,GACL,OAAO,CAAE,IAAI,CAAC,CAwK1B;IAED;;;;OAIG;IACH,wBAFa,OAAO,CAAE,IAAI,CAAC,CAoE1B;IAED;;OAEG;IACH,uCAmDC;IAED;;;;;;OAMG;IACH,6BAJW,MAAM,aACN,MAAM,GACJ,OAAO,CAAE,IAAI,CAAC,CA8B1B;IAED;;;;;;;OAOG;IACH,oCALW,OAAO,YACP,OAAO,aACP,MAAM,GACJ,OAAO,CAAE,OAAO,CAAC,CAuC7B;IAED;;;;;OAKG;IACH,+BAFa,OAAO,CAAE,OAAO,CAAC,CA8C7B;IAED;;;;;;OAMG;IACH,4CAHW,OAAO,GACL,MAAM,EAAE,CAyBpB"} \ No newline at end of file diff --git a/@types/lib/util/init.git.d.ts b/@types/lib/util/init.git.d.ts new file mode 100644 index 000000000..7c6728907 --- /dev/null +++ b/@types/lib/util/init.git.d.ts @@ -0,0 +1,40 @@ +export default Init; +declare namespace Init { + /** + * check if git repo exists and otherwise create one + * + * @returns {Promise.<{status: string, repoName: string}>} success flag + */ + function initGitRepo(): Promise<{ + status: string; + repoName: string; + }>; + /** + * offer to push the new repo straight to the server + * + * @returns {Promise.<void>} - + */ + function gitPush(): Promise<void>; + /** + * offers to add the git remote origin + * + * @returns {Promise.<string>} repo name (optionally) + */ + function _addGitRemote(): Promise<string>; + /** + * checks global config and ask to config the user info and then store it locally + * + * @returns {Promise.<void>} - + */ + function _updateGitConfigUser(): Promise<void>; + /** + * retrieves the global user.name and user.email values + * + * @returns {Promise.<{'user.name': string, 'user.email': string}>} user.name and user.email + */ + function _getGitConfigUser(): Promise<{ + "user.name": string; + "user.email": string; + }>; +} +//# sourceMappingURL=init.git.d.ts.map \ No newline at end of file diff --git a/@types/lib/util/init.git.d.ts.map b/@types/lib/util/init.git.d.ts.map new file mode 100644 index 000000000..6e1a73b2c --- /dev/null +++ b/@types/lib/util/init.git.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"init.git.d.ts","sourceRoot":"","sources":["../../../lib/util/init.git.js"],"names":[],"mappings":";;IAcI;;;;OAIG;IACH,wBAFa,OAAO,CAAE;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAC,CAAC,CA4DxD;IAED;;;;OAIG;IACH,oBAFa,OAAO,CAAE,IAAI,CAAC,CAsC1B;IAED;;;;OAIG;IACH,0BAFa,OAAO,CAAE,MAAM,CAAC,CA2C5B;IAED;;;;OAIG;IACH,iCAFa,OAAO,CAAE,IAAI,CAAC,CAiE1B;IAED;;;;OAIG;IACH,8BAFa,OAAO,CAAE;QAAC,WAAW,EAAE,MAAM,CAAC;QAAC,YAAY,EAAE,MAAM,CAAA;KAAC,CAAC,CAOjE"} \ No newline at end of file diff --git a/@types/lib/util/init.npm.d.ts b/@types/lib/util/init.npm.d.ts new file mode 100644 index 000000000..b41200708 --- /dev/null +++ b/@types/lib/util/init.npm.d.ts @@ -0,0 +1,24 @@ +export default Init; +declare namespace Init { + /** + * initiates npm project and then + * takes care of loading the pre-configured dependency list + * from the boilerplate directory to them as dev-dependencies + * + * @param {string} [repoName] if git URL was provided earlier, the repo name was extracted to use it for npm init + * @returns {Promise.<boolean>} install successful or error occured + */ + function installDependencies(repoName?: string): Promise<boolean>; + /** + * ensure we have certain default values in our config + * + * @param {object} [currentContent] what was read from existing package.json file + * @returns {Promise.<{script: object, author: string, license: string}>} extended currentContent + */ + function _getDefaultPackageJson(currentContent?: object): Promise<{ + script: object; + author: string; + license: string; + }>; +} +//# sourceMappingURL=init.npm.d.ts.map \ No newline at end of file diff --git a/@types/lib/util/init.npm.d.ts.map b/@types/lib/util/init.npm.d.ts.map new file mode 100644 index 000000000..ea194b413 --- /dev/null +++ b/@types/lib/util/init.npm.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"init.npm.d.ts","sourceRoot":"","sources":["../../../lib/util/init.npm.js"],"names":[],"mappings":";;IAcI;;;;;;;OAOG;IACH,wCAHW,MAAM,GACJ,OAAO,CAAE,OAAO,CAAC,CA4G7B;IAED;;;;;OAKG;IACH,iDAHW,MAAM,GACJ,OAAO,CAAE;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAC,CAAC,CA8BvE"} \ No newline at end of file diff --git a/@types/lib/util/replaceContentBlockReference.d.ts b/@types/lib/util/replaceContentBlockReference.d.ts new file mode 100644 index 000000000..c0ad02c62 --- /dev/null +++ b/@types/lib/util/replaceContentBlockReference.d.ts @@ -0,0 +1,133 @@ +/** + * @typedef {import('../../types/mcdev.d.js').AuthObject} AuthObject + * @typedef {import('../../types/mcdev.d.js').BuObject} BuObject + * @typedef {import('../../types/mcdev.d.js').Cache} Cache + * @typedef {import('../../types/mcdev.d.js').CodeExtract} CodeExtract + * @typedef {import('../../types/mcdev.d.js').CodeExtractItem} CodeExtractItem + * @typedef {import('../../types/mcdev.d.js').DeltaPkgItem} DeltaPkgItem + * @typedef {import('../../types/mcdev.d.js').McdevLogger} McdevLogger + * @typedef {import('../../types/mcdev.d.js').Logger} Logger + * @typedef {import('../../types/mcdev.d.js').Mcdevrc} Mcdevrc + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItem} MetadataTypeItem + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItemDiff} MetadataTypeItemDiff + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItemObj} MetadataTypeItemObj + * @typedef {import('../../types/mcdev.d.js').MetadataTypeMap} MetadataTypeMap + * @typedef {import('../../types/mcdev.d.js').MetadataTypeMapObj} MetadataTypeMapObj + * @typedef {import('../../types/mcdev.d.js').MultiMetadataTypeList} MultiMetadataTypeList + * @typedef {import('../../types/mcdev.d.js').MultiMetadataTypeMap} MultiMetadataTypeMap + * @typedef {import('../../types/mcdev.d.js').SkipInteraction} SkipInteraction + * @typedef {import('../../types/mcdev.d.js').SoapRequestParams} SoapRequestParams + * @typedef {import('../../types/mcdev.d.js').TemplateMap} TemplateMap + * @typedef {import('../../types/mcdev.d.js').TypeKeyCombo} TypeKeyCombo + * @typedef {import('../../types/mcdev.d.js').SDKError} SDKError + * + * @typedef {import('../../types/mcdev.d.js').AssetMap} AssetMap + * @typedef {import('../../types/mcdev.d.js').AssetItemSimple} AssetItemSimple + * @typedef {import('../../types/mcdev.d.js').AssetItemSimpleMap} AssetItemSimpleMap + * @typedef {import('../../types/mcdev.d.js').AssetItemIdSimpleMap} AssetItemIdSimpleMap + * @typedef {import('../../types/mcdev.d.js').ContentBlockConversionTypes} ContentBlockConversionTypes + */ +/** + * Util that contains logger and simple util methods + */ +export default class ReplaceContentBlockReference { + /** @type {{id: AssetItemIdSimpleMap, key: AssetItemSimpleMap, name: AssetItemSimpleMap}} */ + static assetCacheMap: { + id: AssetItemIdSimpleMap; + key: AssetItemSimpleMap; + name: AssetItemSimpleMap; + }; + /** @type {Object.<string, {id: RegExp[], key: RegExp[], name: RegExp[]}>} */ + static "__#private@#regexBy": { + [x: string]: { + id: RegExp[]; + key: RegExp[]; + name: RegExp[]; + }; + }; + /** + * helper for tests + */ + static resetCacheMap(): void; + /** + * used to equalize the reference in the code to whatever is set in the "to" field + * + * @param {string} str full code string + * @param {string} parentName name of the object that was passed in; used in error message only + * @param {Set.<string>} [findAssetKeys] list of keys that were found referenced via ContentBlockByX; if set, method only gets keys and runs no updates + * @returns {string} replaced string + */ + static replaceReference(str: string, parentName: string, findAssetKeys?: Set<string>): string; + /** + * + * @param {ContentBlockConversionTypes} from replace with + * @param {string|number} identifier id, key or name of asset + * @param {string} parentName name of the object that was passed in; used in error message only + * @param {boolean} [isSsjs] replaces backslashes with double backslashes in name if true + * @param {boolean} [handleOutside] don not print error message if asset not found + * @returns {AssetItemSimple} asset object + */ + static "__#private@#getAssetBy"(from: ContentBlockConversionTypes, identifier: string | number, parentName: string, isSsjs?: boolean, handleOutside?: boolean): AssetItemSimple; + /** + * + * @param {AssetItemSimple} asset asset object + * @param {ContentBlockConversionTypes} to replace with + * @param {boolean} [isSsjs] replaces backslashes with double backslashes in name if true + * @returns {string} replaced string + */ + static "__#private@#replaceWith"(asset: AssetItemSimple, to: ContentBlockConversionTypes, isSsjs?: boolean): string; + /** + * ensures we cache the right things from disk and if required from server + * + * @param {Mcdevrc} properties properties for auth + * @param {BuObject} buObject properties for auth + * @param {boolean} [retrieveSharedOnly] for --dependencies only, do not have to re-retrieve local assets + * @returns {Promise.<void>} - + */ + static createCache(properties: Mcdevrc, buObject: BuObject, retrieveSharedOnly?: boolean): Promise<void>; + /** + * helper for {@link ReplaceContentBlockReference.createCache} that converts AssetMap into AssetItemSimple entries in this.assetCacheMap + * + * @param {AssetMap} metadataMap list of local or shared assets + */ + static createCacheForMap(metadataMap: AssetMap): void; + /** + * helper for {@link ReplaceContentBlockReference.createCache} + * + * @param {BuObject} buObject references credentials + * @param {Mcdevrc} properties central properties object + * @param {boolean} [retrieveSharedOnly] for --dependencies only, do not have to re-retrieve local assets + * @returns {Promise.<{localAssets: AssetMap, sharedAssets: AssetMap}>} - + */ + static _retrieveCache(buObject: BuObject, properties: Mcdevrc, retrieveSharedOnly?: boolean): Promise<{ + localAssets: AssetMap; + sharedAssets: AssetMap; + }>; +} +export type AuthObject = import("../../types/mcdev.d.js").AuthObject; +export type BuObject = import("../../types/mcdev.d.js").BuObject; +export type Cache = import("../../types/mcdev.d.js").Cache; +export type CodeExtract = import("../../types/mcdev.d.js").CodeExtract; +export type CodeExtractItem = import("../../types/mcdev.d.js").CodeExtractItem; +export type DeltaPkgItem = import("../../types/mcdev.d.js").DeltaPkgItem; +export type McdevLogger = import("../../types/mcdev.d.js").McdevLogger; +export type Logger = import("../../types/mcdev.d.js").Logger; +export type Mcdevrc = import("../../types/mcdev.d.js").Mcdevrc; +export type MetadataTypeItem = import("../../types/mcdev.d.js").MetadataTypeItem; +export type MetadataTypeItemDiff = import("../../types/mcdev.d.js").MetadataTypeItemDiff; +export type MetadataTypeItemObj = import("../../types/mcdev.d.js").MetadataTypeItemObj; +export type MetadataTypeMap = import("../../types/mcdev.d.js").MetadataTypeMap; +export type MetadataTypeMapObj = import("../../types/mcdev.d.js").MetadataTypeMapObj; +export type MultiMetadataTypeList = import("../../types/mcdev.d.js").MultiMetadataTypeList; +export type MultiMetadataTypeMap = import("../../types/mcdev.d.js").MultiMetadataTypeMap; +export type SkipInteraction = import("../../types/mcdev.d.js").SkipInteraction; +export type SoapRequestParams = import("../../types/mcdev.d.js").SoapRequestParams; +export type TemplateMap = import("../../types/mcdev.d.js").TemplateMap; +export type TypeKeyCombo = import("../../types/mcdev.d.js").TypeKeyCombo; +export type SDKError = import("../../types/mcdev.d.js").SDKError; +export type AssetMap = import("../../types/mcdev.d.js").AssetMap; +export type AssetItemSimple = import("../../types/mcdev.d.js").AssetItemSimple; +export type AssetItemSimpleMap = import("../../types/mcdev.d.js").AssetItemSimpleMap; +export type AssetItemIdSimpleMap = import("../../types/mcdev.d.js").AssetItemIdSimpleMap; +export type ContentBlockConversionTypes = import("../../types/mcdev.d.js").ContentBlockConversionTypes; +//# sourceMappingURL=replaceContentBlockReference.d.ts.map \ No newline at end of file diff --git a/@types/lib/util/replaceContentBlockReference.d.ts.map b/@types/lib/util/replaceContentBlockReference.d.ts.map new file mode 100644 index 000000000..c6dfbff26 --- /dev/null +++ b/@types/lib/util/replaceContentBlockReference.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"replaceContentBlockReference.d.ts","sourceRoot":"","sources":["../../../lib/util/replaceContentBlockReference.js"],"names":[],"mappings":"AAUA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAEH;;GAEG;AACH;IACI,4FAA4F;IAC5F,sBADW;QAAC,EAAE,EAAE,oBAAoB,CAAC;QAAC,GAAG,EAAE,kBAAkB,CAAC;QAAC,IAAI,EAAE,kBAAkB,CAAA;KAAC,CAKtF;IACF,6EAA6E;IAC7E;;gBADgC,MAAM,EAAE;iBAAO,MAAM,EAAE;kBAAQ,MAAM,EAAE;;MAkCrE;IAEF;;OAEG;IACH,6BAMC;IAED;;;;;;;OAOG;IACH,6BALW,MAAM,cACN,MAAM,kBACN,GAAG,CAAE,MAAM,CAAC,GACV,MAAM,CAgElB;IAED;;;;;;;;OAQG;IACH,sCAPW,2BAA2B,cAC3B,MAAM,GAAC,MAAM,cACb,MAAM,WACN,OAAO,kBACP,OAAO,GACL,eAAe,CAyB3B;IAED;;;;;;OAMG;IACH,wCALW,eAAe,MACf,2BAA2B,WAC3B,OAAO,GACL,MAAM,CAclB;IAED;;;;;;;OAOG;IACH,+BALW,OAAO,YACP,QAAQ,uBACR,OAAO,GACL,OAAO,CAAE,IAAI,CAAC,CAW1B;IAED;;;;OAIG;IACH,sCAFW,QAAQ,QA0BlB;IAED;;;;;;;OAOG;IACH,gCALW,QAAQ,cACR,OAAO,uBACP,OAAO,GACL,OAAO,CAAE;QAAC,WAAW,EAAE,QAAQ,CAAC;QAAC,YAAY,EAAE,QAAQ,CAAA;KAAC,CAAC,CAoErE;CACJ;yBAlVY,OAAO,wBAAwB,EAAE,UAAU;uBAC3C,OAAO,wBAAwB,EAAE,QAAQ;oBACzC,OAAO,wBAAwB,EAAE,KAAK;0BACtC,OAAO,wBAAwB,EAAE,WAAW;8BAC5C,OAAO,wBAAwB,EAAE,eAAe;2BAChD,OAAO,wBAAwB,EAAE,YAAY;0BAC7C,OAAO,wBAAwB,EAAE,WAAW;qBAC5C,OAAO,wBAAwB,EAAE,MAAM;sBACvC,OAAO,wBAAwB,EAAE,OAAO;+BACxC,OAAO,wBAAwB,EAAE,gBAAgB;mCACjD,OAAO,wBAAwB,EAAE,oBAAoB;kCACrD,OAAO,wBAAwB,EAAE,mBAAmB;8BACpD,OAAO,wBAAwB,EAAE,eAAe;iCAChD,OAAO,wBAAwB,EAAE,kBAAkB;oCACnD,OAAO,wBAAwB,EAAE,qBAAqB;mCACtD,OAAO,wBAAwB,EAAE,oBAAoB;8BACrD,OAAO,wBAAwB,EAAE,eAAe;gCAChD,OAAO,wBAAwB,EAAE,iBAAiB;0BAClD,OAAO,wBAAwB,EAAE,WAAW;2BAC5C,OAAO,wBAAwB,EAAE,YAAY;uBAC7C,OAAO,wBAAwB,EAAE,QAAQ;uBAEzC,OAAO,wBAAwB,EAAE,QAAQ;8BACzC,OAAO,wBAAwB,EAAE,eAAe;iCAChD,OAAO,wBAAwB,EAAE,kBAAkB;mCACnD,OAAO,wBAAwB,EAAE,oBAAoB;0CACrD,OAAO,wBAAwB,EAAE,2BAA2B"} \ No newline at end of file diff --git a/@types/lib/util/util.d.ts b/@types/lib/util/util.d.ts new file mode 100644 index 000000000..b8bfcdc36 --- /dev/null +++ b/@types/lib/util/util.d.ts @@ -0,0 +1,427 @@ +export namespace Util { + let authFileName: string; + let boilerplateDirectory: string; + let configFileName: string; + let defaultGitBranch: string; + let parentBuName: string; + let standardizedSplitChar: string; + let folderNameSlashEscapeChar: string; + let skipInteraction: SkipInteraction; + let packageJsonMcdev: any; + let OPTIONS: {}; + let changedKeysMap: {}; + let matchedByName: {}; + /** + * helper that allows filtering an object by its keys + * + * @param {Object.<string,*>} originalObj object that you want to filter + * @param {string[]} [whitelistArr] positive filter. if not provided, returns originalObj without filter + * @returns {Object.<string,*>} filtered object that only contains keys you provided + */ + function filterObjByKeys(originalObj: { + [x: string]: any; + }, whitelistArr?: string[]): { + [x: string]: any; + }; + /** + * extended Array.includes method that allows check if an array-element starts with a certain string + * + * @param {string[]} arr your array of strigns + * @param {string} search the string you are looking for + * @returns {boolean} found / not found + */ + function includesStartsWith(arr: string[], search: string): boolean; + /** + * extended Array.includes method that allows check if an array-element starts with a certain string + * + * @param {string[]} arr your array of strigns + * @param {string} search the string you are looking for + * @returns {number} array index 0..n or -1 of not found + */ + function includesStartsWithIndex(arr: string[], search: string): number; + /** + * check if a market name exists in current mcdev config + * + * @param {string} market market localizations + * @param {Mcdevrc} properties local mcdev config + * @returns {boolean} found market or not + */ + function checkMarket(market: string, properties: Mcdevrc): boolean; + /** + * check if a market name exists in current mcdev config + * + * @param {string[]} marketArr market localizations + * @param {Mcdevrc} properties local mcdev config + * @returns {boolean} found market or not + */ + function checkMarketList(marketArr: string[], properties: Mcdevrc): boolean; + /** + * ensure provided MarketList exists and it's content including markets and BUs checks out + * + * @param {string} mlName name of marketList + * @param {Mcdevrc} properties General configuration to be used in retrieve + */ + function verifyMarketList(mlName: string, properties: Mcdevrc): void; + /** + * + * @param {string | TypeKeyCombo} selectedTypes supported metadata type + * @param {string[]} [keyArr] name/key of the metadata + * @param {string} [commandName] for log output only + * @returns {TypeKeyCombo | undefined} true if everything is valid; false otherwise + */ + function checkAndPrepareTypeKeyCombo(selectedTypes: string | TypeKeyCombo, keyArr?: string[], commandName?: string): TypeKeyCombo | undefined; + /** + * used to ensure the program tells surrounding software that an unrecoverable error occured + * + * @returns {void} + */ + function signalFatalError(): void; + /** + * SFMC accepts multiple true values for Boolean attributes for which we are checking here. + * The same problem occurs when evaluating boolean CLI flags + * + * @param {*} attrValue value + * @returns {boolean} attribute value == true ? true : false + */ + function isTrue(attrValue: any): boolean; + /** + * SFMC accepts multiple false values for Boolean attributes for which we are checking here. + * The same problem occurs when evaluating boolean CLI flags + * + * @param {*} attrValue value + * @returns {boolean} attribute value == false ? true : false + */ + function isFalse(attrValue: any): boolean; + function isEqual(item1: string | number | boolean | any[] | object, item2: string | number | boolean | any[] | object): boolean; + function _isEqualArray(array1: any[], array2: any[]): boolean; + function _isEqualObject(item1: object, item2: object): boolean; + /** + * helper for Mcdev.retrieve, Mcdev.retrieveAsTemplate and Mcdev.deploy + * + * @param {string} selectedType type or type-subtype + * @param {boolean} [handleOutside] if the API reponse is irregular this allows you to handle it outside of this generic method + * @returns {boolean} type ok or not + */ + function _isValidType(selectedType: string, handleOutside?: boolean): boolean; + /** + * helper for Mcdev.retrieve, Mcdev.retrieveAsTemplate and Mcdev.deploy + * + * @param {Mcdevrc} properties javascript object in .mcdevrc.json + * @param {string} businessUnit name of BU + * @param {boolean} [handleOutside] if the API reponse is irregular this allows you to handle it outside of this generic method + * @returns {boolean} bu found or not + */ + function isValidBU(properties: Mcdevrc, businessUnit: string, handleOutside?: boolean): boolean; + /** + * helper that deals with extracting type and subtype + * + * @param {string} selectedType "type" or "type-subtype" + * @returns {{type:string, subType:string}} first elem is type, second elem is subType + */ + function getTypeAndSubType(selectedType: string): { + type: string; + subType: string; + }; + /** + * helper for getDefaultProperties() + * + * @param {'typeRetrieveByDefault'|'typeCdpByDefault'} field relevant field in type definition + * @returns {string[]} type choices + */ + function getTypeChoices(field: "typeRetrieveByDefault" | "typeCdpByDefault"): string[]; + /** + * helper for cli.selectTypes and init.config.fixMcdevConfig that converts subtypes back to main type if all and only defaults were selected + * this keeps the config automatically upgradable when we add new subtypes or change what is selected by default + * + * @param {'typeRetrieveByDefault'|'typeCdpByDefault'} field relevant field in type definition + * @param {string[]} selectedTypes what types the user selected + * @param {'asset'} [type] metadata type + * @returns {string[]} filtered selectedTypes + */ + function summarizeSubtypes(field: "typeRetrieveByDefault" | "typeCdpByDefault", selectedTypes: string[], type?: "asset"): string[]; + let logFileName: string; + function _createNewLoggerTransport(noLogFile?: boolean): object; + let loggerTransports: any; + let logger: Logger; + function startLogger(restart?: boolean, noLogFile?: boolean): void; + function metadataLogger(level: string, type: string, method: string, payload: any, source?: string): void; + function replaceByObject(str: string | object, obj: TemplateMap): string | object; + function inverseGet(objs: object, val: string | number): string; + /** + *helper for Mcdev.fixKeys. Retrieve dependent metadata + * + * @param {string} fixedType type of the metadata passed as a parameter to fixKeys function + * @returns {string[]} array of types that depend on the given type + */ + function getDependentMetadata(fixedType: string): string[]; + /** + * Returns Order in which metadata needs to be retrieved/deployed + * + * @param {string[]} typeArr which should be retrieved/deployed + * @returns {Object.<string, string[]>} retrieve/deploy order as array + */ + function getMetadataHierachy(typeArr: string[]): { + [x: string]: string[]; + }; + /** + * let's you dynamically walk down an object and get a value + * + * @param {string} path 'fieldA.fieldB.fieldC' + * @param {object} obj some parent object + * @returns {any} value of obj.path + */ + function resolveObjPath(path: string, obj: object): any; + /** + * helper to run other commands as if run manually by user + * + * @param {string} cmd to be executed command + * @param {string[]} [args] list of arguments + * @param {boolean} [hideOutput] if true, output of command will be hidden from CLI + * @returns {string|void} output of command if hideOutput is true + */ + function execSync(cmd: string, args?: string[], hideOutput?: boolean): string | void; + /** + * standardize check to ensure only one result is returned from template search + * + * @param {MetadataTypeItem[]} results array of metadata + * @param {string} keyToSearch the field which contains the searched value + * @param {string} searchValue the value which is being looked for + * @returns {MetadataTypeItem} metadata to be used in building template + */ + function templateSearchResult(results: MetadataTypeItem[], keyToSearch: string, searchValue: string): MetadataTypeItem; + /** + * configures what is displayed in the console + * + * @param {object} argv list of command line parameters given by user + * @param {boolean} [argv.silent] only errors printed to CLI + * @param {boolean} [argv.verbose] chatty user CLI output + * @param {boolean} [argv.debug] enables developer output & features + * @returns {void} + */ + function setLoggingLevel(argv: { + silent?: boolean; + verbose?: boolean; + debug?: boolean; + }): void; + /** + * outputs a warning that the given type is still in beta + * + * @param {string} type api name of the type thats in beta + */ + function logBeta(type: string): void; + /** + * outputs a warning that the given method is deprecated + * + * @param {string} method name of the method + * @param {string} [useInstead] optionally specify which method to use instead + */ + function logDeprecated(method: string, useInstead?: string): void; + function logNotSupported(definition: any, method: string, item?: MetadataTypeItem): void; + namespace color { + let reset: string; + let dim: string; + let bright: string; + let underscore: string; + let blink: string; + let reverse: string; + let hidden: string; + let fgBlack: string; + let fgRed: string; + let fgGreen: string; + let fgYellow: string; + let fgBlue: string; + let fgMagenta: string; + let fgCyan: string; + let fgWhite: string; + let fgGray: string; + let bgBlack: string; + let bgRed: string; + let bgGreen: string; + let bgYellow: string; + let bgBlue: string; + let bgMagenta: string; + let bgCyan: string; + let bgWhite: string; + let bgGray: string; + } + /** + * helper that wraps a message in the correct color codes to have them printed gray + * + * @param {string} msg log message that should be wrapped with color codes + * @returns {string} gray msg + */ + function getGrayMsg(msg: string): string; + /** + * helper that returns the prefix of item specific log messages + * + * @param {any} definition metadata definition + * @param {MetadataTypeItem} metadataItem metadata item + * @returns {string} msg prefix + */ + function getMsgPrefix(definition: any, metadataItem: MetadataTypeItem): string; + /** + * helper that returns the prefix of item specific log messages + * + * @param {any} definition metadata definition + * @param {MetadataTypeItem} metadataItem metadata item + * @returns {string} key or key/name combo + */ + function getTypeKeyName(definition: any, metadataItem: MetadataTypeItem): string; + /** + * helper that returns the prefix of item specific log messages + * + * @param {any} definition metadata definition + * @param {MetadataTypeItem} metadataItem metadata item + * @returns {string} key or key/name combo + */ + function getKeyName(definition: any, metadataItem: MetadataTypeItem): string; + /** + * helper to print the subtypes we filtered by + * + * @param {string[]} subTypeArr list of subtypes to be printed + * @param {string} [indent] optional prefix of spaces to be added to the log message + * @returns {void} + */ + function logSubtypes(subTypeArr: string[], indent?: string): void; + /** + * helper to print the subtypes we filtered by + * + * @param {string[] | string} keyArr list of subtypes to be printed + * @param {boolean} [isId] optional flag to indicate if key is an id + * @returns {string} string to be appended to log message + */ + function getKeysString(keyArr: string[] | string, isId?: boolean): string; + /** + * pause execution of code; useful when multiple server calls are dependent on each other and might not be executed right away + * + * @param {number} ms time in miliseconds to wait + * @returns {Promise.<void>} - promise to wait for + */ + function sleep(ms: number): Promise<void>; + /** + * helper for Asset.extractCode and Script.prepExtractedCode to determine if a code block is a valid SSJS block + * + * @example the following is invalid: + * <script runat="server"> + * // 1 + * </script> + * <script runat="server"> + * // 2 + * </script> + * + * the following is valid: + * <script runat="server"> + * // 3 + * </script> + * @param {string} code code block to check + * @returns {string} the SSJS code if code block is a valid SSJS block, otherwise null + */ + function getSsjs(code: string): string; + /** + * allows us to filter just like with SQL's LIKE operator + * + * @param {string} testString field value to test + * @param {string} search search string in SQL LIKE format + * @returns {boolean} true if testString matches search + */ + function stringLike(testString: string, search: string): boolean; + /** + * returns true if no LIKE filter is defined or if all filters match + * + * @param {MetadataTypeItem} metadata a single metadata item + * @param {object} definition type definition + * @param {object} [filters] only used in recursive calls + * @returns {boolean} true if no LIKE filter is defined or if all filters match + */ + function fieldsLike(metadata: MetadataTypeItem, definition: object, filters?: object): boolean; + /** + * helper used by SOAP methods to ensure the type always uses an upper-cased first letter + * + * @param {string} str string to capitalize + * @returns {string} str with first letter capitalized + */ + function capitalizeFirstLetter(str: string): string; + /** + * helper for Retriever and Deployer class + * + * @param {string | string[]} typeArr - + * @param {string[]} keyArr - + * @param {boolean} [returnEmpty] returns array with null element if false/not set; Retriever needs this to be false; Deployer needs it to be true + * @returns {TypeKeyCombo} - + */ + function createTypeKeyCombo(typeArr: string | string[], keyArr: string[], returnEmpty?: boolean): TypeKeyCombo; + /** + * helper that converts TypeKeyCombo objects into a string with all relevant -m parameters + * + * @param {TypeKeyCombo} [selectedTypes] selected metadata types & key + * @returns {string} object converted into --metadata parameters + */ + function convertTypeKeyToCli(selectedTypes?: TypeKeyCombo): string; + /** + * helper that converts TypeKeyCombo objects into a string with all relevant -m parameters + * + * @param {TypeKeyCombo} [selectedTypes] selected metadata types & key + * @returns {string} object converted into --metadata parameters + */ + function convertTypeKeyToString(selectedTypes?: TypeKeyCombo): string; + /** + * helper that checks how many keys are defined in TypeKeyCombo object + * + * @param {TypeKeyCombo} [selectedTypes] selected metadata types & key + * @returns {number} amount of keys across all types + */ + function getTypeKeyCount(selectedTypes?: TypeKeyCombo): number; + /** + * async version of Array.find() + * returns the first element in the provided array that satisfies the provided testin function + * + * @param {Array} arr your test array + * @param {Function} asyncCallback callback + * @returns {Promise.<any | undefined>} first element that passed the test + */ + function findAsync(arr: any[], asyncCallback: Function): Promise<any | undefined>; + /** + * + * @param {Array} array array to be chunked + * @param {number} chunk_size integer > 0 + * @returns {Array[]} array of arrays with max chunk_size members per element, last element might have less + */ + function chunk(array: any[], chunk_size: number): any[][]; + /** + * recursively find all values of the given key in the object + * + * @param {any} object data to search in + * @param {string} key attribute to find + * @returns {Array} all values of the given key + */ + function findLeafVals(object: any, key: string): any[]; + /** + * helper that returns a new object with sorted attributes of the given object + * + * @param {object} obj object with unsorted attributes + * @returns {object} obj but with sorted attributes + */ + function sortObjectAttributes(obj: object): object; +} +export type AuthObject = import("../../types/mcdev.d.js").AuthObject; +export type BuObject = import("../../types/mcdev.d.js").BuObject; +export type Cache = import("../../types/mcdev.d.js").Cache; +export type CodeExtract = import("../../types/mcdev.d.js").CodeExtract; +export type CodeExtractItem = import("../../types/mcdev.d.js").CodeExtractItem; +export type DeltaPkgItem = import("../../types/mcdev.d.js").DeltaPkgItem; +export type McdevLogger = import("../../types/mcdev.d.js").McdevLogger; +export type Logger = import("../../types/mcdev.d.js").Logger; +export type Mcdevrc = import("../../types/mcdev.d.js").Mcdevrc; +export type MetadataTypeItem = import("../../types/mcdev.d.js").MetadataTypeItem; +export type MetadataTypeItemDiff = import("../../types/mcdev.d.js").MetadataTypeItemDiff; +export type MetadataTypeItemObj = import("../../types/mcdev.d.js").MetadataTypeItemObj; +export type MetadataTypeMap = import("../../types/mcdev.d.js").MetadataTypeMap; +export type MetadataTypeMapObj = import("../../types/mcdev.d.js").MetadataTypeMapObj; +export type MultiMetadataTypeList = import("../../types/mcdev.d.js").MultiMetadataTypeList; +export type MultiMetadataTypeMap = import("../../types/mcdev.d.js").MultiMetadataTypeMap; +export type SkipInteraction = import("../../types/mcdev.d.js").SkipInteraction; +export type SoapRequestParams = import("../../types/mcdev.d.js").SoapRequestParams; +export type TemplateMap = import("../../types/mcdev.d.js").TemplateMap; +export type TypeKeyCombo = import("../../types/mcdev.d.js").TypeKeyCombo; +export type SDKError = import("../../types/mcdev.d.js").SDKError; +//# sourceMappingURL=util.d.ts.map \ No newline at end of file diff --git a/@types/lib/util/util.d.ts.map b/@types/lib/util/util.d.ts.map new file mode 100644 index 000000000..d9b7b42e5 --- /dev/null +++ b/@types/lib/util/util.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"util.d.ts","sourceRoot":"","sources":["../../../lib/util/util.js"],"names":[],"mappings":";;;;;;;;yBAiDe,eAAe;;;;;IAO1B;;;;;;OAMG;IACH;;sBAHW,MAAM,EAAE;;MAalB;IAED;;;;;;OAMG;IACH,iCAJW,MAAM,EAAE,UACR,MAAM,GACJ,OAAO,CAInB;IAED;;;;;;OAMG;IACH,sCAJW,MAAM,EAAE,UACR,MAAM,GACJ,MAAM,CAIlB;IAED;;;;;;OAMG;IACH,6BAJW,MAAM,cACN,OAAO,GACL,OAAO,CAcnB;IAED;;;;;;OAMG;IACH,oCAJW,MAAM,EAAE,cACR,OAAO,GACL,OAAO,CAYnB;IAED;;;;;OAKG;IACH,kCAHW,MAAM,cACN,OAAO,QAqCjB;IACD;;;;;;OAMG;IACH,oDALW,MAAM,GAAG,YAAY,WACrB,MAAM,EAAE,gBACR,MAAM,GACJ,YAAY,GAAG,SAAS,CAwBpC;IAED;;;;OAIG;IACH,6BAFa,IAAI,CAKhB;IAED;;;;;;OAMG;IACH,2BAHW,GAAC,GACC,OAAO,CAInB;IAED;;;;;;OAMG;IACH,4BAHW,GAAC,GACC,OAAO,CAInB;IAQQ,wBAJE,MAAM,GAAG,MAAM,GAAG,OAAO,WAAW,MAAM,SAC1C,MAAM,GAAG,MAAM,GAAG,OAAO,WAAW,MAAM,GACxC,OAAO,CAgBnB;IAQc,sDAFF,OAAO,CAQnB;IAQe,+BAJL,MAAM,SACN,MAAM,GACJ,OAAO,CAYnB;IAED;;;;;;OAMG;IACH,oCAJW,MAAM,kBACN,OAAO,GACL,OAAO,CAoBnB;IAED;;;;;;;OAOG;IACH,+BALW,OAAO,gBACP,MAAM,kBACN,OAAO,GACL,OAAO,CAgBnB;IAED;;;;;OAKG;IACH,yCAHW,MAAM,GACJ;QAAC,IAAI,EAAC,MAAM,CAAC;QAAC,OAAO,EAAC,MAAM,CAAA;KAAC,CAWzC;IAED;;;;;OAKG;IACH,+BAHW,uBAAuB,GAAC,kBAAkB,GACxC,MAAM,EAAE,CA2BpB;IACD;;;;;;;;OAQG;IACH,kCALW,uBAAuB,GAAC,kBAAkB,iBAC1C,MAAM,EAAE,SACR,OAAO,GACL,MAAM,EAAE,CAmBpB;qBAEU,MAAM;IASU,+CAHhB,OAAO,GACL,MAAM,CAqElB;;gBAMS,MAAM;IAWH,+BAJF,OAAO,cACP,OAAO,GACL,IAAI,CAsFhB;IAYe,+BAPL,MAAM,QACN,MAAM,UACN,MAAM,WACN,GAAC,WACD,MAAM,GACJ,IAAI,CAiBhB;IAUgB,8BAJN,MAAM,GAAG,MAAM,OACf,WAAW,GACT,MAAM,GAAG,MAAM,CA2B3B;IASW,0BAJD,MAAM,OACN,MAAM,GAAG,MAAM,GACb,MAAM,CASlB;IAED;;;;;OAKG;IACH,yCAHW,MAAM,GACJ,MAAM,EAAE,CAmBpB;IAED;;;;;OAKG;IACH,sCAHW,MAAM,EAAE;;MAuFlB;IAED;;;;;;OAMG;IACH,8BAJW,MAAM,OACN,MAAM,GACJ,GAAG,CAIf;IAED;;;;;;;OAOG;IACH,uBALW,MAAM,SACN,MAAM,EAAE,eACR,OAAO,GACL,MAAM,GAAC,IAAI,CAuBvB;IAED;;;;;;;OAOG;IACH,uCALW,gBAAgB,EAAE,eAClB,MAAM,eACN,MAAM,GACJ,gBAAgB,CAc5B;IAED;;;;;;;;OAQG;IACH,+BALG;QAAuB,MAAM,GAArB,OAAO;QACQ,OAAO,GAAtB,OAAO;QACQ,KAAK,GAApB,OAAO;KACf,GAAU,IAAI,CA2BhB;IAED;;;;OAIG;IACH,uBAFW,MAAM,QAMhB;IAED;;;;;OAKG;IACH,+BAHW,MAAM,eACN,MAAM,QAMhB;IASgB,qCAJN,GAAG,UACH,MAAM,SACN,gBAAgB,QAM1B;;;;;;;;;;;;;;;;;;;;;;;;;;;;IAiCD;;;;;OAKG;IACH,yBAHW,MAAM,GACJ,MAAM,CAIlB;IAED;;;;;;OAMG;IACH,kCAJW,GAAG,gBACH,gBAAgB,GACd,MAAM,CAIlB;IAED;;;;;;OAMG;IACH,oCAJW,GAAG,gBACH,gBAAgB,GACd,MAAM,CAIlB;IAED;;;;;;OAMG;IACH,gCAJW,GAAG,gBACH,gBAAgB,GACd,MAAM,CAOlB;IAED;;;;;;OAMG;IACH,iCAJW,MAAM,EAAE,WACR,MAAM,GACJ,IAAI,CAUhB;IAED;;;;;;OAMG;IACH,+BAJW,MAAM,EAAE,GAAG,MAAM,SACjB,OAAO,GACL,MAAM,CAgBlB;IAED;;;;;OAKG;IACH,mBAHW,MAAM,GACJ,OAAO,CAAE,IAAI,CAAC,CAU1B;IAED;;;;;;;;;;;;;;;;;OAiBG;IACH,uBAHW,MAAM,GACJ,MAAM,CAoClB;IAED;;;;;;OAMG;IACH,gCAJW,MAAM,UACN,MAAM,GACJ,OAAO,CAoBnB;IAED;;;;;;;OAOG;IACH,8BALW,gBAAgB,cAChB,MAAM,YACN,MAAM,GACJ,OAAO,CAuCnB;IAED;;;;;OAKG;IACH,oCAHW,MAAM,GACJ,MAAM,CAIlB;IAED;;;;;;;OAOG;IACH,qCALW,MAAM,GAAG,MAAM,EAAE,UACjB,MAAM,EAAE,gBACR,OAAO,GACL,YAAY,CAkBxB;IAED;;;;;OAKG;IACH,6CAHW,YAAY,GACV,MAAM,CAelB;IAED;;;;;OAKG;IACH,gDAHW,YAAY,GACV,MAAM,CA4BlB;IAED;;;;;OAKG;IACH,yCAHW,YAAY,GACV,MAAM,CAQlB;IAED;;;;;;;OAOG;IACH,yDAFa,OAAO,CAAE,GAAG,GAAG,SAAS,CAAC,CAQrC;IAED;;;;;OAKG;IACH,yCAHW,MAAM,GACJ,OAAO,CAMnB;IACD;;;;;;OAMG;IACH,8BAJW,GAAG,OACH,MAAM,SAehB;IACD;;;;;OAKG;IACH,mCAHW,MAAM,GACJ,MAAM,CASlB;;yBAl0CQ,OAAO,wBAAwB,EAAE,UAAU;uBAC3C,OAAO,wBAAwB,EAAE,QAAQ;oBACzC,OAAO,wBAAwB,EAAE,KAAK;0BACtC,OAAO,wBAAwB,EAAE,WAAW;8BAC5C,OAAO,wBAAwB,EAAE,eAAe;2BAChD,OAAO,wBAAwB,EAAE,YAAY;0BAC7C,OAAO,wBAAwB,EAAE,WAAW;qBAC5C,OAAO,wBAAwB,EAAE,MAAM;sBACvC,OAAO,wBAAwB,EAAE,OAAO;+BACxC,OAAO,wBAAwB,EAAE,gBAAgB;mCACjD,OAAO,wBAAwB,EAAE,oBAAoB;kCACrD,OAAO,wBAAwB,EAAE,mBAAmB;8BACpD,OAAO,wBAAwB,EAAE,eAAe;iCAChD,OAAO,wBAAwB,EAAE,kBAAkB;oCACnD,OAAO,wBAAwB,EAAE,qBAAqB;mCACtD,OAAO,wBAAwB,EAAE,oBAAoB;8BACrD,OAAO,wBAAwB,EAAE,eAAe;gCAChD,OAAO,wBAAwB,EAAE,iBAAiB;0BAClD,OAAO,wBAAwB,EAAE,WAAW;2BAC5C,OAAO,wBAAwB,EAAE,YAAY;uBAC7C,OAAO,wBAAwB,EAAE,QAAQ"} \ No newline at end of file diff --git a/@types/lib/util/validations.d.ts b/@types/lib/util/validations.d.ts new file mode 100644 index 000000000..e3567c6cb --- /dev/null +++ b/@types/lib/util/validations.d.ts @@ -0,0 +1,14 @@ +/** + * + * @param {any} definition type definition + * @param {any} item MetadataItem + * @param {string} targetDir folder in which the MetadataItem is deployed from (deploy/cred/bu) + * @param {CodeExtract[]} [codeExtractItemArr] array of code snippets + * @returns {Promise.<validationRuleList>} MetadataItem + */ +export default function validation(definition: any, item: any, targetDir: string, codeExtractItemArr?: CodeExtract[]): Promise<validationRuleList>; +export type validationRuleList = import("../../types/mcdev.d.js").validationRuleList; +export type validationRuleFix = import("../../types/mcdev.d.js").validationRuleFix; +export type validationRuleTest = import("../../types/mcdev.d.js").validationRuleTest; +export type CodeExtract = import("../../types/mcdev.d.js").CodeExtract; +//# sourceMappingURL=validations.d.ts.map \ No newline at end of file diff --git a/@types/lib/util/validations.d.ts.map b/@types/lib/util/validations.d.ts.map new file mode 100644 index 000000000..a58e87ac0 --- /dev/null +++ b/@types/lib/util/validations.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"validations.d.ts","sourceRoot":"","sources":["../../../lib/util/validations.js"],"names":[],"mappings":"AAqCA;;;;;;;GAOG;AACH,+CANW,GAAG,QACH,GAAG,aACH,MAAM,uBACN,WAAW,EAAE,GACX,OAAO,CAAE,kBAAkB,CAAC,CAuHxC;iCA7JY,OAAO,wBAAwB,EAAE,kBAAkB;gCACnD,OAAO,wBAAwB,EAAE,iBAAiB;iCAClD,OAAO,wBAAwB,EAAE,kBAAkB;0BACnD,OAAO,wBAAwB,EAAE,WAAW"} \ No newline at end of file diff --git a/@types/types/mcdev.d.d.ts b/@types/types/mcdev.d.d.ts new file mode 100644 index 000000000..b2e886167 --- /dev/null +++ b/@types/types/mcdev.d.d.ts @@ -0,0 +1,2145 @@ +declare const _default: {}; +export default _default; +export type BuObject = { + /** + * installed package client id + */ + clientId?: string; + /** + * installed package client secret + */ + clientSecret?: string; + /** + * subdomain part of Authentication Base Uri + */ + tenant?: string; + /** + * Enterprise ID = MID of the parent BU + */ + eid?: number; + /** + * MID of the BU to work with + */ + mid?: number; + /** + * name of the BU to interact with + */ + businessUnit?: string; + /** + * name of the credential to interact with + */ + credential?: string; +}; +export type TemplateMap = { + [x: string]: string; +}; +export type SupportedMetadataTypes = "asset" | "asset-archive" | "asset-asset" | "asset-audio" | "asset-block" | "asset-code" | "asset-document" | "asset-image" | "asset-message" | "asset-other" | "asset-rawimage" | "asset-template" | "asset-textfile" | "asset-video" | "attributeGroup" | "attributeSet" | "automation" | "campaign" | "contentArea" | "dataExtension" | "dataExtensionField" | "dataExtensionTemplate" | "dataExtract" | "dataExtractType" | "discovery" | "deliveryProfile" | "email" | "emailSend" | "event" | "fileLocation" | "fileTransfer" | "filter" | "folder" | "importFile" | "journey" | "list" | "mobileCode" | "mobileKeyword" | "mobileMessage" | "query" | "role" | "script" | "sendClassification" | "senderProfile" | "transactionalEmail" | "transactionalPush" | "transactionalSMS" | "triggeredSend" | "user" | "verification"; +/** + * object-key=SupportedMetadataTypes, value=array of external keys + */ +export type TypeKeyCombo = { + [x: string]: string[]; +}; +/** + * generic metadata item + */ +export type MetadataTypeItem = any; +/** + * key=customer key + */ +export type MetadataTypeMap = { + [x: string]: any; +}; +/** + * key=Supported MetadataType + */ +export type MultiMetadataTypeMap = { + [x: string]: { + [x: string]: any; + }; +}; +/** + * key=Supported MetadataType + */ +export type MultiMetadataTypeList = { + [x: string]: any[]; +}; +export type MetadataTypeMapObj = { + metadata: MetadataTypeMap; + type: string; +}; +export type MetadataTypeItemObj = { + metadata: MetadataTypeItem; + type: string; +}; +/** + * key=MID + */ +export type Cache = { + [x: number]: { + [x: string]: { + [x: string]: any; + }; + }; +}; +/** + * used during update + */ +export type MetadataTypeItemDiff = { + before: MetadataTypeItem; + after: MetadataTypeItem; +}; +export type CodeExtractItem = { + /** + * metadata of one item w/o code + */ + json: MetadataTypeItem; + /** + * list of code snippets in this item + */ + codeArr: CodeExtract[]; + /** + * mostly set to null, otherwise list of subfolders + */ + subFolder: string[]; +}; +export type CodeExtract = { + /** + * mostly set to null, otherwise subfolders path split into elements + */ + subFolder: string[]; + /** + * name of file w/o extension + */ + fileName: string; + /** + * file extension + */ + fileExt: string; + /** + * file content + */ + content: string; + /** + * optional for binary files + */ + encoding?: "base64"; +}; +export type QueryItem = { + /** + * name + */ + name: string; + /** + * key + */ + key: string; + /** + * - + */ + description: string; + /** + * Object ID of DE (removed before save) + */ + targetId?: string; + /** + * key of target data extension + */ + targetKey: string; + /** + * key of target data extension + */ + r__dataExtension_key: string; + /** + * e.g. "2020-09-14T01:42:03.017" + */ + createdDate: string; + /** + * e.g. "2020-09-14T01:42:03.017" + */ + modifiedDate: string; + /** + * defines how the query writes into the target data extension + */ + targetUpdateTypeName: "Overwrite" | "Update" | "Append"; + /** + * 0|1|2, mapped to targetUpdateTypeName via this.definition.targetUpdateTypeMapping + */ + targetUpdateTypeId?: number; + /** + * Description DE (removed before save) + */ + targetDescription?: string; + /** + * looks like this is always set to false + */ + isFrozen: boolean; + /** + * contains SQL query with line breaks converted to '\n'. The content is extracted during retrieval and written into a separate *.sql file + */ + queryText?: string; + /** + * holds folder ID, replaced with r__folder_Path during retrieve + */ + categoryId?: string; + /** + * folder path in which this DE is saved + */ + r__folder_Path: string; + /** + * Object ID of query + */ + queryDefinitionId?: string; +}; +export type QueryMap = { + [x: string]: QueryItem; +}; +export type ScriptItem = { + /** + * name + */ + name: string; + /** + * key + */ + key: string; + /** + * - + */ + description: string; + /** + * e.g. "2020-09-14T01:42:03.017" + */ + createdDate: string; + /** + * e.g. "2020-09-14T01:42:03.017" + */ + modifiedDate: string; + /** + * contains script with line breaks converted to '\n'. The content is extracted during retrieval and written into a separate *.ssjs file + */ + script?: string; + /** + * holds folder ID, replaced with r__folder_Path during retrieve + */ + categoryId?: string; + /** + * folder path in which this DE is saved + */ + r__folder_Path: string; +}; +export type ScriptMap = { + [x: string]: ScriptItem; +}; +export type AssetItem = { + [x: string]: any; +}; +export type AssetMap = { + [x: string]: { + [x: string]: any; + }; +}; +export type AssetSubType = "archive" | "asset" | "audio" | "block" | "code" | "document" | "image" | "message" | "other" | "rawimage" | "template" | "textfile" | "video"; +export type DataExtensionFieldItem = { + /** + * id + */ + ObjectID?: string; + /** + * key in format [DEkey].[FieldName] + */ + CustomerKey?: string; + /** + * - + */ + DataExtension?: { + CustomerKey: string; + }; + /** + * name of field + */ + Name: string; + /** + * custom attribute that is only used when trying to rename a field from Name to Name_new + */ + Name_new?: string; + /** + * empty string for not set + */ + DefaultValue: string; + /** + * - + */ + IsRequired: true | false; + /** + * opposite of IsRequired + */ + IsNullable?: true | false; + /** + * - + */ + IsPrimaryKey: true | false; + /** + * 1, 2, 3, ... + */ + Ordinal: number; + /** + * can only be set on create + */ + FieldType: "Text" | "Number" | "Date" | "Boolean" | "Decimal" | "EmailAddress" | "Phone" | "Locale"; + /** + * field length + */ + MaxLength: number | string; + /** + * the number of places after the decimal that the field can hold; example: "0","1", ... + */ + Scale: string; +}; +/** + * key: name of field, value: DataExtensionFieldItem + */ +export type DataExtensionFieldMap = { + [x: string]: DataExtensionFieldItem; +}; +export type DataExtensionItem = { + /** + * key + */ + CustomerKey: string; + /** + * name + */ + Name: string; + /** + * - + */ + Description: string; + /** + * iso format + */ + CreatedDate?: string; + /** + * iso format + */ + ModifiedDate?: string; + /** + * - + */ + IsSendable: true | false; + /** + * - + */ + IsTestable: true | false; + /** + * - + */ + SendableDataExtensionField: { + Name: string; + }; + /** + * - + */ + SendableSubscriberField: { + Name: string; + }; + /** + * list of DE fields + */ + Fields: DataExtensionFieldItem[]; + /** + * retrieved from associated folder + */ + r__folder_ContentType: "dataextension" | "salesforcedataextension" | "synchronizeddataextension" | "shared_dataextension" | "shared_salesforcedataextension"; + /** + * folder path in which this DE is saved + */ + r__folder_Path: string; + /** + * holds folder ID, replaced with r__folder_Path during retrieve + */ + CategoryID?: string; + /** + * name of optionally associated DE template + */ + r__dataExtensionTemplate_name?: string; + /** + * - + */ + Template?: { + CustomerKey?: string; + }; + /** + * empty string or US date + 12:00:00 AM + */ + RetainUntil: string; + /** + * YYYY-MM-DD + */ + c__retainUntil: string; + /** + * readable name of retention policy + */ + c__retentionPolicy?: "none" | "allRecordsAndDataextension" | "allRecords" | "individialRecords"; + /** + * number of days/weeks/months/years before retention kicks in + */ + DataRetentionPeriodLength?: number; + /** + * 3:Days, 4:Weeks, 5:Months, 6:Years + */ + DataRetentionPeriodUnitOfMeasure?: number; + /** + * 3:Days, 4:Weeks, 5:Months, 6:Years + */ + c__dataRetentionPeriodUnitOfMeasure?: string; + /** + * true for retention policy individialRecords + */ + RowBasedRetention?: boolean; + /** + * ? + */ + ResetRetentionPeriodOnImport: boolean; + /** + * true for retention policy allRecords + */ + DeleteAtEndOfRetentionPeriod?: boolean; +}; +export type DataExtensionMap = { + [x: string]: DataExtensionItem; +}; +export type UserDocument = { + /** + * - + */ + TYPE: "User" | "Installed Package" | "Inactivated User"; + /** + * equal to UserID; optional in update/create calls + */ + ID?: string; + /** + * equal to ID; required in update/create calls + */ + UserID: string; + /** + * user.AccountUserID + */ + AccountUserID?: number; + /** + * copy of AccountUserID + */ + c__AccountUserID: number; + /** + * user.CustomerKey + */ + CustomerKey: string; + /** + * user.Name + */ + Name: string; + /** + * user.Email + */ + Email: string; + /** + * user.NotificationEmailAddress + */ + NotificationEmailAddress: string; + /** + * user.ActiveFlag === true ? '✓' : '-' + */ + ActiveFlag: boolean; + /** + * user.IsAPIUser === true ? '✓' : '-' + */ + IsAPIUser: boolean; + /** + * user.MustChangePassword === true ? '✓' : '-' + */ + MustChangePassword: boolean; + /** + * default MID; BUName after we resolved it + */ + DefaultBusinessUnit: number; + /** + * associatedBus + */ + c__AssociatedBusinessUnits: number[]; + /** + * (API only) + */ + Roles?: { + Role?: object[]; + }; + /** + * roles + */ + c__RoleNamesGlobal: string[]; + /** + * userPermissions + */ + UserPermissions: string[]; + /** + * this.timeSinceDate(user.LastSuccessfulLogin) + */ + LastSuccessfulLogin: string; + /** + * user.CreatedDate + */ + CreatedDate: string; + /** + * user.ModifiedDate + */ + ModifiedDate: string; + /** + * - + */ + Client: { + ID?: number; + ModifiedBy?: number; + }; + /** + * - + */ + c__type: "User" | "Installed Package"; + /** + * (API only) + */ + IsLocked?: boolean; + /** + * used to unlock a user that has IsLocked === true + */ + Unlock?: boolean; + /** + * copy of IsLocked + */ + c__IsLocked_readOnly: boolean; + /** + * name of timezone + */ + c__TimeZoneName: string; + /** + * (API only) + */ + TimeZone?: { + Name?: string; + ID?: string; + }; + /** + * only used to set the password. cannot be retrieved + */ + Password?: string; + /** + * fr-CA, en-US, ... + */ + c__LocaleCode: "en-US" | "fr-CA" | "fr-FR" | "de-DE" | "it-IT" | "ja-JP" | "pt-BR" | "es-419" | "es-ES"; + /** + * (API only) + */ + Locale?: { + LocaleCode?: "en-US" | "fr-CA" | "fr-FR" | "de-DE" | "it-IT" | "ja-JP" | "pt-BR" | "es-419" | "es-ES"; + }; + /** + * - + */ + SsoIdentity?: object; + /** + * - + */ + SsoIdentities?: any[] | object; +}; +export type UserDocumentDiff = { + before: UserDocument; + after: UserDocument; +}; +/** + * key=customer key + */ +export type UserDocumentMap = { + [x: string]: UserDocument; +}; +export type UserDocumentDocumentHelper = { + /** + * docs: user.ActiveFlag === true ? '✓' : '-' + */ + ActiveFlagDocs: string; + /** + * docs: user.IsAPIUser === true ? '✓' : '-' + */ + IsAPIUserDocs: string; + /** + * docs: user.MustChangePassword === true ? '✓' : '-' + */ + MustChangePasswordDocs: string; + /** + * docs: default MID; BUName after we resolved it + */ + DefaultBusinessUnitDocs: string; + /** + * docs: list of roles as concatenated string + */ + RolesDocs: string; + /** + * docs: list of associated BUs as concatenated string + */ + AssociatedBusDocs: string; + /** + * docs: user name who last modified this user + */ + ModifiedBy: string | number; + /** + * docs: name of timezone + */ + TimeZoneName: string; + /** + * docs: if the user cannot login + */ + IsLockedDocs: string; +}; +export type UserDocumentDocument = UserDocument & UserDocumentDocumentHelper; +export type AccountUserConfiguration = { + /** + * wrapper + */ + Client: { + ID: number; + }; + /** + * empty string + */ + PartnerKey?: string; + /** + * User ID e.g:717133502 + */ + ID: number | string; + /** + * empty string + */ + ObjectID?: string; + /** + * 0,1 + */ + Delete?: number; + /** + * - + */ + BusinessUnitAssignmentConfiguration: BusinessUnitAssignmentConfiguration; +}; +export type BusinessUnitAssignmentConfiguration = { + /** + * wrapper + */ + BusinessUnitIds: { + BusinessUnitId: number[] | number; + }; + /** + * assign BU if false, remove assignment if true + */ + IsDelete: boolean; +}; +export type AutomationActivity = { + /** + * key of associated activity + */ + r__key: string; + /** + * name (not key) of associated activity + */ + name?: string; + /** + * used by wait activity if a specific time of day was set + */ + timeZone?: string; + /** + * Id of assoicated activity type; see this.definition.activityTypeMapping + */ + objectTypeId?: number; + /** + * Object Id of assoicated metadata item + */ + activityObjectId?: string; + /** + * order within step; starts with 1 or higher number + */ + displayOrder?: number; + /** + * see this.definition.activityTypeMapping + */ + r__type: string; +}; +export type AutomationStep = { + /** + * description + */ + name: string; + /** + * equals AutomationStep.name + */ + annotation?: string; + /** + * step iterator; starts with 1 + */ + step?: number; + /** + * step iterator, automatically set during deployment + */ + stepNumber?: number; + /** + * - + */ + activities: AutomationActivity[]; +}; +/** + * REST format + */ +export type AutomationSchedule = { + /** + * legacy id of schedule + */ + id: string; + /** + * equals schedule.scheduleTypeId; upsert endpoint requires scheduleTypeId. retrieve endpoint returns typeId + */ + typeId: number; + /** + * equals schedule.typeId; upsert endpoint requires scheduleTypeId. retrieve endpoint returns typeId + */ + scheduleTypeId?: number; + /** + * example: '2021-05-07T09:00:00' + */ + startDate: string; + /** + * example: '2021-05-07T09:00:00' + */ + endDate: string; + /** + * example: 'FREQ=DAILY;UNTIL=20790606T160000;INTERVAL=1' + */ + icalRecur: string; + /** + * same as icalRecur but returned by legacy-API; example: 'FREQ=DAILY;UNTIL=20790606T160000;INTERVAL=1' + */ + iCalRecur?: string; + /** + * example: 'W. Europe Standard Time'; see this.definition.timeZoneMapping + */ + timezoneName: string; + /** + * same as timezoneName but returned by legacy-API; example: 'W. Europe Standard Time'; see this.definition.timeZoneMapping + */ + timeZone?: string; + /** + * kept in legacy API only, exact description of what this schedule does + */ + description?: string; + /** + * see this.definition.timeZoneMapping + */ + timezoneId?: number; + /** + * same as timezoneId but returned by legacy-API; see this.definition.timeZoneMapping + */ + timeZoneId?: number; + /** + * ? + */ + rangeTypeId?: number; + /** + * ? + */ + pattern?: any; + /** + * ? + */ + scheduledTime?: any; + /** + * ? + */ + scheduledStatus?: string; +}; +/** + * SOAP format + */ +export type AutomationScheduleSoap = { + /** + * 'Minutely'|'Hourly'|'Daily'|'Weekly'|'Monthly'|'Yearly' + */ + RecurrenceType?: string; + /** + * - + */ + Recurrence: { + $?: object; + YearlyRecurrencePatternType?: "ByYear"; + MonthlyRecurrencePatternType?: "ByMonth"; + WeeklyRecurrencePatternType?: "ByWeek"; + DailyRecurrencePatternType?: "ByDay"; + MinutelyRecurrencePatternType?: "Interval"; + HourlyRecurrencePatternType?: "Interval"; + YearInterval?: number; + MonthInterval?: number; + WeekInterval?: number; + DayInterval?: number; + HourInterval?: number; + MinuteInterval?: number; + }; + /** + * internal variable for CLI output only + */ + _interval?: number; + /** + * - + */ + TimeZone: { + ID: number; + IDSpecified?: true; + }; + /** + * internal variable for CLI output only + */ + _timezoneString?: string; + /** + * AutomationSchedule.startDate + */ + StartDateTime: string; + /** + * AutomationSchedule.startDate; internal variable for CLI output only + */ + _StartDateTime?: string; + /** + * AutomationSchedule.endDate + */ + EndDateTime?: string; + /** + * set to 'EndOn' if AutomationSchedule.icalRecur contains 'UNTIL'; otherwise to 'EndAfter' + */ + RecurrenceRangeType: "EndOn" | "EndAfter"; + /** + * only exists if RecurrenceRangeType=='EndAfter' + */ + Occurrences?: number; +}; +export type AutomationItem = { + /** + * Object Id + */ + id: string; + /** + * legacy Object Id - used for handling notifications + */ + legacyId?: string; + /** + * Object Id as returned by SOAP API + */ + ObjectID?: string; + /** + * legacy id + */ + programId?: string; + /** + * key (Rest API) + */ + key: string; + /** + * key (SOAP API) + */ + CustomerKey?: string; + /** + * name (Rest API) + */ + name?: string; + /** + * name (SOAP API) + */ + Name?: string; + /** + * notifications + */ + notifications?: any; + /** + * - + */ + description?: string; + /** + * Starting Source = Schedule / File Drop + */ + type?: "scheduled" | "triggered" | "automationtriggered"; + /** + * Starting Source = Schedule / File Drop; from legacy api + */ + automationType?: "scheduled" | "triggered" | "automationtriggered"; + /** + * automation status + */ + status?: "Scheduled" | "Running" | "Ready" | "Building" | "PausedSchedule" | "InactiveTrigger"; + /** + * automation status + */ + statusId?: number; + /** + * only existing if type=scheduled + */ + schedule?: AutomationSchedule; + /** + * only existing if type=triggered + */ + fileTrigger?: { + fileNamingPattern: string; + fileNamePatternTypeId: number; + folderLocationText: string; + isPublished: boolean; + queueFiles: boolean; + triggerActive: boolean; + }; + /** + * only existing if type=automationtriggered + */ + automationTrigger?: object; + /** + * - + */ + startSource?: { + schedule?: AutomationSchedule; + fileDrop?: { + fileNamePattern: string; + fileNamePatternTypeId: number; + folderLocation: string; + queueFiles: boolean; + }; + typeId: number; + }; + /** + * - + */ + steps?: AutomationStep[]; + /** + * folder path + */ + r__folder_Path?: string; + /** + * holds folder ID, replaced with r__folder_Path during retrieve + */ + categoryId?: string; + /** + * user name of person who created this automation + */ + createdName?: string; + /** + * iso format + */ + createdDate?: string; + /** + * user name of person who last modified this automation + */ + modifiedName?: string; + /** + * iso format + */ + modifiedDate?: string; + /** + * user name of person who paused this automation + */ + pausedName?: string; + /** + * iso format + */ + pausedDate?: string; +}; +export type VerificationItem = { + /** + * ID / Key + */ + dataVerificationDefinitionId: string; + /** + * key + */ + verificationType: "IsEqualTo" | "IsLessThan" | "IsGreaterThan" | "IsOutsideRange" | "IsInsideRange" | "IsNotEqualTo" | "IsNotLessThan" | "IsNotGreaterThan" | "IsNotOutsideRange" | "IsNotInsideRange"; + /** + * used for all verificationTypes; lower value for IsOutsideRange, IsInsideRange, IsNotOutsideRange, IsNotInsideRange + */ + value1: number; + /** + * only used for IsOutsideRange, IsInsideRange, IsNotOutsideRange, IsNotInsideRange; otherwise set to 0 + */ + value2: number; + /** + * flag to stop automation if verification fails + */ + shouldStopOnFailure: boolean; + /** + * flag to send email if verification fails + */ + shouldEmailOnFailure: boolean; + /** + * email address to send notification to; empty string if shouldEmailOnFailure=false + */ + notificationEmailAddress: string; + /** + * email message to send; empty string if shouldEmailOnFailure=false + */ + notificationEmailMessage: string; + /** + * user id of creator + */ + createdBy: number; + /** + * ObjectID of target data extension + */ + targetObjectId?: string; + /** + * key of target data extension + */ + r__dataExtension_key: string; + /** + * custom key for verifications based on automation, step and activity number + */ + c__automation_step: string; +}; +export type AutomationMap = { + [x: string]: AutomationItem; +}; +export type AutomationMapObj = { + metadata: AutomationMap; + type: string; +}; +export type AutomationItemObj = { + metadata: object | AutomationItem; + type: string; +}; +export type McdevDeltaPkgItem = { + /** + * relative path to file + */ + file: string; + /** + * changed lines + */ + changes: number; + /** + * added lines + */ + insertions: number; + /** + * deleted lines + */ + deletions: number; + /** + * is a binary file + */ + binary: boolean; + /** + * git thinks this file was moved + */ + moved: boolean; + /** + * git thinks this relative path is where the file was before + */ + fromPath?: string; + /** + * metadata type + */ + type: string; + /** + * key + */ + externalKey: string; + /** + * name + */ + name: string; + /** + * what git recognized as an action + */ + gitAction: "move" | "add/update" | "delete"; + /** + * mcdev credential name + */ + _credential: string; + /** + * mcdev business unit name inside of _credential + */ + _businessUnit: string; +}; +export type DeltaPkgItem = import("simple-git").DiffResultTextFile & McdevDeltaPkgItem; +export type RestError = import("sfmc-sdk/util").RestError; +export type SOAPError = import("sfmc-sdk/util").SOAPError; +export type SDKError = SOAPError & RestError; +/** + * signals what to insert automatically for things usually asked via wizard + */ +export type SkipInteraction = { + /** + * client id of installed package + */ + client_id?: string; + /** + * client secret of installed package + */ + client_secret?: string; + /** + * tenant specific auth url of installed package + */ + auth_url?: string; + /** + * MID of the Parent Business Unit + */ + account_id?: number; + /** + * how you would like the credential to be named + */ + credentialName?: string; + /** + * URL of Git remote server + */ + gitRemoteUrl?: string; + /** + * will trigger re-downloading latest versions of dependent types after fixing keys + */ + fixKeysReretrieve?: boolean; + /** + * used by mcdev init to directly push to a remote + */ + gitPush?: string; + /** + * used by mcdev init to directly push to a remote + */ + developmentBu?: string; + /** + * used by mcdev init to directly push to a remote + */ + downloadBUs?: string; +}; +export type FilterItem = { + /** + * folder id + */ + categoryId: number; + /** + * - + */ + createdDate?: string; + /** + * key + */ + customerKey: string; + /** + * DE/List ID + */ + destinationObjectId: string; + /** + * 1:SubscriberList, 2:DataExtension, 3:GroupWizard, 4:BehavioralData + */ + destinationTypeId: 1 | 2 | 3 | 4; + /** + * ? + */ + filterActivityId: string; + /** + * ObjectID of filterDefinition + */ + filterDefinitionId: string; + /** + * - + */ + modifiedDate: string; + /** + * name + */ + name: string; + /** + * - + */ + description?: string; + /** + * DE/List ID + */ + sourceObjectId: string; + /** + * required for upsert; unknown purpose; set to null + */ + resultGroupFolderId: null; + /** + * required for upsert; unknown purpose; set to null + */ + resultGroupName: null; + /** + * required for upsert; unknown purpose; set to null + */ + sourceId: null; + /** + * 1:SubscriberList, 2:DataExtension, 3:GroupWizard, 4:BehavioralData + */ + sourceTypeId: 1 | 2 | 3 | 4; + /** + * seems to be a duplicate of sourceTypeId? + */ + filterDefinitionSourceTypeId?: 1 | 2 | 3 | 4; + /** + * description of destination DE + */ + resultDEDescription?: string; + /** + * name of destination DE + */ + resultDEName?: string; + /** + * key of destination DE + */ + resultDEKey?: string; + /** + * ? + */ + statusId: number; + /** + * relationship to filterDefinition + */ + r__dataFilter_key?: string; + /** + * relationship to dataExtension source + */ + r__source_dataExtension_key?: string; + /** + * relationship to dataExtension destination + */ + r__destination_dataExtension_key?: string; + /** + * relationship to folder + */ + r__folder_Path?: string; +}; +export type FilterMap = { + [x: string]: FilterItem; +}; +/** + * /automation/v1/filterdefinitions/<id> (not used) + */ +export type AutomationFilterDefinitionItem = { + /** + * object id + */ + id: string; + /** + * external key + */ + key: string; + /** + * - + */ + createdDate: string; + /** + * user id + */ + createdBy: number; + /** + * - + */ + createdName: string; + /** + * (omitted by API if empty) + */ + description?: string; + /** + * - + */ + modifiedDate: string; + /** + * user id + */ + modifiedBy: number; + /** + * - + */ + modifiedName: string; + /** + * name + */ + name: string; + /** + * folder id + */ + categoryId: string; + /** + * from REST API defines the filter in XML form + */ + filterDefinitionXml: string; + /** + * 1:list/profile attributes/measures, 2: dataExtension + */ + derivedFromType: 1 | 2; + /** + * ? + */ + isSendable: boolean; +}; +/** + * /email/v1/filters/filterdefinition/<id> + */ +export type DataFilterItem = { + /** + * object id + */ + id: string; + /** + * external key + */ + key: string; + /** + * date + */ + createdDate: string; + /** + * user id + */ + createdBy: number; + /** + * name + */ + createdName: string; + /** + * (omitted by API if empty) + */ + description?: string; + /** + * date + */ + lastUpdated: string; + /** + * user id + */ + lastUpdatedBy: number; + /** + * name + */ + lastUpdatedName: string; + /** + * name + */ + name: string; + /** + * folder id + */ + categoryId: string; + /** + * from REST API defines the filter in XML form + */ + filterDefinitionXml: string; + /** + * 1:list/profile attributes/measures, 2: dataExtension + */ + derivedFromType: 1 | 2; + /** + * Id of DataExtension - present if derivedFromType=2 + */ + derivedFromObjectId: string; + /** + * - + */ + derivedFromObjectTypeName: "DataExtension" | "SubscriberAttributes"; + /** + * name of DataExtension + */ + derivedFromObjectName?: string; + /** + * ? + */ + isSendable: boolean; + /** + * copied from SOAP API, defines the filter in readable form + */ + c__filterDefinition?: { + ConditionSet: FilterConditionSet; + }; + /** + * relationship to list source (if derivedFromType=1) + */ + r__source_list_PathName?: string; + /** + * relationship to dataExtension source (if derivedFromType=2) + */ + r__source_dataExtension_key?: string; +}; +export type FilterConditionSet = { + /** + * - + */ + Condition: FilterCondition | FilterCondition[]; + /** + * - + */ + ConditionSet: FilterConditionSet; +}; +export type FilterCondition = { + /** + * comparison operator (actually \@_Operator) + */ + Operator: "IsEmpty" | "IsNotEmpty" | "Equals"; + /** + * object id of field (actually \@_ID) + */ + ID?: string; + /** + * filter value to compare against + */ + Value?: string; + /** + * name of field + */ + r__dataExtensionField_name?: string; +}; +export type DataFilterMap = { + [x: string]: DataFilterItem; +}; +export type AuthObject = { + /** + * client_id client_id for sfmc-sdk auth + */ + client_id: string; + /** + * client_secret for sfmc-sdk auth + */ + client_secret: string; + /** + * mid of business unit to auth against + */ + account_id: number; + /** + * authentication base url + */ + auth_url: string; +}; +export type SoapRequestParams = { + /** + * request id + */ + continueRequest?: string; + /** + * additional options (CallsInConversation, Client, ConversationID, Priority, RequestType, SaveOptions, ScheduledTime, SendResponseTo, SequenceCode) + */ + options?: object; + /** + * ? + */ + clientIDs?: any; + /** + * simple or complex + * complex + */ + filter?: SoapSDKFilter; + /** + * all BUs or just one + */ + QueryAllAccounts?: boolean; +}; +export type SoapFilterSimple = { + /** + * field + */ + property: string; + /** + * various options + */ + simpleOperator: "equals" | "notEquals" | "isNull" | "isNotNull" | "greaterThan" | "lessThan" | "greaterThanOrEqual" | "lessThanOrEqual" | "between" | "IN" | "in" | "like"; + /** + * field value + */ + value?: string | number | boolean | string[] | number[]; +}; +export type SoapFilterComplex = { + /** + * string for simple or a new filter-object for complex + */ + leftOperand: SoapSDKFilter; + /** + * various options + */ + logicalOperator: "AND" | "OR"; + /** + * string for simple or a new filter-object for complex; omit for isNull and isNotNull + */ + rightOperand: SoapSDKFilter; +}; +export type SoapSDKFilterSimple = { + /** + * string for simple or a new filter-object for complex + */ + leftOperand: SoapFilterSimple["property"]; + /** + * various options + */ + operator: SoapFilterSimple["simpleOperator"]; + /** + * string for simple or a new filter-object for complex; omit for isNull and isNotNull + */ + rightOperand?: SoapFilterSimple["value"]; +}; +export type SoapSDKFilterComplex = { + /** + * string for simple or a new filter-object for complex + */ + leftOperand: SoapFilterComplex["leftOperand"]; + /** + * various options + */ + operator: SoapFilterComplex["logicalOperator"]; + /** + * string for simple or a new filter-object for complex; omit for isNull and isNotNull + */ + rightOperand: SoapFilterComplex["rightOperand"]; +}; +export type SoapSDKFilter = SoapSDKFilterSimple | SoapSDKFilterComplex; +export type AssetRequestParams = { + /** + * request id + */ + continueRequest?: string; + /** + * additional options (CallsInConversation, Client, ConversationID, Priority, RequestType, SaveOptions, ScheduledTime, SendResponseTo, SequenceCode) + */ + options?: object; + /** + * ? + * complex + */ + clientIDs?: any; + /** + * pagination + */ + page?: object; + /** + * list of fields we want returned + */ + fields?: string[]; + /** + * pagination + */ + sort?: { + property: string; + direction: "ASC" | "DESC"; + }[]; + /** + * simple or complex filter + */ + query?: AssetFilter | AssetFilterSimple; +}; +export type AssetFilter = { + /** + * string for simple or a new filter-object for complex + */ + leftOperand: AssetFilter | AssetFilterSimple; + /** + * various options + */ + logicalOperator: "AND" | "OR"; + /** + * string for simple or a new filter-object for complex; omit for isNull and isNotNull + */ + rightOperand?: SoapSDKFilter | AssetFilterSimple; +}; +export type AssetFilterSimple = { + /** + * field + */ + property: string; + /** + * various options + */ + simpleOperator: "equal" | "notEquals" | "isNull" | "isNotNull" | "greaterThan" | "lessThan" | "greaterThanOrEqual" | "lessThanOrEqual" | "between" | "IN" | "in" | "like"; + /** + * field value + */ + value: string | number | boolean | any[]; +}; +export type Mcdevrc = { + /** + * list of credentials + */ + credentials: object; + /** + * configure options for mcdev + */ + options: object; + /** + * configure directories for mcdev to read/write to + */ + directories: { + businessUnits: string; + deploy: string; + docs: string; + retrieve: string; + template: string; + templateBuilds: string; + }; + /** + * templating variables grouped by markets + */ + markets: { + [x: string]: any; + }; + /** + * combination of markets and BUs for streamlined deployments + */ + marketList: object; + /** + * templating variables grouped by markets + */ + metaDataTypes: { + retrieve: string[]; + createDeltaPkg: string[]; + documentOnRetrieve: string[]; + }; + /** + * mcdev version that last updated the config file + */ + version: string; +}; +export type LoggerLevel = "error" | "verbose" | "info" | "debug"; +export type McdevLogger = { + /** + * (msg) print info message + */ + level?: LoggerLevel; + /** + * (msg) print error message; wrapper around winstonLogger.error that also sets error code to 1 + */ + error: (msg: string) => void; + /** + * print error with trace message + */ + errorStack: (ex: SDKError, message?: string) => void; +}; +export type Logger = import("winston").Logger & McdevLogger; +export type AssetItemSimple = { + id: number; + key: string; + name: string; +}; +export type AssetItemSimpleMap = { + [x: string]: AssetItemSimple; +}; +export type AssetItemIdSimpleMap = { + [x: number]: AssetItemSimple; +}; +export type ContentBlockConversionTypes = "id" | "key" | "name"; +export type ExplainType = { + /** + * readable name of type + */ + name: string; + /** + * api parameter name for type + */ + apiName: string; + /** + * more info on what this type is about + */ + description: string; + /** + * is it retrieved by default OR list of subtypes that are retrieved by default + */ + retrieveByDefault: boolean | string[]; + /** + * supported features + */ + supports: { + retrieve: boolean; + create: boolean; + update: boolean; + delete: boolean; + changeKey: boolean; + buildTemplate: boolean; + retrieveAsTemplate: boolean; + }; +}; +export type ListItem = { + /** + * wrapper + */ + Client?: { + ID: number; + }; + /** + * not used + */ + PartnerKey?: string; + /** + * "2021-06-21T11:54:57.103" + */ + CreatedDate?: string; + /** + * "2021-06-21T11:54:57.103" + */ + ModifiedDate?: string; + /** + * unique identifier per BU + */ + ID?: number; + /** + * not used + */ + ObjectID?: string; + /** + * unique identifer per BU + */ + CustomerKey?: string; + /** + * customn field that tracks the exact directory path of the current folder including its own name + */ + Path?: string; + /** + * wrapper + */ + ParentFolder?: { + ID: number; + ObjectID?: string; + Path?: string; + }; + /** + * folder name + */ + Name: string; + /** + * deprecated option to describe the folder content + */ + Description?: string; + /** + * e.g. "shared_data"; see folder-subtypes for complete list + */ + ContentType: string; + /** + * ? + */ + IsActive: boolean; + /** + * option to disable renaming/moving this folder via GUI + */ + IsEditable: boolean; + /** + * option to prevent creating subfolders via GUI + */ + AllowChildren: boolean; + /** + * helper flag for Deployer class to signal if the folder was auto-generated or manually placed + */ + _generated?: boolean; +}; +/** + * key=id + */ +export type ListIdMap = { + [x: number]: ListItem; +}; +/** + * key=customer key + */ +export type ListMap = { + [x: string]: ListItem; +}; +/** + * returned by /data/v1/integration/member/salesforce/object/<OBJECT NAME>/referenceobjects + */ +export type ReferenceObject = { + /** + * label + */ + displayname: string; + /** + * api name of salesforce object + */ + referenceObjectName: string; + /** + * name of lookup/MD field on related object ending on __r (way to return fields from other object) + */ + relationshipName: string; + /** + * name of lookup/MD field on related object ending on __c (returning id) + */ + relationshipIdName: string; + /** + * if this lookup can point to multiple objects or not + */ + isPolymorphic: boolean; +}; +/** + * returned by /legacy/v1/beta/integration/member/salesforce/object/<OBJECT NAME> + */ +export type SfObjectPicklist = { + /** + * - + */ + active: boolean; + /** + * - + */ + defaultValue: boolean; + /** + * what you see in the GUI + */ + label: string; + /** + * whats stored in the DB + */ + value: string; +}; +/** + * returned by /legacy/v1/beta/integration/member/salesforce/object/<OBJECT NAME> + */ +export type SfObjectField = { + /** + * "Annual Revenue" + */ + label: string; + /** + * "AnnualRevenue" + */ + name: string; + /** + * type + */ + datatype: "currency" | "string" | "int" | "picklist" | "textarea" | "boolean" | "date" | "datetime" | "email"; + /** + * 0-4000 + */ + length: number; + /** + * == not required + */ + nillable: boolean; + /** + * is it a custom field + */ + custom: boolean; + /** + * always true? + */ + updateable: boolean; + /** + * always true? + */ + createable: boolean; + /** + * - + */ + defaultedoncreate: boolean; + /** + * - + */ + externalid: boolean; + /** + * - + */ + idlookup: boolean; + /** + * - + */ + precision: number; + /** + * - + */ + scale: number; + /** + * "Currency" + */ + displaydatatype: "Currency" | "Text" | "Number" | "Picklist" | "Text Area (long)" | "Checkbox" | "Date" | "Date/Time" | "Email"; + /** + * "Lead", + */ + objectname: string; + /** + * "", + */ + relationname: string; + /** + * - + */ + isnamefield: boolean; + /** + * list of values + */ + picklist?: SfObjectPicklist[]; +}; +export type configurationArguments = { + /** + * SalesforceObjectTriggerV2 + */ + applicationExtensionKey: string; + /** + * 3.0 + */ + version: string; + /** + * what record event in SF triggers this + */ + salesforceTriggerCriteria: "Created" | "Updated" | "CreatedUpdated"; + /** + * what objects are used by this event + */ + eventDataConfig: { + objects: eventDataConfigObject[]; + }; + /** + * TODO + */ + primaryObjectFilterCriteria: Conditions; + /** + * TODO + */ + relatedObjectFilterCriteria: Conditions; + /** + * seems to only exist on journey but not on event and also not on every journey + */ + additionalObjectFilterCriteria?: object; + /** + * defines how this event links to the all contacts list + */ + contactKey: { + relationshipIdName: string; + relationshipName: string; + isPolymorphic: boolean; + referenceObjectName: string; + fieldName?: string; + }; + /** + * TODO + */ + passThroughArgument: { + fields: { + ContactKey: string; + Email: object; + HasOptedOutOfEmail?: string; + }; + }; + /** + * primaryObjectFilterCriteria in simplified string-form + */ + primaryObjectFilterSummary: string; + /** + * relatedObjectFilterCriteria in simplified string-form + */ + relatedObjectFilterSummary: string; + /** + * eventDataConfig in simplified string-form + */ + eventDataSummary: string[]; + /** + * salesforceTriggerCriteria plus semi-colon + */ + evaluationCriteriaSummary: "Created;" | "Updated;" | "Created;Updated;"; + /** + * if objectAPIName==CampaignMember then this is also CampaignMember; otherwise it's Contact + */ + contactPersonType: "CampaignMember" | "Contact"; + /** + * the SF object on which the salesforceTriggerCriteria is listening on + */ + objectAPIName: string; + /** + * "objectAPIName (Contact / Lead / Contacts and Leads)" + */ + whoToInject: string; + /** + * empty string for SF events + */ + criteria: string; + /** + * set to 0 for SF events + */ + schemaVersionId: number; +}; +/** + * part of configurationArguments + */ +export type eventDataConfigObject = { + /** + * CampaignMember:Campaign: + */ + dePrefix: string; + /** + * ? + */ + isPolymorphic: boolean; + /** + * field on parent object containing the id; ends on __c for custom fields; same as referenceObject for standard fields; can be "Contacts and Leads" + */ + referenceObject: string; + /** + * field on parent object acting as lookup; ends on __r for custom fields; same as referenceObject for standard fields; can be "Common" + */ + relationshipName: string; + /** + * ? + */ + relationshipIdName?: string; + /** + * list of field names that are used by this journey + */ + fields: string[]; +}; +/** + * part of configurationArguments + */ +export type Conditions = { + /** + * - + */ + operand: "AND" | "OR"; + /** + * list of conditions + */ + conditions: (Conditions | FieldCondition)[]; +}; +/** + * part of configurationArguments + */ +export type FieldCondition = { + /** + * is 0 for booleans, otherwise field length + */ + _length: number; + /** + * type + */ + datatype: "currency" | "string" | "int" | "picklist" | "textarea" | "boolean" | "date" | "datetime" | "email"; + /** + * field API name; "TR1__Email__c" + */ + fieldName: string; + /** + * "CampaignMember-CampaignMember" + */ + folderId: string; + /** + * "CampaignMember-CampaignMember-TR1__Email__c" + */ + id: string; + /** + * ? + */ + isPolymorphic: boolean; + /** + * likely the field label; "Email" + */ + name: string; + /** + * condition comparator + */ + operator: "equals" | "EQUALS" | "WASSET"; + /** + * value to compare the field with if operator is sth like "equals"; booleans are stored as upper-camel-case string! + */ + value?: string; + /** + * ? + */ + precision: number; + /** + * "Contacts and Leads" + */ + referenceObjectName: string; + /** + * "CommonId"; can be an empty string + */ + relationshipIdName: string; + /** + * "Common"; can be an empty string + */ + relationshipName: string; + /** + * ? + */ + scale: number; + /** + * seems to be equal to name-attribute?; "Email" + */ + text: string; +}; +export type validationRuleFix = () => boolean | null; +export type validationRuleTest = () => boolean; +export type validationRule = { + /** + * error message to display in case of a failed test + */ + failedMsg: string; + /** + * test to run + */ + passed: validationRuleTest; + /** + * test to run + */ + fix?: validationRuleFix; +}; +/** + * key=rule name + */ +export type validationRuleList = { + [x: string]: validationRule; +}; +export type DomainVerificationItem = { + /** + * EID + */ + enterpriseId?: number; + /** + * MID + */ + memberId?: number; + /** + * domain or email address used in retrieve and create + */ + domain?: string; + /** + * email address used in update call for isSendable field + */ + emailAddress?: string; + /** + * returned by retrieve + */ + status?: "Verified" | "Pending"; + /** + * returned by retrieve and required for update call + */ + domainType?: "SAP" | "UserDomain" | "PrivateDomain" | "RegisteredDomain"; + /** + * automatically true upon creation. can be changed to false via update + */ + isSendable: boolean; + /** + * e.g. ""2023-06-19T11:11:17.32"" + */ + emailSendTime?: string; + /** + * for bulk-creation only: email address to send notifications to when done + */ + notificationEmail?: string; + /** + * for bulk-creation only: list of email addresses to verify + */ + addresses?: string[]; + /** + * for bulk-creation only: instead of an array in addresses, specify the name of a DE + */ + deTable?: string; + /** + * for bulk-creation only: instead of an array in addresses, specify the name of a DE column/field here + */ + deColumn?: string; +}; +export type BuildFilter = { + /** + * include key filters + */ + include?: BuildFilterKeys; + /** + * exclude key filters + */ + exclude?: BuildFilterKeys; +}; +export type BuildFilterKeys = { + /** + * object with keys representing metadata types ("*" for all types, or specific type names) and values being arrays of string patterns to match against + */ + key?: any; +}; +//# sourceMappingURL=mcdev.d.d.ts.map \ No newline at end of file diff --git a/@types/types/mcdev.d.d.ts.map b/@types/types/mcdev.d.d.ts.map new file mode 100644 index 000000000..8b521e4fb --- /dev/null +++ b/@types/types/mcdev.d.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"mcdev.d.d.ts","sourceRoot":"","sources":["../../types/mcdev.d.js"],"names":[],"mappings":";;;;;;eAEc,MAAM;;;;mBACN,MAAM;;;;aACN,MAAM;;;;UACN,MAAM;;;;UACN,MAAM;;;;mBACN,MAAM;;;;iBACN,MAAM;;;;;qCAKP,OAAO,GAAC,eAAe,GAAC,aAAa,GAAC,aAAa,GAAC,aAAa,GAAC,YAAY,GAAC,gBAAgB,GAAC,aAAa,GAAC,eAAe,GAAC,aAAa,GAAC,gBAAgB,GAAC,gBAAgB,GAAC,gBAAgB,GAAC,aAAa,GAAC,gBAAgB,GAAC,cAAc,GAAC,YAAY,GAAC,UAAU,GAAC,aAAa,GAAC,eAAe,GAAC,oBAAoB,GAAC,uBAAuB,GAAC,aAAa,GAAC,iBAAiB,GAAC,WAAW,GAAC,iBAAiB,GAAC,OAAO,GAAC,WAAW,GAAC,OAAO,GAAC,cAAc,GAAC,cAAc,GAAC,QAAQ,GAAC,QAAQ,GAAC,YAAY,GAAC,SAAS,GAAC,MAAM,GAAC,YAAY,GAAC,eAAe,GAAC,eAAe,GAAC,OAAO,GAAC,MAAM,GAAC,QAAQ,GAAC,oBAAoB,GAAC,eAAe,GAAC,oBAAoB,GAAC,mBAAmB,GAAC,kBAAkB,GAAC,eAAe,GAAC,MAAM,GAAC,cAAc;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iCASnsB;IAAC,QAAQ,EAAE,eAAe,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAC;kCACzC;IAAC,QAAQ,EAAE,gBAAgB,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAC;;;;;;;;;;;;;;mCAE1C;IAAC,MAAM,EAAE,gBAAgB,CAAC;IAAC,KAAK,EAAE,gBAAgB,CAAA;CAAC;;;;;UAKlD,gBAAgB;;;;aAChB,WAAW,EAAE;;;;eACb,MAAM,EAAE;;;;;;eAKR,MAAM,EAAE;;;;cACR,MAAM;;;;aACN,MAAM;;;;aACN,MAAM;;;;eACN,QAAQ;;;;;;UAKR,MAAM;;;;SACN,MAAM;;;;iBACN,MAAM;;;;eACN,MAAM;;;;eACN,MAAM;;;;0BACN,MAAM;;;;iBACN,MAAM;;;;kBACN,MAAM;;;;0BACN,WAAW,GAAC,QAAQ,GAAC,QAAQ;;;;yBAC7B,MAAM;;;;wBACN,MAAM;;;;cACN,OAAO;;;;gBACP,MAAM;;;;iBACN,MAAM;;;;oBACN,MAAM;;;;wBACN,MAAM;;;;;;;;;UAMN,MAAM;;;;SACN,MAAM;;;;iBACN,MAAM;;;;iBACN,MAAM;;;;kBACN,MAAM;;;;aACN,MAAM;;;;iBACN,MAAM;;;;oBACN,MAAM;;;;;;;;;;;;;2BAOP,SAAS,GAAC,OAAO,GAAC,OAAO,GAAC,OAAO,GAAC,MAAM,GAAC,UAAU,GAAC,OAAO,GAAC,SAAS,GAAC,OAAO,GAAC,UAAU,GAAC,UAAU,GAAC,UAAU,GAAC,OAAO;;;;;eAKrH,MAAM;;;;kBACN,MAAM;;;;oBAEjB;QAAiC,WAAW,EAAjC,MAAM;KACjB;;;;UAAW,MAAM;;;;eACN,MAAM;;;;kBACN,MAAM;;;;gBACN,IAAI,GAAC,KAAK;;;;iBACV,IAAI,GAAC,KAAK;;;;kBACV,IAAI,GAAC,KAAK;;;;aACV,MAAM;;;;eACN,MAAM,GAAC,QAAQ,GAAC,MAAM,GAAC,SAAS,GAAC,SAAS,GAAC,cAAc,GAAC,OAAO,GAAC,QAAQ;;;;eAC1E,MAAM,GAAC,MAAM;;;;WACb,MAAM;;;;;;;;;;;;iBASN,MAAM;;;;UACN,MAAM;;;;iBACN,MAAM;;;;kBACN,MAAM;;;;mBACN,MAAM;;;;gBACN,IAAI,GAAC,KAAK;;;;gBACV,IAAI,GAAC,KAAK;;;;gCAErB;QAA8C,IAAI,EAAvC,MAAM;KACjB;;;;6BACA;QAA2C,IAAI,EAApC,MAAM;KACjB;;;;YAAW,sBAAsB,EAAE;;;;2BACxB,eAAe,GAAC,yBAAyB,GAAC,2BAA2B,GAAC,sBAAsB,GAAC,gCAAgC;;;;oBAC7H,MAAM;;;;iBACN,MAAM;;;;oCACN,MAAM;;;;eAEjB;QAA6B,WAAW,GAA7B,MAAM;KACjB;;;;iBAAW,MAAM;;;;oBACN,MAAM;;;;yBACN,MAAM,GAAC,4BAA4B,GAAC,YAAY,GAAC,mBAAmB;;;;gCACpE,MAAM;;;;uCACN,MAAM;;;;0CACN,MAAM;;;;wBACN,OAAO;;;;kCACP,OAAO;;;;mCACP,OAAO;;;;;;;;;UASP,MAAM,GAAC,mBAAmB,GAAC,kBAAkB;;;;SAC7C,MAAM;;;;YACN,MAAM;;;;oBACN,MAAM;;;;sBACN,MAAM;;;;iBACN,MAAM;;;;UACN,MAAM;;;;WACN,MAAM;;;;8BACN,MAAM;;;;gBACN,OAAO;;;;eACP,OAAO;;;;wBACP,OAAO;;;;yBACP,MAAM;;;;gCACN,MAAM,EAAE;;;;YAEnB;QAA4B,IAAI,GAArB,MAAM,EAAE;KACnB;;;;wBAAW,MAAM,EAAE;;;;qBACR,MAAM,EAAE;;;;yBACR,MAAM;;;;iBACN,MAAM;;;;kBACN,MAAM;;;;YAEjB;QAA2B,EAAE,GAAlB,MAAM;QACU,UAAU,GAA1B,MAAM;KACjB;;;;aAAW,MAAM,GAAC,mBAAmB;;;;eAC1B,OAAO;;;;aACP,OAAO;;;;0BACP,OAAO;;;;qBACP,MAAM;;;;eAEjB;QAA6B,IAAI,GAAtB,MAAM;QACY,EAAE,GAApB,MAAM;KACjB;;;;eAAW,MAAM;;;;mBACN,OAAO,GAAC,OAAO,GAAC,OAAO,GAAC,OAAO,GAAC,OAAO,GAAC,OAAO,GAAC,OAAO,GAAC,QAAQ,GAAC,OAAO;;;;aAEnF;QAA6F,UAAU,GAA5F,OAAO,GAAC,OAAO,GAAC,OAAO,GAAC,OAAO,GAAC,OAAO,GAAC,OAAO,GAAC,OAAO,GAAC,QAAQ,GAAC,OAAO;KACnF;;;;kBAAW,MAAM;;;;oBACN,QAAM,MAAM;;+BAIb;IAAC,MAAM,EAAC,YAAY,CAAC;IAAA,KAAK,EAAC,YAAY,CAAA;CAAC;;;;;;;;;;;oBAMvC,MAAM;;;;mBACN,MAAM;;;;4BACN,MAAM;;;;6BACN,MAAM;;;;eACN,MAAM;;;;uBACN,MAAM;;;;gBACN,MAAM,GAAG,MAAM;;;;kBACf,MAAM;;;;kBACN,MAAM;;mCACP,YAAY,GAAG,0BAA0B;;;;;YAMnD;QAA0B,EAAE,EAAjB,MAAM;KACjB;;;;iBAAW,MAAM;;;;QACN,MAAM,GAAG,MAAM;;;;eACf,MAAM;;;;aACN,MAAM;;;;yCACN,mCAAmC;;;;;;qBAG9C;QAA4C,cAAc,EAA/C,MAAM,EAAE,GAAC,MAAM;KAC1B;;;;cAAW,OAAO;;;;;;YAKP,MAAM;;;;WACN,MAAM;;;;eACN,MAAM;;;;mBACN,MAAM;;;;uBACN,MAAM;;;;mBACN,MAAM;;;;aACN,MAAM;;;;;;UAKN,MAAM;;;;iBACN,MAAM;;;;WACN,MAAM;;;;iBACN,MAAM;;;;gBACN,kBAAkB,EAAE;;;;;;;;;QAKpB,MAAM;;;;YACN,MAAM;;;;qBACN,MAAM;;;;eACN,MAAM;;;;aACN,MAAM;;;;eACN,MAAM;;;;gBACN,MAAM;;;;kBACN,MAAM;;;;eACN,MAAM;;;;kBACN,MAAM;;;;iBACN,MAAM;;;;iBACN,MAAM;;;;kBACN,MAAM;;;;cACN,GAAG;;;;oBACH,GAAG;;;;sBACH,MAAM;;;;;;;;;qBAKN,MAAM;;;;gBAEjB;QAA+B,CAAC,GAArB,MAAM;QACgB,2BAA2B,GAAjD,QAAQ;QACe,4BAA4B,GAAnD,SAAS;QACa,2BAA2B,GAAjD,QAAQ;QACa,0BAA0B,GAA/C,OAAO;QACiB,6BAA6B,GAArD,UAAU;QACc,2BAA2B,GAAnD,UAAU;QACU,YAAY,GAAhC,MAAM;QACc,aAAa,GAAjC,MAAM;QACc,YAAY,GAAhC,MAAM;QACc,WAAW,GAA/B,MAAM;QACc,YAAY,GAAhC,MAAM;QACc,cAAc,GAAlC,MAAM;KACjB;;;;gBAAW,MAAM;;;;cAEjB;QAA4B,EAAE,EAAnB,MAAM;QACU,WAAW,GAA3B,IAAI;KACf;;;;sBAAW,MAAM;;;;mBACN,MAAM;;;;qBACN,MAAM;;;;kBACN,MAAM;;;;yBACN,OAAO,GAAC,UAAU;;;;kBAClB,MAAM;;;;;;QAKN,MAAM;;;;eACN,MAAM;;;;eACN,MAAM;;;;gBACN,MAAM;;;;SACN,MAAM;;;;kBACN,MAAM;;;;WACN,MAAM;;;;WACN,MAAM;;;;oBACN,GAAG;;;;kBACH,MAAM;;;;WACN,WAAW,GAAC,WAAW,GAAC,qBAAqB;;;;qBAC7C,WAAW,GAAC,WAAW,GAAC,qBAAqB;;;;aAC7C,WAAW,GAAC,SAAS,GAAC,OAAO,GAAC,UAAU,GAAC,gBAAgB,GAAC,iBAAiB;;;;eAC3E,MAAM;;;;eACN,kBAAkB;;;;kBAE7B;QAA+B,iBAAiB,EAArC,MAAM;QACc,qBAAqB,EAAzC,MAAM;QACc,kBAAkB,EAAtC,MAAM;QACe,WAAW,EAAhC,OAAO;QACc,UAAU,EAA/B,OAAO;QACc,aAAa,EAAlC,OAAO;KAClB;;;;wBAAW,MAAM;;;;kBAEjB;QAA4C,QAAQ,GAAzC,kBAAkB;QACG,QAAQ,GACxC;YAAwC,eAAe,EAA5C,MAAM;YACuB,qBAAqB,EAAlD,MAAM;YACuB,cAAc,EAA3C,MAAM;YACwB,UAAU,EAAxC,OAAO;SAClB;QAA+B,MAAM,EAA1B,MAAM;KACjB;;;;YAAW,cAAc,EAAE;;;;qBAChB,MAAM;;;;iBACN,MAAM;;;;kBACN,MAAM;;;;kBACN,MAAM;;;;mBACN,MAAM;;;;mBACN,MAAM;;;;iBACN,MAAM;;;;iBACN,MAAM;;;;;;kCAKN,MAAM;;;;sBACN,WAAW,GAAC,YAAY,GAAC,eAAe,GAAC,gBAAgB,GAAC,eAAe,GAAC,cAAc,GAAC,eAAe,GAAC,kBAAkB,GAAC,mBAAmB,GAAC,kBAAkB;;;;YAClK,MAAM;;;;YACN,MAAM;;;;yBACN,OAAO;;;;0BACP,OAAO;;;;8BACP,MAAM;;;;8BACN,MAAM;;;;eACN,MAAM;;;;qBACN,MAAM;;;;0BACN,MAAM;;;;wBACN,MAAM;;;;;+BAKP;IAAC,QAAQ,EAAC,aAAa,CAAC;IAAA,IAAI,EAAC,MAAM,CAAA;CAAC;gCACpC;IAAC,QAAQ,EAAC,MAAM,GAAG,cAAc,CAAC;IAAA,IAAI,EAAC,MAAM,CAAA;CAAC;;;;;UAE7C,MAAM;;;;aACN,MAAM;;;;gBACN,MAAM;;;;eACN,MAAM;;;;YACN,OAAO;;;;WACP,OAAO;;;;eACP,MAAM;;;;UACN,MAAM;;;;iBACN,MAAM;;;;UACN,MAAM;;;;eACN,MAAM,GAAC,YAAY,GAAC,QAAQ;;;;iBAC5B,MAAM;;;;mBACN,MAAM;;2BACP,OAAO,YAAY,EAAE,kBAAkB,GAAG,iBAAiB;wBAI3D,OAAO,eAAe,EAAE,SAAS;wBACjC,OAAO,eAAe,EAAE,SAAS;uBACjC,SAAS,GAAG,SAAS;;;;;;;;gBAKpB,MAAM;;;;oBACN,MAAM;;;;eACN,MAAM;;;;iBACN,MAAM;;;;qBACN,MAAM;;;;mBACN,MAAM;;;;wBACN,OAAO;;;;cACP,MAAM;;;;oBACN,MAAM;;;;kBACN,MAAM;;;;;;gBAKN,MAAM;;;;kBACN,MAAM;;;;iBACN,MAAM;;;;yBACN,MAAM;;;;uBACN,CAAC,GAAC,CAAC,GAAC,CAAC,GAAC,CAAC;;;;sBACP,MAAM;;;;wBACN,MAAM;;;;kBACN,MAAM;;;;UACN,MAAM;;;;kBACN,MAAM;;;;oBACN,MAAM;;;;yBACN,IAAI;;;;qBACJ,IAAI;;;;cACJ,IAAI;;;;kBACJ,CAAC,GAAC,CAAC,GAAC,CAAC,GAAC,CAAC;;;;mCACP,CAAC,GAAC,CAAC,GAAC,CAAC,GAAC,CAAC;;;;0BACP,MAAM;;;;mBACN,MAAM;;;;kBACN,MAAM;;;;cACN,MAAM;;;;wBACN,MAAM;;;;kCACN,MAAM;;;;uCACN,MAAM;;;;qBACN,MAAM;;;;;;;;;;;;QAQN,MAAM;;;;SACN,MAAM;;;;iBACN,MAAM;;;;eACN,MAAM;;;;iBACN,MAAM;;;;kBACN,MAAM;;;;kBACN,MAAM;;;;gBACN,MAAM;;;;kBACN,MAAM;;;;UACN,MAAM;;;;gBACN,MAAM;;;;yBACN,MAAM;;;;qBACN,CAAC,GAAC,CAAC;;;;gBACH,OAAO;;;;;;;;;QAMP,MAAM;;;;SACN,MAAM;;;;iBACN,MAAM;;;;eACN,MAAM;;;;iBACN,MAAM;;;;kBACN,MAAM;;;;iBACN,MAAM;;;;mBACN,MAAM;;;;qBACN,MAAM;;;;UACN,MAAM;;;;gBACN,MAAM;;;;yBACN,MAAM;;;;qBACN,CAAC,GAAC,CAAC;;;;yBACH,MAAM;;;;+BACN,eAAe,GAAC,sBAAsB;;;;4BACtC,MAAM;;;;gBACN,OAAO;;;;0BAElB;QAAmD,YAAY,EAApD,kBAAkB;KAC7B;;;;8BAAW,MAAM;;;;kCACN,MAAM;;;;;;eAIN,eAAe,GAAG,eAAe,EAAE;;;;kBACnC,kBAAkB;;;;;;cAIlB,SAAS,GAAC,YAAY,GAAC,QAAQ;;;;SAC/B,MAAM;;;;YACN,MAAM;;;;iCACN,MAAM;;;;;;;;;eAQN,MAAM;;;;mBACN,MAAM;;;;gBACN,MAAM;;;;cACN,MAAM;;;;;;sBAKN,MAAM;;;;cACN,MAAM;;;;gBACN,GAAC;;;;;aACD,aAAa;;;;uBAEb,OAAO;;;;;;cAKP,MAAM;;;;oBACN,QAAQ,GAAC,WAAW,GAAC,QAAQ,GAAC,WAAW,GAAC,aAAa,GAAC,UAAU,GAAC,oBAAoB,GAAC,iBAAiB,GAAC,SAAS,GAAC,IAAI,GAAC,IAAI,GAAC,MAAM;;;;YACpI,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,MAAM,EAAE,GAAG,MAAM,EAAE;;;;;;iBAK/C,aAAa;;;;qBACb,KAAK,GAAC,IAAI;;;;kBACV,aAAa;;;;;;iBAKb,gBAAgB,CAAC,UAAU,CAAC;;;;cAC5B,gBAAgB,CAAC,gBAAgB,CAAC;;;;mBAClC,gBAAgB,CAAC,OAAO,CAAC;;;;;;iBAKzB,iBAAiB,CAAC,aAAa,CAAC;;;;cAChC,iBAAiB,CAAC,iBAAiB,CAAC;;;;kBACpC,iBAAiB,CAAC,cAAc,CAAC;;4BAIlC,mBAAmB,GAAG,oBAAoB;;;;;sBAKzC,MAAM;;;;cACN,MAAM;;;;;gBACN,GAAC;;;;WAED,MAAM;;;;aACN,MAAM,EAAE;;;;WACR;QAAC,QAAQ,EAAC,MAAM,CAAC;QAAC,SAAS,EAAE,KAAK,GAAC,MAAM,CAAA;KAAC,EAAE;;;;YAC5C,WAAW,GAAG,iBAAiB;;;;;;iBAK/B,WAAW,GAAG,iBAAiB;;;;qBAC/B,KAAK,GAAC,IAAI;;;;mBACV,aAAa,GAAG,iBAAiB;;;;;;cAKjC,MAAM;;;;oBACN,OAAO,GAAC,WAAW,GAAC,QAAQ,GAAC,WAAW,GAAC,aAAa,GAAC,UAAU,GAAC,oBAAoB,GAAC,iBAAiB,GAAC,SAAS,GAAC,IAAI,GAAC,IAAI,GAAC,MAAM;;;;WACnI,MAAM,GAAG,MAAM,GAAG,OAAO,QAAQ;;;;;;iBAKjC,MAAM;;;;aACN,MAAM;;;;iBAEjB;QAA+B,aAAa,EAAjC,MAAM;QACc,MAAM,EAA1B,MAAM;QACc,IAAI,EAAxB,MAAM;QACc,QAAQ,EAA5B,MAAM;QACc,QAAQ,EAA5B,MAAM;QACc,cAAc,EAAlC,MAAM;KACjB;;;;;;;;;;gBACW,MAAM;;;;mBAEjB;QAAmC,QAAQ,EAAhC,MAAM,EAAE;QACgB,cAAc,EAAtC,MAAM,EAAE;QACgB,kBAAkB,EAA1C,MAAM,EAAE;KACnB;;;;aAAW,MAAM;;0BAIP,OAAO,GAAC,SAAS,GAAC,MAAM,GAAC,OAAO;;;;;YAE/B,WAAW;;;;WACX,CAAC,GAAG,EAAC,MAAM,KAAG,IAAI;;;;gBAClB,CAAC,EAAE,EAAC,QAAQ,EAAC,OAAO,CAAC,EAAC,MAAM,KAAG,IAAI;;qBACpC,OAAO,SAAS,EAAE,MAAM,GAAG,WAAW;8BAItC;IAAC,EAAE,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAC;;;;;;;0CAGvC,IAAI,GAAC,KAAK,GAAC,MAAM;;;;;UAKhB,MAAM;;;;aACN,MAAM;;;;iBACN,MAAM;;;;uBACN,OAAO,GAAG,MAAM,EAAE;;;;cAE7B;QAA6B,QAAQ,EAA1B,OAAO;QACW,MAAM,EAAxB,OAAO;QACW,MAAM,EAAxB,OAAO;QACW,MAAM,EAAxB,OAAO;QACW,SAAS,EAA3B,OAAO;QACW,aAAa,EAA/B,OAAO;QACW,kBAAkB,EAApC,OAAO;KACpB;;;;;;aAKE;QAA0B,EAAE,EAAjB,MAAM;KACjB;;;;iBAAW,MAAM;;;;kBACN,MAAM;;;;mBACN,MAAM;;;;SACN,MAAM;;;;eACN,MAAM;;;;kBACN,MAAM;;;;WACN,MAAM;;;;mBAEjB;QAAgC,EAAE,EAAvB,MAAM;QACgB,QAAQ,GAA9B,MAAM;QACgB,IAAI,GAA1B,MAAM;KACjB;;;;UAAW,MAAM;;;;kBACN,MAAM;;;;iBACN,MAAM;;;;cACN,OAAO;;;;gBACP,OAAO;;;;mBACP,OAAO;;;;iBACP,OAAO;;;;;;;;;;;;;;;;;;;;;iBAQP,MAAM;;;;yBACN,MAAM;;;;sBACN,MAAM;;;;wBACN,MAAM;;;;mBACN,OAAO;;;;;;;;;YAGP,OAAO;;;;kBACP,OAAO;;;;WACP,MAAM;;;;WACN,MAAM;;;;;;;;;WAKN,MAAM;;;;UACN,MAAM;;;;cACN,UAAU,GAAC,QAAQ,GAAC,KAAK,GAAC,UAAU,GAAC,UAAU,GAAC,SAAS,GAAC,MAAM,GAAC,UAAU,GAAC,OAAO;;;;YACnF,MAAM;;;;cACN,OAAO;;;;YACP,OAAO;;;;gBACP,OAAO;;;;gBACP,OAAO;;;;uBACP,OAAO;;;;gBACP,OAAO;;;;cACP,OAAO;;;;eACP,MAAM;;;;WACN,MAAM;;;;qBACN,UAAU,GAAC,MAAM,GAAC,QAAQ,GAAC,UAAU,GAAC,kBAAkB,GAAC,UAAU,GAAC,MAAM,GAAC,WAAW,GAAC,OAAO;;;;gBAC9F,MAAM;;;;kBACN,MAAM;;;;iBACN,OAAO;;;;eACP,gBAAgB,EAAE;;;;;;6BAKlB,MAAM;;;;aACN,MAAM;;;;+BACN,SAAS,GAAC,SAAS,GAAC,gBAAgB;;;;qBAE/C;QAAoD,OAAO,EAAhD,qBAAqB,EAAE;KAClC;;;;iCAAW,UAAU;;;;iCACV,UAAU;;;;qCACV,MAAM;;;;gBAEjB;QAA8B,kBAAkB,EAArC,MAAM;QACa,gBAAgB,EAAnC,MAAM;QACc,aAAa,EAAjC,OAAO;QACY,mBAAmB,EAAtC,MAAM;QACc,SAAS,GAA7B,MAAM;KACjB;;;;yBACA;QAAuC,MAAM,EAC7C;YAA8C,UAAU,EAA7C,MAAM;YAC6B,KAAK,EAAxC,MAAM;YAC8B,kBAAkB,GAAtD,MAAM;SACjB;KAAA;;;;gCAAW,MAAM;;;;gCACN,MAAM;;;;sBACN,MAAM,EAAE;;;;+BACR,UAAU,GAAC,UAAU,GAAC,kBAAkB;;;;uBACxC,gBAAgB,GAAC,SAAS;;;;mBAC1B,MAAM;;;;iBACN,MAAM;;;;cACN,MAAM;;;;qBACN,MAAM;;;;;;;;;cAKN,MAAM;;;;mBACN,OAAO;;;;qBACP,MAAM;;;;sBACN,MAAM;;;;yBACN,MAAM;;;;YACN,MAAM,EAAE;;;;;;;;;aAIR,KAAK,GAAC,IAAI;;;;gBACV,CAAC,UAAU,GAAG,cAAc,CAAC,EAAE;;;;;;;;;aAI/B,MAAM;;;;cACN,UAAU,GAAC,QAAQ,GAAC,KAAK,GAAC,UAAU,GAAC,UAAU,GAAC,SAAS,GAAC,MAAM,GAAC,UAAU,GAAC,OAAO;;;;eACnF,MAAM;;;;cACN,MAAM;;;;QACN,MAAM;;;;mBACN,OAAO;;;;UACP,MAAM;;;;cACN,QAAQ,GAAC,QAAQ,GAAC,QAAQ;;;;YAC1B,MAAM;;;;eACN,MAAM;;;;yBACN,MAAM;;;;wBACN,MAAM;;;;sBACN,MAAM;;;;WACN,MAAM;;;;UACN,MAAM;;sCAKP,OAAO,GAAC,IAAI;uCAGZ,OAAO;;;;;eAGN,MAAM;;;;YACN,kBAAkB;;;;UAClB,iBAAiB;;;;;;;;;;;;mBAOjB,MAAM;;;;eACN,MAAM;;;;aACN,MAAM;;;;mBACN,MAAM;;;;aACN,UAAU,GAAC,SAAS;;;;iBACpB,KAAK,GAAC,YAAY,GAAC,eAAe,GAAC,kBAAkB;;;;gBACrD,OAAO;;;;oBACP,MAAM;;;;wBACN,MAAM;;;;gBACN,MAAM,EAAE;;;;cACR,MAAM;;;;eACN,MAAM;;;;;;cAKN,eAAe;;;;cACf,eAAe"} \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md deleted file mode 100644 index 9878c0c05..000000000 --- a/CHANGELOG.md +++ /dev/null @@ -1,126 +0,0 @@ -# Changelog - -Accenture SFMC DevTools follows [semantic versioning](https://semver.org/). - ---- - -## [3.1.1](https://github.com/Accenture/sfmc-devtools/compare/v3.1.0...v3.1.1) - 2022-01-10 - -**Bugfixes:** - -- [#160](https://github.com/Accenture/sfmc-devtools/issues/160) mcdev outputs bogus text since dependency colorjs got corrupted ( [background story](https://www.theverge.com/2022/1/9/22874949/developer-corrupts-open-source-libraries-projects-affected)) - -**Chores:** - -- bumped cli-progress to 3.10.0 (removes colors dependency) -- bumped winston to 3.3.4 (removes colors dependency) - ---- - -## [3.1.0](https://github.com/Accenture/sfmc-devtools/compare/v3.0.3...v3.1.0) - 2021-12-27 - -**Features:** - -- [#55](https://github.com/Accenture/sfmc-devtools/issues/55) added user / roles documentation -- [#64](https://github.com/Accenture/sfmc-devtools/issues/64) Added `accountUser` (system users) support (retrieve) -- [#103](https://github.com/Accenture/sfmc-devtools/issues/103) Add rename `dataExtensionField` option (via Name_new) -- [#130](https://github.com/Accenture/sfmc-devtools/issues/130) offer `retrieveChangelog` option to other node packages including mcdev (see [retrieveChangelog.js](/lib/retrieveChangelog.js) for a how-to) -- [#133](https://github.com/Accenture/sfmc-devtools/issues/133) `dataExtensionField` validation during DE update (see [README](README.md#722-addingupdating-fields-on-existing-data-extensions) for details) -- [#136](https://github.com/Accenture/sfmc-devtools/issues/136) enable including mcdev in other node packages (see [README](README.md#26-using-mcdev-in-other-node-packages) for a how-to) -- [#144](https://github.com/Accenture/sfmc-devtools/issues/144) added file type .ai to `asset` - thanks to @fbellgr - -**Bugfixes:** - -- [#112](https://github.com/Accenture/sfmc-devtools/issues/112) add (unknown) new type 783 to defintion of `importFile` -- [#117](https://github.com/Accenture/sfmc-devtools/issues/117) `queries` not deployable when target is `shared DE` -- [#118](https://github.com/Accenture/sfmc-devtools/issues/118) `automation` start not auto-retried during deploy -- [#119](https://github.com/Accenture/sfmc-devtools/issues/119) fixed `list` dependency for importFile -- [#122](https://github.com/Accenture/sfmc-devtools/issues/122) ECONNRESET on caching metadata during deploy -- [#128](https://github.com/Accenture/sfmc-devtools/issues/128) `dataExtension` json not equal for retrieve/deploy -- [#129](https://github.com/Accenture/sfmc-devtools/issues/129) `script` json not equal for retrieve/deploy -- [#140](https://github.com/Accenture/sfmc-devtools/issues/140) avoid issues when retrieving `dataExtensions` that do not have a folder ID (edge case) - thanks to @fbellgr -- [#144](https://github.com/Accenture/sfmc-devtools/issues/144) improved handling high volumes of `asset` - thanks to @fbellgr -- [#149](https://github.com/Accenture/sfmc-devtools/issues/149) handle errors on upsert of data extensions gracefully - -**Chores:** - -- [#5](https://github.com/Accenture/sfmc-devtools/issues/5) removed postinstall msg after npm 7 dropped support for that -- [#127](https://github.com/Accenture/sfmc-devtools/issues/127) bad message "info: updated automation: undefined" -- [#132](https://github.com/Accenture/sfmc-devtools/issues/132) `dataExtension.SendableSubscriberField.Name` now has a slightly more readable value -- [#137](https://github.com/Accenture/sfmc-devtools/issues/137) docs for installing a specific version were incorrect -- [#138](https://github.com/Accenture/sfmc-devtools/issues/138) make issues and pull requests clickable in gitfork -- change `mcdev document` to take the cred/BU first and then the type to align it with other commands -- improved error handling of `document role` command -- bumped cli-progress to 3.9.1 -- bumped eslint to 8.4.1 -- bumped eslint-plugin-mocha to 10.0.1 -- bumped eslint-plugin-prettier to 4.0.0 -- bumped fs-extra to 10.0.0 -- bumped husky to 7.0.4 -- bumped inquirer to 8.2.0 -- bumped jsdoc-to-markdown to 7.1.0 -- bumped lint-staged to 12.1.2 -- bumped mocha to 9.1.3 -- bumped mustache to 4.2.0 -- bumped prettier to 2.5.1 -- bumped semver to 7.3.5 -- bumped simple-git to 2.48.0 -- bumped yargs to 17.3.0 -- [#146](https://github.com/Accenture/sfmc-devtools/issues/146) remove AccountUser retrieve as a default retrieve option - ---- - -## [3.0.3](https://github.com/Accenture/sfmc-devtools/compare/v3.0.2...v3.0.3) - 2021-08-11 - -**Bugfixes:** - -- [#100](https://github.com/Accenture/sfmc-devtools/issues/100) Handle ECONNRESET errors across various types (incl. Data Extensions) -- [#102](https://github.com/Accenture/sfmc-devtools/issues/102) block deployment attempt for synchronized Data Extensions with proper error message -- [#104](https://github.com/Accenture/sfmc-devtools/issues/104) block deployment of shared data extensions on child BUs (existing solution broke somewhere down the line) - -**Chores:** - -- [#107](https://github.com/Accenture/sfmc-devtools/issues/107) rewrite folder to use generic update/create to help with ECONNRESET issue -- [#108](https://github.com/Accenture/sfmc-devtools/issues/108) return full API error messages for create & update via SOAP -- [#110](https://github.com/Accenture/sfmc-devtools/issues/110) improve error message for missing dependencies -- bumped jsdoc-to-markdown to 7.0.1 -- bumped eslint-plugin-mocha to 9.0.0 -- bumped eslint-plugin-prettier to 3.4.0 -- bumped eslint-config-prettier to 8.3.0 -- bumped eslint to 7.32.0 -- enhanced Pull Request Template with note on `npm run docs` - ---- - -## [3.0.2](https://github.com/Accenture/sfmc-devtools/compare/v3.0.1...v3.0.2) - 2021-08-03 - -**Bugfixes:** - -- [#26](https://github.com/Accenture/sfmc-devtools/issues/26) retrieving asset subtypes via r ... asset-xyz actually saves result to disk -- [#45](https://github.com/Accenture/sfmc-devtools/issues/45) connection errors for automations fixed -- [#46](https://github.com/Accenture/sfmc-devtools/issues/46) (temp fix) campaigns break entire retrieve - disabled for now -- [#48](https://github.com/Accenture/sfmc-devtools/issues/48) connection errors for dataExtensions and other types are now handled gracefully -- [#49](https://github.com/Accenture/sfmc-devtools/issues/49) connection errors for asset subtypes no longer restart downloading all subtypes -- [#51](https://github.com/Accenture/sfmc-devtools/issues/51) retrieving asset subtypes now always uses the default list of subtypes -- [#52](https://github.com/Accenture/sfmc-devtools/issues/52) no more endless retries in case of connection errors - ---- - -## [3.0.1](https://github.com/Accenture/sfmc-devtools/compare/v3.0.0...v3.0.1) - 2021-04-11 - -**Bugfixes:** - -- fix [#4](https://github.com/Accenture/sfmc-devtools/issues/4): retrieveAsTemplate led to fatal error if target metadata was not found -- migration from prior internal version was not handled gracefully before - ---- - -## 3.0.0 - 2021-03-26 - -Initial public release. - ---- - -## 2.0.0 - 2020-02-03 - -Initial Accenture-wide release. diff --git a/LICENSE b/LICENSE index 8aa75104a..d4b9b2e42 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2021 Accenture +Copyright (c) 2020-2025 Accenture Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -18,4 +18,4 @@ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. \ No newline at end of file +SOFTWARE. diff --git a/PULL_REQUEST_TEMPLATE.md b/PULL_REQUEST_TEMPLATE.md deleted file mode 100644 index 8d1725439..000000000 --- a/PULL_REQUEST_TEMPLATE.md +++ /dev/null @@ -1,19 +0,0 @@ -# PR details - -## What is the purpose of this pull request? (put an "X" next to an item) - -- [ ] Documentation update -- [ ] Bug fix -- [ ] New metadata support -- [ ] Enhanced metadata -- [ ] Add a CLI option -- [ ] Add something to the core -- [ ] Other, please explain: - -## What changes did you make? (Give an overview) - -... - -## Is there anything you'd like reviewers to focus on? - -... diff --git a/README.md b/README.md index 2dee9fa07..ecbb8fd5e 100644 --- a/README.md +++ b/README.md @@ -1,1470 +1,76 @@ # Accenture SFMC DevTools -<a id="markdown-accenture-sfmc-devtools" name="accenture-sfmc-devtools"></a> - -[![NPM](https://nodei.co/npm/mcdev.png?downloads=true&downloadRank=true&stars=true)](https://www.npmjs.com/package/mcdev) +[![view on npm](https://badgen.net/github/release/Accenture/sfmc-devtools)](https://www.npmjs.org/package/mcdev) +[![view on npm](https://badgen.net/npm/node/mcdev)](https://www.npmjs.org/package/mcdev) +[![license](https://badgen.net/npm/license/mcdev)](https://www.npmjs.org/package/mcdev) +[![npm module downloads](https://badgen.net/npm/dt/mcdev)](https://www.npmjs.org/package/mcdev) +[![GitHub closed issues](https://badgen.net/github/closed-issues/Accenture/sfmc-devtools)](https://github.com/Accenture/sfmc-devtools/issues?q=is%3Aissue+is%3Aclosed) +[![GitHub releases](https://badgen.net/github/releases/Accenture/sfmc-devtools)](https://github.com/Accenture/sfmc-devtools/releases) Accenture Salesforce Marketing Cloud DevTools (mcdev) is a rapid deployment/rollout, backup and development tool for Salesforce Marketing Cloud. It allows you to retrieve and deploy configuration and code across Business Units and instances. -<!-- TOC --> - -- [1. Changelog](#1-changelog) -- [2. Getting Started](#2-getting-started) - - [2.1. Pre-requisites](#21-pre-requisites) - - [2.1.1. Install Node.js with npm](#211-install-nodejs-with-npm) - - [2.1.2. Install the Git Command Line](#212-install-the-git-command-line) - - [2.2. Install Accenture SFMC DevTools](#22-install-accenture-sfmc-devtools) - - [2.3. Initial project setup](#23-initial-project-setup) - - [2.4. Joining a project that was set up before](#24-joining-a-project-that-was-set-up-before) - - [2.5. Recommended additional installs](#25-recommended-additional-installs) - - [2.6 Using mcdev in other node packages](#26-using-mcdev-in-other-node-packages) -- [3. Updating Accenture SFMC DevTools](#3-updating-accenture-sfmc-devtools) -- [4. Troubleshoot Install/Update](#4-troubleshoot-installupdate) - - [4.1. Installing specific version](#41-installing-specific-version) - - [4.2. Using custom CLIs](#42-using-custom-clis) - - [4.3. Missing write access to...on MacOS](#43-missing-write-access-toon-macos) - - [4.4. ...running scripts is disabled on this system](#44-running-scripts-is-disabled-on-this-system) - - [4.5. Operation not permitted OR No such file or directory](#45-operation-not-permitted-or-no-such-file-or-directory) -- [5. Metadata Type Support](#5-metadata-type-support) -- [6. Command Overview](#6-command-overview) - - [6.1. Maintenance and setup commands](#61-maintenance-and-setup-commands) - - [6.1.1. init](#611-init) - - [6.1.2. upgrade](#612-upgrade) - - [6.1.3. reloadBUs](#613-reloadbus) - - [6.1.4. badKeys](#614-badkeys) - - [6.1.5. document](#615-document) - - [6.1.6. selectTypes](#616-selecttypes) - - [6.1.7. explainTypes](#617-explaintypes) - - [6.2. Operational commands](#62-operational-commands) - - [6.2.1. retrieve](#621-retrieve) - - [6.2.2. deploy](#622-deploy) - - [6.2.3. delete](#623-delete) - - [6.2.4. retrieveAsTemplate](#624-retrieveastemplate) - - [6.2.5. buildDefinition](#625-builddefinition) - - [6.2.6. buildDefinitionBulk](#626-builddefinitionbulk) - - [6.2.7. createDeltaPkg](#627-createdeltapkg) -- [7. Advanced Configuration](#7-advanced-configuration) - - [7.1. Config Options](#71-config-options) - - [7.2. Metadata specific settings & options](#72-metadata-specific-settings--options) - - [7.2.1. Retention Policy fields in Data Extensions](#721-retention-policy-fields-in-data-extensions) - - [7.2.2. Adding/Updating Fields on existing Data Extensions](#722-addingupdating-fields-on-existing-data-extensions) - - [7.2.3. Renaming fields of a Data Extensions](#723-renaming-fields-of-a-data-extensions) - - [7.3. Market Configuration](#73-market-configuration) - - [7.4. Market List Configuration](#74-market-list-configuration) -- [8. Examples](#8-examples) - - [8.1. Retrieve and deploy Data Extension](#81-retrieve-and-deploy-data-extension) - - [8.2. Metadata Retrieving/Backup](#82-metadata-retrievingbackup) - - [8.3. Automation Deployment](#83-automation-deployment) -- [9. Contribute](#9-contribute) - - [9.1. Install Guide for Developers](#91-install-guide-for-developers) - - [9.2. Local install](#92-local-install) - - [9.3. NPM Scripts](#93-npm-scripts) - - [9.4. Developer Documentation](#94-developer-documentation) - -<!-- /TOC --> - -## 1. Changelog - -<a id="markdown-changelog" name="changelog"></a> - -Find info on the latest changes in our [Changelog](CHANGELOG.md). - -## 2. Getting Started - -<a id="markdown-getting-started" name="getting-started"></a> - -Accenture SFMC DevTools can be installed as Node.JS package. The following guide will demonstrate how you can get started within 10 minutes or less. - -<a name="pre-requisites"></a> - -### 2.1. Pre-requisites - -<a id="markdown-pre-requisites" name="pre-requisites"></a> - -#### 2.1.1. Install Node.js with npm - -<a id="markdown-install-node.js-with-npm" name="install-node.js-with-npm"></a> - -1. To check if it is already installed, at the OS command prompt, type: `node --version` - - If this command reports Node version 14.16.x or later, you’re done—proceed to the next installation. If the reported version is earlier than 14.16.x, continue to step 2. - - If you get a “command not found” error message, continue to step 2. -2. In a web browser, go to [nodejs.org](https://nodejs.org) -3. Download and run the latest **LTS** installer for your operating system. -4. When the installer finishes, try step 1 again. If it fails, please restart your terminal. If it still does not work, reboot your computer and try the version check then. - -#### 2.1.2. Install the Git Command Line - -<a id="markdown-install-the-git-command-line" name="install-the-git-command-line"></a> - -1. To check if git is already installed, at the OS command prompt, type: `git version` - - If this command reports a git version such as “git version 2.31.0” (or "git version 2.31.0.windows.1" on Windows), you’re done. Proceed to native Android or iOS environment setup. - - If you get a “command not found” error message, continue to step 2. -2. Go to [git-scm.com/downloads](https://git-scm.com/downloads). -3. Under Downloads, click the icon for your operating system. -4. Run the installer. -5. When the installer finishes, try step 1 again. If it fails, please restart your terminal. If it still does not work, reboot your computer and try the version check then. - -<a name="install-mcdev"></a> - -### 2.2. Install Accenture SFMC DevTools - -<a id="markdown-install-accenture-sfmc-devtools" name="install-accenture-sfmc-devtools"></a> - -If you experience issues installing Accenture SFMC DevTools, please check out the [Troubleshoot Install/Update](#troubleshoot-installupdate) section in this manual. - -**How to:** - -1. Install Accenture SFMC DevTools by running `npm install -g mcdev` (prefix with `sudo` on MacOS) - - If you get an error, please see the below troubleshooting section. - -When completed you will see `+ mcdev@3.0.0` printed to your screen (or the current version of it respectively). - -> **_Side note for proud nerds_:** -> -> The `-g` part behind `npm install` triggers a so-called "global installation". This is a term coined by Package Managers, in this case Node's package manager (npm) and it means that Accenture SFMC DevTools is installed on your computer and usable across projects. The alternative is a "local installation" would install Accenture SFMC DevTools only for the current project folder. This local install is a technique used to ensure everyone in the team is using the same version of a tool. Nevertheless, we strongly recommend going with the global installation to be able to use the full feature-set of Accenture SFMC DevTools. -> -> You may choose to install mcdev globally or locally. Global install runs faster and allows you to initialize new projects by running `mcdev init` in any directory. If your project does require a local installation, please refer to the [Local Install Guide](#local-install). - -### 2.3. Initial project setup - -<a id="markdown-initial-project-setup" name="initial-project-setup"></a> - -After the successful installation, you will now need to setup the connection to your Marketing Cloud instance. - -1. In your Marketing Cloud instance - 1. Ensure that you **selected** your **Parent/Global Business Unit**. - 2. Go to `Setup -> Apps -> Installed Packages`. - 3. Create a new installed package and name it "Accenture SFMC DevTools Deployment Tool" - > Note: On some older SFMC instances it will ask you if you want the enhanced version. Please enable this option. - 4. Click on the _Add Component_ button and select `API Integration` with `Server-To-Server` mode. - 5. Make sure you grant all available rights. - 6. Go to the access tab and grant it access to all Business Units that you want to use it for, but ensure that the Parent/Global Business Unit is among these. - - _Why?_ Shared Data Extensions, roles, users, Business Unit info and some other metadata is internally stored solely on the parent Business Unit and hence can only be retrieved and updated via that BU. - 7. Note down _Client Id_, _Client Secret_ and _Authentication Base URI_. -2. In your project folder - 1. Open a CLI in your project folder (e.g. `C:\repos\MyProject\` on Windows or `~/repos/MyProject/` on Mac) - 2. Run `mcdev init` to start the interactive setup wizard. - 1. If not found yet, default configuration files will be copied into your project folder, copied by initializing an npm project and a local Git repository. - 2. The wizard will ask you to name your credential. The name you choose here will be used by all team members because the config is shared via Git. - > Being specific here reduces the chance of deploying to the wrong server (instance) in stressful situations. We suggest you use something like `ClientName`, or `ClientName-ProjectName` if you have multiple projects with the same client. In case your project uses multiples instances you might like to use something like `Client-ProjectName-Sandbox` and `Client-ProjectName-PROD`. - 3. It will then continue to ask for the client ID, client secret and Authentication Base URI. - 4. The credentials will be automatically tested & your list of BUs downloaded until finally the central configuration file `.mcdevrc.json` gets created in your project folder. - 5. Last step is to download an initial backup and commit it into git. No worries - the wizard does that for you! - 3. If this is the first time you set up Accenture SFMC DevTools or you recently upgraded Accenture SFMC DevTools, please restart VS Code now! A pop-up will likely appear in the lower right corner prompting you to install recommended extensions. - 4. Done. -3. Sharing the project with your team - 1. Make sure you have a Git repo (Bitbucket, GitHub, GitLab) set up somewhere. If you are an SI partner, usually, your client will have to do this for you. - > While running `mcdev init`, the tool already made sure to set up a local Git repo for you. Now, you need to upload ("push") it to the online repo: - 2. Open the URL of your online repo and find the "CLONE" button. This will likely show you a normal URL, ending on ".git" - 3. Add this as your repository remote named "origin". If you use a GUI based tool, that should be fairly simple, otherwise execute `git remote add origin YOUR-URL` in your project folder. - 4. Now run `git push -u origin master` to actually start the upload. - -### 2.4. Joining a project that was set up before - -<a id="markdown-joining-a-project-that-was-set-up-before" name="joining-a-project-that-was-set-up-before"></a> - -If Accenture SFMC DevTools was already used to set up the project by somebody in your team, including all of the steps in the above chapter [Initial project configuration](#initial-project-setup), then basically you are in luck. Things are much faster from here on: - -1. Make sure you went through the chapters [Pre-requisites](#pre-requisites) and [Install Accenture SFMC DevTools](#install-mcdev). Do skip [Initial project configuration](#initial-project-setup)! -2. Acquire the URL to your Git repo and Clone it to your computer. It should end on `.git`. Also ask your team lead for `Client ID`, `Client Secret` and the `Authentication Base URI`. You will need this later. - > We recommend you create a folder like `C:\repos\` and clone the repo for your current project into that. By default, the repo name will be suggested as a sub-folder name which you should keep in place. That way you will always have one folder in which all your projects can be found in with their respective sub-folders. -3. Open your main repo folder (e.g. `C:\repos\`) in the CLI of your choice (e.g. PowerShell on Windows) -4. now execute `git clone YOUR-REPO-URL`. This will create a sub-folder with the name of the repo and download everything for you into it (e.g. `C:\repos\YOUR-REPO\`) -5. Still in the command prompt, execute `cd YOUR-REPO`. This will switch your current folder (visible before the command prompt) to the new repo folder (`C:\repos\YOUR-REPO\`). -6. Assuming you installed Accenture SFMC DevTools globally (recommended!), now execute `mcdev init`. -7. At this point the system will recognize the previously set up project and ask you for `Client ID`, `Client Secret` and the `Authentication Base URI`. -8. Done. - -### 2.5. Recommended additional installs - -<a id="markdown-recommended-additional-installs" name="recommended-additional-installs"></a> - -The following seeks to enhance your daily process. Our guide assumes that you are using [Visual Studio Code](https://code.visualstudio.com/download) to develop, backup and deploy your project. For smooth operations we highly recommend the following Marketing Cloud specific plugins for it. - -Nevertheless, Accenture SFMC DevTools will run without them and is not associated with the development of these publicly available apps & plugins. - -> **Note:** The following lists are automatically installed when you run `mcdev init` or `mcdev upgrade`. - -**Visual Studio Code extensions:** - -When you run `mcdev init` or `mcdev upgrade` we add/update the file `.vscode/extensions.json` in your project directory with a list of recommended VSCode extensions that will help your daily workflow with Salesforce Marketing Cloud. - -Restart VS Code after cloning a prepared repo or after you've run `init` / `upgrade` and VS Code will prompt you in the lower right corner with: - -![Recommended extension prompt](img/README.md/vscode-recommendations-1.png) - -Click on `Install All` to quickly get things ready or review the recommendations first via `Show Recommendations`. If you opt for the second option, be aware that there are 2 kinds of recommendations: - -![Recommended extension prompt](img/README.md/vscode-recommendations-2.png) - -The "Workspace Recommendations" were defined by Accenture SFMC DevTools. Clicking on the little cloud icon will install all at once. The "Other Recommendations" are auto-generated by VS Code and are not controlled by Accenture SFMC DevTools. You _may_ look through those as well, but they might also be completely irrelevant for you. - -**Node modules:** - -- [eslint](https://npmjs.com/package/eslint): code linting -- [eslint-config-prettier](http://npmjs.com/package/eslint-config-prettier): ensures that prettier and eslint dont have conflicting rules -- [eslint-config-ssjs](http://npmjs.com/package/eslint-config-ssjs): allows you to have accurate code linting in \*.SSJS files -- [eslint-plugin-jsdoc](http://npmjs.com/package/eslint-plugin-jsdoc): will help you write proper jsdoc comments in your SSJS code -- [eslint-plugin-prettier](http://npmjs.com/package/eslint-plugin-prettier): runs prettier and eslint together -- [prettier](https://prettier.io): opinionated code formatter -- [npm-check](http://npmjs.com/package/npm-check): makes it easier to keep your node modules up-to-date -- [sfmc-boilerplate](http://npmjs.com/package/sfmc-boilerplate): build tool for your more complex email, cloudpage and automation code. - -Please note that Visual Studio Code might warn you about using the local installation of ESLint with a pop up like the following. Please confirm this with `Allow` or, if you are certain about what you are doing, with `Allow Everywhere`. Inside of Accenture SFMC DevTools project folders this warning is normal, because we ask to install the VSCode extension and the node module for ESLint. - -![VSCode Eslint install warning](img/README.md/vscode-eslint-allow_everywhere.jpg) - -### 2.6 Using mcdev in other node packages - -Install it locally first via the following (or with a [specific version](#41-installing-specific-version)): - -```bash -npm install --save mcdev -``` - -And then require it in your code: - -```javascript -const mcdev = require('mcdev'); - -// download all metadata from your instance's Parent BU -mcdev.retrieve('MyCredential/_ParentBU_'); - -// or download all metadata from your instance's Parent BU -mcdev.retrieve('MyCredential/_ParentBU_', 'dataExtension'); -``` - -For more details on the available methods look out for what Intellisense will return or refer to the [developer documentation](docs/dist/documentation.md). - -<a name="updating-mcdev"></a> - -## 3. Updating Accenture SFMC DevTools - -<a id="markdown-updating-accenture-sfmc-devtools" name="updating-accenture-sfmc-devtools"></a> - -If you have mcdev already installed you can update your installation in a simplified way: - -```bash -npm update -g mcdev -``` - -<a name="troubleshoot-installupdate"></a> - -## 4. Troubleshoot Install/Update - -<a id="markdown-troubleshoot-install%2Fupdate" name="troubleshoot-install%2Fupdate"></a> - -### 4.1. Installing specific version - -<a id="installing-specific-version" name="installing-specific-version"></a> - -To work with our **developer-version** or to install a **specific older version** you can select any branch or tag from our git repository during install to do so: - -**Most recent developer version (using the GitHub repo & branch name):** - -```bash -npm install -g accenture/sfmc-devtools#develop -``` - -**Install specific version (using a version tag on npm):** - -```bash -npm install -g mcdev@3.1.0 -``` - -**Warning**: When you used the above method to install Accenture SFMC DevTools for a specific version or tag, trying to [update Accenture SFMC DevTools](#updating-mcdev) might not download the most recently published official version but instead stay on the version or branch you previously selected (in the above examples: develop, 3.1.0)! - -> **Note**: The version is currently _not_ updated on the developer branch until a new release is published. Hence, you will not see a change if you run `mcdev --version`. - -### 4.2. Using custom CLIs - -<a id="markdown-using-custom-clis" name="using-custom-clis"></a> - -Some users of Accenture SFMC DevTools prefer to use git bash or other CLIs instead of the operating system's default. Please note that some of the functionality of Accenture SFMC DevTools but also of other tools like the Node package manager (npm) do not necessarily function properly in these. - -If you encounter problems, we strongly recommend to first try it in the default CLI. - -<a name="missing-write-access-toon-macos"></a> - -### 4.3. Missing write access to...on MacOS - -<a id="markdown-missing-write-access-to...on-macos" name="missing-write-access-to...on-macos"></a> - -Depending on your setup, the default global installs & updates might error out with "Missing write access to /usr/local/lib/node_modules". In this case prefix your command with `sudo`: - -```bash -sudo npm install -g mcdev -``` - -```bash -sudo npm update -g mcdev -``` - -![Mac sudo](img/README.md/troubleshoot-mac-sudo.png) - -### 4.4. ...running scripts is disabled on this system - -<a id="markdown-...running-scripts-is-disabled-on-this-system" name="...running-scripts-is-disabled-on-this-system"></a> - -If you see the below error then your system's security settings are rather strict. - -![Execution Policy](img/README.md/troubleshoot-execution_policy.jpg) - -Steps to solve this: - -1. Start Windows PowerShell with the "Run as Administrator" option. -2. Input the following and then hit ENTER: `set-executionpolicy remotesigned` -3. This will likely show a lenghty message with a question to confirm the change (screenshot below). Please type `y` (="yes") and confirm with `Enter`. - -![Execution Policy](img/README.md/troubleshoot-execution_policy-2.png) - -Please note that this change is global and not just for your current folder. - -### 4.5. Operation not permitted OR No such file or directory - -<a id="markdown-operation-not-permitted-or-no-such-file-or-directory" name="operation-not-permitted-or-no-such-file-or-directory"></a> - -If you encounter out of the 3 following errors you will have to completely remove Node.JS and install it again afterwards. - -**Error 1:** Cannot find module index.js - -![index.js not found](img/README.md/troubleshoot-nodejs-index.jpg) - -**Error 2:** Operation not permitted - -![operation not permitted](img/README.md/troubleshoot-nodejs-permission.jpg) - -**How to completely remove Node.js from Windows:** - -1. Run npm cache clean --force - -2. Uninstall it via the system's `Add or remove programs` (find it by searching in the start menu). - -3. Reboot your computer. +## Quick start -4. Look for these folders and remove them (and their contents) if any still exist. Depending on the version you installed, UAC settings, and CPU architecture, these may or may not exist: +### Install - - C:\Program Files (x86)\Nodejs - - C:\Program Files\Nodejs - - C:\Users\\{User}\AppData\Roaming\npm - - (or %appdata%\npm) - - C:\Users\\{User}\AppData\Roaming\npm-cache - - (or %appdata%\npm-cache) - - C:\Users\\{User}\.npmrc (and possibly check for that without the . prefix too) - - C:\Users\\{User}\npmrc - - C:\Users\\{User}\AppData\Local\Temp\npm-\* - -5. Check your %PATH% environment variable to ensure no references to Nodejs or npm exist. - -6. If it's still not uninstalled, type `where node` at the command prompt and you'll see where it resides -- delete that (and probably the parent directory) too. - -7. Reboot again! - -**Re-install Node.js and Accenture SFMC DevTools:** - -Now, please follow the guides above in the [Pre-requisites](#pre-requisites) section to Install Node.js again and afterwards try again to [install Accenture SFMC DevTools](#install-mcdev). - -<a name="metadata-type-support"></a> - -## 5. Metadata Type Support - -<a id="markdown-metadata-type-support" name="metadata-type-support"></a> - -The following metadata types are currently supported: - -| MetadataType | CLI Argument | Retrieve | Deploy | Template | Retrieved by Default | Description | -| ---------------------------------- | ------------------------- | -------- | ---------- | ---------- | -------------------- | ------------------------------------------------------------------------------------------------------------------ | -| API Discovery | `discovery` | Yes | - | - | - | Description of all API endpoints accessible via REST API; only relevant for developers of Accenture SFMC DevTools. | -| Asset | `asset` | Yes | Yes | Yes | Yes | Assets from Content Builder grouped into subtypes. | -| Automation | `automation` | Yes | Yes | Yes | Yes | Used via Automation Studio directly - or indirectly via Journey Builder & MC Connect. | -| Automation: Data Extract Activity | `dataExtract` | Yes | Yes | Yes | Yes | Creates zipped files in your FTP directory or convert XML into CSV. | -| Automation: File Transfer Activity | `fileTransfer` | Yes | Yes | Yes | Yes | Unzip, decrypt a file or move a file from secure location into FTP directory. | -| Automation: Filter Activity | `filter` | Beta | in backlog | in backlog | - | Part of how filtered Data Extensions are created. Depends on type "FilterDefinitions". | -| Automation: Import File Activity | `importFile` | Yes | Yes | Yes | Yes | Reads files in FTP directory for further processing. | -| Automation: SQL Query Activity | `query` | Yes | Yes | Yes | Yes | Select & transform data using SQL. | -| Automation: Script Activity | `script` | Yes | Yes | Yes | Yes | Execute more complex tasks via SSJS or AMPScript. | -| Campaign Tag | `campaign` | Yes | in backlog | in backlog | Yes | Way of tagging/categorizing emails, journeys and alike. | -| Content Area (Classic) | `contentArea` | Yes | - | - | - | **DEPRECATED**: Old way of saving Content Blocks; please migrate these to new Content Blocks (`Asset: ...`). | -| Data Designer Attribute Groups | `attributeGroup` | Beta | in backlog | in backlog | - | Groupings of Set Definitions (Data Extensions) in Data Designer. | -| Data Designer Set Definitions | `setDefinition` | Beta | in backlog | in backlog | - | Data Extensions linked to Attribute Groups in Data Designer. | -| Data Extension | `dataExtension` | Yes | Yes | Yes | Yes | Database table schemas. | -| Data Extension Template | `dataExtensionTemplate` | Yes | - | - | - | OOTB Database table schemas used for special cases like Transactional Journeys. | -| Data Extract Type | `dataExtractType` | Yes | - | - | - | Types of Data Extracts enabled for a specific business unit. This normally should not be stored. | -| E-Mail (Classic) | `email` | Yes | - | - | - | **DEPRECATED**: Old way of saving E-Mails; please migrate these to new E-Mail (`Asset: message`). | -| E-Mail Send Definition | `emailSendDefinition` | Yes | Yes | in backlog | Yes | Mainly used in Automations as "Send Email Activity". | -| Folder | `folder` | Yes | Yes | in backlog | - | Used to structure all kinds of other metadata. | -| FTPLocation | `ftpLocation` | Yes | - | - | Yes | A File Location which can be used for export or import of files to/from Marketing Cloud. | -| Journey | `interaction` | Yes | in backlog | in backlog | - | Journey from Builder (internally called "Interaction"). | -| Journey: Entry Event Definition | `eventDefinition` | Yes | Yes | in backlog | - | Used in Journeys (Interactions) to define Entry Events. | -| List | `list` | Yes | in backlog | - | Yes | Old way of storing data. Still used for central Email Subscriber DB. | -| Role | `role` | Yes | Yes | - | Yes | User Roles define groups that are used to grant users access to SFMC systems. | -| Triggered Send | `triggeredSendDefinition` | Yes | Yes | - | Yes | **DEPRECATED**: Sends emails via API or DataExtension Event. | -| User | `accountUser` | Yes | in backlog | - | - | Users and Installed Packages including their assigned Roles, BUs and personal permissions | - -## 6. Command Overview - -<a id="markdown-command-overview" name="command-overview"></a> - -If you installed mcdev globally as described above you can run mcdev in any directory. See our [install Accenture SFMC DevTools](#install-mcdev) chapter for more details. - -_Example (global install):_ - -```bash -mcdev retrieve -``` - -If you installed Accenture SFMC DevTools as a local dependency (**not recommended**) to the current directory then you will have to add `npx` in front of each command. See our [Local install](#local-install) chapter for more details. - -_Example (local install):_ - -```bash -npx mcdev retrieve -``` - -The following description will assume a global installation for simplicity reasons. - -_Note:_ Parameters listed below in between square brackets = `[...]` are optional parameters. Required parameters are listed in between less-than / greater-than signs = `<...>`. - -_Note:_ Credentials and Business Unit names can always be selected interactively. Try inputing a questionmark = `?` in their place if more parameters follow, or omit them completely if no other parameters are required for a command. - -### 6.1. Maintenance and setup commands - -<a id="markdown-maintenance-and-setup-commands" name="maintenance-and-setup-commands"></a> - -#### 6.1.1. init - -<a id="markdown-init" name="init"></a> - -_Command:_ `mcdev init` - -_Alias:_ - - -Creates the basic configuration file `.mcdevrc.json` and `.mcdev-auth.json` in your project directory. You may add more credentials by re-running the same command again, e.g. to add produciton and sandbox credentials next to each other. - -In addition, it initializes an npm package for your, installs recommended npm dependencies and places our default IDE configuration files for ESLint, Prettier, Git and VSCode into your project directory. - -The initialization ends with the creation of your Git repository and a first backup of your SFMC instance. - -_Example - initialize project / add additional credentials:_ - -```bash -mcdev init -``` - -_Example - update credentials:_ - -```bash -mcdev init yourCredentialName -``` - -The interactive setup will ask you for a `Client ID` and `Client Secret` of an enhanced installed package (default since August 2019). It also asks for the `Authentication Base Uri`. Each installed package on a given SFMC instance shares the same tenant sub-domain and always shows you 3 domains (Auth, REST and SOAP). - -Example url: `https://mcg123abcysykllg-0321cbs8bbt64.auth.marketingcloudapis.com` - -> **Note to CLI experts:** -> -> You can run this command without the interactive wizard asking questions using the `--skipInteraction` (or short`--yes`/`--y`) flag. In this case, you need to provide a few values in the command: -> -> ```bash -> mcdev init --y.credentialsName "yourCustomCredentialName" --y.clientId "yourClientIdHere" --y.clientSecret "yourClientSecretHere" --y.tenant "yourTenantSubdomainHere" --y.gitRemoteUrl "https://my.git.server.com/myrepo.git" -> ``` -> -> To get the tenant subdomain, please take the Authentication Base Uri and extract the part after `https://` and before `.auth.marketingcloudapis.com`. In the above example this would therefore be `mcg123abcysykllg-0321cbs8bbt64`. - -#### 6.1.2. upgrade - -<a id="markdown-upgrade" name="upgrade"></a> - -_Command:_ `mcdev upgrade` - -_Alias:_ `mcdev up` - -This upgrades older Accenture SFMC DevTools projects to the newest standard: Outdated Accenture SFMC DevTools configuration files are upgraded and the right npm dependencies are installed. It also copies in the right IDE configuration files. See [init](#init) for more details. - -_Example:_ +Run the following to install Accenture SFMC DevTools on your computer: ```bash -mcdev upgrade +npm install -g mcdev ``` -#### 6.1.3. reloadBUs - -<a id="markdown-reloadbus" name="reloadbus"></a> - -_Command:_ `mcdev reloadBUs [credential]` +### VSCode Extension -_Alias:_ `mcdev rb` +We also provide a [VSCode extension](https://marketplace.visualstudio.com/items?itemName=Accenture-oss.sfmc-devtools-vscode) that integrates SFMC DevTools into your IDE. You can install it from the [VSCode Marketplace](https://marketplace.visualstudio.com/items?itemName=Accenture-oss.sfmc-devtools-vscode). -Use this to synchronize your local list of available Business Units for a given credential. This is useful if you've added, deleted or renamed Business Units on your SFMC instance and want to make sure that your local setup reflects that - or if you accidentally changed your config file and want to restore it. +### Include in your package -_Example:_ +First, install it as dependency: ```bash -mcdev reloadBUs MyProject +npm install mcdev --save ``` -#### 6.1.4. badKeys - -<a id="markdown-badkeys" name="badkeys"></a> - -_Command:_ `mcdev badKeys [business unit]` - -_Alias:_ - - -Lists all metadata for which the External key is not in synch with the name to enable you to update them quickly. - -_Example:_ - -```bash -mcdev badKeys MyProject/DEV -``` - -#### 6.1.5. document - -<a id="markdown-document" name="document"></a> - -_Command:_ `mcdev document <TYPE> <business unit>` - -_Alias:_ `mcdev doc` - -Creates human readable documentation for your metadata. This command is executed by default unless you changed your config manually to set `options.documentOnRetrieve : false`. Therefore, running it manually is typically not required. You can choose to generate **HTML** (`html`) or **Markdown** (`md`) docs via `options.documentType`. - -The default format is set to `md` as Markdown renders nicely in Git as well as in VSCode's Markdown preview and can be copied from there into Confluence and other applications without losing the formatting. - -Currently supported types: - -| Name | CLI Argument | -| -------------- | --------------- | -| Data Extension | `dataExtension` | -| Role | `role` | -| User | `accountUser` | - -_Example:_ - -```bash -mcdev document role myServer -``` - -#### 6.1.6. selectTypes - -<a id="markdown-selecttypes" name="selecttypes"></a> - -_Command:_ `mcdev selectTypes` - -_Alias:_ `mcdev st` - -Allows you to interactive select which metadata is retrieved when you run the `retrieve` command. Try out `explainTypes` first to understand what each type means. - -_Example:_ - -```bash -mcdev selectTypes -``` - -_Note:_ You may select non-standard types if you run `mcdev selectTypes --debug`. This may be needed in edge cases but is not recommended in most situations. - -#### 6.1.7. explainTypes - -<a id="markdown-explaintypes" name="explaintypes"></a> - -_Command:_ `mcdev explainTypes` - -_Alias:_ `mcdev et` - -A helper command for `selectTypes` that prints out a table that defines what the various types actually are. - -Types marked as not-default should be ignored. These are either under development or merely meant to support contributing to Accenture SFMC DevTools. - -_Example:_ - -```bash -mcdev explainTypes -``` - -### 6.2. Operational commands - -<a id="markdown-operational-commands" name="operational-commands"></a> - -#### 6.2.1. retrieve - -<a id="markdown-retrieve" name="retrieve"></a> - -_Command:_ `mcdev retrieve [business unit] [metadata type]` - -_Alias:_ `mcdev r` - -Retrieves all metadata from the specified Business Unit. You can limit what types are retrieved by default using the `selectTypes` command or by changing the list in the config file directly. - -_Example:_ - -```bash -mcdev retrieve MyProject/DEV -``` - -You can ommit the Business Unit which will trigger and interactive mode based on your config: - -_Example:_ - -```bash -mcdev retrieve -``` - -If you already know the credentials name but want to only select the Business Unit interactively try this -_Example:_ - -```bash -mcdev retrieve MyProject -``` - -**retrieve specific type:** - -If you want to retrieve only a certain metadata type, let's say `script`, then pass this type in as a second parameter. The other types will remain untouched and in place, if you've previously retrieved them. - -_Example:_ - -```bash -mcdev retrieve MyProject/DEV script -``` +You can then include it in your code with JavaScript/ES module imports: -**retrieve all BUs:** - -A special variant of this command allows you to retrieve all Business Units of a given credential at once. -_Example:_ - -```bash -mcdev retrieve MyProject/* -``` - -or even - -```bash -mcdev retrieve "*" -``` - -> Note: retrieve-all will fail in some CLIs if you do not wrap the asterix (\*) in quotes. This is due to the special meaning of \* as a parameter in these CLIs. - -#### 6.2.2. deploy - -<a id="markdown-deploy" name="deploy"></a> - -_Command:_ `mcdev deploy [business unit] [metadata type]` - -_Alias:_ `mcdev d` - -Deploys metadata to the specified Business Unit. -_Example:_ - -```bash -mcdev deploy MyProject/DEV -``` - -Only metadata that you copied into the **deploy** directory will be deployed. Please keek in mind that the folder structure needs to be similar to what the retrieve command creates in the retrieve folder, including the credentials and Business Unit name. - -Similarly to `mcdev retrieve` you can also use the interactive mode to select credential and/or Business Unit. - -**deploy sepcific type:** - -If you want to deploy only a certain metadata type, let's say `dataExtension`, then pass this type in as a second parameter. If there are other types in the current BU's deploy folder, these will be ignored and hence _not_ uploaded. - -_Example:_ - -```bash -mcdev deploy MyProject/DEV dataExtension -``` - -**deploy all BUs:** - -A special variant of this command allows you to dpeloy all Business Units of a given credential at once. -_Example:_ - -```bash -mcdev deploy MyProject/* -``` - -or even - -```bash -mcdev deploy "*" -``` - -> Note: deploy-all will fail in some CLIs if you do not wrap the asterix (\*) in quotes. This is due to the special meaning of \* as a parameter in these CLIs. - -#### 6.2.3. delete - -<a id="markdown-delete" name="delete"></a> - -_Command:_ `mcdev delete <business unit> <type> <external key>` - -_Alias:_ `mcdev del` - -Deletes the given metadata from your server. This needs to be run with care as any **data** stored in the deleted _meta_-data **will be lost**. - -Currently supported types: - -| Name | CLI Argument | -| -------------- | --------------- | -| Data Extension | `dataExtension` | - -_Example:_ - -```bash -mcdev delete MyProject/_ParentBU_ dataExtension MyUserTable -``` - -#### 6.2.4. retrieveAsTemplate - -<a id="markdown-retrieveastemplate" name="retrieveastemplate"></a> - -_Command:_ `mcdev retrieveAsTemplate <business unit> <type> <name> <market>` - -_Alias:_ `mcdev rt` - -The `rt` command retrieves metadata from the server and uses your `market` configuration in `.mcdevrc.json` to replace strings with variables. The result is then stored in your `template/` folder. Please note that files stored here will keep their original name, despite this possibly containing market-specific suffixes or similar. Also note, that contrary to the deploy & retrieve folders, you will not see credential- or Business Unit-sub-folders here. - -This command is a prerequisite for the `buildDefintion` command. Alternatively though, you can copy-paste retrieved metadata from your `retrieve/` folder to your `template/` folder and update it manually - or even create it from scratch. - -> **Note**: Before using this command, you need to configure your markets first! Check out our guide on [Market Configuration](#market-configuration) to understand how to use templating and prepare your market config. - -Currently supported types: Check out [Metadata Type Support](#metadata-type-support). - -_Example:_ - -```bash -mcdev rt MyProject/DEV dataExtension MyUserTable pilotMarketDEV1 -``` - -This will result in `MyUserTable.dataExtension-meta.json` being created in your `template/` directory: - -**retrieveAsTemplate for multiple sources:** - -You can also create multiple templates with multiple sources at once. Simply specify them in a comma-separated list and put that list in quotes: - -```bash -mcdev rt MyProject/DEV dataExtension "table1,table2,table3" pilotMarketDEV1 -``` - -This will result in the following files being created in your `template/` directory: - -- `table1.dataExtension-meta.json` -- `table2.dataExtension-meta.json` -- `table3.dataExtension-meta.json` - -#### 6.2.5. buildDefinition - -<a id="markdown-builddefinition" name="builddefinition"></a> - -_Command:_ `mcdev buildDefinition <business unit> <type> <name> <market>` - -_Alias:_ `mcdev bd` - -The `buildDefinition` command allows to prepare deployments to one or multiple targets based on templates and [Market Configuration](#market-configuration). -After you have created your templates via `retrieveAsTemplate` (or manually) in your `template/dataExtension/` folder run this command to create the final deployable files in your respective `retrieve/<business unit>/` folder. - -This allows you to double-check if you actually changed something by comparing the before and after using your favorite Git client. You then have to manually copy files you want to deploy into the respective `deploy/` folder. - -> **Note**: Before using this command, you need to configure your markets first! Check out our guide on [Market Configuration](#market-configuration) to understand how to use templating and prepare your market config. - -Currently supported types: Check out [Metadata Type Support](#metadata-type-support). - -_Example:_ - -```bash -mcdev bd MyProject/QA dataExtension MyUserTable pilotMarketQA1 -``` - -This will result in the following files being created in your `retrieve/MyProject/QA/dataExtension/` directory: - -- `MyUserTable.dataExtension-meta.json` - -**buildDefinition for multiple sources:** - -You can also create defintions based on multiple templates at once. Simply specify them in a comma-separated list and put that list in quotes: - -```bash -mcdev bd MyProject/QA dataExtension "table1,table2,table3" pilotMarketDEV1 -``` - -This will result in the following files being created in your `retrieve/MyProject/QA/dataExtension/` directory: - -- `table1.dataExtension-meta.json` -- `table2.dataExtension-meta.json` -- `table3.dataExtension-meta.json` - -#### 6.2.6. buildDefinitionBulk - -<a id="markdown-builddefinitionbulk" name="builddefinitionbulk"></a> - -_Command:_ `mcdev buildDefinitionBulk <list name> <type> <name>` - -_Alias:_ `mcdev bdb` - -With `buildDefinitionBulk` you get a very powerful command that wraps around `buildDefinition`, which it executes internally. It allows you to create the definitions for multiple Business Units and multiple markets at once. - -Instead of passing in the name of credentials, Business Units and markets, you simply refer to a pre-defined market list in your `.mcdevrc.json`. This enables you to re-use the same configs over and over again, across multiple deployments and share it with your team. - -**Note**: Before using this command, you need to configure your markets first! Check out our guide on [Market List Configuration](#market-list-configuration) and [Market Configuration](#market-configuration) to understand how to use **bulk** templating and prepare your market config. - -_Example:_ - -```bash -mcdev bdb pilotMarketsQA dataExtension MyUserTable -``` - -#### 6.2.7. createDeltaPkg - -<a id="markdown-createdeltapkg" name="createdeltapkg"></a> - -_Command:_ `mcdev createDeltaPkg [range] [filter]` - -_Alias:_ `mcdev cdp` - -This command is rather versitile and hence can be used in multiple ways. The most powerful option presents itself when you configure `options.deployment.sourceTargetMapping` to point to a source `marketList` (usually for DEV-BU with a DEV market) and a target `marketList` (e.g. to a QA BU-market combo and a Production BU-market combo). Given this is configured, it can create all deployable files using Accenture SFMC DevTools's templating engine on the fly for you. - -The **minimum configuration** you need to have in your config could look something like the following: - -> Note: the following example does not show all necessary parts of the config, just those that are needed for createDeltaPkg. -> -> The example tells createDeltaPkg that the source BU is called `MyProject/DEV` and that the there are two target for deployment, `MyProject/QA` and `MyProject/PROD`. Furthermore it associates the markets `dev`, `qa` and `prod` to these BUs to ensure templating is applied - however, the markets in this example are empty which means no actual string replacement will occur. This is normal for most basic cases in which you would expect 1:1 copies on DEV, QA and PROD. -> -> When MC Connect is used, one would expect to see the External Keys of the Synchronized DataExtensions to be mentioned in the markets for easy auto-replacement. - -```json -{ - "credentials": { - "MyProject": { - "businessUnits": { - "DEV": "1235", - "QA": "1236", - "PROD": "1237" - } - } - }, - "options": { - "deployment": { - "commitHistory": 10, - "sourceTargetMapping": { - "deployment-source": "deployment-target" - } - } - }, - "directories": { - "deltaPackage": "docs/deltaPackage/", - "deploy": "deploy/", - "retrieve": "retrieve/", - "template": "template/", - "templateBuilds": ["retrieve/", "deploy/"] - }, - "markets": { - "dev": {}, - "qa": {}, - "prod": {} - }, - "marketList": { - "deployment-source": { - "description": "Define one 1:1 BU-Market combo here to as source for automated creation of deployment packages; you can create more than one source market list", - "MyProject/DEV": "dev" - }, - "deployment-target": { - "description": "Define n BU-Market combo here to as target for automated creation of deployment packages; you can create more than one target market list and they can be as complex as you like", - "MyProject/QA": "qa", - "MyProject/PROD": "prod" - } - } -} -``` - -> **Detailed Background infos:** `createDeltaPkg` internally first compares the 2 commits in Git to find the differences, then executes `retrieveAsTemplate` for all of these found differences, which creates files in your `template/` directory. Finally, it runs `buildDefinitionBulk` for everything, updating your `retrieve/` directory as well as, optionally, your `deploy/` directory, depending on your Accenture SFMC DevTools config's `directories.templateBuilds` value. The update to the first folder enables you to update you branch, while the second folder gives you the right files to immediately deploy to your BUs afterwards (not part of `createDeltaPkg). - -**Interactive commit selection:** - -This allows you to compare your latest commit (**not** what's still only unstaged/staged) with previous commits. This approach is especially useful if you are a in charge of the deployment and simply want to compare the latest commits to your master / release branch with the commit that was last deployed. - -> **Important**: Make sure you are on the branch corresponding to the environment you want to deploy to, e.g. the master branch. - -```bash -mcdev createDeltaPkg -``` - -The output will look something like this: - -![interactive commit selection](img/README.md/cdp-1.jpg) - -> _Note: The amount of displayed past commits depends on your Accenture SFMC DevTools configs settings in `options.deployment.commitHistory`. The default value is 10._ - -**Manual commit selection:** - -This is what you would do when you work on a feature branch and want to include the proposed changes for the target BUs already in the branch. - -```bash -# Option 1 - RECOMMENDED -# compare based on what you last committed -# you just committed all your changes and want to create the deployment package for master/Production; -# Recommendation: run this before creating a pull request to include the changes in your PR. - -mcdev createDeltaPkg master # resolves to master..HEAD -``` - -Alternatives: - -```bash -# the same example with another branch name: -mcdev createDeltaPkg "release/sprint-14" # resolves to release/sprint-14..HEAD - -# or even use a commit ID instead of a branch name -mcdev createDeltaPkg d21b4221 # resolves to d21b4221..HEAD - - -# Option 2 - full git range -# Treat this option with caution because createDeltaPkg always runs retrieveAsTemplate and hence downloads from your DEV BU, not from the git branch. -mcdev createDeltaPkg master..develop -``` - -**Manual commit selection without templating:** - -If you don't want to use templating, you may instead provide the optional `filter` parameter. This will limit - -```bash -mcdev createDeltaPkg d21b4221..HEAD 'MyProject/BU1' -``` - -Range and multiple filters (without templating): - -```bash -mcdev createDeltaPkg d21b4221..HEAD 'MyProject/BU1,MyProject/BU3' -``` - -> **Note to CLI experts:** -> -> If you provide a range you can run this command without the interactive wizard asking questions using the `--skipInteraction` (or short`--yes`/`--y`) flag. This will automatically empty your deploy folder before adding new files. Your command will look like this: -> -> ```bash -> mcdev createDeltaPkg <range> [filter] --y -> ``` - -## 7. Advanced Configuration - -<a id="markdown-advanced-configuration" name="advanced-configuration"></a> - -The tools confiuration can be changed in the file `.mcdevrc.json` located in the root of your project folder. - -It contains [Market Configuration](#market-configuration) (`markets: { ... }`), [Market List Configuration](#market-list-configuration) (`marketList: { ... }`) the list of usable Business Units per credentials, `directories`, as well as other `options`. - -You will also find the configuration for what metadata shall be retrieved here in `metaDataTypes.retrieve: [ ... ]`. - -You will also find a secondary file named `.mcdev-auth.json` containing your credentials. **Do not commit this to your repository!** You should only commit `.mcdevrc.json` as this file contains project wide settings that do not compromise security. - -### 7.1. Config Options - -<a id="markdown-config-options" name="config-options"></a> - -The central config in `.mcdevrc.json` holds multiple adjustable settings: - -```json -{ - "options": { - "deployment": { - "commitHistory": 10, - "sourceTargetMapping": { - "deployment-source": "deployment-target" - }, - "targetBranchBuMapping": { - "release/*": "MySandbox/QA-DE", - "master": ["MyProduction/PROD-DE", "MyProduction/PROD-NL"] - } - }, - "documentType": "md", - "exclude": { - "role": { - "CustomerKey": ["excludedRoleKey","excludedOtherRoleKey"] - } - }, - "include": { - "asset": { - "r__folder_Path": ["Content Builder/only/assets/in/here"] - }, - }, - "serverTimeOffset": -6 - }, - "directories": { - "badKeys": "docs/badKeys/", - "businessUnits": "businessUnits/", - "dataExtension": "docs/dataExtension/", - "deltaPackage": "docs/deltaPackage/", - "deploy": "deploy/", - "retrieve": "retrieve/", - "roles": "docs/roles/", - "template": "template/", - "templateBuilds": ["retrieve/", "deploy/"] - }, - "metaDataTypes": { - "documentOnRetrieve": ["role", "dataExtension"], - "retrieve": [...] - } -} -``` - -| Setting | Default | Description | -| ---------------------------------------- | -------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------- | -| options.deployment.commitHistory | 10 | Configures how many commits `createDeltaPkg` will display if no parameters are given | -| options.deployment.sourceTargetMapping | `{"deployment-source": "deployment-target"}` | Configuration of 1 or many source-target marketList combos for `mcdev createDeltaPkg` | -| options.deployment.targetBranchBuMapping | `{"release/*": "...","master": ["..."]}` | Can be used by CI/CD pipelines to know what BUs shall be deployed to upon a merge into one of the specified branches | -| options.documentType | 'md' | Defines the format for documentation ('md', 'html', 'both') | -| options.exclude.`type`.`field` | [] | Allows you to filter out metadata on retrieve based on their field values, e.g. CustomerKey (previously `options.filter`) | -| options.include.`type`.`field` | [] | Allows you to filter out metadata on retrieve based on their field values, e.g. CustomerKey | -| options.serverTimeOffset | -6 | Used to work around quirks in how SFMC handles timezones; For stack4: set to -7 (US Mountain time); others: -6 (US Central) | -| directories.badKeys | 'docs/badKeys/' | Where the documentation for bad key-name combos is stored on retrieve | -| directories.businessUnits | 'businessUnits/' | Directory to save BU base details in | -| directories.dataExtension | 'docs/dataExtension/' | Directory for `document dataExtension` output | -| directories.deltaPackage | 'docs/deltaPackage/' | Where `createDeltaPkg` stores its log | -| directories.deploy | 'deploy/' | Where `deploy` searches for files to deploy | -| directories.retrieve | 'retrieve/' | Where `retrieve` stores downloaded files | -| directories.roles | 'docs/roles/' | Directory for `document role` output | -| directories.users | 'docs/users/' | Directory for `document accountUser` output | -| directories.template | 'template/' | Where `rt` stores downloaded templates & `bd` retrieves them from | -| directories.templateBuilds | ['retrieve/','deploy/'] | Where `bd` saves final deployment versions in. This can hold multiple directories, e.g. ['retrieve/','deploy/'] | -| metaDataTypes.documentOnRetrieve | ['role','dataExtension'] | automatically executes `document` for selected types | -| metaDataTypes.retrieve | _changes with each release_ | check [Metadata Type Support](#metadata-type-support) for current list | - -### 7.2. Metadata specific settings & options - -<a id="markdown-metadata-specific-settings" name="metadata-specific-settings"></a> - -#### 7.2.1. Retention Policy fields in Data Extensions - -<a id="markdown-retention-policy-fields-in-data-extensions" name="retention-policy-fields-in-data-extensions"></a> - -The way retention policy is saved is a bit misleading and hence we wanted to provide a bit of guidance if you ever need to do a deep dive here. - -| Field | Description | Values | -| ------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------- | -| **DataRetentionPeriod** | this field should print the value of the unit of measure but it unfortunately is off by one (e.g. showing "weeks" instead of "months"). Also, it seems to have no impact on what's stored.<br> We therefore excluded it from retrieve/deploy | - | -| **DataRetentionPeriodUnitOfMeasure** | represents drop down for "period after" selection | 6: years<br>5: months<br>4: weeks<br>2: days | -| **DataRetentionPeriodLength** | represents number field for "period after" selection | min: 1<br>max: 999 | -| **RowBasedRetention** | only true if "delete individual records" is selected, otherwise false | true / false | -| **ResetRetentionPeriodOnImport** | true if "Reset period on import" is checked. | This option is always false if "delete individual records" is selected | true / false | -| **DeleteAtEndOfRetentionPeriod** | true if "delete all records" is selected, otherwise false | true / false | -| **RetainUntil** | Normally, this should only be filled if a date, rather than a period was set.<br><br>This is empty for "delete individual records", but filled with a (calculated) date for the other 2 delete options even if "period after" was used.<br> Warning: trying to update a DE is denied when "period after" fields & this is provided | ""<br>or date in US format (m/d/Y H:m:s") "12/6/2021 12:00:00 AM") | - -To **disable retention completely**, ensure that you have the 3 booleans set to false, RetainUntil set to an empty string and no DataRetentionPeriod set (=those 2 attributes not present in file). - -To enable "delete All records and data extensions" you have to set RowBasedRetention:false and DeleteAtEndOfRetentionPeriod:false while at the same time providing a date in RetainUntil field or a DataRetentionPeriod via the 2 associated fields. - -It seems the 2 other modes were added on top later and hence "all records and data extension" is the default retention mode. - -#### 7.2.2. Adding/Updating Fields on existing Data Extensions - -<a id="markdown-8-examples" name="8-examples"></a> - -There are a few rules to keep in mind when playing with Data Extensions fields: - -- The `FieldType` cannot be changed on existing fields; the API returns in error is the attribute is even provided unchanged during an update -- `MaxLength` can be increased or kept on the same value but never decreased during an update -- A Non-Required/Nullable field cannot be set to be required during an UPDATE -- When new fields are added, they can be required, but then also have to have a `DefaultValue` set -- The value for `IsRequired` should be 'true' or 'false' -- The value for `IsPrimary` should be 'true' or 'false' - -#### 7.2.3. Renaming fields of a Data Extensions - -With a small addition to the Data Extension's JSON it is possible to rename fields via MC DevTools. Imagine the following Data Extension: - -```json -{ - "CustomerKey": "Account", - "Name": "Account", - "Description": "", - "IsSendable": "false", - "IsTestable": "false", - "Fields": [ - { - "Name": "BillingCity", - "Scale": "0", - "DefaultValue": "", - "MaxLength": "40", - "IsRequired": "false", - "IsPrimaryKey": "true", - "FieldType": "Text" - }, - { - "Name": "BillingCountry", - "Scale": "0", - "DefaultValue": "", - "MaxLength": "80", - "IsRequired": "false", - "IsPrimaryKey": "false", - "FieldType": "Text" - } - ], - "r__folder_Path": "Data Extensions" -} -``` - -Imagine you wanted to rename `BillingCountry` to `BillingZip` for some reason. Previously, you could either go into the GUI or delete & recreate the field. Now, MC DevTools allows you to specify `Name_new` on the field and the tool will take care of the rest during **deployment**: - -```json -{ - "CustomerKey": "Account", - "Name": "Account", - "Description": "", - "IsSendable": "false", - "IsTestable": "false", - "Fields": [ - { - "Name": "BillingCity", - "Scale": "0", - "DefaultValue": "", - "MaxLength": "40", - "IsRequired": "false", - "IsPrimaryKey": "true", - "FieldType": "Text" - }, - { - "Name": "BillingCountry" /* old name, keep here for reference during the update! */, - "Name_new": "BillingZip" /* new name */, - "Scale": "0", - "DefaultValue": "", - "MaxLength": "80", - "IsRequired": "false", - "IsPrimaryKey": "false", - "FieldType": "Text" - } - ], - "r__folder_Path": "Data Extensions" -} -``` - -All you have to do is deploy the data extension again with Name_new specified for each field that needs to be renamed. - -### 7.3. Market Configuration - -<a id="markdown-market-configuration" name="market-configuration"></a> - -You will want to setup configs for variable parts that change inbetween Business Units. We advise starting this _after_ you've first run the `retrieveAsTemplate` command. This might sound counterintuitive but when you review what was copied into your template folder you will likely spot these variable parts the fastest and can then start setting up your market config. Please consider this an iterative process as you will likely run `rt` followed by another update of your config multiple times until you got it right. - -We advise clustering your logical approach into variable things on the **instance parent** (=`_ParentBU_` in Accenture SFMC DevTools), the **environment parent** (under which you cluster your child Business Units for DEV, QA and PROD respectively), and **child Business Units**. Ideally, the instance parent is only used to deploy _Shared Data Extensions_, the environent parent is used for integrations with external services and to separate incoming data via Automations into the respective _Shared Data Extensions_. The child Business Units are then reserved for everything that is run on a market-by-market basis. - -_Note:_ We do see it often that instance parent and environment parent are one and the same. This is depending on your client's setup, since Business Units are not for free and clients sometimes decide to save the extra money. Sometimes, you even end up with only one BU for DEV activities, no QA environment - and share the instance parent between DEV and production... This is not the recommnded approach for multiple reasons, including security, but it is the reality in some of our projects. - -Here a simple example with one DEV BU, 1 QA BU and 2 PROD BUs: - -```json -// example market config in your .mcdevrc.json -"markets": { - "DEV-NL": { - "mid": "12345", - "buName": "DEV - Child NL", - "sharedFolder": "/Shared Data Extensions/DEV/NL", - "suffix": "_DEV_NL", - "countryCodeIn": "'NL'" - }, - "QA-DE": { - "mid": "12346", - "buName": "QA - Child DE", - "sharedFolder": "/Shared Data Extensions/QA/DE", - "suffix": "_QA_DE", - "countryCodeIn": "'DE'" - }, - "PROD-DE": { - "mid": "12349", - "buName": "DE - Germany", - "sharedFolder": "/Shared Data Extensions/DE - Germany", - "suffix": "_DE", - "countryCodeIn": "'DE'" - }, - "PROD-NL": { - "mid": "12351", - "buName": "NL - Netherlands", - "sharedFolder": "/Shared Data Extensions/NL - Netherlands", - "suffix": "_NL", - "countryCodeIn": "'NL'" - } -} -``` - -Way more complex example with dedicated "Parent" BUs per enviroment (DEV, QA, PROD) and multiple country-specific BUs for QA and for PROD: - -```json -// example market config in your .mcdevrc.json -"markets": { - "DEV-Parent": { - "Account_Salesforce": "Account_Salesforce_1", - "suffix": "_DEV" - }, - "DEV-NL": { - "mid": "12345", - "buName": "DEV - Child NL", - "sharedFolder": "Shared Items/Shared Data Extensions/DEV/NL", - "suffix": "_DEV_NL", - "countryCodeIn": "'NL'" - }, - "QA-Parent": { - "Account_Salesforce": "Account_Salesforce_2", - "suffix": "_QA" - }, - "QA-DE": { - "mid": "12346", - "buName": "QA - Child DE", - "sharedFolder": "Shared Items/Shared Data Extensions/QA/DE", - "suffix": "_QA_DE", - "countryCodeIn": "'DE'" - }, - "QA-GULF": { - "mid": "12347", - "buName": "QA - Child GULF", - "sharedFolder": "Shared Items/Shared Data Extensions/QA/GULF", - "suffix": "_QA_GULF", - "countryCodeIn": "'AE', 'BH', 'IQ', 'KW', 'OM', 'QA', 'SA'" - }, - "PROD-Parent": { - "Account_Salesforce": "Account_Salesforce", - "suffix": "" - }, - "PROD-AT": { - "mid": "123458", - "buName": "AT - Austria", - "sharedFolder": "Shared Items/Shared Data Extensions/AT - Austria", - "suffix": "_AT", - "countryCodeIn": "'AT'" - }, - "PROD-DE": { - "mid": "12349", - "buName": "DE - Germany", - "sharedFolder": "Shared Items/Shared Data Extensions/DE - Germany", - "suffix": "_DE", - "countryCodeIn": "'DE'" - }, - "PROD-CH": { - "mid": "12352", - "buName": "CH - Switzerland", - "sharedFolder": "Shared Items/Shared Data Extensions/CH - Switzerland", - "suffix": "_CH", - "countryCodeIn": "'CH'" - }, - "PROD-GULF": { - "mid": "12350", - "buName": "GULF - Arab states of the Persian Gulf", - "sharedFolder": "Shared Items/Shared Data Extensions/GULF - Arab states of the Persian Gulf", - "suffix": "_IC_GULF", - "countryCodeIn": "'AE', 'BH', 'IQ', 'KW', 'OM', 'QA', 'SA'" - }, - "PROD-NL": { - "mid": "12351", - "buName": "NL - Netherlands", - "sharedFolder": "Shared Items/Shared Data Extensions/NL - Netherlands", - "suffix": "_NL", - "countryCodeIn": "'NL'" - } -} -``` - -<a name="market-list-configuration"></a> - -### 7.4. Market List Configuration - -<a id="markdown-market-list-configuration" name="market-list-configuration"></a> - -Market Lists are very powerful and you will quickly notice how much time they can safe you during your deployment preparation. -Let's first look at an example list config: - -```json -// this is a market-list-config based on the example market-config listed above! -"markets": {...}, -"marketList": { - "deployment-source": { - "description": "Define one 1:1 BU-Market combo here to as source for automated creation of deployment packages; you can create more than one source market list", - "MySandbox/DEV-NL": "DEV-NL" - }, - "deployment-target": { - "description": "Define n BU-Market combo here to as target for automated creation of deployment packages; you can create more than one target market list and they can be as complex as you like", - "MySandbox/QA-DE": "QA-DE", - "MyProduction/PROD-DE": "PROD-DE", - "MyProduction/PROD-NL": "PROD-NL" - } -} -``` - -The above can be used together with `createDeltaPkg` command. - -Way more complex example: - -```json -// this is a market-list-config based on the example market-config listed above! -"markets": {...}, -"marketList": { - "Parent-shared": { - "description": "used to deploy shared data extensions", - "MySandbox/_ParentBU_": ["QA-DE", "QA-GULF"], - "MyProduction/_ParentBU_": ["PROD-AT", "PROD-CH", "PROD-DE", "PROD-GULF", "PROD-NL"] - }, - "Parent-medium": { - "description": "if you use the instance's parent BU also for imports", - "MySandbox/_ParentBU_": "QA-Parent", - "MyProduction/_ParentBU_": "PROD-Parent" - }, - "Parent-large": { - "description": "very large projects often decide against using the instance parent to get more order into the chaos and define their own 'parents' instead", - "MySandbox/QA-_Parent_": "QA-Parent", - "MyProduction/ProjectX-_Parent_": "PROD-Parent" - }, - "Parent-medium-multi": { - "description": "equal to Parent-shared" - }, - "Parent-large-multi": { - "description": "use to deploy market-adapted queries to your parent BUs", - "MySandbox/QA-_Parent_": ["QA-DE", "QA-GULF"], - "MyProduction/ProjectX-_Parent_": [ - "PROD-AT", - "PROD-CH", - "PROD-DE", - "PROD-GULF", - "PROD-NL" - ] - }, - "Children": { - "description": "use this to deploy to your market BUs", - "MySandbox/QA-DE": "QA-DE", - "MySandbox/QA-GULF": "QA-GULF", - "MyProduction/PROD-Child_AT": "PROD-AT", - "MyProduction/PROD-Child_CH": "PROD-CH", - "MyProduction/PROD-Child_DE": "PROD-DE", - "MyProduction/PROD-Child_GULF": "PROD-GULF", - "MyProduction/PROD-Child_NL": "PROD-NL" - } -} +```javascript +import mcdev from 'mcdev'; ``` -First off, we don't see DEV in here. If you have more than one market in DEV then this might deviate but in general, you don't want to bulk-deploy to DEV as this is your single source of truth. - -Apart from that we can see 4 types of lists here: - -1. `Parent-shared` (_instance parent_): This would be used to deploy the Shared Data Extensions to the instance parent. The child-configs are listed in an array to ensure we end up with one file per child in our parent BU folder. -2. `Parent-medium`/`Parent-large` (medium:_instance parent_; large:_environment parent_): A 1:1 config that handles automations and the part of your solution that only runs on the parent. -3. `Parent-medium-multi`/`Parent-large-multi` (medium:_instance parent_; large:_environment parent_): Any scripts, queries, automations that are executed on the parent but require one per child (e.g. query to fill country-specific Shared Data Extensions) -4. `Children` (_child BUs_): everything that is needed on the market specific Business Units. - -## 8. Examples - -<a id="markdown-examples" name="examples"></a> - -### 8.1. Retrieve and deploy Data Extension - -<a id="markdown-retrieve-and-deploy-data-extension" name="retrieve-and-deploy-data-extension"></a> - -1. Retrieve metadata by running `mcdev retrieve <BU>` (where the BU corresponds to a credential-Business Unit combo in the **.mcdevrc.json**) -2. Create a directory called `deploy/` in the root directory -3. Create a directory called `dataExtension/` in the `deploy/` directory -4. Copy a single dataExtension directory from the `retrieve/<credential>/<BU-Name>/dataExtension/` directory into `deploy/<credential>/<BU-Name>/dataExtension/` -5. Run `mcdev deploy <BU>` to deploy everything in the **deploy** folder to the specified Business Unit - -### 8.2. Metadata Retrieving/Backup - -<a id="markdown-metadata-retrieving%2Fbackup" name="metadata-retrieving%2Fbackup"></a> - -Metadata of a Business Unit can be retrieved by running the following command: - -`mcdev retrieve <BU>` - -where `<BU>` needs to be replaced with `credentialName/businessUnit-Name` that is defined in **.mcdevrc.json**. - -Run this command for each of your defined Business Units and this will result in a **retrieve** directory with a sub-directory for each Business Unit. Each sub-directory contains the metadata from this Business Unit that is currently supported to **retrieve**. - -This folder structure can be commited into a git repository and used as backup. +That will load `node_packages/mcdev/lib/index.js`. It can make sense to directly include other files if you have a special scenario. We've done that in our example for [retrieveChangelog.js](https://github.com/Accenture/sfmc-devtools/blob/main/lib/retrieveChangelog.js) or in more detail, in our child-project [sfmc-devtools-copado](https://github.com/Accenture/sfmc-devtools-copado) to get full control over certain aspects. -### 8.3. Automation Deployment +## Documentation -<a id="markdown-automation-deployment" name="automation-deployment"></a> +Please checkout the [GitHub wiki](https://github.com/Accenture/sfmc-devtools/wiki) for the full documentation. -Now we want to deploy an Automation with it's related metadata. Select a retrieved Automation and copy it into the deploy folder. (`deploy/<credential>/<BU-Name>/automation/myAutomation.meta-automation.json`) +## Changelog -Copy all related activity metadata of this automation into the deploy folder. (_Example:_ `deploy/<credential>/<BU-Name>/query/myquery.meta-query.json` and `deploy/<credential>/<BU-Name>/query/myquery.meta-query.sql`) +Find info on the latest releases with a detailed changelog in the [GitHub Releases tab](https://github.com/Accenture/sfmc-devtools/releases). -To start the deployment run the following command: - -`mcdev deploy <BU>` - -## 9. Contribute - -<a id="markdown-contribute" name="contribute"></a> +## Contribute If you want to enhance Accenture SFMC DevTools you are welcome to fork the repo and create a pull request. Please understand that we will have to conduct a code review before accepting your changes. -### 9.1. Install Guide for Developers - -<a id="markdown-install-guide-for-developers" name="install-guide-for-developers"></a> - -Instead of installing Accenture SFMC DevTools as a npm dependency from our git repo, we recommend cloning our repo and then linking it locally: - -Assuming you cloned Accenture SFMC DevTools into `C:\repos\sfmc-devtools\` (or `~/repos/sfmc-devtools/` on Mac) you can then go into your project directory, open a terminal there and run: - -_Local install:_ - -```bash -npm install --save-dev "C:\repos\sfmc-devtools" -``` - -or - -_Global install **(recommended)**:_ - -```bash -npm install -g "C:\repos\sfmc-devtools" -``` - -This should tell npm to create a symlink to your cloned local directoty, allowing you to see updates you make in your mcdev repo instantly. - -> Note: on MacOS you might need to prepend `sudo` to elevate your command. - -**Local vs. Global developer installation:** - -If you use Accenture SFMC DevTools in your team it is recommended to install your developer version **globally**, while the project's package.json should point to our Git repo in its devDependency section. Otherwise other team members would have trouble due to potentially different paths. - -If you do need to install it locally, make sure you don't commit your project's package.json with this change or you might break mcdev for other developers in your team that either didn't clone the Accenture SFMC DevTools repo or stored in a different directory. - -To test your new **global** developer setup, run `mcdev --version` in CLI which should return the current version (e.g. `3.0.0`). Then, go into your mcdev repo and update the version with the suffix `-dev`, e.g. to `3.0.0-dev` and then run `mcdev --version` again to verify that your change propagates instantly. - -<a name="local-install"></a> - -### 9.2. Local install - -<a id="markdown-local-install" name="local-install"></a> - -> **Warning:** local installation (leading to the use of [npx](https://github.com/npm/npx#readme)) causes issues when spaces are used in keys/names and is therefore not recommended. -> You will also make setting up projects much harder if you choose the local installation as you cannot use `mcdev init` to automatically setup your entire project. - -The following explains how you _could_ install it locally for certain edge cases: - -1. Create a new folder for your upcoming SFMC project. Let's assume you named it `MyProject/` - > _Note:_ It is best practice to create a separate project folder for each of your client projects to avoid accidentally overwriting the wrong BU. -2. Now, open a command line interface (CLI) for that folder. - - In Windows, you can easily do that by pressing SHIFT + Right click into that folder and then selecting the option "Open PowerShell window here". - - Alternatively, you could use any other CLI. We recommend opting for [Visual Studio Code](https://code.visualstudio.com/download)'s "Terminal" as you can benefit from this later. - - Your CLI prompt should look something like `PS C:\repos\MyProject>` on Windows or `~/repos/MyProject/` on Mac. -3. Initialize your new SFMC project by running `npm init`. - > _Note:_ npm is the "package manager" of Node.js and we use it to bundle Accenture SFMC DevTools together with other tools. - > - > If you are not familiar with node-projects or npm yet, we found this [blog post on nodesource.com](https://nodesource.com/blog/an-absolute-beginners-guide-to-using-npm/) to be helpful for beginners. - > In short, a package manager provides you with an easy name-based way of installing and updating tools you want to use as a team and ensuring that you are all using the same version. -4. Afterwards, install Accenture SFMC DevTools by running `npm install --save-dev mcdev` - - If you get an error, please see the below troubleshooting section. - -When completed you will see `+ mcdev@3.0.0` printed to your screen (or the current version of it respectively). - -### 9.3. NPM Scripts +More details on how to best do that are described in our [wiki](https://github.com/Accenture/sfmc-devtools/wiki/10.-Contribute). -<a id="markdown-npm-scripts" name="npm-scripts"></a> +## Main Contacts -- `start`: Main entry point -- `mcdev`: alias for `start` -- `build`: Runs documentation and linting scripts -- `debug`: start debugging session -- `docs`: Generates jsdocs API documentation as markdown -- `lint`: Runs eslint with autofix and prettier -- `test`: Runs mocha tests - outdated -- `upgrade`: run npm-check to test for updated depdencies +The people that lead this project: -### 9.4. Developer Documentation +<table><tbody><tr><td align="center" valign="top" width="11%"> +<a href="https://www.linkedin.com/in/joernberkefeld/"> +<img src="https://github.com/JoernBerkefeld.png" width="250" height="250"><br /> +<b>Jörn Berkefeld</b> +</a><br> +<a href="https://github.com/JoernBerkefeld">GitHub profile</a> +</td><td align="center" valign="top" width="11%"> +<a href="https://www.linkedin.com/in/douglasmidgley/"> +<img src="https://github.com/DougMidgley.png" width="250" height="250"><br /> +<b>Doug Midgley</b> +</a><br> +<a href="https://github.com/DougMidgley">GitHub profile</a> +</td></tr></tbody></table> -<a id="markdown-developer-documentation" name="developer-documentation"></a> +## Copyright -- [Link to API Documentation](docs/dist/documentation.md) -- [Link to Considerations & Findings Documentation](docs/dist/considerations.md) +Copyright (c) 2020-2025 Accenture. [MIT licensed](https://github.com/Accenture/sfmc-devtools/blob/main/LICENSE). diff --git a/boilerplate/config.json b/boilerplate/config.json index 7ca2d7525..893f8d176 100644 --- a/boilerplate/config.json +++ b/boilerplate/config.json @@ -1,40 +1,72 @@ { "credentials": { "default": { - "clientId": "--- update me ---", - "clientSecret": "--- update me ---", - "tenant": "--- update me ---", - "eid": "000000000", + "eid": 0, "businessUnits": {} } }, "options": { + "formatOnSave": true, + "formatErrorLog": false, "deployment": { "commitHistory": 10, "sourceTargetMapping": { "deployment-source": "deployment-target" }, + "branchSourceTargetMapping": { + "sit": { + "deployment-sit-source": "deployment-sit-target" + }, + "uat": { + "deployment-uat-source": "deployment-uat-target" + }, + "prod": { + "deployment-prod-source": "deployment-prod-target" + } + }, "targetBranchBuMapping": { "release/*": "MySandbox/QA-DE", "master": ["MyProduction/PROD-DE", "MyProduction/PROD-NL"] } }, + "validation": { + "retrieve": { + "noAmpscriptHtmlTag": "warn", + "noGuidKeys": "warn", + "noRootFolder": "warn" + }, + "buildDefinition": { + "noAmpscriptHtmlTag": "warn", + "noGuidKeys": "warn", + "noRootFolder": "warn" + }, + "deploy": { + "noAmpscriptHtmlTag": "warn", + "noGuidKeys": "warn", + "noRootFolder": "warn", + "overrides": [ + { + "type": ["journey"], + "options": { + "noGuidKeys": "warn" + } + } + ] + } + }, "documentType": "md", + "documentStandardRoles": false, "exclude": {}, "include": {}, "serverTimeOffset": -6 }, "directories": { - "badKeys": "docs/badKeys/", "businessUnits": "businessUnits/", - "dataExtension": "docs/dataExtension/", - "deltaPackage": "docs/deltaPackage/", "deploy": "deploy/", + "docs": "docs/", "retrieve": "retrieve/", - "roles": "docs/roles/", "template": "template/", - "templateBuilds": ["retrieve/", "deploy/"], - "users": "docs/users/" + "templateBuilds": ["retrieve/", "deploy/"] }, "markets": { "DEV-NL": { @@ -68,18 +100,15 @@ }, "marketList": { "deployment-source": { - "description": "Define one 1:1 BU-Market combo here to as source for automated creation of deployment packages; you can create more than one source market list", - "MySandbox/DEV-NL": "DEV-NL" + "description": "Define one 1:1 BU-Market combo here to as source for automated creation of deployment packages; you can create more than one source market list" }, "deployment-target": { - "description": "Define n BU-Market combo here to as target for automated creation of deployment packages; you can create more than one target market list and they can be as complex as you like", - "MySandbox/QA-DE": "QA-DE", - "MyProduction/PROD-DE": "PROD-DE", - "MyProduction/PROD-NL": "PROD-NL" + "description": "Define n BU-Market combo here to as target for automated creation of deployment packages; you can create more than one target market list and they can be as complex as you like" } }, "metaDataTypes": { - "documentOnRetrieve": ["accountUser", "dataExtension", "role"], - "retrieve": [] + "documentOnRetrieve": ["user", "automation", "dataExtension", "role"], + "retrieve": [], + "createDeltaPkg": [] } } diff --git a/boilerplate/files/.beautyamp.json b/boilerplate/files/.beautyamp.json new file mode 100644 index 000000000..612573c50 --- /dev/null +++ b/boilerplate/files/.beautyamp.json @@ -0,0 +1,13 @@ +{ + "ampscript": { + "capitalizeAndOrNot": true, + "capitalizeIfFor": true, + "capitalizeSet": true, + "capitalizeVar": true, + "maxParametersPerLine": 4 + }, + "editor": { + "insertSpaces": true, + "tabSize": 4 + } +} diff --git a/boilerplate/files/.eslintignore b/boilerplate/files/.eslintignore deleted file mode 100644 index 8cf62d16b..000000000 --- a/boilerplate/files/.eslintignore +++ /dev/null @@ -1,5 +0,0 @@ -/deploy/** -/docs/** -/logs/** -/node_modules/** -/template/** diff --git a/boilerplate/files/.eslintrc b/boilerplate/files/.eslintrc deleted file mode 100644 index 859cae9a3..000000000 --- a/boilerplate/files/.eslintrc +++ /dev/null @@ -1,37 +0,0 @@ -{ - "extends": ["eslint:recommended", "prettier", "ssjs"], - "plugins": ["jsdoc", "prettier"], - "rules": { - "padded-blocks": "off", - "prefer-rest-params": "off", - "prefer-spread": "off", - "require-jsdoc": [ - "warn", - { - "require": { - "FunctionDeclaration": true, - "MethodDefinition": true, - "ClassDeclaration": true, - "ArrowFunctionExpression": false, - "FunctionExpression": true - } - } - ], - "valid-jsdoc": "warn", - "spaced-comment": ["warn", "always", { "block": { "exceptions": ["*"], "balanced": true } }] - }, - "overrides": [ - { - "files": ["*.js"], - "env": { "es6": true }, - "parserOptions": { - "ecmaVersion": 2018 - }, - "rules": { - "no-var": "error", - "prefer-const": "error", - "prettier/prettier": "warn" - } - } - ] -} diff --git a/boilerplate/files/.gitattributes b/boilerplate/files/.gitattributes index 8310c41d5..2d2761aeb 100644 --- a/boilerplate/files/.gitattributes +++ b/boilerplate/files/.gitattributes @@ -2,4 +2,4 @@ * text=auto eol=lf # Declare files that will always have LF line endings on checkout. -*.ssjs text eol=lf +*.ssjs text eol=lf gitlab-language=javascript diff --git a/boilerplate/files/.npmrc b/boilerplate/files/.npmrc new file mode 100644 index 000000000..3f7b4cf25 --- /dev/null +++ b/boilerplate/files/.npmrc @@ -0,0 +1 @@ +save-prefix='~' diff --git a/boilerplate/files/.prettierrc b/boilerplate/files/.prettierrc index 4aea7a51a..1d769de3b 100644 --- a/boilerplate/files/.prettierrc +++ b/boilerplate/files/.prettierrc @@ -11,6 +11,23 @@ "parser": "babel", "trailingComma": "none" } + }, + { + "files": "*.sql", + "options": { + "formatter": "sql-formatter", + "language": "tsql", + "identifierCase": "preserve", + "dataTypeCase": "preserve", + "functionCase": "upper", + "keywordCase": "upper" + } + }, + { + "files": ".mcdev-validations.js", + "options": { + "trailingComma": "es5" + } } ] } diff --git a/boilerplate/files/.vscode/extensions.json b/boilerplate/files/.vscode/extensions.json index 9385501af..9f04dab6c 100644 --- a/boilerplate/files/.vscode/extensions.json +++ b/boilerplate/files/.vscode/extensions.json @@ -5,8 +5,9 @@ // List of extensions which should be recommended for users of this workspace. "recommendations": [ // collaboration - "gruntfuggly.todo-tree", + "Accenture-oss.sfmc-devtools-vscode", "aaron-bond.better-comments", + "johnpapa.vscode-peacock", // Linters "dbaeumer.vscode-eslint", @@ -14,8 +15,14 @@ // Formatting & colors "editorconfig.editorconfig", "esbenp.prettier-vscode", - "sergey-agadzhanov.ampscript", - "adpyke.vscode-sql-formatter", + "xnerd.ampscript-language", + "FiB.beautyAmp", + + // coding helper + "MarketingThibs.ampscriptsnippets", + + // file icons for ampscript + "vscode-icons-team.vscode-icons", // Markdown / Readme.md "joernberkefeld.markdown-preview-bitbucket-innersource" diff --git a/boilerplate/files/.vscode/settings.json b/boilerplate/files/.vscode/settings.json index e19668f73..defc66e09 100644 --- a/boilerplate/files/.vscode/settings.json +++ b/boilerplate/files/.vscode/settings.json @@ -1,21 +1,58 @@ { + "explorer.compactFolders": false, + "explorer.fileNesting.enabled": true, + "explorer.fileNesting.expand": false, + "explorer.fileNesting.patterns": { + "*.ts": "${capture}.js", + "*.js": "${capture}.js.map, ${capture}.min.js, ${capture}.d.ts, ${capture}.asset-code-meta.json", + "*.jsx": "${capture}.js", + "*.tsx": "${capture}.ts", + "tsconfig.json": "tsconfig.*.json", + "package.json": "package-lock.json, yarn.lock", + "*-doc.md": "${capture}-meta.json", + "*-meta.amp": "${capture}-meta.json", + "*-meta.html": "${capture}-meta.json", + "*-meta.sql": "${capture}-meta.json", + "*-meta.ssjs": "${capture}-meta.json", + "*-meta.js": "${capture}-meta.json", + "*-meta.css": "${capture}-meta.json", + "*-meta.rss": "${capture}-meta.json", + "*-meta.txt": "${capture}-meta.json", + "*-meta.xml": "${capture}-meta.json", + "*.asset-asset-meta.html": "${dirname}.asset-asset-meta.json", + "*.asset-message-meta.html": "${dirname}.asset-message-meta.json", + "*.asset-template-meta.html": "${dirname}.asset-template-meta.json", + "*.css": "${capture}.asset-code-meta.json", + "*.docx": "${capture}.asset-document-meta.json", + "*.eps": "${capture}.asset-image-meta.json", + "*.gif": "${capture}.asset-image-meta.json", + "*.html": "${capture}.asset-code-meta.json", + "*.ics": "${capture}.asset-document-meta.json", + "*.jpeg": "${capture}.asset-image-meta.json", + "*.jpg": "${capture}.asset-image-meta.json", + "*.pdf": "${capture}.asset-document-meta.json", + "*.png": "${capture}.asset-image-meta.json", + "*.txt": "${capture}.asset-textfile-meta.json" + }, "editor.codeActionsOnSave": { - "source.fixAll.eslint": true + "source.fixAll.eslint": "explicit" }, "editor.formatOnSave": true, "files.associations": { - "*.ssjs": "javascript" + "*.ssjs": "javascript", + "*.html": "ampscript" }, "files.eol": "\n", "files.exclude": { "node_modules": true }, "javascript.validate.enable": false, - "sql-formatter.indent": " ", - "sql-formatter.uppercase": true, - "[html]": { + "[sql]": { "editor.defaultFormatter": "esbenp.prettier-vscode" }, + "[html]": { + "editor.defaultFormatter": "FiB.beautyAmp" + }, "[javascript]": { "editor.defaultFormatter": "esbenp.prettier-vscode" }, @@ -27,5 +64,19 @@ }, "[markdown]": { "editor.defaultFormatter": "esbenp.prettier-vscode" - } + }, + "[AMPscript]": { + "editor.defaultFormatter": "FiB.beautyAmp" + }, + "vsicons.associations.files": [ + { + "icon": "apex", + "languages": [ + { "ids": "ampscript", "defaultExtension": "amp" }, + { "ids": "AMPscript", "defaultExtension": "amp" } + ], + "light": true, + "format": "FileFormat.svg" + } + ] } diff --git a/boilerplate/files/README.md b/boilerplate/files/README.md index 102259af3..4213ade85 100644 --- a/boilerplate/files/README.md +++ b/boilerplate/files/README.md @@ -2,8 +2,8 @@ This project relies on **Accenture SFMC DevTools**! -- Get it, check out the official docs & get support here: https://go.accenture.com/mcdev +- Get it, check out the official docs & get support here: https://github.com/Accenture/sfmc-devtools --- -© 2021 Accenture - [www.accenture.com](https://www.accenture.com/) +© 2024 Accenture - [www.accenture.com](https://www.accenture.com/) diff --git a/boilerplate/files/eslint.config.js b/boilerplate/files/eslint.config.js new file mode 100644 index 000000000..9a92d9b4d --- /dev/null +++ b/boilerplate/files/eslint.config.js @@ -0,0 +1,198 @@ +import eslintPluginPrettierRecommended from 'eslint-plugin-prettier/recommended'; +import eslintPluginUnicorn from 'eslint-plugin-unicorn'; +import globals from 'globals'; +import jsdoc from 'eslint-plugin-jsdoc'; +import js from '@eslint/js'; +import sfmcSsjs from 'eslint-config-ssjs'; + +export default [ + { + ignores: ['deploy/**/*', 'docs/**/*', 'logs/**/*', 'node_modules/**/*', 'template/**/*'] + }, + js.configs.recommended, + eslintPluginPrettierRecommended, + jsdoc.configs['flat/recommended'], + eslintPluginUnicorn.configs['flat/recommended'], + { + plugins: { jsdoc }, + rules: { + 'unicorn/better-regex': 'off', + 'unicorn/prefer-string-raw': 'off', + 'unicorn/catch-error-name': [ + 'error', + { + name: 'ex' + } + ], + 'unicorn/explicit-length-check': 'off', + 'unicorn/no-null': 'off', + 'unicorn/prefer-module': 'off', + 'unicorn/prevent-abbreviations': 'off', + 'unicorn/filename-case': 'off', + 'unicorn/no-array-callback-reference': 'off', + 'unicorn/no-array-reduce': 'off', + 'unicorn/no-await-expression-member': 'off', + 'unicorn/no-hex-escape': 'off', + 'unicorn/no-nested-ternary': 'off', + 'unicorn/no-static-only-class': 'off', + 'unicorn/no-unused-properties': 'warn', + 'unicorn/numeric-separators-style': 'off', + 'unicorn/prefer-array-some': 'off', + 'unicorn/prefer-set-has': 'off', + 'unicorn/prefer-spread': 'off', + 'unicorn/prefer-string-replace-all': 'error', + 'padded-blocks': 'off', + 'prefer-rest-params': 'off', + 'prefer-spread': 'off', + + 'jsdoc/require-jsdoc': [ + 'warn', + { + require: { + FunctionDeclaration: true, + MethodDefinition: true, + ClassDeclaration: true, + ArrowFunctionExpression: false, + FunctionExpression: true + } + } + ], + + 'valid-jsdoc': 'off', + + 'spaced-comment': [ + 'warn', + 'always', + { + block: { + exceptions: ['*'], + balanced: true + } + } + ] + } + }, + { + ...sfmcSsjs.configs.recommended, + files: ['**/*.ssjs'], + rules: { + 'unicorn/text-encoding-identifier-case': 'off', + 'unicorn/prefer-string-replace-all': 'off' + } + }, + { + files: ['**/*.js'], + + languageOptions: { + globals: { + ...globals.browser + }, + ecmaVersion: 2022 + }, + + rules: { + 'no-var': 'error', + 'prefer-const': 'error', + 'prettier/prettier': 'warn' + } + }, + { + files: ['lib/**.js', '.mcdev-validations.js'], + + languageOptions: { + globals: { + ...globals.nodeBuiltin + }, + + ecmaVersion: 2022, + sourceType: 'module' + }, + settings: { + jsdoc: { + mode: 'typescript', + + preferredTypes: { + array: 'Array', + 'array.<>': '[]', + 'Array.<>': '[]', + 'array<>': '[]', + 'Array<>': '[]', + Object: 'object', + 'object.<>': 'Object.<>', + 'object<>': 'Object.<>', + 'Object<>': 'Object.<>', + set: 'Set', + 'set.<>': 'Set.<>', + 'set<>': 'Set.<>', + 'Set<>': 'Set.<>', + promise: 'Promise', + 'promise.<>': 'Promise.<>', + 'promise<>': 'Promise.<>', + 'Promise<>': 'Promise.<>' + } + } + }, + + rules: { + 'logical-assignment-operators': ['error', 'always'], + 'arrow-body-style': ['error', 'as-needed'], + curly: 'error', + + 'jsdoc/check-line-alignment': 2, + + 'jsdoc/require-jsdoc': [ + 'warn', + { + require: { + FunctionDeclaration: true, + MethodDefinition: true, + ClassDeclaration: true, + ArrowFunctionExpression: false, + FunctionExpression: true + } + } + ], + + 'jsdoc/require-param-type': 'error', + + 'jsdoc/tag-lines': [ + 'warn', + 'any', + { + startLines: 1 + } + ], + + 'jsdoc/no-undefined-types': 'off', + 'jsdoc/valid-types': 'off', + + 'spaced-comment': [ + 'warn', + 'always', + { + block: { + exceptions: ['*'], + balanced: true + } + } + ], + 'no-var': 'error', + 'prefer-const': 'error', + 'prettier/prettier': 'warn' + } + }, + { + files: ['eslint.config.js'], + + languageOptions: { + globals: { ...globals.node }, + ecmaVersion: 2022 + }, + + rules: { + 'no-var': 'error', + 'prefer-const': 'error', + 'prettier/prettier': 'warn' + } + } +]; diff --git a/boilerplate/forcedUpdates.json b/boilerplate/forcedUpdates.json new file mode 100644 index 000000000..d0b19db13 --- /dev/null +++ b/boilerplate/forcedUpdates.json @@ -0,0 +1,84 @@ +[ + { + "version": "7.9.1", + "files": ["eslint.config.js"] + }, + { + "version": "7.7.2", + "files": [".vscode/extensions.json"] + }, + { + "version": "7.7.0", + "files": [".gitignore"] + }, + { + "version": "7.6.2", + "files": [".vscode/extensions.json"] + }, + { + "version": "7.4.3", + "files": ["eslint.config.js", ".prettierrc"] + }, + { + "version": "7.4.2", + "files": [".vscode/settings.json"] + }, + { + "version": "7.4.1", + "files": [".gitignore"] + }, + { + "version": "7.3.2", + "files": [".gitattributes"] + }, + { + "version": "7.3.1", + "files": [".vscode/settings.json"] + }, + { + "version": "7.3.0", + "files": [".vscode/settings.json"] + }, + { + "version": "7.1.0", + "files": [".vscode/settings.json", ".gitignore"] + }, + { + "version": "7.0.3", + "files": ["eslint.config.js"], + "filesRemove": [".eslintignore", ".eslintrc"] + }, + { + "version": "7.0.0", + "files": [ + ".vscode/extensions.json", + ".vscode/settings.json", + ".beautyamp.json", + ".prettierrc" + ] + }, + { + "version": "5.0.0", + "files": [".vscode/settings.json", ".prettierrc"] + }, + { + "version": "4.3.4", + "files": [".vscode/settings.json"] + }, + { + "version": "4.1.12", + "files": [".vscode/settings.json"] + }, + { + "version": "4.1.1", + "files": [".vscode/settings.json"] + }, + { + "version": "4.0.0", + "files": [".vscode/settings.json", ".vscode/extensions.json", ".prettierrc"] + }, + { + "version": "3.1.0", + "files": [".vscode/settings.json"] + } +] diff --git a/boilerplate/gitignore-template b/boilerplate/gitignore-template index ae5a16f4e..a4d67f296 100644 --- a/boilerplate/gitignore-template +++ b/boilerplate/gitignore-template @@ -1,9 +1,10 @@ *.DS_Store -deploy/ -docs/badKeys/ -docs/deltaPackage/ -logs/ node_modules/ -template/ +/deploy/ +/docs/badKeys/ +/logs/ **/QueryStudioResults at* .mcdev-auth.json +.mcdev/template/ +*.error.log +*.BAK diff --git a/boilerplate/npm-dependencies.json b/boilerplate/npm-dependencies.json index 1e40ed256..e9b1bf2d3 100644 --- a/boilerplate/npm-dependencies.json +++ b/boilerplate/npm-dependencies.json @@ -1,10 +1,13 @@ [ - "eslint", - "prettier", - "eslint-config-ssjs", + "@eslint/js", "eslint-config-prettier", - "eslint-plugin-prettier", + "eslint-config-ssjs", "eslint-plugin-jsdoc", - "npm-check", + "eslint-plugin-prettier", + "eslint-plugin-unicorn", + "eslint", + "globals", + "prettier-plugin-sql", + "prettier", "sfmc-boilerplate" ] diff --git a/docs/dist/documentation.md b/docs/dist/documentation.md deleted file mode 100644 index f2a9d7ec5..000000000 --- a/docs/dist/documentation.md +++ /dev/null @@ -1,5794 +0,0 @@ -## Classes - -<dl> -<dt><a href="#Builder">Builder</a></dt> -<dd><p>Builds metadata from a template using market specific customisation</p> -</dd> -<dt><a href="#Deployer">Deployer</a></dt> -<dd><p>Reads metadata from local directory and deploys it to specified target business unit. -Source and target business units are also compared before the deployment to apply metadata specific patches.</p> -</dd> -<dt><a href="#Mcdev">Mcdev</a></dt> -<dd><p>main class</p> -</dd> -<dt><a href="#AccountUser">AccountUser</a> ⇐ <code><a href="#MetadataType">MetadataType</a></code></dt> -<dd><p>MessageSendActivity MetadataType</p> -</dd> -<dt><a href="#Asset">Asset</a> ⇐ <code><a href="#MetadataType">MetadataType</a></code></dt> -<dd><p>FileTransfer MetadataType</p> -</dd> -<dt><a href="#AttributeGroup">AttributeGroup</a> ⇐ <code><a href="#MetadataType">MetadataType</a></code></dt> -<dd><p>AttributeGroup MetadataType</p> -</dd> -<dt><a href="#Automation">Automation</a> ⇐ <code><a href="#MetadataType">MetadataType</a></code></dt> -<dd><p>Automation MetadataType</p> -</dd> -<dt><a href="#Campaign">Campaign</a> ⇐ <code><a href="#MetadataType">MetadataType</a></code></dt> -<dd><p>Campaign MetadataType</p> -</dd> -<dt><a href="#ContentArea">ContentArea</a> ⇐ <code><a href="#MetadataType">MetadataType</a></code></dt> -<dd><p>ContentArea MetadataType</p> -</dd> -<dt><a href="#DataExtension">DataExtension</a> ⇐ <code><a href="#MetadataType">MetadataType</a></code></dt> -<dd><p>DataExtension MetadataType</p> -</dd> -<dt><a href="#DataExtensionField">DataExtensionField</a> ⇐ <code><a href="#MetadataType">MetadataType</a></code></dt> -<dd><p>DataExtensionField MetadataType</p> -</dd> -<dt><a href="#DataExtensionTemplate">DataExtensionTemplate</a> ⇐ <code><a href="#MetadataType">MetadataType</a></code></dt> -<dd><p>DataExtensionTemplate MetadataType</p> -</dd> -<dt><a href="#DataExtract">DataExtract</a> ⇐ <code><a href="#MetadataType">MetadataType</a></code></dt> -<dd><p>DataExtract MetadataType</p> -</dd> -<dt><a href="#DataExtractType">DataExtractType</a> ⇐ <code><a href="#MetadataType">MetadataType</a></code></dt> -<dd><p>DataExtractType MetadataType -Only for Caching No retrieve/upsert is required -as this is a configuration in the EID</p> -</dd> -<dt><a href="#Discovery">Discovery</a> ⇐ <code><a href="#MetadataType">MetadataType</a></code></dt> -<dd><p>ImportFile MetadataType</p> -</dd> -<dt><a href="#Email">Email</a> ⇐ <code><a href="#MetadataType">MetadataType</a></code></dt> -<dd><p>Email MetadataType</p> -</dd> -<dt><a href="#EmailSendDefinition">EmailSendDefinition</a> ⇐ <code><a href="#MetadataType">MetadataType</a></code></dt> -<dd><p>MessageSendActivity MetadataType</p> -</dd> -<dt><a href="#EventDefinition">EventDefinition</a> ⇐ <code><a href="#MetadataType">MetadataType</a></code></dt> -<dd><p>EventDefinition MetadataType</p> -</dd> -<dt><a href="#FileTransfer">FileTransfer</a> ⇐ <code><a href="#MetadataType">MetadataType</a></code></dt> -<dd><p>FileTransfer MetadataType</p> -</dd> -<dt><a href="#Filter">Filter</a> ⇐ <code><a href="#MetadataType">MetadataType</a></code></dt> -<dd><p>Filter MetadataType</p> -</dd> -<dt><a href="#Folder">Folder</a> ⇐ <code><a href="#MetadataType">MetadataType</a></code></dt> -<dd><p>Folder MetadataType</p> -</dd> -<dt><a href="#FtpLocation">FtpLocation</a> ⇐ <code><a href="#MetadataType">MetadataType</a></code></dt> -<dd><p>ImportFile MetadataType</p> -</dd> -<dt><a href="#ImportFile">ImportFile</a> ⇐ <code><a href="#MetadataType">MetadataType</a></code></dt> -<dd><p>ImportFile MetadataType</p> -</dd> -<dt><a href="#Interaction">Interaction</a> ⇐ <code><a href="#MetadataType">MetadataType</a></code></dt> -<dd><p>Script MetadataType</p> -</dd> -<dt><a href="#List">List</a> ⇐ <code><a href="#MetadataType">MetadataType</a></code></dt> -<dd><p>List MetadataType</p> -</dd> -<dt><a href="#MetadataType">MetadataType</a></dt> -<dd><p>MetadataType class that gets extended by their specific metadata type class. -Provides default functionality that can be overwritten by child metadata type classes</p> -</dd> -<dt><a href="#Query">Query</a> ⇐ <code><a href="#MetadataType">MetadataType</a></code></dt> -<dd><p>Query MetadataType</p> -</dd> -<dt><a href="#Role">Role</a> ⇐ <code><a href="#MetadataType">MetadataType</a></code></dt> -<dd><p>ImportFile MetadataType</p> -</dd> -<dt><a href="#Script">Script</a> ⇐ <code><a href="#MetadataType">MetadataType</a></code></dt> -<dd><p>Script MetadataType</p> -</dd> -<dt><a href="#SetDefinition">SetDefinition</a> ⇐ <code><a href="#MetadataType">MetadataType</a></code></dt> -<dd><p>SetDefinition MetadataType</p> -</dd> -<dt><a href="#TriggeredSendDefinition">TriggeredSendDefinition</a> ⇐ <code><a href="#MetadataType">MetadataType</a></code></dt> -<dd><p>MessageSendActivity MetadataType</p> -</dd> -<dt><a href="#Retriever">Retriever</a></dt> -<dd><p>Retrieves metadata from a business unit and saves it to the local filesystem.</p> -</dd> -</dl> - -## Constants - -<dl> -<dt><a href="#Util">Util</a></dt> -<dd><p>CLI entry for SFMC DevTools</p> -</dd> -<dt><a href="#MetadataTypeDefinitions">MetadataTypeDefinitions</a></dt> -<dd><p>Provides access to all metadataType classes</p> -</dd> -<dt><a href="#MetadataTypeInfo">MetadataTypeInfo</a></dt> -<dd><p>Provides access to all metadataType classes</p> -</dd> -<dt><a href="#mcdev">mcdev</a></dt> -<dd><p>sample file on how to retrieve a simple changelog to use in GUIs or automated processing of any kind</p> -</dd> -<dt><a href="#BusinessUnit">BusinessUnit</a></dt> -<dd><p>Helper that handles retrieval of BU info</p> -</dd> -<dt><a href="#Cli">Cli</a></dt> -<dd><p>CLI helper class</p> -</dd> -<dt><a href="#DevOps">DevOps</a></dt> -<dd><p>DevOps helper class</p> -</dd> -<dt><a href="#File">File</a></dt> -<dd><p>File extends fs-extra. It adds logger and util methods for file handling</p> -</dd> -<dt><a href="#Init">Init</a></dt> -<dd><p>CLI helper class</p> -</dd> -<dt><a href="#Init">Init</a></dt> -<dd><p>CLI helper class</p> -</dd> -<dt><a href="#Init">Init</a></dt> -<dd><p>CLI helper class</p> -</dd> -<dt><a href="#Init">Init</a></dt> -<dd><p>CLI helper class</p> -</dd> -<dt><a href="#ET_Client">ET_Client</a> : <code><a href="#ET_Client">ET_Client</a></code></dt> -<dd></dd> -<dt><a href="#Util">Util</a></dt> -<dd><p>Util that contains logger and simple util methods</p> -</dd> -</dl> - -## Functions - -<dl> -<dt><a href="#getUserName">getUserName(userList, item, fieldname)</a> ⇒ <code>string</code></dt> -<dd></dd> -<dt><a href="#createNewLoggerTransport">createNewLoggerTransport()</a> ⇒ <code>object</code></dt> -<dd><p>wrapper around our standard winston logging to console and logfile</p> -</dd> -<dt><a href="#startLogger">startLogger()</a> ⇒ <code>void</code></dt> -<dd><p>initiate winston logger</p> -</dd> -</dl> - -## Typedefs - -<dl> -<dt><a href="#CodeExtractItem">CodeExtractItem</a> : <code>Object.<string, any></code></dt> -<dd></dd> -<dt><a href="#AutomationMap">AutomationMap</a> : <code>Object</code></dt> -<dd><p>REST format</p> -</dd> -<dt><a href="#DataExtensionMap">DataExtensionMap</a> : <code>Object</code></dt> -<dd></dd> -<dt><a href="#DataExtensionFieldMap">DataExtensionFieldMap</a> : <code>Object</code></dt> -<dd></dd> -<dt><a href="#MultiMetadataTypeMap">MultiMetadataTypeMap</a> : <code>Object.<string, any></code></dt> -<dd></dd> -<dt><a href="#CodeExtractItem">CodeExtractItem</a> : <code>Object</code></dt> -<dd></dd> -<dt><a href="#CodeExtractItem">CodeExtractItem</a> : <code>Object</code></dt> -<dd></dd> -<dt><a href="#TemplateMap">TemplateMap</a> : <code>Object.<string, string></code></dt> -<dd></dd> -</dl> - -<a name="Builder"></a> - -## Builder -Builds metadata from a template using market specific customisation - -**Kind**: global class - -* [Builder](#Builder) - * [new Builder(properties, buObject, client)](#new_Builder_new) - * _instance_ - * [.buildDefinition(metadataType, name, variables)](#Builder+buildDefinition) ⇒ <code>Promise</code> - * _static_ - * [.verifyMarketList(mlName, properties)](#Builder.verifyMarketList) ⇒ <code>void</code> - -<a name="new_Builder_new"></a> - -### new Builder(properties, buObject, client) -Creates a Builder, uses v2 auth if v2AuthOptions are passed. - - -| Param | Type | Description | -| --- | --- | --- | -| properties | <code>Object</code> | properties for auth | -| properties.clientId | <code>String</code> | clientId for FuelSDK auth | -| properties.clientSecret | <code>String</code> | clientSecret for FuelSDK auth | -| properties.directories | <code>Object</code> | list of default directories | -| properties.directories.template | <code>String</code> | where templates are saved | -| properties.directories.templateBuilds | <code>String</code> | where template-based deployment definitions are saved | -| properties.tenant | <code>String</code> | v2 Auth Tenant Information | -| properties.businessUnits | <code>String</code> | ID of Business Unit to authenticate with | -| buObject | <code>Object</code> | properties for auth | -| buObject.clientId | <code>String</code> | clientId for FuelSDK auth | -| buObject.clientSecret | <code>String</code> | clientSecret for FuelSDK auth | -| buObject.credential | <code>Object</code> | clientId for FuelSDK auth | -| buObject.tenant | <code>String</code> | v2 Auth Tenant Information | -| buObject.mid | <code>String</code> | ID of Business Unit to authenticate with | -| buObject.businessUnit | <code>String</code> | name of Business Unit to authenticate with | -| client | <code>Util.ET\_Client</code> | fuel client | - -<a name="Builder+buildDefinition"></a> - -### builder.buildDefinition(metadataType, name, variables) ⇒ <code>Promise</code> -Builds a specific metadata file by name - -**Kind**: instance method of [<code>Builder</code>](#Builder) -**Returns**: <code>Promise</code> - Promise - -| Param | Type | Description | -| --- | --- | --- | -| metadataType | <code>String</code> | metadata type to build | -| name | <code>String</code> | name of metadata to build | -| variables | <code>Object</code> | variables to be replaced in the metadata | - -<a name="Builder.verifyMarketList"></a> - -### Builder.verifyMarketList(mlName, properties) ⇒ <code>void</code> -ensure provided MarketList exists and it's content including markets and BUs checks out - -**Kind**: static method of [<code>Builder</code>](#Builder) -**Returns**: <code>void</code> - throws errors if problems were found - -| Param | Type | Description | -| --- | --- | --- | -| mlName | <code>String</code> | name of marketList | -| properties | <code>Object</code> | General configuration to be used in retrieve | -| properties.markets | <code>Object</code> | list of template variable combos | -| properties.marketList | <code>Object</code> | list of bu-market combos | -| properties.credentials | <code>Object</code> | list of credentials and their BUs | - -<a name="Deployer"></a> - -## Deployer -Reads metadata from local directory and deploys it to specified target business unit. -Source and target business units are also compared before the deployment to apply metadata specific patches. - -**Kind**: global class - -* [Deployer](#Deployer) - * [new Deployer(properties, buObject, client, [type])](#new_Deployer_new) - * _instance_ - * [.deploy()](#Deployer+deploy) ⇒ <code>Promise</code> - * [.deployCallback(result, metadataType)](#Deployer+deployCallback) ⇒ <code>void</code> - * _static_ - * [.readBUMetadata(deployDir, [type], [listBadKeys])](#Deployer.readBUMetadata) ⇒ <code>Object</code> - * [.createFolderDefinitions(deployDir, metadata, metadataTypeArr)](#Deployer.createFolderDefinitions) ⇒ <code>void</code> - -<a name="new_Deployer_new"></a> - -### new Deployer(properties, buObject, client, [type]) -Creates a Deployer, uses v2 auth if v2AuthOptions are passed. - - -| Param | Type | Description | -| --- | --- | --- | -| properties | <code>Object</code> | General configuration to be used in retrieve | -| properties.directories | <code>Object</code> | Directories to be used when interacting with FS | -| buObject | <code>Object</code> | properties for auth | -| buObject.clientId | <code>String</code> | clientId for FuelSDK auth | -| buObject.clientSecret | <code>String</code> | clientSecret for FuelSDK auth | -| buObject.credential | <code>Object</code> | clientId for FuelSDK auth | -| buObject.tenant | <code>String</code> | v2 Auth Tenant Information | -| buObject.mid | <code>String</code> | ID of Business Unit to authenticate with | -| buObject.businessUnit | <code>String</code> | name of Business Unit to authenticate with | -| client | <code>Util.ET\_Client</code> | fuel client | -| [type] | <code>String</code> | limit deployment to given metadata type | - -<a name="Deployer+deploy"></a> - -### deployer.deploy() ⇒ <code>Promise</code> -Deploy all metadata that is located in the deployDir - -**Kind**: instance method of [<code>Deployer</code>](#Deployer) -**Returns**: <code>Promise</code> - Promise -<a name="Deployer+deployCallback"></a> - -### deployer.deployCallback(result, metadataType) ⇒ <code>void</code> -Gets called for every deployed metadata entry - -**Kind**: instance method of [<code>Deployer</code>](#Deployer) - -| Param | Type | Description | -| --- | --- | --- | -| result | <code>Object</code> | Deployment result | -| metadataType | <code>String</code> | Name of metadata type | - -<a name="Deployer.readBUMetadata"></a> - -### Deployer.readBUMetadata(deployDir, [type], [listBadKeys]) ⇒ <code>Object</code> -Returns metadata of a business unit that is saved locally - -**Kind**: static method of [<code>Deployer</code>](#Deployer) -**Returns**: <code>Object</code> - Metadata of BU in local directory - -| Param | Type | Default | Description | -| --- | --- | --- | --- | -| deployDir | <code>String</code> | | root directory of metadata. | -| [type] | <code>String</code> | | limit deployment to given metadata type | -| [listBadKeys] | <code>boolean</code> | <code>false</code> | do not print errors, used for badKeys() | - -<a name="Deployer.createFolderDefinitions"></a> - -### Deployer.createFolderDefinitions(deployDir, metadata, metadataTypeArr) ⇒ <code>void</code> -parses asset metadata to auto-create folders in target folder - -**Kind**: static method of [<code>Deployer</code>](#Deployer) - -| Param | Type | Description | -| --- | --- | --- | -| deployDir | <code>String</code> | root directory of metadata. | -| metadata | <code>Object</code> | list of metadata | -| metadataTypeArr | <code>String</code> | list of metadata types | - -<a name="Mcdev"></a> - -## Mcdev -main class - -**Kind**: global class - -* [Mcdev](#Mcdev) - * [.createDeltaPkg(argv)](#Mcdev.createDeltaPkg) ⇒ <code>void</code> - * [._setLoggingLevel(argv)](#Mcdev._setLoggingLevel) ⇒ <code>void</code> - * [.selectTypes()](#Mcdev.selectTypes) ⇒ <code>Promise</code> - * [.explainTypes()](#Mcdev.explainTypes) ⇒ <code>Promise</code> - * [.upgrade([skipInteraction])](#Mcdev.upgrade) ⇒ <code>Promise</code> - * [.retrieve(businessUnit, [selectedType], [changelogOnly])](#Mcdev.retrieve) ⇒ <code>Promise.<Object></code> - * [._retrieveBU(cred, bu, [selectedType], [changelogOnly])](#Mcdev._retrieveBU) ⇒ <code>Promise.<Object></code> - * [._deployBU(cred, bu, [type])](#Mcdev._deployBU) ⇒ <code>Promise</code> - * [.deploy(businessUnit, [selectedType])](#Mcdev.deploy) ⇒ <code>Promise.<void></code> - * [.initProject([credentialsName], [skipInteraction])](#Mcdev.initProject) ⇒ <code>Promise.<void></code> - * [.findBUs(credentialsName)](#Mcdev.findBUs) ⇒ <code>Promise.<void></code> - * [.document(businessUnit, type)](#Mcdev.document) ⇒ <code>Promise.<void></code> - * [.deleteByKey(businessUnit, type, customerKey)](#Mcdev.deleteByKey) ⇒ <code>Promise.<void></code> - * [.badKeys(businessUnit)](#Mcdev.badKeys) ⇒ <code>Promise.<void></code> - * [.retrieveAsTemplate(businessUnit, selectedType, name, market)](#Mcdev.retrieveAsTemplate) ⇒ <code>Promise.<void></code> - * [.buildDefinition(businessUnit, type, name, market)](#Mcdev.buildDefinition) ⇒ <code>Promise.<void></code> - * [._checkMarket(market)](#Mcdev._checkMarket) ⇒ <code>Boolean</code> - * [.buildDefinitionBulk(listName, type, name)](#Mcdev.buildDefinitionBulk) ⇒ <code>Promise.<void></code> - -<a name="Mcdev.createDeltaPkg"></a> - -### Mcdev.createDeltaPkg(argv) ⇒ <code>void</code> -handler for 'mcdev createDeltaPkg - -**Kind**: static method of [<code>Mcdev</code>](#Mcdev) - -| Param | Type | Description | -| --- | --- | --- | -| argv | <code>Object</code> | yargs parameters | -| [argv.range] | <code>String</code> | git commit range into deploy directory | -| [argv.filter] | <code>String</code> | filter file paths that start with any | -| [argv.skipInteraction] | <code>Boolean</code> | allows to skip interactive wizard | - -<a name="Mcdev._setLoggingLevel"></a> - -### Mcdev.\_setLoggingLevel(argv) ⇒ <code>void</code> -configures what is displayed in the console - -**Kind**: static method of [<code>Mcdev</code>](#Mcdev) - -| Param | Type | Description | -| --- | --- | --- | -| argv | <code>object</code> | list of command line parameters given by user | -| [argv.silent] | <code>Boolean</code> | only errors printed to CLI | -| [argv.verbose] | <code>Boolean</code> | chatty user CLI output | -| [argv.debug] | <code>Boolean</code> | enables developer output & features | - -<a name="Mcdev.selectTypes"></a> - -### Mcdev.selectTypes() ⇒ <code>Promise</code> -**Kind**: static method of [<code>Mcdev</code>](#Mcdev) -**Returns**: <code>Promise</code> - . -<a name="Mcdev.explainTypes"></a> - -### Mcdev.explainTypes() ⇒ <code>Promise</code> -**Kind**: static method of [<code>Mcdev</code>](#Mcdev) -**Returns**: <code>Promise</code> - . -<a name="Mcdev.upgrade"></a> - -### Mcdev.upgrade([skipInteraction]) ⇒ <code>Promise</code> -**Kind**: static method of [<code>Mcdev</code>](#Mcdev) -**Returns**: <code>Promise</code> - . - -| Param | Type | Description | -| --- | --- | --- | -| [skipInteraction] | <code>Boolean</code> \| <code>Object</code> | signals what to insert automatically for things usually asked via wizard | - -<a name="Mcdev.retrieve"></a> - -### Mcdev.retrieve(businessUnit, [selectedType], [changelogOnly]) ⇒ <code>Promise.<Object></code> -Retrieve all metadata from the specified business unit into the local file system. - -**Kind**: static method of [<code>Mcdev</code>](#Mcdev) -**Returns**: <code>Promise.<Object></code> - - - -| Param | Type | Description | -| --- | --- | --- | -| businessUnit | <code>String</code> | references credentials from properties.json | -| [selectedType] | <code>String</code> | limit retrieval to given metadata type | -| [changelogOnly] | <code>boolean</code> | skip saving, only create json in memory | - -<a name="Mcdev._retrieveBU"></a> - -### Mcdev.\_retrieveBU(cred, bu, [selectedType], [changelogOnly]) ⇒ <code>Promise.<Object></code> -helper for retrieve() - -**Kind**: static method of [<code>Mcdev</code>](#Mcdev) -**Returns**: <code>Promise.<Object></code> - ensure that BUs are worked on sequentially - -| Param | Type | Description | -| --- | --- | --- | -| cred | <code>String</code> | name of Credential | -| bu | <code>String</code> | name of BU | -| [selectedType] | <code>String</code> | limit retrieval to given metadata type/subtype | -| [changelogOnly] | <code>boolean</code> | skip saving, only create json in memory | - -<a name="Mcdev._deployBU"></a> - -### Mcdev.\_deployBU(cred, bu, [type]) ⇒ <code>Promise</code> -helper for deploy() - -**Kind**: static method of [<code>Mcdev</code>](#Mcdev) -**Returns**: <code>Promise</code> - ensure that BUs are worked on sequentially - -| Param | Type | Description | -| --- | --- | --- | -| cred | <code>String</code> | name of Credential | -| bu | <code>String</code> | name of BU | -| [type] | <code>String</code> | limit deployment to given metadata type | - -<a name="Mcdev.deploy"></a> - -### Mcdev.deploy(businessUnit, [selectedType]) ⇒ <code>Promise.<void></code> -Deploys all metadata located in the 'deploy' directory to the specified business unit - -**Kind**: static method of [<code>Mcdev</code>](#Mcdev) -**Returns**: <code>Promise.<void></code> - - - -| Param | Type | Description | -| --- | --- | --- | -| businessUnit | <code>String</code> | references credentials from properties.json | -| [selectedType] | <code>String</code> | limit deployment to given metadata type | - -<a name="Mcdev.initProject"></a> - -### Mcdev.initProject([credentialsName], [skipInteraction]) ⇒ <code>Promise.<void></code> -Creates template file for properties.json - -**Kind**: static method of [<code>Mcdev</code>](#Mcdev) -**Returns**: <code>Promise.<void></code> - - - -| Param | Type | Description | -| --- | --- | --- | -| [credentialsName] | <code>string</code> | identifying name of the installed package / project | -| [skipInteraction] | <code>Boolean</code> \| <code>Object</code> | signals what to insert automatically for things usually asked via wizard | - -<a name="Mcdev.findBUs"></a> - -### Mcdev.findBUs(credentialsName) ⇒ <code>Promise.<void></code> -Refreshes BU names and ID's from MC instance - -**Kind**: static method of [<code>Mcdev</code>](#Mcdev) -**Returns**: <code>Promise.<void></code> - - - -| Param | Type | Description | -| --- | --- | --- | -| credentialsName | <code>string</code> | identifying name of the installed package / project | - -<a name="Mcdev.document"></a> - -### Mcdev.document(businessUnit, type) ⇒ <code>Promise.<void></code> -Creates docs for supported metadata types in Markdown and/or HTML format - -**Kind**: static method of [<code>Mcdev</code>](#Mcdev) -**Returns**: <code>Promise.<void></code> - - - -| Param | Type | Description | -| --- | --- | --- | -| businessUnit | <code>String</code> | references credentials from properties.json | -| type | <code>String</code> | metadata type | - -<a name="Mcdev.deleteByKey"></a> - -### Mcdev.deleteByKey(businessUnit, type, customerKey) ⇒ <code>Promise.<void></code> -Creates docs for supported metadata types in Markdown and/or HTML format - -**Kind**: static method of [<code>Mcdev</code>](#Mcdev) -**Returns**: <code>Promise.<void></code> - - - -| Param | Type | Description | -| --- | --- | --- | -| businessUnit | <code>String</code> | references credentials from properties.json | -| type | <code>String</code> | supported metadata type | -| customerKey | <code>String</code> | Identifier of data extension | - -<a name="Mcdev.badKeys"></a> - -### Mcdev.badKeys(businessUnit) ⇒ <code>Promise.<void></code> -Converts metadata to legacy format. Output is saved in 'converted' directory - -**Kind**: static method of [<code>Mcdev</code>](#Mcdev) -**Returns**: <code>Promise.<void></code> - - - -| Param | Type | Description | -| --- | --- | --- | -| businessUnit | <code>String</code> | references credentials from properties.json | - -<a name="Mcdev.retrieveAsTemplate"></a> - -### Mcdev.retrieveAsTemplate(businessUnit, selectedType, name, market) ⇒ <code>Promise.<void></code> -Retrieve a specific metadata file and templatise. - -**Kind**: static method of [<code>Mcdev</code>](#Mcdev) -**Returns**: <code>Promise.<void></code> - - - -| Param | Type | Description | -| --- | --- | --- | -| businessUnit | <code>String</code> | references credentials from properties.json | -| selectedType | <code>String</code> | supported metadata type | -| name | <code>String</code> | name of the metadata | -| market | <code>String</code> | market which should be used to revert template | - -<a name="Mcdev.buildDefinition"></a> - -### Mcdev.buildDefinition(businessUnit, type, name, market) ⇒ <code>Promise.<void></code> -Build a specific metadata file based on a template. - -**Kind**: static method of [<code>Mcdev</code>](#Mcdev) -**Returns**: <code>Promise.<void></code> - - - -| Param | Type | Description | -| --- | --- | --- | -| businessUnit | <code>String</code> | references credentials from properties.json | -| type | <code>String</code> | supported metadata type | -| name | <code>String</code> | name of the metadata | -| market | <code>String</code> | market localizations | - -<a name="Mcdev._checkMarket"></a> - -### Mcdev.\_checkMarket(market) ⇒ <code>Boolean</code> -check if a market name exists in current mcdev config - -**Kind**: static method of [<code>Mcdev</code>](#Mcdev) -**Returns**: <code>Boolean</code> - found market or not - -| Param | Type | Description | -| --- | --- | --- | -| market | <code>String</code> | market localizations | - -<a name="Mcdev.buildDefinitionBulk"></a> - -### Mcdev.buildDefinitionBulk(listName, type, name) ⇒ <code>Promise.<void></code> -Build a specific metadata file based on a template using a list of bu-market combos - -**Kind**: static method of [<code>Mcdev</code>](#Mcdev) -**Returns**: <code>Promise.<void></code> - - - -| Param | Type | Description | -| --- | --- | --- | -| listName | <code>String</code> | name of list of BU-market combos | -| type | <code>String</code> | supported metadata type | -| name | <code>String</code> | name of the metadata | - -<a name="AccountUser"></a> - -## AccountUser ⇐ [<code>MetadataType</code>](#MetadataType) -MessageSendActivity MetadataType - -**Kind**: global class -**Extends**: [<code>MetadataType</code>](#MetadataType) - -* [AccountUser](#AccountUser) ⇐ [<code>MetadataType</code>](#MetadataType) - * [.retrieve(retrieveDir, _, buObject)](#AccountUser.retrieve) ⇒ <code>Promise.<Object></code> - * [.timeSinceDate(date, date2)](#AccountUser.timeSinceDate) ⇒ <code>number</code> - * [.getBuName(buObject, id)](#AccountUser.getBuName) ⇒ <code>string</code> - * [.document(buObject, [metadata])](#AccountUser.document) ⇒ <code>Promise.<void></code> - * [._generateDocMd(users, type, columnsToPrint, buObject)](#AccountUser._generateDocMd) ⇒ <code>string</code> - * [.postRetrieveTasks(metadata)](#AccountUser.postRetrieveTasks) ⇒ <code>Array.<Object></code> - * [.parseMetadata(metadata)](#AccountUser.parseMetadata) ⇒ <code>Array</code> - -<a name="AccountUser.retrieve"></a> - -### AccountUser.retrieve(retrieveDir, _, buObject) ⇒ <code>Promise.<Object></code> -Retrieves SOAP based metadata of metadata type into local filesystem. executes callback with retrieved metadata - -**Kind**: static method of [<code>AccountUser</code>](#AccountUser) -**Returns**: <code>Promise.<Object></code> - Promise of metadata - -| Param | Type | Description | -| --- | --- | --- | -| retrieveDir | <code>String</code> | Directory where retrieved metadata directory will be saved | -| _ | <code>Array.<String></code> | Returns specified fields even if their retrieve definition is not set to true | -| buObject | <code>Object</code> | properties for auth | - -<a name="AccountUser.timeSinceDate"></a> - -### AccountUser.timeSinceDate(date, date2) ⇒ <code>number</code> -**Kind**: static method of [<code>AccountUser</code>](#AccountUser) -**Returns**: <code>number</code> - time difference - -| Param | Type | Description | -| --- | --- | --- | -| date | <code>string</code> | first date | -| date2 | <code>string</code> | second date | - -<a name="AccountUser.getBuName"></a> - -### AccountUser.getBuName(buObject, id) ⇒ <code>string</code> -helper to print bu names - -**Kind**: static method of [<code>AccountUser</code>](#AccountUser) -**Returns**: <code>string</code> - "bu name (bu id)"" - -| Param | Type | Description | -| --- | --- | --- | -| buObject | <code>Util.BuObject</code> | needed for eid | -| buObject.eid | <code>string</code> | needed to check for parent bu | -| id | <code>numeric</code> | bu id | - -<a name="AccountUser.document"></a> - -### AccountUser.document(buObject, [metadata]) ⇒ <code>Promise.<void></code> -Creates markdown documentation of all roles - -**Kind**: static method of [<code>AccountUser</code>](#AccountUser) -**Returns**: <code>Promise.<void></code> - - - -| Param | Type | Description | -| --- | --- | --- | -| buObject | <code>Util.BuObject</code> | properties for auth | -| [metadata] | <code>Object</code> | user list | - -<a name="AccountUser._generateDocMd"></a> - -### AccountUser.\_generateDocMd(users, type, columnsToPrint, buObject) ⇒ <code>string</code> -**Kind**: static method of [<code>AccountUser</code>](#AccountUser) -**Returns**: <code>string</code> - markdown - -| Param | Type | Description | -| --- | --- | --- | -| users | <code>Array.<Object></code> | list of users and installed package | -| type | <code>'Installed Package'</code> \| <code>'User'</code> | choose what sub type to print | -| columnsToPrint | <code>Array.<Array></code> | helper array | -| buObject | <code>Object</code> | properties for auth | - -<a name="AccountUser.postRetrieveTasks"></a> - -### AccountUser.postRetrieveTasks(metadata) ⇒ <code>Array.<Object></code> -manages post retrieve steps - -**Kind**: static method of [<code>AccountUser</code>](#AccountUser) -**Returns**: <code>Array.<Object></code> - Array with one metadata object and one query string - -| Param | Type | Description | -| --- | --- | --- | -| metadata | <code>Object</code> | a single query | - -<a name="AccountUser.parseMetadata"></a> - -### AccountUser.parseMetadata(metadata) ⇒ <code>Array</code> -parses retrieved Metadata before saving - -**Kind**: static method of [<code>AccountUser</code>](#AccountUser) -**Returns**: <code>Array</code> - Array with one metadata object and one sql string - -| Param | Type | Description | -| --- | --- | --- | -| metadata | <code>Object</code> | a single query activity definition | - -<a name="Asset"></a> - -## Asset ⇐ [<code>MetadataType</code>](#MetadataType) -FileTransfer MetadataType - -**Kind**: global class -**Extends**: [<code>MetadataType</code>](#MetadataType) - -* [Asset](#Asset) ⇐ [<code>MetadataType</code>](#MetadataType) - * [.retrieve(retrieveDir, _, __, [selectedSubType])](#Asset.retrieve) ⇒ <code>Promise.<{metadata:AssetMap, type:string}></code> - * [.retrieveForCache(_, [selectedSubType])](#Asset.retrieveForCache) ⇒ <code>Promise.<{metadata:AssetMap, type:string}></code> - * [.retrieveAsTemplate(templateDir, name, templateVariables, [selectedSubType])](#Asset.retrieveAsTemplate) ⇒ <code>Promise.<{metadata:AssetMap, type:string}></code> - * [.create(metadata)](#Asset.create) ⇒ <code>Promise</code> - * [.update(metadata)](#Asset.update) ⇒ <code>Promise</code> - * [.requestSubType(subType, subTypeArray, [retrieveDir], [templateName], [templateVariables])](#Asset.requestSubType) ⇒ <code>Promise</code> - * [.requestAndSaveExtended(items, subType, retrieveDir, [templateVariables])](#Asset.requestAndSaveExtended) ⇒ <code>Promise</code> - * [._retrieveExtendedFile(metadata, subType, retrieveDir)](#Asset._retrieveExtendedFile) ⇒ <code>Promise.<void></code> - * [._readExtendedFileFromFS(metadata, subType, deployDir)](#Asset._readExtendedFileFromFS) ⇒ <code>Promise.<void></code> - * [.postRetrieveTasks(metadata, [_], isTemplating)](#Asset.postRetrieveTasks) ⇒ [<code>CodeExtractItem</code>](#CodeExtractItem) - * [.preDeployTasks(metadata, deployDir)](#Asset.preDeployTasks) ⇒ <code>Promise.<AssetItem></code> - * [.getSubtype(metadata)](#Asset.getSubtype) ⇒ <code>AssetSubType</code> - * [.buildDefinitionForExtracts(templateDir, targetDir, metadata, variables, templateName)](#Asset.buildDefinitionForExtracts) ⇒ <code>Promise.<void></code> - * [.parseMetadata(metadata)](#Asset.parseMetadata) ⇒ [<code>CodeExtractItem</code>](#CodeExtractItem) - * [._mergeCode(metadata, deployDir, subType, [templateName])](#Asset._mergeCode) ⇒ <code>Promise.<Array.<MetadataType.CodeExtract>></code> - * [._mergeCode_slots(metadataSlots, readDirArr, subtypeExtension, subDirArr, fileList, customerKey, [templateName])](#Asset._mergeCode_slots) ⇒ <code>Promise.<void></code> - * [._extractCode(metadata)](#Asset._extractCode) ⇒ [<code>CodeExtractItem</code>](#CodeExtractItem) - * [._extractCode_slots(metadataSlots, codeArr)](#Asset._extractCode_slots) ⇒ <code>void</code> - * [.getJsonFromFS(dir)](#Asset.getJsonFromFS) ⇒ <code>Object</code> - * [.findSubType(templateDir, templateName)](#Asset.findSubType) ⇒ <code>AssetSubType</code> - * [.readSecondaryFolder(templateDir, typeDirArr, templateName, fileName)](#Asset.readSecondaryFolder) ⇒ <code>AssetItem</code> - -<a name="Asset.retrieve"></a> - -### Asset.retrieve(retrieveDir, _, __, [selectedSubType]) ⇒ <code>Promise.<{metadata:AssetMap, type:string}></code> -Retrieves Metadata of Asset - -**Kind**: static method of [<code>Asset</code>](#Asset) -**Returns**: <code>Promise.<{metadata:AssetMap, type:string}></code> - Promise - -| Param | Type | Description | -| --- | --- | --- | -| retrieveDir | <code>string</code> | Directory where retrieved metadata directory will be saved | -| _ | <code>void</code> | - | -| __ | <code>void</code> | - | -| [selectedSubType] | <code>AssetSubType</code> | optionally limit to a single subtype | - -<a name="Asset.retrieveForCache"></a> - -### Asset.retrieveForCache(_, [selectedSubType]) ⇒ <code>Promise.<{metadata:AssetMap, type:string}></code> -Retrieves asset metadata for caching - -**Kind**: static method of [<code>Asset</code>](#Asset) -**Returns**: <code>Promise.<{metadata:AssetMap, type:string}></code> - Promise - -| Param | Type | Description | -| --- | --- | --- | -| _ | <code>void</code> | - | -| [selectedSubType] | <code>string</code> | optionally limit to a single subtype | - -<a name="Asset.retrieveAsTemplate"></a> - -### Asset.retrieveAsTemplate(templateDir, name, templateVariables, [selectedSubType]) ⇒ <code>Promise.<{metadata:AssetMap, type:string}></code> -Retrieves asset metadata for caching - -**Kind**: static method of [<code>Asset</code>](#Asset) -**Returns**: <code>Promise.<{metadata:AssetMap, type:string}></code> - Promise - -| Param | Type | Description | -| --- | --- | --- | -| templateDir | <code>string</code> | Directory where retrieved metadata directory will be saved | -| name | <code>string</code> | name of the metadata file | -| templateVariables | <code>Util.TemplateMap</code> | variables to be replaced in the metadata | -| [selectedSubType] | <code>AssetSubType</code> | optionally limit to a single subtype | - -<a name="Asset.create"></a> - -### Asset.create(metadata) ⇒ <code>Promise</code> -Creates a single asset - -**Kind**: static method of [<code>Asset</code>](#Asset) -**Returns**: <code>Promise</code> - Promise - -| Param | Type | Description | -| --- | --- | --- | -| metadata | <code>AssetItem</code> | a single asset | - -<a name="Asset.update"></a> - -### Asset.update(metadata) ⇒ <code>Promise</code> -Updates a single asset - -**Kind**: static method of [<code>Asset</code>](#Asset) -**Returns**: <code>Promise</code> - Promise - -| Param | Type | Description | -| --- | --- | --- | -| metadata | <code>AssetItem</code> | a single asset | - -<a name="Asset.requestSubType"></a> - -### Asset.requestSubType(subType, subTypeArray, [retrieveDir], [templateName], [templateVariables]) ⇒ <code>Promise</code> -Retrieves Metadata of a specific asset type - -**Kind**: static method of [<code>Asset</code>](#Asset) -**Returns**: <code>Promise</code> - Promise - -| Param | Type | Description | -| --- | --- | --- | -| subType | <code>AssetSubType</code> | group of similar assets to put in a folder (ie. images) | -| subTypeArray | <code>Array.<AssetSubType></code> | list of all asset types within this subtype | -| [retrieveDir] | <code>string</code> | target directory for saving assets | -| [templateName] | <code>string</code> | name of the metadata file | -| [templateVariables] | <code>Util.TemplateMap</code> | variables to be replaced in the metadata | - -<a name="Asset.requestAndSaveExtended"></a> - -### Asset.requestAndSaveExtended(items, subType, retrieveDir, [templateVariables]) ⇒ <code>Promise</code> -Retrieves extended metadata (files or extended content) of asset - -**Kind**: static method of [<code>Asset</code>](#Asset) -**Returns**: <code>Promise</code> - Promise - -| Param | Type | Description | -| --- | --- | --- | -| items | <code>Array</code> | array of items to retrieve | -| subType | <code>AssetSubType</code> | group of similar assets to put in a folder (ie. images) | -| retrieveDir | <code>string</code> | target directory for saving assets | -| [templateVariables] | <code>Util.TemplateMap</code> | variables to be replaced in the metadata | - -<a name="Asset._retrieveExtendedFile"></a> - -### Asset.\_retrieveExtendedFile(metadata, subType, retrieveDir) ⇒ <code>Promise.<void></code> -Some metadata types store their actual content as a separate file, e.g. images -This method retrieves these and saves them alongside the metadata json - -**Kind**: static method of [<code>Asset</code>](#Asset) -**Returns**: <code>Promise.<void></code> - - - -| Param | Type | Description | -| --- | --- | --- | -| metadata | <code>AssetItem</code> | a single asset | -| subType | <code>AssetSubType</code> | group of similar assets to put in a folder (ie. images) | -| retrieveDir | <code>string</code> | target directory for saving assets | - -<a name="Asset._readExtendedFileFromFS"></a> - -### Asset.\_readExtendedFileFromFS(metadata, subType, deployDir) ⇒ <code>Promise.<void></code> -helper for this.preDeployTasks() -Some metadata types store their actual content as a separate file, e.g. images -This method reads these from the local FS stores them in the metadata object allowing to deploy it - -**Kind**: static method of [<code>Asset</code>](#Asset) -**Returns**: <code>Promise.<void></code> - - - -| Param | Type | Description | -| --- | --- | --- | -| metadata | <code>AssetItem</code> | a single asset | -| subType | <code>AssetSubType</code> | group of similar assets to put in a folder (ie. images) | -| deployDir | <code>string</code> | directory of deploy files | - -<a name="Asset.postRetrieveTasks"></a> - -### Asset.postRetrieveTasks(metadata, [_], isTemplating) ⇒ [<code>CodeExtractItem</code>](#CodeExtractItem) -manages post retrieve steps - -**Kind**: static method of [<code>Asset</code>](#Asset) -**Returns**: [<code>CodeExtractItem</code>](#CodeExtractItem) - metadata - -| Param | Type | Description | -| --- | --- | --- | -| metadata | <code>AssetItem</code> | a single asset | -| [_] | <code>string</code> | unused | -| isTemplating | <code>Boolean</code> | signals that we are retrieving templates | - -<a name="Asset.preDeployTasks"></a> - -### Asset.preDeployTasks(metadata, deployDir) ⇒ <code>Promise.<AssetItem></code> -prepares an asset definition for deployment - -**Kind**: static method of [<code>Asset</code>](#Asset) -**Returns**: <code>Promise.<AssetItem></code> - Promise - -| Param | Type | Description | -| --- | --- | --- | -| metadata | <code>AssetItem</code> | a single asset | -| deployDir | <code>string</code> | directory of deploy files | - -<a name="Asset.getSubtype"></a> - -### Asset.getSubtype(metadata) ⇒ <code>AssetSubType</code> -determines the subtype of the current asset - -**Kind**: static method of [<code>Asset</code>](#Asset) -**Returns**: <code>AssetSubType</code> - subtype - -| Param | Type | Description | -| --- | --- | --- | -| metadata | <code>AssetItem</code> | a single asset | - -<a name="Asset.buildDefinitionForExtracts"></a> - -### Asset.buildDefinitionForExtracts(templateDir, targetDir, metadata, variables, templateName) ⇒ <code>Promise.<void></code> -helper for buildDefinition -handles extracted code if any are found for complex types - -**Kind**: static method of [<code>Asset</code>](#Asset) -**Returns**: <code>Promise.<void></code> - Promise - -| Param | Type | Description | -| --- | --- | --- | -| templateDir | <code>string</code> | Directory where metadata templates are stored | -| targetDir | <code>string</code> | Directory where built definitions will be saved | -| metadata | <code>AssetItem</code> | main JSON file that was read from file system | -| variables | <code>Util.TemplateMap</code> | variables to be replaced in the metadata | -| templateName | <code>string</code> | name of the template to be built | - -<a name="Asset.parseMetadata"></a> - -### Asset.parseMetadata(metadata) ⇒ [<code>CodeExtractItem</code>](#CodeExtractItem) -parses retrieved Metadata before saving - -**Kind**: static method of [<code>Asset</code>](#Asset) -**Returns**: [<code>CodeExtractItem</code>](#CodeExtractItem) - parsed metadata definition - -| Param | Type | Description | -| --- | --- | --- | -| metadata | <code>AssetItem</code> | a single asset definition | - -<a name="Asset._mergeCode"></a> - -### Asset.\_mergeCode(metadata, deployDir, subType, [templateName]) ⇒ <code>Promise.<Array.<MetadataType.CodeExtract>></code> -helper for this.preDeployTasks() that loads extracted code content back into JSON - -**Kind**: static method of [<code>Asset</code>](#Asset) -**Returns**: <code>Promise.<Array.<MetadataType.CodeExtract>></code> - fileList for templating (disregarded during deployment) - -| Param | Type | Description | -| --- | --- | --- | -| metadata | <code>AssetItem</code> | a single asset definition | -| deployDir | <code>string</code> | directory of deploy files | -| subType | <code>AssetSubType</code> | asset-subtype name | -| [templateName] | <code>string</code> | name of the template used to built defintion (prior applying templating) | - -<a name="Asset._mergeCode_slots"></a> - -### Asset.\_mergeCode\_slots(metadataSlots, readDirArr, subtypeExtension, subDirArr, fileList, customerKey, [templateName]) ⇒ <code>Promise.<void></code> -helper for this.preDeployTasks() that loads extracted code content back into JSON - -**Kind**: static method of [<code>Asset</code>](#Asset) -**Returns**: <code>Promise.<void></code> - - - -| Param | Type | Description | -| --- | --- | --- | -| metadataSlots | <code>Object</code> | metadata.views.html.slots or deeper slots.<>.blocks.<>.slots | -| readDirArr | <code>Array.<string></code> | directory of deploy files | -| subtypeExtension | <code>string</code> | asset-subtype name ending on -meta | -| subDirArr | <code>Array.<string></code> | directory of files w/o leading deploy dir | -| fileList | <code>Array.<Object></code> | directory of files w/o leading deploy dir | -| customerKey | <code>string</code> | external key of template (could have been changed if used during templating) | -| [templateName] | <code>string</code> | name of the template used to built defintion (prior applying templating) | - -<a name="Asset._extractCode"></a> - -### Asset.\_extractCode(metadata) ⇒ [<code>CodeExtractItem</code>](#CodeExtractItem) -helper for this.parseMetadata() that finds code content in JSON and extracts it -to allow saving that separately and formatted - -**Kind**: static method of [<code>Asset</code>](#Asset) -**Returns**: [<code>CodeExtractItem</code>](#CodeExtractItem) - { json: metadata, codeArr: object[], subFolder: string[] } - -| Param | Type | Description | -| --- | --- | --- | -| metadata | <code>AssetItem</code> | a single asset definition | - -<a name="Asset._extractCode_slots"></a> - -### Asset.\_extractCode\_slots(metadataSlots, codeArr) ⇒ <code>void</code> -**Kind**: static method of [<code>Asset</code>](#Asset) - -| Param | Type | Description | -| --- | --- | --- | -| metadataSlots | <code>Object</code> | metadata.views.html.slots or deeper slots.<>.blocks.<>.slots | -| codeArr | <code>Array.<Object></code> | to be extended array for extracted code | - -<a name="Asset.getJsonFromFS"></a> - -### Asset.getJsonFromFS(dir) ⇒ <code>Object</code> -Returns file contents mapped to their fileName without '.json' ending - -**Kind**: static method of [<code>Asset</code>](#Asset) -**Returns**: <code>Object</code> - fileName => fileContent map - -| Param | Type | Description | -| --- | --- | --- | -| dir | <code>string</code> | directory that contains '.json' files to be read | - -<a name="Asset.findSubType"></a> - -### Asset.findSubType(templateDir, templateName) ⇒ <code>AssetSubType</code> -check template directory for complex types that open subfolders for their subtypes - -**Kind**: static method of [<code>Asset</code>](#Asset) -**Returns**: <code>AssetSubType</code> - subtype name - -| Param | Type | Description | -| --- | --- | --- | -| templateDir | <code>string</code> | Directory where metadata templates are stored | -| templateName | <code>string</code> | name of the metadata file | - -<a name="Asset.readSecondaryFolder"></a> - -### Asset.readSecondaryFolder(templateDir, typeDirArr, templateName, fileName) ⇒ <code>AssetItem</code> -optional method used for some types to try a different folder structure - -**Kind**: static method of [<code>Asset</code>](#Asset) -**Returns**: <code>AssetItem</code> - metadata - -| Param | Type | Description | -| --- | --- | --- | -| templateDir | <code>string</code> | Directory where metadata templates are stored | -| typeDirArr | <code>Array.<string></code> | current subdir for this type | -| templateName | <code>string</code> | name of the metadata template | -| fileName | <code>string</code> | name of the metadata template file w/o extension | - -<a name="AttributeGroup"></a> - -## AttributeGroup ⇐ [<code>MetadataType</code>](#MetadataType) -AttributeGroup MetadataType - -**Kind**: global class -**Extends**: [<code>MetadataType</code>](#MetadataType) - -* [AttributeGroup](#AttributeGroup) ⇐ [<code>MetadataType</code>](#MetadataType) - * [.retrieveForCache()](#AttributeGroup.retrieveForCache) ⇒ <code>Promise.<Object></code> - * [.retrieve(retrieveDir)](#AttributeGroup.retrieve) ⇒ <code>Promise.<Object></code> - -<a name="AttributeGroup.retrieveForCache"></a> - -### AttributeGroup.retrieveForCache() ⇒ <code>Promise.<Object></code> -Retrieves Metadata of schema attribute groups for caching. - -**Kind**: static method of [<code>AttributeGroup</code>](#AttributeGroup) -**Returns**: <code>Promise.<Object></code> - Promise of metadata -<a name="AttributeGroup.retrieve"></a> - -### AttributeGroup.retrieve(retrieveDir) ⇒ <code>Promise.<Object></code> -Retrieves Metadata of schema attribute groups. - -**Kind**: static method of [<code>AttributeGroup</code>](#AttributeGroup) -**Returns**: <code>Promise.<Object></code> - Promise of metadata - -| Param | Type | Description | -| --- | --- | --- | -| retrieveDir | <code>String</code> | Directory where retrieved metadata directory will be saved | - -<a name="Automation"></a> - -## Automation ⇐ [<code>MetadataType</code>](#MetadataType) -Automation MetadataType - -**Kind**: global class -**Extends**: [<code>MetadataType</code>](#MetadataType) - -* [Automation](#Automation) ⇐ [<code>MetadataType</code>](#MetadataType) - * [.client](#Automation.client) : <code>Util.ET\_Client</code> - * [.retrieve(retrieveDir)](#Automation.retrieve) ⇒ <code>Promise.<{metadata:AutomationMap, type:string}></code> - * [.retrieveChangelog()](#Automation.retrieveChangelog) ⇒ <code>Promise.<{metadata:AutomationMap, type:string}></code> - * [.retrieveForCache()](#Automation.retrieveForCache) ⇒ <code>Promise.<{metadata:AutomationMap, type:string}></code> - * [.retrieveAsTemplate(templateDir, name, templateVariables)](#Automation.retrieveAsTemplate) ⇒ <code>Promise.<{metadata:AutomationMap, type:string}></code> - * [.postRetrieveTasks(metadata, [_], [isTemplating])](#Automation.postRetrieveTasks) ⇒ <code>AutomationItem</code> - * [.deploy(metadata, targetBU, retrieveDir)](#Automation.deploy) ⇒ [<code>Promise.<AutomationMap></code>](#AutomationMap) - * [.create(metadata)](#Automation.create) ⇒ <code>Promise</code> - * [.update(metadata, metadataBefore)](#Automation.update) ⇒ <code>Promise</code> - * [.preDeployTasks(metadata)](#Automation.preDeployTasks) ⇒ <code>Promise.<AutomationItem></code> - * [.validateDeployMetadata(metadata)](#Automation.validateDeployMetadata) ⇒ <code>Boolean</code> - * [.postDeployTasks(metadata, originalMetadata)](#Automation.postDeployTasks) ⇒ <code>Promise.<void></code> - * [.parseMetadata(metadata)](#Automation.parseMetadata) ⇒ <code>Array</code> - * [._buildSchedule(scheduleObject)](#Automation._buildSchedule) ⇒ <code>AutomationScheduleSoap</code> - * [._calcTime(offsetServer, dateInput, [offsetInput])](#Automation._calcTime) ⇒ <code>string</code> - -<a name="Automation.client"></a> - -### Automation.client : <code>Util.ET\_Client</code> -**Kind**: static property of [<code>Automation</code>](#Automation) -<a name="Automation.retrieve"></a> - -### Automation.retrieve(retrieveDir) ⇒ <code>Promise.<{metadata:AutomationMap, type:string}></code> -Retrieves Metadata of Automation - -**Kind**: static method of [<code>Automation</code>](#Automation) -**Returns**: <code>Promise.<{metadata:AutomationMap, type:string}></code> - Promise of metadata - -| Param | Type | Description | -| --- | --- | --- | -| retrieveDir | <code>string</code> | Directory where retrieved metadata directory will be saved | - -<a name="Automation.retrieveChangelog"></a> - -### Automation.retrieveChangelog() ⇒ <code>Promise.<{metadata:AutomationMap, type:string}></code> -Retrieves Metadata of Automation - -**Kind**: static method of [<code>Automation</code>](#Automation) -**Returns**: <code>Promise.<{metadata:AutomationMap, type:string}></code> - Promise of metadata -<a name="Automation.retrieveForCache"></a> - -### Automation.retrieveForCache() ⇒ <code>Promise.<{metadata:AutomationMap, type:string}></code> -Retrieves automation metadata for caching - -**Kind**: static method of [<code>Automation</code>](#Automation) -**Returns**: <code>Promise.<{metadata:AutomationMap, type:string}></code> - Promise of metadata -<a name="Automation.retrieveAsTemplate"></a> - -### Automation.retrieveAsTemplate(templateDir, name, templateVariables) ⇒ <code>Promise.<{metadata:AutomationMap, type:string}></code> -Retrieve a specific Automation Definition by Name - -**Kind**: static method of [<code>Automation</code>](#Automation) -**Returns**: <code>Promise.<{metadata:AutomationMap, type:string}></code> - Promise of metadata - -| Param | Type | Description | -| --- | --- | --- | -| templateDir | <code>string</code> | Directory where retrieved metadata directory will be saved | -| name | <code>string</code> | name of the metadata file | -| templateVariables | <code>Util.TemplateMap</code> | variables to be replaced in the metadata | - -<a name="Automation.postRetrieveTasks"></a> - -### Automation.postRetrieveTasks(metadata, [_], [isTemplating]) ⇒ <code>AutomationItem</code> -manages post retrieve steps - -**Kind**: static method of [<code>Automation</code>](#Automation) -**Returns**: <code>AutomationItem</code> - metadata - -| Param | Type | Description | -| --- | --- | --- | -| metadata | <code>AutomationItem</code> | a single automation | -| [_] | <code>string</code> | unused | -| [isTemplating] | <code>Boolean</code> | signals that we are retrieving templates | - -<a name="Automation.deploy"></a> - -### Automation.deploy(metadata, targetBU, retrieveDir) ⇒ [<code>Promise.<AutomationMap></code>](#AutomationMap) -Deploys automation - the saved file is the original one due to large differences required for deployment - -**Kind**: static method of [<code>Automation</code>](#Automation) -**Returns**: [<code>Promise.<AutomationMap></code>](#AutomationMap) - Promise - -| Param | Type | Description | -| --- | --- | --- | -| metadata | [<code>AutomationMap</code>](#AutomationMap) | metadata mapped by their keyField | -| targetBU | <code>string</code> | name/shorthand of target businessUnit for mapping | -| retrieveDir | <code>string</code> | directory where metadata after deploy should be saved | - -<a name="Automation.create"></a> - -### Automation.create(metadata) ⇒ <code>Promise</code> -Creates a single automation - -**Kind**: static method of [<code>Automation</code>](#Automation) -**Returns**: <code>Promise</code> - Promise - -| Param | Type | Description | -| --- | --- | --- | -| metadata | <code>AutomationItem</code> | single metadata entry | - -<a name="Automation.update"></a> - -### Automation.update(metadata, metadataBefore) ⇒ <code>Promise</code> -Updates a single automation - -**Kind**: static method of [<code>Automation</code>](#Automation) -**Returns**: <code>Promise</code> - Promise - -| Param | Type | Description | -| --- | --- | --- | -| metadata | <code>AutomationItem</code> | single metadata entry | -| metadataBefore | <code>AutomationItem</code> | metadata mapped by their keyField | - -<a name="Automation.preDeployTasks"></a> - -### Automation.preDeployTasks(metadata) ⇒ <code>Promise.<AutomationItem></code> -Gets executed before deploying metadata - -**Kind**: static method of [<code>Automation</code>](#Automation) -**Returns**: <code>Promise.<AutomationItem></code> - Promise - -| Param | Type | Description | -| --- | --- | --- | -| metadata | <code>AutomationItem</code> | metadata mapped by their keyField | - -<a name="Automation.validateDeployMetadata"></a> - -### Automation.validateDeployMetadata(metadata) ⇒ <code>Boolean</code> -Validates the automation to be sure it can be deployed. -Whitelisted Activites are deployed but require configuration - -**Kind**: static method of [<code>Automation</code>](#Automation) -**Returns**: <code>Boolean</code> - result if automation can be deployed based on steps - -| Param | Type | Description | -| --- | --- | --- | -| metadata | <code>AutomationItem</code> | single automation record | - -<a name="Automation.postDeployTasks"></a> - -### Automation.postDeployTasks(metadata, originalMetadata) ⇒ <code>Promise.<void></code> -Gets executed after deployment of metadata type - -**Kind**: static method of [<code>Automation</code>](#Automation) -**Returns**: <code>Promise.<void></code> - - - -| Param | Type | Description | -| --- | --- | --- | -| metadata | [<code>AutomationMap</code>](#AutomationMap) | metadata mapped by their keyField | -| originalMetadata | [<code>AutomationMap</code>](#AutomationMap) | metadata to be updated (contains additioanl fields) | - -<a name="Automation.parseMetadata"></a> - -### Automation.parseMetadata(metadata) ⇒ <code>Array</code> -parses retrieved Metadata before saving - -**Kind**: static method of [<code>Automation</code>](#Automation) -**Returns**: <code>Array</code> - Array with one metadata object and one sql string - -| Param | Type | Description | -| --- | --- | --- | -| metadata | <code>AutomationItem</code> | a single automation definition | - -<a name="Automation._buildSchedule"></a> - -### Automation.\_buildSchedule(scheduleObject) ⇒ <code>AutomationScheduleSoap</code> -Builds a schedule object to be used for scheduling an automation -based on combination of ical string and start/end dates. - -**Kind**: static method of [<code>Automation</code>](#Automation) -**Returns**: <code>AutomationScheduleSoap</code> - Schedulable object for soap API (currently not rest supported) - -| Param | Type | Description | -| --- | --- | --- | -| scheduleObject | <code>AutomationSchedule</code> | child of automation metadata used for scheduling | - -<a name="Automation._calcTime"></a> - -### Automation.\_calcTime(offsetServer, dateInput, [offsetInput]) ⇒ <code>string</code> -used to convert dates to the system timezone required for startDate - -**Kind**: static method of [<code>Automation</code>](#Automation) -**Returns**: <code>string</code> - date in server - -| Param | Type | Description | -| --- | --- | --- | -| offsetServer | <code>number</code> | stack4: US Mountain time (UTC-7); other stacks: US Central (UTC-6) | -| dateInput | <code>string</code> \| <code>Date</code> | date in ISO format (2021-12-05T20:00:00.983) | -| [offsetInput] | <code>string</code> | timzone difference (+02:00) | - -<a name="Campaign"></a> - -## Campaign ⇐ [<code>MetadataType</code>](#MetadataType) -Campaign MetadataType - -**Kind**: global class -**Extends**: [<code>MetadataType</code>](#MetadataType) - -* [Campaign](#Campaign) ⇐ [<code>MetadataType</code>](#MetadataType) - * [.retrieve(retrieveDir)](#Campaign.retrieve) ⇒ <code>Promise</code> - * [._retrieveCampaignAsset(retrieveDir, id, name)](#Campaign._retrieveCampaignAsset) ⇒ <code>Promise</code> - * [._parseAssetResponseBody(body)](#Campaign._parseAssetResponseBody) ⇒ <code>Object</code> - -<a name="Campaign.retrieve"></a> - -### Campaign.retrieve(retrieveDir) ⇒ <code>Promise</code> -Retrieves Metadata of campaigns. Afterwards, starts metadata retrieval for their campaign assets - -**Kind**: static method of [<code>Campaign</code>](#Campaign) -**Returns**: <code>Promise</code> - Promise - -| Param | Type | Description | -| --- | --- | --- | -| retrieveDir | <code>String</code> | Directory where retrieved metadata directory will be saved | - -<a name="Campaign._retrieveCampaignAsset"></a> - -### Campaign.\_retrieveCampaignAsset(retrieveDir, id, name) ⇒ <code>Promise</code> -Retrieves campaign asset for a specific campaign - -**Kind**: static method of [<code>Campaign</code>](#Campaign) -**Returns**: <code>Promise</code> - Promise - -| Param | Type | Description | -| --- | --- | --- | -| retrieveDir | <code>String</code> | Directory where retrieved metadata directory will be saved | -| id | <code>Number</code> | id of the parent campaign | -| name | <code>String</code> | name of the parent campaign | - -<a name="Campaign._parseAssetResponseBody"></a> - -### Campaign.\_parseAssetResponseBody(body) ⇒ <code>Object</code> -Parses campaign asset response body and returns metadata entries mapped to their id - -**Kind**: static method of [<code>Campaign</code>](#Campaign) -**Returns**: <code>Object</code> - keyField => metadata map - -| Param | Type | Description | -| --- | --- | --- | -| body | <code>Object</code> | response body of metadata retrieval | - -<a name="ContentArea"></a> - -## ContentArea ⇐ [<code>MetadataType</code>](#MetadataType) -ContentArea MetadataType - -**Kind**: global class -**Extends**: [<code>MetadataType</code>](#MetadataType) - -* [ContentArea](#ContentArea) ⇐ [<code>MetadataType</code>](#MetadataType) - * [.retrieve(retrieveDir)](#ContentArea.retrieve) ⇒ <code>Promise.<Object></code> - * [.postRetrieveTasks(metadata)](#ContentArea.postRetrieveTasks) ⇒ <code>Array.<Object></code> - * [.parseMetadata(metadata)](#ContentArea.parseMetadata) ⇒ <code>Array</code> - -<a name="ContentArea.retrieve"></a> - -### ContentArea.retrieve(retrieveDir) ⇒ <code>Promise.<Object></code> -Retrieves SOAP based metadata of metadata type into local filesystem. executes callback with retrieved metadata - -**Kind**: static method of [<code>ContentArea</code>](#ContentArea) -**Returns**: <code>Promise.<Object></code> - Promise of metadata - -| Param | Type | Description | -| --- | --- | --- | -| retrieveDir | <code>String</code> | Directory where retrieved metadata directory will be saved | - -<a name="ContentArea.postRetrieveTasks"></a> - -### ContentArea.postRetrieveTasks(metadata) ⇒ <code>Array.<Object></code> -manages post retrieve steps - -**Kind**: static method of [<code>ContentArea</code>](#ContentArea) -**Returns**: <code>Array.<Object></code> - Array with one metadata object and one query string - -| Param | Type | Description | -| --- | --- | --- | -| metadata | <code>Object</code> | a single query | - -<a name="ContentArea.parseMetadata"></a> - -### ContentArea.parseMetadata(metadata) ⇒ <code>Array</code> -parses retrieved Metadata before saving - -**Kind**: static method of [<code>ContentArea</code>](#ContentArea) -**Returns**: <code>Array</code> - Array with one metadata object and one sql string - -| Param | Type | Description | -| --- | --- | --- | -| metadata | <code>Object</code> | a single query activity definition | - -<a name="DataExtension"></a> - -## DataExtension ⇐ [<code>MetadataType</code>](#MetadataType) -DataExtension MetadataType - -**Kind**: global class -**Extends**: [<code>MetadataType</code>](#MetadataType) - -* [DataExtension](#DataExtension) ⇐ [<code>MetadataType</code>](#MetadataType) - * [.client](#DataExtension.client) : <code>Util.ET\_Client</code> - * [.upsert(desToDeploy, _, buObject)](#DataExtension.upsert) ⇒ <code>Promise</code> - * [._filterUpsertResults(res)](#DataExtension._filterUpsertResults) ⇒ <code>Boolean</code> - * [.create(metadata)](#DataExtension.create) ⇒ <code>Promise</code> - * [.update(metadata)](#DataExtension.update) ⇒ <code>Promise</code> - * [.postDeployTasks(upsertedMetadata)](#DataExtension.postDeployTasks) ⇒ <code>void</code> - * [.retrieve(retrieveDir, [additionalFields], buObject, [_], [isDeploy])](#DataExtension.retrieve) ⇒ <code>Promise.<{metadata:DataExtensionMap, type:string}></code> - * [.retrieveChangelog([additionalFields])](#DataExtension.retrieveChangelog) ⇒ <code>Promise.<{metadata:DataExtensionMap, type:string}></code> - * [.postRetrieveTasks(metadata, [_], [isTemplating])](#DataExtension.postRetrieveTasks) ⇒ <code>DataExtensionItem</code> - * [.preDeployTasks(metadata)](#DataExtension.preDeployTasks) ⇒ <code>Promise.<DataExtensionItem></code> - * [.document(buObject, [metadata], [isDeploy])](#DataExtension.document) ⇒ <code>Promise.<void></code> - * [.deleteByKey(buObject, customerKey)](#DataExtension.deleteByKey) ⇒ <code>Promise.<void></code> - * [.retrieveForCache(buObject, [_], [isDeploy])](#DataExtension.retrieveForCache) ⇒ <code>Promise</code> - * [.retrieveAsTemplate(templateDir, name, templateVariables)](#DataExtension.retrieveAsTemplate) ⇒ <code>Promise.<{metadata:DataExtensionMap, type:string}></code> - -<a name="DataExtension.client"></a> - -### DataExtension.client : <code>Util.ET\_Client</code> -**Kind**: static property of [<code>DataExtension</code>](#DataExtension) -<a name="DataExtension.upsert"></a> - -### DataExtension.upsert(desToDeploy, _, buObject) ⇒ <code>Promise</code> -Upserts dataExtensions after retrieving them from source and target to compare -if create or update operation is needed. - -**Kind**: static method of [<code>DataExtension</code>](#DataExtension) -**Returns**: <code>Promise</code> - Promise - -| Param | Type | Description | -| --- | --- | --- | -| desToDeploy | [<code>DataExtensionMap</code>](#DataExtensionMap) | dataExtensions mapped by their customerKey | -| _ | <code>Object</code> | - | -| buObject | <code>Util.BuObject</code> | properties for auth | - -<a name="DataExtension._filterUpsertResults"></a> - -### DataExtension.\_filterUpsertResults(res) ⇒ <code>Boolean</code> -helper for upsert() - -**Kind**: static method of [<code>DataExtension</code>](#DataExtension) -**Returns**: <code>Boolean</code> - true: keep, false: discard - -| Param | Type | Description | -| --- | --- | --- | -| res | <code>Object</code> | - | - -<a name="DataExtension.create"></a> - -### DataExtension.create(metadata) ⇒ <code>Promise</code> -Create a single dataExtension. Also creates their columns in 'dataExtension.columns' - -**Kind**: static method of [<code>DataExtension</code>](#DataExtension) -**Returns**: <code>Promise</code> - Promise - -| Param | Type | Description | -| --- | --- | --- | -| metadata | <code>DataExtensionItem</code> | single metadata entry | - -<a name="DataExtension.update"></a> - -### DataExtension.update(metadata) ⇒ <code>Promise</code> -Updates a single dataExtension. Also updates their columns in 'dataExtension.columns' - -**Kind**: static method of [<code>DataExtension</code>](#DataExtension) -**Returns**: <code>Promise</code> - Promise - -| Param | Type | Description | -| --- | --- | --- | -| metadata | <code>DataExtensionItem</code> | single metadata entry | - -<a name="DataExtension.postDeployTasks"></a> - -### DataExtension.postDeployTasks(upsertedMetadata) ⇒ <code>void</code> -Gets executed after deployment of metadata type - -**Kind**: static method of [<code>DataExtension</code>](#DataExtension) - -| Param | Type | Description | -| --- | --- | --- | -| upsertedMetadata | [<code>DataExtensionMap</code>](#DataExtensionMap) | metadata mapped by their keyField | - -<a name="DataExtension.retrieve"></a> - -### DataExtension.retrieve(retrieveDir, [additionalFields], buObject, [_], [isDeploy]) ⇒ <code>Promise.<{metadata:DataExtensionMap, type:string}></code> -Retrieves dataExtension metadata. Afterwards starts retrieval of dataExtensionColumn metadata retrieval - -**Kind**: static method of [<code>DataExtension</code>](#DataExtension) -**Returns**: <code>Promise.<{metadata:DataExtensionMap, type:string}></code> - Promise of item map - -| Param | Type | Description | -| --- | --- | --- | -| retrieveDir | <code>string</code> | Directory where retrieved metadata directory will be saved | -| [additionalFields] | <code>Array.<string></code> | Returns specified fields even if their retrieve definition is not set to true | -| buObject | <code>Util.BuObject</code> | properties for auth | -| [_] | <code>void</code> | - | -| [isDeploy] | <code>boolean</code> | used to signal that fields shall be retrieve in caching mode | - -<a name="DataExtension.retrieveChangelog"></a> - -### DataExtension.retrieveChangelog([additionalFields]) ⇒ <code>Promise.<{metadata:DataExtensionMap, type:string}></code> -Retrieves dataExtension metadata. Afterwards starts retrieval of dataExtensionColumn metadata retrieval - -**Kind**: static method of [<code>DataExtension</code>](#DataExtension) -**Returns**: <code>Promise.<{metadata:DataExtensionMap, type:string}></code> - Promise of item map - -| Param | Type | Description | -| --- | --- | --- | -| [additionalFields] | <code>Array.<string></code> | Returns specified fields even if their retrieve definition is not set to true | - -<a name="DataExtension.postRetrieveTasks"></a> - -### DataExtension.postRetrieveTasks(metadata, [_], [isTemplating]) ⇒ <code>DataExtensionItem</code> -manages post retrieve steps - -**Kind**: static method of [<code>DataExtension</code>](#DataExtension) -**Returns**: <code>DataExtensionItem</code> - metadata - -| Param | Type | Description | -| --- | --- | --- | -| metadata | <code>DataExtensionItem</code> | a single dataExtension | -| [_] | <code>string</code> | unused | -| [isTemplating] | <code>boolean</code> | signals that we are retrieving templates | - -<a name="DataExtension.preDeployTasks"></a> - -### DataExtension.preDeployTasks(metadata) ⇒ <code>Promise.<DataExtensionItem></code> -prepares a DataExtension for deployment - -**Kind**: static method of [<code>DataExtension</code>](#DataExtension) -**Returns**: <code>Promise.<DataExtensionItem></code> - Promise of updated single DE - -| Param | Type | Description | -| --- | --- | --- | -| metadata | <code>DataExtensionItem</code> | a single data Extension | - -<a name="DataExtension.document"></a> - -### DataExtension.document(buObject, [metadata], [isDeploy]) ⇒ <code>Promise.<void></code> -Parses metadata into a readable Markdown/HTML format then saves it - -**Kind**: static method of [<code>DataExtension</code>](#DataExtension) -**Returns**: <code>Promise.<void></code> - - - -| Param | Type | Description | -| --- | --- | --- | -| buObject | <code>Util.BuObject</code> | properties for auth | -| [metadata] | [<code>DataExtensionMap</code>](#DataExtensionMap) | a list of dataExtension definitions | -| [isDeploy] | <code>boolean</code> | used to skip non-supported message during deploy | - -<a name="DataExtension.deleteByKey"></a> - -### DataExtension.deleteByKey(buObject, customerKey) ⇒ <code>Promise.<void></code> -Delete a data extension from the specified business unit - -**Kind**: static method of [<code>DataExtension</code>](#DataExtension) -**Returns**: <code>Promise.<void></code> - - - -| Param | Type | Description | -| --- | --- | --- | -| buObject | <code>Object</code> | references credentials | -| customerKey | <code>string</code> | Identifier of data extension | - -<a name="DataExtension.retrieveForCache"></a> - -### DataExtension.retrieveForCache(buObject, [_], [isDeploy]) ⇒ <code>Promise</code> -Retrieves folder metadata into local filesystem. Also creates a uniquePath attribute for each folder. - -**Kind**: static method of [<code>DataExtension</code>](#DataExtension) -**Returns**: <code>Promise</code> - Promise - -| Param | Type | Description | -| --- | --- | --- | -| buObject | <code>Object</code> | properties for auth | -| [_] | <code>void</code> | - | -| [isDeploy] | <code>boolean</code> | used to signal that fields shall be retrieve in caching mode | - -<a name="DataExtension.retrieveAsTemplate"></a> - -### DataExtension.retrieveAsTemplate(templateDir, name, templateVariables) ⇒ <code>Promise.<{metadata:DataExtensionMap, type:string}></code> -Retrieves dataExtension metadata in template format. - -**Kind**: static method of [<code>DataExtension</code>](#DataExtension) -**Returns**: <code>Promise.<{metadata:DataExtensionMap, type:string}></code> - Promise of items - -| Param | Type | Description | -| --- | --- | --- | -| templateDir | <code>string</code> | Directory where retrieved metadata directory will be saved | -| name | <code>string</code> | name of the metadata item | -| templateVariables | <code>Util.TemplateMap</code> | variables to be replaced in the metadata | - -<a name="DataExtensionField"></a> - -## DataExtensionField ⇐ [<code>MetadataType</code>](#MetadataType) -DataExtensionField MetadataType - -**Kind**: global class -**Extends**: [<code>MetadataType</code>](#MetadataType) - -* [DataExtensionField](#DataExtensionField) ⇐ [<code>MetadataType</code>](#MetadataType) - * [.retrieve(retrieveDir, [additionalFields], buObject)](#DataExtensionField.retrieve) ⇒ <code>Promise.<{metadata:DataExtensionFieldMap, type:string}></code> - * [.retrieveForCache([options], [additionalFields])](#DataExtensionField.retrieveForCache) ⇒ <code>Promise.<{metadata:DataExtensionFieldMap, type:string}></code> - * [.convertToSortedArray(fieldsObj)](#DataExtensionField.convertToSortedArray) ⇒ <code>Array.<DataExtensionFieldItem></code> - * [.sortDeFields(a, b)](#DataExtensionField.sortDeFields) ⇒ <code>boolean</code> - * [.postRetrieveTasks(metadata, forDataExtension)](#DataExtensionField.postRetrieveTasks) ⇒ <code>DataExtensionFieldItem</code> - * [.prepareDeployColumnsOnUpdate(deployColumns, deKey)](#DataExtensionField.prepareDeployColumnsOnUpdate) ⇒ <code>Object.<string, DataExtensionFieldItem></code> - -<a name="DataExtensionField.retrieve"></a> - -### DataExtensionField.retrieve(retrieveDir, [additionalFields], buObject) ⇒ <code>Promise.<{metadata:DataExtensionFieldMap, type:string}></code> -Retrieves all records and saves it to disk - -**Kind**: static method of [<code>DataExtensionField</code>](#DataExtensionField) -**Returns**: <code>Promise.<{metadata:DataExtensionFieldMap, type:string}></code> - Promise of items - -| Param | Type | Description | -| --- | --- | --- | -| retrieveDir | <code>string</code> | Directory where retrieved metadata directory will be saved | -| [additionalFields] | <code>Array.<string></code> | Returns specified fields even if their retrieve definition is not set to true | -| buObject | <code>Object</code> | properties for auth | - -<a name="DataExtensionField.retrieveForCache"></a> - -### DataExtensionField.retrieveForCache([options], [additionalFields]) ⇒ <code>Promise.<{metadata:DataExtensionFieldMap, type:string}></code> -Retrieves all records for caching - -**Kind**: static method of [<code>DataExtensionField</code>](#DataExtensionField) -**Returns**: <code>Promise.<{metadata:DataExtensionFieldMap, type:string}></code> - Promise of items - -| Param | Type | Description | -| --- | --- | --- | -| [options] | <code>Object</code> | required for the specific request (filter for example) | -| [additionalFields] | <code>Array.<string></code> | Returns specified fields even if their retrieve definition is not set to true | - -<a name="DataExtensionField.convertToSortedArray"></a> - -### DataExtensionField.convertToSortedArray(fieldsObj) ⇒ <code>Array.<DataExtensionFieldItem></code> -helper for DataExtension.js that sorts the fields into an array - -**Kind**: static method of [<code>DataExtensionField</code>](#DataExtensionField) -**Returns**: <code>Array.<DataExtensionFieldItem></code> - sorted array of field objects - -| Param | Type | Description | -| --- | --- | --- | -| fieldsObj | [<code>DataExtensionFieldMap</code>](#DataExtensionFieldMap) | customerKey-based list of fields for one dataExtension | - -<a name="DataExtensionField.sortDeFields"></a> - -### DataExtensionField.sortDeFields(a, b) ⇒ <code>boolean</code> -sorting method to ensure `Ordinal` is respected - -**Kind**: static method of [<code>DataExtensionField</code>](#DataExtensionField) -**Returns**: <code>boolean</code> - sorting based on Ordinal - -| Param | Type | Description | -| --- | --- | --- | -| a | <code>DataExtensionFieldItem</code> | - | -| b | <code>DataExtensionFieldItem</code> | - | - -<a name="DataExtensionField.postRetrieveTasks"></a> - -### DataExtensionField.postRetrieveTasks(metadata, forDataExtension) ⇒ <code>DataExtensionFieldItem</code> -manages post retrieve steps - -**Kind**: static method of [<code>DataExtensionField</code>](#DataExtensionField) -**Returns**: <code>DataExtensionFieldItem</code> - metadata - -| Param | Type | Description | -| --- | --- | --- | -| metadata | <code>DataExtensionFieldItem</code> | a single item | -| forDataExtension | <code>boolean</code> | when used by DataExtension class we remove more fields | - -<a name="DataExtensionField.prepareDeployColumnsOnUpdate"></a> - -### DataExtensionField.prepareDeployColumnsOnUpdate(deployColumns, deKey) ⇒ <code>Object.<string, DataExtensionFieldItem></code> -Mofifies passed deployColumns for update by mapping ObjectID to their target column's values. -Removes FieldType field if its the same in deploy and target column, because it results in an error even if its of the same type - -**Kind**: static method of [<code>DataExtensionField</code>](#DataExtensionField) -**Returns**: <code>Object.<string, DataExtensionFieldItem></code> - existing fields by their original name to allow re-adding FieldType after update - -| Param | Type | Description | -| --- | --- | --- | -| deployColumns | <code>Array.<DataExtensionFieldItem></code> | Columns of data extension that will be deployed | -| deKey | <code>string</code> | external/customer key of Data Extension | - -<a name="DataExtensionTemplate"></a> - -## DataExtensionTemplate ⇐ [<code>MetadataType</code>](#MetadataType) -DataExtensionTemplate MetadataType - -**Kind**: global class -**Extends**: [<code>MetadataType</code>](#MetadataType) -<a name="DataExtensionTemplate.retrieve"></a> - -### DataExtensionTemplate.retrieve(retrieveDir) ⇒ <code>Promise.<Object></code> -Retrieves SOAP based metadata of metadata type into local filesystem. executes callback with retrieved metadata - -**Kind**: static method of [<code>DataExtensionTemplate</code>](#DataExtensionTemplate) -**Returns**: <code>Promise.<Object></code> - Promise of metadata - -| Param | Type | Description | -| --- | --- | --- | -| retrieveDir | <code>String</code> | Directory where retrieved metadata directory will be saved | - -<a name="DataExtract"></a> - -## DataExtract ⇐ [<code>MetadataType</code>](#MetadataType) -DataExtract MetadataType - -**Kind**: global class -**Extends**: [<code>MetadataType</code>](#MetadataType) - -* [DataExtract](#DataExtract) ⇐ [<code>MetadataType</code>](#MetadataType) - * [.retrieve(retrieveDir)](#DataExtract.retrieve) ⇒ <code>Promise.<Object></code> - * [.retrieveForCache()](#DataExtract.retrieveForCache) ⇒ <code>Promise.<Object></code> - * [.retrieveAsTemplate(templateDir, name, templateVariables)](#DataExtract.retrieveAsTemplate) ⇒ <code>Promise.<Object></code> - * [.postRetrieveTasks(fileTransfer)](#DataExtract.postRetrieveTasks) ⇒ <code>Array.<Object></code> - * [.create(dataExtract)](#DataExtract.create) ⇒ <code>Promise</code> - * [.update(dataExtract)](#DataExtract.update) ⇒ <code>Promise</code> - * [.preDeployTasks(metadata)](#DataExtract.preDeployTasks) ⇒ <code>Object</code> - * [.parseMetadata(metadata)](#DataExtract.parseMetadata) ⇒ <code>Array</code> - -<a name="DataExtract.retrieve"></a> - -### DataExtract.retrieve(retrieveDir) ⇒ <code>Promise.<Object></code> -Retrieves Metadata of Data Extract Activity. -Endpoint /automation/v1/dataextracts/ returns all Data Extracts - -**Kind**: static method of [<code>DataExtract</code>](#DataExtract) -**Returns**: <code>Promise.<Object></code> - Promise of metadata - -| Param | Type | Description | -| --- | --- | --- | -| retrieveDir | <code>String</code> | Directory where retrieved metadata directory will be saved | - -<a name="DataExtract.retrieveForCache"></a> - -### DataExtract.retrieveForCache() ⇒ <code>Promise.<Object></code> -Retrieves Metadata of Data Extract Activity for caching - -**Kind**: static method of [<code>DataExtract</code>](#DataExtract) -**Returns**: <code>Promise.<Object></code> - Promise of metadata -<a name="DataExtract.retrieveAsTemplate"></a> - -### DataExtract.retrieveAsTemplate(templateDir, name, templateVariables) ⇒ <code>Promise.<Object></code> -Retrieve a specific dataExtract Definition by Name - -**Kind**: static method of [<code>DataExtract</code>](#DataExtract) -**Returns**: <code>Promise.<Object></code> - Promise of metadata - -| Param | Type | Description | -| --- | --- | --- | -| templateDir | <code>String</code> | Directory where retrieved metadata directory will be saved | -| name | <code>String</code> | name of the metadata file | -| templateVariables | <code>Object</code> | variables to be replaced in the metadata | - -<a name="DataExtract.postRetrieveTasks"></a> - -### DataExtract.postRetrieveTasks(fileTransfer) ⇒ <code>Array.<Object></code> -manages post retrieve steps - -**Kind**: static method of [<code>DataExtract</code>](#DataExtract) -**Returns**: <code>Array.<Object></code> - metadata - -| Param | Type | Description | -| --- | --- | --- | -| fileTransfer | <code>Object</code> | a single fileTransfer | - -<a name="DataExtract.create"></a> - -### DataExtract.create(dataExtract) ⇒ <code>Promise</code> -Creates a single Data Extract - -**Kind**: static method of [<code>DataExtract</code>](#DataExtract) -**Returns**: <code>Promise</code> - Promise - -| Param | Type | Description | -| --- | --- | --- | -| dataExtract | <code>Object</code> | a single Data Extract | - -<a name="DataExtract.update"></a> - -### DataExtract.update(dataExtract) ⇒ <code>Promise</code> -Updates a single Data Extract - -**Kind**: static method of [<code>DataExtract</code>](#DataExtract) -**Returns**: <code>Promise</code> - Promise - -| Param | Type | Description | -| --- | --- | --- | -| dataExtract | <code>Object</code> | a single Data Extract | - -<a name="DataExtract.preDeployTasks"></a> - -### DataExtract.preDeployTasks(metadata) ⇒ <code>Object</code> -prepares a dataExtract for deployment - -**Kind**: static method of [<code>DataExtract</code>](#DataExtract) -**Returns**: <code>Object</code> - metadata object - -| Param | Type | Description | -| --- | --- | --- | -| metadata | <code>Object</code> | a single dataExtract activity definition | - -<a name="DataExtract.parseMetadata"></a> - -### DataExtract.parseMetadata(metadata) ⇒ <code>Array</code> -parses retrieved Metadata before saving - -**Kind**: static method of [<code>DataExtract</code>](#DataExtract) -**Returns**: <code>Array</code> - Array with one metadata object and one sql string - -| Param | Type | Description | -| --- | --- | --- | -| metadata | <code>Object</code> | a single dataExtract activity definition | - -<a name="DataExtractType"></a> - -## DataExtractType ⇐ [<code>MetadataType</code>](#MetadataType) -DataExtractType MetadataType -Only for Caching No retrieve/upsert is required -as this is a configuration in the EID - -**Kind**: global class -**Extends**: [<code>MetadataType</code>](#MetadataType) - -* [DataExtractType](#DataExtractType) ⇐ [<code>MetadataType</code>](#MetadataType) - * [.retrieve(retrieveDir)](#DataExtractType.retrieve) ⇒ <code>Promise.<Object></code> - * [.retrieveForCache()](#DataExtractType.retrieveForCache) ⇒ <code>Promise.<Object></code> - -<a name="DataExtractType.retrieve"></a> - -### DataExtractType.retrieve(retrieveDir) ⇒ <code>Promise.<Object></code> -Retrieves Metadata of Data Extract Type. - -**Kind**: static method of [<code>DataExtractType</code>](#DataExtractType) -**Returns**: <code>Promise.<Object></code> - Promise of metadata - -| Param | Type | Description | -| --- | --- | --- | -| retrieveDir | <code>String</code> | Directory where retrieved metadata directory will be saved | - -<a name="DataExtractType.retrieveForCache"></a> - -### DataExtractType.retrieveForCache() ⇒ <code>Promise.<Object></code> -Retrieves Metadata of Data Extract Type for caching. - -**Kind**: static method of [<code>DataExtractType</code>](#DataExtractType) -**Returns**: <code>Promise.<Object></code> - Promise of metadata -<a name="Discovery"></a> - -## Discovery ⇐ [<code>MetadataType</code>](#MetadataType) -ImportFile MetadataType - -**Kind**: global class -**Extends**: [<code>MetadataType</code>](#MetadataType) -<a name="Discovery.retrieve"></a> - -### Discovery.retrieve(retrieveDir, [_], buObject) ⇒ <code>Promise</code> -Retrieves API endpoint -documentation: https://developer.salesforce.com/docs/atlas.en-us.noversion.mc-apis.meta/mc-apis/routes.htm - -**Kind**: static method of [<code>Discovery</code>](#Discovery) -**Returns**: <code>Promise</code> - Promise - -| Param | Type | Description | -| --- | --- | --- | -| retrieveDir | <code>String</code> | Directory where retrieved metadata directory will be saved | -| [_] | <code>Array.<String></code> | not used | -| buObject | <code>Object</code> | properties for auth | - -<a name="Email"></a> - -## Email ⇐ [<code>MetadataType</code>](#MetadataType) -Email MetadataType - -**Kind**: global class -**Extends**: [<code>MetadataType</code>](#MetadataType) - -* [Email](#Email) ⇐ [<code>MetadataType</code>](#MetadataType) - * [.retrieve(retrieveDir)](#Email.retrieve) ⇒ <code>Promise.<Object></code> - * [.postRetrieveTasks(metadata)](#Email.postRetrieveTasks) ⇒ <code>Array.<Object></code> - * [.parseMetadata(metadata)](#Email.parseMetadata) ⇒ <code>Array</code> - -<a name="Email.retrieve"></a> - -### Email.retrieve(retrieveDir) ⇒ <code>Promise.<Object></code> -Retrieves SOAP based metadata of metadata type into local filesystem. executes callback with retrieved metadata - -**Kind**: static method of [<code>Email</code>](#Email) -**Returns**: <code>Promise.<Object></code> - Promise of metadata - -| Param | Type | Description | -| --- | --- | --- | -| retrieveDir | <code>String</code> | Directory where retrieved metadata directory will be saved | - -<a name="Email.postRetrieveTasks"></a> - -### Email.postRetrieveTasks(metadata) ⇒ <code>Array.<Object></code> -manages post retrieve steps - -**Kind**: static method of [<code>Email</code>](#Email) -**Returns**: <code>Array.<Object></code> - Array with one metadata object and one query string - -| Param | Type | Description | -| --- | --- | --- | -| metadata | <code>Object</code> | a single query | - -<a name="Email.parseMetadata"></a> - -### Email.parseMetadata(metadata) ⇒ <code>Array</code> -parses retrieved Metadata before saving - -**Kind**: static method of [<code>Email</code>](#Email) -**Returns**: <code>Array</code> - Array with one metadata object and one sql string - -| Param | Type | Description | -| --- | --- | --- | -| metadata | <code>Object</code> | a single query activity definition | - -<a name="EmailSendDefinition"></a> - -## EmailSendDefinition ⇐ [<code>MetadataType</code>](#MetadataType) -MessageSendActivity MetadataType - -**Kind**: global class -**Extends**: [<code>MetadataType</code>](#MetadataType) - -* [EmailSendDefinition](#EmailSendDefinition) ⇐ [<code>MetadataType</code>](#MetadataType) - * [.retrieve(retrieveDir, _, buObject)](#EmailSendDefinition.retrieve) ⇒ <code>Promise.<Object></code> - * [.update(metadataItem)](#EmailSendDefinition.update) ⇒ <code>Promise</code> - * [.create(metadataItem)](#EmailSendDefinition.create) ⇒ <code>Promise</code> - * [.preDeployTasks(metadata)](#EmailSendDefinition.preDeployTasks) ⇒ <code>Promise</code> - * [.postRetrieveTasks(metadata)](#EmailSendDefinition.postRetrieveTasks) ⇒ <code>Array.<Object></code> - * [.parseMetadata(metadata)](#EmailSendDefinition.parseMetadata) ⇒ <code>Array</code> - -<a name="EmailSendDefinition.retrieve"></a> - -### EmailSendDefinition.retrieve(retrieveDir, _, buObject) ⇒ <code>Promise.<Object></code> -Retrieves SOAP based metadata of metadata type into local filesystem. executes callback with retrieved metadata - -**Kind**: static method of [<code>EmailSendDefinition</code>](#EmailSendDefinition) -**Returns**: <code>Promise.<Object></code> - Promise of metadata - -| Param | Type | Description | -| --- | --- | --- | -| retrieveDir | <code>String</code> | Directory where retrieved metadata directory will be saved | -| _ | <code>void</code> | - | -| buObject | <code>Object</code> | properties for auth | - -<a name="EmailSendDefinition.update"></a> - -### EmailSendDefinition.update(metadataItem) ⇒ <code>Promise</code> -Updates a single item - -**Kind**: static method of [<code>EmailSendDefinition</code>](#EmailSendDefinition) -**Returns**: <code>Promise</code> - Promise - -| Param | Type | Description | -| --- | --- | --- | -| metadataItem | <code>Object</code> | a single item | - -<a name="EmailSendDefinition.create"></a> - -### EmailSendDefinition.create(metadataItem) ⇒ <code>Promise</code> -Creates a single item - -**Kind**: static method of [<code>EmailSendDefinition</code>](#EmailSendDefinition) -**Returns**: <code>Promise</code> - Promise - -| Param | Type | Description | -| --- | --- | --- | -| metadataItem | <code>Object</code> | a single item | - -<a name="EmailSendDefinition.preDeployTasks"></a> - -### EmailSendDefinition.preDeployTasks(metadata) ⇒ <code>Promise</code> -prepares a single item for deployment - -**Kind**: static method of [<code>EmailSendDefinition</code>](#EmailSendDefinition) -**Returns**: <code>Promise</code> - Promise - -| Param | Type | Description | -| --- | --- | --- | -| metadata | <code>Object</code> | a single script activity definition | - -<a name="EmailSendDefinition.postRetrieveTasks"></a> - -### EmailSendDefinition.postRetrieveTasks(metadata) ⇒ <code>Array.<Object></code> -manages post retrieve steps - -**Kind**: static method of [<code>EmailSendDefinition</code>](#EmailSendDefinition) -**Returns**: <code>Array.<Object></code> - Array with one metadata object and one query string - -| Param | Type | Description | -| --- | --- | --- | -| metadata | <code>Object</code> | a single query | - -<a name="EmailSendDefinition.parseMetadata"></a> - -### EmailSendDefinition.parseMetadata(metadata) ⇒ <code>Array</code> -parses retrieved Metadata before saving - -**Kind**: static method of [<code>EmailSendDefinition</code>](#EmailSendDefinition) -**Returns**: <code>Array</code> - Array with one metadata object and one sql string - -| Param | Type | Description | -| --- | --- | --- | -| metadata | <code>Object</code> | a single query activity definition | - -<a name="EventDefinition"></a> - -## EventDefinition ⇐ [<code>MetadataType</code>](#MetadataType) -EventDefinition MetadataType - -**Kind**: global class -**Extends**: [<code>MetadataType</code>](#MetadataType) - -* [EventDefinition](#EventDefinition) ⇐ [<code>MetadataType</code>](#MetadataType) - * [.retrieve(retrieveDir)](#EventDefinition.retrieve) ⇒ <code>Promise.<Object></code> - * [.retrieveForCache()](#EventDefinition.retrieveForCache) ⇒ <code>Promise.<Object></code> - * [.retrieveAsTemplate(templateDir, name, templateVariables)](#EventDefinition.retrieveAsTemplate) ⇒ <code>Promise.<Object></code> - * [.postRetrieveTasks(eventDef)](#EventDefinition.postRetrieveTasks) ⇒ <code>Array.<Object></code> - * [.create(EventDefinition)](#EventDefinition.create) ⇒ <code>Promise</code> - * [.update(EventDefinition)](#EventDefinition.update) ⇒ <code>Promise</code> - * [.preDeployTasks(metadata)](#EventDefinition.preDeployTasks) ⇒ <code>Promise</code> - * [.parseMetadata(metadata)](#EventDefinition.parseMetadata) ⇒ <code>Array</code> - -<a name="EventDefinition.retrieve"></a> - -### EventDefinition.retrieve(retrieveDir) ⇒ <code>Promise.<Object></code> -Retrieves Metadata of Event Definition. -Endpoint /interaction/v1/EventDefinitions return all Event Definitions with all details. -Currently it is not needed to loop over Imports with endpoint /interaction/v1/EventDefinitions/{id} - -**Kind**: static method of [<code>EventDefinition</code>](#EventDefinition) -**Returns**: <code>Promise.<Object></code> - Promise of metadata - -| Param | Type | Description | -| --- | --- | --- | -| retrieveDir | <code>String</code> | Directory where retrieved metadata directory will be saved | - -<a name="EventDefinition.retrieveForCache"></a> - -### EventDefinition.retrieveForCache() ⇒ <code>Promise.<Object></code> -Retrieves event definition metadata for caching - -**Kind**: static method of [<code>EventDefinition</code>](#EventDefinition) -**Returns**: <code>Promise.<Object></code> - Promise of metadata -<a name="EventDefinition.retrieveAsTemplate"></a> - -### EventDefinition.retrieveAsTemplate(templateDir, name, templateVariables) ⇒ <code>Promise.<Object></code> -Retrieve a specific Event Definition by Name - -**Kind**: static method of [<code>EventDefinition</code>](#EventDefinition) -**Returns**: <code>Promise.<Object></code> - Promise of metadata - -| Param | Type | Description | -| --- | --- | --- | -| templateDir | <code>String</code> | Directory where retrieved metadata directory will be saved | -| name | <code>String</code> | name of the metadata file | -| templateVariables | <code>Object</code> | variables to be replaced in the metadata | - -<a name="EventDefinition.postRetrieveTasks"></a> - -### EventDefinition.postRetrieveTasks(eventDef) ⇒ <code>Array.<Object></code> -manages post retrieve steps - -**Kind**: static method of [<code>EventDefinition</code>](#EventDefinition) -**Returns**: <code>Array.<Object></code> - metadata - -| Param | Type | Description | -| --- | --- | --- | -| eventDef | <code>Object</code> | a single importDef | - -<a name="EventDefinition.create"></a> - -### EventDefinition.create(EventDefinition) ⇒ <code>Promise</code> -Creates a single Event Definition - -**Kind**: static method of [<code>EventDefinition</code>](#EventDefinition) -**Returns**: <code>Promise</code> - Promise - -| Param | Type | Description | -| --- | --- | --- | -| EventDefinition | <code>Object</code> | a single Event Definition | - -<a name="EventDefinition.update"></a> - -### EventDefinition.update(EventDefinition) ⇒ <code>Promise</code> -Updates a single Event Definition (using PUT method since PATCH isn't supported) - -**Kind**: static method of [<code>EventDefinition</code>](#EventDefinition) -**Returns**: <code>Promise</code> - Promise - -| Param | Type | Description | -| --- | --- | --- | -| EventDefinition | <code>Object</code> | a single Event Definition | - -<a name="EventDefinition.preDeployTasks"></a> - -### EventDefinition.preDeployTasks(metadata) ⇒ <code>Promise</code> -prepares an event definition for deployment - -**Kind**: static method of [<code>EventDefinition</code>](#EventDefinition) -**Returns**: <code>Promise</code> - Promise - -| Param | Type | Description | -| --- | --- | --- | -| metadata | <code>Object</code> | a single eventDefinition | - -<a name="EventDefinition.parseMetadata"></a> - -### EventDefinition.parseMetadata(metadata) ⇒ <code>Array</code> -parses retrieved Metadata before saving - -**Kind**: static method of [<code>EventDefinition</code>](#EventDefinition) -**Returns**: <code>Array</code> - Array with one metadata object and one sql string - -| Param | Type | Description | -| --- | --- | --- | -| metadata | <code>Object</code> | a single event definition | - -<a name="FileTransfer"></a> - -## FileTransfer ⇐ [<code>MetadataType</code>](#MetadataType) -FileTransfer MetadataType - -**Kind**: global class -**Extends**: [<code>MetadataType</code>](#MetadataType) - -* [FileTransfer](#FileTransfer) ⇐ [<code>MetadataType</code>](#MetadataType) - * [.retrieve(retrieveDir)](#FileTransfer.retrieve) ⇒ <code>Promise</code> - * [.retrieveForCache()](#FileTransfer.retrieveForCache) ⇒ <code>Promise</code> - * [.retrieveAsTemplate(templateDir, name, templateVariables)](#FileTransfer.retrieveAsTemplate) ⇒ <code>Promise</code> - * [.postRetrieveTasks(metadata)](#FileTransfer.postRetrieveTasks) ⇒ <code>Array.<Object></code> - * [.create(fileTransfer)](#FileTransfer.create) ⇒ <code>Promise</code> - * [.update(fileTransfer)](#FileTransfer.update) ⇒ <code>Promise</code> - * [.preDeployTasks(metadata)](#FileTransfer.preDeployTasks) ⇒ <code>Promise</code> - * [.parseMetadata(metadata)](#FileTransfer.parseMetadata) ⇒ <code>Array</code> - -<a name="FileTransfer.retrieve"></a> - -### FileTransfer.retrieve(retrieveDir) ⇒ <code>Promise</code> -Retrieves Metadata of FileTransfer Activity. -Endpoint /automation/v1/filetransfers/ returns all File Transfers - -**Kind**: static method of [<code>FileTransfer</code>](#FileTransfer) -**Returns**: <code>Promise</code> - Promise - -| Param | Type | Description | -| --- | --- | --- | -| retrieveDir | <code>String</code> | Directory where retrieved metadata directory will be saved | - -<a name="FileTransfer.retrieveForCache"></a> - -### FileTransfer.retrieveForCache() ⇒ <code>Promise</code> -Retrieves Metadata of FileTransfer Activity for caching - -**Kind**: static method of [<code>FileTransfer</code>](#FileTransfer) -**Returns**: <code>Promise</code> - Promise -<a name="FileTransfer.retrieveAsTemplate"></a> - -### FileTransfer.retrieveAsTemplate(templateDir, name, templateVariables) ⇒ <code>Promise</code> -Retrieve a specific File Transfer Definition by Name - -**Kind**: static method of [<code>FileTransfer</code>](#FileTransfer) -**Returns**: <code>Promise</code> - Promise - -| Param | Type | Description | -| --- | --- | --- | -| templateDir | <code>String</code> | Directory where retrieved metadata directory will be saved | -| name | <code>String</code> | name of the metadata file | -| templateVariables | <code>Object</code> | variables to be replaced in the metadata | - -<a name="FileTransfer.postRetrieveTasks"></a> - -### FileTransfer.postRetrieveTasks(metadata) ⇒ <code>Array.<Object></code> -manages post retrieve steps - -**Kind**: static method of [<code>FileTransfer</code>](#FileTransfer) -**Returns**: <code>Array.<Object></code> - metadata - -| Param | Type | Description | -| --- | --- | --- | -| metadata | <code>Object</code> | a single fileTransfer activity definition | - -<a name="FileTransfer.create"></a> - -### FileTransfer.create(fileTransfer) ⇒ <code>Promise</code> -Creates a single File Transfer - -**Kind**: static method of [<code>FileTransfer</code>](#FileTransfer) -**Returns**: <code>Promise</code> - Promise - -| Param | Type | Description | -| --- | --- | --- | -| fileTransfer | <code>Object</code> | a single File Transfer | - -<a name="FileTransfer.update"></a> - -### FileTransfer.update(fileTransfer) ⇒ <code>Promise</code> -Updates a single File Transfer - -**Kind**: static method of [<code>FileTransfer</code>](#FileTransfer) -**Returns**: <code>Promise</code> - Promise - -| Param | Type | Description | -| --- | --- | --- | -| fileTransfer | <code>Object</code> | a single File Transfer | - -<a name="FileTransfer.preDeployTasks"></a> - -### FileTransfer.preDeployTasks(metadata) ⇒ <code>Promise</code> -prepares a fileTransfer for deployment - -**Kind**: static method of [<code>FileTransfer</code>](#FileTransfer) -**Returns**: <code>Promise</code> - Promise - -| Param | Type | Description | -| --- | --- | --- | -| metadata | <code>Object</code> | a single fileTransfer activity definition | - -<a name="FileTransfer.parseMetadata"></a> - -### FileTransfer.parseMetadata(metadata) ⇒ <code>Array</code> -parses retrieved Metadata before saving - -**Kind**: static method of [<code>FileTransfer</code>](#FileTransfer) -**Returns**: <code>Array</code> - Array with one metadata object and one sql string - -| Param | Type | Description | -| --- | --- | --- | -| metadata | <code>Object</code> | a single fileTransfer activity definition | - -<a name="Filter"></a> - -## Filter ⇐ [<code>MetadataType</code>](#MetadataType) -Filter MetadataType - -**Kind**: global class -**Extends**: [<code>MetadataType</code>](#MetadataType) -<a name="Filter.retrieve"></a> - -### Filter.retrieve(retrieveDir) ⇒ <code>Promise</code> -Retrieves Metadata of Filter. -Endpoint /automation/v1/filters/ returns all Filters, -but only with some of the fields. So it is needed to loop over -Filters with the endpoint /automation/v1/filters/{id} - -**Kind**: static method of [<code>Filter</code>](#Filter) -**Returns**: <code>Promise</code> - Promise - -| Param | Type | Description | -| --- | --- | --- | -| retrieveDir | <code>String</code> | Directory where retrieved metadata directory will be saved | - -<a name="Folder"></a> - -## Folder ⇐ [<code>MetadataType</code>](#MetadataType) -Folder MetadataType - -**Kind**: global class -**Extends**: [<code>MetadataType</code>](#MetadataType) - -* [Folder](#Folder) ⇐ [<code>MetadataType</code>](#MetadataType) - * [.retrieve(retrieveDir, [additionalFields], buObject)](#Folder.retrieve) ⇒ <code>Promise</code> - * [.retrieveForCache(buObject)](#Folder.retrieveForCache) ⇒ <code>Promise</code> - * [.upsert(metadata)](#Folder.upsert) ⇒ <code>Promise.<Object></code> - * [.create(metadata)](#Folder.create) ⇒ <code>Promise</code> - * [.update(metadata)](#Folder.update) ⇒ <code>Promise</code> - * [.preDeployTasks(metadata)](#Folder.preDeployTasks) ⇒ <code>Promise</code> - * [.getJsonFromFS(dir, [listBadKeys])](#Folder.getJsonFromFS) ⇒ <code>Object</code> - * [.retrieveHelper([additionalFields], [queryAllAccounts])](#Folder.retrieveHelper) ⇒ <code>Promise.<Object></code> - * [.postRetrieveTasks(metadata)](#Folder.postRetrieveTasks) ⇒ <code>Array.<Object></code> - * [.saveResults(results, retrieveDir, mid)](#Folder.saveResults) ⇒ <code>Promise.<Object></code> - -<a name="Folder.retrieve"></a> - -### Folder.retrieve(retrieveDir, [additionalFields], buObject) ⇒ <code>Promise</code> -Retrieves metadata of metadata type into local filesystem. executes callback with retrieved metadata - -**Kind**: static method of [<code>Folder</code>](#Folder) -**Returns**: <code>Promise</code> - Promise - -| Param | Type | Description | -| --- | --- | --- | -| retrieveDir | <code>String</code> | Directory where retrieved metadata directory will be saved | -| [additionalFields] | <code>Array.<String></code> | Returns specified fields even if their retrieve definition is not set to true | -| buObject | <code>Object</code> | properties for auth | - -<a name="Folder.retrieveForCache"></a> - -### Folder.retrieveForCache(buObject) ⇒ <code>Promise</code> -Retrieves folder metadata for caching - -**Kind**: static method of [<code>Folder</code>](#Folder) -**Returns**: <code>Promise</code> - Promise - -| Param | Type | Description | -| --- | --- | --- | -| buObject | <code>Object</code> | properties for auth | - -<a name="Folder.upsert"></a> - -### Folder.upsert(metadata) ⇒ <code>Promise.<Object></code> -Folder upsert (copied from Metadata Upsert), after retrieving from target -and comparing to check if create or update operation is needed. -Copied due to having a dependency on itself, meaning the created need to be serial - -**Kind**: static method of [<code>Folder</code>](#Folder) -**Returns**: <code>Promise.<Object></code> - Promise of saved metadata - -| Param | Type | Description | -| --- | --- | --- | -| metadata | <code>Object</code> | metadata mapped by their keyField | - -<a name="Folder.create"></a> - -### Folder.create(metadata) ⇒ <code>Promise</code> -creates a folder based on metatadata - -**Kind**: static method of [<code>Folder</code>](#Folder) -**Returns**: <code>Promise</code> - Promise - -| Param | Type | Description | -| --- | --- | --- | -| metadata | <code>Object</code> | metadata of the folder | - -<a name="Folder.update"></a> - -### Folder.update(metadata) ⇒ <code>Promise</code> -Updates a single Folder. - -**Kind**: static method of [<code>Folder</code>](#Folder) -**Returns**: <code>Promise</code> - Promise - -| Param | Type | Description | -| --- | --- | --- | -| metadata | <code>Object</code> | single metadata entry | - -<a name="Folder.preDeployTasks"></a> - -### Folder.preDeployTasks(metadata) ⇒ <code>Promise</code> -prepares a folder for deployment - -**Kind**: static method of [<code>Folder</code>](#Folder) -**Returns**: <code>Promise</code> - Promise - -| Param | Type | Description | -| --- | --- | --- | -| metadata | <code>Object</code> | a single folder definition | - -<a name="Folder.getJsonFromFS"></a> - -### Folder.getJsonFromFS(dir, [listBadKeys]) ⇒ <code>Object</code> -Returns file contents mapped to their filename without '.json' ending - -**Kind**: static method of [<code>Folder</code>](#Folder) -**Returns**: <code>Object</code> - fileName => fileContent map - -| Param | Type | Default | Description | -| --- | --- | --- | --- | -| dir | <code>String</code> | | directory that contains '.json' files to be read | -| [listBadKeys] | <code>boolean</code> | <code>false</code> | do not print errors, used for badKeys() | - -<a name="Folder.retrieveHelper"></a> - -### Folder.retrieveHelper([additionalFields], [queryAllAccounts]) ⇒ <code>Promise.<Object></code> -Helper to retrieve the folders as promise - -**Kind**: static method of [<code>Folder</code>](#Folder) -**Returns**: <code>Promise.<Object></code> - soap object - -| Param | Type | Description | -| --- | --- | --- | -| [additionalFields] | <code>Array.<String></code> | Returns specified fields even if their retrieve definition is not set to true | -| [queryAllAccounts] | <code>Boolean</code> | which queryAllAccounts setting to use | - -<a name="Folder.postRetrieveTasks"></a> - -### Folder.postRetrieveTasks(metadata) ⇒ <code>Array.<Object></code> -Gets executed after retreive of metadata type - -**Kind**: static method of [<code>Folder</code>](#Folder) -**Returns**: <code>Array.<Object></code> - cloned metadata - -| Param | Type | Description | -| --- | --- | --- | -| metadata | <code>Object</code> | metadata mapped by their keyField | - -<a name="Folder.saveResults"></a> - -### Folder.saveResults(results, retrieveDir, mid) ⇒ <code>Promise.<Object></code> -Helper for writing Metadata to disk, used for Retrieve and deploy - -**Kind**: static method of [<code>Folder</code>](#Folder) -**Returns**: <code>Promise.<Object></code> - Promise of saved metadata - -| Param | Type | Description | -| --- | --- | --- | -| results | <code>Object</code> | metadata results from deploy | -| retrieveDir | <code>String</code> | directory where metadata should be stored after deploy/retrieve | -| mid | <code>Number</code> | current mid for this credential / business unit | - -<a name="FtpLocation"></a> - -## FtpLocation ⇐ [<code>MetadataType</code>](#MetadataType) -ImportFile MetadataType - -**Kind**: global class -**Extends**: [<code>MetadataType</code>](#MetadataType) - -* [FtpLocation](#FtpLocation) ⇐ [<code>MetadataType</code>](#MetadataType) - * [.retrieve(retrieveDir)](#FtpLocation.retrieve) ⇒ <code>Promise</code> - * [.retrieveForCache()](#FtpLocation.retrieveForCache) ⇒ <code>Promise</code> - -<a name="FtpLocation.retrieve"></a> - -### FtpLocation.retrieve(retrieveDir) ⇒ <code>Promise</code> -Retrieves Metadata of FtpLocation -Endpoint /automation/v1/ftplocations/ return all FtpLocations - -**Kind**: static method of [<code>FtpLocation</code>](#FtpLocation) -**Returns**: <code>Promise</code> - Promise - -| Param | Type | Description | -| --- | --- | --- | -| retrieveDir | <code>String</code> | Directory where retrieved metadata directory will be saved | - -<a name="FtpLocation.retrieveForCache"></a> - -### FtpLocation.retrieveForCache() ⇒ <code>Promise</code> -Retrieves folder metadata into local filesystem. Also creates a uniquePath attribute for each folder. - -**Kind**: static method of [<code>FtpLocation</code>](#FtpLocation) -**Returns**: <code>Promise</code> - Promise -<a name="ImportFile"></a> - -## ImportFile ⇐ [<code>MetadataType</code>](#MetadataType) -ImportFile MetadataType - -**Kind**: global class -**Extends**: [<code>MetadataType</code>](#MetadataType) - -* [ImportFile](#ImportFile) ⇐ [<code>MetadataType</code>](#MetadataType) - * [.retrieve(retrieveDir)](#ImportFile.retrieve) ⇒ <code>Promise</code> - * [.retrieveForCache()](#ImportFile.retrieveForCache) ⇒ <code>Promise</code> - * [.retrieveAsTemplate(templateDir, name, templateVariables)](#ImportFile.retrieveAsTemplate) ⇒ <code>Promise</code> - * [.postRetrieveTasks(importDef)](#ImportFile.postRetrieveTasks) ⇒ <code>Array.<Object></code> - * [.create(importFile)](#ImportFile.create) ⇒ <code>Promise</code> - * [.update(importFile)](#ImportFile.update) ⇒ <code>Promise</code> - * [.preDeployTasks(metadata)](#ImportFile.preDeployTasks) ⇒ <code>Promise</code> - * [.parseMetadata(metadata)](#ImportFile.parseMetadata) ⇒ <code>Object</code> - -<a name="ImportFile.retrieve"></a> - -### ImportFile.retrieve(retrieveDir) ⇒ <code>Promise</code> -Retrieves Metadata of Import File. -Endpoint /automation/v1/imports/ return all Import Files with all details. -Currently it is not needed to loop over Imports with endpoint /automation/v1/imports/{id} - -**Kind**: static method of [<code>ImportFile</code>](#ImportFile) -**Returns**: <code>Promise</code> - Promise - -| Param | Type | Description | -| --- | --- | --- | -| retrieveDir | <code>String</code> | Directory where retrieved metadata directory will be saved | - -<a name="ImportFile.retrieveForCache"></a> - -### ImportFile.retrieveForCache() ⇒ <code>Promise</code> -Retrieves import definition metadata for caching - -**Kind**: static method of [<code>ImportFile</code>](#ImportFile) -**Returns**: <code>Promise</code> - Promise -<a name="ImportFile.retrieveAsTemplate"></a> - -### ImportFile.retrieveAsTemplate(templateDir, name, templateVariables) ⇒ <code>Promise</code> -Retrieve a specific Import Definition by Name - -**Kind**: static method of [<code>ImportFile</code>](#ImportFile) -**Returns**: <code>Promise</code> - Promise - -| Param | Type | Description | -| --- | --- | --- | -| templateDir | <code>String</code> | Directory where retrieved metadata directory will be saved | -| name | <code>String</code> | name of the metadata file | -| templateVariables | <code>Object</code> | variables to be replaced in the metadata | - -<a name="ImportFile.postRetrieveTasks"></a> - -### ImportFile.postRetrieveTasks(importDef) ⇒ <code>Array.<Object></code> -manages post retrieve steps - -**Kind**: static method of [<code>ImportFile</code>](#ImportFile) -**Returns**: <code>Array.<Object></code> - metadata - -| Param | Type | Description | -| --- | --- | --- | -| importDef | <code>Object</code> | a single importDef | - -<a name="ImportFile.create"></a> - -### ImportFile.create(importFile) ⇒ <code>Promise</code> -Creates a single Import File - -**Kind**: static method of [<code>ImportFile</code>](#ImportFile) -**Returns**: <code>Promise</code> - Promise - -| Param | Type | Description | -| --- | --- | --- | -| importFile | <code>Object</code> | a single Import File | - -<a name="ImportFile.update"></a> - -### ImportFile.update(importFile) ⇒ <code>Promise</code> -Updates a single Import File - -**Kind**: static method of [<code>ImportFile</code>](#ImportFile) -**Returns**: <code>Promise</code> - Promise - -| Param | Type | Description | -| --- | --- | --- | -| importFile | <code>Object</code> | a single Import File | - -<a name="ImportFile.preDeployTasks"></a> - -### ImportFile.preDeployTasks(metadata) ⇒ <code>Promise</code> -prepares a import definition for deployment - -**Kind**: static method of [<code>ImportFile</code>](#ImportFile) -**Returns**: <code>Promise</code> - Promise - -| Param | Type | Description | -| --- | --- | --- | -| metadata | <code>Object</code> | a single importDef | - -<a name="ImportFile.parseMetadata"></a> - -### ImportFile.parseMetadata(metadata) ⇒ <code>Object</code> -parses retrieved Metadata before saving - -**Kind**: static method of [<code>ImportFile</code>](#ImportFile) -**Returns**: <code>Object</code> - parsed metadata definition - -| Param | Type | Description | -| --- | --- | --- | -| metadata | <code>Object</code> | a single import definition | - -<a name="Interaction"></a> - -## Interaction ⇐ [<code>MetadataType</code>](#MetadataType) -Script MetadataType - -**Kind**: global class -**Extends**: [<code>MetadataType</code>](#MetadataType) -<a name="Interaction.retrieve"></a> - -### Interaction.retrieve(retrieveDir) ⇒ <code>Promise</code> -Retrieves Metadata of Interaction -Endpoint /interaction/v1/interactions?extras=all&pageSize=50000 return 50000 Scripts with all details. - -**Kind**: static method of [<code>Interaction</code>](#Interaction) -**Returns**: <code>Promise</code> - Promise - -| Param | Type | Description | -| --- | --- | --- | -| retrieveDir | <code>String</code> | Directory where retrieved metadata directory will be saved | - -<a name="List"></a> - -## List ⇐ [<code>MetadataType</code>](#MetadataType) -List MetadataType - -**Kind**: global class -**Extends**: [<code>MetadataType</code>](#MetadataType) - -* [List](#List) ⇐ [<code>MetadataType</code>](#MetadataType) - * [.retrieve(retrieveDir)](#List.retrieve) ⇒ <code>Promise</code> - * [.retrieveForCache()](#List.retrieveForCache) ⇒ <code>Promise.<Object></code> - * [.postRetrieveTasks(list)](#List.postRetrieveTasks) ⇒ <code>Array.<Object></code> - * [.parseMetadata(metadata, [parseForCache])](#List.parseMetadata) ⇒ <code>Array</code> - -<a name="List.retrieve"></a> - -### List.retrieve(retrieveDir) ⇒ <code>Promise</code> -Retrieves Metadata of Lists - -**Kind**: static method of [<code>List</code>](#List) -**Returns**: <code>Promise</code> - Promise - -| Param | Type | Description | -| --- | --- | --- | -| retrieveDir | <code>String</code> | Directory where retrieved metadata directory will be saved | - -<a name="List.retrieveForCache"></a> - -### List.retrieveForCache() ⇒ <code>Promise.<Object></code> -Gets metadata cache with limited fields and does not store value to disk - -**Kind**: static method of [<code>List</code>](#List) -**Returns**: <code>Promise.<Object></code> - Promise of metadata -<a name="List.postRetrieveTasks"></a> - -### List.postRetrieveTasks(list) ⇒ <code>Array.<Object></code> -manages post retrieve steps - -**Kind**: static method of [<code>List</code>](#List) -**Returns**: <code>Array.<Object></code> - metadata - -| Param | Type | Description | -| --- | --- | --- | -| list | <code>Object</code> | a single list | - -<a name="List.parseMetadata"></a> - -### List.parseMetadata(metadata, [parseForCache]) ⇒ <code>Array</code> -parses retrieved Metadata before saving - -**Kind**: static method of [<code>List</code>](#List) -**Returns**: <code>Array</code> - Array with one metadata object and one sql string - -| Param | Type | Description | -| --- | --- | --- | -| metadata | <code>Object</code> | a single list definition | -| [parseForCache] | <code>Boolean</code> | if set to true, the Category ID is kept | - -<a name="MetadataType"></a> - -## MetadataType -MetadataType class that gets extended by their specific metadata type class. -Provides default functionality that can be overwritten by child metadata type classes - -**Kind**: global class - -* [MetadataType](#MetadataType) - * [new MetadataType(client, businessUnit, cache, properties, [subType])](#new_MetadataType_new) - * [.client](#MetadataType.client) : <code>Util.ET\_Client</code> - * [.cache](#MetadataType.cache) : [<code>MultiMetadataTypeMap</code>](#MultiMetadataTypeMap) - * [.getJsonFromFS(dir, [listBadKeys])](#MetadataType.getJsonFromFS) ⇒ <code>Object</code> - * [.getFieldNamesToRetrieve([additionalFields])](#MetadataType.getFieldNamesToRetrieve) ⇒ <code>Array.<string></code> - * [.deploy(metadata, deployDir, retrieveDir, buObject)](#MetadataType.deploy) ⇒ <code>Promise.<Object></code> - * [.postDeployTasks(metadata, originalMetadata)](#MetadataType.postDeployTasks) ⇒ <code>void</code> - * [.postRetrieveTasks(metadata, targetDir, [isTemplating])](#MetadataType.postRetrieveTasks) ⇒ <code>MetadataTypeItem</code> - * [.overrideKeyWithName(metadata, [warningMsg])](#MetadataType.overrideKeyWithName) ⇒ <code>void</code> - * [.retrieve(retrieveDir, [additionalFields], buObject, [subType])](#MetadataType.retrieve) ⇒ <code>Promise.<{metadata:MetadataTypeMap, type:string}></code> - * [.retrieveChangelog([additionalFields], buObject, [subType])](#MetadataType.retrieveChangelog) ⇒ <code>Promise.<{metadata:MetadataTypeMap, type:string}></code> - * [.retrieveForCache(buObject, [subType])](#MetadataType.retrieveForCache) ⇒ <code>Promise.<{metadata:MetadataTypeMap, type:string}></code> - * [.retrieveAsTemplate(templateDir, name, templateVariables, [subType])](#MetadataType.retrieveAsTemplate) ⇒ <code>Promise.<{metadata:MetadataTypeMap, type:string}></code> - * [.preDeployTasks(metadata, deployDir)](#MetadataType.preDeployTasks) ⇒ <code>Promise.<MetadataTypeItem></code> - * [.create(metadata, deployDir)](#MetadataType.create) ⇒ <code>void</code> - * [.update(metadata, [metadataBefore])](#MetadataType.update) ⇒ <code>void</code> - * [.upsert(metadata, deployDir, [buObject])](#MetadataType.upsert) ⇒ <code>Promise.<MetadataTypeMap></code> - * [.createREST(metadataEntry, uri)](#MetadataType.createREST) ⇒ <code>Promise</code> - * [.createSOAP(metadataEntry, [overrideType], [handleOutside])](#MetadataType.createSOAP) ⇒ <code>Promise</code> - * [.updateREST(metadataEntry, uri)](#MetadataType.updateREST) ⇒ <code>Promise</code> - * [.updateSOAP(metadataEntry, [overrideType], [handleOutside])](#MetadataType.updateSOAP) ⇒ <code>Promise</code> - * [.retrieveSOAPgeneric(retrieveDir, buObject, [options], [additionalFields], [overrideType])](#MetadataType.retrieveSOAPgeneric) ⇒ <code>Promise.<{metadata:MetadataTypeMap, type:string}></code> - * [.retrieveSOAPBody(fields, [options], [type])](#MetadataType.retrieveSOAPBody) ⇒ <code>Promise.<MetadataTypeMap></code> - * [.retrieveREST(retrieveDir, uri, [overrideType], [templateVariables])](#MetadataType.retrieveREST) ⇒ <code>Promise.<{metadata:MetadataTypeMap, type:string}></code> - * [.parseResponseBody(body)](#MetadataType.parseResponseBody) ⇒ <code>Promise.<MetadataTypeMap></code> - * [.deleteFieldByDefinition(metadataEntry, fieldPath, definitionProperty, origin)](#MetadataType.deleteFieldByDefinition) ⇒ <code>void</code> - * [.removeNotCreateableFields(metadataEntry)](#MetadataType.removeNotCreateableFields) ⇒ <code>void</code> - * [.removeNotUpdateableFields(metadataEntry)](#MetadataType.removeNotUpdateableFields) ⇒ <code>void</code> - * [.keepTemplateFields(metadataEntry)](#MetadataType.keepTemplateFields) ⇒ <code>void</code> - * [.keepRetrieveFields(metadataEntry)](#MetadataType.keepRetrieveFields) ⇒ <code>void</code> - * [.isFiltered(metadataEntry, [include])](#MetadataType.isFiltered) ⇒ <code>boolean</code> - * [.isFilteredFolder(metadataEntry, [include])](#MetadataType.isFilteredFolder) ⇒ <code>boolean</code> - * [.paginate(url, last)](#MetadataType.paginate) ⇒ <code>string</code> - * [.saveResults(results, retrieveDir, [overrideType], [templateVariables])](#MetadataType.saveResults) ⇒ <code>Promise.<MetadataTypeMap></code> - * [.buildDefinitionForExtracts(templateDir, targetDir, metadata, variables, templateName)](#MetadataType.buildDefinitionForExtracts) ⇒ <code>Promise.<void></code> - * [.findSubType(templateDir, templateName)](#MetadataType.findSubType) ⇒ <code>string</code> - * [.readSecondaryFolder(templateDir, typeDirArr, templateName, fileName, ex)](#MetadataType.readSecondaryFolder) ⇒ <code>Object</code> - * [.buildDefinition(templateDir, targetDir, templateName, variables)](#MetadataType.buildDefinition) ⇒ <code>Promise.<{metadata:MetadataTypeMap, type:string}></code> - * [.checkForErrors(response)](#MetadataType.checkForErrors) ⇒ <code>void</code> - * [.document([buObject], [metadata], [isDeploy])](#MetadataType.document) ⇒ <code>void</code> - * [.deleteByKey(buObject, customerKey)](#MetadataType.deleteByKey) ⇒ <code>void</code> - * [.readBUMetadataForType(readDir, [listBadKeys], [buMetadata])](#MetadataType.readBUMetadataForType) ⇒ <code>Object</code> - -<a name="new_MetadataType_new"></a> - -### new MetadataType(client, businessUnit, cache, properties, [subType]) -Instantiates a metadata constructor to avoid passing variables. - - -| Param | Type | Description | -| --- | --- | --- | -| client | <code>Util.ET\_Client</code> | client for sfmc fuelsdk | -| businessUnit | <code>string</code> | Name of business unit (corresponding to their keys in 'properties.json' file). Used to access correct directories | -| cache | <code>Object</code> | metadata cache | -| properties | <code>Object</code> | mcdev config | -| [subType] | <code>string</code> | limit retrieve to specific subType | - -<a name="MetadataType.client"></a> - -### MetadataType.client : <code>Util.ET\_Client</code> -**Kind**: static property of [<code>MetadataType</code>](#MetadataType) -<a name="MetadataType.cache"></a> - -### MetadataType.cache : [<code>MultiMetadataTypeMap</code>](#MultiMetadataTypeMap) -**Kind**: static property of [<code>MetadataType</code>](#MetadataType) -<a name="MetadataType.getJsonFromFS"></a> - -### MetadataType.getJsonFromFS(dir, [listBadKeys]) ⇒ <code>Object</code> -Returns file contents mapped to their filename without '.json' ending - -**Kind**: static method of [<code>MetadataType</code>](#MetadataType) -**Returns**: <code>Object</code> - fileName => fileContent map - -| Param | Type | Default | Description | -| --- | --- | --- | --- | -| dir | <code>string</code> | | directory that contains '.json' files to be read | -| [listBadKeys] | <code>boolean</code> | <code>false</code> | do not print errors, used for badKeys() | - -<a name="MetadataType.getFieldNamesToRetrieve"></a> - -### MetadataType.getFieldNamesToRetrieve([additionalFields]) ⇒ <code>Array.<string></code> -Returns fieldnames of Metadata Type. 'this.definition.fields' variable only set in child classes. - -**Kind**: static method of [<code>MetadataType</code>](#MetadataType) -**Returns**: <code>Array.<string></code> - Fieldnames - -| Param | Type | Description | -| --- | --- | --- | -| [additionalFields] | <code>Array.<string></code> | Returns specified fields even if their retrieve definition is not set to true | - -<a name="MetadataType.deploy"></a> - -### MetadataType.deploy(metadata, deployDir, retrieveDir, buObject) ⇒ <code>Promise.<Object></code> -Deploys metadata - -**Kind**: static method of [<code>MetadataType</code>](#MetadataType) -**Returns**: <code>Promise.<Object></code> - Promise of keyField => metadata map - -| Param | Type | Description | -| --- | --- | --- | -| metadata | <code>MetadataTypeMap</code> | metadata mapped by their keyField | -| deployDir | <code>string</code> | directory where deploy metadata are saved | -| retrieveDir | <code>string</code> | directory where metadata after deploy should be saved | -| buObject | <code>Util.BuObject</code> | properties for auth | - -<a name="MetadataType.postDeployTasks"></a> - -### MetadataType.postDeployTasks(metadata, originalMetadata) ⇒ <code>void</code> -Gets executed after deployment of metadata type - -**Kind**: static method of [<code>MetadataType</code>](#MetadataType) - -| Param | Type | Description | -| --- | --- | --- | -| metadata | <code>MetadataTypeMap</code> | metadata mapped by their keyField | -| originalMetadata | <code>MetadataTypeMap</code> | metadata to be updated (contains additioanl fields) | - -<a name="MetadataType.postRetrieveTasks"></a> - -### MetadataType.postRetrieveTasks(metadata, targetDir, [isTemplating]) ⇒ <code>MetadataTypeItem</code> -Gets executed after retreive of metadata type - -**Kind**: static method of [<code>MetadataType</code>](#MetadataType) -**Returns**: <code>MetadataTypeItem</code> - cloned metadata - -| Param | Type | Description | -| --- | --- | --- | -| metadata | <code>MetadataTypeItem</code> | a single item | -| targetDir | <code>string</code> | folder where retrieves should be saved | -| [isTemplating] | <code>boolean</code> | signals that we are retrieving templates | - -<a name="MetadataType.overrideKeyWithName"></a> - -### MetadataType.overrideKeyWithName(metadata, [warningMsg]) ⇒ <code>void</code> -used to synchronize name and external key during retrieveAsTemplate - -**Kind**: static method of [<code>MetadataType</code>](#MetadataType) - -| Param | Type | Description | -| --- | --- | --- | -| metadata | <code>MetadataTypeItem</code> | a single item | -| [warningMsg] | <code>string</code> | optional msg to show the user | - -<a name="MetadataType.retrieve"></a> - -### MetadataType.retrieve(retrieveDir, [additionalFields], buObject, [subType]) ⇒ <code>Promise.<{metadata:MetadataTypeMap, type:string}></code> -Gets metadata from Marketing Cloud - -**Kind**: static method of [<code>MetadataType</code>](#MetadataType) -**Returns**: <code>Promise.<{metadata:MetadataTypeMap, type:string}></code> - metadata - -| Param | Type | Description | -| --- | --- | --- | -| retrieveDir | <code>string</code> | Directory where retrieved metadata directory will be saved | -| [additionalFields] | <code>Array.<string></code> | Returns specified fields even if their retrieve definition is not set to true | -| buObject | <code>Util.BuObject</code> | properties for auth | -| [subType] | <code>string</code> | optionally limit to a single subtype | - -<a name="MetadataType.retrieveChangelog"></a> - -### MetadataType.retrieveChangelog([additionalFields], buObject, [subType]) ⇒ <code>Promise.<{metadata:MetadataTypeMap, type:string}></code> -Gets metadata from Marketing Cloud - -**Kind**: static method of [<code>MetadataType</code>](#MetadataType) -**Returns**: <code>Promise.<{metadata:MetadataTypeMap, type:string}></code> - metadata - -| Param | Type | Description | -| --- | --- | --- | -| [additionalFields] | <code>Array.<string></code> | Returns specified fields even if their retrieve definition is not set to true | -| buObject | <code>Util.BuObject</code> | properties for auth | -| [subType] | <code>string</code> | optionally limit to a single subtype | - -<a name="MetadataType.retrieveForCache"></a> - -### MetadataType.retrieveForCache(buObject, [subType]) ⇒ <code>Promise.<{metadata:MetadataTypeMap, type:string}></code> -Gets metadata cache with limited fields and does not store value to disk - -**Kind**: static method of [<code>MetadataType</code>](#MetadataType) -**Returns**: <code>Promise.<{metadata:MetadataTypeMap, type:string}></code> - metadata - -| Param | Type | Description | -| --- | --- | --- | -| buObject | <code>Util.BuObject</code> | properties for auth | -| [subType] | <code>string</code> | optionally limit to a single subtype | - -<a name="MetadataType.retrieveAsTemplate"></a> - -### MetadataType.retrieveAsTemplate(templateDir, name, templateVariables, [subType]) ⇒ <code>Promise.<{metadata:MetadataTypeMap, type:string}></code> -Gets metadata cache with limited fields and does not store value to disk - -**Kind**: static method of [<code>MetadataType</code>](#MetadataType) -**Returns**: <code>Promise.<{metadata:MetadataTypeMap, type:string}></code> - metadata - -| Param | Type | Description | -| --- | --- | --- | -| templateDir | <code>string</code> | Directory where retrieved metadata directory will be saved | -| name | <code>string</code> | name of the metadata file | -| templateVariables | <code>Util.TemplateMap</code> | variables to be replaced in the metadata | -| [subType] | <code>string</code> | optionally limit to a single subtype | - -<a name="MetadataType.preDeployTasks"></a> - -### MetadataType.preDeployTasks(metadata, deployDir) ⇒ <code>Promise.<MetadataTypeItem></code> -Gets executed before deploying metadata - -**Kind**: static method of [<code>MetadataType</code>](#MetadataType) -**Returns**: <code>Promise.<MetadataTypeItem></code> - Promise of a single metadata item - -| Param | Type | Description | -| --- | --- | --- | -| metadata | <code>MetadataTypeItem</code> | a single metadata item | -| deployDir | <code>string</code> | folder where files for deployment are stored | - -<a name="MetadataType.create"></a> - -### MetadataType.create(metadata, deployDir) ⇒ <code>void</code> -Abstract create method that needs to be implemented in child metadata type - -**Kind**: static method of [<code>MetadataType</code>](#MetadataType) - -| Param | Type | Description | -| --- | --- | --- | -| metadata | <code>MetadataTypeItem</code> | single metadata entry | -| deployDir | <code>string</code> | directory where deploy metadata are saved | - -<a name="MetadataType.update"></a> - -### MetadataType.update(metadata, [metadataBefore]) ⇒ <code>void</code> -Abstract update method that needs to be implemented in child metadata type - -**Kind**: static method of [<code>MetadataType</code>](#MetadataType) - -| Param | Type | Description | -| --- | --- | --- | -| metadata | <code>MetadataTypeItem</code> | single metadata entry | -| [metadataBefore] | <code>MetadataTypeItem</code> | metadata mapped by their keyField | - -<a name="MetadataType.upsert"></a> - -### MetadataType.upsert(metadata, deployDir, [buObject]) ⇒ <code>Promise.<MetadataTypeMap></code> -MetadataType upsert, after retrieving from target and comparing to check if create or update operation is needed. - -**Kind**: static method of [<code>MetadataType</code>](#MetadataType) -**Returns**: <code>Promise.<MetadataTypeMap></code> - keyField => metadata map - -| Param | Type | Description | -| --- | --- | --- | -| metadata | <code>MetadataTypeMap</code> | metadata mapped by their keyField | -| deployDir | <code>string</code> | directory where deploy metadata are saved | -| [buObject] | <code>Util.BuObject</code> | properties for auth | - -<a name="MetadataType.createREST"></a> - -### MetadataType.createREST(metadataEntry, uri) ⇒ <code>Promise</code> -Creates a single metadata entry via REST - -**Kind**: static method of [<code>MetadataType</code>](#MetadataType) -**Returns**: <code>Promise</code> - Promise - -| Param | Type | Description | -| --- | --- | --- | -| metadataEntry | <code>MetadataTypeItem</code> | a single metadata Entry | -| uri | <code>string</code> | rest endpoint for POST | - -<a name="MetadataType.createSOAP"></a> - -### MetadataType.createSOAP(metadataEntry, [overrideType], [handleOutside]) ⇒ <code>Promise</code> -Creates a single metadata entry via fuel-soap (generic lib not wrapper) - -**Kind**: static method of [<code>MetadataType</code>](#MetadataType) -**Returns**: <code>Promise</code> - Promise - -| Param | Type | Description | -| --- | --- | --- | -| metadataEntry | <code>MetadataTypeItem</code> | single metadata entry | -| [overrideType] | <code>string</code> | can be used if the API type differs from the otherwise used type identifier | -| [handleOutside] | <code>boolean</code> | if the API reponse is irregular this allows you to handle it outside of this generic method | - -<a name="MetadataType.updateREST"></a> - -### MetadataType.updateREST(metadataEntry, uri) ⇒ <code>Promise</code> -Updates a single metadata entry via REST - -**Kind**: static method of [<code>MetadataType</code>](#MetadataType) -**Returns**: <code>Promise</code> - Promise - -| Param | Type | Description | -| --- | --- | --- | -| metadataEntry | <code>MetadataTypeItem</code> | a single metadata Entry | -| uri | <code>string</code> | rest endpoint for PATCH | - -<a name="MetadataType.updateSOAP"></a> - -### MetadataType.updateSOAP(metadataEntry, [overrideType], [handleOutside]) ⇒ <code>Promise</code> -Updates a single metadata entry via fuel-soap (generic lib not wrapper) - -**Kind**: static method of [<code>MetadataType</code>](#MetadataType) -**Returns**: <code>Promise</code> - Promise - -| Param | Type | Description | -| --- | --- | --- | -| metadataEntry | <code>MetadataTypeItem</code> | single metadata entry | -| [overrideType] | <code>string</code> | can be used if the API type differs from the otherwise used type identifier | -| [handleOutside] | <code>boolean</code> | if the API reponse is irregular this allows you to handle it outside of this generic method | - -<a name="MetadataType.retrieveSOAPgeneric"></a> - -### MetadataType.retrieveSOAPgeneric(retrieveDir, buObject, [options], [additionalFields], [overrideType]) ⇒ <code>Promise.<{metadata:MetadataTypeMap, type:string}></code> -Retrieves SOAP via generic fuel-soap wrapper based metadata of metadata type into local filesystem. executes callback with retrieved metadata - -**Kind**: static method of [<code>MetadataType</code>](#MetadataType) -**Returns**: <code>Promise.<{metadata:MetadataTypeMap, type:string}></code> - Promise of item map - -| Param | Type | Description | -| --- | --- | --- | -| retrieveDir | <code>string</code> | Directory where retrieved metadata directory will be saved | -| buObject | <code>Util.BuObject</code> | properties for auth | -| [options] | <code>Object</code> | required for the specific request (filter for example) | -| [additionalFields] | <code>Array.<string></code> | Returns specified fields even if their retrieve definition is not set to true | -| [overrideType] | <code>string</code> | can be used if the API type differs from the otherwise used type identifier | - -<a name="MetadataType.retrieveSOAPBody"></a> - -### MetadataType.retrieveSOAPBody(fields, [options], [type]) ⇒ <code>Promise.<MetadataTypeMap></code> -helper that handles batched retrieve via SOAP - -**Kind**: static method of [<code>MetadataType</code>](#MetadataType) -**Returns**: <code>Promise.<MetadataTypeMap></code> - keyField => metadata map - -| Param | Type | Description | -| --- | --- | --- | -| fields | <code>Array.<string></code> | list of fields that we want to see retrieved | -| [options] | <code>Object</code> | required for the specific request (filter for example) | -| [type] | <code>string</code> | optionally overwrite the API type of the metadata here | - -<a name="MetadataType.retrieveREST"></a> - -### MetadataType.retrieveREST(retrieveDir, uri, [overrideType], [templateVariables]) ⇒ <code>Promise.<{metadata:MetadataTypeMap, type:string}></code> -Retrieves Metadata for Rest Types - -**Kind**: static method of [<code>MetadataType</code>](#MetadataType) -**Returns**: <code>Promise.<{metadata:MetadataTypeMap, type:string}></code> - Promise of item map - -| Param | Type | Description | -| --- | --- | --- | -| retrieveDir | <code>string</code> | Directory where retrieved metadata directory will be saved | -| uri | <code>string</code> | rest endpoint for GET | -| [overrideType] | <code>string</code> | force a metadata type (mainly used for Folders) | -| [templateVariables] | <code>Util.TemplateMap</code> | variables to be replaced in the metadata | - -<a name="MetadataType.parseResponseBody"></a> - -### MetadataType.parseResponseBody(body) ⇒ <code>Promise.<MetadataTypeMap></code> -Builds map of metadata entries mapped to their keyfields - -**Kind**: static method of [<code>MetadataType</code>](#MetadataType) -**Returns**: <code>Promise.<MetadataTypeMap></code> - keyField => metadata map - -| Param | Type | Description | -| --- | --- | --- | -| body | <code>Object</code> | json of response body | - -<a name="MetadataType.deleteFieldByDefinition"></a> - -### MetadataType.deleteFieldByDefinition(metadataEntry, fieldPath, definitionProperty, origin) ⇒ <code>void</code> -Deletes a field in a metadata entry if the selected definition property equals false. - -**Kind**: static method of [<code>MetadataType</code>](#MetadataType) - -| Param | Type | Description | -| --- | --- | --- | -| metadataEntry | <code>MetadataTypeItem</code> | One entry of a metadataType | -| fieldPath | <code>string</code> | field path to be checked if it conforms to the definition (dot seperated if nested): 'fuu.bar' | -| definitionProperty | <code>'isCreateable'</code> \| <code>'isUpdateable'</code> \| <code>'retrieving'</code> \| <code>'templating'</code> | delete field if definitionProperty equals false for specified field. Options: [isCreateable | isUpdateable] | -| origin | <code>string</code> | string of parent object, required when using arrays as these are parsed slightly differently. | - -**Example** -```js -Removes field (or nested fields childs) that are not updateable -deleteFieldByDefinition(metadataEntry, 'CustomerKey', 'isUpdateable'); -``` -<a name="MetadataType.removeNotCreateableFields"></a> - -### MetadataType.removeNotCreateableFields(metadataEntry) ⇒ <code>void</code> -Remove fields from metadata entry that are not createable - -**Kind**: static method of [<code>MetadataType</code>](#MetadataType) - -| Param | Type | Description | -| --- | --- | --- | -| metadataEntry | <code>MetadataTypeItem</code> | metadata entry | - -<a name="MetadataType.removeNotUpdateableFields"></a> - -### MetadataType.removeNotUpdateableFields(metadataEntry) ⇒ <code>void</code> -Remove fields from metadata entry that are not updateable - -**Kind**: static method of [<code>MetadataType</code>](#MetadataType) - -| Param | Type | Description | -| --- | --- | --- | -| metadataEntry | <code>MetadataTypeItem</code> | metadata entry | - -<a name="MetadataType.keepTemplateFields"></a> - -### MetadataType.keepTemplateFields(metadataEntry) ⇒ <code>void</code> -Remove fields from metadata entry that are not needed in the template - -**Kind**: static method of [<code>MetadataType</code>](#MetadataType) - -| Param | Type | Description | -| --- | --- | --- | -| metadataEntry | <code>MetadataTypeItem</code> | metadata entry | - -<a name="MetadataType.keepRetrieveFields"></a> - -### MetadataType.keepRetrieveFields(metadataEntry) ⇒ <code>void</code> -Remove fields from metadata entry that are not needed in the stored metadata - -**Kind**: static method of [<code>MetadataType</code>](#MetadataType) - -| Param | Type | Description | -| --- | --- | --- | -| metadataEntry | <code>MetadataTypeItem</code> | metadata entry | - -<a name="MetadataType.isFiltered"></a> - -### MetadataType.isFiltered(metadataEntry, [include]) ⇒ <code>boolean</code> -checks if the current metadata entry should be saved on retrieve or not - -**Kind**: static method of [<code>MetadataType</code>](#MetadataType) -**Returns**: <code>boolean</code> - true: skip saving == filtered; false: continue with saving - -| Param | Type | Default | Description | -| --- | --- | --- | --- | -| metadataEntry | <code>MetadataTypeItem</code> | | metadata entry | -| [include] | <code>boolean</code> | <code>false</code> | true: use definition.include / options.include; false=exclude: use definition.filter / options.exclude | - -<a name="MetadataType.isFilteredFolder"></a> - -### MetadataType.isFilteredFolder(metadataEntry, [include]) ⇒ <code>boolean</code> -optionally filter by what folder something is in - -**Kind**: static method of [<code>MetadataType</code>](#MetadataType) -**Returns**: <code>boolean</code> - true: filtered == do NOT save; false: not filtered == do save - -| Param | Type | Default | Description | -| --- | --- | --- | --- | -| metadataEntry | <code>Object</code> | | metadata entry | -| [include] | <code>boolean</code> | <code>false</code> | true: use definition.include / options.include; false=exclude: use definition.filter / options.exclude | - -<a name="MetadataType.paginate"></a> - -### MetadataType.paginate(url, last) ⇒ <code>string</code> -Paginates a URL - -**Kind**: static method of [<code>MetadataType</code>](#MetadataType) -**Returns**: <code>string</code> - new url with pagination - -| Param | Type | Description | -| --- | --- | --- | -| url | <code>string</code> | url of the request | -| last | <code>number</code> | Number of the page of the last request | - -<a name="MetadataType.saveResults"></a> - -### MetadataType.saveResults(results, retrieveDir, [overrideType], [templateVariables]) ⇒ <code>Promise.<MetadataTypeMap></code> -Helper for writing Metadata to disk, used for Retrieve and deploy - -**Kind**: static method of [<code>MetadataType</code>](#MetadataType) -**Returns**: <code>Promise.<MetadataTypeMap></code> - Promise of saved metadata - -| Param | Type | Description | -| --- | --- | --- | -| results | <code>MetadataTypeMap</code> | metadata results from deploy | -| retrieveDir | <code>string</code> | directory where metadata should be stored after deploy/retrieve | -| [overrideType] | <code>string</code> | for use when there is a subtype (such as folder-queries) | -| [templateVariables] | <code>Util.TemplateMap</code> | variables to be replaced in the metadata | - -<a name="MetadataType.buildDefinitionForExtracts"></a> - -### MetadataType.buildDefinitionForExtracts(templateDir, targetDir, metadata, variables, templateName) ⇒ <code>Promise.<void></code> -helper for buildDefinition -handles extracted code if any are found for complex types (e.g script, asset, query) - -**Kind**: static method of [<code>MetadataType</code>](#MetadataType) -**Returns**: <code>Promise.<void></code> - Promise - -| Param | Type | Description | -| --- | --- | --- | -| templateDir | <code>string</code> | Directory where metadata templates are stored | -| targetDir | <code>string</code> | Directory where built definitions will be saved | -| metadata | <code>MetadataTypeItem</code> | main JSON file that was read from file system | -| variables | <code>Util.TemplateMap</code> | variables to be replaced in the metadata | -| templateName | <code>string</code> | name of the template to be built | - -<a name="MetadataType.findSubType"></a> - -### MetadataType.findSubType(templateDir, templateName) ⇒ <code>string</code> -check template directory for complex types that open subfolders for their subtypes - -**Kind**: static method of [<code>MetadataType</code>](#MetadataType) -**Returns**: <code>string</code> - subtype name - -| Param | Type | Description | -| --- | --- | --- | -| templateDir | <code>string</code> | Directory where metadata templates are stored | -| templateName | <code>string</code> | name of the metadata file | - -<a name="MetadataType.readSecondaryFolder"></a> - -### MetadataType.readSecondaryFolder(templateDir, typeDirArr, templateName, fileName, ex) ⇒ <code>Object</code> -optional method used for some types to try a different folder structure - -**Kind**: static method of [<code>MetadataType</code>](#MetadataType) -**Returns**: <code>Object</code> - metadata - -| Param | Type | Description | -| --- | --- | --- | -| templateDir | <code>string</code> | Directory where metadata templates are stored | -| typeDirArr | <code>Array.<string></code> | current subdir for this type | -| templateName | <code>string</code> | name of the metadata template | -| fileName | <code>string</code> | name of the metadata template file w/o extension | -| ex | <code>Error</code> | error from first attempt | - -<a name="MetadataType.buildDefinition"></a> - -### MetadataType.buildDefinition(templateDir, targetDir, templateName, variables) ⇒ <code>Promise.<{metadata:MetadataTypeMap, type:string}></code> -Builds definition based on template -NOTE: Most metadata files should use this generic method, unless custom -parsing is required (for example scripts & queries) - -**Kind**: static method of [<code>MetadataType</code>](#MetadataType) -**Returns**: <code>Promise.<{metadata:MetadataTypeMap, type:string}></code> - Promise of item map - -| Param | Type | Description | -| --- | --- | --- | -| templateDir | <code>string</code> | Directory where metadata templates are stored | -| targetDir | <code>String</code> \| <code>Array.<String></code> | (List of) Directory where built definitions will be saved | -| templateName | <code>string</code> | name of the metadata file | -| variables | <code>Util.TemplateMap</code> | variables to be replaced in the metadata | - -<a name="MetadataType.checkForErrors"></a> - -### MetadataType.checkForErrors(response) ⇒ <code>void</code> -**Kind**: static method of [<code>MetadataType</code>](#MetadataType) - -| Param | Type | Description | -| --- | --- | --- | -| response | <code>Object</code> | response payload from REST API | - -<a name="MetadataType.document"></a> - -### MetadataType.document([buObject], [metadata], [isDeploy]) ⇒ <code>void</code> -Gets metadata cache with limited fields and does not store value to disk - -**Kind**: static method of [<code>MetadataType</code>](#MetadataType) - -| Param | Type | Description | -| --- | --- | --- | -| [buObject] | <code>Util.BuObject</code> | properties for auth | -| [metadata] | <code>MetadataTypeMap</code> | a list of type definitions | -| [isDeploy] | <code>boolean</code> | used to skip non-supported message during deploy | - -<a name="MetadataType.deleteByKey"></a> - -### MetadataType.deleteByKey(buObject, customerKey) ⇒ <code>void</code> -Delete a data extension from the specified business unit - -**Kind**: static method of [<code>MetadataType</code>](#MetadataType) -**Returns**: <code>void</code> - - - -| Param | Type | Description | -| --- | --- | --- | -| buObject | <code>Util.BuObject</code> | references credentials | -| customerKey | <code>string</code> | Identifier of data extension | - -<a name="MetadataType.readBUMetadataForType"></a> - -### MetadataType.readBUMetadataForType(readDir, [listBadKeys], [buMetadata]) ⇒ <code>Object</code> -Returns metadata of a business unit that is saved locally - -**Kind**: static method of [<code>MetadataType</code>](#MetadataType) -**Returns**: <code>Object</code> - Metadata of BU in local directory - -| Param | Type | Default | Description | -| --- | --- | --- | --- | -| readDir | <code>string</code> | | root directory of metadata. | -| [listBadKeys] | <code>boolean</code> | <code>false</code> | do not print errors, used for badKeys() | -| [buMetadata] | <code>Object</code> | | Metadata of BU in local directory | - -<a name="Query"></a> - -## Query ⇐ [<code>MetadataType</code>](#MetadataType) -Query MetadataType - -**Kind**: global class -**Extends**: [<code>MetadataType</code>](#MetadataType) - -* [Query](#Query) ⇐ [<code>MetadataType</code>](#MetadataType) - * [.retrieve(retrieveDir)](#Query.retrieve) ⇒ <code>Promise.<{metadata:QueryMap, type:string}></code> - * [.retrieveForCache()](#Query.retrieveForCache) ⇒ <code>Promise.<{metadata:QueryMap, type:string}></code> - * [.retrieveAsTemplate(templateDir, name, templateVariables)](#Query.retrieveAsTemplate) ⇒ <code>Promise.<{metadata:QueryMap, type:string}></code> - * [.postRetrieveTasks(metadata, _, isTemplating)](#Query.postRetrieveTasks) ⇒ [<code>CodeExtractItem</code>](#CodeExtractItem) - * [.create(query)](#Query.create) ⇒ <code>Promise</code> - * [.update(query)](#Query.update) ⇒ <code>Promise</code> - * [.preDeployTasks(metadata, deployDir)](#Query.preDeployTasks) ⇒ <code>Promise.<QueryItem></code> - * [.buildDefinitionForExtracts(templateDir, targetDir, metadata, variables, templateName)](#Query.buildDefinitionForExtracts) ⇒ <code>Promise</code> - * [.parseMetadata(metadata)](#Query.parseMetadata) ⇒ [<code>CodeExtractItem</code>](#CodeExtractItem) - -<a name="Query.retrieve"></a> - -### Query.retrieve(retrieveDir) ⇒ <code>Promise.<{metadata:QueryMap, type:string}></code> -Retrieves Metadata of queries - -**Kind**: static method of [<code>Query</code>](#Query) -**Returns**: <code>Promise.<{metadata:QueryMap, type:string}></code> - Promise of metadata - -| Param | Type | Description | -| --- | --- | --- | -| retrieveDir | <code>string</code> | Directory where retrieved metadata directory will be saved | - -<a name="Query.retrieveForCache"></a> - -### Query.retrieveForCache() ⇒ <code>Promise.<{metadata:QueryMap, type:string}></code> -Retrieves query metadata for caching - -**Kind**: static method of [<code>Query</code>](#Query) -**Returns**: <code>Promise.<{metadata:QueryMap, type:string}></code> - Promise of metadata -<a name="Query.retrieveAsTemplate"></a> - -### Query.retrieveAsTemplate(templateDir, name, templateVariables) ⇒ <code>Promise.<{metadata:QueryMap, type:string}></code> -Retrieve a specific Query by Name - -**Kind**: static method of [<code>Query</code>](#Query) -**Returns**: <code>Promise.<{metadata:QueryMap, type:string}></code> - Promise of metadata - -| Param | Type | Description | -| --- | --- | --- | -| templateDir | <code>string</code> | Directory where retrieved metadata directory will be saved | -| name | <code>string</code> | name of the metadata file | -| templateVariables | <code>Util.TemplateMap</code> | variables to be replaced in the metadata | - -<a name="Query.postRetrieveTasks"></a> - -### Query.postRetrieveTasks(metadata, _, isTemplating) ⇒ [<code>CodeExtractItem</code>](#CodeExtractItem) -manages post retrieve steps - -**Kind**: static method of [<code>Query</code>](#Query) -**Returns**: [<code>CodeExtractItem</code>](#CodeExtractItem) - Array with one metadata object and one query string - -| Param | Type | Description | -| --- | --- | --- | -| metadata | <code>QueryItem</code> | a single query | -| _ | <code>string</code> | unused | -| isTemplating | <code>boolean</code> | signals that we are retrieving templates | - -<a name="Query.create"></a> - -### Query.create(query) ⇒ <code>Promise</code> -Creates a single query - -**Kind**: static method of [<code>Query</code>](#Query) -**Returns**: <code>Promise</code> - Promise - -| Param | Type | Description | -| --- | --- | --- | -| query | <code>QueryItem</code> | a single query | - -<a name="Query.update"></a> - -### Query.update(query) ⇒ <code>Promise</code> -Updates a single query - -**Kind**: static method of [<code>Query</code>](#Query) -**Returns**: <code>Promise</code> - Promise - -| Param | Type | Description | -| --- | --- | --- | -| query | <code>QueryItem</code> | a single query | - -<a name="Query.preDeployTasks"></a> - -### Query.preDeployTasks(metadata, deployDir) ⇒ <code>Promise.<QueryItem></code> -prepares a Query for deployment - -**Kind**: static method of [<code>Query</code>](#Query) -**Returns**: <code>Promise.<QueryItem></code> - Promise - -| Param | Type | Description | -| --- | --- | --- | -| metadata | <code>QueryItem</code> | a single query activity | -| deployDir | <code>string</code> | directory of deploy files | - -<a name="Query.buildDefinitionForExtracts"></a> - -### Query.buildDefinitionForExtracts(templateDir, targetDir, metadata, variables, templateName) ⇒ <code>Promise</code> -helper for buildDefinition -handles extracted code if any are found for complex types - -**Kind**: static method of [<code>Query</code>](#Query) -**Returns**: <code>Promise</code> - Promise - -| Param | Type | Description | -| --- | --- | --- | -| templateDir | <code>string</code> | Directory where metadata templates are stored | -| targetDir | <code>string</code> \| <code>Array.<string></code> | (List of) Directory where built definitions will be saved | -| metadata | <code>Object</code> | main JSON file that was read from file system | -| variables | <code>Object</code> | variables to be replaced in the metadata | -| templateName | <code>string</code> | name of the template to be built | - -<a name="Query.parseMetadata"></a> - -### Query.parseMetadata(metadata) ⇒ [<code>CodeExtractItem</code>](#CodeExtractItem) -parses retrieved Metadata before saving - -**Kind**: static method of [<code>Query</code>](#Query) -**Returns**: [<code>CodeExtractItem</code>](#CodeExtractItem) - a single item with code parts extracted - -| Param | Type | Description | -| --- | --- | --- | -| metadata | <code>QueryItem</code> | a single query activity definition | - -<a name="Role"></a> - -## Role ⇐ [<code>MetadataType</code>](#MetadataType) -ImportFile MetadataType - -**Kind**: global class -**Extends**: [<code>MetadataType</code>](#MetadataType) - -* [Role](#Role) ⇐ [<code>MetadataType</code>](#MetadataType) - * [.retrieve(retrieveDir, _, buObject)](#Role.retrieve) ⇒ <code>Promise.<Object></code> - * [.preDeployTasks(metadata)](#Role.preDeployTasks) ⇒ <code>Promise.<Object></code> - * [.create(metadata)](#Role.create) ⇒ <code>Promise</code> - * [.update(metadata)](#Role.update) ⇒ <code>Promise</code> - * [.document(buObject, [metadata])](#Role.document) ⇒ <code>Promise.<void></code> - * [._traverseRoles(role, element, [permission], [isAllowed])](#Role._traverseRoles) ⇒ <code>void</code> - -<a name="Role.retrieve"></a> - -### Role.retrieve(retrieveDir, _, buObject) ⇒ <code>Promise.<Object></code> -Gets metadata from Marketing Cloud - -**Kind**: static method of [<code>Role</code>](#Role) -**Returns**: <code>Promise.<Object></code> - Metadata store object - -| Param | Type | Description | -| --- | --- | --- | -| retrieveDir | <code>String</code> | Directory where retrieved metadata directory will be saved | -| _ | <code>Array.<String></code> | Returns specified fields even if their retrieve definition is not set to true | -| buObject | <code>Object</code> | properties for auth | - -<a name="Role.preDeployTasks"></a> - -### Role.preDeployTasks(metadata) ⇒ <code>Promise.<Object></code> -Gets executed before deploying metadata - -**Kind**: static method of [<code>Role</code>](#Role) -**Returns**: <code>Promise.<Object></code> - Promise of a single metadata item - -| Param | Type | Description | -| --- | --- | --- | -| metadata | <code>Object</code> | a single metadata item | - -<a name="Role.create"></a> - -### Role.create(metadata) ⇒ <code>Promise</code> -Create a single Role. - -**Kind**: static method of [<code>Role</code>](#Role) -**Returns**: <code>Promise</code> - Promise - -| Param | Type | Description | -| --- | --- | --- | -| metadata | <code>Object</code> | single metadata entry | - -<a name="Role.update"></a> - -### Role.update(metadata) ⇒ <code>Promise</code> -Updates a single Role. - -**Kind**: static method of [<code>Role</code>](#Role) -**Returns**: <code>Promise</code> - Promise - -| Param | Type | Description | -| --- | --- | --- | -| metadata | <code>Object</code> | single metadata entry | - -<a name="Role.document"></a> - -### Role.document(buObject, [metadata]) ⇒ <code>Promise.<void></code> -Creates markdown documentation of all roles - -**Kind**: static method of [<code>Role</code>](#Role) -**Returns**: <code>Promise.<void></code> - - - -| Param | Type | Description | -| --- | --- | --- | -| buObject | <code>Object</code> | properties for auth | -| [metadata] | <code>Object</code> | role definitions | - -<a name="Role._traverseRoles"></a> - -### Role.\_traverseRoles(role, element, [permission], [isAllowed]) ⇒ <code>void</code> -iterates through permissions to output proper row-names for nested permissionss - -**Kind**: static method of [<code>Role</code>](#Role) - -| Param | Type | Description | -| --- | --- | --- | -| role | <code>string</code> | name of the user role | -| element | <code>object</code> | data of the permission | -| [permission] | <code>string</code> | name of the permission | -| [isAllowed] | <code>string</code> | "true" / "false" from the | - -<a name="Script"></a> - -## Script ⇐ [<code>MetadataType</code>](#MetadataType) -Script MetadataType - -**Kind**: global class -**Extends**: [<code>MetadataType</code>](#MetadataType) - -* [Script](#Script) ⇐ [<code>MetadataType</code>](#MetadataType) - * [.retrieve(retrieveDir)](#Script.retrieve) ⇒ <code>Promise.<{metadata:ScriptMap, type:string}></code> - * [.retrieveForCache()](#Script.retrieveForCache) ⇒ <code>Promise.<{metadata:ScriptMap, type:string}></code> - * [.retrieveAsTemplate(templateDir, name, templateVariables)](#Script.retrieveAsTemplate) ⇒ <code>Promise.<{metadata:ScriptMap, type:string}></code> - * [.postRetrieveTasks(metadata, [_], [isTemplating])](#Script.postRetrieveTasks) ⇒ [<code>CodeExtractItem</code>](#CodeExtractItem) - * [.update(script)](#Script.update) ⇒ <code>Promise</code> - * [.create(script)](#Script.create) ⇒ <code>Promise</code> - * [._mergeCode(metadata, deployDir, [templateName])](#Script._mergeCode) ⇒ <code>Promise.<String></code> - * [.preDeployTasks(metadata, dir)](#Script.preDeployTasks) ⇒ <code>ScriptItem</code> - * [.buildDefinitionForExtracts(templateDir, targetDir, metadata, variables, templateName)](#Script.buildDefinitionForExtracts) ⇒ <code>Promise</code> - * [.parseMetadata(metadata)](#Script.parseMetadata) ⇒ [<code>CodeExtractItem</code>](#CodeExtractItem) - -<a name="Script.retrieve"></a> - -### Script.retrieve(retrieveDir) ⇒ <code>Promise.<{metadata:ScriptMap, type:string}></code> -Retrieves Metadata of Script -Endpoint /automation/v1/scripts/ return all Scripts with all details. - -**Kind**: static method of [<code>Script</code>](#Script) -**Returns**: <code>Promise.<{metadata:ScriptMap, type:string}></code> - Promise - -| Param | Type | Description | -| --- | --- | --- | -| retrieveDir | <code>string</code> | Directory where retrieved metadata directory will be saved | - -<a name="Script.retrieveForCache"></a> - -### Script.retrieveForCache() ⇒ <code>Promise.<{metadata:ScriptMap, type:string}></code> -Retrieves script metadata for caching - -**Kind**: static method of [<code>Script</code>](#Script) -**Returns**: <code>Promise.<{metadata:ScriptMap, type:string}></code> - Promise -<a name="Script.retrieveAsTemplate"></a> - -### Script.retrieveAsTemplate(templateDir, name, templateVariables) ⇒ <code>Promise.<{metadata:ScriptMap, type:string}></code> -Retrieve a specific Script by Name - -**Kind**: static method of [<code>Script</code>](#Script) -**Returns**: <code>Promise.<{metadata:ScriptMap, type:string}></code> - Promise - -| Param | Type | Description | -| --- | --- | --- | -| templateDir | <code>string</code> | Directory where retrieved metadata directory will be saved | -| name | <code>string</code> | name of the metadata file | -| templateVariables | <code>Util.TemplateMap</code> | variables to be replaced in the metadata | - -<a name="Script.postRetrieveTasks"></a> - -### Script.postRetrieveTasks(metadata, [_], [isTemplating]) ⇒ [<code>CodeExtractItem</code>](#CodeExtractItem) -manages post retrieve steps - -**Kind**: static method of [<code>Script</code>](#Script) -**Returns**: [<code>CodeExtractItem</code>](#CodeExtractItem) - Array with one metadata object and one ssjs string - -| Param | Type | Description | -| --- | --- | --- | -| metadata | <code>ScriptItem</code> | a single script | -| [_] | <code>string</code> | unused | -| [isTemplating] | <code>boolean</code> | signals that we are retrieving templates | - -<a name="Script.update"></a> - -### Script.update(script) ⇒ <code>Promise</code> -Updates a single Script - -**Kind**: static method of [<code>Script</code>](#Script) -**Returns**: <code>Promise</code> - Promise - -| Param | Type | Description | -| --- | --- | --- | -| script | <code>Object</code> | a single Script | - -<a name="Script.create"></a> - -### Script.create(script) ⇒ <code>Promise</code> -Creates a single Script - -**Kind**: static method of [<code>Script</code>](#Script) -**Returns**: <code>Promise</code> - Promise - -| Param | Type | Description | -| --- | --- | --- | -| script | <code>Object</code> | a single Script | - -<a name="Script._mergeCode"></a> - -### Script.\_mergeCode(metadata, deployDir, [templateName]) ⇒ <code>Promise.<String></code> -helper for this.preDeployTasks() that loads extracted code content back into JSON - -**Kind**: static method of [<code>Script</code>](#Script) -**Returns**: <code>Promise.<String></code> - content for metadata.script - -| Param | Type | Description | -| --- | --- | --- | -| metadata | <code>ScriptItem</code> | a single asset definition | -| deployDir | <code>string</code> | directory of deploy files | -| [templateName] | <code>string</code> | name of the template used to built defintion (prior applying templating) | - -<a name="Script.preDeployTasks"></a> - -### Script.preDeployTasks(metadata, dir) ⇒ <code>ScriptItem</code> -prepares a Script for deployment - -**Kind**: static method of [<code>Script</code>](#Script) -**Returns**: <code>ScriptItem</code> - Promise - -| Param | Type | Description | -| --- | --- | --- | -| metadata | <code>ScriptItem</code> | a single script activity definition | -| dir | <code>string</code> | directory of deploy files | - -<a name="Script.buildDefinitionForExtracts"></a> - -### Script.buildDefinitionForExtracts(templateDir, targetDir, metadata, variables, templateName) ⇒ <code>Promise</code> -helper for buildDefinition -handles extracted code if any are found for complex types - -**Kind**: static method of [<code>Script</code>](#Script) -**Returns**: <code>Promise</code> - Promise - -| Param | Type | Description | -| --- | --- | --- | -| templateDir | <code>string</code> | Directory where metadata templates are stored | -| targetDir | <code>string</code> \| <code>Array.<string></code> | (List of) Directory where built definitions will be saved | -| metadata | <code>ScriptItem</code> | main JSON file that was read from file system | -| variables | <code>Util.TemplateMap</code> | variables to be replaced in the metadata | -| templateName | <code>string</code> | name of the template to be built | - -<a name="Script.parseMetadata"></a> - -### Script.parseMetadata(metadata) ⇒ [<code>CodeExtractItem</code>](#CodeExtractItem) -Splits the script metadata into two parts and parses in a standard manner - -**Kind**: static method of [<code>Script</code>](#Script) -**Returns**: [<code>CodeExtractItem</code>](#CodeExtractItem) - a single item with code parts extracted - -| Param | Type | Description | -| --- | --- | --- | -| metadata | <code>ScriptItem</code> | a single script activity definition | - -<a name="SetDefinition"></a> - -## SetDefinition ⇐ [<code>MetadataType</code>](#MetadataType) -SetDefinition MetadataType - -**Kind**: global class -**Extends**: [<code>MetadataType</code>](#MetadataType) - -* [SetDefinition](#SetDefinition) ⇐ [<code>MetadataType</code>](#MetadataType) - * [.retrieve(retrieveDir)](#SetDefinition.retrieve) ⇒ <code>Promise</code> - * [.retrieveForCache()](#SetDefinition.retrieveForCache) ⇒ <code>Promise</code> - -<a name="SetDefinition.retrieve"></a> - -### SetDefinition.retrieve(retrieveDir) ⇒ <code>Promise</code> -Retrieves Metadata of schema set Definitions. - -**Kind**: static method of [<code>SetDefinition</code>](#SetDefinition) -**Returns**: <code>Promise</code> - Promise - -| Param | Type | Description | -| --- | --- | --- | -| retrieveDir | <code>String</code> | Directory where retrieved metadata directory will be saved | - -<a name="SetDefinition.retrieveForCache"></a> - -### SetDefinition.retrieveForCache() ⇒ <code>Promise</code> -Retrieves Metadata of schema set definitions for caching. - -**Kind**: static method of [<code>SetDefinition</code>](#SetDefinition) -**Returns**: <code>Promise</code> - Promise -<a name="TriggeredSendDefinition"></a> - -## TriggeredSendDefinition ⇐ [<code>MetadataType</code>](#MetadataType) -MessageSendActivity MetadataType - -**Kind**: global class -**Extends**: [<code>MetadataType</code>](#MetadataType) - -* [TriggeredSendDefinition](#TriggeredSendDefinition) ⇐ [<code>MetadataType</code>](#MetadataType) - * [.retrieve(retrieveDir)](#TriggeredSendDefinition.retrieve) ⇒ <code>Promise.<Object></code> - * [.create(metadata)](#TriggeredSendDefinition.create) ⇒ <code>Promise</code> - * [.update(metadata)](#TriggeredSendDefinition.update) ⇒ <code>Promise</code> - * [.postRetrieveTasks(metadata)](#TriggeredSendDefinition.postRetrieveTasks) ⇒ <code>Array.<Object></code> - * [.parseMetadata(metadata)](#TriggeredSendDefinition.parseMetadata) ⇒ <code>Array</code> - * [.preDeployTasks(metadata)](#TriggeredSendDefinition.preDeployTasks) ⇒ <code>Object</code> - -<a name="TriggeredSendDefinition.retrieve"></a> - -### TriggeredSendDefinition.retrieve(retrieveDir) ⇒ <code>Promise.<Object></code> -Retrieves SOAP based metadata of metadata type into local filesystem. executes callback with retrieved metadata - -**Kind**: static method of [<code>TriggeredSendDefinition</code>](#TriggeredSendDefinition) -**Returns**: <code>Promise.<Object></code> - Promise of metadata - -| Param | Type | Description | -| --- | --- | --- | -| retrieveDir | <code>String</code> | Directory where retrieved metadata directory will be saved | - -<a name="TriggeredSendDefinition.create"></a> - -### TriggeredSendDefinition.create(metadata) ⇒ <code>Promise</code> -Create a single TSD. - -**Kind**: static method of [<code>TriggeredSendDefinition</code>](#TriggeredSendDefinition) -**Returns**: <code>Promise</code> - Promise - -| Param | Type | Description | -| --- | --- | --- | -| metadata | <code>Object</code> | single metadata entry | - -<a name="TriggeredSendDefinition.update"></a> - -### TriggeredSendDefinition.update(metadata) ⇒ <code>Promise</code> -Updates a single TSD. - -**Kind**: static method of [<code>TriggeredSendDefinition</code>](#TriggeredSendDefinition) -**Returns**: <code>Promise</code> - Promise - -| Param | Type | Description | -| --- | --- | --- | -| metadata | <code>Object</code> | single metadata entry | - -<a name="TriggeredSendDefinition.postRetrieveTasks"></a> - -### TriggeredSendDefinition.postRetrieveTasks(metadata) ⇒ <code>Array.<Object></code> -manages post retrieve steps - -**Kind**: static method of [<code>TriggeredSendDefinition</code>](#TriggeredSendDefinition) -**Returns**: <code>Array.<Object></code> - Array with one metadata object and one query string - -| Param | Type | Description | -| --- | --- | --- | -| metadata | <code>Object</code> | a single query | - -<a name="TriggeredSendDefinition.parseMetadata"></a> - -### TriggeredSendDefinition.parseMetadata(metadata) ⇒ <code>Array</code> -parses retrieved Metadata before saving - -**Kind**: static method of [<code>TriggeredSendDefinition</code>](#TriggeredSendDefinition) -**Returns**: <code>Array</code> - Array with one metadata object and one sql string - -| Param | Type | Description | -| --- | --- | --- | -| metadata | <code>Object</code> | a single query activity definition | - -<a name="TriggeredSendDefinition.preDeployTasks"></a> - -### TriggeredSendDefinition.preDeployTasks(metadata) ⇒ <code>Object</code> -prepares a TSD for deployment - -**Kind**: static method of [<code>TriggeredSendDefinition</code>](#TriggeredSendDefinition) -**Returns**: <code>Object</code> - metadata object - -| Param | Type | Description | -| --- | --- | --- | -| metadata | <code>Object</code> | of a single TSD | - -<a name="Retriever"></a> - -## Retriever -Retrieves metadata from a business unit and saves it to the local filesystem. - -**Kind**: global class - -* [Retriever](#Retriever) - * [new Retriever(properties, buObject, client)](#new_Retriever_new) - * [.retrieve(metadataTypes, [name], [templateVariables], [changelogOnly])](#Retriever+retrieve) ⇒ <code>Promise.<Object.<string, Object>></code> - -<a name="new_Retriever_new"></a> - -### new Retriever(properties, buObject, client) -Creates a Retriever, uses v2 auth if v2AuthOptions are passed. - - -| Param | Type | Description | -| --- | --- | --- | -| properties | <code>Object</code> | General configuration to be used in retrieve | -| properties.directories | <code>Object</code> | Directories to be used when interacting with FS | -| buObject | <code>Object</code> | properties for auth | -| buObject.clientId | <code>String</code> | clientId for FuelSDK auth | -| buObject.clientSecret | <code>String</code> | clientSecret for FuelSDK auth | -| buObject.credential | <code>Object</code> | clientId for FuelSDK auth | -| buObject.tenant | <code>String</code> | v2 Auth Tenant Information | -| [buObject.mid] | <code>String</code> | ID of Business Unit to authenticate with | -| [buObject.businessUnit] | <code>String</code> | name of Business Unit to authenticate with | -| client | <code>Util.ET\_Client</code> | fuel client | - -<a name="Retriever+retrieve"></a> - -### retriever.retrieve(metadataTypes, [name], [templateVariables], [changelogOnly]) ⇒ <code>Promise.<Object.<string, Object>></code> -Retrieve metadata of specified types into local file system and Retriever.metadata - -**Kind**: instance method of [<code>Retriever</code>](#Retriever) -**Returns**: <code>Promise.<Object.<string, Object>></code> - Promise - -| Param | Type | Description | -| --- | --- | --- | -| metadataTypes | <code>Array.<String></code> | String list of metadata types to retrieve | -| [name] | <code>String</code> | name of Metadata to retrieve (in case of templating) | -| [templateVariables] | <code>Object</code> | Object of values which can be replaced (in case of templating) | -| [changelogOnly] | <code>boolean</code> | skip saving, only create json in memory | - -<a name="Util"></a> - -## Util -CLI entry for SFMC DevTools - -**Kind**: global constant - -* [Util](#Util) - * [.logger](#Util.logger) - * [.isTrue(attrValue)](#Util.isTrue) ⇒ <code>boolean</code> - * [.isFalse(attrValue)](#Util.isFalse) ⇒ <code>boolean</code> - * [.getDefaultProperties()](#Util.getDefaultProperties) ⇒ <code>object</code> - * [.getRetrieveTypeChoices()](#Util.getRetrieveTypeChoices) ⇒ <code>Array.<string></code> - * [.checkProperties(properties, [silent])](#Util.checkProperties) ⇒ <code>boolean</code> \| <code>Array.<String></code> - * [.metadataLogger(level, type, method, payload, [source])](#Util.metadataLogger) ⇒ <code>void</code> - * [.replaceByObject(str, obj)](#Util.replaceByObject) ⇒ <code>String</code> \| <code>Object</code> - * [.inverseGet(objs, val)](#Util.inverseGet) ⇒ <code>String</code> - * [.getMetadataHierachy(metadataTypes)](#Util.getMetadataHierachy) ⇒ <code>Array.<String></code> - * [.getETClient(buObject)](#Util.getETClient) ⇒ [<code>Promise.<ET\_Client></code>](#ET_Client) - * [~myClient](#Util.getETClient..myClient) : [<code>ET\_Client</code>](#ET_Client) - * [.getFromCache(cache, metadataType, searchValue, searchField, returnField)](#Util.getFromCache) ⇒ <code>String</code> - * [.resolveObjPath(path, obj)](#Util.resolveObjPath) ⇒ <code>any</code> - * [.getListObjectIdFromCache(cache, listPathName, returnField)](#Util.getListObjectIdFromCache) ⇒ <code>String</code> - * [.getListPathNameFromCache(cache, searchValue, searchField)](#Util.getListPathNameFromCache) ⇒ <code>String</code> - * [.retryOnError(errorMsg, callback, [silentError], [retries])](#Util.retryOnError) ⇒ <code>Promise.<void></code> - * [.execSync(cmd, [args])](#Util.execSync) ⇒ <code>undefined</code> - -<a name="Util.logger"></a> - -### Util.logger -Logger that creates timestamped log file in 'logs/' directory - -**Kind**: static property of [<code>Util</code>](#Util) -<a name="Util.isTrue"></a> - -### Util.isTrue(attrValue) ⇒ <code>boolean</code> -SFMC accepts multiple true values for Boolean attributes for which we are checking here - -**Kind**: static method of [<code>Util</code>](#Util) -**Returns**: <code>boolean</code> - attribute value == true ? true : false - -| Param | Type | Description | -| --- | --- | --- | -| attrValue | <code>\*</code> | value | - -<a name="Util.isFalse"></a> - -### Util.isFalse(attrValue) ⇒ <code>boolean</code> -SFMC accepts multiple false values for Boolean attributes for which we are checking here - -**Kind**: static method of [<code>Util</code>](#Util) -**Returns**: <code>boolean</code> - attribute value == false ? true : false - -| Param | Type | Description | -| --- | --- | --- | -| attrValue | <code>\*</code> | value | - -<a name="Util.getDefaultProperties"></a> - -### Util.getDefaultProperties() ⇒ <code>object</code> -defines how the properties.json should look like -used for creating a template and for checking if variables are set - -**Kind**: static method of [<code>Util</code>](#Util) -**Returns**: <code>object</code> - default properties -<a name="Util.getRetrieveTypeChoices"></a> - -### Util.getRetrieveTypeChoices() ⇒ <code>Array.<string></code> -helper for getDefaultProperties() - -**Kind**: static method of [<code>Util</code>](#Util) -**Returns**: <code>Array.<string></code> - type choices -<a name="Util.checkProperties"></a> - -### Util.checkProperties(properties, [silent]) ⇒ <code>boolean</code> \| <code>Array.<String></code> -check if the config file is correctly formatted and has values - -**Kind**: static method of [<code>Util</code>](#Util) -**Returns**: <code>boolean</code> \| <code>Array.<String></code> - file structure ok OR list of fields to be fixed - -| Param | Type | Description | -| --- | --- | --- | -| properties | <code>object</code> | javascript object in .mcdevrc.json | -| [silent] | <code>boolean</code> | set to true for internal use w/o cli output | - -<a name="Util.metadataLogger"></a> - -### Util.metadataLogger(level, type, method, payload, [source]) ⇒ <code>void</code> -Logger helper for Metadata functions - -**Kind**: static method of [<code>Util</code>](#Util) - -| Param | Type | Description | -| --- | --- | --- | -| level | <code>String</code> | of log (error, info, warn) | -| type | <code>String</code> | of metadata being referenced | -| method | <code>String</code> | name which log was called from | -| payload | <code>\*</code> | generic object which details the error | -| [source] | <code>String</code> | key/id of metadata which relates to error | - -<a name="Util.replaceByObject"></a> - -### Util.replaceByObject(str, obj) ⇒ <code>String</code> \| <code>Object</code> -replaces values in a JSON object string, based on a series of -key-value pairs (obj) - -**Kind**: static method of [<code>Util</code>](#Util) -**Returns**: <code>String</code> \| <code>Object</code> - replaced version of str - -| Param | Type | Description | -| --- | --- | --- | -| str | <code>String</code> \| <code>Object</code> | JSON object or its stringified version, which has values to be replaced | -| obj | [<code>TemplateMap</code>](#TemplateMap) | key value object which contains keys to be replaced and values to be replaced with | - -<a name="Util.inverseGet"></a> - -### Util.inverseGet(objs, val) ⇒ <code>String</code> -get key of an object based on the first matching value - -**Kind**: static method of [<code>Util</code>](#Util) -**Returns**: <code>String</code> - key - -| Param | Type | Description | -| --- | --- | --- | -| objs | <code>Object</code> | object of objects to be searched | -| val | <code>String</code> | value to be searched for | - -<a name="Util.getMetadataHierachy"></a> - -### Util.getMetadataHierachy(metadataTypes) ⇒ <code>Array.<String></code> -Returns Order in which metadata needs to be retrieved/deployed - -**Kind**: static method of [<code>Util</code>](#Util) -**Returns**: <code>Array.<String></code> - retrieve/deploy order as array - -| Param | Type | Description | -| --- | --- | --- | -| metadataTypes | <code>Array.<String></code> | which should be retrieved/deployed | - -<a name="Util.getETClient"></a> - -### Util.getETClient(buObject) ⇒ [<code>Promise.<ET\_Client></code>](#ET_Client) -signs in with SFMC - -**Kind**: static method of [<code>Util</code>](#Util) -**Returns**: [<code>Promise.<ET\_Client></code>](#ET_Client) - auth object - -| Param | Type | Description | -| --- | --- | --- | -| buObject | <code>BuObject</code> | properties for auth | - -<a name="Util.getETClient..myClient"></a> - -#### getETClient~myClient : [<code>ET\_Client</code>](#ET_Client) -**Kind**: inner constant of [<code>getETClient</code>](#Util.getETClient) -<a name="Util.getFromCache"></a> - -### Util.getFromCache(cache, metadataType, searchValue, searchField, returnField) ⇒ <code>String</code> -standardized method for getting data from cache. - -**Kind**: static method of [<code>Util</code>](#Util) -**Returns**: <code>String</code> - unique user definable metadata key (usually external/customer key) - -| Param | Type | Description | -| --- | --- | --- | -| cache | <code>Object</code> | data retrieved from sfmc instance | -| metadataType | <code>String</code> | metadata type ie. query | -| searchValue | <code>String</code> | unique identifier of metadata being looked for | -| searchField | <code>String</code> | field name (key in object) which contains the unique identifer | -| returnField | <code>String</code> | field which should be returned | - -<a name="Util.resolveObjPath"></a> - -### Util.resolveObjPath(path, obj) ⇒ <code>any</code> -let's you dynamically walk down an object and get a value - -**Kind**: static method of [<code>Util</code>](#Util) -**Returns**: <code>any</code> - value of obj.path - -| Param | Type | Description | -| --- | --- | --- | -| path | <code>String</code> | 'fieldA.fieldB.fieldC' | -| obj | <code>Object</code> | some parent object | - -<a name="Util.getListObjectIdFromCache"></a> - -### Util.getListObjectIdFromCache(cache, listPathName, returnField) ⇒ <code>String</code> -standardized method for getting data from cache - adapted for special case of lists -! keeping this in util/util.js rather than in metadataTypes/List.js to avoid potential circular dependencies - -**Kind**: static method of [<code>Util</code>](#Util) -**Returns**: <code>String</code> - unique ObjectId of list - -| Param | Type | Description | -| --- | --- | --- | -| cache | <code>Object</code> | data retrieved from sfmc instance | -| listPathName | <code>String</code> | folderPath/ListName combo of list | -| returnField | <code>String</code> | ObjectID or ID | - -<a name="Util.getListPathNameFromCache"></a> - -### Util.getListPathNameFromCache(cache, searchValue, searchField) ⇒ <code>String</code> -standardized method for getting data from cache - adapted for special case of lists -! keeping this in util/util.js rather than in metadataTypes/List.js to avoid potential circular dependencies - -**Kind**: static method of [<code>Util</code>](#Util) -**Returns**: <code>String</code> - unique folderPath/ListName combo of list - -| Param | Type | Description | -| --- | --- | --- | -| cache | <code>Object</code> | data retrieved from sfmc instance | -| searchValue | <code>String</code> | unique identifier of metadata being looked for | -| searchField | <code>String</code> | ObjectID or ID | - -<a name="Util.retryOnError"></a> - -### Util.retryOnError(errorMsg, callback, [silentError], [retries]) ⇒ <code>Promise.<void></code> -retry on network issues - -**Kind**: static method of [<code>Util</code>](#Util) -**Returns**: <code>Promise.<void></code> - - - -| Param | Type | Default | Description | -| --- | --- | --- | --- | -| errorMsg | <code>String</code> | | what to print behind "Connection error. " | -| callback | <code>function</code> | | what to try executing | -| [silentError] | <code>Boolean</code> | <code>false</code> | prints retry messages to log only; default=false | -| [retries] | <code>Number</code> | <code>1</code> | number of retries; default=1 | - -<a name="Util.execSync"></a> - -### Util.execSync(cmd, [args]) ⇒ <code>undefined</code> -helper to run other commands as if run manually by user - -**Kind**: static method of [<code>Util</code>](#Util) - -| Param | Type | Description | -| --- | --- | --- | -| cmd | <code>string</code> | to be executed command | -| [args] | <code>Array.<string></code> | list of arguments | - -<a name="MetadataTypeDefinitions"></a> - -## MetadataTypeDefinitions -Provides access to all metadataType classes - -**Kind**: global constant -<a name="MetadataTypeInfo"></a> - -## MetadataTypeInfo -Provides access to all metadataType classes - -**Kind**: global constant -<a name="mcdev"></a> - -## mcdev -sample file on how to retrieve a simple changelog to use in GUIs or automated processing of any kind - -**Kind**: global constant -**Example** -```js -[{ - name: 'deName', - key: 'deKey', - t: 'dataExtension', - cd: '2020-05-06T00:16:00.737', - cb: 'name of creator', - ld: '2020-05-06T00:16:00.737', - lb: 'name of lastmodified' - }] -``` -<a name="BusinessUnit"></a> - -## BusinessUnit -Helper that handles retrieval of BU info - -**Kind**: global constant -<a name="BusinessUnit.refreshBUProperties"></a> - -### BusinessUnit.refreshBUProperties(properties, credentialsName) ⇒ <code>Promise.<boolean></code> -Refreshes BU names and ID's from MC instance - -**Kind**: static method of [<code>BusinessUnit</code>](#BusinessUnit) -**Returns**: <code>Promise.<boolean></code> - success of refresh - -| Param | Type | Description | -| --- | --- | --- | -| properties | <code>object</code> | current properties that have to be refreshed | -| credentialsName | <code>string</code> | identifying name of the installed package / project | - -<a name="Cli"></a> - -## Cli -CLI helper class - -**Kind**: global constant - -* [Cli](#Cli) - * [.initMcdevConfig([skipInteraction])](#Cli.initMcdevConfig) ⇒ <code>Promise.<boolean></code> - * [.addExtraCredential(properties, [skipInteraction])](#Cli.addExtraCredential) ⇒ <code>Promise.<void></code> - * [.updateCredential(properties, credName, [skipInteraction])](#Cli.updateCredential) ⇒ <code>Promise.<Boolean></code> - * [.getCredentialObject(properties, target, [isCredentialOnly], [allowAll])](#Cli.getCredentialObject) ⇒ <code>Promise.<Util.BuObject></code> - * [._selectBU(properties, [credential], [isCredentialOnly], [allowAll])](#Cli._selectBU) ⇒ <code>Promise.<Array></code> - * [._setCredential(properties, [credName], [skipInteraction])](#Cli._setCredential) ⇒ <code>Promise.<(boolean\|String)></code> - * [._askCredentials(properties, [credName])](#Cli._askCredentials) ⇒ <code>Promise.<Object></code> - * [.selectTypes(properties, [setTypesArr])](#Cli.selectTypes) ⇒ <code>Promise.<void></code> - * [._summarizeSubtypes(responses, type)](#Cli._summarizeSubtypes) ⇒ <code>void</code> - * [.explainTypes()](#Cli.explainTypes) ⇒ <code>void</code> - -<a name="Cli.initMcdevConfig"></a> - -### Cli.initMcdevConfig([skipInteraction]) ⇒ <code>Promise.<boolean></code> -used when initially setting up a project. -loads default config and adds first credential - -**Kind**: static method of [<code>Cli</code>](#Cli) -**Returns**: <code>Promise.<boolean></code> - success of init - -| Param | Type | Description | -| --- | --- | --- | -| [skipInteraction] | <code>Object</code> | signals what to insert automatically for things usually asked via wizard | -| skipInteraction.clientId | <code>String</code> | client id of installed package | -| skipInteraction.clientSecret | <code>String</code> | client id of installed package | -| skipInteraction.tenant | <code>String</code> | client id of installed package | -| skipInteraction.credentialsName | <code>String</code> | how you would like the credential to be named | - -<a name="Cli.addExtraCredential"></a> - -### Cli.addExtraCredential(properties, [skipInteraction]) ⇒ <code>Promise.<void></code> -Extends template file for properties.json - -**Kind**: static method of [<code>Cli</code>](#Cli) -**Returns**: <code>Promise.<void></code> - - - -| Param | Type | Description | -| --- | --- | --- | -| properties | <code>Object</code> | config file's json | -| properties.credentials | <code>Object</code> | list of existing credentials | -| [skipInteraction] | <code>Object</code> | signals what to insert automatically for things usually asked via wizard | -| skipInteraction.clientId | <code>String</code> | client id of installed package | -| skipInteraction.clientSecret | <code>String</code> | client id of installed package | -| skipInteraction.tenant | <code>String</code> | client id of installed package | -| skipInteraction.credentialsName | <code>String</code> | how you would like the credential to be named | - -<a name="Cli.updateCredential"></a> - -### Cli.updateCredential(properties, credName, [skipInteraction]) ⇒ <code>Promise.<Boolean></code> -Extends template file for properties.json -update credentials - -**Kind**: static method of [<code>Cli</code>](#Cli) -**Returns**: <code>Promise.<Boolean></code> - success of update - -| Param | Type | Description | -| --- | --- | --- | -| properties | <code>object</code> | config file's json | -| credName | <code>string</code> | name of credential that needs updating | -| [skipInteraction] | <code>Object</code> | signals what to insert automatically for things usually asked via wizard | -| skipInteraction.clientId | <code>String</code> | client id of installed package | -| skipInteraction.clientSecret | <code>String</code> | client id of installed package | -| skipInteraction.tenant | <code>String</code> | client id of installed package | -| skipInteraction.credentialsName | <code>String</code> | how you would like the credential to be named | - -<a name="Cli.getCredentialObject"></a> - -### Cli.getCredentialObject(properties, target, [isCredentialOnly], [allowAll]) ⇒ <code>Promise.<Util.BuObject></code> -Returns Object with parameters required for accessing API - -**Kind**: static method of [<code>Cli</code>](#Cli) -**Returns**: <code>Promise.<Util.BuObject></code> - credential to be used for Business Unit - -| Param | Type | Description | -| --- | --- | --- | -| properties | <code>Object</code> | object of all configuration including credentials | -| target | <code>String</code> | code of BU to use | -| [isCredentialOnly] | <code>boolean</code> \| <code>string</code> | true:don't ask for BU | string: name of BU | -| [allowAll] | <code>boolean</code> | Offer ALL as option in BU selection | - -<a name="Cli._selectBU"></a> - -### Cli.\_selectBU(properties, [credential], [isCredentialOnly], [allowAll]) ⇒ <code>Promise.<Array></code> -helps select the right credential in case of bad initial input - -**Kind**: static method of [<code>Cli</code>](#Cli) -**Returns**: <code>Promise.<Array></code> - selected credential/BU combo - -| Param | Type | Description | -| --- | --- | --- | -| properties | <code>object</code> | config file's json | -| [credential] | <code>string</code> | name of valid credential | -| [isCredentialOnly] | <code>boolean</code> | don't ask for BU if true | -| [allowAll] | <code>boolean</code> | Offer ALL as option in BU selection | - -<a name="Cli._setCredential"></a> - -### Cli.\_setCredential(properties, [credName], [skipInteraction]) ⇒ <code>Promise.<(boolean\|String)></code> -helper around _askCredentials - -**Kind**: static method of [<code>Cli</code>](#Cli) -**Returns**: <code>Promise.<(boolean\|String)></code> - success of refresh or credential name - -| Param | Type | Description | -| --- | --- | --- | -| properties | <code>object</code> | from config file | -| [credName] | <code>string</code> | name of credential that needs updating | -| [skipInteraction] | <code>Object</code> | signals what to insert automatically for things usually asked via wizard | -| skipInteraction.clientId | <code>String</code> | client id of installed package | -| skipInteraction.clientSecret | <code>String</code> | client id of installed package | -| skipInteraction.tenant | <code>String</code> | client id of installed package | -| skipInteraction.credentialsName | <code>String</code> | how you would like the credential to be named | - -<a name="Cli._askCredentials"></a> - -### Cli.\_askCredentials(properties, [credName]) ⇒ <code>Promise.<Object></code> -helper for addExtraCredential() - -**Kind**: static method of [<code>Cli</code>](#Cli) -**Returns**: <code>Promise.<Object></code> - credential info - -| Param | Type | Description | -| --- | --- | --- | -| properties | <code>Object</code> | from config file | -| [credName] | <code>string</code> | name of credential that needs updating | - -<a name="Cli.selectTypes"></a> - -### Cli.selectTypes(properties, [setTypesArr]) ⇒ <code>Promise.<void></code> -allows updating the metadata types that shall be retrieved - -**Kind**: static method of [<code>Cli</code>](#Cli) -**Returns**: <code>Promise.<void></code> - - - -| Param | Type | Description | -| --- | --- | --- | -| properties | <code>object</code> | config file's json | -| properties.metaDataTypes | <code>object</code> | - | -| properties.metaDataTypes.retrieve | <code>Array.<String></code> | list of currently retrieved types | -| [setTypesArr] | <code>Array.<String></code> | skip user prompt and overwrite with this list if given | - -<a name="Cli._summarizeSubtypes"></a> - -### Cli.\_summarizeSubtypes(responses, type) ⇒ <code>void</code> -helper for this.selectTypes() that converts subtypes back to main type if all and only defaults were selected -this keeps the config automatically upgradable when we add new subtypes or change what is selected by default - -**Kind**: static method of [<code>Cli</code>](#Cli) - -| Param | Type | Description | -| --- | --- | --- | -| responses | <code>Object</code> | wrapper object for respones | -| responses.selectedTypes | <code>Array.<String></code> | what types the user selected | -| type | <code>String</code> | metadata type | - -<a name="Cli.explainTypes"></a> - -### Cli.explainTypes() ⇒ <code>void</code> -shows metadata type descriptions - -**Kind**: static method of [<code>Cli</code>](#Cli) -**Returns**: <code>void</code> - - -<a name="DevOps"></a> - -## DevOps -DevOps helper class - -**Kind**: global constant - -* [DevOps](#DevOps) - * [.createDeltaPkg(properties, [range], [saveToDeployDir], [filterPaths])](#DevOps.createDeltaPkg) ⇒ <code>Promise.<Object></code> - * [.document(directory, jsonReport)](#DevOps.document) ⇒ <code>void</code> - -<a name="DevOps.createDeltaPkg"></a> - -### DevOps.createDeltaPkg(properties, [range], [saveToDeployDir], [filterPaths]) ⇒ <code>Promise.<Object></code> -Extracts the delta between a commit and the current state for deployment. -Interactive commit selection if no commits are passed. - -**Kind**: static method of [<code>DevOps</code>](#DevOps) -**Returns**: <code>Promise.<Object></code> - - - -| Param | Type | Description | -| --- | --- | --- | -| properties | <code>Object</code> | central properties object | -| [range] | <code>String</code> | git commit range | -| [saveToDeployDir] | <code>boolean</code> | if true, copy metadata changes into deploy directory | -| [filterPaths] | <code>String</code> | filter file paths that start with any specified path (comma separated) | - -<a name="DevOps.document"></a> - -### DevOps.document(directory, jsonReport) ⇒ <code>void</code> -create markdown file for deployment listing - -**Kind**: static method of [<code>DevOps</code>](#DevOps) - -| Param | Type | Description | -| --- | --- | --- | -| directory | <code>String</code> | - | -| jsonReport | <code>Object</code> | - | - -<a name="File"></a> - -## File -File extends fs-extra. It adds logger and util methods for file handling - -**Kind**: global constant - -* [File](#File) - * [.copyFile(from, to)](#File.copyFile) ⇒ <code>Object</code> - * [.filterIllegalPathChars(path)](#File.filterIllegalPathChars) ⇒ <code>String</code> - * [.filterIllegalFilenames(filename)](#File.filterIllegalFilenames) ⇒ <code>String</code> - * [.reverseFilterIllegalFilenames(filename)](#File.reverseFilterIllegalFilenames) ⇒ <code>String</code> - * [.normalizePath(denormalizedPath)](#File.normalizePath) ⇒ <code>String</code> - * [.writeJSONToFile(directory, filename, content)](#File.writeJSONToFile) ⇒ <code>Promise</code> - * [.writePrettyToFile(directory, filename, filetype, content, [templateVariables])](#File.writePrettyToFile) ⇒ <code>Promise.<Boolean></code> - * [._beautify_sql(content)](#File._beautify_sql) ⇒ <code>String</code> - * [._beautify_prettier(directory, filename, filetype, content)](#File._beautify_prettier) ⇒ <code>String</code> - * [.writeToFile(directory, filename, filetype, content, [encoding])](#File.writeToFile) ⇒ <code>Promise.<Boolean></code> - * [.readJSONFile(directory, filename, sync, cleanPath)](#File.readJSONFile) ⇒ <code>Promise</code> \| <code>Object</code> - * [.readFile(directory, filename, filetype, [encoding])](#File.readFile) ⇒ <code>Promise.<String></code> - * [.readDirectories(directory, depth, [includeStem], [_stemLength])](#File.readDirectories) ⇒ <code>Promise.<Array.<String>></code> - * [.readDirectoriesSync(directory, [depth], [includeStem], [_stemLength])](#File.readDirectoriesSync) ⇒ <code>Array.<String></code> - * [.loadConfigFile([silent])](#File.loadConfigFile) ⇒ <code>Object</code> - * [.saveConfigFile(properties)](#File.saveConfigFile) ⇒ <code>Promise.<void></code> - * [.initPrettier([filetype])](#File.initPrettier) ⇒ <code>Promise.<Boolean></code> - -<a name="File.copyFile"></a> - -### File.copyFile(from, to) ⇒ <code>Object</code> -copies a file from one path to another - -**Kind**: static method of [<code>File</code>](#File) -**Returns**: <code>Object</code> - - results object - -| Param | Type | Description | -| --- | --- | --- | -| from | <code>String</code> | full filepath including name of existing file | -| to | <code>String</code> | full filepath including name where file should go | - -<a name="File.filterIllegalPathChars"></a> - -### File.filterIllegalPathChars(path) ⇒ <code>String</code> -makes sure Windows accepts path names - -**Kind**: static method of [<code>File</code>](#File) -**Returns**: <code>String</code> - - corrected string - -| Param | Type | Description | -| --- | --- | --- | -| path | <code>String</code> | filename or path | - -<a name="File.filterIllegalFilenames"></a> - -### File.filterIllegalFilenames(filename) ⇒ <code>String</code> -makes sure Windows accepts file names - -**Kind**: static method of [<code>File</code>](#File) -**Returns**: <code>String</code> - - corrected string - -| Param | Type | Description | -| --- | --- | --- | -| filename | <code>String</code> | filename or path | - -<a name="File.reverseFilterIllegalFilenames"></a> - -### File.reverseFilterIllegalFilenames(filename) ⇒ <code>String</code> -makes sure Windows accepts file names - -**Kind**: static method of [<code>File</code>](#File) -**Returns**: <code>String</code> - - corrected string - -| Param | Type | Description | -| --- | --- | --- | -| filename | <code>String</code> | filename or path | - -<a name="File.normalizePath"></a> - -### File.normalizePath(denormalizedPath) ⇒ <code>String</code> -Takes various types of path strings and formats into a platform specific path - -**Kind**: static method of [<code>File</code>](#File) -**Returns**: <code>String</code> - Path strings - -| Param | Type | Description | -| --- | --- | --- | -| denormalizedPath | <code>string</code> \| <code>Array.<string></code> | directory the file will be written to | - -<a name="File.writeJSONToFile"></a> - -### File.writeJSONToFile(directory, filename, content) ⇒ <code>Promise</code> -Saves json content to a file in the local file system. Will create the parent directory if it does not exist - -**Kind**: static method of [<code>File</code>](#File) -**Returns**: <code>Promise</code> - Promise - -| Param | Type | Description | -| --- | --- | --- | -| directory | <code>string</code> \| <code>Array.<string></code> | directory the file will be written to | -| filename | <code>String</code> | name of the file without '.json' ending | -| content | <code>Object</code> | filecontent | - -<a name="File.writePrettyToFile"></a> - -### File.writePrettyToFile(directory, filename, filetype, content, [templateVariables]) ⇒ <code>Promise.<Boolean></code> -Saves beautified files in the local file system. Will create the parent directory if it does not exist -! Important: run 'await File.initPrettier()' in your MetadataType.retrieve() once before hitting this - -**Kind**: static method of [<code>File</code>](#File) -**Returns**: <code>Promise.<Boolean></code> - Promise - -| Param | Type | Description | -| --- | --- | --- | -| directory | <code>string</code> \| <code>Array.<string></code> | directory the file will be written to | -| filename | <code>String</code> | name of the file without suffix | -| filetype | <code>String</code> | filetype ie. JSON or SSJS | -| content | <code>String</code> | filecontent | -| [templateVariables] | <code>Object</code> | templating variables to be replaced in the metadata | - -<a name="File._beautify_sql"></a> - -### File.\_beautify\_sql(content) ⇒ <code>String</code> -helper for writePrettyToFile, applying sql formatting onto given stringified content - -**Kind**: static method of [<code>File</code>](#File) -**Returns**: <code>String</code> - original string on error; formatted string on success - -| Param | Type | Description | -| --- | --- | --- | -| content | <code>String</code> | filecontent | - -<a name="File._beautify_prettier"></a> - -### File.\_beautify\_prettier(directory, filename, filetype, content) ⇒ <code>String</code> -helper for writePrettyToFile, applying prettier onto given stringified content -! Important: run 'await File.initPrettier()' in your MetadataType.retrieve() once before hitting this - -**Kind**: static method of [<code>File</code>](#File) -**Returns**: <code>String</code> - original string on error; formatted string on success - -| Param | Type | Description | -| --- | --- | --- | -| directory | <code>string</code> \| <code>Array.<string></code> | directory the file will be written to | -| filename | <code>String</code> | name of the file without suffix | -| filetype | <code>String</code> | filetype ie. JSON or SSJS | -| content | <code>String</code> | filecontent | - -<a name="File.writeToFile"></a> - -### File.writeToFile(directory, filename, filetype, content, [encoding]) ⇒ <code>Promise.<Boolean></code> -Saves text content to a file in the local file system. Will create the parent directory if it does not exist - -**Kind**: static method of [<code>File</code>](#File) -**Returns**: <code>Promise.<Boolean></code> - Promise - -| Param | Type | Description | -| --- | --- | --- | -| directory | <code>string</code> \| <code>Array.<string></code> | directory the file will be written to | -| filename | <code>String</code> | name of the file without '.json' ending | -| filetype | <code>String</code> | filetype suffix | -| content | <code>String</code> | filecontent | -| [encoding] | <code>Object</code> | added for certain file types (like images) | - -<a name="File.readJSONFile"></a> - -### File.readJSONFile(directory, filename, sync, cleanPath) ⇒ <code>Promise</code> \| <code>Object</code> -Saves json content to a file in the local file system. Will create the parent directory if it does not exist - -**Kind**: static method of [<code>File</code>](#File) -**Returns**: <code>Promise</code> \| <code>Object</code> - Promise or JSON object depending on if async or not - -| Param | Type | Description | -| --- | --- | --- | -| directory | <code>String</code> \| <code>Array.<String></code> | directory where the file is stored | -| filename | <code>String</code> | name of the file without '.json' ending | -| sync | <code>Boolean</code> | should execute sync (default is async) | -| cleanPath | <code>Boolean</code> | should execute sync (default is true) | - -<a name="File.readFile"></a> - -### File.readFile(directory, filename, filetype, [encoding]) ⇒ <code>Promise.<String></code> -reads file from local file system. - -**Kind**: static method of [<code>File</code>](#File) -**Returns**: <code>Promise.<String></code> - file contents - -| Param | Type | Default | Description | -| --- | --- | --- | --- | -| directory | <code>String</code> \| <code>Array.<String></code> | | directory where the file is stored | -| filename | <code>String</code> | | name of the file without '.json' ending | -| filetype | <code>String</code> | | filetype suffix | -| [encoding] | <code>String</code> | <code>'utf8'</code> | read file with encoding (defaults to utf-8) | - -<a name="File.readDirectories"></a> - -### File.readDirectories(directory, depth, [includeStem], [_stemLength]) ⇒ <code>Promise.<Array.<String>></code> -reads directories to a specific depth returning an array -of file paths to be iterated over - -**Kind**: static method of [<code>File</code>](#File) -**Returns**: <code>Promise.<Array.<String>></code> - array of fully defined file paths - -| Param | Type | Description | -| --- | --- | --- | -| directory | <code>String</code> | directory to checkin | -| depth | <code>Number</code> | how many levels to check (1 base) | -| [includeStem] | <code>Boolean</code> | include the parent directory in the response | -| [_stemLength] | <code>Number</code> | set recursively for subfolders. do not set manually! | - -**Example** -```js -['deploy/mcdev/bu1'] -``` -<a name="File.readDirectoriesSync"></a> - -### File.readDirectoriesSync(directory, [depth], [includeStem], [_stemLength]) ⇒ <code>Array.<String></code> -reads directories to a specific depth returning an array -of file paths to be iterated over using sync api (required in constructors) - -**Kind**: static method of [<code>File</code>](#File) -**Returns**: <code>Array.<String></code> - array of fully defined file paths - -| Param | Type | Description | -| --- | --- | --- | -| directory | <code>String</code> | directory to checkin | -| [depth] | <code>Number</code> | how many levels to check (1 base) | -| [includeStem] | <code>Boolean</code> | include the parent directory in the response | -| [_stemLength] | <code>Number</code> | set recursively for subfolders. do not set manually! | - -**Example** -```js -['deploy/mcdev/bu1'] -``` -<a name="File.loadConfigFile"></a> - -### File.loadConfigFile([silent]) ⇒ <code>Object</code> -loads central properties from config file - -**Kind**: static method of [<code>File</code>](#File) -**Returns**: <code>Object</code> - central properties object - -| Param | Type | Description | -| --- | --- | --- | -| [silent] | <code>Boolean</code> | omit throwing errors and print messages; assuming not silent if not set | - -<a name="File.saveConfigFile"></a> - -### File.saveConfigFile(properties) ⇒ <code>Promise.<void></code> -helper that splits the config back into auth & config parts to save them separately - -**Kind**: static method of [<code>File</code>](#File) -**Returns**: <code>Promise.<void></code> - - - -| Param | Type | Description | -| --- | --- | --- | -| properties | <code>Object</code> | central properties object | - -<a name="File.initPrettier"></a> - -### File.initPrettier([filetype]) ⇒ <code>Promise.<Boolean></code> -Initalises Prettier formatting lib async. - -**Kind**: static method of [<code>File</code>](#File) -**Returns**: <code>Promise.<Boolean></code> - success of config load - -| Param | Type | Default | Description | -| --- | --- | --- | --- | -| [filetype] | <code>String</code> | <code>'html'</code> | filetype ie. JSON or SSJS | - -<a name="Init"></a> - -## Init -CLI helper class - -**Kind**: global constant - -* [Init](#Init) - * [.fixMcdevConfig(properties)](#Init.fixMcdevConfig) ⇒ <code>Promise.<Boolean></code> - * [.createIdeConfigFiles()](#Init.createIdeConfigFiles) ⇒ <code>Promise.<Boolean></code> - * [._updateLeaf(propertiersCur, defaultPropsCur, fieldName)](#Init._updateLeaf) ⇒ <code>void</code> - * [._createIdeConfigFile(fileNameArr, [fileContent])](#Init._createIdeConfigFile) ⇒ <code>Promise.<Boolean></code> - * [.initGitRepo([skipInteraction])](#Init.initGitRepo) ⇒ <code>Promise.<{status:String, repoName:String}></code> - * [.gitPush([skipInteraction])](#Init.gitPush) ⇒ <code>void</code> - * [._addGitRemote([skipInteraction])](#Init._addGitRemote) ⇒ <code>String</code> - * [._updateGitConfigUser([skipInteraction])](#Init._updateGitConfigUser) ⇒ <code>void</code> - * [._getGitConfigUser()](#Init._getGitConfigUser) ⇒ <code>Promise.<{'user.name': String, 'user.email': String}></code> - * [.initProject(properties, credentialsName, [skipInteraction])](#Init.initProject) ⇒ <code>Promise.<void></code> - * [._downloadAllBUs(bu, gitStatus, [skipInteraction])](#Init._downloadAllBUs) ⇒ <code>Promise.<void></code> - * [.upgradeProject(properties, [initial], [repoName])](#Init.upgradeProject) ⇒ <code>Promise.<Boolean></code> - * [._getMissingCredentials(properties)](#Init._getMissingCredentials) ⇒ <code>Array.<String></code> - * [.installDependencies([repoName])](#Init.installDependencies) ⇒ <code>Promise.<Boolean></code> - * [._getDefaultPackageJson([currentContent])](#Init._getDefaultPackageJson) ⇒ <code>Promise.<{script: Object, author: String, license: String}></code> - -<a name="Init.fixMcdevConfig"></a> - -### Init.fixMcdevConfig(properties) ⇒ <code>Promise.<Boolean></code> -helper method for this.upgradeProject that upgrades project config if needed - -**Kind**: static method of [<code>Init</code>](#Init) -**Returns**: <code>Promise.<Boolean></code> - returns true if worked without errors - -| Param | Type | Description | -| --- | --- | --- | -| properties | <code>Object</code> | config file's json | - -<a name="Init.createIdeConfigFiles"></a> - -### Init.createIdeConfigFiles() ⇒ <code>Promise.<Boolean></code> -handles creation/update of all config file from the boilerplate - -**Kind**: static method of [<code>Init</code>](#Init) -**Returns**: <code>Promise.<Boolean></code> - status of config file creation -<a name="Init._updateLeaf"></a> - -### Init.\_updateLeaf(propertiersCur, defaultPropsCur, fieldName) ⇒ <code>void</code> -recursive helper for _fixMcdevConfig that adds missing settings - -**Kind**: static method of [<code>Init</code>](#Init) - -| Param | Type | Description | -| --- | --- | --- | -| propertiersCur | <code>Object</code> | current sub-object of project settings | -| defaultPropsCur | <code>Object</code> | current sub-object of default settings | -| fieldName | <code>String</code> | dot-concatenated object-path that needs adding | - -<a name="Init._createIdeConfigFile"></a> - -### Init.\_createIdeConfigFile(fileNameArr, [fileContent]) ⇒ <code>Promise.<Boolean></code> -handles creation/update of one config file from the boilerplate at a time - -**Kind**: static method of [<code>Init</code>](#Init) -**Returns**: <code>Promise.<Boolean></code> - install successful or error occured - -| Param | Type | Description | -| --- | --- | --- | -| fileNameArr | <code>Array.<String></code> | 0: path, 1: filename, 2: extension with dot | -| [fileContent] | <code>String</code> | in case we cannot copy files 1:1 this can be used to pass in content | - -<a name="Init.initGitRepo"></a> - -### Init.initGitRepo([skipInteraction]) ⇒ <code>Promise.<{status:String, repoName:String}></code> -check if git repo exists and otherwise create one - -**Kind**: static method of [<code>Init</code>](#Init) -**Returns**: <code>Promise.<{status:String, repoName:String}></code> - success flag - -| Param | Type | Description | -| --- | --- | --- | -| [skipInteraction] | <code>Object</code> | signals what to insert automatically for things usually asked via wizard | -| skipInteraction.gitRemoteUrl | <code>String</code> | URL of Git remote server | - -<a name="Init.gitPush"></a> - -### Init.gitPush([skipInteraction]) ⇒ <code>void</code> -offer to push the new repo straight to the server - -**Kind**: static method of [<code>Init</code>](#Init) - -| Param | Type | Description | -| --- | --- | --- | -| [skipInteraction] | <code>Boolean</code> \| <code>Object</code> | signals what to insert automatically for things usually asked via wizard | - -<a name="Init._addGitRemote"></a> - -### Init.\_addGitRemote([skipInteraction]) ⇒ <code>String</code> -offers to add the git remote origin - -**Kind**: static method of [<code>Init</code>](#Init) -**Returns**: <code>String</code> - repo name (optionally) - -| Param | Type | Description | -| --- | --- | --- | -| [skipInteraction] | <code>Object</code> | signals what to insert automatically for things usually asked via wizard | -| skipInteraction.gitRemoteUrl | <code>String</code> | URL of Git remote server | - -<a name="Init._updateGitConfigUser"></a> - -### Init.\_updateGitConfigUser([skipInteraction]) ⇒ <code>void</code> -checks global config and ask to config the user info and then store it locally - -**Kind**: static method of [<code>Init</code>](#Init) - -| Param | Type | Description | -| --- | --- | --- | -| [skipInteraction] | <code>Object</code> \| <code>Boolean</code> | signals what to insert automatically for things usually asked via wizard | - -<a name="Init._getGitConfigUser"></a> - -### Init.\_getGitConfigUser() ⇒ <code>Promise.<{'user.name': String, 'user.email': String}></code> -retrieves the global user.name and user.email values - -**Kind**: static method of [<code>Init</code>](#Init) -**Returns**: <code>Promise.<{'user.name': String, 'user.email': String}></code> - user.name and user.email -<a name="Init.initProject"></a> - -### Init.initProject(properties, credentialsName, [skipInteraction]) ⇒ <code>Promise.<void></code> -Creates template file for properties.json - -**Kind**: static method of [<code>Init</code>](#Init) -**Returns**: <code>Promise.<void></code> - - - -| Param | Type | Description | -| --- | --- | --- | -| properties | <code>Object</code> | config file's json | -| credentialsName | <code>string</code> | identifying name of the installed package / project | -| [skipInteraction] | <code>Object</code> | signals what to insert automatically for things usually asked via wizard | -| skipInteraction.clientId | <code>String</code> | client id of installed package | -| skipInteraction.clientSecret | <code>String</code> | client id of installed package | -| skipInteraction.tenant | <code>String</code> | client id of installed package | -| skipInteraction.credentialsName | <code>String</code> | how you would like the credential to be named | -| skipInteraction.gitRemoteUrl | <code>String</code> | URL of Git remote server | - -<a name="Init._downloadAllBUs"></a> - -### Init.\_downloadAllBUs(bu, gitStatus, [skipInteraction]) ⇒ <code>Promise.<void></code> -helper for this.initProject() - -**Kind**: static method of [<code>Init</code>](#Init) -**Returns**: <code>Promise.<void></code> - - - -| Param | Type | Description | -| --- | --- | --- | -| bu | <code>String</code> | cred/bu or cred/* or * | -| gitStatus | <code>String</code> | signals what state the git repo is in | -| [skipInteraction] | <code>Boolean</code> \| <code>Object</code> | signals what to insert automatically for things usually asked via wizard | - -<a name="Init.upgradeProject"></a> - -### Init.upgradeProject(properties, [initial], [repoName]) ⇒ <code>Promise.<Boolean></code> -wrapper around npm dependency & configuration file setup - -**Kind**: static method of [<code>Init</code>](#Init) -**Returns**: <code>Promise.<Boolean></code> - success flag - -| Param | Type | Description | -| --- | --- | --- | -| properties | <code>Object</code> | config file's json | -| [initial] | <code>Boolean</code> | print message if not part of initial setup | -| [repoName] | <code>String</code> | if git URL was provided earlier, the repo name was extracted to use it for npm init | - -<a name="Init._getMissingCredentials"></a> - -### Init.\_getMissingCredentials(properties) ⇒ <code>Array.<String></code> -finds credentials that are set up in config but not in auth file - -**Kind**: static method of [<code>Init</code>](#Init) -**Returns**: <code>Array.<String></code> - list of credential names - -| Param | Type | Description | -| --- | --- | --- | -| properties | <code>object</code> | javascript object in .mcdevrc.json | - -<a name="Init.installDependencies"></a> - -### Init.installDependencies([repoName]) ⇒ <code>Promise.<Boolean></code> -initiates npm project and then -takes care of loading the pre-configured dependency list -from the boilerplate directory to them as dev-dependencies - -**Kind**: static method of [<code>Init</code>](#Init) -**Returns**: <code>Promise.<Boolean></code> - install successful or error occured - -| Param | Type | Description | -| --- | --- | --- | -| [repoName] | <code>String</code> | if git URL was provided earlier, the repo name was extracted to use it for npm init | - -<a name="Init._getDefaultPackageJson"></a> - -### Init.\_getDefaultPackageJson([currentContent]) ⇒ <code>Promise.<{script: Object, author: String, license: String}></code> -ensure we have certain default values in our config - -**Kind**: static method of [<code>Init</code>](#Init) -**Returns**: <code>Promise.<{script: Object, author: String, license: String}></code> - extended currentContent - -| Param | Type | Description | -| --- | --- | --- | -| [currentContent] | <code>Object</code> | what was read from existing package.json file | - -<a name="Init"></a> - -## Init -CLI helper class - -**Kind**: global constant - -* [Init](#Init) - * [.fixMcdevConfig(properties)](#Init.fixMcdevConfig) ⇒ <code>Promise.<Boolean></code> - * [.createIdeConfigFiles()](#Init.createIdeConfigFiles) ⇒ <code>Promise.<Boolean></code> - * [._updateLeaf(propertiersCur, defaultPropsCur, fieldName)](#Init._updateLeaf) ⇒ <code>void</code> - * [._createIdeConfigFile(fileNameArr, [fileContent])](#Init._createIdeConfigFile) ⇒ <code>Promise.<Boolean></code> - * [.initGitRepo([skipInteraction])](#Init.initGitRepo) ⇒ <code>Promise.<{status:String, repoName:String}></code> - * [.gitPush([skipInteraction])](#Init.gitPush) ⇒ <code>void</code> - * [._addGitRemote([skipInteraction])](#Init._addGitRemote) ⇒ <code>String</code> - * [._updateGitConfigUser([skipInteraction])](#Init._updateGitConfigUser) ⇒ <code>void</code> - * [._getGitConfigUser()](#Init._getGitConfigUser) ⇒ <code>Promise.<{'user.name': String, 'user.email': String}></code> - * [.initProject(properties, credentialsName, [skipInteraction])](#Init.initProject) ⇒ <code>Promise.<void></code> - * [._downloadAllBUs(bu, gitStatus, [skipInteraction])](#Init._downloadAllBUs) ⇒ <code>Promise.<void></code> - * [.upgradeProject(properties, [initial], [repoName])](#Init.upgradeProject) ⇒ <code>Promise.<Boolean></code> - * [._getMissingCredentials(properties)](#Init._getMissingCredentials) ⇒ <code>Array.<String></code> - * [.installDependencies([repoName])](#Init.installDependencies) ⇒ <code>Promise.<Boolean></code> - * [._getDefaultPackageJson([currentContent])](#Init._getDefaultPackageJson) ⇒ <code>Promise.<{script: Object, author: String, license: String}></code> - -<a name="Init.fixMcdevConfig"></a> - -### Init.fixMcdevConfig(properties) ⇒ <code>Promise.<Boolean></code> -helper method for this.upgradeProject that upgrades project config if needed - -**Kind**: static method of [<code>Init</code>](#Init) -**Returns**: <code>Promise.<Boolean></code> - returns true if worked without errors - -| Param | Type | Description | -| --- | --- | --- | -| properties | <code>Object</code> | config file's json | - -<a name="Init.createIdeConfigFiles"></a> - -### Init.createIdeConfigFiles() ⇒ <code>Promise.<Boolean></code> -handles creation/update of all config file from the boilerplate - -**Kind**: static method of [<code>Init</code>](#Init) -**Returns**: <code>Promise.<Boolean></code> - status of config file creation -<a name="Init._updateLeaf"></a> - -### Init.\_updateLeaf(propertiersCur, defaultPropsCur, fieldName) ⇒ <code>void</code> -recursive helper for _fixMcdevConfig that adds missing settings - -**Kind**: static method of [<code>Init</code>](#Init) - -| Param | Type | Description | -| --- | --- | --- | -| propertiersCur | <code>Object</code> | current sub-object of project settings | -| defaultPropsCur | <code>Object</code> | current sub-object of default settings | -| fieldName | <code>String</code> | dot-concatenated object-path that needs adding | - -<a name="Init._createIdeConfigFile"></a> - -### Init.\_createIdeConfigFile(fileNameArr, [fileContent]) ⇒ <code>Promise.<Boolean></code> -handles creation/update of one config file from the boilerplate at a time - -**Kind**: static method of [<code>Init</code>](#Init) -**Returns**: <code>Promise.<Boolean></code> - install successful or error occured - -| Param | Type | Description | -| --- | --- | --- | -| fileNameArr | <code>Array.<String></code> | 0: path, 1: filename, 2: extension with dot | -| [fileContent] | <code>String</code> | in case we cannot copy files 1:1 this can be used to pass in content | - -<a name="Init.initGitRepo"></a> - -### Init.initGitRepo([skipInteraction]) ⇒ <code>Promise.<{status:String, repoName:String}></code> -check if git repo exists and otherwise create one - -**Kind**: static method of [<code>Init</code>](#Init) -**Returns**: <code>Promise.<{status:String, repoName:String}></code> - success flag - -| Param | Type | Description | -| --- | --- | --- | -| [skipInteraction] | <code>Object</code> | signals what to insert automatically for things usually asked via wizard | -| skipInteraction.gitRemoteUrl | <code>String</code> | URL of Git remote server | - -<a name="Init.gitPush"></a> - -### Init.gitPush([skipInteraction]) ⇒ <code>void</code> -offer to push the new repo straight to the server - -**Kind**: static method of [<code>Init</code>](#Init) - -| Param | Type | Description | -| --- | --- | --- | -| [skipInteraction] | <code>Boolean</code> \| <code>Object</code> | signals what to insert automatically for things usually asked via wizard | - -<a name="Init._addGitRemote"></a> - -### Init.\_addGitRemote([skipInteraction]) ⇒ <code>String</code> -offers to add the git remote origin - -**Kind**: static method of [<code>Init</code>](#Init) -**Returns**: <code>String</code> - repo name (optionally) - -| Param | Type | Description | -| --- | --- | --- | -| [skipInteraction] | <code>Object</code> | signals what to insert automatically for things usually asked via wizard | -| skipInteraction.gitRemoteUrl | <code>String</code> | URL of Git remote server | - -<a name="Init._updateGitConfigUser"></a> - -### Init.\_updateGitConfigUser([skipInteraction]) ⇒ <code>void</code> -checks global config and ask to config the user info and then store it locally - -**Kind**: static method of [<code>Init</code>](#Init) - -| Param | Type | Description | -| --- | --- | --- | -| [skipInteraction] | <code>Object</code> \| <code>Boolean</code> | signals what to insert automatically for things usually asked via wizard | - -<a name="Init._getGitConfigUser"></a> - -### Init.\_getGitConfigUser() ⇒ <code>Promise.<{'user.name': String, 'user.email': String}></code> -retrieves the global user.name and user.email values - -**Kind**: static method of [<code>Init</code>](#Init) -**Returns**: <code>Promise.<{'user.name': String, 'user.email': String}></code> - user.name and user.email -<a name="Init.initProject"></a> - -### Init.initProject(properties, credentialsName, [skipInteraction]) ⇒ <code>Promise.<void></code> -Creates template file for properties.json - -**Kind**: static method of [<code>Init</code>](#Init) -**Returns**: <code>Promise.<void></code> - - - -| Param | Type | Description | -| --- | --- | --- | -| properties | <code>Object</code> | config file's json | -| credentialsName | <code>string</code> | identifying name of the installed package / project | -| [skipInteraction] | <code>Object</code> | signals what to insert automatically for things usually asked via wizard | -| skipInteraction.clientId | <code>String</code> | client id of installed package | -| skipInteraction.clientSecret | <code>String</code> | client id of installed package | -| skipInteraction.tenant | <code>String</code> | client id of installed package | -| skipInteraction.credentialsName | <code>String</code> | how you would like the credential to be named | -| skipInteraction.gitRemoteUrl | <code>String</code> | URL of Git remote server | - -<a name="Init._downloadAllBUs"></a> - -### Init.\_downloadAllBUs(bu, gitStatus, [skipInteraction]) ⇒ <code>Promise.<void></code> -helper for this.initProject() - -**Kind**: static method of [<code>Init</code>](#Init) -**Returns**: <code>Promise.<void></code> - - - -| Param | Type | Description | -| --- | --- | --- | -| bu | <code>String</code> | cred/bu or cred/* or * | -| gitStatus | <code>String</code> | signals what state the git repo is in | -| [skipInteraction] | <code>Boolean</code> \| <code>Object</code> | signals what to insert automatically for things usually asked via wizard | - -<a name="Init.upgradeProject"></a> - -### Init.upgradeProject(properties, [initial], [repoName]) ⇒ <code>Promise.<Boolean></code> -wrapper around npm dependency & configuration file setup - -**Kind**: static method of [<code>Init</code>](#Init) -**Returns**: <code>Promise.<Boolean></code> - success flag - -| Param | Type | Description | -| --- | --- | --- | -| properties | <code>Object</code> | config file's json | -| [initial] | <code>Boolean</code> | print message if not part of initial setup | -| [repoName] | <code>String</code> | if git URL was provided earlier, the repo name was extracted to use it for npm init | - -<a name="Init._getMissingCredentials"></a> - -### Init.\_getMissingCredentials(properties) ⇒ <code>Array.<String></code> -finds credentials that are set up in config but not in auth file - -**Kind**: static method of [<code>Init</code>](#Init) -**Returns**: <code>Array.<String></code> - list of credential names - -| Param | Type | Description | -| --- | --- | --- | -| properties | <code>object</code> | javascript object in .mcdevrc.json | - -<a name="Init.installDependencies"></a> - -### Init.installDependencies([repoName]) ⇒ <code>Promise.<Boolean></code> -initiates npm project and then -takes care of loading the pre-configured dependency list -from the boilerplate directory to them as dev-dependencies - -**Kind**: static method of [<code>Init</code>](#Init) -**Returns**: <code>Promise.<Boolean></code> - install successful or error occured - -| Param | Type | Description | -| --- | --- | --- | -| [repoName] | <code>String</code> | if git URL was provided earlier, the repo name was extracted to use it for npm init | - -<a name="Init._getDefaultPackageJson"></a> - -### Init.\_getDefaultPackageJson([currentContent]) ⇒ <code>Promise.<{script: Object, author: String, license: String}></code> -ensure we have certain default values in our config - -**Kind**: static method of [<code>Init</code>](#Init) -**Returns**: <code>Promise.<{script: Object, author: String, license: String}></code> - extended currentContent - -| Param | Type | Description | -| --- | --- | --- | -| [currentContent] | <code>Object</code> | what was read from existing package.json file | - -<a name="Init"></a> - -## Init -CLI helper class - -**Kind**: global constant - -* [Init](#Init) - * [.fixMcdevConfig(properties)](#Init.fixMcdevConfig) ⇒ <code>Promise.<Boolean></code> - * [.createIdeConfigFiles()](#Init.createIdeConfigFiles) ⇒ <code>Promise.<Boolean></code> - * [._updateLeaf(propertiersCur, defaultPropsCur, fieldName)](#Init._updateLeaf) ⇒ <code>void</code> - * [._createIdeConfigFile(fileNameArr, [fileContent])](#Init._createIdeConfigFile) ⇒ <code>Promise.<Boolean></code> - * [.initGitRepo([skipInteraction])](#Init.initGitRepo) ⇒ <code>Promise.<{status:String, repoName:String}></code> - * [.gitPush([skipInteraction])](#Init.gitPush) ⇒ <code>void</code> - * [._addGitRemote([skipInteraction])](#Init._addGitRemote) ⇒ <code>String</code> - * [._updateGitConfigUser([skipInteraction])](#Init._updateGitConfigUser) ⇒ <code>void</code> - * [._getGitConfigUser()](#Init._getGitConfigUser) ⇒ <code>Promise.<{'user.name': String, 'user.email': String}></code> - * [.initProject(properties, credentialsName, [skipInteraction])](#Init.initProject) ⇒ <code>Promise.<void></code> - * [._downloadAllBUs(bu, gitStatus, [skipInteraction])](#Init._downloadAllBUs) ⇒ <code>Promise.<void></code> - * [.upgradeProject(properties, [initial], [repoName])](#Init.upgradeProject) ⇒ <code>Promise.<Boolean></code> - * [._getMissingCredentials(properties)](#Init._getMissingCredentials) ⇒ <code>Array.<String></code> - * [.installDependencies([repoName])](#Init.installDependencies) ⇒ <code>Promise.<Boolean></code> - * [._getDefaultPackageJson([currentContent])](#Init._getDefaultPackageJson) ⇒ <code>Promise.<{script: Object, author: String, license: String}></code> - -<a name="Init.fixMcdevConfig"></a> - -### Init.fixMcdevConfig(properties) ⇒ <code>Promise.<Boolean></code> -helper method for this.upgradeProject that upgrades project config if needed - -**Kind**: static method of [<code>Init</code>](#Init) -**Returns**: <code>Promise.<Boolean></code> - returns true if worked without errors - -| Param | Type | Description | -| --- | --- | --- | -| properties | <code>Object</code> | config file's json | - -<a name="Init.createIdeConfigFiles"></a> - -### Init.createIdeConfigFiles() ⇒ <code>Promise.<Boolean></code> -handles creation/update of all config file from the boilerplate - -**Kind**: static method of [<code>Init</code>](#Init) -**Returns**: <code>Promise.<Boolean></code> - status of config file creation -<a name="Init._updateLeaf"></a> - -### Init.\_updateLeaf(propertiersCur, defaultPropsCur, fieldName) ⇒ <code>void</code> -recursive helper for _fixMcdevConfig that adds missing settings - -**Kind**: static method of [<code>Init</code>](#Init) - -| Param | Type | Description | -| --- | --- | --- | -| propertiersCur | <code>Object</code> | current sub-object of project settings | -| defaultPropsCur | <code>Object</code> | current sub-object of default settings | -| fieldName | <code>String</code> | dot-concatenated object-path that needs adding | - -<a name="Init._createIdeConfigFile"></a> - -### Init.\_createIdeConfigFile(fileNameArr, [fileContent]) ⇒ <code>Promise.<Boolean></code> -handles creation/update of one config file from the boilerplate at a time - -**Kind**: static method of [<code>Init</code>](#Init) -**Returns**: <code>Promise.<Boolean></code> - install successful or error occured - -| Param | Type | Description | -| --- | --- | --- | -| fileNameArr | <code>Array.<String></code> | 0: path, 1: filename, 2: extension with dot | -| [fileContent] | <code>String</code> | in case we cannot copy files 1:1 this can be used to pass in content | - -<a name="Init.initGitRepo"></a> - -### Init.initGitRepo([skipInteraction]) ⇒ <code>Promise.<{status:String, repoName:String}></code> -check if git repo exists and otherwise create one - -**Kind**: static method of [<code>Init</code>](#Init) -**Returns**: <code>Promise.<{status:String, repoName:String}></code> - success flag - -| Param | Type | Description | -| --- | --- | --- | -| [skipInteraction] | <code>Object</code> | signals what to insert automatically for things usually asked via wizard | -| skipInteraction.gitRemoteUrl | <code>String</code> | URL of Git remote server | - -<a name="Init.gitPush"></a> - -### Init.gitPush([skipInteraction]) ⇒ <code>void</code> -offer to push the new repo straight to the server - -**Kind**: static method of [<code>Init</code>](#Init) - -| Param | Type | Description | -| --- | --- | --- | -| [skipInteraction] | <code>Boolean</code> \| <code>Object</code> | signals what to insert automatically for things usually asked via wizard | - -<a name="Init._addGitRemote"></a> - -### Init.\_addGitRemote([skipInteraction]) ⇒ <code>String</code> -offers to add the git remote origin - -**Kind**: static method of [<code>Init</code>](#Init) -**Returns**: <code>String</code> - repo name (optionally) - -| Param | Type | Description | -| --- | --- | --- | -| [skipInteraction] | <code>Object</code> | signals what to insert automatically for things usually asked via wizard | -| skipInteraction.gitRemoteUrl | <code>String</code> | URL of Git remote server | - -<a name="Init._updateGitConfigUser"></a> - -### Init.\_updateGitConfigUser([skipInteraction]) ⇒ <code>void</code> -checks global config and ask to config the user info and then store it locally - -**Kind**: static method of [<code>Init</code>](#Init) - -| Param | Type | Description | -| --- | --- | --- | -| [skipInteraction] | <code>Object</code> \| <code>Boolean</code> | signals what to insert automatically for things usually asked via wizard | - -<a name="Init._getGitConfigUser"></a> - -### Init.\_getGitConfigUser() ⇒ <code>Promise.<{'user.name': String, 'user.email': String}></code> -retrieves the global user.name and user.email values - -**Kind**: static method of [<code>Init</code>](#Init) -**Returns**: <code>Promise.<{'user.name': String, 'user.email': String}></code> - user.name and user.email -<a name="Init.initProject"></a> - -### Init.initProject(properties, credentialsName, [skipInteraction]) ⇒ <code>Promise.<void></code> -Creates template file for properties.json - -**Kind**: static method of [<code>Init</code>](#Init) -**Returns**: <code>Promise.<void></code> - - - -| Param | Type | Description | -| --- | --- | --- | -| properties | <code>Object</code> | config file's json | -| credentialsName | <code>string</code> | identifying name of the installed package / project | -| [skipInteraction] | <code>Object</code> | signals what to insert automatically for things usually asked via wizard | -| skipInteraction.clientId | <code>String</code> | client id of installed package | -| skipInteraction.clientSecret | <code>String</code> | client id of installed package | -| skipInteraction.tenant | <code>String</code> | client id of installed package | -| skipInteraction.credentialsName | <code>String</code> | how you would like the credential to be named | -| skipInteraction.gitRemoteUrl | <code>String</code> | URL of Git remote server | - -<a name="Init._downloadAllBUs"></a> - -### Init.\_downloadAllBUs(bu, gitStatus, [skipInteraction]) ⇒ <code>Promise.<void></code> -helper for this.initProject() - -**Kind**: static method of [<code>Init</code>](#Init) -**Returns**: <code>Promise.<void></code> - - - -| Param | Type | Description | -| --- | --- | --- | -| bu | <code>String</code> | cred/bu or cred/* or * | -| gitStatus | <code>String</code> | signals what state the git repo is in | -| [skipInteraction] | <code>Boolean</code> \| <code>Object</code> | signals what to insert automatically for things usually asked via wizard | - -<a name="Init.upgradeProject"></a> - -### Init.upgradeProject(properties, [initial], [repoName]) ⇒ <code>Promise.<Boolean></code> -wrapper around npm dependency & configuration file setup - -**Kind**: static method of [<code>Init</code>](#Init) -**Returns**: <code>Promise.<Boolean></code> - success flag - -| Param | Type | Description | -| --- | --- | --- | -| properties | <code>Object</code> | config file's json | -| [initial] | <code>Boolean</code> | print message if not part of initial setup | -| [repoName] | <code>String</code> | if git URL was provided earlier, the repo name was extracted to use it for npm init | - -<a name="Init._getMissingCredentials"></a> - -### Init.\_getMissingCredentials(properties) ⇒ <code>Array.<String></code> -finds credentials that are set up in config but not in auth file - -**Kind**: static method of [<code>Init</code>](#Init) -**Returns**: <code>Array.<String></code> - list of credential names - -| Param | Type | Description | -| --- | --- | --- | -| properties | <code>object</code> | javascript object in .mcdevrc.json | - -<a name="Init.installDependencies"></a> - -### Init.installDependencies([repoName]) ⇒ <code>Promise.<Boolean></code> -initiates npm project and then -takes care of loading the pre-configured dependency list -from the boilerplate directory to them as dev-dependencies - -**Kind**: static method of [<code>Init</code>](#Init) -**Returns**: <code>Promise.<Boolean></code> - install successful or error occured - -| Param | Type | Description | -| --- | --- | --- | -| [repoName] | <code>String</code> | if git URL was provided earlier, the repo name was extracted to use it for npm init | - -<a name="Init._getDefaultPackageJson"></a> - -### Init.\_getDefaultPackageJson([currentContent]) ⇒ <code>Promise.<{script: Object, author: String, license: String}></code> -ensure we have certain default values in our config - -**Kind**: static method of [<code>Init</code>](#Init) -**Returns**: <code>Promise.<{script: Object, author: String, license: String}></code> - extended currentContent - -| Param | Type | Description | -| --- | --- | --- | -| [currentContent] | <code>Object</code> | what was read from existing package.json file | - -<a name="Init"></a> - -## Init -CLI helper class - -**Kind**: global constant - -* [Init](#Init) - * [.fixMcdevConfig(properties)](#Init.fixMcdevConfig) ⇒ <code>Promise.<Boolean></code> - * [.createIdeConfigFiles()](#Init.createIdeConfigFiles) ⇒ <code>Promise.<Boolean></code> - * [._updateLeaf(propertiersCur, defaultPropsCur, fieldName)](#Init._updateLeaf) ⇒ <code>void</code> - * [._createIdeConfigFile(fileNameArr, [fileContent])](#Init._createIdeConfigFile) ⇒ <code>Promise.<Boolean></code> - * [.initGitRepo([skipInteraction])](#Init.initGitRepo) ⇒ <code>Promise.<{status:String, repoName:String}></code> - * [.gitPush([skipInteraction])](#Init.gitPush) ⇒ <code>void</code> - * [._addGitRemote([skipInteraction])](#Init._addGitRemote) ⇒ <code>String</code> - * [._updateGitConfigUser([skipInteraction])](#Init._updateGitConfigUser) ⇒ <code>void</code> - * [._getGitConfigUser()](#Init._getGitConfigUser) ⇒ <code>Promise.<{'user.name': String, 'user.email': String}></code> - * [.initProject(properties, credentialsName, [skipInteraction])](#Init.initProject) ⇒ <code>Promise.<void></code> - * [._downloadAllBUs(bu, gitStatus, [skipInteraction])](#Init._downloadAllBUs) ⇒ <code>Promise.<void></code> - * [.upgradeProject(properties, [initial], [repoName])](#Init.upgradeProject) ⇒ <code>Promise.<Boolean></code> - * [._getMissingCredentials(properties)](#Init._getMissingCredentials) ⇒ <code>Array.<String></code> - * [.installDependencies([repoName])](#Init.installDependencies) ⇒ <code>Promise.<Boolean></code> - * [._getDefaultPackageJson([currentContent])](#Init._getDefaultPackageJson) ⇒ <code>Promise.<{script: Object, author: String, license: String}></code> - -<a name="Init.fixMcdevConfig"></a> - -### Init.fixMcdevConfig(properties) ⇒ <code>Promise.<Boolean></code> -helper method for this.upgradeProject that upgrades project config if needed - -**Kind**: static method of [<code>Init</code>](#Init) -**Returns**: <code>Promise.<Boolean></code> - returns true if worked without errors - -| Param | Type | Description | -| --- | --- | --- | -| properties | <code>Object</code> | config file's json | - -<a name="Init.createIdeConfigFiles"></a> - -### Init.createIdeConfigFiles() ⇒ <code>Promise.<Boolean></code> -handles creation/update of all config file from the boilerplate - -**Kind**: static method of [<code>Init</code>](#Init) -**Returns**: <code>Promise.<Boolean></code> - status of config file creation -<a name="Init._updateLeaf"></a> - -### Init.\_updateLeaf(propertiersCur, defaultPropsCur, fieldName) ⇒ <code>void</code> -recursive helper for _fixMcdevConfig that adds missing settings - -**Kind**: static method of [<code>Init</code>](#Init) - -| Param | Type | Description | -| --- | --- | --- | -| propertiersCur | <code>Object</code> | current sub-object of project settings | -| defaultPropsCur | <code>Object</code> | current sub-object of default settings | -| fieldName | <code>String</code> | dot-concatenated object-path that needs adding | - -<a name="Init._createIdeConfigFile"></a> - -### Init.\_createIdeConfigFile(fileNameArr, [fileContent]) ⇒ <code>Promise.<Boolean></code> -handles creation/update of one config file from the boilerplate at a time - -**Kind**: static method of [<code>Init</code>](#Init) -**Returns**: <code>Promise.<Boolean></code> - install successful or error occured - -| Param | Type | Description | -| --- | --- | --- | -| fileNameArr | <code>Array.<String></code> | 0: path, 1: filename, 2: extension with dot | -| [fileContent] | <code>String</code> | in case we cannot copy files 1:1 this can be used to pass in content | - -<a name="Init.initGitRepo"></a> - -### Init.initGitRepo([skipInteraction]) ⇒ <code>Promise.<{status:String, repoName:String}></code> -check if git repo exists and otherwise create one - -**Kind**: static method of [<code>Init</code>](#Init) -**Returns**: <code>Promise.<{status:String, repoName:String}></code> - success flag - -| Param | Type | Description | -| --- | --- | --- | -| [skipInteraction] | <code>Object</code> | signals what to insert automatically for things usually asked via wizard | -| skipInteraction.gitRemoteUrl | <code>String</code> | URL of Git remote server | - -<a name="Init.gitPush"></a> - -### Init.gitPush([skipInteraction]) ⇒ <code>void</code> -offer to push the new repo straight to the server - -**Kind**: static method of [<code>Init</code>](#Init) - -| Param | Type | Description | -| --- | --- | --- | -| [skipInteraction] | <code>Boolean</code> \| <code>Object</code> | signals what to insert automatically for things usually asked via wizard | - -<a name="Init._addGitRemote"></a> - -### Init.\_addGitRemote([skipInteraction]) ⇒ <code>String</code> -offers to add the git remote origin - -**Kind**: static method of [<code>Init</code>](#Init) -**Returns**: <code>String</code> - repo name (optionally) - -| Param | Type | Description | -| --- | --- | --- | -| [skipInteraction] | <code>Object</code> | signals what to insert automatically for things usually asked via wizard | -| skipInteraction.gitRemoteUrl | <code>String</code> | URL of Git remote server | - -<a name="Init._updateGitConfigUser"></a> - -### Init.\_updateGitConfigUser([skipInteraction]) ⇒ <code>void</code> -checks global config and ask to config the user info and then store it locally - -**Kind**: static method of [<code>Init</code>](#Init) - -| Param | Type | Description | -| --- | --- | --- | -| [skipInteraction] | <code>Object</code> \| <code>Boolean</code> | signals what to insert automatically for things usually asked via wizard | - -<a name="Init._getGitConfigUser"></a> - -### Init.\_getGitConfigUser() ⇒ <code>Promise.<{'user.name': String, 'user.email': String}></code> -retrieves the global user.name and user.email values - -**Kind**: static method of [<code>Init</code>](#Init) -**Returns**: <code>Promise.<{'user.name': String, 'user.email': String}></code> - user.name and user.email -<a name="Init.initProject"></a> - -### Init.initProject(properties, credentialsName, [skipInteraction]) ⇒ <code>Promise.<void></code> -Creates template file for properties.json - -**Kind**: static method of [<code>Init</code>](#Init) -**Returns**: <code>Promise.<void></code> - - - -| Param | Type | Description | -| --- | --- | --- | -| properties | <code>Object</code> | config file's json | -| credentialsName | <code>string</code> | identifying name of the installed package / project | -| [skipInteraction] | <code>Object</code> | signals what to insert automatically for things usually asked via wizard | -| skipInteraction.clientId | <code>String</code> | client id of installed package | -| skipInteraction.clientSecret | <code>String</code> | client id of installed package | -| skipInteraction.tenant | <code>String</code> | client id of installed package | -| skipInteraction.credentialsName | <code>String</code> | how you would like the credential to be named | -| skipInteraction.gitRemoteUrl | <code>String</code> | URL of Git remote server | - -<a name="Init._downloadAllBUs"></a> - -### Init.\_downloadAllBUs(bu, gitStatus, [skipInteraction]) ⇒ <code>Promise.<void></code> -helper for this.initProject() - -**Kind**: static method of [<code>Init</code>](#Init) -**Returns**: <code>Promise.<void></code> - - - -| Param | Type | Description | -| --- | --- | --- | -| bu | <code>String</code> | cred/bu or cred/* or * | -| gitStatus | <code>String</code> | signals what state the git repo is in | -| [skipInteraction] | <code>Boolean</code> \| <code>Object</code> | signals what to insert automatically for things usually asked via wizard | - -<a name="Init.upgradeProject"></a> - -### Init.upgradeProject(properties, [initial], [repoName]) ⇒ <code>Promise.<Boolean></code> -wrapper around npm dependency & configuration file setup - -**Kind**: static method of [<code>Init</code>](#Init) -**Returns**: <code>Promise.<Boolean></code> - success flag - -| Param | Type | Description | -| --- | --- | --- | -| properties | <code>Object</code> | config file's json | -| [initial] | <code>Boolean</code> | print message if not part of initial setup | -| [repoName] | <code>String</code> | if git URL was provided earlier, the repo name was extracted to use it for npm init | - -<a name="Init._getMissingCredentials"></a> - -### Init.\_getMissingCredentials(properties) ⇒ <code>Array.<String></code> -finds credentials that are set up in config but not in auth file - -**Kind**: static method of [<code>Init</code>](#Init) -**Returns**: <code>Array.<String></code> - list of credential names - -| Param | Type | Description | -| --- | --- | --- | -| properties | <code>object</code> | javascript object in .mcdevrc.json | - -<a name="Init.installDependencies"></a> - -### Init.installDependencies([repoName]) ⇒ <code>Promise.<Boolean></code> -initiates npm project and then -takes care of loading the pre-configured dependency list -from the boilerplate directory to them as dev-dependencies - -**Kind**: static method of [<code>Init</code>](#Init) -**Returns**: <code>Promise.<Boolean></code> - install successful or error occured - -| Param | Type | Description | -| --- | --- | --- | -| [repoName] | <code>String</code> | if git URL was provided earlier, the repo name was extracted to use it for npm init | - -<a name="Init._getDefaultPackageJson"></a> - -### Init.\_getDefaultPackageJson([currentContent]) ⇒ <code>Promise.<{script: Object, author: String, license: String}></code> -ensure we have certain default values in our config - -**Kind**: static method of [<code>Init</code>](#Init) -**Returns**: <code>Promise.<{script: Object, author: String, license: String}></code> - extended currentContent - -| Param | Type | Description | -| --- | --- | --- | -| [currentContent] | <code>Object</code> | what was read from existing package.json file | - -<a name="ET_Client"></a> - -## ET\_Client : [<code>ET\_Client</code>](#ET_Client) -**Kind**: global constant -<a name="Util"></a> - -## Util -Util that contains logger and simple util methods - -**Kind**: global constant - -* [Util](#Util) - * [.logger](#Util.logger) - * [.isTrue(attrValue)](#Util.isTrue) ⇒ <code>boolean</code> - * [.isFalse(attrValue)](#Util.isFalse) ⇒ <code>boolean</code> - * [.getDefaultProperties()](#Util.getDefaultProperties) ⇒ <code>object</code> - * [.getRetrieveTypeChoices()](#Util.getRetrieveTypeChoices) ⇒ <code>Array.<string></code> - * [.checkProperties(properties, [silent])](#Util.checkProperties) ⇒ <code>boolean</code> \| <code>Array.<String></code> - * [.metadataLogger(level, type, method, payload, [source])](#Util.metadataLogger) ⇒ <code>void</code> - * [.replaceByObject(str, obj)](#Util.replaceByObject) ⇒ <code>String</code> \| <code>Object</code> - * [.inverseGet(objs, val)](#Util.inverseGet) ⇒ <code>String</code> - * [.getMetadataHierachy(metadataTypes)](#Util.getMetadataHierachy) ⇒ <code>Array.<String></code> - * [.getETClient(buObject)](#Util.getETClient) ⇒ [<code>Promise.<ET\_Client></code>](#ET_Client) - * [~myClient](#Util.getETClient..myClient) : [<code>ET\_Client</code>](#ET_Client) - * [.getFromCache(cache, metadataType, searchValue, searchField, returnField)](#Util.getFromCache) ⇒ <code>String</code> - * [.resolveObjPath(path, obj)](#Util.resolveObjPath) ⇒ <code>any</code> - * [.getListObjectIdFromCache(cache, listPathName, returnField)](#Util.getListObjectIdFromCache) ⇒ <code>String</code> - * [.getListPathNameFromCache(cache, searchValue, searchField)](#Util.getListPathNameFromCache) ⇒ <code>String</code> - * [.retryOnError(errorMsg, callback, [silentError], [retries])](#Util.retryOnError) ⇒ <code>Promise.<void></code> - * [.execSync(cmd, [args])](#Util.execSync) ⇒ <code>undefined</code> - -<a name="Util.logger"></a> - -### Util.logger -Logger that creates timestamped log file in 'logs/' directory - -**Kind**: static property of [<code>Util</code>](#Util) -<a name="Util.isTrue"></a> - -### Util.isTrue(attrValue) ⇒ <code>boolean</code> -SFMC accepts multiple true values for Boolean attributes for which we are checking here - -**Kind**: static method of [<code>Util</code>](#Util) -**Returns**: <code>boolean</code> - attribute value == true ? true : false - -| Param | Type | Description | -| --- | --- | --- | -| attrValue | <code>\*</code> | value | - -<a name="Util.isFalse"></a> - -### Util.isFalse(attrValue) ⇒ <code>boolean</code> -SFMC accepts multiple false values for Boolean attributes for which we are checking here - -**Kind**: static method of [<code>Util</code>](#Util) -**Returns**: <code>boolean</code> - attribute value == false ? true : false - -| Param | Type | Description | -| --- | --- | --- | -| attrValue | <code>\*</code> | value | - -<a name="Util.getDefaultProperties"></a> - -### Util.getDefaultProperties() ⇒ <code>object</code> -defines how the properties.json should look like -used for creating a template and for checking if variables are set - -**Kind**: static method of [<code>Util</code>](#Util) -**Returns**: <code>object</code> - default properties -<a name="Util.getRetrieveTypeChoices"></a> - -### Util.getRetrieveTypeChoices() ⇒ <code>Array.<string></code> -helper for getDefaultProperties() - -**Kind**: static method of [<code>Util</code>](#Util) -**Returns**: <code>Array.<string></code> - type choices -<a name="Util.checkProperties"></a> - -### Util.checkProperties(properties, [silent]) ⇒ <code>boolean</code> \| <code>Array.<String></code> -check if the config file is correctly formatted and has values - -**Kind**: static method of [<code>Util</code>](#Util) -**Returns**: <code>boolean</code> \| <code>Array.<String></code> - file structure ok OR list of fields to be fixed - -| Param | Type | Description | -| --- | --- | --- | -| properties | <code>object</code> | javascript object in .mcdevrc.json | -| [silent] | <code>boolean</code> | set to true for internal use w/o cli output | - -<a name="Util.metadataLogger"></a> - -### Util.metadataLogger(level, type, method, payload, [source]) ⇒ <code>void</code> -Logger helper for Metadata functions - -**Kind**: static method of [<code>Util</code>](#Util) - -| Param | Type | Description | -| --- | --- | --- | -| level | <code>String</code> | of log (error, info, warn) | -| type | <code>String</code> | of metadata being referenced | -| method | <code>String</code> | name which log was called from | -| payload | <code>\*</code> | generic object which details the error | -| [source] | <code>String</code> | key/id of metadata which relates to error | - -<a name="Util.replaceByObject"></a> - -### Util.replaceByObject(str, obj) ⇒ <code>String</code> \| <code>Object</code> -replaces values in a JSON object string, based on a series of -key-value pairs (obj) - -**Kind**: static method of [<code>Util</code>](#Util) -**Returns**: <code>String</code> \| <code>Object</code> - replaced version of str - -| Param | Type | Description | -| --- | --- | --- | -| str | <code>String</code> \| <code>Object</code> | JSON object or its stringified version, which has values to be replaced | -| obj | [<code>TemplateMap</code>](#TemplateMap) | key value object which contains keys to be replaced and values to be replaced with | - -<a name="Util.inverseGet"></a> - -### Util.inverseGet(objs, val) ⇒ <code>String</code> -get key of an object based on the first matching value - -**Kind**: static method of [<code>Util</code>](#Util) -**Returns**: <code>String</code> - key - -| Param | Type | Description | -| --- | --- | --- | -| objs | <code>Object</code> | object of objects to be searched | -| val | <code>String</code> | value to be searched for | - -<a name="Util.getMetadataHierachy"></a> - -### Util.getMetadataHierachy(metadataTypes) ⇒ <code>Array.<String></code> -Returns Order in which metadata needs to be retrieved/deployed - -**Kind**: static method of [<code>Util</code>](#Util) -**Returns**: <code>Array.<String></code> - retrieve/deploy order as array - -| Param | Type | Description | -| --- | --- | --- | -| metadataTypes | <code>Array.<String></code> | which should be retrieved/deployed | - -<a name="Util.getETClient"></a> - -### Util.getETClient(buObject) ⇒ [<code>Promise.<ET\_Client></code>](#ET_Client) -signs in with SFMC - -**Kind**: static method of [<code>Util</code>](#Util) -**Returns**: [<code>Promise.<ET\_Client></code>](#ET_Client) - auth object - -| Param | Type | Description | -| --- | --- | --- | -| buObject | <code>BuObject</code> | properties for auth | - -<a name="Util.getETClient..myClient"></a> - -#### getETClient~myClient : [<code>ET\_Client</code>](#ET_Client) -**Kind**: inner constant of [<code>getETClient</code>](#Util.getETClient) -<a name="Util.getFromCache"></a> - -### Util.getFromCache(cache, metadataType, searchValue, searchField, returnField) ⇒ <code>String</code> -standardized method for getting data from cache. - -**Kind**: static method of [<code>Util</code>](#Util) -**Returns**: <code>String</code> - unique user definable metadata key (usually external/customer key) - -| Param | Type | Description | -| --- | --- | --- | -| cache | <code>Object</code> | data retrieved from sfmc instance | -| metadataType | <code>String</code> | metadata type ie. query | -| searchValue | <code>String</code> | unique identifier of metadata being looked for | -| searchField | <code>String</code> | field name (key in object) which contains the unique identifer | -| returnField | <code>String</code> | field which should be returned | - -<a name="Util.resolveObjPath"></a> - -### Util.resolveObjPath(path, obj) ⇒ <code>any</code> -let's you dynamically walk down an object and get a value - -**Kind**: static method of [<code>Util</code>](#Util) -**Returns**: <code>any</code> - value of obj.path - -| Param | Type | Description | -| --- | --- | --- | -| path | <code>String</code> | 'fieldA.fieldB.fieldC' | -| obj | <code>Object</code> | some parent object | - -<a name="Util.getListObjectIdFromCache"></a> - -### Util.getListObjectIdFromCache(cache, listPathName, returnField) ⇒ <code>String</code> -standardized method for getting data from cache - adapted for special case of lists -! keeping this in util/util.js rather than in metadataTypes/List.js to avoid potential circular dependencies - -**Kind**: static method of [<code>Util</code>](#Util) -**Returns**: <code>String</code> - unique ObjectId of list - -| Param | Type | Description | -| --- | --- | --- | -| cache | <code>Object</code> | data retrieved from sfmc instance | -| listPathName | <code>String</code> | folderPath/ListName combo of list | -| returnField | <code>String</code> | ObjectID or ID | - -<a name="Util.getListPathNameFromCache"></a> - -### Util.getListPathNameFromCache(cache, searchValue, searchField) ⇒ <code>String</code> -standardized method for getting data from cache - adapted for special case of lists -! keeping this in util/util.js rather than in metadataTypes/List.js to avoid potential circular dependencies - -**Kind**: static method of [<code>Util</code>](#Util) -**Returns**: <code>String</code> - unique folderPath/ListName combo of list - -| Param | Type | Description | -| --- | --- | --- | -| cache | <code>Object</code> | data retrieved from sfmc instance | -| searchValue | <code>String</code> | unique identifier of metadata being looked for | -| searchField | <code>String</code> | ObjectID or ID | - -<a name="Util.retryOnError"></a> - -### Util.retryOnError(errorMsg, callback, [silentError], [retries]) ⇒ <code>Promise.<void></code> -retry on network issues - -**Kind**: static method of [<code>Util</code>](#Util) -**Returns**: <code>Promise.<void></code> - - - -| Param | Type | Default | Description | -| --- | --- | --- | --- | -| errorMsg | <code>String</code> | | what to print behind "Connection error. " | -| callback | <code>function</code> | | what to try executing | -| [silentError] | <code>Boolean</code> | <code>false</code> | prints retry messages to log only; default=false | -| [retries] | <code>Number</code> | <code>1</code> | number of retries; default=1 | - -<a name="Util.execSync"></a> - -### Util.execSync(cmd, [args]) ⇒ <code>undefined</code> -helper to run other commands as if run manually by user - -**Kind**: static method of [<code>Util</code>](#Util) - -| Param | Type | Description | -| --- | --- | --- | -| cmd | <code>string</code> | to be executed command | -| [args] | <code>Array.<string></code> | list of arguments | - -<a name="getUserName"></a> - -## getUserName(userList, item, fieldname) ⇒ <code>string</code> -**Kind**: global function -**Returns**: <code>string</code> - username or user id or 'n/a' - -| Param | Type | Description | -| --- | --- | --- | -| userList | <code>object.<string, string></code> | user-id > user-name map | -| item | <code>object.<string, string></code> | single metadata item | -| fieldname | <code>string</code> | name of field containing the info | - -<a name="createNewLoggerTransport"></a> - -## createNewLoggerTransport() ⇒ <code>object</code> -wrapper around our standard winston logging to console and logfile - -**Kind**: global function -**Returns**: <code>object</code> - initiated logger for console and file -<a name="startLogger"></a> - -## startLogger() ⇒ <code>void</code> -initiate winston logger - -**Kind**: global function -<a name="CodeExtractItem"></a> - -## CodeExtractItem : <code>Object.<string, any></code> -**Kind**: global typedef -**Properties** - -| Name | Type | Description | -| --- | --- | --- | -| json | <code>AssetItem</code> | metadata of one item w/o code | -| codeArr | <code>Array.<MetadataType.CodeExtract></code> | list of code snippets in this item | -| subFolder | <code>Array.<string></code> | mostly set to null, otherwise list of subfolders | - -<a name="AutomationMap"></a> - -## AutomationMap : <code>Object</code> -REST format - -**Kind**: global typedef -**Properties** - -| Name | Type | Description | -| --- | --- | --- | -| name | <code>string</code> | name (not key) of activity | -| [objectTypeId] | <code>string</code> | Id of assoicated activity type; see this.definition.activityTypeMapping | -| [activityObjectId] | <code>string</code> | Object Id of assoicated metadata item | -| displayOrder | <code>number</code> | order within step; starts with 1 or higher number | -| r__type | <code>string</code> | see this.definition.activityTypeMapping | -| name | <code>string</code> | description | -| [annotation] | <code>string</code> | equals AutomationStep.name | -| step | <code>number</code> | step iterator | -| [stepNumber] | <code>number</code> | step iterator, automatically set during deployment | -| activities | <code>Array.<AutomationActivity></code> | - | -| typeId | <code>number</code> | ? | -| startDate | <code>string</code> | example: '2021-05-07T09:00:00' | -| endDate | <code>string</code> | example: '2021-05-07T09:00:00' | -| icalRecur | <code>string</code> | example: 'FREQ=DAILY;UNTIL=20790606T160000;INTERVAL=1' | -| timezoneName | <code>string</code> | example: 'W. Europe Standard Time'; see this.definition.timeZoneMapping | -| [timezoneId] | <code>number</code> | see this.definition.timeZoneMapping | -| Recurrence | <code>Object</code> | - | -| Recurrence.$ | <code>Object</code> | {'xsi:type': keyStem + 'lyRecurrence'} | -| [Recurrence.YearlyRecurrencePatternType] | <code>'ByYear'</code> | * currently not supported by tool * | -| [Recurrence.MonthlyRecurrencePatternType] | <code>'ByMonth'</code> | * currently not supported by tool * | -| [Recurrence.WeeklyRecurrencePatternType] | <code>'ByWeek'</code> | * currently not supported by tool * | -| [Recurrence.DailyRecurrencePatternType] | <code>'ByDay'</code> | - | -| [Recurrence.MinutelyRecurrencePatternType] | <code>'Interval'</code> | - | -| [Recurrence.HourlyRecurrencePatternType] | <code>'Interval'</code> | - | -| [Recurrence.YearInterval] | <code>number</code> | 1..n * currently not supported by tool * | -| [Recurrence.MonthInterval] | <code>number</code> | 1..n * currently not supported by tool * | -| [Recurrence.WeekInterval] | <code>number</code> | 1..n * currently not supported by tool * | -| [Recurrence.DayInterval] | <code>number</code> | 1..n | -| [Recurrence.HourInterval] | <code>number</code> | 1..n | -| [Recurrence.MinuteInterval] | <code>number</code> | 1..n | -| _interval | <code>number</code> | internal variable for CLI output only | -| TimeZone | <code>Object</code> | - | -| TimeZone.ID | <code>number</code> | AutomationSchedule.timezoneId | -| _timezoneString | <code>string</code> | internal variable for CLI output only | -| StartDateTime | <code>string</code> | AutomationSchedule.startDate | -| EndDateTime | <code>string</code> | AutomationSchedule.endDate | -| _StartDateTime | <code>string</code> | AutomationSchedule.startDate; internal variable for CLI output only | -| RecurrenceRangeType | <code>'EndOn'</code> \| <code>'EndAfter'</code> | set to 'EndOn' if AutomationSchedule.icalRecur contains 'UNTIL'; otherwise to 'EndAfter' | -| Occurrences | <code>number</code> | only exists if RecurrenceRangeType=='EndAfter' | -| [id] | <code>string</code> | Object Id | -| key | <code>string</code> | key | -| name | <code>string</code> | name | -| description | <code>string</code> | - | -| type | <code>'scheduled'</code> \| <code>'triggered'</code> | Starting Source = Schedule / File Drop | -| status | <code>'Scheduled'</code> \| <code>'Running'</code> | - | -| [schedule] | <code>AutomationSchedule</code> | only existing if type=scheduled | -| [fileTrigger] | <code>Object</code> | only existing if type=triggered | -| fileTrigger.fileNamingPattern | <code>string</code> | - | -| fileTrigger.fileNamePatternTypeId | <code>string</code> | - | -| fileTrigger.folderLocationText | <code>string</code> | - | -| fileTrigger.queueFiles | <code>string</code> | - | -| [startSource] | <code>Object</code> | - | -| [startSource.schedule] | <code>AutomationSchedule</code> | rewritten to AutomationItem.schedule | -| [startSource.fileDrop] | <code>Object</code> | rewritten to AutomationItem.fileTrigger | -| startSource.fileDrop.fileNamingPattern | <code>string</code> | - | -| startSource.fileDrop.fileNamePatternTypeId | <code>string</code> | - | -| startSource.fileDrop.folderLocation | <code>string</code> | - | -| startSource.fileDrop.queueFiles | <code>string</code> | - | -| startSource.typeId | <code>number</code> | - | -| steps | <code>Array.<AutomationStep></code> | - | -| r__folder_Path | <code>string</code> | folder path | -| [categoryId] | <code>string</code> | holds folder ID, replaced with r__folder_Path during retrieve | - -<a name="DataExtensionMap"></a> - -## DataExtensionMap : <code>Object</code> -**Kind**: global typedef -**Properties** - -| Name | Type | Description | -| --- | --- | --- | -| CustomerKey | <code>string</code> | key | -| Name | <code>string</code> | name | -| Description | <code>string</code> | - | -| IsSendable | <code>'true'</code> \| <code>'false'</code> | - | -| IsTestable | <code>'true'</code> \| <code>'false'</code> | - | -| SendableDataExtensionField | <code>Object</code> | - | -| SendableDataExtensionField.Name | <code>string</code> | - | -| SendableSubscriberField | <code>Object</code> | - | -| SendableSubscriberField.Name | <code>string</code> | - | -| Fields | <code>Array.<DataExtensionField.DataExtensionFieldItem></code> | list of DE fields | -| r__folder_ContentType | <code>'dataextension'</code> \| <code>'salesforcedataextension'</code> \| <code>'synchronizeddataextension'</code> \| <code>'shared\_dataextension'</code> \| <code>'shared\_salesforcedataextension'</code> | retrieved from associated folder | -| r__folder_Path | <code>string</code> | folder path in which this DE is saved | -| [CategoryID] | <code>string</code> | holds folder ID, replaced with r__folder_Path during retrieve | -| [r__dataExtensionTemplate_Name] | <code>string</code> | name of optionally associated DE template | -| [Template] | <code>Object</code> | - | -| [Template.CustomerKey] | <code>string</code> | key of optionally associated DE teplate | - -<a name="DataExtensionFieldMap"></a> - -## DataExtensionFieldMap : <code>Object</code> -**Kind**: global typedef -**Properties** - -| Name | Type | Description | -| --- | --- | --- | -| [ObjectID] | <code>string</code> | id | -| [CustomerKey] | <code>string</code> | key in format [DEkey].[FieldName] | -| [DataExtension] | <code>Object</code> | - | -| DataExtension.CustomerKey | <code>string</code> | key of DE | -| Name | <code>string</code> | name of field | -| [Name_new] | <code>string</code> | custom attribute that is only used when trying to rename a field from Name to Name_new | -| DefaultValue | <code>string</code> | empty string for not set | -| IsRequired | <code>'true'</code> \| <code>'false'</code> | - | -| IsPrimaryKey | <code>'true'</code> \| <code>'false'</code> | - | -| Ordinal | <code>string</code> | 1, 2, 3, ... | -| FieldType | <code>'Text'</code> \| <code>'Number'</code> \| <code>'Date'</code> \| <code>'Boolean'</code> \| <code>'Decimal'</code> \| <code>'EmailAddress'</code> \| <code>'Phone'</code> \| <code>'Locale'</code> | can only be set on create | -| Scale | <code>string</code> | the number of places after the decimal that the field can hold; example: "0","1", ... | - -<a name="MultiMetadataTypeMap"></a> - -## MultiMetadataTypeMap : <code>Object.<string, any></code> -**Kind**: global typedef -**Properties** - -| Name | Type | Description | -| --- | --- | --- | -| json | <code>MetadataTypeItem</code> | metadata of one item w/o code | -| codeArr | <code>Array.<CodeExtract></code> | list of code snippets in this item | -| subFolder | <code>Array.<string></code> | mostly set to null, otherwise list of subfolders | -| subFolder | <code>Array.<string></code> | mostly set to null, otherwise subfolders path split into elements | -| fileName | <code>string</code> | name of file w/o extension | -| fileExt | <code>string</code> | file extension | -| content | <code>string</code> | file content | -| [encoding] | <code>'base64'</code> | optional for binary files | - -<a name="CodeExtractItem"></a> - -## CodeExtractItem : <code>Object</code> -**Kind**: global typedef -**Properties** - -| Name | Type | Description | -| --- | --- | --- | -| name | <code>string</code> | name | -| key | <code>string</code> | key | -| description | <code>string</code> | - | -| targetKey | <code>string</code> | key of target data extension | -| createdDate | <code>string</code> | e.g. "2020-09-14T01:42:03.017" | -| modifiedDate | <code>string</code> | e.g. "2020-09-14T01:42:03.017" | -| targetUpdateTypeName | <code>'Overwrite'</code> \| <code>'Update'</code> \| <code>'Append'</code> | defines how the query writes into the target data extension | -| [targetUpdateTypeId] | <code>0</code> \| <code>1</code> \| <code>2</code> | mapped to targetUpdateTypeName via this.definition.targetUpdateTypeMapping | -| [targetId] | <code>string</code> | Object ID of DE (removed before save) | -| [targetDescription] | <code>string</code> | Description DE (removed before save) | -| isFrozen | <code>boolean</code> | looks like this is always set to false | -| [queryText] | <code>string</code> | contains SQL query with line breaks converted to '\n'. The content is extracted during retrieval and written into a separate *.sql file | -| [categoryId] | <code>string</code> | holds folder ID, replaced with r__folder_Path during retrieve | -| r__folder_Path | <code>string</code> | folder path in which this DE is saved | -| json | <code>QueryItem</code> | metadata of one item w/o code | -| codeArr | <code>Array.<MetadataType.CodeExtract></code> | list of code snippets in this item | -| subFolder | <code>Array.<string></code> | mostly set to null, otherwise list of subfolders | - -<a name="CodeExtractItem"></a> - -## CodeExtractItem : <code>Object</code> -**Kind**: global typedef -**Properties** - -| Name | Type | Description | -| --- | --- | --- | -| name | <code>string</code> | name | -| key | <code>string</code> | key | -| description | <code>string</code> | - | -| createdDate | <code>string</code> | e.g. "2020-09-14T01:42:03.017" | -| modifiedDate | <code>string</code> | e.g. "2020-09-14T01:42:03.017" | -| [script] | <code>string</code> | contains script with line breaks converted to '\n'. The content is extracted during retrieval and written into a separate *.ssjs file | -| [categoryId] | <code>string</code> | holds folder ID, replaced with r__folder_Path during retrieve | -| r__folder_Path | <code>string</code> | folder path in which this DE is saved | -| json | <code>ScriptItem</code> | metadata of one item w/o code | -| codeArr | <code>Array.<MetadataType.CodeExtract></code> | list of code snippets in this item | -| subFolder | <code>Array.<string></code> | mostly set to null, otherwise list of subfolders | - -<a name="TemplateMap"></a> - -## TemplateMap : <code>Object.<string, string></code> -**Kind**: global typedef diff --git a/eslint.config.js b/eslint.config.js new file mode 100644 index 000000000..5c8627092 --- /dev/null +++ b/eslint.config.js @@ -0,0 +1,144 @@ +import eslintPluginPrettierRecommended from 'eslint-plugin-prettier/recommended'; +import eslintPluginUnicorn from 'eslint-plugin-unicorn'; +import globals from 'globals'; +import mochaPlugin from 'eslint-plugin-mocha'; +import jsdoc from 'eslint-plugin-jsdoc'; +import js from '@eslint/js'; + +export default [ + { + ignores: ['docs/**/*', 'node_modules/**/*', 'retrieve/**/*'], + }, + js.configs.recommended, + eslintPluginPrettierRecommended, + mochaPlugin.configs.recommended, + jsdoc.configs['flat/recommended'], + eslintPluginUnicorn.configs['recommended'], + { + languageOptions: { + globals: { + ...globals.nodeBuiltin, + Atomics: 'readonly', + SharedArrayBuffer: 'readonly', + }, + + ecmaVersion: 2022, + sourceType: 'module', + }, + + settings: { + jsdoc: { + mode: 'typescript', + + preferredTypes: { + array: 'Array', + 'array.<>': '[]', + 'Array.<>': '[]', + 'array<>': '[]', + 'Array<>': '[]', + Object: 'object', + 'object.<>': 'Object.<>', + 'object<>': 'Object.<>', + 'Object<>': 'Object.<>', + set: 'Set', + 'set.<>': 'Set.<>', + 'set<>': 'Set.<>', + 'Set<>': 'Set.<>', + promise: 'Promise', + 'promise.<>': 'Promise.<>', + 'promise<>': 'Promise.<>', + 'Promise<>': 'Promise.<>', + }, + }, + }, + + rules: { + 'logical-assignment-operators': ['error', 'always'], + 'unicorn/better-regex': 'off', + + 'unicorn/catch-error-name': [ + 'error', + { + name: 'ex', + }, + ], + + 'unicorn/explicit-length-check': 'off', + 'unicorn/filename-case': 'off', + 'unicorn/no-array-callback-reference': 'off', + 'unicorn/no-array-reduce': 'off', + 'unicorn/no-await-expression-member': 'off', + 'unicorn/no-empty-file': 'off', + 'unicorn/no-hex-escape': 'off', + 'unicorn/no-nested-ternary': 'off', + 'unicorn/no-null': 'off', + 'unicorn/no-static-only-class': 'off', + 'unicorn/no-unused-properties': 'warn', + 'unicorn/numeric-separators-style': 'off', + 'unicorn/prefer-array-some': 'off', + 'unicorn/prefer-module': 'off', + 'unicorn/prefer-set-has': 'off', + 'unicorn/prefer-spread': 'off', + 'unicorn/prefer-string-replace-all': 'error', + 'unicorn/prevent-abbreviations': 'off', + 'arrow-body-style': ['error', 'as-needed'], + curly: 'error', + 'no-console': 'error', + 'jsdoc/check-line-alignment': 2, + + 'jsdoc/require-jsdoc': [ + 'warn', + { + require: { + FunctionDeclaration: true, + MethodDefinition: true, + ClassDeclaration: true, + ArrowFunctionExpression: false, + FunctionExpression: true, + }, + }, + ], + + 'jsdoc/require-param-type': 'error', + + 'jsdoc/tag-lines': [ + 'warn', + 'any', + { + startLines: 1, + }, + ], + + 'jsdoc/no-undefined-types': 'off', + 'jsdoc/valid-types': 'off', + + 'spaced-comment': [ + 'warn', + 'always', + { + block: { + exceptions: ['*'], + balanced: true, + }, + }, + ], + }, + }, + { + files: ['**/*.js'], + + rules: { + 'no-var': 'error', + 'prefer-const': 'error', + 'prettier/prettier': 'warn', + 'prefer-arrow-callback': 'warn', + }, + }, + { + files: ['test/*.js'], + rules: { + 'mocha/no-mocha-arrows': 'off', + 'mocha/no-pending-tests': 'off', + }, + }, +]; diff --git a/jsconfig.json b/jsconfig.json deleted file mode 100644 index 6993eb8c1..000000000 --- a/jsconfig.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "include": ["lib/**/*.js"] -} diff --git a/lib/Builder.js b/lib/Builder.js index c38208c2b..c33b760ad 100644 --- a/lib/Builder.js +++ b/lib/Builder.js @@ -1,9 +1,26 @@ 'use strict'; -const Util = require('./util/util'); +import { Util } from './util/util.js'; +import File from './util/file.js'; +import config from './util/config.js'; +import Cli from './util/cli.js'; +import auth from './util/auth.js'; +import MetadataTypeInfo from './MetadataTypeInfo.js'; -const MetadataTypeInfo = require('./MetadataTypeInfo'); -// @ts-ignore +/** + * @typedef {import('../types/mcdev.d.js').BuObject} BuObject + * @typedef {import('../types/mcdev.d.js').CodeExtract} CodeExtract + * @typedef {import('../types/mcdev.d.js').CodeExtractItem} CodeExtractItem + * @typedef {import('../types/mcdev.d.js').Mcdevrc} Mcdevrc + * @typedef {import('../types/mcdev.d.js').MetadataTypeItem} MetadataTypeItem + * @typedef {import('../types/mcdev.d.js').MetadataTypeItemDiff} MetadataTypeItemDiff + * @typedef {import('../types/mcdev.d.js').MetadataTypeItemObj} MetadataTypeItemObj + * @typedef {import('../types/mcdev.d.js').MetadataTypeMap} MetadataTypeMap + * @typedef {import('../types/mcdev.d.js').MetadataTypeMapObj} MetadataTypeMapObj + * @typedef {import('../types/mcdev.d.js').MultiMetadataTypeList} MultiMetadataTypeList + * @typedef {import('../types/mcdev.d.js').SoapRequestParams} SoapRequestParams + * @typedef {import('../types/mcdev.d.js').TemplateMap} TemplateMap + */ /** * Builds metadata from a template using market specific customisation @@ -12,139 +29,327 @@ class Builder { /** * Creates a Builder, uses v2 auth if v2AuthOptions are passed. * - * @param {Object} properties properties for auth - * @param {String} properties.clientId clientId for FuelSDK auth - * @param {String} properties.clientSecret clientSecret for FuelSDK auth - * @param {Object} properties.directories list of default directories - * @param {String} properties.directories.template where templates are saved - * @param {String} properties.directories.templateBuilds where template-based deployment definitions are saved - * @param {String} properties.tenant v2 Auth Tenant Information - * @param {String} properties.businessUnits ID of Business Unit to authenticate with - * @param {Object} buObject properties for auth - * @param {String} buObject.clientId clientId for FuelSDK auth - * @param {String} buObject.clientSecret clientSecret for FuelSDK auth - * @param {Object} buObject.credential clientId for FuelSDK auth - * @param {String} buObject.tenant v2 Auth Tenant Information - * @param {String} buObject.mid ID of Business Unit to authenticate with - * @param {String} buObject.businessUnit name of Business Unit to authenticate with - * @param {Util.ET_Client} client fuel client + * @param {Mcdevrc} properties properties for auth +saved + * @param {BuObject} buObject properties for auth */ - constructor(properties, buObject, client) { - this.client = client; + constructor(properties, buObject) { this.properties = properties; this.templateDir = properties.directories.template; + this.retrieveDir = File.normalizePath([ + properties.directories.retrieve, + buObject.credential, + buObject.businessUnit, + ]); + this.buObject = buObject; // allow multiple target directories const templateBuildsArr = Array.isArray(properties.directories.templateBuilds) ? properties.directories.templateBuilds : [properties.directories.templateBuilds]; - - this.targetDir = templateBuildsArr.map( - (directoriesTemplateBuilds) => - directoriesTemplateBuilds + buObject.credential + '/' + buObject.businessUnit + this.targetDir = templateBuildsArr.map((directoriesTemplateBuilds) => + File.normalizePath([ + directoriesTemplateBuilds, + buObject.credential, + buObject.businessUnit, + ]) ); + /** + * @type {MultiMetadataTypeList} + */ this.metadata = {}; } /** * Builds a specific metadata file by name - * @param {String} metadataType metadata type to build - * @param {String} name name of metadata to build - * @param {Object} variables variables to be replaced in the metadata - * @returns {Promise} Promise + * + * @param {string} metadataType metadata type to build + * @param {string[]} nameArr name of metadata to build + * @param {TemplateMap} templateVariables variables to be replaced in the metadata + * @returns {Promise.<MultiMetadataTypeList>} Promise */ - async buildDefinition(metadataType, name, variables) { - let nameArr; - if (name.includes(',')) { - nameArr = name.split(',').map((item) => - // allow whitespace in comma-separated lists - item.trim() + async _buildDefinition(metadataType, nameArr, templateVariables) { + const type = metadataType; + try { + const result = ( + await Promise.all( + nameArr.map((name) => { + // with npx and powershell spaces are not parsed correctly as part of a string + // we hence require users to put %20 in their stead and have to convert that back + name = name.split('%20').join(' '); + + MetadataTypeInfo[type].client = auth.getSDK(this.buObject); + MetadataTypeInfo[type].properties = this.properties; + MetadataTypeInfo[type].buObject = this.buObject; + return MetadataTypeInfo[type].buildDefinition( + this.templateDir, + this.targetDir, + name, + templateVariables + ); + }) + ) + ).filter(Boolean); + if (result && type === result[0]?.type) { + // result elements can be undefined for each key that we did not find + this.metadata[type] = result.map((element) => element.metadata); + } + } catch (ex) { + Util.logger.errorStack(ex, 'mcdev.buildDefinition'); + } + return this.metadata; + } + + /** + * Build a template based on a list of metadata files in the retrieve folder. + * + * @param {string} businessUnit references credentials from properties.json + * @param {string} selectedType supported metadata type + * @param {string[]} keyArr customerkey of the metadata + * @param {string[]} marketArr market localizations + * @returns {Promise.<MultiMetadataTypeList>} - + */ + static async buildTemplate(businessUnit, selectedType, keyArr, marketArr) { + const properties = await config.getProperties(); + if (!properties) { + return; + } + if (!Util._isValidType(selectedType)) { + return; + } + if (selectedType.includes('-')) { + Util.logger.error( + `:: '${selectedType}' is not a valid metadata type. Please don't include subtypes.` ); - } else { - nameArr = [name.trim()]; + return; + } + /** @type {TemplateMap} */ + const templateVariables = {}; + if (marketArr[0] !== '__clone__') { + // if __clone__ is passed, we don't want to actually change anything but simply clone the metadata as-is + for (const market of marketArr) { + if (Util.checkMarket(market, properties)) { + Object.assign(templateVariables, properties.markets[market]); + } else { + // do not execute the rest of this method if a market was invalid + return; + } + } + } + const buObject = await Cli.getCredentialObject(properties, businessUnit); + if (buObject !== null) { + const builder = new Builder(properties, buObject); + return builder._buildTemplate(selectedType, keyArr, templateVariables); } + } + + /** + * Build a template based on a list of metadata files in the retrieve folder. + * + * @param {string} metadataType metadata type to create a template of + * @param {string[]} keyArr customerkey of metadata to create a template of + * @param {TemplateMap} templateVariables variables to be replaced in the metadata + * @returns {Promise.<MultiMetadataTypeList>} Promise + */ + async _buildTemplate(metadataType, keyArr, templateVariables) { const type = metadataType; try { - const result = await Promise.all( - nameArr.map((name) => { - // with npx and powershell spaces are not parsed correctly as part of a string - // we hence require users to put %20 in their stead and have to convert that back - name = name.split('%20').join(' '); - - MetadataTypeInfo[type].cache = null; - MetadataTypeInfo[type].client = this.client; - MetadataTypeInfo[type].properties = this.properties; - return MetadataTypeInfo[type].buildDefinition( - this.templateDir, - this.targetDir, - name, - variables - ); - }) - ); - if (result) { - this.metadata[result[0].type] = []; - result.forEach((element) => { - this.metadata[result[0].type].push(element.metadata); - }); + const removeKeys = []; + /** @type {MetadataTypeItemObj[]} */ + const result = ( + await Promise.all( + keyArr.map(async (key) => { + MetadataTypeInfo[type].properties = this.properties; + MetadataTypeInfo[type].buObject = this.buObject; + + try { + /** @type {MetadataTypeItemObj} */ + const response = await MetadataTypeInfo[type].buildTemplate( + this.retrieveDir, + this.templateDir, + key, + templateVariables + ); + if (!response) { + removeKeys.push(key); + } + return response; + } catch (ex) { + removeKeys.push(key); + Util.logger.errorStack(ex, ` ☇ skipping template asset: ${key}`); + } + }) + ) + ).filter(Boolean); + // remove keys that errored out + keyArr.splice(0, keyArr.length, ...keyArr.filter((key) => !removeKeys.includes(key))); + if (result && type === result[0]?.type) { + // result elements can be undefined for each key that we did not find + this.metadata[type] = result.map((element) => element.metadata); } } catch (ex) { - Util.logger.error('mcdev.buildDefinition:' + ex.message); - Util.logger.debug(ex.stack); - if (Util.logger.level === 'debug') { - console.log(ex.stack); - } + Util.logger.errorStack(ex, 'mcdev.buildTemplate'); } return this.metadata; } + /** - * ensure provided MarketList exists and it's content including markets and BUs checks out - * @param {String} mlName name of marketList - * @param {Object} properties General configuration to be used in retrieve - * @param {Object} properties.markets list of template variable combos - * @param {Object} properties.marketList list of bu-market combos - * @param {Object} properties.credentials list of credentials and their BUs - * @returns {void} throws errors if problems were found + * Build a specific metadata file based on a template. + * + * @param {string} businessUnit references credentials from properties.json + * @param {string} selectedType supported metadata type + * @param {string[]} nameArr name of the metadata + * @param {string[]} marketArr market localizations + * @returns {Promise.<MultiMetadataTypeList>} - */ - static verifyMarketList(mlName, properties) { - if (!properties.marketList[mlName]) { - // ML does not exist - throw new Error(`Market List ${mlName} is not defined`); - } else { - // ML exists, check if it is properly set up - - // check if BUs in marketList are valid - let buCounter = 0; - for (const businessUnit in properties.marketList[mlName]) { - if (businessUnit !== 'description') { - buCounter++; - const [cred, bu] = businessUnit ? businessUnit.split('/') : [null, null]; - if ( - !properties.credentials[cred] || - !properties.credentials[cred].businessUnits[bu] - ) { - throw new Error(`'${businessUnit}' in Market ${mlName} is not defined.`); - } - // check if markets are valid - let marketArr = properties.marketList[mlName][businessUnit]; - if ('string' === typeof marketArr) { - marketArr = [marketArr]; - } - for (const market of marketArr) { - if (!properties.markets[market]) { - throw new Error(`Market '${market}' is not defined.`); - } else { - // * markets can be empty or include variables. Nothing we can test here - } + static async buildDefinition(businessUnit, selectedType, nameArr, marketArr) { + const properties = await config.getProperties(); + if (!properties) { + return; + } + if (!Util._isValidType(selectedType)) { + return; + } + if (selectedType.includes('-')) { + Util.logger.error( + `:: '${selectedType}' is not a valid metadata type. Please don't include subtypes.` + ); + return; + } + /** @type {TemplateMap} */ + const templateVariables = {}; + if (marketArr[0] !== '__clone__') { + // if __clone__ is passed, we don't want to actually change anything but simply clone the metadata as-is + for (const market of marketArr) { + if (Util.checkMarket(market, properties)) { + Object.assign(templateVariables, properties.markets[market]); + } else { + // do not execute the rest of this method if a market was invalid + return; + } + } + } + const buObject = await Cli.getCredentialObject(properties, businessUnit); + if (buObject !== null) { + const builder = new Builder(properties, buObject); + + return builder._buildDefinition(selectedType, nameArr, templateVariables); + } + } + + /** + * Build a specific metadata file based on a template using a list of bu-market combos + * + * @param {string} listName name of list of BU-market combos + * @param {string} type supported metadata type + * @param {string[]} nameArr name of the metadata + * @returns {Promise.<object>} - + */ + static async buildDefinitionBulk(listName, type, nameArr) { + const properties = await config.getProperties(); + if (!properties) { + return; + } + try { + Util.verifyMarketList(listName, properties); + } catch (ex) { + Util.logger.error(ex.message); + return; + } + if (type && !MetadataTypeInfo[type]) { + Util.logger.error(`:: '${type}' is not a valid metadata type`); + return; + } + let i = 0; + + const responseObj = {}; + for (const businessUnit in properties.marketList[listName]) { + if (businessUnit === 'description') { + // skip, it's just a metadata on this list and not a BU + continue; + } + i++; + /** @type {string | string[] | string[][]} */ + const market = properties.marketList[listName][businessUnit]; + const marketList = 'string' === typeof market ? [market] : market; + + for (const market of marketList) { + // one can now send multiple markets to buildTemplate/buildDefinition and hence that also needs to work for marketLists + const marketArr = 'string' === typeof market ? [market] : market; + for (const market of marketArr) { + if (!Util.checkMarket(market, properties)) { + return; } } + + Util.logger.info(`Executing for '${businessUnit}': '${marketArr.join('-')}'`); + // omitting "await" to speed up creation + responseObj[businessUnit] ||= {}; + responseObj[businessUnit][marketArr.join('-')] = await this.buildDefinition( + businessUnit, + type, + nameArr, + marketArr + ); } - if (!buCounter) { - throw new Error(`No BUs defined in marketList ${mlName}`); + } + + if (!i) { + Util.logger.error('Please define properties.marketList in your config'); + } + return responseObj; + } + /** + * helper for buildDefinitionBulk, createDeltaPkg + * + * @param {string} listName market list name + * @returns {Promise.<void>} - + */ + static async purgeDeployFolderList(listName) { + const properties = await config.getProperties(); + if (!properties) { + return; + } + for (const businessUnit in properties.marketList[listName]) { + if (businessUnit === 'description') { + // skip, it's just a metadata on this list and not a BU + continue; } + if (!Util.isValidBU(properties, businessUnit, true)) { + throw new Error(`'${businessUnit}' in Market ${listName} is not defined.`); + } + await this.purgeDeployFolder(businessUnit); + } + } + /** + * helper for buildDefiniton, purgeDeployFolderList + * + * @param {string} businessUnit cred/bu combo + * @returns {Promise.<void>} - + */ + static async purgeDeployFolder(businessUnit) { + const properties = await config.getProperties(); + if (!properties) { + return; + } + if (!Util.isValidBU(properties, businessUnit, true)) { + throw new Error(`'${businessUnit}' does not exist.`); + } + const deployDir = File.normalizePath([ + properties.directories.deploy, + ...businessUnit.split('/'), + ]); + // Clear output folder structure for selected sub-type + // only run this if the standard deploy folder is a target of buildDefinition (which technically could be changed) + Util.logger.info(` - 🚮 purging folder ${deployDir}`); + try { + await File.remove(deployDir); + } catch { + // sometimes the first attempt is not successful for some operating system reason. Trying again mostly solves this + await File.remove(deployDir); } } } -module.exports = Builder; +export default Builder; diff --git a/lib/Deployer.js b/lib/Deployer.js index 694eb9e0d..f43b564e5 100644 --- a/lib/Deployer.js +++ b/lib/Deployer.js @@ -1,9 +1,32 @@ 'use strict'; -const MetadataTypeInfo = require('./MetadataTypeInfo'); -const path = require('path'); -const Util = require('./util/util'); -const File = require('./util/file'); +import MetadataTypeInfo from './MetadataTypeInfo.js'; +import path from 'node:path'; +import Cli from './util/cli.js'; +import { Util } from './util/util.js'; +import File from './util/file.js'; +import config from './util/config.js'; +import cache from './util/cache.js'; +import auth from './util/auth.js'; + +/** + * @typedef {import('../types/mcdev.d.js').BuObject} BuObject + * @typedef {import('../types/mcdev.d.js').CodeExtract} CodeExtract + * @typedef {import('../types/mcdev.d.js').CodeExtractItem} CodeExtractItem + * @typedef {import('../types/mcdev.d.js').Mcdevrc} Mcdevrc + * @typedef {import('../types/mcdev.d.js').MetadataTypeItem} MetadataTypeItem + * @typedef {import('../types/mcdev.d.js').MetadataTypeItemDiff} MetadataTypeItemDiff + * @typedef {import('../types/mcdev.d.js').MetadataTypeItemObj} MetadataTypeItemObj + * @typedef {import('../types/mcdev.d.js').MetadataTypeMap} MetadataTypeMap + * @typedef {import('../types/mcdev.d.js').MetadataTypeMapObj} MetadataTypeMapObj + * @typedef {import('../types/mcdev.d.js').MultiMetadataTypeList} MultiMetadataTypeList + * @typedef {import('../types/mcdev.d.js').SoapRequestParams} SoapRequestParams + * @typedef {import('../types/mcdev.d.js').TemplateMap} TemplateMap + * @typedef {import('../types/mcdev.d.js').MultiMetadataTypeMap} MultiMetadataTypeMap + * @typedef {import('../types/mcdev.d.js').TypeKeyCombo} TypeKeyCombo + * + * @typedef {import('../types/mcdev.d.js').ListMap} ListMap + */ /** * Reads metadata from local directory and deploys it to specified target business unit. @@ -13,22 +36,11 @@ class Deployer { /** * Creates a Deployer, uses v2 auth if v2AuthOptions are passed. * - * - * @param {Object} properties General configuration to be used in retrieve - * @param {Object} properties.directories Directories to be used when interacting with FS - * @param {Object} buObject properties for auth - * @param {String} buObject.clientId clientId for FuelSDK auth - * @param {String} buObject.clientSecret clientSecret for FuelSDK auth - * @param {Object} buObject.credential clientId for FuelSDK auth - * @param {String} buObject.tenant v2 Auth Tenant Information - * @param {String} buObject.mid ID of Business Unit to authenticate with - * @param {String} buObject.businessUnit name of Business Unit to authenticate with - * @param {Util.ET_Client} client fuel client - * @param {String} [type] limit deployment to given metadata type + * @param {Mcdevrc} properties General configuration to be used in retrieve + * @param {BuObject} buObject properties for auth */ - constructor(properties, buObject, client, type) { + constructor(properties, buObject) { this.buObject = buObject; - this.client = client; this.properties = properties; this.deployDir = File.normalizePath([ properties.directories.deploy, @@ -41,142 +53,393 @@ class Deployer { buObject.businessUnit, ]); // prep folders for auto-creation - MetadataTypeInfo.folder.cache = this.cache; - MetadataTypeInfo.folder.client = this.client; - MetadataTypeInfo.folder.properties = this.properties; - // Remove tmp folder of previous deploys - File.removeSync('tmp'); - if (File.existsSync(this.deployDir)) { - this.metadata = Deployer.readBUMetadata(this.deployDir, type); - } else { - this.metadata = null; - Util.logger.warn( - 'Deployer.constructor:: Please create a directory called deploy and include your metadata in it: ./' + - this.deployDir + MetadataTypeInfo.folder.client = auth.getSDK(buObject); + MetadataTypeInfo.folder.buObject = buObject; + MetadataTypeInfo.folder.properties = properties; + } + + /** + * Deploys all metadata located in the 'deploy' directory to the specified business unit + * + * @param {string} businessUnit references credentials from properties.json + * @param {string[] | TypeKeyCombo} [selectedTypesArr] limit deployment to given metadata type + * @param {string[]} [keyArr] limit deployment to given metadata keys + * @returns {Promise.<Object.<string, MultiMetadataTypeMap>>} deployed metadata per BU (first key: bu name, second key: metadata type) + */ + static async deploy(businessUnit, selectedTypesArr, keyArr) { + Util.logger.info('mcdev:: Deploy'); + /** @type {Object.<string, MultiMetadataTypeMap>} */ + const buMultiMetadataTypeMap = {}; + const properties = await config.getProperties(); + if (!properties) { + return; + } + const deployDirBak = properties.directories.deploy; + if (Util.OPTIONS.fromRetrieve) { + properties.directories.deploy = properties.directories.retrieve; + } + if (selectedTypesArr) { + for (const selectedType of Array.isArray(selectedTypesArr) + ? selectedTypesArr + : Object.keys(selectedTypesArr)) { + if (!Util._isValidType(selectedType)) { + return; + } + } + } + if (Util.OPTIONS.fromRetrieve) { + // check if either type & key or typeKeyCombo including keys was supplied + // we dont want to allow deploying without key from the retrieve dir for safety reasons + let keysFound = false; + if ( + Array.isArray(selectedTypesArr) && + selectedTypesArr.length && + Array.isArray(keyArr) && + keyArr.length + ) { + // check legacy way of passing in type(s) and key(s) + keysFound = true; + } else if ( + selectedTypesArr && + !Array.isArray(selectedTypesArr) && + Object.values(selectedTypesArr).length + ) { + // TypeKeyCombo - a single null value (== no keys for one type) should lead to the error + keysFound = true; + for (const keys of Object.values(selectedTypesArr)) { + if (keys === null) { + keysFound = false; + break; + } + } + } + if (!keysFound) { + Util.logger.error('type & key need to be defined to deploy from retrieve folder'); + return; + } + } + let counter_credBu = 0; + if (businessUnit === '*') { + if (Util.OPTIONS.changeKeyValue) { + Util.logger.error('--changeKeyValue is not supported for deployments to all BUs'); + return; + } + // all credentials and all BUs shall be deployed to + const deployFolders = await File.readDirectories( + properties.directories.deploy, + 2, + false ); + + for (const buPath of deployFolders.filter((r) => r.includes(path.sep))) { + const [cred, bu] = buPath.split(path.sep); + const multiMetadataTypeMap = await this._deployBU( + cred, + bu, + properties, + selectedTypesArr, + keyArr + ); + buMultiMetadataTypeMap[cred + '/' + bu] = multiMetadataTypeMap; + counter_credBu++; + Util.logger.info(''); + Util.startLogger(true); + } + } else { + // anything but "*" passed in + let [cred, bu] = businessUnit ? businessUnit.split('/') : [null, null]; + + // to allow all-BU via user selection we need to run this here already + if ( + properties.credentials && + (!properties.credentials[cred] || + (bu !== '*' && properties.credentials[cred].businessUnits[bu])) + ) { + const buObject = await Cli.getCredentialObject( + properties, + cred === null ? null : cred + '/' + bu, + null, + true + ); + if (buObject === null) { + return; + } else { + cred = buObject.credential; + bu = buObject.businessUnit; + } + } + + if (bu === '*' && properties.credentials && properties.credentials[cred]) { + if (Util.OPTIONS.changeKeyValue) { + Util.logger.error( + '--changeKeyValue is not supported for deployments to all BUs' + ); + return; + } + // valid credential given and -all- BUs targeted + Util.logger.info(`:: Deploying all BUs for ${cred}`); + let counter_credBu = 0; + // for (const bu in properties.credentials[cred].businessUnits) { + const deployFolders = await File.readDirectories( + File.normalizePath([properties.directories.deploy, cred]), + 1, + false + ); + for (const buPath of deployFolders) { + const multiMetadataTypeMap = await this._deployBU( + cred, + buPath, + properties, + selectedTypesArr, + keyArr + ); + buMultiMetadataTypeMap[cred + '/' + buPath] = multiMetadataTypeMap; + counter_credBu++; + Util.logger.info(''); + Util.startLogger(true); + } + Util.logger.info(` :: ${counter_credBu} BUs for ${cred}\n`); + } else { + // either bad credential or specific BU or no BU given + const multiMetadataTypeMap = await this._deployBU( + cred, + bu, + properties, + selectedTypesArr, + keyArr + ); + counter_credBu++; + buMultiMetadataTypeMap[cred + '/' + bu] = multiMetadataTypeMap; + } + } + if (Util.OPTIONS.fromRetrieve) { + properties.directories.deploy = deployDirBak; } - this.cache = {}; + if (counter_credBu !== 0) { + Util.logger.info(`:: Deployed ${counter_credBu} BUs\n`); + } + return buMultiMetadataTypeMap; + } + + /** + * helper for {@link Deployer.deploy} + * + * @param {string} cred name of Credential + * @param {string} bu name of BU + * @param {Mcdevrc} properties General configuration to be used in retrieve + * @param {string[] | TypeKeyCombo} [typeArr] limit deployment to given metadata type + * @param {string[]} [keyArr] limit deployment to given metadata keys + * @returns {Promise.<MultiMetadataTypeMap>} ensure that BUs are worked on sequentially + */ + static async _deployBU(cred, bu, properties, typeArr, keyArr) { + // ensure changes to the typeArr on one BU do not affect other BUs called in the same go + typeArr = structuredClone(typeArr); + + const buPath = `${cred}/${bu}`; + Util.logger.info(`:: Deploying to ${buPath}`); + const buObject = await Cli.getCredentialObject(properties, buPath, null, true); + let multiMetadataTypeMap; + + if (buObject !== null) { + cache.initCache(buObject); + const deployer = new Deployer(properties, buObject); + try { + // await is required or the calls end up conflicting + multiMetadataTypeMap = await deployer._deploy(typeArr, keyArr); + } catch (ex) { + Util.logger.errorStack(ex, 'mcdev.deploy failed'); + } + } + return multiMetadataTypeMap; } + /** * Deploy all metadata that is located in the deployDir - * @returns {Promise} Promise + * + * @param {string[] | TypeKeyCombo} [types] limit deployment to given metadata type (can include subtype) + * @param {string[]} [keyArr] limit deployment to given metadata keys + * @returns {Promise.<MultiMetadataTypeMap>} Promise of all deployed metadata */ - async deploy() { + async _deploy(types, keyArr) { + const typeArr = types ? (Array.isArray(types) ? types : Object.keys(types)) : undefined; + const typeKeyCombo = Array.isArray(types) + ? Util.createTypeKeyCombo(typeArr, keyArr, true) + : types; + if (await File.pathExists(this.deployDir)) { + /** @type {MultiMetadataTypeMap} */ + this.metadata = await Deployer.readBUMetadata(this.deployDir, typeArr); + // filter found metadata by key if given + if (typeArr && Array.isArray(typeArr)) { + for (const selectedType of typeArr) { + const type = selectedType.split('-')[0]; + this.metadata[type] = Util.filterObjByKeys( + this.metadata[type], + typeKeyCombo[selectedType] + ); + if (!this.metadata[type] || !Object.keys(this.metadata[type]).length) { + // the type array is not set if the folder wasnt there. it is set but empty if the folder was there but no metadata was found + Util.logger.warn( + `No deployable metadata found for type ${type} ${keyArr?.length ? 'with keys ' + keyArr.join(', ') : ''}` + ); + delete this.metadata[type]; + } + } + } + } else { + this.metadata = null; + Util.logger.error( + 'Please create a directory called deploy and include your metadata in it: ' + + this.deployDir + ); + return null; + } if (this.metadata === null || !Object.keys(this.metadata).length) { - Util.logger.warn('No metadata found in deploy folder for selected BU'); + Util.logger.error('No metadata found in deploy folder for selected BU'); return null; } - await Deployer.createFolderDefinitions( - this.deployDir, - this.metadata, - Object.keys(this.metadata) - ); + if (Util.OPTIONS.changeKeyValue && Object.keys(this.metadata).length) { + if (Object.keys(this.metadata).length > 1) { + Util.logger.error('--changeKeyValue expects a single type to be deployed'); + return null; + } else if (Object.keys(Object.values(this.metadata)[0]).length > 1) { + Util.logger.error('--changeKeyValue expects a single key to be deployed'); + return null; + } + } + + const foundDeployTypes = Object.keys(this.metadata) + // remove empty types + .filter((type) => Object.keys(this.metadata[type]).length) + // make sure we keep the subtype in this list if that's what the user defined + .map((type) => + type === 'asset' && Util.includesStartsWith(typeArr, type) + ? typeArr[Util.includesStartsWithIndex(typeArr, type)] + : type + ); + if (!foundDeployTypes.length) { + throw new Error('No metadata found for deployment'); + } + const deployOrder = Util.getMetadataHierachy(foundDeployTypes); - const deployOrder = Util.getMetadataHierachy(Object.keys(this.metadata)); + if (!Util.OPTIONS.fromRetrieve) { + // remove auto-created folder-directory from previous deployments unless 'folder' was specifically listed as to-be-deployed type + if (!typeArr || !typeArr.includes('folder')) { + await File.remove(File.normalizePath([this.deployDir, 'folder'])); + } + + // run this AFTER identifying deployOrder or else ALL folders will be cached + await Deployer.createFolderDefinitions( + this.deployDir, + this.metadata, + Object.keys(this.metadata) + ); + } // build cache, including all metadata types which will be deployed (Avoids retrieve later) - for (const metadataType of deployOrder) { - const [type, subType] = metadataType.split('-'); + for (const metadataType in deployOrder) { + const type = metadataType; + const subTypeArr = deployOrder[metadataType]; // add metadata & client to metadata process class instead of passing cache/mapping every time - MetadataTypeInfo[type].cache = this.cache; - MetadataTypeInfo[type].client = this.client; + MetadataTypeInfo[type].client = auth.getSDK(this.buObject); MetadataTypeInfo[type].properties = this.properties; - Util.logger.info('Caching dependent Metadata: ' + metadataType); - let result; - await Util.retryOnError(`Retrying ${type}`, async () => { - result = await MetadataTypeInfo[type].retrieveForCache(this.buObject, subType); - }); - this.cache[type] = result.metadata; + MetadataTypeInfo[type].buObject = this.buObject; + Util.logger.info(`Caching dependent Metadata: ${metadataType}`); + Util.logSubtypes(subTypeArr); + const result = await MetadataTypeInfo[type].retrieveForCache(null, subTypeArr); + if (result?.metadata) { + // in case of dataExtensionField retrieveForCache() will return undefined on purpose + cache.setMetadata(type, result.metadata); + } } + /** @type {MultiMetadataTypeMap} */ + const multiMetadataTypeMap = {}; // deploy metadata files, extending cache once deploys - for (const metadataType of deployOrder) { - let result; - // TODO rewrite to allow deploying only a specific sub-type - // const [type, subType] = metadataType.split('-'); - const type = metadataType.split('-')[0]; + for (const metadataType in deployOrder) { + // TODO rewrite to allow deploying only a specific sub-type; currently, subtypes are ignored when executing deploy + const type = metadataType; if (this.metadata[type]) { - MetadataTypeInfo[type].cache = this.cache; - Util.logger.info('Deploying: ' + metadataType); - await Util.retryOnError(`Retrying ${metadataType}`, async () => { - result = await MetadataTypeInfo[type].deploy( - this.metadata[type], - this.deployDir, - this.retrieveDir, - this.buObject - ); - }); - this.cache[type] = Object.assign(this.cache[type], result); - this.deployCallback(result, type); - } - } - } + Util.logger.info( + 'Deploying: ' + + metadataType + + (Util.OPTIONS.fromRetrieve ? ' (from retrieve folder)' : '') + ); - /** - * Gets called for every deployed metadata entry - * @param {Object} result Deployment result - * @param {String} metadataType Name of metadata type - * @returns {void} - */ - deployCallback(result, metadataType) { - if (result) { - File.writeJSONToFile('logs/', 'deployResult_' + metadataType, result); - Util.logger.verbose( - 'Deployer.deployCallback:: Results written to: ' + - path.normalize(process.cwd() + '/logs/deployResult_' + metadataType + '.json') - ); + const result = await MetadataTypeInfo[type].deploy( + this.metadata[type], + this.deployDir, + type === 'folder' && (!typeArr || !typeArr.includes('folder')) + ? null + : this.retrieveDir + ); + multiMetadataTypeMap[type] = result; + cache.mergeMetadata(type, result); + } } + return multiMetadataTypeMap; } /** * Returns metadata of a business unit that is saved locally - * @param {String} deployDir root directory of metadata. - * @param {String} [type] limit deployment to given metadata type - * @param {boolean} [listBadKeys=false] do not print errors, used for badKeys() - * @returns {Object} Metadata of BU in local directory + * + * @param {string} deployDir root directory of metadata. + * @param {string[]} [typeArr] limit deployment to given metadata type + * @param {boolean} [listBadKeys] do not print errors, used for badKeys() + * @returns {Promise.<MultiMetadataTypeMap>} Metadata of BU in local directory */ - static readBUMetadata(deployDir, type, listBadKeys) { + static async readBUMetadata(deployDir, typeArr, listBadKeys) { + /** @type {MultiMetadataTypeMap} */ const buMetadata = {}; try { - if (File.existsSync(deployDir)) { - const metadataTypes = File.readdirSync(deployDir); - metadataTypes.forEach((metadataType) => { - if (MetadataTypeInfo[metadataType] && (!type || type === metadataType)) { - // check if folder name is a valid metadataType, then check if the user limited to a certain type in the command params - buMetadata[metadataType] = MetadataTypeInfo[metadataType].getJsonFromFS( - File.normalizePath([deployDir, metadataType]), - listBadKeys - ); - } - }); - - return buMetadata; - } else { - throw new Error(`Directory '${deployDir}' does not exist.`); + await File.ensureDir(deployDir); + const metadataTypes = await File.readdir(deployDir); + for (const metadataType of metadataTypes) { + if ( + MetadataTypeInfo[metadataType] && + (!typeArr || Util.includesStartsWith(typeArr, metadataType)) + ) { + // check if folder name is a valid metadataType, then check if the user limited to a certain type in the command params + buMetadata[metadataType] = await MetadataTypeInfo[metadataType].getJsonFromFS( + File.normalizePath([deployDir, metadataType]), + listBadKeys, + typeArr + ); + } + } + if (Object.keys(buMetadata).length === 0) { + throw new Error('No metadata found in deploy folder for selected BU & type'); } + return buMetadata; } catch (ex) { - throw new Error(ex.message); + throw new Error(ex.message, { cause: ex }); } } /** * parses asset metadata to auto-create folders in target folder - * @param {String} deployDir root directory of metadata. - * @param {Object} metadata list of metadata - * @param {String} metadataTypeArr list of metadata types - * @returns {void} + * + * @param {string} deployDir root directory of metadata. + * @param {MultiMetadataTypeMap} metadata list of metadata + * @param {string[]} metadataTypeArr list of metadata types + * @returns {Promise.<object>} folder metadata */ static async createFolderDefinitions(deployDir, metadata, metadataTypeArr) { let i = 0; + /** @type {ListMap} */ const folderMetadata = {}; - metadataTypeArr.forEach((metadataType) => { - if (!MetadataTypeInfo[metadataType].definition.dependencies.includes('folder')) { - Util.logger.debug( - `_createFolderDefinitions(${metadataType}) - folder not a dependency` - ); - return; + const allowedDeFolderContentTypes = ['dataextension', 'shared_dataextension']; + for (const metadataType of metadataTypeArr) { + // check if folder or folder-like metadata type is in dependencies + if ( + !MetadataTypeInfo[metadataType].definition.dependencies.includes('folder') && + !MetadataTypeInfo[metadataType].definition.dependencies.some((dep) => + dep.startsWith('folder-') + ) + ) { + Util.logger.debug(` ☇ skipping ${metadataType} folders: folder not a dependency`); + continue; } if (!MetadataTypeInfo[metadataType].definition.folderType) { - Util.logger.debug(`_createFolderDefinitions(${metadataType}) - folderType not set`); - return; + Util.logger.debug(` ☇ skipping ${metadataType} folders: folderType not set`); + continue; } if ( !MetadataTypeInfo.folder.definition.deployFolderTypes.includes( @@ -184,68 +447,88 @@ class Deployer { ) ) { Util.logger.warn( - `_createFolderDefinitions(${metadataType}: ${MetadataTypeInfo[metadataType].definition.folderType}) - folderType not supported for deployment` + ` ☇ skipping ${metadataType} folders: folderType ${MetadataTypeInfo[metadataType].definition.folderType} not supported for deployment. Please consider creating folders for this type manually as a pre-deployment step, if you see errors about missing dependent folders for this type later in this log.` ); - return; + continue; } - Util.logger.debug(`Creating relevant folders for ${metadataType} in deploy dir`); - - let allFolders = Object.keys(metadata[metadataType]).filter( - // filter out root folders (which would not have a slash in their path) - (key) => metadata[metadataType][key].r__folder_Path.includes('/') + Util.logger.debug( + ` - create ${metadataType} folders: Creating relevant folders in deploy dir` ); - if (metadataType === 'dataExtension') { - allFolders = allFolders - .filter( - // filter out any shared / synchronized / salesforce folders - (key) => - metadata[metadataType][key].r__folder_ContentType === 'dataextension' - ) - .map((key) => metadata[metadataType][key].r__folder_Path); - } else { - allFolders = allFolders.map((key) => metadata[metadataType][key].r__folder_Path); - } + + const allFolders = Object.keys(metadata[metadataType]) + .filter( + // filter out root folders (which would not have a slash in their path) + (key) => metadata[metadataType][key].r__folder_Path?.includes('/') + ) + .filter( + // filter out dataExtension folders other than standard & shared (--> synchronized / salesforce are not allowed) + (key) => + metadataType !== 'dataExtension' || + allowedDeFolderContentTypes.includes( + metadata[metadataType][key].r__folder_ContentType + ) + ) + .map((key) => metadata[metadataType][key].r__folder_Path); + // deduplicate const folderPathSet = new Set(allFolders); - [...folderPathSet].sort().forEach((item) => { + for (const item of [...folderPathSet].toSorted()) { let aggregatedPath = ''; const parts = item.split('/'); - parts.forEach((pathElement) => { + for (const pathElement of parts) { if (aggregatedPath) { aggregatedPath += '/'; } aggregatedPath += pathElement; folderPathSet.add(aggregatedPath); - }); - }); + } + } const folderPathArrExtended = [...folderPathSet] // strip root folders .filter((folderName) => folderName.includes('/')) - .sort(); + .toSorted(); - folderPathArrExtended.forEach((folder) => { + for (const folder of folderPathArrExtended) { i++; + let contentType = MetadataTypeInfo[metadataType].definition.folderType; + if ( + metadataType === 'dataExtension' && + folder.startsWith('Shared Items/Shared Data Extensions') + ) { + contentType = 'shared_dataextension'; + } + if ( + metadataType === 'triggeredSend' && + folder.startsWith('Journey Builder Sends/') + ) { + contentType = 'triggered_send_journeybuilder'; + } + if (metadataType === 'asset' && folder.startsWith('CloudPages/')) { + contentType = 'cloudpages'; + } folderMetadata[`on-the-fly-${i}`] = { Path: folder, - Name: folder.split('/').pop(), - Description: '', - ContentType: MetadataTypeInfo[metadataType].definition.folderType, - IsActive: 'true', - IsEditable: 'true', - AllowChildren: 'true', + // unescape folder name slash escape chars to get the actual SFMC folder name + Name: folder.split('/').pop().replaceAll(Util.folderNameSlashEscapeChar, '/'), + Description: '', // required for Create, omitted for update via definition file + ContentType: contentType, + IsActive: true, // would be auto-updated for existing folders if needed + IsEditable: true, // would be auto-updated for existing folders if needed + AllowChildren: true, // would be auto-updated for existing folders if needed + _generated: true, }; - }); - }); + } + } if (i > 0) { - Util.logger.info(`Saving folders to deploy dir (${i}) - please wait`); - + MetadataTypeInfo.folder.definition.fields._generated.retrieving = true; // ensure we keep that flag in deploy folder // await results to allow us to re-read it right after - await MetadataTypeInfo.folder.saveResults(folderMetadata, deployDir, null); - Util.logger.info(`Saved: folders in deploy dir`); + await MetadataTypeInfo.folder.saveResults(folderMetadata, deployDir); + MetadataTypeInfo.folder.definition.fields._generated.retrieving = false; // reset flag + Util.logger.info(`Created folders in deploy dir: ${i}`); // reload from file system to ensure we use the same logic for building the temporary JSON - metadata.folder = MetadataTypeInfo.folder.getJsonFromFS( + metadata.folder = await MetadataTypeInfo.folder.getJsonFromFS( File.normalizePath([deployDir, 'folder']) ); } @@ -253,4 +536,4 @@ class Deployer { } } -module.exports = Deployer; +export default Deployer; diff --git a/lib/MetadataTypeDefinitions.js b/lib/MetadataTypeDefinitions.js index ebc74ff15..0fd38d43c 100644 --- a/lib/MetadataTypeDefinitions.js +++ b/lib/MetadataTypeDefinitions.js @@ -1,36 +1,92 @@ 'use strict'; +import asset from './metadataTypes/definitions/Asset.definition.js'; +import attributeGroup from './metadataTypes/definitions/AttributeGroup.definition.js'; +import attributeSet from './metadataTypes/definitions/AttributeSet.definition.js'; +import automation from './metadataTypes/definitions/Automation.definition.js'; +import campaign from './metadataTypes/definitions/Campaign.definition.js'; +import contentArea from './metadataTypes/definitions/ContentArea.definition.js'; +import dataFilter from './metadataTypes/definitions/DataFilter.definition.js'; +import dataFilterHidden from './metadataTypes/definitions/DataFilterHidden.definition.js'; +import dataExtension from './metadataTypes/definitions/DataExtension.definition.js'; +import dataExtensionField from './metadataTypes/definitions/DataExtensionField.definition.js'; +import dataExtensionTemplate from './metadataTypes/definitions/DataExtensionTemplate.definition.js'; +import dataExtract from './metadataTypes/definitions/DataExtract.definition.js'; +import dataExtractType from './metadataTypes/definitions/DataExtractType.definition.js'; +import deliveryProfile from './metadataTypes/definitions/DeliveryProfile.definition.js'; +import discovery from './metadataTypes/definitions/Discovery.definition.js'; +import domainVerification from './metadataTypes/definitions/DomainVerification.definition.js'; +import email from './metadataTypes/definitions/Email.definition.js'; +import emailSend from './metadataTypes/definitions/EmailSend.definition.js'; +import event from './metadataTypes/definitions/Event.definition.js'; +import fileLocation from './metadataTypes/definitions/FileLocation.definition.js'; +import fileTransfer from './metadataTypes/definitions/FileTransfer.definition.js'; +import filter from './metadataTypes/definitions/Filter.definition.js'; +import folder from './metadataTypes/definitions/Folder.definition.js'; +import importFile from './metadataTypes/definitions/ImportFile.definition.js'; +import journey from './metadataTypes/definitions/Journey.definition.js'; +import list from './metadataTypes/definitions/List.definition.js'; +import mobileCode from './metadataTypes/definitions/MobileCode.definition.js'; +import mobileKeyword from './metadataTypes/definitions/MobileKeyword.definition.js'; +import mobileMessage from './metadataTypes/definitions/MobileMessage.definition.js'; +import query from './metadataTypes/definitions/Query.definition.js'; +import role from './metadataTypes/definitions/Role.definition.js'; +import script from './metadataTypes/definitions/Script.definition.js'; +import sendClassification from './metadataTypes/definitions/SendClassification.definition.js'; +import senderProfile from './metadataTypes/definitions/SenderProfile.definition.js'; +import transactionalMessage from './metadataTypes/definitions/TransactionalMessage.definition.js'; +import transactionalEmail from './metadataTypes/definitions/TransactionalEmail.definition.js'; +import transactionalPush from './metadataTypes/definitions/TransactionalPush.definition.js'; +import transactionalSMS from './metadataTypes/definitions/TransactionalSMS.definition.js'; +import triggeredSend from './metadataTypes/definitions/TriggeredSend.definition.js'; +import triggeredSendSummary from './metadataTypes/definitions/TriggeredSendSummary.definition.js'; +import user from './metadataTypes/definitions/User.definition.js'; +import verification from './metadataTypes/definitions/Verification.definition.js'; + /** - * Provides access to all metadataType classes + * Provides access to definitions of all metadataType classes */ -const MetadataTypeDefinitions = { - accountUser: require('./metadataTypes/definitions/AccountUser.definition'), - asset: require('./metadataTypes/definitions/Asset.definition'), - attributeGroup: require('./metadataTypes/definitions/AttributeGroup.definition'), - automation: require('./metadataTypes/definitions/Automation.definition'), - campaign: require('./metadataTypes/definitions/Campaign.definition'), - contentArea: require('./metadataTypes/definitions/ContentArea.definition'), - dataExtension: require('./metadataTypes/definitions/DataExtension.definition'), - dataExtensionField: require('./metadataTypes/definitions/DataExtensionField.definition'), - dataExtensionTemplate: require('./metadataTypes/definitions/DataExtensionTemplate.definition'), - dataExtract: require('./metadataTypes/definitions/DataExtract.definition'), - dataExtractType: require('./metadataTypes/definitions/DataExtractType.definition'), - discovery: require('./metadataTypes/definitions/Discovery.definition'), - email: require('./metadataTypes/definitions/Email.definition'), - emailSendDefinition: require('./metadataTypes/definitions/EmailSendDefinition.definition'), - eventDefinition: require('./metadataTypes/definitions/EventDefinition.definition'), - fileTransfer: require('./metadataTypes/definitions/FileTransfer.definition'), - filter: require('./metadataTypes/definitions/Filter.definition'), - folder: require('./metadataTypes/definitions/Folder.definition'), - ftpLocation: require('./metadataTypes/definitions/FtpLocation.definition'), - importFile: require('./metadataTypes/definitions/ImportFile.definition'), - interaction: require('./metadataTypes/definitions/Interaction.definition'), - list: require('./metadataTypes/definitions/List.definition'), - query: require('./metadataTypes/definitions/Query.definition'), - role: require('./metadataTypes/definitions/Role.definition'), - script: require('./metadataTypes/definitions/Script.definition'), - setDefinition: require('./metadataTypes/definitions/SetDefinition.definition'), - triggeredSendDefinition: require('./metadataTypes/definitions/TriggeredSendDefinition.definition'), +export default { + asset, + attributeGroup, + attributeSet, + automation, + campaign, + contentArea, + dataFilter, + dataFilterHidden, + dataExtension, + dataExtensionField, + dataExtensionTemplate, + dataExtract, + dataExtractType, + deliveryProfile, + discovery, + domainVerification, + email, + emailSend, + event, + fileLocation, + fileTransfer, + filter, + folder, + importFile, + journey, + list, + mobileCode, + mobileKeyword, + mobileMessage, + query, + role, + script, + sendClassification, + senderProfile, + transactionalMessage, + transactionalEmail, + transactionalPush, + transactionalSMS, + triggeredSend, + triggeredSendSummary, + user, + verification, }; - -module.exports = MetadataTypeDefinitions; diff --git a/lib/MetadataTypeInfo.js b/lib/MetadataTypeInfo.js index e09ef97ce..67d99dc8b 100644 --- a/lib/MetadataTypeInfo.js +++ b/lib/MetadataTypeInfo.js @@ -1,36 +1,90 @@ 'use strict'; +import asset from './metadataTypes/Asset.js'; +import attributeGroup from './metadataTypes/AttributeGroup.js'; +import attributeSet from './metadataTypes/AttributeSet.js'; +import automation from './metadataTypes/Automation.js'; +import campaign from './metadataTypes/Campaign.js'; +import contentArea from './metadataTypes/ContentArea.js'; +import dataFilter from './metadataTypes/DataFilter.js'; +import dataFilterHidden from './metadataTypes/DataFilterHidden.js'; +import dataExtension from './metadataTypes/DataExtension.js'; +import dataExtensionField from './metadataTypes/DataExtensionField.js'; +import dataExtensionTemplate from './metadataTypes/DataExtensionTemplate.js'; +import dataExtract from './metadataTypes/DataExtract.js'; +import dataExtractType from './metadataTypes/DataExtractType.js'; +import deliveryProfile from './metadataTypes/DeliveryProfile.js'; +import discovery from './metadataTypes/Discovery.js'; +import domainVerification from './metadataTypes/DomainVerification.js'; +import email from './metadataTypes/Email.js'; +import emailSend from './metadataTypes/EmailSend.js'; +import event from './metadataTypes/Event.js'; +import fileLocation from './metadataTypes/FileLocation.js'; +import fileTransfer from './metadataTypes/FileTransfer.js'; +import filter from './metadataTypes/Filter.js'; +import folder from './metadataTypes/Folder.js'; +import importFile from './metadataTypes/ImportFile.js'; +import journey from './metadataTypes/Journey.js'; +import list from './metadataTypes/List.js'; +import mobileCode from './metadataTypes/MobileCode.js'; +import mobileKeyword from './metadataTypes/MobileKeyword.js'; +import mobileMessage from './metadataTypes/MobileMessage.js'; +import query from './metadataTypes/Query.js'; +import role from './metadataTypes/Role.js'; +import script from './metadataTypes/Script.js'; +import sendClassification from './metadataTypes/SendClassification.js'; +import senderProfile from './metadataTypes/SenderProfile.js'; +import transactionalEmail from './metadataTypes/TransactionalEmail.js'; +import transactionalPush from './metadataTypes/TransactionalPush.js'; +import transactionalSMS from './metadataTypes/TransactionalSMS.js'; +import triggeredSend from './metadataTypes/TriggeredSend.js'; +import triggeredSendSummary from './metadataTypes/TriggeredSendSummary.js'; +import user from './metadataTypes/User.js'; +import verification from './metadataTypes/Verification.js'; + /** * Provides access to all metadataType classes */ -const MetadataTypeInfo = { - accountUser: require('./metadataTypes/AccountUser'), - asset: require('./metadataTypes/Asset'), - attributeGroup: require('./metadataTypes/AttributeGroup'), - automation: require('./metadataTypes/Automation'), - campaign: require('./metadataTypes/Campaign'), - contentArea: require('./metadataTypes/ContentArea'), - dataExtension: require('./metadataTypes/DataExtension'), - dataExtensionField: require('./metadataTypes/DataExtensionField'), - dataExtensionTemplate: require('./metadataTypes/DataExtensionTemplate'), - dataExtract: require('./metadataTypes/DataExtract'), - dataExtractType: require('./metadataTypes/DataExtractType'), - discovery: require('./metadataTypes/Discovery'), - email: require('./metadataTypes/Email'), - emailSendDefinition: require('./metadataTypes/EmailSendDefinition'), - eventDefinition: require('./metadataTypes/EventDefinition'), - fileTransfer: require('./metadataTypes/FileTransfer'), - filter: require('./metadataTypes/Filter'), - folder: require('./metadataTypes/Folder'), - ftpLocation: require('./metadataTypes/FtpLocation'), - importFile: require('./metadataTypes/ImportFile'), - interaction: require('./metadataTypes/Interaction'), - list: require('./metadataTypes/List'), - query: require('./metadataTypes/Query'), - role: require('./metadataTypes/Role'), - script: require('./metadataTypes/Script'), - setDefinition: require('./metadataTypes/SetDefinition'), - triggeredSendDefinition: require('./metadataTypes/TriggeredSendDefinition'), +export default { + asset, + attributeGroup, + attributeSet, + automation, + campaign, + contentArea, + dataExtension, + dataExtensionField, + dataExtensionTemplate, + dataExtract, + dataExtractType, + dataFilter, + dataFilterHidden, + deliveryProfile, + discovery, + domainVerification, + email, + emailSend, + event, + fileLocation, + fileTransfer, + filter, + folder, + importFile, + journey, + list, + mobileCode, + mobileKeyword, + mobileMessage, + query, + role, + script, + sendClassification, + senderProfile, + transactionalEmail, + transactionalPush, + transactionalSMS, + triggeredSend, + triggeredSendSummary, + user, + verification, }; - -module.exports = MetadataTypeInfo; diff --git a/lib/Retriever.js b/lib/Retriever.js index c57e23f0d..0cab0ec5c 100644 --- a/lib/Retriever.js +++ b/lib/Retriever.js @@ -1,8 +1,29 @@ 'use strict'; -const MetadataTypeInfo = require('./MetadataTypeInfo'); -const Util = require('./util/util'); -const File = require('./util/file'); +import MetadataTypeInfo from './MetadataTypeInfo.js'; +import MetadataDefinitions from './MetadataTypeDefinitions.js'; +import { Util } from './util/util.js'; +import File from './util/file.js'; +import cache from './util/cache.js'; +import auth from './util/auth.js'; + +/** + * @typedef {import('../types/mcdev.d.js').BuObject} BuObject + * @typedef {import('../types/mcdev.d.js').CodeExtract} CodeExtract + * @typedef {import('../types/mcdev.d.js').CodeExtractItem} CodeExtractItem + * @typedef {import('../types/mcdev.d.js').Mcdevrc} Mcdevrc + * @typedef {import('../types/mcdev.d.js').MetadataTypeItem} MetadataTypeItem + * @typedef {import('../types/mcdev.d.js').MetadataTypeItemDiff} MetadataTypeItemDiff + * @typedef {import('../types/mcdev.d.js').MetadataTypeItemObj} MetadataTypeItemObj + * @typedef {import('../types/mcdev.d.js').MetadataTypeMap} MetadataTypeMap + * @typedef {import('../types/mcdev.d.js').MetadataTypeMapObj} MetadataTypeMapObj + * @typedef {import('../types/mcdev.d.js').MultiMetadataTypeList} MultiMetadataTypeList + * @typedef {import('../types/mcdev.d.js').MultiMetadataTypeMap} MultiMetadataTypeMap + * @typedef {import('../types/mcdev.d.js').SoapRequestParams} SoapRequestParams + * @typedef {import('../types/mcdev.d.js').TemplateMap} TemplateMap + * @typedef {import('../types/mcdev.d.js').TypeKeyCombo} TypeKeyCombo + */ + /** * Retrieves metadata from a business unit and saves it to the local filesystem. */ @@ -10,20 +31,11 @@ class Retriever { /** * Creates a Retriever, uses v2 auth if v2AuthOptions are passed. * - * @param {Object} properties General configuration to be used in retrieve - * @param {Object} properties.directories Directories to be used when interacting with FS - * @param {Object} buObject properties for auth - * @param {String} buObject.clientId clientId for FuelSDK auth - * @param {String} buObject.clientSecret clientSecret for FuelSDK auth - * @param {Object} buObject.credential clientId for FuelSDK auth - * @param {String} buObject.tenant v2 Auth Tenant Information - * @param {String} [buObject.mid] ID of Business Unit to authenticate with - * @param {String} [buObject.businessUnit] name of Business Unit to authenticate with - * @param {Util.ET_Client} client fuel client + * @param {Mcdevrc} properties General configuration to be used in retrieve + * @param {BuObject} buObject properties for auth */ - constructor(properties, buObject, client) { + constructor(properties, buObject) { this.buObject = buObject; - this.client = client; this.properties = properties; this.retrieveDir = properties.directories.retrieve; this.templateDir = properties.directories.template; @@ -32,113 +44,200 @@ class Retriever { buObject.credential, buObject.businessUnit, ]); - this.metadata = {}; } /** * Retrieve metadata of specified types into local file system and Retriever.metadata - * @param {String[]} metadataTypes String list of metadata types to retrieve - * @param {String} [name] name of Metadata to retrieve (in case of templating) - * @param {Object} [templateVariables] Object of values which can be replaced (in case of templating) + * + * @param {string[]} metadataTypes list of metadata types to retrieve; can include subtypes! + * @param {string[] | TypeKeyCombo} [namesOrKeys] name of Metadata to retrieveAsTemplate or list of keys for normal retrieval + * @param {TemplateMap} [templateVariables] Object of values which can be replaced (in case of templating) * @param {boolean} [changelogOnly] skip saving, only create json in memory - * @returns {Promise<Object<string,Object>>} Promise + * @returns {Promise.<MultiMetadataTypeList>} Promise of a list of retrieved items grouped by type {automation:[...], query:[...]} */ - async retrieve(metadataTypes, name, templateVariables, changelogOnly) { + async retrieve(metadataTypes, namesOrKeys, templateVariables, changelogOnly) { + /** + * @type {MultiMetadataTypeList} + */ const retrieveChangelog = {}; - for (const metadataType of Util.getMetadataHierachy(metadataTypes)) { - let result; - const [type, subType] = metadataType.split('-'); - // add metadata & client to metadata process class instead of passing cache/mapping every time - MetadataTypeInfo[type].cache = this.metadata; - MetadataTypeInfo[type].client = this.client; - MetadataTypeInfo[type].properties = this.properties; + /** @type {TypeKeyCombo} */ + const typeKeyMap = + !namesOrKeys || Array.isArray(namesOrKeys) + ? Util.createTypeKeyCombo( + metadataTypes, + Array.isArray(namesOrKeys) ? namesOrKeys : undefined + ) + : namesOrKeys; + // ensure we know which real dependencies we have to ensure we cache those completely + const dependencies = this._getTypeDependencies(metadataTypes); + const deployOrder = Util.getMetadataHierachy(metadataTypes); + for (const type in deployOrder) { + if (!MetadataTypeInfo[type]) { + throw new Error(`invalid type "${type}" in dependencies.`); + } + const subTypeArr = deployOrder[type]; + // if types were added by getMetadataHierachy() for caching, make sure the key-list is set to [null] for them which will retrieve all + // if we have a subtype, we need to find the correct key-list for it + typeKeyMap[type] ||= typeKeyMap[ + Object.keys(typeKeyMap).find((k) => k.startsWith(type + '-')) + ] || [null]; + // add client to metadata process class instead of passing every time + MetadataTypeInfo[type].client = auth.getSDK(this.buObject); + MetadataTypeInfo[type].properties = this.properties; + MetadataTypeInfo[type].buObject = this.buObject; try { - if (!metadataTypes.includes(type) && !metadataTypes.includes(metadataType)) { - if (changelogOnly) { - // no extra caching needed for list view + let result; + if ( + !metadataTypes.includes(type) && + (!Array.isArray(subTypeArr) || + (Array.isArray(subTypeArr) && + !metadataTypes.includes(`${type}-${subTypeArr?.[0]}`))) + ) { + // type not in list of types to retrieve, but is a dependency of one of them + if (changelogOnly && type !== 'folder') { + // no extra caching needed for list view except for folders continue; } - Util.logger.info(`Caching dependent Metadata: ${metadataType}`); - await Util.retryOnError( - `Retrying to cache ${metadataType}`, - async () => { - result = await MetadataTypeInfo[type].retrieveForCache( - this.buObject, - subType - ); - }, - false - ); + Util.logger.info(`Caching dependent Metadata: ${type}`); + Util.logSubtypes(subTypeArr); + result = await MetadataTypeInfo[type].retrieveForCache(null, subTypeArr); } else if (templateVariables) { - Util.logger.info(`Retrieving as Template: ${metadataType}`); - let nameArr; - if (name.includes(',')) { - nameArr = name.split(',').map((item) => - // allow whitespace in comma-separated lists - item.trim() + // type is in list of types to retrieve and we have template variables + Util.logger.info(`Retrieving as Template: ${type}`); + if (subTypeArr?.length > 1) { + Util.logger.warn( + `retrieveAsTemplate only works with one subtype, ignoring all but first subtype from your list: ${subTypeArr.join( + ', ' + )}` ); - } else { - nameArr = [name.trim()]; } - await Util.retryOnError(`Retrying ${metadataType}`, async () => { - result = await Promise.all( - nameArr.map((name) => { - // with npx and powershell spaces are not parsed correctly as part of a string - // we hence require users to put %20 in their stead and have to convert that back - name = name.split('%20').join(' '); - - return MetadataTypeInfo[type].retrieveAsTemplate( - this.templateDir, - name, - templateVariables, - subType - ); - }) - ); - }); + result = await Promise.all( + typeKeyMap[type].map((name) => + MetadataTypeInfo[type].retrieveAsTemplate( + this.templateDir, + name, + templateVariables, + subTypeArr?.[0] + ) + ) + ); } else { - Util.logger.info('Retrieving: ' + metadataType); + // type is in list of types to retrieve and we don't have template variables + let cacheResult = null; + if ( + (typeKeyMap[type].length > 1 || typeKeyMap[type][0] !== null) && + dependencies.includes(type) + ) { + // if we have a key-list and the type is a dependency, we need to cache the whole type + Util.logger.info(`Caching dependent Metadata: ${type}`); + Util.logSubtypes(subTypeArr); + cacheResult = await MetadataTypeInfo[type].retrieveForCache( + null, + subTypeArr + ); + } else if ( + dependencies.includes(type) && + Object.prototype.hasOwnProperty.call( + MetadataTypeInfo[type], + 'retrieveSharedForCache' + ) + ) { + // some types exist locally and shared from other BUs (parent and siblings). those need to be put into the cache or else we wont find them when looking for dependencies + const cacheSharedResult = + await MetadataTypeInfo[type].retrieveSharedForCache(); + cache.mergeMetadata(type, cacheSharedResult.metadata); + } + Util.logger.info( + `Retrieving: ${type}` + + (typeKeyMap[type][0] === null + ? '' + : Util.getKeysString(typeKeyMap[type])) + ); + result = await (changelogOnly + ? MetadataTypeInfo[type].retrieveChangelog(null, subTypeArr) + : Promise.all( + typeKeyMap[type].map((key) => + MetadataTypeInfo[type].retrieve( + this.savePath, + null, + subTypeArr, + key + ) + ) + )); + if (Array.isArray(result) && cacheResult !== null) { + // if we have a key-list and the type is a dependency, we need to cache the whole type + result = [cacheResult, ...result]; + } if (changelogOnly) { - await Util.retryOnError(`Retrying ${metadataType}`, async () => { - result = await MetadataTypeInfo[type].retrieveChangelog( - null, - this.buObject, - subType - ); - }); - } else { - await Util.retryOnError(`Retrying ${metadataType}`, async () => { - result = await MetadataTypeInfo[type].retrieve( - this.savePath, - null, - this.buObject, - subType - ); - }); + // add folder to changelog + for (const key of Object.keys(result.metadata)) { + MetadataTypeInfo[type].setFolderPath(result.metadata[key]); + } } } if (result) { - if (templateVariables && Array.isArray(result)) { - // so far we are only doing this for templates, hence the above if-check - this.metadata[type] = result.map((element) => element.metadata); + if (Array.isArray(result)) { + for (const result_i of result) { + if (result_i?.metadata && Object.keys(result_i.metadata).length) { + cache.mergeMetadata(type, result_i.metadata); + } + } + if ( + metadataTypes.includes(type) || + metadataTypes.some((el) => el.startsWith(type + '-')) + ) { + retrieveChangelog[type] = result + .filter((el) => !!el) + .map((element) => element.metadata); + } } else { - this.metadata[type] = result.metadata; - if (metadataTypes.includes(type) || metadataTypes.includes(metadataType)) { + cache.mergeMetadata(type, result.metadata); + if ( + metadataTypes.includes(type) || + metadataTypes.some((el) => el.startsWith(type + '-')) + ) { retrieveChangelog[type] = result.metadata; } } } } catch (ex) { - Util.logger.error(`Retriever.retrieve:: Retrieving ${metadataType} failed`); - Util.logger.debug(ex.stack); - if (Util.logger.level === 'debug') { - console.log(ex.stack); + if ( + ex.code === 'invalid_client' || + ex.message.startsWith('Client authentication failed.') + ) { + // do not continue retrieving if we logged an authentication issue + Util.logger.error(ex.message); + break; + } else { + Util.logger.errorStack(ex, ` - Retrieving ${type} failed`); } } } return retrieveChangelog; } + + /** + * helper for Retriever.retrieve to get all dependencies of the given types + * + * @param {string[]} metadataTypes list of metadata types to retrieve; can include subtypes! + * @returns {string[]} unique list dependent metadata types + */ + _getTypeDependencies(metadataTypes) { + let dependencies = []; + for (const metadataType of metadataTypes) { + const type = metadataType.split('-')[0]; + // if they have dependencies then add a dependency pair for each type + if (MetadataDefinitions[type].dependencies.length > 0) { + dependencies.push( + ...MetadataDefinitions[type].dependencies.map((dep) => dep.split('-')[0]) + ); + } + } + dependencies = [...new Set(dependencies)]; + return dependencies; + } } -module.exports = Retriever; +export default Retriever; diff --git a/lib/cli.js b/lib/cli.js index a0e82aa73..c5e6e6806 100644 --- a/lib/cli.js +++ b/lib/cli.js @@ -1,23 +1,28 @@ #!/usr/bin/env node -'use strict'; /** * CLI entry for SFMC DevTools */ -const Util = require('./util/util'); -const yargs = require('yargs'); -const Mcdev = require('./index'); +import { Util } from './util/util.js'; -yargs +import yargs from 'yargs'; +import { hideBin } from 'yargs/helpers'; +import Mcdev from './index.js'; + +// use this instead of setting "true" directly to more easily find deprecated commands in this file +const isDeprecated = true; + +/** + * @typedef {import('../types/mcdev.d.js').TypeKeyCombo} TypeKeyCombo + */ +yargs(hideBin(process.argv)) .scriptName('mcdev') .usage('$0 <command> [options]') - .command({ - command: 'retrieve [BU] [TYPE]', - aliases: ['r'], - desc: 'retrieves metadata of a business unit', - // @ts-ignore - builder: (yargs) => { + .command( + ['retrieve [BU] [TYPE] [KEY]', 'r'], + 'retrieves metadata of a business unit', + (yargs) => yargs .positional('BU', { type: 'string', @@ -27,18 +32,68 @@ yargs .positional('TYPE', { type: 'string', describe: 'metadata type that shall be exclusively downloaded', - }); - }, - handler: (argv) => { - Mcdev.setLoggingLevel(argv); - Mcdev.retrieve(argv.BU, argv.TYPE); - }, - }) - .command({ - command: 'deploy [BU] [TYPE]', - aliases: ['d'], - desc: 'deploys local metadata to a business unit', - builder: (yargs) => { + }) + .positional('KEY', { + type: 'string', + describe: 'metadata keys that shall be exclusively downloaded', + }) + .option('metadata', { + type: 'string', + array: true, + alias: 'm', + group: 'Options for retrieve:', + describe: + 'type or type:key or type:i:id or type:n:name to retrieve; if not provided, all metadata will be retrieved', + }) + .option('like', { + type: 'string', + group: 'Options for retrieve:', + describe: + 'filter metadata components (can include % as wildcard or _ for a single character)', + }) + .option('skipValidation', { + alias: 'sv', + group: 'Options for retrieve:', + describe: + 'allows reducing validation rules from error to warn to handle edge cases', + }) + .option('fix', { + group: 'Options for retrieve:', + describe: + 'should ONLY be used to identify what items would be filtered out or changed during build/deploy. This does not actually change anything on the server.', + }) + .option('format', { + type: 'boolean', + alias: 'f', + group: 'Options for retrieve:', + describe: + 'allows overwriting options.formatOnSave from the config file. Disable formatting via --no-format', + }) + .option('purge', { + type: 'boolean', + group: 'Options for retrieve:', + describe: 'deletes the relevant retrieve folder before retrieving', + }) + .option('onlyPublished', { + type: 'boolean', + alias: 'op', + group: 'Options for retrieve:', + describe: 'only retrieve the version of the metadata that was published', + }), + (argv) => { + Mcdev.setOptions(argv); + const typeKeyCombo = Mcdev.metadataToTypeKey(argv.metadata); + if ('undefined' === typeof typeKeyCombo) { + Mcdev.retrieve(argv.BU, csvToArray(argv.TYPE), csvToArray(argv.KEY)); + } else { + Mcdev.retrieve(argv.BU, typeKeyCombo); + } + } + ) + .command( + ['deploy [BU] [TYPE] [KEY]', 'd'], + 'deploys local metadata to a business unit', + (yargs) => yargs .positional('BU', { type: 'string', @@ -48,83 +103,210 @@ yargs .positional('TYPE', { type: 'string', describe: 'metadata type that shall be exclusively uploaded', - }); - }, - handler: (argv) => { - Mcdev.setLoggingLevel(argv); - Mcdev.deploy(argv.BU, argv.TYPE); - }, - }) - .command({ - command: 'init [credentialsName]', - desc: `creates '${Util.configFileName}' in your root or adds additional credentials to the existing one`, - builder: (yargs) => { + }) + .positional('KEY', { + type: 'string', + describe: 'metadata key that shall be exclusively uploaded', + }) + .option('metadata', { + type: 'string', + array: true, + alias: 'm', + group: 'Options for deploy:', + describe: + 'type or type:key or type:i:id or type:n:name to deploy; if not provided, all metadata will be deploy', + }) + .option('keySuffix', { + type: 'string', + alias: 'ks', + group: 'Options for deploy:', + describe: + 'allows you to add a suffix to the key of the metadata to be deployed', + }) + .option('autoMidSuffix', { + type: 'boolean', + group: 'Options for deploy:', + describe: + 'for asset: enables the automatic addition of the MID to the key of the deployed metadata when deploying cross-BU. Alternatively, use --keySuffix or templating-based suffixes', + }) + .option('changeKeyField', { + type: 'string', + alias: 'ckf', + group: 'Options for deploy:', + describe: + 'enables updating the key of the deployed metadata with the value in provided field (e.g. c__newKey). Can be used to sync name and key fields.', + }) + .option('changeKeyValue', { + type: 'string', + alias: 'ckv', + group: 'Options for deploy:', + describe: + 'allows updating the key of the metadata to the provided value. Only available if a single type and key is deployed', + }) + .option('fromRetrieve', { + type: 'boolean', + alias: 'fr', + group: 'Options for deploy:', + describe: 'deploy from retrieve folder', + }) + .option('refresh', { + type: 'boolean', + alias: 'r', + group: 'Options for deploy:', + describe: + 'for asset-message: runs refresh command for related triggeredSends after deploy', + }) + .option('execute', { + type: 'boolean', + alias: 'e', + group: 'Options for deploy:', + describe: 'executes item after deploy; this will run the item once immediately', + }) + .option('schedule', { + type: 'boolean', + alias: 's', + group: 'Options for deploy:', + describe: + 'start existing schedule instead of running item once immediately (only works for automations)', + }) + .option('fixShared', { + group: 'Options for deploy:', + describe: + "ensure that updates to shared DataExtensions become visible in child BU's data designer (SF Known issue W-11031095)", + }) + .option('noUpdate', { + group: 'Options for deploy:', + describe: + 'if set, no metadata will be updated, only new metadata will be created', + }) + .option('publish', { + group: 'Options for deploy:', + describe: 'publishes the entity after deploy (only works on journeys)', + }) + .option('validate', { + group: 'Options for deploy:', + describe: 'validate the entity after deploy (only works on journeys)', + }) + .option('skipStatusCheck', { + group: 'Options for deploy:', + describe: + 'only relevant if used together with --publish. if you do not care if publishing actually worked you can skip the checks with this option.', + }) + .option('matchName', { + group: 'Options for deploy:', + describe: + 'Some metadata types allow updating resources despite a key mismatch by matching the name. That avoids clean-ups on all BUs but instead allows you to continously get higher environmetns into a better shape.', + }) + .option('skipValidation', { + alias: 'sv', + group: 'Options for deploy:', + describe: + 'allows reducing validation rules from error to warn to handle edge cases', + }) + .option('format', { + type: 'boolean', + alias: 'f', + group: 'Options for deploy:', + describe: + 'allows overwriting options.formatOnSave from the config file. Disable formatting via --no-format', + }) + .option('ignoreFolder', { + type: 'boolean', + alias: 'if', + group: 'Options for deploy:', + describe: + 'works with --matchName and allows skipping folder match if there is only 1 name match', + }) + .option('ignoreSfFields', { + type: 'boolean', + alias: 'isf', + group: 'Options for deploy:', + describe: + 'relevant for Salesforce triggered journeys and events; allows ignoring errors on missing Salesforce fields in case the API returns other info than the GUI. CAUTION!', + }) + .option('fix', { + group: 'Options for deploy:', + describe: 'auto-fix validation issues if the rule is able to do it', + }), + + (argv) => { + Mcdev.setOptions(argv); + + const typeKeyCombo = Mcdev.metadataToTypeKey(argv.metadata); + if ('undefined' === typeof typeKeyCombo) { + Mcdev.deploy(argv.BU, csvToArray(argv.TYPE), csvToArray(argv.KEY)); + } else { + Mcdev.deploy(argv.BU, typeKeyCombo); + } + } + ) + .command( + ['init [credentialsName]'], + `creates '${Util.configFileName}' in your root or adds additional credentials to the existing one`, + (yargs) => yargs.positional('credentialsName', { type: 'string', describe: 'name of your installed package', - }); - }, - handler: (argv) => { - Mcdev.setLoggingLevel(argv); - Mcdev.initProject(argv.credentialsName, argv.skipInteraction); - }, + }), + (argv) => { + Mcdev.setOptions(argv); + Mcdev.initProject(argv.credentialsName); + } + ) + .command(['join'], `clones an existing project from git`, {}, (argv) => { + Mcdev.setOptions(argv); + Mcdev.joinProject(); }) - .command({ - command: 'reloadBUs [credentialsName]', - aliases: ['rb'], - desc: 'loads the list of available BUs from the server and saves it to your config', - builder: (yargs) => { + .command( + ['reloadBUs [credentialsName]', 'rb', 'refreshBUs'], + 'loads the list of available BUs from the server and saves it to your config', + (yargs) => yargs.positional('credentialsName', { type: 'string', describe: 'name of your installed package', - }); - }, - handler: (argv) => { - Mcdev.setLoggingLevel(argv); + }), + (argv) => { + Mcdev.setOptions(argv); Mcdev.findBUs(argv.credentialsName); - }, - }) - .command({ - command: 'badKeys [BU]', - desc: 'lists metadata with random API names in specified Business Unit directory', - builder: (yargs) => { + } + ) + .command( + ['badKeys [BU]'], + 'lists metadata with random API names in specified Business Unit directory', + (yargs) => yargs.positional('BU', { type: 'string', describe: 'the business unit to deploy to', - }); - }, - handler: (argv) => { - Mcdev.setLoggingLevel(argv); + }), + (argv) => { + Mcdev.setOptions(argv); Mcdev.badKeys(argv.BU); - }, - }) - .command({ - command: 'document <BU> <TYPE>', - aliases: ['doc'], - desc: 'Creates Markdown or HTML documentation for the selected type', - builder: (yargs) => { + } + ) + .command( + ['document <BU> <TYPE>', 'doc'], + 'Creates Markdown or HTML documentation for the selected type', + (yargs) => yargs - .positional('TYPE', { + .positional('BU', { type: 'string', describe: - 'metadata type to generate docs for; currently supported: dataExtension, role', + 'the business unit to generate docs for (in format "credential name/BU name")', }) - .positional('BU', { + .positional('TYPE', { type: 'string', describe: - 'the business unit to generate docs for (in format "credential name/BU name")', - }); - }, - handler: (argv) => { - Mcdev.setLoggingLevel(argv); + 'metadata type to generate docs for; currently supported: dataExtension, role', + }), + (argv) => { + Mcdev.setOptions(argv); Mcdev.document(argv.BU, argv.TYPE); - }, - }) - .command({ - command: 'delete <BU> <TYPE> <EXTERNALKEY>', - aliases: ['del'], - desc: 'deletes metadata of selected type and external key', - builder: (yargs) => { + } + ) + .command( + ['delete <BU> [TYPE] [KEY]', 'del'], + 'deletes metadata of selected type and external key', + (yargs) => yargs .positional('BU', { type: 'string', @@ -133,23 +315,64 @@ yargs }) .positional('TYPE', { type: 'string', - describe: 'metadata type to delete from; currently supported: dataExtension', + describe: 'metadata type to delete from;', }) - .positional('EXTERNALKEY', { + .positional('KEY', { type: 'string', describe: 'the key to delete', - }); - }, - handler: (argv) => { - Mcdev.setLoggingLevel(argv); - Mcdev.deleteByKey(argv.BU, argv.TYPE, argv.EXTERNALKEY); - }, - }) - .command({ - command: 'retrieveAsTemplate <BU> <TYPE> <NAME> <MARKET>', - aliases: ['rt'], - desc: 'Retrieves a specific metadata file by name for templating', - builder: (yargs) => { + }) + .option('metadata', { + type: 'string', + array: true, + alias: 'm', + group: 'Options for delete:', + describe: 'type or type:key or type:i:id or type:n:name to delete', + }), + (argv) => { + Mcdev.setOptions(argv); + const typeKeyCombo = Mcdev.metadataToTypeKey(argv.metadata, ['key', 'id']); + if ('undefined' === typeof typeKeyCombo) { + if (argv.TYPE && argv.KEY) { + Mcdev.deleteByKey(argv.BU, argv.TYPE, csvToArray(argv.KEY)); + } + } else { + Mcdev.deleteByKey(argv.BU, typeKeyCombo, null); + } + } + ) + .command( + ['resolveId <BU> <TYPE> <ID>', 'rid'], + 'resolves metadata key by ID', + (yargs) => + yargs + .positional('BU', { + type: 'string', + describe: + 'the business unit to search in (in format "credential name/BU name")', + }) + .positional('TYPE', { + type: 'string', + describe: 'metadata type to search in; currently supported: asset', + }) + .positional('ID', { + type: 'string', + describe: 'the id to resolve', + }) + .option('json', { + type: 'boolean', + group: 'Options for resolveId:', + describe: 'optionaly return info in json format', + }), + // TODO: add option --metadata + (argv) => { + Mcdev.setOptions(argv); + Mcdev.resolveId(argv.BU, argv.TYPE, argv.ID); + } + ) + .command( + ['retrieveAsTemplate <BU> <TYPE> <NAME> <MARKET>', 'rt'], + '[DEPRECATED] Retrieves a specific metadata file by name from the server for templating', + (yargs) => yargs .positional('BU', { type: 'string', @@ -167,46 +390,323 @@ yargs .positional('MARKET', { type: 'string', describe: 'market used for reverse building template', - }); - }, - handler: (argv) => { - Mcdev.setLoggingLevel(argv); - Mcdev.retrieveAsTemplate(argv.BU, argv.TYPE, argv.NAME, argv.MARKET); + }), + + (argv) => { + Mcdev.setOptions(argv); + Mcdev.retrieveAsTemplate(argv.BU, argv.TYPE, csvToArray(argv.NAME), argv.MARKET); }, - }) - .command({ - command: 'buildDefinition <BU> <TYPE> <NAME> <MARKET>', - aliases: ['bd'], - desc: 'builds metadata definition based on template', - builder: (yargs) => { + [], + isDeprecated + ) + .command( + ['clone'], + 'clones items across BUs. Alias for: mcdev build --mf __clone__ --mt __clone__', + (yargs) => + yargs + .option('metadata', { + type: 'string', + array: true, + alias: 'm', + group: 'Required parameters for clone:', + describe: 'type:key combos to clone', + demandOption: true, + }) + .option('buFrom', { + type: 'string', + alias: 'bf', + group: 'Required parameters for clone:', + describe: + 'the business unit to create the templates from (in format "credential name/BU name")', + demandOption: true, + }) + .option('buTo', { + type: 'string', + alias: 'bt', + group: 'Required parameters for clone:', + describe: 'the business unit to deploy to; required unless --bulk is set', + }) + .option('dependencies', { + type: 'boolean', + alias: 'D', + group: 'Options for clone:', + describe: 'create templates for all dependencies of the metadata component', + }) + .option('retrieve', { + type: 'boolean', + alias: 'r', + group: 'Options for clone:', + describe: + 're-retrieves potentially relevant metadata before running buildTemplate (all if --dependencies is used)', + }) + .option('skipValidation', { + alias: 'sv', + group: 'Options for clone:', + describe: + 'allows reducing validation rules from error to warn to handle edge cases', + }) + .option('purge', { + group: 'Options for clone:', + describe: + 'deletes the relevant deploy folder before building the definition. Add "--no-purge" to skip the question and not delete anything', + }), + (argv) => { + Mcdev.setOptions(argv); + const typeKeyCombo = Mcdev.metadataToTypeKey(argv.metadata); + if ('undefined' !== typeof typeKeyCombo) { + Mcdev.clone(argv.buFrom, argv.buTo, typeKeyCombo); + } + } + ) + .command( + ['build'], + 'runs buildTemplate followed by buildDefinition', + (yargs) => + yargs + .option('metadata', { + type: 'string', + array: true, + alias: 'm', + group: 'Required parameters for build:', + describe: 'type:key combos to build template for', + demandOption: true, + }) + .option('buFrom', { + type: 'string', + alias: 'bf', + group: 'Required parameters for build:', + describe: + 'the business unit to create the templates from (in format "credential name/BU name")', + demandOption: true, + }) + .option('buTo', { + type: 'string', + alias: 'bt', + group: 'Required parameters for build:', + describe: 'the business unit to deploy to; required unless --bulk is set', + }) + .option('marketFrom', { + type: 'string', + array: true, + alias: 'mf', + group: 'Required parameters for build:', + describe: 'market used for reverse building template', + demandOption: true, + }) + .option('marketTo', { + type: 'string', + array: true, + alias: 'mt', + group: 'Required parameters for build:', + describe: 'market used for building deployable definition', + demandOption: true, + }) + .option('bulk', { + type: 'boolean', + group: 'Options for build:', + describe: + 'if defined, the marketTo parameter has to be a marketList and buildDefinitionBulk is executed', + }) + .option('dependencies', { + type: 'boolean', + alias: 'D', + group: 'Options for build:', + describe: 'create templates for all dependencies of the metadata component', + }) + .option('retrieve', { + type: 'boolean', + alias: 'r', + group: 'Options for build:', + describe: + 're-retrieves potentially relevant metadata before running buildTemplate (all if --dependencies is used)', + }) + .option('skipValidation', { + alias: 'sv', + group: 'Options for build:', + describe: + 'allows reducing validation rules from error to warn to handle edge cases', + }) + .option('purge', { + group: 'Options for build:', + describe: + 'deletes the relevant deploy folder before building the definition. Add "--no-purge" to skip the question and not delete anything', + }) + .option('fix', { + group: 'Options for build:', + describe: 'auto-fix validation issues if the rule is able to do it', + }), + (argv) => { + Mcdev.setOptions(argv); + const typeKeyCombo = Mcdev.metadataToTypeKey(argv.metadata); + if ('undefined' !== typeof typeKeyCombo) { + Mcdev.build( + argv.buFrom, + argv.buTo, + typeKeyCombo, + argv.marketFrom, + argv.marketTo, + argv.bulk + ); + } + } + ) + .command( + ['buildTemplate <BU> [TYPE] [KEY] [MARKET]', 'bt'], + 'builds a template out of a specific metadata file already in your retrieve folder', + (yargs) => yargs .positional('BU', { type: 'string', - describe: 'the business unit to deploy to', + describe: + 'the business unit to create the templates from (in format "credential name/BU name")', }) .positional('TYPE', { type: 'string', describe: 'metadata type', }) - .positional('NAME', { + .positional('KEY', { type: 'string', - describe: 'name of the metadata component', + describe: 'key(s) of the metadata component(s)', }) .positional('MARKET', { + type: 'string', + describe: 'market used for reverse building template', + }) + .option('metadata', { + type: 'string', + array: true, + alias: 'm', + group: 'Options for buildTemplate:', + describe: 'type:key combos to build template for', + }) + .option('market', { + type: 'string', + array: true, + group: 'Options for buildTemplate:', + describe: 'market used for reverse building template', + }) + .option('dependencies', { + type: 'boolean', + alias: 'D', + group: 'Options for buildTemplate:', + describe: 'create templates for all dependencies of the metadata component', + }) + .option('retrieve', { + type: 'boolean', + alias: 'r', + group: 'Options for buildTemplate:', + describe: + 're-retrieves potentially relevant metadata before building (all if --dependencies is used)', + }) + .check((argv) => { + if (!argv.MARKET && !argv.market) { + throw new Error( + 'Error: You need to provide a market for reverse building the template' + ); + } + return true; + }), + (argv) => { + Mcdev.setOptions(argv); + const typeKeyCombo = Mcdev.metadataToTypeKey(argv.metadata); + if ('undefined' === typeof typeKeyCombo) { + Mcdev.buildTemplate( + argv.BU, + argv.TYPE, + csvToArray(argv.KEY), + argv.MARKET ? [argv.MARKET] : argv.market + ); + } else { + Mcdev.buildTemplate( + argv.BU, + typeKeyCombo, + null, + argv.MARKET ? [argv.MARKET] : argv.market + ); + } + } + ) + .command( + ['buildDefinition <BU> [TYPE] [FILENAME] [MARKET]', 'bd'], + 'builds metadata definition based on template', + (yargs) => + yargs + .positional('BU', { type: 'string', describe: 'the business unit to deploy to', - }); - }, - handler: (argv) => { - Mcdev.setLoggingLevel(argv); - Mcdev.buildDefinition(argv.BU, argv.TYPE, argv.NAME, argv.MARKET); - }, - }) - .command({ - command: 'buildDefinitionBulk <LISTNAME> <TYPE> <NAME>', - aliases: ['bdb'], - desc: 'builds metadata definition based on template en bulk', - builder: (yargs) => { + }) + .positional('TYPE', { + type: 'string', + describe: 'metadata type', + }) + .positional('FILENAME', { + type: 'string', + describe: 'File name of the metadata template without the extension', + }) + .positional('MARKET', { + type: 'string', + describe: 'market used for building deployable definition', + }) + .option('metadata', { + type: 'string', + array: true, + alias: 'm', + group: 'Options for buildDefinition:', + describe: 'type:templateName combos to build template for', + }) + .option('market', { + type: 'string', + array: true, + group: 'Options for buildDefinition:', + describe: 'market used for building deployable definition', + }) + .option('skipValidation', { + alias: 'sv', + group: 'Options for buildDefinition:', + describe: + 'allows reducing validation rules from error to warn to handle edge cases', + }) + .option('purge', { + group: 'Options for buildDefinition:', + describe: + 'deletes the relevant deploy folder before building the definition. Add "--no-purge" to skip the question and not delete anything', + }) + .option('fix', { + group: 'Options for buildDefinition:', + describe: 'auto-fix validation issues if the rule is able to do it', + }) + .check((argv) => { + if (!argv.MARKET && !argv.market) { + throw new Error( + 'Error: You need to provide a market for reverse building the template' + ); + } + return true; + }), + (argv) => { + Mcdev.setOptions(argv); + const typeKeyCombo = Mcdev.metadataToTypeKey(argv.metadata); + if ('undefined' === typeof typeKeyCombo) { + Mcdev.buildDefinition( + argv.BU, + argv.TYPE, + csvToArray(argv.FILENAME), + argv.MARKET ? [argv.MARKET] : argv.market + ); + } else { + Mcdev.buildDefinition( + argv.BU, + typeKeyCombo, + null, + argv.MARKET ? [argv.MARKET] : argv.market + ); + } + } + ) + .command( + ['buildDefinitionBulk <LISTNAME> [TYPE] [FILENAME]', 'bdb'], + 'builds metadata definition based on template en bulk', + (yargs) => yargs .positional('LISTNAME', { type: 'string', @@ -216,64 +716,670 @@ yargs type: 'string', describe: 'metadata type', }) - .positional('NAME', { + .positional('FILENAME', { type: 'string', - describe: 'name of the metadata component', - }); - }, - handler: (argv) => { - Mcdev.setLoggingLevel(argv); - Mcdev.buildDefinitionBulk(argv.LISTNAME, argv.TYPE, argv.NAME); - }, - }) - .command({ - command: 'selectTypes', - aliases: ['st'], - desc: 'lets you choose what metadata types to retrieve', - handler: (argv) => { - Mcdev.setLoggingLevel(argv); + describe: 'File name of the metadata template without the extension', + }) + .option('metadata', { + type: 'string', + array: true, + alias: 'm', + group: 'Options for buildDefinitionBulk:', + describe: 'type:templateName combos to build template for', + }) + .option('skipValidation', { + alias: 'sv', + group: 'Options for buildDefinitionBulk:', + describe: + 'allows reducing validation rules from error to warn to handle edge cases', + }) + .option('purge', { + group: 'Options for buildDefinitionBulk:', + describe: + 'deletes the relevant deploy folder before building the definition. Add "--no-purge" to skip the question and not delete anything', + }) + .option('fix', { + group: 'Options for buildDefinitionBulk:', + describe: 'auto-fix validation issues if the rule is able to do it', + }), + (argv) => { + Mcdev.setOptions(argv); + const typeKeyCombo = Mcdev.metadataToTypeKey(argv.metadata); + if ('undefined' === typeof typeKeyCombo) { + Mcdev.buildDefinitionBulk(argv.LISTNAME, argv.TYPE, csvToArray(argv.FILENAME)); + } else { + Mcdev.buildDefinitionBulk(argv.LISTNAME, typeKeyCombo); + } + } + ) + .command( + ['selectTypes', 'st'], + 'lets you choose what metadata types to retrieve', + {}, + (argv) => { + Mcdev.setOptions(argv); Mcdev.selectTypes(); - }, - }) - .command({ - command: 'explainTypes', - aliases: ['et'], - desc: 'explains metadata types that can be retrieved', - handler: (argv) => { - Mcdev.setLoggingLevel(argv); + } + ) + .command( + ['explainTypes', 'et'], + 'explains metadata types that can be retrieved', + (yargs) => + yargs.option('json', { + type: 'boolean', + group: 'Options for explainTypes:', + describe: 'optionaly return info in json format', + }), + (argv) => { + Mcdev.setOptions(argv); Mcdev.explainTypes(); - }, - }) - .command({ - command: 'createDeltaPkg [range] [filter]', - aliases: ['cdp'], - desc: 'Copies commit-based file delta into deploy folder', - builder: (yargs) => { + } + ) + .command( + ['createDeltaPkg [commitrange]', 'cdp'], + 'Copies commit-based file delta into deploy folder', + (yargs) => yargs - .positional('range', { + .positional('commitrange', { type: 'string', describe: 'Pull Request target branch or git commit range', }) - .positional('filter', { + .option('range', { type: 'string', + alias: ['branch', 'commit', 'R'], + group: 'Options for createDeltaPkg:', + describe: 'Pull Request target branch or git commit range', + }) + .option('filter', { + type: 'string', + group: 'Options for createDeltaPkg:', describe: - 'Disable templating & instead filter by the specified file path (comma separated)', - }); - }, - handler: (argv) => { - Mcdev.setLoggingLevel(argv); + 'Disable templating & instead filter by the specified BU path (comma separated), can include subtype, will be prefixed with "retrieve/"', + }) + .option('commitHistory', { + type: 'number', + group: 'Options for createDeltaPkg:', + describe: 'Number of commits to look back for changes (supersedes config)', + }) + .option('dependencies', { + type: 'boolean', + alias: 'D', + group: 'Options for build (run via createDeltaPkg):', + describe: 'create templates for all dependencies of the metadata component', + }) + .option('retrieve', { + type: 'boolean', + alias: 'r', + group: 'Options for build (run via createDeltaPkg):', + describe: + 're-retrieves potentially relevant metadata before running buildTemplate (all if --dependencies is used)', + }) + .option('skipValidation', { + alias: 'sv', + group: 'Options for build (run via createDeltaPkg):', + describe: + 'allows reducing validation rules from error to warn to handle edge cases', + }) + .option('purge', { + group: 'Options for build (run via createDeltaPkg):', + describe: + 'deletes the relevant deploy folder before building the definition. Add "--no-purge" to skip the question and not delete anything', + }) + .option('fix', { + group: 'Options for build (run via createDeltaPkg)', + describe: 'auto-fix validation issues if the rule is able to do it', + }), + (argv) => { + Mcdev.setOptions(argv); Mcdev.createDeltaPkg(argv); - }, - }) - .command({ - command: 'upgrade', - aliases: ['up'], - desc: 'Add NPM dependencies and IDE configuration files to your project', - handler: (argv) => { - Mcdev.setLoggingLevel(argv); - Mcdev.upgrade(argv.skipInteraction); - }, - }) + } + ) + .command( + ['getFilesToCommit <BU> <TYPE> <KEY>', 'fc'], + 'returns a list of relative paths to files one needs to include in a commit', + (yargs) => + yargs + .positional('BU', { + type: 'string', + describe: + 'the business unit to deploy to (in format "credential name/BU name")', + }) + .positional('TYPE', { + type: 'string', + describe: 'metadata type', + }) + .positional('KEY', { + type: 'string', + describe: 'key(s) of the metadata component(s)', + }), + // TODO: add option --metadata + (argv) => { + Mcdev.setOptions(argv); + Mcdev.getFilesToCommit(argv.BU, argv.TYPE, csvToArray(argv.KEY)); + } + ) + .command( + ['refresh <BU> [TYPE] [KEY]', 're'], + 'ensures that updates are properly published', + (yargs) => + yargs + .positional('BU', { + type: 'string', + describe: 'the business unit to execute the refresh on', + }) + .positional('TYPE', { + type: 'string', + describe: 'metadata type', + }) + .positional('KEY', { + type: 'string', + describe: 'key(s) of the metadata component(s)', + }) + .option('metadata', { + type: 'string', + array: true, + alias: 'm', + group: 'Options for execute:', + describe: 'type or type:key or type:i:id or type:n:name to fix', + }), + (argv) => { + Mcdev.setOptions(argv); + const typeKeyCombo = Mcdev.metadataToTypeKey(argv.metadata); + if ('undefined' === typeof typeKeyCombo) { + Mcdev.refresh(argv.BU, csvToArray(argv.TYPE), csvToArray(argv.KEY)); + } else { + Mcdev.refresh(argv.BU, typeKeyCombo); + } + } + ) + .command( + ['execute <BU> [TYPE] [KEY]', 'exec', 'start', 'resume'], + 'executes the entity', + (yargs) => + yargs + .positional('BU', { + type: 'string', + describe: 'the business unit where to start an item', + }) + .positional('TYPE', { + type: 'string', + describe: 'metadata type', + }) + .positional('KEY', { + type: 'string', + describe: 'key(s) of the metadata component(s)', + }) + .option('metadata', { + type: 'string', + array: true, + alias: 'm', + group: 'Options for execute:', + describe: 'type or type:key or type:i:id or type:n:name to fix', + }) + .option('like', { + type: 'string', + group: 'Options for execute:', + describe: + 'filter metadata components (can include % as wildcard or _ for a single character)', + }) + .option('schedule', { + type: 'boolean', + group: 'Options for execute:', + describe: + 'optionally start existing schedule instead of running item once immediately (only works for automations)', + }) + .check((argv) => { + if (!argv.TYPE && !argv.metadata) { + throw new Error( + 'Error: Either specify the metadata type after the BU or use --metadata' + ); + } + return true; + }), + (argv) => { + Mcdev.setOptions(argv); + const typeKeyCombo = Mcdev.metadataToTypeKey(argv.metadata); + if ('undefined' === typeof typeKeyCombo) { + Mcdev.execute(argv.BU, csvToArray(argv.TYPE), csvToArray(argv.KEY)); + } else { + Mcdev.execute(argv.BU, typeKeyCombo); + } + } + ) + .command( + ['publish <BU> [TYPE] [KEY]', 'activate'], + 'publishes the entity', + (yargs) => + yargs + .positional('BU', { + type: 'string', + describe: 'the business unit where to start an item', + }) + .positional('TYPE', { + type: 'string', + describe: 'metadata type', + }) + .positional('KEY', { + type: 'string', + describe: 'key(s) of the metadata component(s)', + }) + .option('metadata', { + type: 'string', + array: true, + alias: 'm', + group: 'Options for publish:', + describe: 'type or type:key or type:i:id or type:n:name to fix', + }) + .option('like', { + type: 'string', + group: 'Options for publish:', + describe: + 'filter metadata components (can include % as wildcard or _ for a single character)', + }) + .option('skipStatusCheck', { + group: 'Options for publish:', + describe: + 'if you don not care if publishing actually worked you can skip the checks', + }), + + (argv) => { + Mcdev.setOptions(argv); + const typeKeyCombo = Mcdev.metadataToTypeKey(argv.metadata); + if ('undefined' === typeof typeKeyCombo) { + Mcdev.publish(argv.BU, csvToArray(argv.TYPE), csvToArray(argv.KEY)); + } else { + Mcdev.publish(argv.BU, typeKeyCombo); + } + } + ) + .command( + ['validate <BU> [TYPE] [KEY]'], + 'validates the entity', + (yargs) => + yargs + .positional('BU', { + type: 'string', + describe: 'the business unit where to start an item', + }) + .positional('TYPE', { + type: 'string', + describe: 'metadata type', + }) + .positional('KEY', { + type: 'string', + describe: 'key(s) of the metadata component(s)', + }) + .option('metadata', { + type: 'string', + array: true, + alias: 'm', + group: 'Options for validate:', + describe: 'type or type:key or type:i:id or type:n:name to fix', + }) + .option('like', { + type: 'string', + group: 'Options for validate:', + describe: + 'filter metadata components (can include % as wildcard or _ for a single character)', + }), + + (argv) => { + Mcdev.setOptions(argv); + const typeKeyCombo = Mcdev.metadataToTypeKey(argv.metadata); + if ('undefined' === typeof typeKeyCombo) { + Mcdev.validate(argv.BU, csvToArray(argv.TYPE), csvToArray(argv.KEY)); + } else { + Mcdev.validate(argv.BU, typeKeyCombo); + } + } + ) + .command( + ['schedule <BU> [TYPE] [KEY]', 'sched'], + 'starts the predefined schedule of the item (shortcut for running execute --schedule)', + (yargs) => + yargs + .positional('BU', { + type: 'string', + describe: 'the business unit where to start an item', + }) + .positional('TYPE', { + type: 'string', + describe: 'metadata type', + }) + .positional('KEY', { + type: 'string', + describe: 'key(s) of the metadata component(s)', + }) + .option('metadata', { + type: 'string', + array: true, + alias: 'm', + group: 'Options for schedule:', + describe: 'type or type:key or type:i:id or type:n:name to fix', + }) + .option('like', { + type: 'string', + group: 'Options for schedule:', + describe: + 'filter metadata components (can include % as wildcard or _ for a single character)', + }) + .check((argv) => { + if (!argv.TYPE && !argv.metadata) { + throw new Error( + 'Error: Either specify the metadata type after the BU or use --metadata' + ); + } + return true; + }), + (argv) => { + Mcdev.setOptions(argv); + const typeKeyCombo = Mcdev.metadataToTypeKey(argv.metadata); + if ('undefined' === typeof typeKeyCombo) { + Mcdev.schedule(argv.BU, csvToArray(argv.TYPE), csvToArray(argv.KEY)); + } else { + Mcdev.schedule(argv.BU, typeKeyCombo); + } + } + ) + .command( + ['pause <BU> [TYPE] [KEY]', 'p'], + 'pauses the entity (automation etc.)', + (yargs) => + yargs + .positional('BU', { + type: 'string', + describe: 'the business unit where to start an item', + }) + .positional('TYPE', { + type: 'string', + describe: 'metadata type', + }) + .positional('KEY', { + type: 'string', + describe: 'key(s) of the metadata component(s)', + }) + .option('metadata', { + type: 'string', + array: true, + alias: 'm', + group: 'Options for pause:', + describe: 'type or type:key or type:i:id or type:n:name to fix', + }) + .option('like', { + type: 'string', + group: 'Options for pause:', + describe: + 'filter metadata components (can include % as wildcard or _ for a single character)', + }) + .check((argv) => { + if (!argv.TYPE && !argv.metadata) { + throw new Error( + 'Error: Either specify the metadata type after the BU or use --metadata' + ); + } + return true; + }), + (argv) => { + Mcdev.setOptions(argv); + const typeKeyCombo = Mcdev.metadataToTypeKey(argv.metadata); + if ('undefined' === typeof typeKeyCombo) { + Mcdev.pause(argv.BU, csvToArray(argv.TYPE), csvToArray(argv.KEY)); + } else { + Mcdev.pause(argv.BU, typeKeyCombo); + } + } + ) + .command( + ['stop <BU> [TYPE] [KEY]'], + 'stops the entity (journey etc.)', + (yargs) => + yargs + .positional('BU', { + type: 'string', + describe: 'the business unit where to start an item', + }) + .positional('TYPE', { + type: 'string', + describe: 'metadata type', + }) + .positional('KEY', { + type: 'string', + describe: 'key(s) of the metadata component(s)', + }) + .option('metadata', { + type: 'string', + array: true, + alias: 'm', + group: 'Options for pause:', + describe: 'type or type:key or type:i:id or type:n:name to fix', + }) + .option('like', { + type: 'string', + group: 'Options for pause:', + describe: + 'filter metadata components (can include % as wildcard or _ for a single character)', + }) + .check((argv) => { + if (!argv.TYPE && !argv.metadata) { + throw new Error( + 'Error: Either specify the metadata type after the BU or use --metadata' + ); + } + return true; + }), + (argv) => { + Mcdev.setOptions(argv); + const typeKeyCombo = Mcdev.metadataToTypeKey(argv.metadata); + if ('undefined' === typeof typeKeyCombo) { + Mcdev.stop(argv.BU, csvToArray(argv.TYPE), csvToArray(argv.KEY)); + } else { + Mcdev.stop(argv.BU, typeKeyCombo); + } + } + ) + .command( + ['audit <BU>'], + 'shows audit log for the entity (journey etc.)', + (yargs) => + yargs + .positional('BU', { + type: 'string', + describe: 'the business unit where to start an item', + }) + .option('metadata', { + type: 'string', + array: true, + alias: 'm', + group: 'Options for audit:', + describe: 'type or type:key or type:i:id or type:n:name to fix', + demandOption: true, + }) + .option('like', { + type: 'string', + group: 'Options for audit:', + describe: + 'filter metadata components (can include % as wildcard or _ for a single character)', + }), + (argv) => { + Mcdev.setOptions(argv); + const typeKeyCombo = Mcdev.metadataToTypeKey(argv.metadata); + Mcdev.audit(argv.BU, typeKeyCombo); + } + ) + .command( + ['fixKeys <BU> [TYPE] [KEY]', 'fx'], + 'changes the key of the items to match the name', + (yargs) => + yargs + .positional('BU', { + type: 'string', + describe: 'the business unit where to fix keys', + }) + .positional('TYPE', { + type: 'string', + describe: 'metadata type', + }) + .positional('KEY', { + type: 'string', + describe: 'key(s) of the metadata component(s)', + }) + .option('metadata', { + type: 'string', + array: true, + alias: 'm', + group: 'Options for fixKeys:', + describe: 'type or type:key or type:i:id or type:n:name to fix', + }) + .option('like', { + type: 'string', + group: 'Options for fixKeys:', + describe: + 'filter metadata components (can include % as wildcard or _ for a single character)', + }) + .option('keySuffix', { + type: 'string', + alias: 'ks', + group: 'Options for fixKeys:', + describe: + 'allows you to add a suffix to the key of the metadata to be deployed.', + }) + .option('execute', { + type: 'boolean', + alias: 'e', + group: 'Options for fixKeys:', + describe: + 'optional: executes item after deploy; this will run the item once immediately', + }) + .option('schedule', { + type: 'boolean', + alias: 's', + group: 'Options for fixKeys:', + describe: + 'optionally start existing schedule instead of running item once immediately (only works for automations)', + }) + .check((argv) => { + if (!argv.TYPE && !argv.metadata) { + throw new Error( + 'Error: Either specify the metadata type after the BU or use --metadata' + ); + } + return true; + }), + (argv) => { + Mcdev.setOptions(argv); + const typeKeyCombo = Mcdev.metadataToTypeKey(argv.metadata); + if ('undefined' === typeof typeKeyCombo) { + Mcdev.fixKeys(argv.BU, csvToArray(argv.TYPE), csvToArray(argv.KEY)); + } else { + Mcdev.fixKeys(argv.BU, typeKeyCombo); + } + } + ) + .command( + ['replaceContentBlock', 'rcb'], + 'Replaces ContentBlockById, ContentBlockByKey or ContentBlockByName functions with each other in AMPscript', + (yargs) => + yargs + .option('bu', { + type: 'string', + group: 'Required parameters for replaceContentBlock:', + describe: + 'the business unit on which to perform the operation (in format "credential name/BU name")', + demandOption: true, + }) + .option('to', { + type: 'string', + alias: 't', + choices: ['key', 'name', 'id'], + group: 'Required parameters for replaceContentBlock:', + describe: 'what ampscript function to replace it with (key, name, id)', + demandOption: true, + }) + .option('metadata', { + type: 'string', + array: true, + alias: 'm', + group: 'Optional parameters for replaceContentBlock:', + describe: 'type or type:key or type:i:id or type:n:name to fix', + }) + .option('from', { + type: 'string', + alias: 'f', + choices: ['key', 'name', 'id'], + array: true, + group: 'Optional parameters for replaceContentBlock:', + describe: + 'what ampscript function to search for (key, name, id); automatically set to values not used by --to if not provided', + }) + .option('skipRetrieve', { + type: 'boolean', + alias: 'sr', + group: 'Optional parameters for replaceContentBlock:', + describe: + 'if you have already just downloaded the metadata and want to skip the retrieve step', + }) + .option('skipDeploy', { + type: 'boolean', + group: 'Optional parameters for replaceContentBlock:', + describe: + 'if you have want to carefully examine the changed files in your retrieve folder you can run this dry-run mode which skips the deploy step at the end', + }) + .option('refresh', { + type: 'boolean', + alias: 'r', + group: 'Optional parameters for replaceContentBlock:', + describe: + 'for asset-message: runs refresh command for related triggeredSends after deploy', + }) + .check((argv) => { + if (argv.from) { + for (const from of argv.from) { + if (from == argv.to) { + throw new Error('Error: --from and --to cannot be the same'); + } + } + } + return true; + }), + (argv) => { + Mcdev.setOptions(argv); + const typeKeyCombo = Mcdev.metadataToTypeKey(argv.metadata); + Mcdev.replaceCbReference(argv.bu, typeKeyCombo, argv.to, argv.from); + } + ) + .command( + ['describeSoap <TYPE>', 'describe', 'soap'], + 'Contributor help: describes SOAP API objects and fields', + (yargs) => + yargs + .positional('TYPE', { + type: 'string', + describe: 'Soap object name', + }) + .option('bu', { + type: 'string', + group: 'Optional parameters for describeSoap:', + describe: 'defaults to _ParentBU_ but if you', + }) + .option('json', { + type: 'boolean', + group: 'Options for describeSoap:', + describe: 'optionaly return info in json format', + }), + (argv) => { + Mcdev.setOptions(argv); + Mcdev.describeSoap(argv.TYPE, argv.bu); + } + ) + .command( + ['upgrade', 'up'], + 'Add NPM dependencies and IDE configuration files to your project', + {}, + (argv) => { + Mcdev.setOptions(argv); + Mcdev.upgrade(); + } + ) .option('verbose', { type: 'boolean', description: 'Run with verbose CLI output', @@ -286,13 +1392,53 @@ yargs type: 'boolean', description: 'Only output errors to CLI', }) + .option('noLogColors', { + type: 'boolean', + description: 'do not use color codes in CLI log output', + }) + .option('noLogFile', { + type: 'boolean', + description: 'Only output log to CLI but not to files', + }) .option('skipInteraction', { alias: ['yes', 'y'], description: 'Interactive questions where possible and go with defaults instead', }) + .option('api', { + choices: ['log', 'cli'], + description: 'Print API calls to log', + }) + .option('errorLog', { + type: 'boolean', + description: 'Create a second log file that only contains error messages', + }) .demandCommand(1, 'Please enter a valid command') .strict() .recommendCommands() - .wrap(yargs.terminalWidth()) - .epilog('Copyright 2021. Accenture.') + .wrap(yargs(hideBin(process.argv)).terminalWidth()) + .epilog( + 'Copyright 2025. Accenture. Get support at https://github.com/Accenture/sfmc-devtools/issues' + ) .help().argv; + +/** + * helper to convert CSVs into an array. if only one value was given, it's also returned as an array + * + * @param {string} csv potentially comma-separated value or null + * @returns {string[]} values split into an array. + */ +function csvToArray(csv) { + // eslint-disable-next-line unicorn/no-negated-condition + return !csv + ? null + : csv.includes(',') + ? csv + .split(',') + .map((item) => + // allow whitespace in comma-separated lists + item.trim() + ) + // make sure trailing commas are ignored + .filter(Boolean) + : [csv.trim()].filter(Boolean); +} diff --git a/lib/index.js b/lib/index.js index 010862bf3..859f3cd1b 100644 --- a/lib/index.js +++ b/lib/index.js @@ -1,239 +1,187 @@ 'use strict'; -const Util = require('./util/util'); -const File = require('./util/file'); -const Init = require('./util/init'); -const InitGit = require('./util/init.git'); -const Cli = require('./util/cli'); -const DevOps = require('./util/devops'); -const BuHelper = require('./util/businessUnit'); -const Builder = require('./Builder'); -const Deployer = require('./Deployer'); -const MetadataTypeInfo = require('./MetadataTypeInfo'); -const MetadataTypeDefinitions = require('./MetadataTypeDefinitions'); -const Retriever = require('./Retriever'); -const inquirer = require('inquirer'); -let properties; +import { Util } from './util/util.js'; +import auth from './util/auth.js'; +import File from './util/file.js'; +import config from './util/config.js'; +import Init from './util/init.js'; +import InitGit from './util/init.git.js'; +import Cli from './util/cli.js'; +import DevOps from './util/devops.js'; +import BuHelper from './util/businessUnit.js'; +import Builder from './Builder.js'; +import Deployer from './Deployer.js'; +import MetadataTypeInfo from './MetadataTypeInfo.js'; +import MetadataTypeDefinitions from './MetadataTypeDefinitions.js'; +import Retriever from './Retriever.js'; +import cache from './util/cache.js'; +import ReplaceContentBlockReference from './util/replaceContentBlockReference.js'; +import pLimit from 'p-limit'; +import path from 'node:path'; + +import { confirm } from '@inquirer/prompts'; + +/** + * @typedef {import('../types/mcdev.d.js').BuObject} BuObject + * @typedef {import('../types/mcdev.d.js').CodeExtract} CodeExtract + * @typedef {import('../types/mcdev.d.js').CodeExtractItem} CodeExtractItem + * @typedef {import('../types/mcdev.d.js').DeltaPkgItem} DeltaPkgItem + * @typedef {import('../types/mcdev.d.js').Mcdevrc} Mcdevrc + * @typedef {import('../types/mcdev.d.js').MetadataTypeItem} MetadataTypeItem + * @typedef {import('../types/mcdev.d.js').MetadataTypeItemDiff} MetadataTypeItemDiff + * @typedef {import('../types/mcdev.d.js').MetadataTypeItemObj} MetadataTypeItemObj + * @typedef {import('../types/mcdev.d.js').MetadataTypeMap} MetadataTypeMap + * @typedef {import('../types/mcdev.d.js').MetadataTypeMapObj} MetadataTypeMapObj + * @typedef {import('../types/mcdev.d.js').MultiMetadataTypeList} MultiMetadataTypeList + * @typedef {import('../types/mcdev.d.js').MultiMetadataTypeMap} MultiMetadataTypeMap + * @typedef {import('../types/mcdev.d.js').SkipInteraction} SkipInteraction + * @typedef {import('../types/mcdev.d.js').SoapRequestParams} SoapRequestParams + * @typedef {import('../types/mcdev.d.js').TemplateMap} TemplateMap + * @typedef {import('../types/mcdev.d.js').TypeKeyCombo} TypeKeyCombo + * @typedef {import('../types/mcdev.d.js').ExplainType} ExplainType + * @typedef {import('../types/mcdev.d.js').ContentBlockConversionTypes} ContentBlockConversionTypes + * @typedef {import('../types/mcdev.d.js').BuildFilter} BuildFilter + */ /** * main class */ class Mcdev { /** - * handler for 'mcdev createDeltaPkg - * @param {Object} argv yargs parameters - * @param {String} [argv.range] git commit range - into deploy directory - * @param {String} [argv.filter] filter file paths that start with any - * @param {Boolean} [argv.skipInteraction] allows to skip interactive wizard - * @returns {void} - */ - static async createDeltaPkg(argv) { - properties = properties || File.loadConfigFile(); - if (!Util.checkProperties(properties)) { - return null; - } - // get source market and source BU from config - if (argv.filter) { - return DevOps.createDeltaPkg(properties, argv.range, true, argv.filter); - } else { - // If no custom filter was provided, use deployment marketLists & templating - - // check if sourceTargetMapping is valid - if ( - !properties.options.deployment.sourceTargetMapping || - !Object.keys(properties.options.deployment.sourceTargetMapping).length - ) { - Util.logger.error('Bad configuration of options.deployment.sourceTargetMapping'); - return; - } - const sourceMarketListArr = Object.keys( - properties.options.deployment.sourceTargetMapping - ); - - for (const sourceML of sourceMarketListArr) { - // check if sourceTargetMapping has valid values - // #1 check source marketlist - try { - Builder.verifyMarketList(sourceML, properties); - // remove potentially existing "description"-entry - delete properties.marketList[sourceML].description; - - const sourceMarketBuArr = Object.keys(properties.marketList[sourceML]); - if (sourceMarketBuArr.length !== 1) { - throw new Error('Only 1 BU is allowed per source marketList'); - } - if ('string' !== typeof properties.marketList[sourceML][sourceMarketBuArr[0]]) { - throw new Error('Only 1 market per BU is allowed per source marketList'); - } - } catch (ex) { - Util.logger.error('Deployment Source: ' + ex.message); - return; - } - // #2 check corresponding target marketList - let targetML; - try { - targetML = properties.options.deployment.sourceTargetMapping[sourceML]; - if ('string' !== typeof targetML) { - throw new Error( - 'Please define one target marketList per source in deployment.sourceTargetMapping (No arrays allowed)' - ); - } - Builder.verifyMarketList(targetML, properties); - // remove potentially existing "description"-entry - delete properties.marketList[targetML].description; - } catch (ex) { - Util.logger.error('Deployment Target: ' + ex.message); - } - } - // all good let's loop a second time for actual execution - for (const sourceMlName of sourceMarketListArr) { - const targetMlName = - properties.options.deployment.sourceTargetMapping[sourceMlName]; - const sourceBU = Object.keys(properties.marketList[sourceMlName])[0]; - const sourceMarket = Object.values(properties.marketList[sourceMlName])[0]; - - const delta = await DevOps.createDeltaPkg(properties, argv.range, false, sourceBU); - // If only chaing templating and buildDefinition if required - if (!delta || delta.length === 0) { - // info/error messages was printed by DevOps.createDeltaPkg() already - return; - } - Util.logger.info('============='); - - // Put files into maps. One map with BU -> type -> file (for retrieveAsTemplate) - // Other map only with type -> file (for buildDefinitionBulk) - const buTypeDelta = {}; - const typeDelta = {}; - delta - // Only template/build files that were added/updated/moved. no deletions - // ! doesn't work for folder, because their name parsing doesnt work at the moment - .filter((file) => file.gitAction !== 'delete' && file.name) - .forEach((file) => { - const buPath = `${file._credential}/${file._businessUnit}`; - if (!buTypeDelta[buPath]) { - buTypeDelta[buPath] = {}; - } - if (!buTypeDelta[buPath][file.type]) { - buTypeDelta[buPath][file.type] = []; - } - buTypeDelta[buPath][file.type].push(file.name); - - if (!typeDelta[file.type]) { - typeDelta[file.type] = []; - } - typeDelta[file.type].push(file.name); - }); - - // Run retrieve as template for each business unit for each type - Util.logger.info('Retrieve template from Git delta'); - // ! needs to be for (.. in ..) loop so that it gets executed in series - for (const bu in buTypeDelta) { - for (const type in buTypeDelta[bu]) { - Util.logger.info( - `⚡ mcdev rt ${bu} ${type} "${buTypeDelta[bu][type].join( - ',' - )}" ${sourceMarket}` - ); - await this.retrieveAsTemplate( - bu, - type, - buTypeDelta[bu][type].join(','), - sourceMarket - ); - } - } + * @returns {string} current version of mcdev + */ + static version() { + console.log('mcdev v' + Util.packageJsonMcdev.version); // eslint-disable-line no-console + return Util.packageJsonMcdev.version; + } - // Run build definitions bulk for each type - Util.logger.info(`- ✔️ Templates created`); - Util.logger.info('============='); - Util.logger.info('Build definitions from delta templates'); - if ( - properties.directories.templateBuilds == properties.directories.deploy || - (Array.isArray(properties.directories.templateBuilds) && - properties.directories.templateBuilds.includes( - properties.directories.deploy - )) - ) { - let responses; - if (!argv.skipInteraction) { - // deploy folder is in targets for definition creation - // recommend to purge their content first - const questions = [ - { - type: 'confirm', - name: 'isPurgeDeployFolder', - message: - 'Do you want to empty the deploy folder (ensures no files from previous deployments remain)?', - default: true, - }, - ]; - responses = await new Promise((resolve) => { - inquirer.prompt(questions).then((answers) => { - resolve(answers); - }); - }); - } - if (argv.skipInteraction || responses.isPurgeDeployFolders) { - // Clear output folder structure for selected sub-type - File.removeSync(File.normalizePath([properties.directories.deploy])); - } - } - const bdPromises = []; - for (const type in typeDelta) { - Util.logger.info( - `⚡ mcdev bdb ${targetMlName} ${type} "${typeDelta[type].join(',')}"` - ); - // omitting "await" to speed up creation - bdPromises.push( - this.buildDefinitionBulk(targetMlName, type, typeDelta[type].join(',')) - ); - } - await Promise.all(bdPromises); - Util.logger.info(`- ✔️ Deploy defintions created`); - if ( - properties.directories.templateBuilds == properties.directories.deploy || - (Array.isArray(properties.directories.templateBuilds) && - properties.directories.templateBuilds.includes( - properties.directories.deploy - )) - ) { - Util.logger.info(`You can now run deploy on the prepared BUs`); - } else { - Util.logger.info( - `Your templated defintions are now ready to be copied into the deploy folder. Hint: You can have this auto-copied if you adjust directories.templateBuilds in your config.` - ); - } - } - } + /** + * helper method to use unattended mode when including mcdev as a package + * + * @param {SkipInteraction} [skipInteraction] signals what to insert automatically for things usually asked via wizard + * @returns {void} + */ + static setSkipInteraction(skipInteraction) { + Util.skipInteraction = skipInteraction; } /** * configures what is displayed in the console + * * @param {object} argv list of command line parameters given by user - * @param {Boolean} [argv.silent] only errors printed to CLI - * @param {Boolean} [argv.verbose] chatty user CLI output - * @param {Boolean} [argv.debug] enables developer output & features + * @param {boolean} [argv.silent] only errors printed to CLI + * @param {boolean} [argv.verbose] chatty user CLI output + * @param {boolean} [argv.debug] enables developer output & features * @returns {void} */ static setLoggingLevel(argv) { - if (argv.silent) { - // only errors printed to CLI - Util.logger.level = 'error'; - Util.loggerTransports.console.level = 'error'; - } else if (argv.verbose) { - // chatty user cli logs - Util.logger.level = 'verbose'; - Util.loggerTransports.console.level = 'verbose'; - } else { - // default user cli logs - // TODO to be switched to "warn" when cli-process is integrated - Util.logger.level = 'info'; - Util.loggerTransports.console.level = 'info'; + Util.setLoggingLevel(argv); + } + static knownOptions = [ + '_runningTest', + '_welcomeMessageShown', + 'api', + 'autoMidSuffix', + 'changeKeyField', + 'changeKeyValue', + 'commitHistory', + 'dependencies', + 'errorLog', + 'execute', + 'filter', + 'fix', + 'fixShared', + 'format', + 'fromRetrieve', + 'ignoreFolder', + 'ignoreSfFields', + 'json', + 'keySuffix', + 'onlyPublished', + 'like', + 'matchName', + 'noLogColors', + 'noLogFile', + 'noUpdate', + 'publish', + 'purge', + 'range', + 'referenceFrom', + 'referenceTo', + 'refresh', + 'retrieve', + 'schedule', + 'skipDeploy', + 'skipInteraction', + 'skipRetrieve', + 'skipStatusCheck', + 'skipValidation', + 'validate', + ]; + + /** + * allows setting system wide / command related options + * + * @param {object} argv list of command line parameters given by user + * @returns {void} + */ + static setOptions(argv) { + for (const option of this.knownOptions) { + if (argv[option] !== undefined) { + Util.OPTIONS[option] = argv[option]; + } + } + // set logging level + const loggingOptions = ['silent', 'verbose', 'debug']; + for (const option of loggingOptions) { + if (argv[option] !== undefined) { + this.setLoggingLevel(argv); + break; + } + } + // set skip interaction + if (argv.skipInteraction !== undefined) { + this.setSkipInteraction(argv.skipInteraction); + } + } + + /** + * handler for 'mcdev createDeltaPkg + * + * @param {object} argv yargs parameters + * @param {string} [argv.commitrange] git commit range via positional + * @param {string} [argv.range] git commit range via option + * @param {string} [argv.filter] filter file paths that start with any + * @param {number} [argv.commitHistory] filter file paths that start with any + * @param {DeltaPkgItem[]} [argv.diffArr] list of files to include in delta package (skips git diff when provided) + * @returns {Promise.<DeltaPkgItem[]>} list of changed items + */ + static async createDeltaPkg(argv) { + Util.startLogger(); + Util.logger.info('Create Delta Package ::'); + const properties = await config.getProperties(); + if (!properties) { + return; } - if (argv.debug) { - // enables developer output & features. no change to actual logs - Util.logger.level = 'debug'; + if (argv.commitrange) { + Util.logger.warn( + `Depecation Notice: Please start using --range to define the commit range or target branch. The positional argument will be removed in the next major release.` + ); + } + const range = argv.commitrange || Util.OPTIONS.range; + try { + return await (argv.filter + ? // get source market and source BU from config + DevOps.getDeltaList(properties, range, true, argv.filter, argv.commitHistory) + : // If no custom filter was provided, use deployment marketLists & templating + DevOps.buildDeltaDefinitions( + properties, + range, + argv.diffArr, + argv.commitHistory + )); + } catch (ex) { + Util.logger.error(ex.message); } } @@ -241,350 +189,380 @@ class Mcdev { * @returns {Promise} . */ static async selectTypes() { - properties = properties || File.loadConfigFile(); - if (!Util.checkProperties(properties)) { - return null; + Util.startLogger(); + const properties = await config.getProperties(); + if (!properties) { + return; } + await Cli.selectTypes(properties); } + /** - * @returns {Promise} . + * @returns {ExplainType[]} list of supported types with their apiNames */ static explainTypes() { - Cli.explainTypes(); + return Cli.explainTypes(); } + /** - * @param {Boolean|Object} [skipInteraction] signals what to insert automatically for things usually asked via wizard - * @returns {Promise} . + * @returns {Promise.<boolean>} success flag */ - static async upgrade(skipInteraction) { - properties = properties || File.loadConfigFile(); + static async upgrade() { + Util.startLogger(); + const properties = await config.getProperties(false, true); if (!properties) { - Util.logger.error('No config found. Please run mcdev init'); return; } - if ((await InitGit.initGitRepo(skipInteraction)).status === 'error') { + + if ((await InitGit.initGitRepo()).status === 'error') { + return false; + } + + return Init.upgradeProject(properties, false); + } + + /** + * helper to show an off-the-logs message to users + */ + static #welcomeMessage() { + if (Util.OPTIONS._welcomeMessageShown) { + // ensure we don't spam the user in case methods are called multiple times return; } + Util.OPTIONS._welcomeMessageShown = true; - Init.upgradeProject(properties, false); + const color = Util.color; + /* eslint-disable no-console */ + if (process.env['USERDNSDOMAIN'] === 'DIR.SVC.ACCENTURE.COM') { + // Accenture internal message + console.log( + `\n` + + ` Thank you for using Accenture SFMC DevTools on your Accenture laptop!\n` + + ` We are trying to understand who is using mcdev across the globe and would therefore appreciate it if you left a message\n` + + ` in our Accenture Teams channel ${color.bgWhite}telling us about your journey with mcdev${color.reset}: ${color.fgBlue}https://go.accenture.com/mcdevTeams${color.reset}.\n` + + `\n` + + ` For any questions or concerns, please feel free to create a ticket in GitHub: ${color.fgBlue}https://bit.ly/mcdev-support${color.reset}.\n` + ); + } else { + // external message + console.log( + `\n` + + ` Thank you for using Accenture SFMC DevTools!\n` + + `\n` + + ` For any questions or concerns, please feel free to create a ticket in GitHub: ${color.fgBlue}https://bit.ly/mcdev-support${color.reset}.\n` + ); + } + /* eslint-enable no-console */ } /** * Retrieve all metadata from the specified business unit into the local file system. - * @param {String} businessUnit references credentials from properties.json - * @param {String} [selectedType] limit retrieval to given metadata type + * + * @param {string} businessUnit references credentials from properties.json + * @param {string[] | TypeKeyCombo} [selectedTypesArr] limit retrieval to given metadata type + * @param {string[]} [keys] limit retrieval to given metadata key * @param {boolean} [changelogOnly] skip saving, only create json in memory - * @returns {Promise<Object>} - + * @returns {Promise.<object>} - */ - static async retrieve(businessUnit, selectedType, changelogOnly) { + static async retrieve(businessUnit, selectedTypesArr, keys, changelogOnly) { + this.#welcomeMessage(); + console.time('Time'); // eslint-disable-line no-console + Util.startLogger(); Util.logger.info('mcdev:: Retrieve'); - properties = properties || File.loadConfigFile(); - if (!Util.checkProperties(properties)) { - // return null here to avoid seeing 2 error messages for the same issue - return null; - } - const [type, subType] = selectedType ? selectedType.split('-') : []; - if (type && !MetadataTypeInfo[type]) { - Util.logger.error(`:: '${type}' is not a valid metadata type`); - return; - } else if ( - type && - subType && - (!MetadataTypeInfo[type] || !MetadataTypeDefinitions[type].subTypes.includes(subType)) - ) { - Util.logger.error(`:: '${selectedType}' is not a valid metadata type`); + const properties = await config.getProperties(); + if (!properties) { return; } + // assume a list was passed in and check each entry's validity + if (selectedTypesArr) { + for (const selectedType of Array.isArray(selectedTypesArr) + ? selectedTypesArr + : Object.keys(selectedTypesArr)) { + if (!Util._isValidType(selectedType)) { + return; + } + } + } + const resultsObj = {}; if (businessUnit === '*') { - Util.logger.info('\n:: Retrieving all BUs for all credentials'); + Util.logger.info(':: Retrieving all BUs for all credentials'); let counter_credTotal = 0; for (const cred in properties.credentials) { - Util.logger.info(`\n:: Retrieving all BUs for ${cred}`); + Util.logger.info(`:: Retrieving all BUs for ${cred}`); let counter_credBu = 0; for (const bu in properties.credentials[cred].businessUnits) { - await this._retrieveBU(cred, bu, selectedType); + resultsObj[`${cred}/${bu}`] = await this.#retrieveBU( + cred, + bu, + selectedTypesArr, + keys + ); counter_credBu++; - Util.restartLogger(); + Util.startLogger(true); } counter_credTotal += counter_credBu; - Util.logger.info(`\n:: ${counter_credBu} BUs for ${cred}\n`); + Util.logger.info(`:: ${counter_credBu} BUs of ${cred}\n`); } - Util.logger.info(`\n:: ${counter_credTotal} BUs in total\n`); + const credentialCount = Object.keys(properties.credentials).length; + Util.logger.info( + `:: Done for ${counter_credTotal} BUs of ${credentialCount} credential${ + credentialCount === 1 ? '' : 's' + } in total\n` + ); } else { let [cred, bu] = businessUnit ? businessUnit.split('/') : [null, null]; // to allow all-BU via user selection we need to run this here already if ( properties.credentials && (!properties.credentials[cred] || - (bu !== '*' && properties.credentials[cred].businessUnits[bu])) + (bu !== '*' && !properties.credentials[cred].businessUnits[bu])) ) { const buObject = await Cli.getCredentialObject( properties, - cred !== null ? cred + '/' + bu : null, + cred === null ? null : cred + '/' + bu, null, true ); - if (buObject !== null) { + if (buObject === null) { + return; + } else { cred = buObject.credential; bu = buObject.businessUnit; - } else { - return; } } if (bu === '*' && properties.credentials && properties.credentials[cred]) { - Util.logger.info(`\n:: Retrieving all BUs for ${cred}`); + Util.logger.info(`:: Retrieving all BUs for ${cred}`); let counter_credBu = 0; for (const bu in properties.credentials[cred].businessUnits) { - await this._retrieveBU(cred, bu, selectedType); + resultsObj[`${cred}/${bu}`] = await this.#retrieveBU( + cred, + bu, + selectedTypesArr, + keys + ); counter_credBu++; - Util.restartLogger(); + Util.startLogger(true); } - Util.logger.info(`\n:: ${counter_credBu} BUs for ${cred}\n`); + Util.logger.info(`:: Done for ${counter_credBu} BUs of ${cred}\n`); } else { // retrieve a single BU; return - const retrieveChangelog = await this._retrieveBU( + const retrieveChangelog = await this.#retrieveBU( cred, bu, - selectedType, + selectedTypesArr, + keys, changelogOnly ); if (changelogOnly) { + console.timeEnd('Time'); // eslint-disable-line no-console return retrieveChangelog; + } else { + resultsObj[`${cred}/${bu}`] = retrieveChangelog; } Util.logger.info(`:: Done\n`); } } + + // merge all results into one object + for (const credBu in resultsObj) { + for (const type in resultsObj[credBu]) { + const base = resultsObj[credBu][type][0]; + + for (let i = 1; i < resultsObj[credBu][type].length; i++) { + // merge all items into the first array + Object.assign(base, resultsObj[credBu][type][i]); + } + resultsObj[credBu][type] = resultsObj[credBu][type][0]; + } + } + console.timeEnd('Time'); // eslint-disable-line no-console + + return resultsObj; } + /** - * helper for retrieve() - * @param {String} cred name of Credential - * @param {String} bu name of BU - * @param {String} [selectedType] limit retrieval to given metadata type/subtype + * helper for {@link Mcdev.retrieve} + * + * @param {string} cred name of Credential + * @param {string} bu name of BU + * @param {string[] | TypeKeyCombo} [selectedTypesArr] limit retrieval to given metadata type/subtype + * @param {string[]} [keys] limit retrieval to given metadata key * @param {boolean} [changelogOnly] skip saving, only create json in memory - * @returns {Promise<Object>} ensure that BUs are worked on sequentially + * @returns {Promise.<object>} ensure that BUs are worked on sequentially */ - static async _retrieveBU(cred, bu, selectedType, changelogOnly) { - properties = properties || File.loadConfigFile(); + static async #retrieveBU(cred, bu, selectedTypesArr, keys, changelogOnly) { + // ensure changes to the selectedTypesArr on one BU do not affect other BUs called in the same go + selectedTypesArr = structuredClone(selectedTypesArr); + + const properties = await config.getProperties(); + if (!properties) { + return; + } + const buObject = await Cli.getCredentialObject( properties, - cred !== null ? cred + '/' + bu : null, + cred === null ? null : cred + '/' + bu, null, true ); if (buObject !== null) { + cache.initCache(buObject); cred = buObject.credential; bu = buObject.businessUnit; - Util.logger.info(`\n:: Retrieving ${cred}/${bu}\n`); - let retrieveTypesArr; - const [type, subType] = selectedType ? selectedType.split('-') : []; - if ( - type && - subType && - MetadataTypeInfo[type] && - MetadataTypeDefinitions[type].subTypes.includes(subType) - ) { - // Clear output folder structure for selected sub-type - File.removeSync( - File.normalizePath([properties.directories.retrieve, cred, bu, type, subType]) - ); - retrieveTypesArr = [selectedType]; - } else if (type && MetadataTypeInfo[type]) { - // Clear output folder structure for selected type - File.removeSync( - File.normalizePath([properties.directories.retrieve, cred, bu, type]) - ); - retrieveTypesArr = [type]; - } else { - // Clear output folder structure - File.removeSync(File.normalizePath([properties.directories.retrieve, cred, bu])); + + Util.logger.info(''); + Util.logger.info(`:: Retrieving ${cred}/${bu}`); + const retrieveTypesArr = []; + if (selectedTypesArr) { + for (const selectedType of Array.isArray(selectedTypesArr) + ? selectedTypesArr + : Object.keys(selectedTypesArr)) { + const { type, subType } = Util.getTypeAndSubType(selectedType); + const removePathArr = [properties.directories.retrieve, cred, bu, type]; + if ( + type && + subType && + MetadataTypeInfo[type] && + MetadataTypeDefinitions[type].subTypes.includes(subType) + ) { + // Clear output folder structure for selected sub-type + removePathArr.push(subType); + retrieveTypesArr.push(selectedType); + } else if (type && MetadataTypeInfo[type]) { + // Clear output folder structure for selected type + retrieveTypesArr.push(type); + } + const areKeySet = Array.isArray(selectedTypesArr) + ? !!keys + : selectedTypesArr[selectedType] !== null; + if ((!areKeySet && !Util.OPTIONS.like) || Util.OPTIONS.purge) { + Util.logger.debug(`:: Cleaning output folder for ${selectedType}`); + // dont delete directories if we are just re-retrieving a single file or if we are re-retrieving only files matching the --like criteria + let isCleaned = false; + const MAX_RETRIES = 10; + let retryCount = 0; + do { + try { + await File.remove(File.normalizePath(removePathArr)); + isCleaned = true; + } catch (ex) { + // to avoid EBUSY: resource busy or locked errors on Windows, we retry after a short wait + retryCount++; + if (retryCount >= MAX_RETRIES) { + Util.logger.error( + `Failed to clean output folder for ${selectedType} after ${MAX_RETRIES} attempts: ${ex && ex.message ? ex.message : ex}` + ); + break; + } + await Util.sleep(100); + } + } while (!isCleaned); + } else { + Util.logger.debug(`:: NOT cleaning output folder for ${selectedType}`); + } + } + } + if (!retrieveTypesArr.length) { // assume no type was given and config settings are used instead: + // Clear output folder structure + await File.remove(File.normalizePath([properties.directories.retrieve, cred, bu])); // removes subtypes and removes duplicates - retrieveTypesArr = [ - ...new Set(properties.metaDataTypes.retrieve.map((type) => type.split('-')[0])), - ]; - } - let client; - try { - client = await Util.getETClient(buObject); - } catch (ex) { - Util.logger.error(ex.message); - return; + retrieveTypesArr.push( + ...new Set(properties.metaDataTypes.retrieve.map((type) => type.split('-')[0])) + ); + for (const selectedType of retrieveTypesArr) { + const test = Util._isValidType(selectedType); + if (!test) { + Util.logger.error( + `Please remove the type ${selectedType} from your ${Util.configFileName}` + ); + return; + } + } } - const retriever = new Retriever(properties, buObject, client); + const retriever = new Retriever(properties, buObject); try { // await is required or the calls end up conflicting const retrieveChangelog = await retriever.retrieve( retrieveTypesArr, - null, + Array.isArray(selectedTypesArr) ? keys : selectedTypesArr, null, changelogOnly ); - if (changelogOnly) { - return retrieveChangelog; - } - if (properties.options.documentOnRetrieve) { - // todo: find the underlying async issue that makes this wait necessary - await new Promise((resolve) => { - setTimeout(() => resolve('done!'), 1000); - }); - await this.badKeys(`${cred}/${bu}`); - } - } catch (ex) { - Util.logger.error('mcdev.retrieve failed: ' + ex.message); - Util.logger.debug(ex.stack); - if (Util.logger.level === 'debug') { - console.log(ex.stack); - } - } - } - } - /** - * helper for deploy() - * @param {String} cred name of Credential - * @param {String} bu name of BU - * @param {String} [type] limit deployment to given metadata type - * @returns {Promise} ensure that BUs are worked on sequentially - */ - static async _deployBU(cred, bu, type) { - const buPath = `${cred}/${bu}`; - Util.logger.info(`::Deploying ${buPath}`); - properties = properties || File.loadConfigFile(); - const buObject = await Cli.getCredentialObject(properties, buPath, null, true); - if (buObject !== null) { - let client; - try { - client = await Util.getETClient(buObject); - } catch (ex) { - Util.logger.error(ex.message); - return; - } - const deployer = new Deployer(properties, buObject, client, type); - try { - // await is required or the calls end up conflicting - await deployer.deploy(); + return retrieveChangelog; } catch (ex) { - Util.logger.error('mcdev.deploy failed: ' + ex.message); - Util.logger.debug(ex.stack); - if (Util.logger.level === 'debug') { - console.log(ex.stack); - } + Util.logger.errorStack(ex, 'mcdev.retrieve failed'); } } } /** * Deploys all metadata located in the 'deploy' directory to the specified business unit - * @param {String} businessUnit references credentials from properties.json - * @param {String} [selectedType] limit deployment to given metadata type - * @returns {Promise<void>} - + * + * @param {string} businessUnit references credentials from properties.json + * @param {string[] | TypeKeyCombo} [selectedTypesArr] limit deployment to given metadata type + * @param {string[]} [keyArr] limit deployment to given metadata keys + * @returns {Promise.<Object.<string, MultiMetadataTypeMap>>} deployed metadata per BU (first key: bu name, second key: metadata type) */ - static async deploy(businessUnit, selectedType) { - Util.logger.info('mcdev:: Deploy'); - properties = properties || File.loadConfigFile(); - - const [type, subType] = selectedType ? selectedType.split('-') : []; - if (type && !MetadataTypeInfo[type]) { - Util.logger.error(`:: '${type}' is not a valid metadata type`); - return; - } else if ( - type && - subType && - (!MetadataTypeInfo[type] || !MetadataTypeDefinitions[type].subTypes.includes(subType)) - ) { - Util.logger.error(`:: '${selectedType}' is not a valid metadata type`); - return; - } - let counter_credBu = 0; - if (businessUnit === '*') { - // all credentials and all BUs shall be deployed to - const deployFolders = await File.readDirectories( - properties.directories.deploy, - 2, - false - ); - for (const buPath of deployFolders.filter((r) => r.includes('/'))) { - const [cred, bu] = buPath.split('/'); - await this._deployBU(cred, bu, type); - counter_credBu++; - Util.logger.info(''); - Util.restartLogger(); - } - } else { - // anything but "*" passed in - let [cred, bu] = businessUnit ? businessUnit.split('/') : [null, null]; - - // to allow all-BU via user selection we need to run this here already - if ( - properties.credentials && - (!properties.credentials[cred] || - (bu !== '*' && properties.credentials[cred].businessUnits[bu])) - ) { - const buObject = await Cli.getCredentialObject( - properties, - cred !== null ? cred + '/' + bu : null, - null, - true - ); - if (buObject !== null) { - cred = buObject.credential; - bu = buObject.businessUnit; - } else { - return; - } - } - - if (bu === '*' && properties.credentials && properties.credentials[cred]) { - // valid credential given and -all- BUs targeted - Util.logger.info(`\n:: Deploying all BUs for ${cred}`); - let counter_credBu = 0; - // for (const bu in properties.credentials[cred].businessUnits) { - const deployFolders = await File.readDirectories( - File.normalizePath([properties.directories.deploy, cred]), - 1, - false - ); - for (const buPath of deployFolders) { - await this._deployBU(cred, buPath, type); - counter_credBu++; - Util.logger.info(''); - Util.restartLogger(); - } - Util.logger.info(`\n:: ${counter_credBu} BUs for ${cred}\n`); - } else { - // either bad credential or specific BU or no BU given - await this._deployBU(cred, bu, type); - counter_credBu++; - } - } - if (counter_credBu !== 0) { - Util.logger.info(`\n:: Deployed ${counter_credBu} BUs\n`); - } + static async deploy(businessUnit, selectedTypesArr, keyArr) { + this.#welcomeMessage(); + console.time('Time'); // eslint-disable-line no-console + Util.startLogger(); + const deployResult = await Deployer.deploy(businessUnit, selectedTypesArr, keyArr); + console.timeEnd('Time'); // eslint-disable-line no-console + return deployResult; } /** * Creates template file for properties.json + * * @param {string} [credentialsName] identifying name of the installed package / project - * @param {Boolean|Object} [skipInteraction] signals what to insert automatically for things usually asked via wizard - * @returns {Promise<void>} - + * @returns {Promise.<void>} - */ - static async initProject(credentialsName, skipInteraction) { + static async initProject(credentialsName) { + Util.startLogger(); Util.logger.info('mcdev:: Setting up project'); - properties = properties || File.loadConfigFile(!!credentialsName); - await Init.initProject(properties, credentialsName, skipInteraction); + const properties = await config.getProperties(!!credentialsName, true); + try { + await Init.initProject(properties, credentialsName); + } catch (ex) { + Util.logger.error(ex.message); + } + } + + /** + * Clones an existing project from git repository and installs it + * + * @returns {Promise.<void>} - + */ + static async joinProject() { + Util.startLogger(); + Util.logger.info('mcdev:: Joining an existing project'); + try { + await Init.joinProject(); + } catch (ex) { + Util.logger.error(ex.message); + } } /** * Refreshes BU names and ID's from MC instance + * * @param {string} credentialsName identifying name of the installed package / project - * @returns {Promise<void>} - + * @returns {Promise.<void>} - */ static async findBUs(credentialsName) { + Util.startLogger(); Util.logger.info('mcdev:: Load BUs'); - properties = properties || File.loadConfigFile(); + const properties = await config.getProperties(); + if (!properties) { + return; + } + const buObject = await Cli.getCredentialObject(properties, credentialsName, true); if (buObject !== null) { BuHelper.refreshBUProperties(properties, buObject.credential); @@ -594,19 +572,24 @@ class Mcdev { /** * Creates docs for supported metadata types in Markdown and/or HTML format * - * @param {String} businessUnit references credentials from properties.json - * @param {String} type metadata type - * @returns {Promise<void>} - + * @param {string} businessUnit references credentials from properties.json + * @param {string} type metadata type + * @returns {Promise.<void>} - */ static async document(businessUnit, type) { + Util.startLogger(); Util.logger.info('mcdev:: Document'); - properties = properties || File.loadConfigFile(); + const properties = await config.getProperties(); + if (!properties) { + return; + } + if (type && !MetadataTypeInfo[type]) { Util.logger.error(`:: '${type}' is not a valid metadata type`); return; } try { - const parentBUOnlyTypes = ['role']; + const parentBUOnlyTypes = ['user', 'role']; const buObject = await Cli.getCredentialObject( properties, parentBUOnlyTypes.includes(type) ? businessUnit.split('/')[0] : businessUnit, @@ -614,7 +597,8 @@ class Mcdev { ); if (buObject !== null) { MetadataTypeInfo[type].properties = properties; - MetadataTypeInfo[type].document(buObject); + MetadataTypeInfo[type].buObject = buObject; + MetadataTypeInfo[type].document(); } } catch (ex) { Util.logger.error('mcdev.document ' + ex.message); @@ -626,38 +610,211 @@ class Mcdev { } /** - * Creates docs for supported metadata types in Markdown and/or HTML format + * deletes metadata from MC instance by key * - * @param {String} businessUnit references credentials from properties.json - * @param {String} type supported metadata type - * @param {String} customerKey Identifier of data extension - * @returns {Promise<void>} - + * @param {string} businessUnit references credentials from properties.json + * @param {string | TypeKeyCombo} selectedTypes supported metadata type (single) or complex object + * @param {string[] | string} [keys] Identifier of metadata + * @returns {Promise.<boolean>} true if successful, false otherwise */ - static async deleteByKey(businessUnit, type, customerKey) { + static async deleteByKey(businessUnit, selectedTypes, keys) { + Util.startLogger(); Util.logger.info('mcdev:: delete'); - properties = properties || File.loadConfigFile(); - const buObject = await Cli.getCredentialObject(properties, businessUnit); - if (buObject !== null) { - if ('string' !== typeof type) { - Util.logger.error('mcdev.delete failed: Bad metadata type passed in'); + + /** @typedef {string[]} */ + let selectedTypesArr; + + /** @typedef {TypeKeyCombo} */ + let selectedTypesObj; + let keyArr; + keyArr = 'string' === typeof keys ? [keys] : keys; + if ('string' === typeof selectedTypes) { + selectedTypesArr = [selectedTypes]; + } else { + selectedTypesObj = selectedTypes; + // reset keys array because it will be overriden by values from selectedTypesObj + keyArr = null; + } + // check if types are valid + for (const selectedType of selectedTypesArr || Object.keys(selectedTypesObj)) { + if (!Util._isValidType(selectedType)) { return; } - try { - MetadataTypeInfo[type].properties = properties; - MetadataTypeInfo[type].deleteByKey(buObject, customerKey); - } catch (ex) { - Util.logger.error('mcdev.delete ' + ex.message); - } } - } + const properties = await config.getProperties(); + if (!properties) { + return; + } + + const buObject = await Cli.getCredentialObject(properties, businessUnit); + if (!buObject) { + return; + } + let client; + try { + client = auth.getSDK(buObject); + } catch (ex) { + Util.logger.error(ex.message); + return; + } + let status = true; + for (const type of selectedTypesArr || Object.keys(selectedTypesObj)) { + keyArr = selectedTypesArr ? keyArr : selectedTypesObj[type]; + if (!keyArr) { + Util.logger.error(`No keys set for ${type}`); + return; + } + MetadataTypeInfo[type].client = client; + MetadataTypeInfo[type].properties = properties; + MetadataTypeInfo[type].buObject = buObject; + + await MetadataTypeInfo[type].preDeleteTasks(keyArr); + + const deleteLimit = pLimit( + MetadataTypeInfo[type].definition.deleteSynchronously ? 1 : 20 + ); + + await Promise.allSettled( + keyArr.map((key) => + deleteLimit(async () => { + try { + const result = await MetadataTypeInfo[type].deleteByKey(key); + status &&= result; + } catch (ex) { + Util.logger.errorStack( + ex, + ` - Deleting ${type} ${key} on BU ${businessUnit} failed` + ); + status = false; + } + return status; + }) + ) + ); + } + + return status; + } + + /** + * get name & key for provided id + * + * @param {string} businessUnit references credentials from properties.json + * @param {string} type supported metadata type + * @param {string} id Identifier of metadata + * @returns {Promise.<{key:string, name:string, path:string}>} key, name and path of metadata; null if not found + */ + static async resolveId(businessUnit, type, id) { + Util.startLogger(); + if (!Util.OPTIONS.json) { + Util.logger.info('mcdev:: resolveId'); + } + if (!Util._isValidType(type)) { + return; + } + const properties = await config.getProperties(); + if (!properties) { + return; + } + + const buObject = await Cli.getCredentialObject(properties, businessUnit); + if (buObject !== null) { + try { + MetadataTypeInfo[type].client = auth.getSDK(buObject); + } catch (ex) { + Util.logger.error(ex.message); + return; + } + if (!Util.OPTIONS.json) { + Util.logger.info( + Util.getGrayMsg(` - Searching ${type} with id ${id} on BU ${businessUnit}`) + ); + } + try { + MetadataTypeInfo[type].properties = properties; + MetadataTypeInfo[type].buObject = buObject; + return await MetadataTypeInfo[type].resolveId(id); + } catch (ex) { + Util.logger.errorStack(ex, ` - Could not resolve ID of ${type} ${id}`); + } + } + } + + /** + * ensures triggered sends are restarted to ensure they pick up on changes of the underlying emails + * + * @param {string} businessUnit references credentials from properties.json + * @param {string[] | TypeKeyCombo} selectedTypes limit to given metadata types + * @param {string[]} [keys] customerkey of the metadata + * @returns {Promise.<Object.<string, Object.<string, string[]>>>} key: business unit name, key2: type, value: list of affected item keys + */ + static async refresh(businessUnit, selectedTypes, keys) { + return this.#runMethod('refresh', businessUnit, selectedTypes, keys); + } + + /** + * method for contributors to get details on SOAP objects + * + * @param {string} type references credentials from properties.json + * @param {string} [businessUnit] defaults to first credential's ParentBU + * @returns {Promise.<void>} - + */ + static async describeSoap(type, businessUnit) { + Util.startLogger(); + Util.logger.info('mcdev:: describe SOAP'); + const properties = await config.getProperties(); + if (!properties) { + return; + } + + const credential = Object.keys(properties.credentials)[0]; + businessUnit ||= + credential + '/' + Object.keys(properties.credentials[credential].businessUnits)[0]; + const buObject = await Cli.getCredentialObject(properties, businessUnit); + if (!buObject) { + return; + } + try { + const client = auth.getSDK(buObject); + const response = await client.soap.describe(type); + if (response?.ObjectDefinition?.Properties) { + Util.logger.info( + `Properties for SOAP object ${response.ObjectDefinition.ObjectType}:` + ); + const properties = response.ObjectDefinition.Properties.map((prop) => { + delete prop.PartnerKey; + delete prop.ObjectID; + return prop; + }); + if (Util.OPTIONS.json) { + console.log(JSON.stringify(properties, null, 2)); // eslint-disable-line no-console + } else { + console.table(properties); // eslint-disable-line no-console + } + return properties; + } else { + throw new Error( + `Soap object ${type} not found. Please check the spelling and retry` + ); + } + } catch (ex) { + Util.logger.error(ex.message); + } + } /** * Converts metadata to legacy format. Output is saved in 'converted' directory - * @param {String} businessUnit references credentials from properties.json - * @returns {Promise<void>} - + * + * @param {string} businessUnit references credentials from properties.json + * @returns {Promise.<void>} - */ static async badKeys(businessUnit) { - properties = properties || File.loadConfigFile(); + Util.startLogger(); + const properties = await config.getProperties(); + if (!properties) { + return; + } + const buObject = await Cli.getCredentialObject(properties, businessUnit); if (buObject !== null) { Util.logger.info('Gathering list of Name<>External Key mismatches (bad keys)'); @@ -668,29 +825,23 @@ class Mcdev { buObject.businessUnit, ]) ); - const docPath = File.filterIllegalPathChars( - properties.directories.badKeys + buObject.credential - ); + const docPath = File.normalizePath([ + properties.directories.docs, + 'badKeys', + buObject.credential, + ]); const filename = File.normalizePath([ docPath, File.filterIllegalFilenames(buObject.businessUnit) + '.badKeys.md', ]); - if (!File.existsSync(docPath)) { - File.mkdirpSync(docPath); - } else if (File.existsSync(filename)) { - File.removeSync(filename); + await File.ensureDir(docPath); + if (await File.pathExists(filename)) { + await File.remove(filename); } - const regex = RegExp('(\\w+-){4}\\w+'); - let metadata; - if (File.existsSync(retrieveDir)) { - metadata = Deployer.readBUMetadata(retrieveDir, null, true); - } else { - Util.logger.warn( - `Looks like ${retrieveDir} does not exist. If there was no metadata retrieved this is expected, in other cases re-run retrieve to attempt to fix this issue` - ); - return; - } + const regex = new RegExp(String.raw`(\w+-){4}\w+`); + await File.ensureDir(retrieveDir); + const metadata = await Deployer.readBUMetadata(retrieveDir, null, true); let output = '# List of Metadata with Name-Key mismatches\n'; for (const metadataType in metadata) { let listEntries = ''; @@ -725,27 +876,26 @@ class Mcdev { /** * Retrieve a specific metadata file and templatise. - * @param {String} businessUnit references credentials from properties.json - * @param {String} selectedType supported metadata type - * @param {String} name name of the metadata - * @param {String} market market which should be used to revert template - * @returns {Promise<void>} - + * + * @deprecated Use `retrieve` followed by `build` instead. `retrieveAsTemplate` will be removed in a future version. + * @param {string} businessUnit references credentials from properties.json + * @param {string} selectedType supported metadata type + * @param {string[]} name name of the metadata + * @param {string} market market which should be used to revert template + * @returns {Promise.<MultiMetadataTypeList>} - */ static async retrieveAsTemplate(businessUnit, selectedType, name, market) { - Util.logger.info('mcdev:: Retrieve as Template'); - properties = properties || File.loadConfigFile(); - const [type, subType] = selectedType ? selectedType.split('-') : []; - if (type && !MetadataTypeInfo[type]) { - Util.logger.error(`:: '${type}' is not a valid metadata type`); + Util.startLogger(); + Util.logDeprecated('retrieveAsTemplate', `'retrieve' followed by 'build'`); + const properties = await config.getProperties(); + if (!properties) { return; - } else if ( - type && - subType && - (!MetadataTypeInfo[type] || !MetadataTypeDefinitions[type].subTypes.includes(subType)) - ) { - Util.logger.error(`:: '${selectedType}' is not a valid metadata type`); + } + + if (!Util._isValidType(selectedType)) { return; } + const { type, subType } = Util.getTypeAndSubType(selectedType); let retrieveTypesArr; if ( @@ -760,128 +910,1585 @@ class Mcdev { } const buObject = await Cli.getCredentialObject(properties, businessUnit); if (buObject !== null) { - let client; - try { - client = await Util.getETClient(buObject); - } catch (ex) { - Util.logger.error(ex.message); - return; - } - const retriever = new Retriever(properties, buObject, client); - if (this._checkMarket(market)) { + cache.initCache(buObject); + const retriever = new Retriever(properties, buObject); + if (Util.checkMarket(market, properties)) { return retriever.retrieve(retrieveTypesArr, name, properties.markets[market]); } } } /** - * Build a specific metadata file based on a template. - * @param {String} businessUnit references credentials from properties.json - * @param {String} type supported metadata type - * @param {String} name name of the metadata - * @param {String} market market localizations - * @returns {Promise<void>} - + * @param {string} businessUnit references credentials from properties.json + * @param {TypeKeyCombo} typeKeyList limit retrieval to given metadata type + * @returns {Promise.<TypeKeyCombo>} selected types including dependencies */ - static async buildDefinition(businessUnit, type, name, market) { - Util.logger.info('mcdev:: Build Definition from Template'); - properties = properties || File.loadConfigFile(); - if (type.includes('-')) { - Util.logger.error( - `:: '${type}' is not a valid metadata type. Please don't include subtypes.` + static async addDependentCbReferences(businessUnit, typeKeyList) { + if (!Util.OPTIONS.dependencies) { + return; + } + const initialAssetNumber = typeKeyList['asset']?.length || 0; + const properties = await config.getProperties(); + if (!properties) { + return; + } + + const buObject = await Cli.getCredentialObject(properties, businessUnit); + Util.logger.info( + 'Searching for additional dependencies that were linked via ContentBlockByKey, ContentBlockByName and ContentBlockById' + ); + + await ReplaceContentBlockReference.createCache(properties, buObject, true); + + // because we re-use the replaceReference logic here we need to manually set this value + /** @type {ContentBlockConversionTypes[]} */ + Util.OPTIONS.referenceFrom = ['key', 'name', 'id']; + /** @type {ContentBlockConversionTypes} */ + Util.OPTIONS.referenceTo = 'key'; + + /** @type {Set.<string>} */ + const assetDependencies = new Set(); + const retrieveDir = File.filterIllegalPathChars( + File.normalizePath([ + properties.directories.retrieve, + buObject.credential, + buObject.businessUnit, + ]) + ); + // check all non-asset types for dependencies + for (const depType in typeKeyList) { + if ( + !Object.prototype.hasOwnProperty.call( + MetadataTypeInfo[depType], + 'replaceCbReference' + ) || + depType === 'asset' + ) { + continue; + } + MetadataTypeInfo[depType].properties = properties; + MetadataTypeInfo[depType].buObject = buObject; + await MetadataTypeInfo[depType].getCbReferenceKeys( + typeKeyList[depType], + retrieveDir, + assetDependencies ); + } + // add dependencies to selectedTypes + if (assetDependencies.size) { + const depType = 'asset'; + if (typeKeyList[depType]) { + typeKeyList[depType].push(...assetDependencies); + } else { + typeKeyList[depType] = [...assetDependencies]; + } + // remove duplicates in main object after adding dependencies + typeKeyList[depType] = [...new Set(typeKeyList[depType])]; + } + + // check all assets for dependencies recursively + if (typeKeyList.asset?.length) { + const depType = 'asset'; + const Asset = MetadataTypeInfo[depType]; + Asset.properties = properties; + Asset.buObject = buObject; + const additionalAssetDependencies = [ + ...(await Asset.getCbReferenceKeys( + typeKeyList[depType], + retrieveDir, + new Set(typeKeyList[depType]) + )), + ]; + if (additionalAssetDependencies.length) { + Util.logger.info( + `Found ${additionalAssetDependencies.length - initialAssetNumber} additional assets linked via ContentBlockByX.` + ); + } + // reset cache in case this is used progammatically somehow + Asset.getJsonFromFSCache = null; + + // remove duplicates in main object after adding dependencies + typeKeyList[depType] = [...new Set(typeKeyList[depType])]; + } + + return typeKeyList; + } + + /** + * + * @param {string} businessUnit references credentials from properties.json + * @param {TypeKeyCombo} typeKeyList limit retrieval to given metadata type + * @returns {Promise.<TypeKeyCombo>} dependencies + */ + static async addDependencies(businessUnit, typeKeyList) { + if (!Util.OPTIONS.dependencies) { return; } - if (type && !MetadataTypeInfo[type]) { - Util.logger.error(`:: '${type}' is not a valid metadata type`); + Util.logger.info( + 'You might see warnings about items not being found if you have not re-retrieved everything lately.' + ); + + // try re-retrieve without passing selectedTypes to ensure we find all dependencies + await this._reRetrieve(businessUnit, true, null, typeKeyList); + + Util.logger.info( + 'Searching for selected items and their dependencies in your project folder' + ); + /** @type {TypeKeyCombo} */ + const dependencies = {}; + /** @type {TypeKeyCombo} */ + const notFoundList = {}; + const initiallySelectedTypesArr = Object.keys(typeKeyList); + + const properties = await config.getProperties(); + if (!properties) { return; } const buObject = await Cli.getCredentialObject(properties, businessUnit); - if (buObject !== null) { - const builder = new Builder(properties, buObject, null); - if (market === '*') { - for (const oneMarket in properties.markets) { - builder.buildDefinition(type, name, properties.markets[oneMarket]); - } + for (const type of initiallySelectedTypesArr) { + MetadataTypeInfo[type].properties = properties; + MetadataTypeInfo[type].buObject = buObject; + await MetadataTypeInfo[type].getDependentFiles( + typeKeyList[type], + dependencies, + notFoundList, + true + ); + } + if (Util.getTypeKeyCount(notFoundList)) { + // if we have missing items, we need to retrieve them + Util.logger.warn( + `We recommend you retrieve the missing items with the following command and then re-run buildDefinition:` + ); + Util.logger.warn( + ` mcdev retrieve ${businessUnit} ${Util.convertTypeKeyToCli(notFoundList)}` + ); + } + + // remove duplicates & empty types + for (const type in dependencies) { + if (dependencies[type].length) { + dependencies[type] = [...new Set(dependencies[type])]; } else { - if (this._checkMarket(market)) { - builder.buildDefinition(type, name, properties.markets[market]); + delete dependencies[type]; + } + } + + // add dependencies to selectedTypes + if (Object.keys(dependencies).length) { + Util.logger.info( + `Found ${Util.getTypeKeyCount(dependencies)} items across ${Object.keys(dependencies).length} types.` + ); + for (const type in dependencies) { + if (typeKeyList[type]) { + typeKeyList[type].push(...dependencies[type]); + } else { + typeKeyList[type] = dependencies[type]; } + // remove duplicates in main object after adding dependencies + typeKeyList[type] = [...new Set(typeKeyList[type])]; } } + return dependencies; } + /** - * check if a market name exists in current mcdev config - * @param {String} market market localizations - * @returns {Boolean} found market or not + * Build a template based on a list of metadata files in the retrieve folder. + * + * @param {string} businessUnitTemplate references credentials from properties.json + * @param {string} businessUnitDefinition references credentials from properties.json + * @param {TypeKeyCombo} typeKeyCombo limit retrieval to given metadata type + * @returns {Promise.<MultiMetadataTypeList | object>} response from buildDefinition */ - static _checkMarket(market) { - properties = properties || File.loadConfigFile(); - if (properties.markets[market]) { - return true; - } else { - Util.logger.error(`Could not find the market '${market}' in your configuration file.`); - const marketArr = []; - for (const oneMarket in properties.markets) { - marketArr.push(oneMarket); + static async clone(businessUnitTemplate, businessUnitDefinition, typeKeyCombo) { + return this.build( + businessUnitTemplate, + businessUnitDefinition, + typeKeyCombo, + ['__clone__'], + ['__clone__'] + ); + } + + /** + * Build a template based on a list of metadata files in the retrieve folder. + * + * @param {string} businessUnitTemplate references credentials from properties.json + * @param {string} businessUnitDefinition references credentials from properties.json + * @param {TypeKeyCombo} typeKeyCombo limit retrieval to given metadata type + * @param {string[]} marketTemplate market localizations + * @param {string[]} marketDefinition market localizations + * @param {boolean} [bulk] runs buildDefinitionBulk instead of buildDefinition; requires marketList to be defined and given via marketDefinition + * @param {BuildFilter} [filter] market list specific filter for buildTemplate + * @returns {Promise.<MultiMetadataTypeList | object>} response from buildDefinition + */ + static async build( + businessUnitTemplate, + businessUnitDefinition, + typeKeyCombo, + marketTemplate, + marketDefinition, + bulk, + filter + ) { + if (!bulk && !businessUnitDefinition) { + Util.logger.error( + 'Please provide a business unit to deploy to via --buTo or activate --bulk' + ); + return; + } + + // check if types are valid + for (const type of Object.keys(typeKeyCombo)) { + if (!Util._isValidType(type)) { + return; } - if (marketArr.length) { - Util.logger.info('Available markets are: ' + marketArr.join(', ')); + if (!Array.isArray(typeKeyCombo[type]) || typeKeyCombo[type].length === 0) { + Util.logger.error('You need to define keys, not just types to run build'); + // we need an array of keys here + return; } - return false; } + + // redirect templates to temporary folder when executed via build() + const properties = await config.getProperties(); + if (!properties) { + return; + } + const templateDirBackup = properties.directories.template; + properties.directories.template = '.mcdev/template/'; + + Util.logger.info('mcdev:: Build Template & Build Definition'); + const templates = await this.buildTemplate( + businessUnitTemplate, + typeKeyCombo, + null, + marketTemplate, + filter + ); + // check if any templates were found + if (!Object.keys(templates).length || !Util.getTypeKeyCount(typeKeyCombo)) { + Util.logger.error('No templates created. Aborting build'); + properties.directories.template = templateDirBackup; + return; + } + + if (typeof Util.OPTIONS.purge !== 'boolean') { + // deploy folder is in targets for definition creation + // recommend to purge their content first + Util.OPTIONS.purge = await confirm({ + message: `Do you want to empty relevant BU sub-folders in /${properties.directories.deploy} (ensures no files from previous deployments remain)?`, + default: true, + }); + } + + const response = bulk + ? await this.buildDefinitionBulk(marketDefinition[0], typeKeyCombo, null) + : await this.buildDefinition( + businessUnitDefinition, + typeKeyCombo, + null, + marketDefinition + ); + + // reset temporary template folder + try { + await File.remove(properties.directories.template); + } catch { + // sometimes the first attempt is not successful for some operating system reason. Trying again mostly solves this + await File.remove(properties.directories.template); + } + properties.directories.template = templateDirBackup; + + return response; } /** - * Build a specific metadata file based on a template using a list of bu-market combos - * @param {String} listName name of list of BU-market combos - * @param {String} type supported metadata type - * @param {String} name name of the metadata - * @returns {Promise<void>} - + * Build a template based on a list of metadata files in the retrieve folder. + * + * @param {string} businessUnit references credentials from properties.json + * @param {string | TypeKeyCombo} selectedTypes limit retrieval to given metadata type + * @param {string[] | undefined} keyArr customerkey of the metadata + * @param {string[]} marketArr market localizations + * @param {BuildFilter} [filter] market list specific filter + * @returns {Promise.<MultiMetadataTypeList>} - */ - static async buildDefinitionBulk(listName, type, name) { - Util.logger.info('mcdev:: Build Definition from Template Bulk'); - properties = properties || File.loadConfigFile(); - if (!properties.marketList) { - Util.logger.error('Please define properties.marketList object in your config'); + static async buildTemplate(businessUnit, selectedTypes, keyArr, marketArr, filter) { + this.#welcomeMessage(); + + Util.startLogger(); + Util.logger.info('mcdev:: Build Template from retrieved files'); + const properties = await config.getProperties(); + if (!properties) { return; } - if (!properties.marketList[listName]) { - Util.logger.error(`Please define properties.marketList.${listName} in your config`); + const buObject = await Cli.getCredentialObject(properties, businessUnit); + if (!Util.checkMarketList(marketArr, properties)) { return; } - if (type && !MetadataTypeInfo[type]) { - Util.logger.error(`:: '${type}' is not a valid metadata type`); + + const typeKeyList = Util.checkAndPrepareTypeKeyCombo( + selectedTypes, + keyArr, + 'buildTemplate' + ); + if (!typeKeyList) { return; } - let i = 0; - for (const businessUnit in properties.marketList[listName]) { - if (businessUnit === 'description') { - // skip, it's just a metadata on this list and not a BU - continue; + this.applyKeyFilters(typeKeyList, filter); + + if (!Util.OPTIONS.dependencies) { + await this._reRetrieve(businessUnit, false, typeKeyList); + } + // convert names to keys + const retrieveDir = File.normalizePath([ + properties.directories.retrieve, + buObject.credential, + buObject.businessUnit, + ]); + for (const type of Object.keys(typeKeyList)) { + const keyArr = typeKeyList[type]; + if (keyArr.some((key) => key.startsWith('name:'))) { + // at least one key was provided as a name -> load all files from disk to try and find that key + const builTemplateCache = Object.values( + await MetadataTypeInfo[type].getJsonFromFS(retrieveDir + path.sep + type) + ); + typeKeyList[type] = keyArr + .map((key) => { + if (key.startsWith('name:')) { + // key was defined by name. try and find matching item on disk + const name = key.slice(5); + const foundKeysByName = builTemplateCache + .filter( + (item) => + name == item[MetadataTypeInfo[type].definition.nameField] + ) + .map((item) => item[MetadataTypeInfo[type].definition.keyField]); + if (foundKeysByName.length === 1) { + key = foundKeysByName[0]; + Util.logger.debug( + `- found ${type} key '${key}' for name '${name}'` + ); + return key; + } else if (foundKeysByName.length > 1) { + Util.logger.error( + `Found multiple keys (${foundKeysByName.join(', ')}) for name: ${key}` + ); + return; + } else { + Util.logger.error(`Could not find any keys for name: ${name}`); + return; + } + } else { + return key; + } + }) + .filter(Boolean); } - i++; - const market = properties.marketList[listName][businessUnit]; - let marketList = []; - if ('string' === typeof market) { - marketList.push(market); - } else { - marketList = market; + } + + // if dependencies are enabled, we need to search for them and add them to our + await this.addDependencies(businessUnit, typeKeyList); + await this.addDependentCbReferences(businessUnit, typeKeyList); + + /** @type {MultiMetadataTypeList} */ + const returnObj = {}; + for (const type of Object.keys(typeKeyList).toSorted()) { + // ensure keys are sorted again, after finding dependencies, to enhance log readability + typeKeyList[type].sort(); + + const result = await Builder.buildTemplate( + businessUnit, + type, + typeKeyList[type], + marketArr + ); + if (result[type]) { + returnObj[type] = result[type]; } - marketList.forEach((market) => { - if (market && properties.markets[market]) { - Util.logger.info(`Executing for '${businessUnit}': '${market}'`); - this.buildDefinition(businessUnit, type, name, market); - } else { - Util.logger.error( - `Could not find '${market}' in properties.markets. Please check your properties.marketList.${listName} confguration.` - ); + } + Util.logger.info(`Templated ${Util.getTypeKeyCount(returnObj)} items`); + return returnObj; + } + + /** + * helper for {@link buildTemplate} to apply include/exclude key filters + * + * @param {TypeKeyCombo | undefined} typeKeyList supported metadata type + * @param {BuildFilter} filter market list specific filter for buildTemplate + */ + static applyKeyFilters(typeKeyList, filter) { + if (!filter) { + Util.logger.debug(`no filter object defined on template market`); + return; + } + const excludeKey = filter?.exclude?.key; + if (excludeKey && Object.keys(excludeKey)?.length) { + Util.logger.debug('exclude-key-filters: ' + Object.keys(excludeKey)); + for (const type of Object.keys(typeKeyList)) { + const excludeKeyType = []; + if (excludeKey['*']) { + // if excludeKey is defined for all types, use it + excludeKeyType.push(...excludeKey['*']); + } + if (excludeKey[type]) { + // if excludeKey is defined for this type, expand list with it + excludeKeyType.push(...excludeKey[type]); + } + if (!excludeKeyType.length) { + continue; } + + typeKeyList[type] = typeKeyList[type].filter((key) => { + for (const element of excludeKeyType) { + if (Util.stringLike(key, element)) { + Util.logger.info(`🚫 ☇ filtered ${type} ${key}: exclude-filter-match`); + return false; + } + } + return true; + }); + } + } else { + Util.logger.debug(`no exclude-filter defined`); + } + const includeKey = filter?.include?.key; + if (includeKey && Object.keys(includeKey)?.length) { + Util.logger.debug('include-key-filters: ' + Object.keys(includeKey)); + for (const type of Object.keys(typeKeyList)) { + const includeKeyType = []; + if (includeKey['*']) { + // if includeKey is defined for all types, use it + includeKeyType.push(...includeKey['*']); + } + if (includeKey[type]) { + // if includeKey is defined for this type, expand list with it + includeKeyType.push(...includeKey[type]); + } + if (!includeKeyType.length) { + continue; + } + + typeKeyList[type] = typeKeyList[type].filter((key) => { + let included = false; + for (const element of includeKeyType) { + if (Util.stringLike(key, element)) { + included = true; + break; + } + } + if (!included) { + Util.logger.info(`🚫 ☇ filtered ${type} ${key}: no include-filter-match`); + return false; + } + return true; + }); + } + } else { + Util.logger.debug(`no include-filter defined`); + } + } + + /** + * Build a specific metadata file based on a template. + * + * @param {string} businessUnit references credentials from properties.json + * @param {boolean} [alwaysAsk] by default this code only runs if --retrieve is set; this flag allows to always ask + * @param {TypeKeyCombo} [selectedTypes] limit retrieval to given metadata type + * @param {TypeKeyCombo} [defaultPlusTheseTypes] if we run build for a non-standard type we need to tell it what to download on top + * @returns {Promise.<void>} - + */ + static async _reRetrieve( + businessUnit, + alwaysAsk = false, + selectedTypes, + defaultPlusTheseTypes + ) { + let runRetrieveNow; + if (!Util.OPTIONS.skipInteraction && Util.OPTIONS.retrieve === undefined && alwaysAsk) { + runRetrieveNow = await confirm({ + message: `Do you want to re-retrieve ${selectedTypes ? Util.convertTypeKeyToString(selectedTypes) : 'all metadata'} for ${businessUnit} now?`, + default: false, }); } - if (!i) { - Util.logger.error('Please define properties.marketList in your config'); + if (runRetrieveNow || Util.OPTIONS.retrieve) { + Util.logger.info( + `Re-retrieving ${businessUnit}: ${selectedTypes ? Util.convertTypeKeyToString(selectedTypes) : 'all metadata'}` + ); + /** @type {TypeKeyCombo | string[]} */ + let retrieveTypes = selectedTypes ? structuredClone(selectedTypes) : null; + if (defaultPlusTheseTypes) { + if (selectedTypes) { + // we need to work with a clone here because retrieve() modifies the object passed in as 2nd parameter + retrieveTypes = Object.assign( + retrieveTypes, + structuredClone(defaultPlusTheseTypes) + ); + } else { + const properties = await config.getProperties(); + retrieveTypes = [ + ...new Set( + properties.metaDataTypes.retrieve.map((type) => type.split('-')[0]) + ), + ...Object.keys(defaultPlusTheseTypes), + ]; + } + } + await this.retrieve(businessUnit, retrieveTypes); } } + + /** + * Build a specific metadata file based on a template. + * + * @param {string} businessUnit references credentials from properties.json + * @param {string | TypeKeyCombo} selectedTypes limit retrieval to given metadata type + * @param {string[] | undefined} nameArr name of the metadata + * @param {string[]} marketArr market localizations + * @returns {Promise.<MultiMetadataTypeList>} - + */ + static async buildDefinition(businessUnit, selectedTypes, nameArr, marketArr) { + this.#welcomeMessage(); + + Util.startLogger(); + Util.logger.info('mcdev:: Build Definition from Template'); + const properties = await config.getProperties(); + if (!properties) { + return; + } + if (!Util.checkMarketList(marketArr, properties)) { + return; + } + const typeKeyList = Util.checkAndPrepareTypeKeyCombo( + selectedTypes, + nameArr, + 'buildDefinition' + ); + if (!typeKeyList) { + return; + } + + if (Util.OPTIONS.purge) { + const buObject = await Cli.getCredentialObject(properties, businessUnit); + await Builder.purgeDeployFolder(buObject.credential + '/' + buObject.businessUnit); + } else { + Util.logger.info(` ☇ skipping purge of folder`); + } + /** @type {MultiMetadataTypeList} */ + const returnObj = {}; + for (const type of Object.keys(typeKeyList).toSorted()) { + const result = await Builder.buildDefinition( + businessUnit, + type, + typeKeyList[type], + marketArr + ); + returnObj[type] = result[type]; + } + Util.logger.info('Done'); + return returnObj; + } + + /** + * Build a specific metadata file based on a template using a list of bu-market combos + * + * @param {string} listName name of list of BU-market combos + * @param {string | TypeKeyCombo} selectedTypes supported metadata type + * @param {string[]} [nameArr] name of the metadata + * @returns {Promise.<object>} - + */ + static async buildDefinitionBulk(listName, selectedTypes, nameArr) { + this.#welcomeMessage(); + + Util.startLogger(); + Util.logger.info('mcdev:: Build Definition from Template Bulk'); + + const properties = await config.getProperties(); + if (!properties) { + return; + } + try { + Util.verifyMarketList(listName, properties); + } catch (ex) { + Util.logger.error(ex.message); + return; + } + const typeKeyList = Util.checkAndPrepareTypeKeyCombo( + selectedTypes, + nameArr, + 'buildDefinitionBulk' + ); + if (!typeKeyList) { + return; + } + if (Util.OPTIONS.purge) { + await Builder.purgeDeployFolderList(listName); + } else { + Util.logger.info(` ☇ skipping purge of folder`); + } + /** @type {MultiMetadataTypeList} */ + const returnObj = {}; + for (const type of Object.keys(typeKeyList).toSorted()) { + Util.logger.info(Util.getGrayMsg(`buildDefinitionBulk for ${type}`)); + const result = await Builder.buildDefinitionBulk(listName, type, typeKeyList[type]); + returnObj[type] = result; + } + Util.logger.info('Done'); + return returnObj; + } + + /** + * + * @param {string} businessUnit references credentials from properties.json + * @param {string} selectedType supported metadata type + * @param {string[]} keyArr customerkey of the metadata + * @returns {Promise.<string[]>} list of all files that need to be committed in a flat array ['path/file1.ext', 'path/file2.ext'] + */ + static async getFilesToCommit(businessUnit, selectedType, keyArr) { + Util.startLogger(); + Util.logger.info('mcdev:: getFilesToCommit'); + const properties = await config.getProperties(); + if (!properties) { + return; + } + if (!Util._isValidType(selectedType)) { + return; + } + if (selectedType.includes('-')) { + Util.logger.error( + `:: '${selectedType}' is not a valid metadata type. Please don't include subtypes.` + ); + return; + } + const buObject = await Cli.getCredentialObject(properties, businessUnit); + if (buObject !== null) { + return DevOps.getFilesToCommit(properties, buObject, selectedType, keyArr); + } + } + + /** + * Publish an item + * + * @param {string} businessUnit name of BU + * @param {string[] | TypeKeyCombo} selectedTypes limit to given metadata types + * @param {string[]} [keys] customerkey of the metadata + * @returns {Promise.<Object.<string, Object.<string, string[]>>>} key: business unit name, key2: type, value: list of affected item keys + */ + static async publish(businessUnit, selectedTypes, keys) { + return this.#runMethod('publish', businessUnit, selectedTypes, keys); + } + /** + * Publish an item + * + * @param {string} businessUnit name of BU + * @param {string[] | TypeKeyCombo} selectedTypes limit to given metadata types + * @param {string[]} [keys] customerkey of the metadata + * @returns {Promise.<Object.<string, Object.<string, string[]>>>} key: business unit name, key2: type, value: list of affected item keys + */ + static async validate(businessUnit, selectedTypes, keys) { + return this.#runMethod('validate', businessUnit, selectedTypes, keys); + } + + /** + * Start/execute an item + * + * @param {string} businessUnit name of BU + * @param {string[] | TypeKeyCombo} selectedTypes limit to given metadata types + * @param {string[]} [keys] customerkey of the metadata + * @returns {Promise.<Object.<string, Object.<string, string[]>>>} key: business unit name, key2: type, value: list of affected item keys + */ + static async execute(businessUnit, selectedTypes, keys) { + return this.#runMethod('execute', businessUnit, selectedTypes, keys); + } + + /** + * Schedule an item (shortcut for execute --schedule) + * + * @param {string} businessUnit name of BU + * @param {string[] | TypeKeyCombo} selectedTypes limit to given metadata types + * @param {string[]} [keys] customerkey of the metadata + * @returns {Promise.<Object.<string, Object.<string, string[]>>>} key: business unit name, key2: type, value: list of affected item keys + */ + static async schedule(businessUnit, selectedTypes, keys) { + return this.#runMethod('schedule', businessUnit, selectedTypes, keys); + } + + /** + * pause an item + * + * @param {string} businessUnit name of BU + * @param {string[] | TypeKeyCombo} selectedTypes limit to given metadata types + * @param {string[]} [keys] customerkey of the metadata + * @returns {Promise.<Object.<string, Object.<string, string[]>>>} key: business unit name, key2: type, value: list of affected item keys + */ + static async pause(businessUnit, selectedTypes, keys) { + return this.#runMethod('pause', businessUnit, selectedTypes, keys); + } + + /** + * stop an item + * + * @param {string} businessUnit name of BU + * @param {string[] | TypeKeyCombo} selectedTypes limit to given metadata types + * @param {string[]} [keys] customerkey of the metadata + * @returns {Promise.<Object.<string, Object.<string, string[]>>>} key: business unit name, key2: type, value: list of affected item keys + */ + static async stop(businessUnit, selectedTypes, keys) { + return this.#runMethod('stop', businessUnit, selectedTypes, keys); + } + + /** + * stop an item + * + * @param {string} businessUnit name of BU + * @param {TypeKeyCombo} selectedTypes limit to given metadata types + * @returns {Promise.<Object.<string, Object.<string, string[]>>>} key: business unit name, key2: type, value: list of affected item keys + */ + static async audit(businessUnit, selectedTypes) { + return this.#runMethod('audit', businessUnit, selectedTypes); + } + + /** + * Updates the key to match the name field + * + * @param {string} businessUnit name of BU + * @param {TypeKeyCombo | undefined} selectedTypesObj limit retrieval to given metadata type + * @param {string} to what to replace with + * @param {string[]} [fromList] what to replace + * @returns {Promise.<Object.<string, object>>} key1: business unit name, key2:type value: list of fixed item keys + */ + static async replaceCbReference(businessUnit, selectedTypesObj, to, fromList) { + const allowedFromTo = ['key', 'name', 'id']; + if (!allowedFromTo.includes(to)) { + Util.logger.error( + `Invalid value for argument: --to, Given: "${to}", Choices: "${allowedFromTo.join('", "')}"` + ); + return; + } + + if (fromList) { + if (!Array.isArray(fromList)) { + // equalize to array + fromList = [fromList]; + } + for (const from of fromList) { + if (!allowedFromTo.includes(from)) { + Util.logger.error( + `Invalid value for argument: --from, Given: "${from}", Choices: "${allowedFromTo.join('", "')}"` + ); + } + if (from == to) { + Util.logger.error('--from and --to cannot be the same'); + } + } + } + + // define final from/to values and, if from was not set, auto-set it to remaining values not set for to + const referenceFrom = fromList || allowedFromTo.filter((item) => item !== to); + const referenceTo = to; + + // if called via CLI, saving the from/to values in OPTIONS was done already, but we need to cover package includes as well + this.setOptions({ referenceFrom, referenceTo }); + + const properties = await config.getProperties(); + if (!properties) { + return; + } + if (!Util.isValidBU(properties, businessUnit)) { + return; + } + + /** @typedef {string[]} */ + let selectedTypesArr; + if (selectedTypesObj) { + // check if types are valid + for (const selectedType of Object.keys(selectedTypesObj)) { + if (!Util._isValidType(selectedType)) { + return; + } + } + } else { + // do it for all types that have a replaceCbReference method + selectedTypesArr = [ + ...new Set( + properties.metaDataTypes.retrieve + .map((type) => type.split('-')[0]) + .filter((type) => + Object.prototype.hasOwnProperty.call( + MetadataTypeInfo[type], + 'replaceCbReference' + ) + ) + ), + ]; + } + Util.logger.info( + `:: Replacing ${referenceFrom.map((from) => 'ContentBlockBy' + Util.capitalizeFirstLetter(from)).join(' and ')} with ContentBlockBy${Util.capitalizeFirstLetter(to)} for ${(Array.isArray( + selectedTypesArr + ) + ? selectedTypesArr + : Object.keys(selectedTypesObj) + ).join(', ')}` + ); + + const response = await this.#runMethod( + 'replaceCbReference', + businessUnit, + selectedTypesArr || selectedTypesObj + ); + + return response; + } + + /** + * Updates the key to match the name field + * + * @param {string} businessUnit name of BU + * @param {string[] | TypeKeyCombo} selectedTypes limit retrieval to given metadata type + * @param {string[]} [keys] customerkey of the metadata + * @returns {Promise.<Object.<string, object>>} key1: business unit name, key2:type value: list of fixed item keys + */ + static async fixKeys(businessUnit, selectedTypes, keys) { + const properties = await config.getProperties(); + if (!properties) { + return; + } + // make sure validation rules dont keep us from fixing the keys + this.setOptions({ skipValidation: true }); + let reRetrieveAll = false; + + /** @typedef {string[]} */ + let selectedTypesArr; + + /** @typedef {TypeKeyCombo} */ + let selectedTypesObj; + if (selectedTypes) { + // check if types are valid + for (const selectedType of Array.isArray(selectedTypes) + ? selectedTypes + : Object.keys(selectedTypes)) { + if (!Util._isValidType(selectedType)) { + return; + } + } + if (Array.isArray(selectedTypes)) { + selectedTypesArr = selectedTypes; + } else { + selectedTypesObj = selectedTypes; + } + } else { + // do it for all standard retrieve types + selectedTypesArr = [ + ...new Set( + properties.metaDataTypes.retrieve + .map((type) => type.split('-')[0]) + .filter( + (type) => + !MetadataTypeDefinitions[type].keyIsFixed && + MetadataTypeDefinitions[type].keyField !== + MetadataTypeDefinitions[type].nameField && + MetadataTypeDefinitions[type].keyField !== + MetadataTypeDefinitions[type].idField + ) + ), + ]; + Util.logger.info( + `:: Fixing keys for ${selectedTypesArr ? selectedTypesArr.join(', ') : Object.keys(selectedTypesObj).join(', ')}` + ); + reRetrieveAll = true; + this.setOptions({ + skipInteraction: { fixKeysReretrieve: false }, + }); + } + // `Type 'event' is not supported for fixKeys for compatibility reasons. Draft Journeys would otherwise be broken after the key change. If you do need to update an event key, use deploy --changeKeyValue or --changeKeyField instead.`; + if (Array.isArray(selectedTypes) && selectedTypes.includes('event')) { + selectedTypesArr = selectedTypes.filter((type) => type !== 'event'); + } else if (selectedTypesObj && selectedTypesObj.event) { + delete selectedTypesObj.event; + } + + const response = await this.#runMethod( + 'fixKeys', + businessUnit, + selectedTypesArr || selectedTypesObj, + keys + ); + + if (reRetrieveAll) { + // only done if selectedTypesArr is set as fallback + Util.logger.info( + `Retrieving latest versions of ${selectedTypesArr.join(', ')} from server` + ); + const buObject = await Cli.getCredentialObject(properties, businessUnit, null, true); + const retriever = new Retriever(properties, buObject); + await retriever.retrieve(selectedTypesArr, null, null, false); + } + return response; + } + + /** + * run a method across BUs + * + * @param {'schedule'|'execute'|'pause'|'stop'|'publish'|'validate'|'fixKeys'|'replaceCbReference'|'refresh'|'audit'} methodName what to run + * @param {string} businessUnit name of BU + * @param {string[] | TypeKeyCombo} [selectedTypes] limit to given metadata types + * @param {string[]} [keys] customerkey of the metadata + * @returns {Promise.<Object.<string, Object.<string, string[]>>>} key: business unit name, key2: type, value: list of affected item keys + */ + static async #runMethod(methodName, businessUnit, selectedTypes, keys) { + Util.startLogger(); + let lang_past; + let lang_present; + let requireType; + let requireKeyOrLike; + let checkMetadataSupport; + /** @type {Object.<string, Object.<string, string[]>>} */ + const resultObj = {}; + + switch (methodName) { + case 'schedule': { + lang_past = 'scheduled'; + lang_present = 'scheduling'; + requireType = true; + requireKeyOrLike = true; + checkMetadataSupport = true; + break; + } + case 'execute': { + lang_past = 'executed'; + lang_present = 'executing'; + requireType = true; + requireKeyOrLike = true; + checkMetadataSupport = true; + break; + } + case 'pause': { + lang_past = 'paused'; + lang_present = 'pausing'; + requireType = true; + requireKeyOrLike = true; + checkMetadataSupport = true; + break; + } + case 'stop': { + lang_past = 'stopped'; + lang_present = 'stopping'; + requireType = true; + requireKeyOrLike = true; + checkMetadataSupport = true; + break; + } + case 'publish': { + lang_past = 'published'; + lang_present = 'publishing'; + requireType = true; + requireKeyOrLike = true; + checkMetadataSupport = true; + break; + } + case 'validate': { + lang_past = 'validated'; + lang_present = 'validating'; + requireType = true; + requireKeyOrLike = true; + checkMetadataSupport = true; + break; + } + case 'fixKeys': { + lang_past = 'fixed keys'; + lang_present = 'fixing keys'; + requireType = false; + requireKeyOrLike = false; + checkMetadataSupport = false; + break; + } + case 'replaceCbReference': { + lang_past = 'replaced references'; + lang_present = 'replacing references'; + requireType = false; + requireKeyOrLike = false; + checkMetadataSupport = true; + break; + } + case 'refresh': { + lang_past = 'refreshed'; + lang_present = 'refreshing'; + requireType = true; + requireKeyOrLike = false; + checkMetadataSupport = true; + break; + } + case 'audit': { + lang_past = 'audited'; + lang_present = 'auditing'; + requireType = true; + requireKeyOrLike = true; + checkMetadataSupport = true; + break; + } + } + + /** @typedef {string[]} */ + let selectedTypesArr; + + /** @typedef {TypeKeyCombo} */ + let selectedTypesObj; + if (selectedTypes) { + // check if types are valid + for (const selectedType of Array.isArray(selectedTypes) + ? selectedTypes + : Object.keys(selectedTypes)) { + if (!Util._isValidType(selectedType)) { + return resultObj; + } + if ( + checkMetadataSupport && + !Object.prototype.hasOwnProperty.call( + MetadataTypeInfo[selectedType], + methodName + ) + ) { + Util.logger.error( + ` ☇ skipping ${selectedType}: ${methodName} is not supported yet for ${selectedType}` + ); + return resultObj; + } + } + if (Array.isArray(selectedTypes)) { + selectedTypesArr = selectedTypes; + } else { + selectedTypesObj = selectedTypes; + } + } + if ( + requireType && + !Array.isArray(selectedTypesArr) && + (!selectedTypesObj || !Object.keys(selectedTypesObj).length) + ) { + Util.logger.error('At least one metadata type needs to be defined.'); + return resultObj; + } + const properties = await config.getProperties(); + if (!properties) { + return; + } + for (const selectedType of selectedTypesArr || Object.keys(selectedTypesObj)) { + Util.logger.info(`mcdev:: ${methodName} ${selectedType}`); + let counter_credBu = 0; + let counter_credKeys = 0; + const keyArr = selectedTypesArr ? keys : selectedTypesObj[selectedType]; + if ( + requireKeyOrLike && + (!Array.isArray(keyArr) || !keyArr.length) && + (!Util.OPTIONS.like || !Object.keys(Util.OPTIONS.like).length) + ) { + Util.logger.error('At least one key or a --like filter is required.'); + return resultObj; + } else if ( + Array.isArray(keyArr) && + keyArr.length && + Util.OPTIONS.like && + Object.keys(Util.OPTIONS.like).length + ) { + Util.logger.error('You can either specify keys OR a --like filter.'); + return resultObj; + } + + if (businessUnit === '*') { + Util.OPTIONS._multiBuExecution = true; + Util.logger.info( + `:: ${lang_present} the ${selectedType} on all BUs for all credentials` + ); + let counter_credTotal = 0; + for (const cred in properties.credentials) { + Util.logger.info(`:: ${lang_present} ${selectedType} on all BUs for ${cred}`); + // reset counter per cred + counter_credKeys = 0; + counter_credBu = 0; + for (const bu in properties.credentials[cred].businessUnits) { + resultObj[cred + '/' + bu] ||= {}; + resultObj[cred + '/' + bu][selectedType] = await this.#runOnBU( + methodName, + cred, + bu, + selectedType, + keyArr + ); + counter_credBu++; + counter_credKeys += resultObj[cred + '/' + bu][selectedType].length; + Util.startLogger(true); + } + counter_credTotal += counter_credBu; + Util.logger.info( + `:: ${lang_past} for ${counter_credKeys} ${selectedType}s on ${counter_credBu} BUs for ${cred}` + ); + } + Util.logger.info( + `:: ${lang_past} ${selectedType} on ${counter_credTotal} BUs in total\n` + ); + } else { + let [cred, bu] = businessUnit ? businessUnit.split('/') : [null, null]; + // to allow all-BU via user selection we need to run this here already + if ( + properties.credentials && + (!properties.credentials[cred] || + (bu !== '*' && !properties.credentials[cred].businessUnits[bu])) + ) { + const buObject = await Cli.getCredentialObject( + properties, + cred === null ? null : cred + '/' + bu, + null, + true + ); + if (buObject === null) { + return resultObj; + } else { + cred = buObject.credential; + bu = buObject.businessUnit; + } + } + if (bu === '*' && properties.credentials && properties.credentials[cred]) { + Util.OPTIONS._multiBuExecution = true; + Util.logger.info(`:: ${lang_present} ${selectedType} on all BUs for ${cred}`); + for (const bu in properties.credentials[cred].businessUnits) { + resultObj[cred + '/' + bu] ||= {}; + resultObj[cred + '/' + bu][selectedType] = await this.#runOnBU( + methodName, + cred, + bu, + selectedType, + keyArr + ); + counter_credBu++; + counter_credKeys += resultObj[cred + '/' + bu][selectedType].length; + Util.startLogger(true); + } + Util.logger.info( + `:: ${lang_past} for ${counter_credKeys} ${selectedType}s on ${counter_credBu} BUs for ${cred}` + ); + } else { + // execute runMethod for the entity on one BU only + resultObj[cred + '/' + bu] ||= {}; + resultObj[cred + '/' + bu][selectedType] = await this.#runOnBU( + methodName, + cred, + bu, + selectedType, + keyArr + ); + Util.logger.info(`:: Done`); + } + } + } + return resultObj; + } + + /** + * helper for Mcdev.#runMethod + * + * @param {'schedule'|'execute'|'pause'|'stop'|'publish'|'validate'|'fixKeys'|'replaceCbReference'|'refresh'|'audit'} methodName what to run + * @param {string} cred name of Credential + * @param {string} bu name of BU + * @param {string} [type] limit execution to given metadata type + * @param {string[]} [keyArr] customerkey of the metadata + * @returns {Promise.<string[]>} list of keys that were affected + */ + static async #runOnBU(methodName, cred, bu, type, keyArr) { + const properties = await config.getProperties(); + if (!properties) { + return; + } + const resultArr = []; + const buObject = await Cli.getCredentialObject( + properties, + cred === null ? null : cred + '/' + bu, + null, + true + ); + try { + if (!type) { + throw new Error('No type was provided'); + } + if (buObject !== null) { + cache.initCache(buObject); + cred = buObject.credential; + bu = buObject.businessUnit; + } + Util.logger.info(`:: ${methodName} ${type} on ${cred}/${bu}`); + MetadataTypeInfo[type].client = auth.getSDK(buObject); + + MetadataTypeInfo[type].properties = properties; + MetadataTypeInfo[type].buObject = buObject; + switch (methodName) { + case 'fixKeys': { + { + resultArr.push(...(await this.#fixKeys(cred, bu, type, keyArr))); + + break; + } + } + case 'replaceCbReference': { + { + resultArr.push(...(await this.#replaceCbReference(cred, bu, type, keyArr))); + + break; + } + } + default: { + if (Util.OPTIONS.like && Object.keys(Util.OPTIONS.like).length) { + keyArr = await this.#retrieveKeysWithLike(type, buObject); + } + resultArr.push(...(await MetadataTypeInfo[type][methodName](keyArr))); + } + } + } catch (ex) { + Util.logger.errorStack(ex, 'mcdev.' + methodName + ' failed'); + } + + return resultArr; + } + + /** + * helper for Mcdev.#runOnBU + * + * @param {string} selectedType limit execution to given metadata type + * @param {BuObject} buObject properties for auth + * @returns {Promise.<string[]>} keyArr + */ + static async #retrieveKeysWithLike(selectedType, buObject) { + const properties = await config.getProperties(); + if (!properties) { + return; + } + + // cache depenencies + const deployOrder = Util.getMetadataHierachy([selectedType]); + for (const type in deployOrder) { + const subTypeArr = deployOrder[type]; + MetadataTypeInfo[type].client = auth.getSDK(buObject); + MetadataTypeInfo[type].properties = properties; + MetadataTypeInfo[type].buObject = buObject; + Util.logger.info(`Caching dependent Metadata: ${type}`); + Util.logSubtypes(subTypeArr); + const result = await MetadataTypeInfo[type].retrieveForCache(null, subTypeArr); + if (result) { + if (Array.isArray(result)) { + for (const result_i of result) { + if (result_i?.metadata && Object.keys(result_i.metadata).length) { + cache.mergeMetadata(type, result_i.metadata); + } + } + } else { + cache.setMetadata(type, result.metadata); + } + } + } + + // find all keys in chosen type that match the like-filter + const keyArr = []; + const metadataMap = cache.getCache()[selectedType]; + if (!metadataMap) { + throw new Error(`Selected type ${selectedType} could not be cached`); + } + Util.logger.info( + Util.getGrayMsg(`Found ${Object.keys(metadataMap).length} ${selectedType}s`) + ); + for (const originalKey in metadataMap) { + // hide postRetrieveOutput + Util.setLoggingLevel({ silent: true }); + metadataMap[originalKey] = await MetadataTypeInfo[selectedType].postRetrieveTasks( + metadataMap[originalKey] + ); + // reactivate logging + Util.setLoggingLevel({}); + + if (Util.fieldsLike(metadataMap[originalKey], MetadataTypeDefinitions[selectedType])) { + keyArr.push(originalKey); + } + } + Util.logger.info( + Util.getGrayMsg( + `Identified ${keyArr.length} ${selectedType}${ + keyArr.length === 1 ? '' : 's' + } that match${keyArr.length === 1 ? 'es' : ''} the like-filter` + ) + ); + + return keyArr; + } + + /** + * Updates the key to match the name field + * + * @param {string} cred name of Credential + * @param {string} bu name of BU + * @param {string} type limit execution to given metadata type + * @param {string[]} [keyArr] customerkey of the metadata + * @returns {Promise.<string[]>} list of keys that were affected + */ + static async #fixKeys(cred, bu, type, keyArr) { + const properties = await config.getProperties(); + if (!properties) { + return; + } + /** @type {string[]} */ + let actuallyFixedKeys; + const resultArr = []; + + if ( + MetadataTypeDefinitions[type].keyIsFixed === true || + MetadataTypeDefinitions[type].keyField === MetadataTypeDefinitions[type].idField + ) { + Util.logger.error(`Key cannot be updated for this type`); + return resultArr; + } + + const buObject = await Cli.getCredentialObject( + properties, + cred === null ? null : cred + '/' + bu, + null, + true + ); + try { + Util.logger.info(`Retrieving latest versions of ${type} from server`); + const retriever = new Retriever(properties, buObject); + const retrieved = await retriever.retrieve([type], keyArr, null, false); + + const metadataMap = Object.values(retrieved)[0][0]; + const keysForDeploy = MetadataTypeInfo[type].getKeysForFixing(metadataMap); + if (keysForDeploy.length < 1) { + Util.logger.warn( + `No items found with a key-name mismatch that match your criteria.\n` + ); + return resultArr; + } + this.setOptions({ + changeKeyField: MetadataTypeDefinitions[type].nameField, + fromRetrieve: true, + }); + const deployed = await Deployer.deploy(cred + '/' + bu, [type], keysForDeploy); + actuallyFixedKeys = Object.keys(Object.values(Object.values(deployed)[0])[0]); + resultArr.push(...actuallyFixedKeys); + const dependentTypes = await Util.getDependentMetadata(type); + if (actuallyFixedKeys && actuallyFixedKeys.length) { + Util.logger.info( + `Successfully updated ${actuallyFixedKeys.length} key${ + actuallyFixedKeys.length === 1 ? '' : 's' + } of type ${type}` + ); + if (dependentTypes.length) { + Util.logger.warn( + `Please re-retrieve the following types as your local copies might now be outdated: ${Util.getGrayMsg( + dependentTypes.join(', ') + )}` + ); + const reRetrieve = await Cli.postFixKeysReretrieve(dependentTypes); + if (reRetrieve) { + Util.logger.info( + `Retrieving latest versions of ${dependentTypes.join(', ')} from server` + ); + const retriever = new Retriever(properties, buObject); + await retriever.retrieve(dependentTypes, null, null, false); + } + } else { + Util.logger.info( + `No dependent types found that need to be re-retrieved after fixing keys of type ${type}.` + ); + } + } else { + Util.logger.warn(`No keys of type ${type} updated.`); + } + } catch (ex) { + Util.logger.errorStack(ex, 'mcdev.fixKeys failed'); + } + return resultArr; + } + + /** + * Updates the key to match the name field + * + * @param {string} cred name of Credential + * @param {string} bu name of BU + * @param {string} type limit execution to given metadata type + * @param {string[]} [keyArr] customerkey of the metadata + * @returns {Promise.<string[]>} list of keys that were affected + */ + static async #replaceCbReference(cred, bu, type, keyArr) { + const properties = await config.getProperties(); + if (!properties) { + return; + } + /** @type {string[]} */ + let updatedKeys; + const resultArr = []; + + const buObject = await Cli.getCredentialObject( + properties, + cred === null ? null : cred + '/' + bu, + null, + true + ); + const savePath = File.normalizePath([ + properties.directories.retrieve, + buObject.credential, + buObject.businessUnit, + ]); + + await ReplaceContentBlockReference.createCache(properties, buObject); + + try { + let metadataMap; + if (Util.OPTIONS.skipRetrieve) { + Util.logger.warn( + 'Skipping retrieve due to --skipRetrieve flag. Hope you know what you are doing.' + ); + metadataMap = await MetadataTypeInfo[type].getJsonFromFS( + File.normalizePath([savePath, type]) + ); + } else { + Util.logger.info(`Retrieving latest versions of ${type} from server`); + const retriever = new Retriever(properties, buObject); + const retrieved = await retriever.retrieve([type], keyArr); + metadataMap = Object.values(retrieved)[0][0]; + } + const keysForDeploy = await MetadataTypeInfo[type].replaceCbReferenceLoop( + metadataMap, + savePath + ); + + if (keysForDeploy.length < 1) { + Util.logger.warn(`No items found that can be updated.\n`); + return resultArr; + } + if (Util.OPTIONS.skipDeploy) { + resultArr.push(...keysForDeploy); + Util.logger.warn('DRY-RUN MODE: Skipping deploy due to --skipDeploy flag.'); + Util.logger.info( + 'Once you are satisfied with the result, re-run without --skipRetrieve nor --skipDeploy to actually deploy the changes or run:' + ); + Util.logger.info(` mcdev d ${cred}/${bu} ${type} "${keysForDeploy.join(',')}"`); + } else { + this.setOptions({ + fromRetrieve: true, + }); + const deployed = await Deployer.deploy(cred + '/' + bu, [type], keysForDeploy); + updatedKeys = Object.keys(Object.values(Object.values(deployed)[0])[0]); + resultArr.push(...updatedKeys); + if (updatedKeys && updatedKeys.length) { + Util.logger.info( + `Successfully updated ${updatedKeys.length} item${ + updatedKeys.length === 1 ? '' : 's' + } of type ${type}` + ); + } else { + Util.logger.warn(`Nothing updated for type ${type}`); + } + } + } catch (ex) { + Util.logger.errorStack(ex, 'mcdev.replaceCbReference failed'); + } + return resultArr; + } + + /** + * helper to convert CSVs into an array. if only one value was given, it's also returned as an array + * + * @param {string|string[]|undefined} metadataOption potentially comma-separated value or null + * @param {string[]} [allowedIdentifiers] 'key', 'id', 'name' + * @param {boolean} [firstOnly] removes all but the first entry if enabled + * @returns {TypeKeyCombo} values split into an array. + */ + static metadataToTypeKey( + metadataOption, + allowedIdentifiers = ['key', 'id', 'name'], + firstOnly = false + ) { + if (!metadataOption) { + return undefined; // eslint-disable-line unicorn/no-useless-undefined + } else if (!Array.isArray(metadataOption)) { + metadataOption = [metadataOption]; + } + if (firstOnly) { + // delete everything but the first entry + metadataOption.length = 1; + } + const metadataOptionMap = metadataOption.map((item) => { + const itemArr = item.split(':'); + const type = itemArr.shift(); + switch (itemArr.length) { + case 0: { + // no ":" found + return { type }; + } + case 1: { + // 1 ":" found + if (allowedIdentifiers.includes('key')) { + return { type, key: itemArr[0] }; + } + break; + } + default: { + // 2 or more ":" found + switch (itemArr[0]) { + case 'key': + case 'k': { + if (allowedIdentifiers.includes('key')) { + // remove k/key + itemArr.shift(); + return { type, key: itemArr.join(':') }; + } + break; + } + case 'id': + case 'i': { + if (allowedIdentifiers.includes('id')) { + // remove i/id + itemArr.shift(); + return { type, id: itemArr.join(':') }; + } + break; + } + case 'name': + case 'n': { + if (allowedIdentifiers.includes('name')) { + // remove n/name + itemArr.shift(); + return { type, name: itemArr.join(':') }; + } + break; + } + default: { + // assume ":" is part of the key (e.g. possible for DE-fields) + if (allowedIdentifiers.includes('key')) { + return { type, key: itemArr.join(':') }; + } + } + } + } + } + }); + /** @type {TypeKeyCombo} */ + const response = {}; + for (const item of metadataOptionMap) { + if (item) { + if (item.key || item.id || item.name) { + if (!response[item.type]) { + response[item.type] = []; + } + response[item.type].push( + item.key || + (item.id ? 'id:' + item.id : item.name ? 'name:' + item.name : null) + ); + } else { + if (!response[item.type]) { + response[item.type] = null; + } + } + } + } + + return Object.keys(response).length >= 1 ? response : undefined; + } } -module.exports = Mcdev; +export default Mcdev; diff --git a/lib/metadataTypes/AccountUser.js b/lib/metadataTypes/AccountUser.js deleted file mode 100644 index 5eb034503..000000000 --- a/lib/metadataTypes/AccountUser.js +++ /dev/null @@ -1,389 +0,0 @@ -'use strict'; - -const MetadataType = require('./MetadataType'); -const Util = require('../util/util'); -const File = require('../util/file'); - -/** - * MessageSendActivity MetadataType - * @augments MetadataType - */ -class AccountUser extends MetadataType { - /** - * Retrieves SOAP based metadata of metadata type into local filesystem. executes callback with retrieved metadata - * @param {String} retrieveDir Directory where retrieved metadata directory will be saved - * @param {String[]} _ Returns specified fields even if their retrieve definition is not set to true - * @param {Object} buObject properties for auth - * @returns {Promise<Object>} Promise of metadata - */ - static async retrieve(retrieveDir, _, buObject) { - if (buObject.eid !== buObject.mid) { - Util.logger.info('Skipping User retrieval on non-parent BU'); - return; - } - Util.logger.info('- Caching dependent Metadata: AccountUserAccount'); - - // get BUs that each users have access to - const optionsBUs = {}; - let resultsBatch; - await Util.retryOnError(`Retrying ${this.definition.type}`, async () => { - resultsBatch = await new Promise((resolve, reject) => { - this.client.SoapClient.retrieve( - 'AccountUserAccount', - [ - 'AccountUser.AccountUserID', - 'AccountUser.UserID', - 'Account.ID', - 'Account.Name', - ], - optionsBUs, - (ex, response) => (ex ? reject(ex) : resolve(response.body.Results)) - ); - }); - }); - this.userIdBuMap = {}; - resultsBatch.forEach((item) => { - this.userIdBuMap[item.AccountUser.AccountUserID] = - this.userIdBuMap[item.AccountUser.AccountUserID] || []; - this.userIdBuMap[item.AccountUser.AccountUserID].push({ - ID: item.Account.ID, - Name: item.Account.Name, - }); - }); - // get actual user details - const options = { - queryAllAccounts: true, - - filter: { - leftOperand: { - // normal users - leftOperand: 'Email', - operator: 'like', - rightOperand: '@', - }, - operator: 'OR', - rightOperand: { - // installed packages - leftOperand: { - leftOperand: 'Name', - operator: 'like', - rightOperand: ' app user', // ! will not work if the name was too long as "app user" might be cut off - }, - operator: 'AND', - rightOperand: { - // this is used to filter out system generated installed packages. in our testing, at least those installed packages created in the last few years have hat set this to false while additional (hidden) installed packages have it set to true. - leftOperand: 'MustChangePassword', - operator: 'equals', - rightOperand: 'false', - }, - }, - }, - }; - - return super.retrieveSOAPgeneric(retrieveDir, buObject, options); - } - /** - * - * @param {string} date first date - * @param {string} date2 second date - * @returns {number} time difference - */ - static timeSinceDate(date) { - const interval = 'days'; - const second = 1000, - minute = second * 60, - hour = minute * 60, - day = hour * 24, - week = day * 7; - date = new Date(date); - const now = new Date(); - const timediff = now - date; - if (isNaN(timediff)) { - return NaN; - } - let result; - switch (interval) { - case 'years': - result = now.getFullYear() - date.getFullYear(); - break; - case 'months': - result = - now.getFullYear() * 12 + - now.getMonth() - - (date.getFullYear() * 12 + date.getMonth()); - break; - case 'weeks': - result = Math.floor(timediff / week); - break; - case 'days': - result = Math.floor(timediff / day); - break; - case 'hours': - result = Math.floor(timediff / hour); - break; - case 'minutes': - result = Math.floor(timediff / minute); - break; - case 'seconds': - result = Math.floor(timediff / second); - break; - default: - return undefined; - } - return result + ' ' + interval; - } - /** - * helper to print bu names - * @param {Util.BuObject} buObject needed for eid - * @param {string} buObject.eid needed to check for parent bu - * @param {numeric} id bu id - * @returns {string} "bu name (bu id)"" - */ - static getBuName(buObject, id) { - let name; - if (buObject.eid == id) { - name = '_ParentBU_'; - } else { - name = this.buIdName[id]; - } - return `<nobr>${name} (${id})</nobr>`; - } - /** - * Creates markdown documentation of all roles - * @param {Util.BuObject} buObject properties for auth - * @param {Object} [metadata] user list - * @returns {Promise<void>} - - */ - static async document(buObject, metadata) { - if (buObject.eid !== buObject.mid) { - Util.logger.error( - `Users can only be retrieved & documented for the ${Util.parentBuName}` - ); - return; - } - if (!metadata) { - // load users from disk if document was called directly and not part of a retrieve - try { - metadata = this.readBUMetadataForType( - File.normalizePath([ - this.properties.directories.retrieve, - buObject.credential, - Util.parentBuName, - ]), - true - ).accountUser; - } catch (ex) { - Util.logger.error(ex.message); - return; - } - } - // init map of BU Ids > BU Name - this.buIdName = {}; - - // initialize permission object - this.allPermissions = {}; - const users = []; - // traverse all permissions recursively and write them into allPermissions object once it has reached the end - for (const id in metadata) { - const user = metadata[id]; - // TODO resolve user permissions to something readable - let userPermissions = ''; - if (user.UserPermissions) { - if (!user.UserPermissions.length) { - // 1 single user permission found, normalize it - user.UserPermissions = [user.UserPermissions]; - } - userPermissions = user.UserPermissions.map((item) => item.ID * 1) - .sort(function (a, b) { - return a < b ? -1 : a > b ? 1 : 0; - }) - .join(', '); - } - // user roles - // TODO think about what to do with "individual role" entries - let roles = ''; - if (user.Roles) { - roles = - '<nobr>' + - user.Roles.map((item) => item.Name) - .sort(function (a, b) { - return a < b ? -1 : a > b ? 1 : 0; - }) - .join(',</nobr><br> <nobr>') + - '</nobr>'; - } - let associatedBus = ''; - if (user.AssociatedBusinessUnits__c) { - associatedBus = user.AssociatedBusinessUnits__c.map((item) => { - this.buIdName[item.ID] = item.Name; - return this.getBuName(buObject, item.ID); - }) - .sort(function (a, b) { - return a < b ? -1 : a > b ? 1 : 0; - }) - .join(',<br> '); - } - const defaultBUName = this.getBuName(buObject, user.DefaultBusinessUnit); - users.push({ - TYPE: user.type__c, - UserID: user.UserID, - AccountUserID: user.AccountUserID, - CustomerKey: user.CustomerKey, - Name: user.Name, - Email: user.Email, - NotificationEmailAddress: user.NotificationEmailAddress, - ActiveFlag: user.ActiveFlag === 'true' ? '✓' : '-', - IsAPIUser: user.IsAPIUser === 'true' ? '✓' : '-', - MustChangePassword: user.MustChangePassword === 'true' ? '✓' : '-', - DefaultBusinessUnit: defaultBUName, - AssociatedBusinessUnits__c: associatedBus, - Roles: roles, - UserPermissions: userPermissions, - LastSuccessfulLogin: this.timeSinceDate(user.LastSuccessfulLogin), - CreatedDate: user.CreatedDate.split('T').join(' '), - ModifiedDate: user.ModifiedDate.split('T').join(' '), - }); - } - users.sort(function (a, b) { - return a.Name < b.Name ? -1 : a.Name > b.Name ? 1 : 0; - }); - const columnsToPrint = [ - ['Name', 'Name'], - ['Last successful Login', 'LastSuccessfulLogin'], - ['Active', 'ActiveFlag'], - ['API User', 'IsAPIUser'], - ['Must change PW', 'MustChangePassword'], - ['Default BU', 'DefaultBusinessUnit'], - ['BU Access', 'AssociatedBusinessUnits__c'], - ['Roles', 'Roles'], - ['User Permissions', 'UserPermissions'], - ['Login', 'UserID'], - ['ID', 'AccountUserID'], - ['Key', 'CustomerKey'], - ['E-Mail', 'Email'], - ['Notification E-Mail', 'NotificationEmailAddress'], - ['Modified Date', 'ModifiedDate'], - ['Created Date', 'CreatedDate'], - ]; - let output = `# User Overview - ${buObject.credential}`; - output += this._generateDocMd( - users.filter((user) => user.TYPE === 'User' && user.ActiveFlag === '✓'), - 'User', - columnsToPrint - ); - output += this._generateDocMd( - users.filter((user) => user.TYPE === 'User' && user.ActiveFlag === '-'), - 'Inactivated User', - columnsToPrint - ); - output += this._generateDocMd( - users.filter((user) => user.TYPE === 'Installed Package'), - 'Installed Package', - columnsToPrint - ); - const docPath = File.normalizePath([this.properties.directories.users]); - - try { - const filename = buObject.credential; - // ensure docs/roles folder is existing (depends on setup in .mcdevrc.json) - if (!File.existsSync(docPath)) { - File.mkdirpSync(docPath); - } - // write to disk - await File.writeToFile(docPath, filename + '.accountUser', 'md', output); - Util.logger.info(`Created ${docPath}${filename}.accountUser.md`); - if (['html', 'both'].includes(this.properties.options.documentType)) { - Util.logger.warn( - 'HTML-based documentation of accountUser currently not supported.' - ); - } - } catch (ex) { - Util.logger.error(`AccountUser.document():: error | `, ex.message); - } - } - /** - * Experimental: Only working for DataExtensions: - * Saves json content to a html table in the local file system. Will create the parent directory if it does not exist. - * The json's first level of keys must represent the rows and the secend level the columns - * @private - * @param {DataExtensionItem} json dataextension - * @param {Array} tabled prepped array for output in tabular format - * @returns {string} file content - */ - /** - * - * @param {Object[]} users list of users and installed package - * @param {'Installed Package'|'User'} type choose what sub type to print - * @param {Array[]} columnsToPrint helper array - * @param {Object} buObject properties for auth - * @returns {string} markdown - */ - static _generateDocMd(users, type, columnsToPrint) { - let output = `\n\n## ${type}s (${users.length})\n\n`; - let tableSeparator = ''; - columnsToPrint.forEach((column) => { - output += `| ${column[0]} `; - tableSeparator += '| --- '; - }); - output += `|\n${tableSeparator}|\n`; - users.forEach((user) => { - columnsToPrint.forEach((column) => { - output += `| ${user[column[1]]} `; - }); - output += `|\n`; - }); - return output; - } - - /** - * manages post retrieve steps - * @param {Object} metadata a single query - * @returns {Object[]} Array with one metadata object and one query string - */ - static postRetrieveTasks(metadata) { - return this.parseMetadata(metadata); - } - /** - * parses retrieved Metadata before saving - * @param {Object} metadata a single query activity definition - * @returns {Array} Array with one metadata object and one sql string - */ - static parseMetadata(metadata) { - metadata.type__c = 'Installed Package'; - if (metadata.Email.includes('@') && !metadata.Name.endsWith('app user')) { - metadata.type__c = 'User'; - } - - if (this.userIdBuMap[metadata.ID]) { - metadata.AssociatedBusinessUnits__c = this.userIdBuMap[metadata.ID]; - } else { - metadata.AssociatedBusinessUnits__c = []; - } - - let roles; - if (metadata.Roles.Role) { - // normalize to always use array - if (!metadata.Roles.Role.length) { - metadata.Roles.Role = [metadata.Roles.Role]; - } - // convert complex object into basic set of info - roles = metadata.Roles.Role.map((item) => ({ - Name: item.Name, - CustomerKey: item.CustomerKey, - })).sort(function (a, b) { - return a.Name < b.Name ? -1 : a.Name > b.Name ? 1 : 0; - }); - } else { - // set to empty array - roles = []; - } - metadata.Roles = roles; - - return metadata; - } -} - -// Assign definition to static attributes -AccountUser.definition = require('../MetadataTypeDefinitions').accountUser; - -module.exports = AccountUser; diff --git a/lib/metadataTypes/Asset.js b/lib/metadataTypes/Asset.js index 23351ce4f..cd8a55997 100644 --- a/lib/metadataTypes/Asset.js +++ b/lib/metadataTypes/Asset.js @@ -1,58 +1,118 @@ 'use strict'; -const MetadataType = require('./MetadataType'); -const Util = require('../util/util'); -const File = require('../util/file'); -const bluebird = require('bluebird'); -const cliProgress = require('cli-progress'); -const Mustache = require('mustache'); +import MetadataType from './MetadataType.js'; +import { Util } from '../util/util.js'; +import File from '../util/file.js'; +import pLimit from 'p-limit'; +import cliProgress from 'cli-progress'; +import cache from '../util/cache.js'; +import TriggeredSend from './TriggeredSend.js'; +import Folder from './Folder.js'; +import ReplaceCbReference from '../util/replaceContentBlockReference.js'; +import toposort from 'toposort'; /** - * @typedef {Object.<string, any>} AssetItem - * - * @typedef {Object.<string, AssetItem>} AssetMap - * - * @typedef {'archive'|'asset'|'audio'|'block'|'code'|'document'|'image'|'message'|'other'|'rawimage'|'template'|'textfile'|'video'} AssetSubType - * - * @typedef {Object} CodeExtractItem - * @property {AssetItem} json metadata of one item w/o code - * @property {MetadataType.CodeExtract[]} codeArr list of code snippets in this item - * @property {string[]} subFolder mostly set to null, otherwise list of subfolders + * @typedef {import('../../types/mcdev.d.js').BuObject} BuObject + * @typedef {import('../../types/mcdev.d.js').CodeExtract} CodeExtract + * @typedef {import('../../types/mcdev.d.js').CodeExtractItem} CodeExtractItem + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItem} MetadataTypeItem + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItemDiff} MetadataTypeItemDiff + * @typedef {import('../../types/mcdev.d.js').MetadataTypeMap} MetadataTypeMap + * @typedef {import('../../types/mcdev.d.js').SoapRequestParams} SoapRequestParams + * @typedef {import('../../types/mcdev.d.js').TemplateMap} TemplateMap + * @typedef {import('../../types/mcdev.d.js').TypeKeyCombo} TypeKeyCombo + */ + +/** + * @typedef {import('../../types/mcdev.d.js').AssetSubType} AssetSubType + * @typedef {import('../../types/mcdev.d.js').AssetMap} AssetMap + * @typedef {import('../../types/mcdev.d.js').AssetItem} AssetItem + * @typedef {import('../../types/mcdev.d.js').AssetRequestParams} AssetRequestParams + * @typedef {import('../../types/mcdev.d.js').ContentBlockConversionTypes} ContentBlockConversionTypes */ /** * FileTransfer MetadataType + * * @augments MetadataType */ class Asset extends MetadataType { /** * Retrieves Metadata of Asset + * * @param {string} retrieveDir Directory where retrieved metadata directory will be saved - * @param {void} _ - - * @param {void} __ - - * @param {AssetSubType} [selectedSubType] optionally limit to a single subtype - * @returns {Promise<{metadata:AssetMap,type:string}>} Promise + * @param {void | string[]} _ unused parameter + * @param {string[]} [subTypeArr] optionally limit to a single AssetSubType + * @param {string} [key] customer key + * @param {boolean} [loadShared] optionally retrieve assets from other BUs that were shared with the current + * @returns {Promise.<{metadata: AssetMap, type: string}>} Promise */ - static async retrieve(retrieveDir, _, __, selectedSubType) { + static async retrieve(retrieveDir, _, subTypeArr, key, loadShared = false) { const items = []; - const subTypes = selectedSubType ? [selectedSubType] : this._getSubTypes(); - await File.initPrettier(); - // loop through subtypes and return results of each subType for caching (saving is handled per subtype) - for (const subType of subTypes) { - // each subtype contains multiple different specific types (images contains jpg and png for example) - // we use await here to limit the risk of too many concurrent api requests at time - items.push( - ...(await this.requestSubType( - subType, - this.definition.extendedSubTypes[subType], - retrieveDir - )) + if (subTypeArr) { + // check if elements in subTypeArr exist in this.definition.subTypes + const invalidSubTypes = subTypeArr.filter( + (subType) => !this.definition.subTypes.includes(subType) + ); + if (invalidSubTypes.length) { + throw new Error(`Invalid subType(s) found: ${invalidSubTypes.join(', ')}`); + } + } + subTypeArr ||= this._getSubTypes(); + if (retrieveDir) { + await File.initPrettier(); + } + if (retrieveDir && !cache.getCache()?.asset) { + // cache this for 3 reasons: + // 1) subtypes asset, message and template reference other content blocks by id/key/objectId as part of their views + // 2) subtype message references a template if it is template-based + // 3) all non-binary subtypes support ampscript / ssjs which can load otherc content blocks via ContentBlockyByX() + + Util.logger.info(' - Caching dependent Metadata: asset'); + const resultLocal = await this.retrieveForCache( + undefined, + this.definition.selflinkedSubTypes, + undefined, + false ); + cache.mergeMetadata('asset', resultLocal.metadata); + Util.logger.info(' - Caching dependent Metadata: shared asset'); + const resultShared = await this.retrieveForCache( + undefined, + this.definition.selflinkedSubTypes, + undefined, + true + ); + cache.mergeMetadata('asset', resultShared.metadata); + } + if (retrieveDir) { + if (key) { + // running post-delete tasks to clean up potential old files + await this.postDeleteTasks(key); + // retrieve by key/id/name + items.push( + ...(await this.requestSubType(null, retrieveDir, key, null, loadShared)) + ); + } else { + // retrieve all + // loop through subtypes and return results of each subType for caching (saving is handled per subtype) + for (const subType of subTypeArr) { + // each subtype contains multiple different specific types (images contains jpg and png for example) + // we use await here to limit the risk of too many concurrent api requests at time + items.push( + ...(await this.requestSubType(subType, retrieveDir, key, null, loadShared)) + ); + } + } + } else { + // caching + items.push(...(await this.requestSubType(subTypeArr, null, null, null, loadShared))); } const metadata = this.parseResponseBody({ items: items }); if (retrieveDir) { Util.logger.info( - `Downloaded: ${this.definition.type} (${Object.keys(metadata).length})` + `Downloaded: ${this.definition.type} (${Object.keys(metadata).length})` + + Util.getKeysString(key) ); } return { metadata: metadata, type: this.definition.type }; @@ -60,23 +120,29 @@ class Asset extends MetadataType { /** * Retrieves asset metadata for caching - * @param {void} _ - - * @param {string} [selectedSubType] optionally limit to a single subtype - * @returns {Promise<{metadata:AssetMap,type:string}>} Promise + * + * @param {void | string[]} [_] parameter not used + * @param {string[]} [subTypeArr] optionally limit to a single subtype + * @param {void | string} [__] parameter not used + * @param {boolean} [loadShared] optionally retrieve assets from other BUs that were shared with the current + * @returns {Promise.<{metadata: AssetMap, type: string}>} Promise */ - static retrieveForCache(_, selectedSubType) { - return this.retrieve(null, null, null, selectedSubType); + static retrieveForCache(_, subTypeArr, __, loadShared = false) { + return this.retrieve(null, null, subTypeArr, undefined, loadShared); } /** - * Retrieves asset metadata for caching + * Retrieves asset metadata for templating + * + * @deprecated Use `retrieve` followed by `build` instead. `retrieveAsTemplate` will be removed in a future version. * @param {string} templateDir Directory where retrieved metadata directory will be saved * @param {string} name name of the metadata file - * @param {Util.TemplateMap} templateVariables variables to be replaced in the metadata + * @param {TemplateMap} templateVariables variables to be replaced in the metadata * @param {AssetSubType} [selectedSubType] optionally limit to a single subtype - * @returns {Promise<{metadata:AssetMap,type:string}>} Promise + * @returns {Promise.<{metadata: AssetItem, type: string}>} Promise */ static async retrieveAsTemplate(templateDir, name, templateVariables, selectedSubType) { + Util.logDeprecated('retrieveAsTemplate', `'retrieve' followed by 'build'`); const items = []; const subTypes = selectedSubType ? [selectedSubType] : this._getSubTypes(); await File.initPrettier(); @@ -87,9 +153,8 @@ class Asset extends MetadataType { items.push( ...(await this.requestSubType( subType, - this.definition.extendedSubTypes[subType], templateDir, - name, + 'name:' + name, templateVariables )) ); @@ -100,17 +165,20 @@ class Asset extends MetadataType { } Util.logger.info(`Downloaded: ${this.definition.type} (${Object.keys(metadata).length})`); - return { metadata: metadata, type: this.definition.type }; + return { metadata: Object.values(metadata)[0], type: this.definition.type }; } + /** - * helper for retrieve + retrieveAsTemplate + * helper for {@link Asset.retrieve} + {@link Asset.retrieveAsTemplate} + * * @private - * @returns {AssetSubType[]} subtype array + * @returns {string[]} AssetSubType array */ static _getSubTypes() { const selectedSubTypeArr = this.properties.metaDataTypes.retrieve.filter((type) => type.startsWith('asset-') ); + /* eslint-disable unicorn/prefer-ternary */ if ( this.properties.metaDataTypes.retrieve.includes('asset') || !selectedSubTypeArr.length @@ -120,20 +188,155 @@ class Asset extends MetadataType { } else { return selectedSubTypeArr.map((type) => type.replace('asset-', '')); } + /* eslint-enable unicorn/prefer-ternary */ + } + + /** + * Returns Order in which metadata needs to be retrieved/deployed and skips components with missing components + * + * @param {AssetMap} metadataMap metadata thats about to be deployed + * @param {string} deployDir directory where deploy metadata are saved + * @returns {Promise.<AssetMap>} keyField => metadata map but sorted to ensure dependencies are deployed in correct order + */ + static async _getUpsertOrderAndSkipMissing(metadataMap, deployDir) { + /** + * one entry for each dependency with the first item being the key thats required by the second item + * + * @type {string[][]} + */ + const dependencies = []; + /** @type {ContentBlockConversionTypes[]} */ + Util.OPTIONS.referenceFrom = ['key', 'name', 'id']; + /** @type {ContentBlockConversionTypes} */ + Util.OPTIONS.referenceTo = 'key'; + // loop through all metadata types which are being retrieved/deployed + for (const key in metadataMap) { + const errors = []; + const findAssetKeys = new Set(); + // find asset references in metadata + const findAssetKeyMeta = Util.findLeafVals(metadataMap[key], 'r__asset_key'); + for (const metaKey of findAssetKeyMeta) { + if (metadataMap[key] || cache.getByKey(this.definition.type, metaKey)) { + findAssetKeys.add(metaKey); + } else { + errors.push( + `content block ${metaKey} that is referenced via r__asset_key was not found on BU nor in deployment package` + ); + } + } + try { + // find asset references in code + await this.replaceCbReference(metadataMap[key], deployDir, findAssetKeys); + } catch (ex) { + if (ex.code === 200) { + // no dependent keys found + // good from this perspective + } else { + errors.push( + `content block ${ex.message} that is referenced via ContentBlockByX was not found on BU nor in deployment package` + ); + } + } + if (errors.length) { + Util.logger.error( + ` ☇ skipping ${this.definition.type} ${key}:${errors.length > 1 ? '\n ·' : ''} ${errors.join('\n · ')}` + ); + } else { + const dependentKeys = [...findAssetKeys]; + if (dependentKeys.length > 0) { + dependencies.push(...dependentKeys.map((depKey) => [depKey, key])); + } else { + Util.logger.debug('Asset._getUpsertOrder: no dependent keys found for ' + key); + dependencies.push([undefined, key]); + } + } + } + + // sort list & remove the undefined dependencies + const flatList = toposort(dependencies).filter((a) => !!a); + + /** @type {AssetMap} */ + const metadataTypeMapSorted = {}; + // group subtypes per type + for (const key of flatList) { + if (metadataMap[key]) { + metadataTypeMapSorted[key] = metadataMap[key]; + } + } + return metadataTypeMapSorted; + } + + /** + * MetadataType upsert, after retrieving from target and comparing to check if create or update operation is needed. + * + * @param {AssetMap} metadataMap metadata mapped by their keyField + * @param {string} deployDir directory where deploy metadata are saved + * @returns {Promise.<AssetMap>} keyField => metadata map + */ + static async upsert(metadataMap, deployDir) { + // add already existing, cached items to our cache map to ensure we can find them + ReplaceCbReference.createCacheForMap(cache.getCache().asset); + // await ReplaceCbReference.createCache(this.properties, this.buObject, true); + // fill the cache map with our deployment package to ensure we can find + ReplaceCbReference.createCacheForMap(metadataMap); + // assets can link to other assets (via template, content block reference and SSJS/AMPscript) and deployment would fail if we did not sort this here + metadataMap = await this._getUpsertOrderAndSkipMissing(metadataMap, deployDir); + return super.upsert(metadataMap, deployDir, true); + } + + /** + * helper for {@link MetadataType.updateREST} and {@link MetadataType.updateSOAP} + * + * @param {MetadataTypeItem} metadataEntry a single metadata Entry + * @param {object} apiResponse varies depending on the API call + * @returns {Promise.<object>} apiResponse, potentially modified + */ + static async postUpdateTasks(metadataEntry, apiResponse) { + // ensure we do not have any old files left aftert content blocks changed their type or got removed + await this.postDeleteTasks(metadataEntry[this.definition.keyField]); + return apiResponse; } /** * Creates a single asset + * * @param {AssetItem} metadata a single asset * @returns {Promise} Promise */ static create(metadata) { + delete metadata.businessUnitAvailability; const uri = '/asset/v1/content/assets/'; return super.createREST(metadata, uri); } + /** + * helper for {@link MetadataType.createREST} + * + * @param {MetadataTypeItem} metadataEntry a single metadata Entry + * @param {object} apiResponse varies depending on the API call + * @returns {Promise.<object>} apiResponse, potentially modified + */ + static async postCreateTasks(metadataEntry, apiResponse) { + if (apiResponse[this.definition.idField]) { + // this also happens inside of MetadataType.upsert but we need it for createCacheMap() + // ensure we have the ID in the cache + metadataEntry[this.definition.idField] = apiResponse[this.definition.idField]; + } + if (apiResponse.objectID) { + // ensure we have the asset objectId in the cache + metadataEntry.objectID = apiResponse.objectID; + } + + // make this newly created item available in cache for other itmes that might reference it + /** @type {MetadataTypeMap} */ + const newObject = { [metadataEntry[this.definition.keyField]]: metadataEntry }; + ReplaceCbReference.createCacheForMap(newObject); + return apiResponse; + } + /** * Updates a single asset + * * @param {AssetItem} metadata a single asset * @returns {Promise} Promise */ @@ -141,66 +344,63 @@ class Asset extends MetadataType { const uri = '/asset/v1/content/assets/' + metadata.id; return super.updateREST(metadata, uri); } + /** * Retrieves Metadata of a specific asset type - * @param {AssetSubType} subType group of similar assets to put in a folder (ie. images) - * @param {AssetSubType[]} subTypeArray list of all asset types within this subtype + * + * @param {string|string[]} subType group of similar assets to put in a folder (ie. images) * @param {string} [retrieveDir] target directory for saving assets - * @param {string} [templateName] name of the metadata file - * @param {Util.TemplateMap} [templateVariables] variables to be replaced in the metadata - * @returns {Promise} Promise + * @param {string} [key] key/id/name to filter by + * @param {TemplateMap} [templateVariables] variables to be replaced in the metadata + * @param {boolean} [loadShared] optionally retrieve assets from other BUs that were shared with the current + * @returns {Promise.<object[]>} Promise */ - static async requestSubType( - subType, - subTypeArray, - retrieveDir, - templateName, - templateVariables - ) { + static async requestSubType(subType, retrieveDir, key, templateVariables, loadShared = false) { + const subTypeArr = Array.isArray(subType) ? subType : [subType]; if (retrieveDir) { - Util.logger.info(`- Retrieving Subtype: ${subType}`); + if (Array.isArray(subType)) { + throw new TypeError( + 'requestSubType should not be called with multiple subtypes when retrieving to disk.' + ); + } else if (!key) { + Util.logger.info(`- Retrieving Subtype: ${subType}`); + } } else { - Util.logger.info(`- Caching Subtype: ${subType}`); - } - const subtypeIds = subTypeArray?.map(subTypeItemName => Asset.definition.typeMapping[subTypeItemName]); - const uri = 'asset/v1/content/assets/'; - const options = { - uri: uri + 'query', - headers: {}, - json: { - page: { - page: 1, - pageSize: 50, - }, - query: null, - fields: [], + // in this mode we can accept arrays because we don't need to save this to a subtype folder but just want the records + Util.logSubtypes(subTypeArr); + } + /** @type {AssetSubType[]} */ + const extendedSubTypeArr = key + ? [null] + : subTypeArr.flatMap((subType) => this.definition.extendedSubTypes[subType]); + // the API can only assetType.ids at a time or else will throw: "DbUtility.GetPagedCollection passing through non-timeout DB error (30001)" + const subtypeIdsList = key + ? [null] + : Util.chunk( + extendedSubTypeArr + ?.map((subTypeItemName) => this.definition.typeMapping[subTypeItemName]) + .toSorted((a, b) => a - b), + 50 + ); + const uri = '/asset/v1/content/assets/query' + (loadShared ? '?scope=shared' : ''); + /** @type {AssetRequestParams} */ + const payload = { + page: { + page: 1, + pageSize: 50, }, + query: null, + fields: [ + 'category', + 'createdDate', + 'createdBy', + 'modifiedDate', + 'modifiedBy', + 'objectID', + ], // get folder to allow duplicate name check against cache }; - if (templateName) { - options.json.query = { - leftOperand: { - property: 'assetType.id', - simpleOperator: 'in', - value: subtypeIds, - }, - logicalOperator: 'AND', - rightOperand: { - property: 'name', - simpleOperator: 'equal', - value: templateName, - }, - }; - } else { - options.json.query = { - property: 'assetType.id', - simpleOperator: 'in', - value: subtypeIds, - }; - options.json.sort = [{ property: 'id', direction: 'ASC' }]; - } - // for caching we do not need these fields if (retrieveDir) { - options.json.fields = [ + payload.fields = [ 'fileProperties', 'status', 'category', @@ -211,148 +411,300 @@ class Asset extends MetadataType { 'availableViews', 'data', 'tags', + + 'meta', + 'content', ]; } - let moreResults = false; - let lastPage = 0; + let items = []; - do { - options.json.page.page = lastPage + 1; - let response; - await Util.retryOnError(`Retrying Subtype: ${subType}`, async () => { - response = await this.client.RestClient.post(options); - }); - if (response && response.body && response.body.items && response.body.items.length) { - // sometimes the api will return a payload without items - // --> ensure we only add proper items-arrays here - items = items.concat(response.body.items); - } - // check if any more records - if (response.body.message && response.body.message.includes('all shards failed')) { - // When running certain filters, there is a limit of 10k on ElastiCache. - // Since we sort by ID, we can get the last ID then run new requests from there - options.json.query = { - leftOperand: { - property: 'assetType.id', - simpleOperator: 'in', - value: subtypeIds, - }, - logicalOperator: 'AND', - rightOperand: { - property: 'id', - simpleOperator: 'greaterThan', - value: items[items.length - 1].id, - }, - }; - lastPage = 0; - moreResults = true; - } else if (response.body.page * response.body.pageSize < response.body.count) { - moreResults = true; - lastPage = Number(response.body.page); + + for (const subtypeIds of subtypeIdsList) { + if (key) { + if (key.startsWith('id:')) { + payload.query = { + property: this.definition.idField, + simpleOperator: 'equal', + value: key.slice(3), + }; + } else if (key.startsWith('name:')) { + payload.query = { + property: this.definition.nameField, + simpleOperator: 'equal', + value: key.slice(5), + }; + } else { + payload.query = { + property: this.definition.keyField, + simpleOperator: 'equal', + value: key, + }; + } } else { - moreResults = false; + payload.query = { + property: 'assetType.id', + simpleOperator: 'in', + value: subtypeIds, + }; + // payload.sort = [{ property: 'id', direction: 'ASC' }]; } - } while (moreResults); + // for caching we do not need these fields + /** @type {boolean} */ + let moreResults; + let lastPage = 0; + do { + payload.page.page = lastPage + 1; + const response = await this.client.rest.post(uri, payload); + if (response?.items?.length) { + // sometimes the api will return a payload without items + // --> ensure we only add proper items-arrays here + items = items.concat(response.items); + if (key && subType === null) { + subType = this.#getMainSubtype(response?.items[0].assetType.name); + } + } + // check if any more records + if (response?.message?.includes('all shards failed')) { + // When running certain filters, there is a limit of 10k on ElastiCache. + // Since we sort by ID, we can get the last ID then run new requests from there + payload.query = { + leftOperand: { + property: 'assetType.id', + simpleOperator: 'in', + value: subtypeIds, + }, + logicalOperator: 'AND', + rightOperand: { + property: 'id', + simpleOperator: 'greaterThan', + value: items.at(-1).id, + }, + }; + lastPage = 0; + moreResults = true; + } else if (response.page * response.pageSize < response.count) { + moreResults = true; + lastPage = Number(response.page); + } else { + moreResults = false; + } + } while (moreResults); + } + // only when we save results do we need the complete metadata or files. caching can skip these - if (retrieveDir && items.length > 0) { - // we have to wait on execution or it potentially causes memory reference issues when changing between BUs - await this.requestAndSaveExtended(items, subType, retrieveDir, templateVariables); + if (retrieveDir && !Array.isArray(subType)) { + let downloadedItemsMap = {}; + if (items.length > 0) { + for (const item of items) { + if (item.customerKey.trim() !== item.customerKey) { + Util.logger.warn( + ` - ${this.definition.type} ${item[this.definition.nameField]} (${ + item[this.definition.keyField] + }) has leading or trailing spaces in customerKey. Please remove them in SFMC.` + ); + } + } + // we have to wait on execution or it potentially causes memory reference issues when changing between BUs + downloadedItemsMap = await this.requestAndSaveExtended( + items, + subType, + retrieveDir, + templateVariables + ); + } + // always show the summary even if we already had the progress bar in the console + Util.logger.info( + ` Downloaded asset${subType ? '-' + subType : ''}: ${Object.keys(downloadedItemsMap).length}` + ); + return Object.values(downloadedItemsMap); + } else { + return items; } - return items; } + /** * Retrieves extended metadata (files or extended content) of asset + * * @param {Array} items array of items to retrieve - * @param {AssetSubType} subType group of similar assets to put in a folder (ie. images) + * @param {string} subType group of similar assets to put in a folder (ie. images) * @param {string} retrieveDir target directory for saving assets - * @param {Util.TemplateMap} [templateVariables] variables to be replaced in the metadata - * @returns {Promise} Promise + * @param {TemplateMap} [templateVariables] variables to be replaced in the metadata + * @returns {Promise.<MetadataTypeMap>} Promise */ static async requestAndSaveExtended(items, subType, retrieveDir, templateVariables) { + // disable CLI logs other than error while retrieving subtype + const loggerLevelBak = Util.logger.level; + if (loggerLevelBak !== 'error') { + // disable logging to cli other than Errors + Util.setLoggingLevel({ silent: true }); + } const extendedBar = new cliProgress.SingleBar( - { format: 'Processing [{bar}] {percentage}% | {value}/{total}' }, + { + format: + ' Downloading [{bar}] {percentage}% | {value}/{total} | asset-' + + subType, + }, cliProgress.Presets.shades_classic ); const completed = []; + const failed = []; + const metadataMap = {}; + let filterCounter = 0; + // put in do loop to manage issues with connection timeout do { // use promise execution limiting to avoid rate limits on api, but speed up execution // start the progress bar with a total value of 200 and start value of 0 extendedBar.start(items.length - completed.length, 0); try { - const promiseMap = await bluebird.map( - items, - async (item) => { - await Util.retryOnError( - `Retrying asset-${subType} ${item[this.definition.nameField]} (${ - item[this.definition.keyField] - })`, - async () => { - const metadata = {}; - // this is a file so extended is at another endpoint - if ( - item.fileProperties && - item.fileProperties.extension && - !completed.includes(item.id) - ) { - metadata[item.customerKey] = item; - if (templateVariables) { - // do this here already because otherwise the extended file could be saved with wrong fileName - const warningMsg = - 'Ensure that Code that might be loading this via ContentBlockByKey is updated with the new key before deployment.'; - this.overrideKeyWithName(item, warningMsg); - } + const rateLimit = pLimit(5); + + await Promise.all( + items.map((item, index) => + rateLimit(async () => { + const metadataMapSaveSingle = {}; + + // this is a file so extended is at another endpoint + if (item?.fileProperties?.extension && !completed.includes(item.id)) { + try { // retrieving the extended file does not need to be awaited await this._retrieveExtendedFile(item, subType, retrieveDir); + } catch (ex) { + failed.push({ item: item, error: ex }); } - // this is a complex type which stores data in the asset itself - else if (!completed.includes(item.id)) { - const extendedItem = await this.client.RestClient.get({ - uri: 'asset/v1/content/assets/' + item.id, - }); - metadata[item.customerKey] = extendedItem.body; + // still return even if extended failed + metadataMap[item.customerKey] = item; + // even if the extended file failed, still save the metadata + metadataMapSaveSingle[item.customerKey] = item; + } + // this is a complex type which stores data in the asset itself + else if (!completed.includes(item.id)) { + try { + const extendedItem = await this.client.rest.get( + 'asset/v1/content/assets/' + item.id + ); + // only return the metadata if we have extended content + metadataMap[item.customerKey] = extendedItem; + // only save the metadata if we have extended content + metadataMapSaveSingle[item.customerKey] = extendedItem; + // overwrite the original item with the extended content to ensure retrieve() returns it + items[index] = extendedItem; + } catch (ex) { + failed.push({ item: item, error: ex }); } - completed.push(item.id); - await this.saveResults( - metadata, + } + completed.push(item.id); + if (metadataMapSaveSingle[item.customerKey]) { + const savedItem = await this.saveResults( + metadataMapSaveSingle, retrieveDir, 'asset-' + subType, templateVariables ); - // update the current value in your application.. - extendedBar.increment(); - }, - true - ); - }, - { concurrency: 5 } + if (!savedItem[item.customerKey]) { + // filtered by like-option + delete metadataMap[item.customerKey]; + filterCounter++; + } + } + // update the current value in your application.. + extendedBar.increment(); + if (metadataMap[item.customerKey]) { + return metadataMap[item.customerKey]; + } + }) + ) ); // stop the progress bar extendedBar.stop(); - return promiseMap; + Asset._resetLogLevel(loggerLevelBak, failed); + if (filterCounter) { + Util.logger.info( + ` - Filtered ${this.definition.type}-${subType}: ${filterCounter} (downloaded but not saved to disk)` + ); + } + return metadataMap; } catch (ex) { extendedBar.stop(); - // timeouts should be retried, others can be retried + Asset._resetLogLevel(loggerLevelBak, failed); + // timeouts should be retried, others can be exited if (ex.code !== 'ETIMEDOUT') { throw ex; } } } while (completed.length === items.length); + return metadataMap; + } + + /** + * helper that reset the log level and prints errors + * + * @private + * @param {'info'|'verbose'|'debug'|'error'} loggerLevelBak original logger level + * @param {object[]} failed array of failed items + */ + static _resetLogLevel(loggerLevelBak, failed) { + // re-enable CLI logs + // reset logging level + let obj; + switch (loggerLevelBak) { + case 'info': { + obj = {}; + break; + } + case 'verbose': { + obj = { verbose: true }; + break; + } + case 'debug': { + obj = { debug: true }; + break; + } + case 'error': { + obj = { silent: true }; + } + } + Util.setLoggingLevel(obj); + + if (failed.length) { + Util.logger.warn( + ` - Failed to download ${failed.length} extended file${ + failed.length > 1 ? 's' : '' + }:` + ); + for (const fail of failed) { + Util.logger.warn( + ` - "${fail.item.name}" (${fail.item.customerKey}): ${fail.error.message} (${ + fail.error.code + })${ + fail.error.endpoint + ? Util.getGrayMsg( + ' - ' + + fail.error.endpoint.split('rest.marketingcloudapis.com')[1] + ) + : '' + }` + ); + } + Util.logger.info( + ' - You will still find a JSON file for each of these in the download directory.' + ); + } } + /** * Some metadata types store their actual content as a separate file, e.g. images * This method retrieves these and saves them alongside the metadata json + * * @param {AssetItem} metadata a single asset - * @param {AssetSubType} subType group of similar assets to put in a folder (ie. images) + * @param {string} subType group of similar assets to put in a folder (ie. images) * @param {string} retrieveDir target directory for saving assets - * @returns {Promise<void>} - + * @returns {Promise.<void>} - */ static async _retrieveExtendedFile(metadata, subType, retrieveDir) { - const file = await this.client.RestClient.get({ - uri: 'asset/v1/content/assets/' + metadata.id + '/file', - }); + const file = await this.client.rest.get('asset/v1/content/assets/' + metadata.id + '/file'); // to handle uploaded files that bear the same name, SFMC engineers decided to add a number after the fileName // however, their solution was not following standards: fileName="header.png (4) " and then extension="png (4) " @@ -362,166 +714,531 @@ class Asset extends MetadataType { [retrieveDir, this.definition.type, subType], metadata.customerKey, fileExt, - file.body, + file, 'base64' ); } + /** - * helper for this.preDeployTasks() + * helper for {@link Asset.preDeployTasks} * Some metadata types store their actual content as a separate file, e.g. images * This method reads these from the local FS stores them in the metadata object allowing to deploy it + * * @param {AssetItem} metadata a single asset - * @param {AssetSubType} subType group of similar assets to put in a folder (ie. images) + * @param {string} subType group of similar assets to put in a folder (ie. images) * @param {string} deployDir directory of deploy files - * @returns {Promise<void>} - + * @param {boolean} [pathOnly] used by getFilesToCommit which does not need the binary file to be actually read + * @returns {Promise.<string>} if found will return the path of the binary file */ - static async _readExtendedFileFromFS(metadata, subType, deployDir) { - if (metadata.fileProperties && metadata.fileProperties.extension) { - // to handle uploaded files that bear the same name, SFMC engineers decided to add a number after the fileName - // however, their solution was not following standards: fileName="header.png (4) " and then extension="png (4) " - const fileExt = metadata.fileProperties.extension.split(' ')[0]; + static async _readExtendedFileFromFS(metadata, subType, deployDir, pathOnly = false) { + // to handle uploaded files that bear the same name, SFMC engineers decided to add a number after the fileName + // however, their solution was not following standards: fileName="header.png (4) " and then extension="png (4) " + if (!metadata?.fileProperties?.extension) { + return; + } + const fileExt = metadata.fileProperties.extension.split(' ')[0]; - metadata.file = await File.readFile( - [deployDir, this.definition.type, subType], - metadata.customerKey, - fileExt, - 'base64' - ); + const path = File.normalizePath([ + deployDir, + this.definition.type, + subType, + `${metadata.customerKey}.${fileExt}`, + ]); + if (await File.pathExists(path)) { + if (!pathOnly) { + metadata.file = await File.readFilteredFilename( + [deployDir, this.definition.type, subType], + metadata.customerKey, + fileExt, + 'base64' + ); + } + return path; } } + /** * manages post retrieve steps + * * @param {AssetItem} metadata a single asset - * @param {string} [_] unused - * @param {Boolean} isTemplating signals that we are retrieving templates * @returns {CodeExtractItem} metadata */ - static postRetrieveTasks(metadata, _, isTemplating) { - // if retrieving template, replace the name with customer key if that wasn't already the case - if (isTemplating) { - const warningMsg = - 'Ensure that Code that might be loading this via ContentBlockByKey is updated with the new key before deployment.'; - this.overrideKeyWithName(metadata, warningMsg); + static postRetrieveTasks(metadata) { + // folder + this.setFolderPath(metadata); + + // template-based emails + if (metadata.assetType.name === 'templatebasedemail') { + // get template + try { + if (metadata.views?.html?.template?.id) { + metadata.views.html.template.r__asset_key = cache.searchForField( + 'asset', + metadata.views?.html?.template?.id, + 'id', + 'customerKey' + ); + delete metadata.views.html.template.id; + delete metadata.views.html.template.name; + delete metadata.views.html.template.assetType; + delete metadata.views.html.template.availableViews; + delete metadata.views.html.template.data; + delete metadata.views.html.template.modelVersion; + } + } catch { + Util.logger.warn( + ` - ${this.definition.type} '${metadata[this.definition.nameField]}' (${ + metadata[this.definition.keyField] + }): Could not find email template with id (${metadata.views.html.template.id})` + ); + } + } + + // get asset-asset + try { + if (metadata.meta?.thumbnailRefAssetId) { + // cloudpages', 'landingpage', 'microsite', 'interactivecontent' + metadata.meta.r__asset_key = cache.searchForField( + 'asset', + metadata.meta?.thumbnailRefAssetId, + 'id', + 'customerKey' + ); + delete metadata.meta.thumbnailRefAssetId; + } + } catch { + Util.logger.warn( + ` - ${this.definition.type} '${metadata[this.definition.nameField]}' (${ + metadata[this.definition.keyField] + }): Could not find associated cloudpage content with id (${metadata.meta.thumbnailRefAssetId})` + ); + } + if ( + ['landingpage', 'microsite', 'interactivecontent'].includes(metadata.assetType.name) && + typeof metadata.content === 'string' + ) { + // cloudpages', 'landingpage', 'microsite', 'interactivecontent' + metadata.content = JSON.parse(metadata.content); + } + + if (typeof metadata.data?.site?.content === 'string') { + // for all xx-coderesource types + metadata.data.site.content = JSON.parse(metadata.data.site.content); + } + + if (metadata.meta?.cloudPages) { + metadata.meta.cloudPages.c__published = metadata.meta.cloudPages.publishDate + ? true + : false; + } + + // extract HTML for selected subtypes and convert payload for easier processing in MetadataType.saveResults() + return this._extractCode(metadata); + } + + /** + * Gets executed after deployment of metadata type + * + * @param {MetadataTypeMap} metadata metadata mapped by their keyField + * @param {MetadataTypeMap} _ originalMetadata to be updated (contains additioanl fields) + * @param {{created: number, updated: number}} createdUpdated counter representing successful creates/updates + * @returns {Promise.<void>} - + */ + static async postDeployTasks(metadata, _, createdUpdated) { + if (Util.OPTIONS.refresh) { + if (createdUpdated.updated) { + // only run this if assets were updated. for created assets we do not expect + await this._refreshTriggeredSend(metadata); + } else { + Util.logger.warn( + 'You set the --refresh flag but no updated assets found. Skipping refresh of triggeredSendDefinitions.' + ); + } + } + } + + /** + * helper for {@link Asset.postDeployTasks}. triggers a refresh of active triggerredSendDefinitions associated with the updated asset-message items. Gets executed if refresh option has been set. + * + * @private + * @param {MetadataTypeMap} metadata metadata mapped by their keyField + * @returns {Promise.<void>} - + */ + static async _refreshTriggeredSend(metadata) { + // get legacyData.legacyId from assets to compare to TSD's metadata.Email.ID to + const legacyIdArr = Object.keys(metadata) + .map((key) => metadata[key]?.legacyData?.legacyId) + .filter(Boolean); + + if (!legacyIdArr.length) { + Util.logger.warn( + 'No legacyId found in updated emails. Skipping refresh of triggeredSendDefinitions.' + ); + return; + } + // prep triggeredSendDefinition class + TriggeredSend.properties = this.properties; + TriggeredSend.buObject = this.buObject; + TriggeredSend.client = this.client; + try { + // find refreshable TSDs + const tsdObj = (await TriggeredSend.findRefreshableItems(true))?.metadata; + + const tsdCountInitial = Object.keys(tsdObj).length; + const emailCount = legacyIdArr.length; + // filter TSDs by legacyId + for (const key in tsdObj) { + if (!legacyIdArr.includes(tsdObj[key].Email.ID)) { + delete tsdObj[key]; + } + } + const tsdCountFiltered = Object.keys(tsdObj).length; + Util.logger.info( + `Found ${tsdCountFiltered} out of ${tsdCountInitial} total triggeredSendDefinitions for ${emailCount} deployed emails. Commencing validation...` + ); + + // get keys of TSDs to refresh + const keyArr = await TriggeredSend.getKeysForValidTSDs(tsdObj); + + await TriggeredSend.refresh(keyArr); + } catch { + Util.logger.warn('Failed to refresh triggeredSendDefinition'); } - return this.parseMetadata(metadata); } /** * prepares an asset definition for deployment + * * @param {AssetItem} metadata a single asset * @param {string} deployDir directory of deploy files - * @returns {Promise<AssetItem>} Promise + * @returns {Promise.<AssetItem>} Promise */ static async preDeployTasks(metadata, deployDir) { // additonalattributes fail where the value is "" so we need to remove them from deploy - if ( - metadata.data && - metadata.data.email && - metadata.data.email && - metadata.data.email.attributes && - metadata.data.email.attributes.length > 0 - ) { + if (metadata?.data?.email?.attributes?.length > 0) { metadata.data.email.attributes = metadata.data.email.attributes.filter( (attr) => attr.value ); } // folder - metadata.category = { - id: Util.getFromCache(this.cache, 'folder', metadata.r__folder_Path, 'Path', 'ID'), - }; - delete metadata.r__folder_Path; + this.setFolderId(metadata); - // restore asset type id which is needed for deploy - metadata.assetType.id = this.definition.typeMapping[metadata.assetType.name]; + if (!cache.getByKey(this.definition.type, metadata[this.definition.keyField])) { + if (metadata.assetType.name === 'webpage') { + // we are attempting to CREATE a cloudpage asset which needs to be prevented. + throw new Error( + 'CloudPage content cannot be created via mcdev. Please create it via the UI first, then you can update the content or key.' + ); + } + if ( + this.definition.extendedSubTypes.cloudpage.includes(metadata.assetType.name) || + this.definition.extendedSubTypes.coderesource.includes(metadata.assetType.name) + ) { + // if we do create those, we get the error "Asset <id> not found" because the internal endpoint internal/v2/cloudpages/sites won't find it. + throw new Error( + 'CloudPage assets cannot be created via mcdev. Please create it via the UI first, then you can update the content or key.' + ); + } + } - // define asset's subtype - const subType = this.getSubtype(metadata); + // template-based emails + if ( + metadata.assetType.name === 'templatebasedemail' && + metadata.views?.html?.template?.r__asset_key + ) { + // template + metadata.views.html.template.id = cache.searchForField( + 'asset', + metadata.views.html.template.r__asset_key, + 'customerKey', + 'id' + ); + metadata.views.html.template.name = cache.searchForField( + 'asset', + metadata.views.html.template.r__asset_key, + 'customerKey', + 'name' + ); + metadata.views.html.template.assetType = { + id: 4, + name: 'template', + displayName: 'Template', + }; - // #1 get text extracts back into the JSON - await this._mergeCode(metadata, deployDir, subType); + metadata.views.html.template.data = { + email: { options: { generateFrom: null } }, + }; - // #2 get file from local disk and insert as base64 - await this._readExtendedFileFromFS(metadata, subType, deployDir); + metadata.views.html.template.availableViews = []; + metadata.views.html.template.modelVersion = 2; + delete metadata.views.html.template.r__asset_key; + } + + if (metadata.meta?.r__asset_key) { + // cloudpages: 'landingpage', 'microsite', 'interactivecontent' + // get asset-asset + metadata.meta.thumbnailRefAssetId = cache.searchForField( + 'asset', + metadata.meta.r__asset_key, + 'customerKey', + 'id' + ); + delete metadata.meta.r__asset_key; + } + if (metadata.meta?.cloudPages?.c__published) { + // TODO: removal should be done via asset.definition instead + delete metadata.meta.cloudPages.c__published; + } + if ( + ['landingpage', 'microsite', 'interactivecontent'].includes(metadata.assetType.name) && + typeof metadata.content === 'object' + ) { + // cloudpages: 'landingpage', 'microsite', 'interactivecontent' + metadata.content = JSON.stringify(metadata.content); + } + if (typeof metadata.data?.site?.content === 'object') { + // coderesource: for all xx-coderesource types + metadata.data.site.content = JSON.stringify(metadata.data.site.content); + } + + // restore asset type id which is needed for deploy + metadata.assetType.id = this.definition.typeMapping[metadata.assetType.name]; + + // define asset's subtype + const subType = this._getSubtype(metadata); + + // #0 format blocks in slots for deployment + await this._preDeployTasksBocks(metadata); + + // #1 get text extracts back into the JSON + await this._mergeCode(metadata, deployDir, subType); + + // #2 get file from local disk and insert as base64 + await this._readExtendedFileFromFS(metadata, subType, deployDir); + + // only execute #3 if we are deploying / copying from one BU to another, not while using mcdev as a developer tool + if ( + Util.OPTIONS.autoMidSuffix && + this.buObject.mid && + metadata.memberId != this.buObject.mid && // soft comparison to accomodate for string-version of mid + !metadata[this.definition.keyField].endsWith(this.buObject.mid) + ) { + // #3 make sure customer key is unique by suffixing it with target MID (unless we are deploying to the same MID) + // check if this suffixed with the source MID + const suffix = '-' + this.buObject.mid; + // for customer key max is 36 chars + metadata[this.definition.keyField] = + metadata[this.definition.keyField].slice(0, Math.max(0, 36 - suffix.length)) + + suffix; + } + if (!Util.OPTIONS.matchName) { + // #4 make sure the name is unique + const assetCache = cache.getCache()[this.definition.type]; + const namesInFolder = Object.keys(assetCache) + .filter((key) => assetCache[key].category.id === metadata.category.id) + .map((key) => ({ + type: this.#getMainSubtype(assetCache[key].assetType.name), + key: key, + name: assetCache[key].name, + })); + // if the name is already in the folder for a different key, add a number to the end + metadata[this.definition.nameField] = this.findUniqueName( + metadata[this.definition.keyField], + metadata[this.definition.nameField], + namesInFolder, + this.#getMainSubtype(metadata.assetType.name) + ); + } + return metadata; + } + + /** + * find the subType matching the extendedSubType + * + * @param {string} extendedSubType webpage, htmlblock, etc + * @returns {string} subType: block, message, other, etc + */ + static #getMainSubtype(extendedSubType) { + return Object.keys(this.definition.extendedSubTypes).find((subType) => + this.definition.extendedSubTypes[subType].includes(extendedSubType) + ); + } - return metadata; - } /** * determines the subtype of the current asset + * + * @private * @param {AssetItem} metadata a single asset - * @returns {AssetSubType} subtype + * @returns {string} subtype */ - static getSubtype(metadata) { + static _getSubtype(metadata) { for (const sub in this.definition.extendedSubTypes) { if (this.definition.extendedSubTypes[sub].includes(metadata.assetType.name)) { return sub; } } + return; } /** - * helper for buildDefinition + * helper for {@link MetadataType.buildDefinition} * handles extracted code if any are found for complex types + * * @param {string} templateDir Directory where metadata templates are stored * @param {string} targetDir Directory where built definitions will be saved * @param {AssetItem} metadata main JSON file that was read from file system - * @param {Util.TemplateMap} variables variables to be replaced in the metadata + * @param {TemplateMap} templateVariables variables to be replaced in the metadata + * @param {string} templateName name of the template to be built + * @returns {Promise.<string[][]>} list of extracted files with path-parts provided as an array + */ + static buildDefinitionForNested( + templateDir, + targetDir, + metadata, + templateVariables, + templateName + ) { + return this._buildForNested( + templateDir, + targetDir, + metadata, + templateVariables, + templateName, + 'definition' + ); + } + + /** + * helper for {@link MetadataType.buildTemplate} + * handles extracted code if any are found for complex types + * + * @example assets of type codesnippetblock will result in 1 json and 1 amp/html file. both files need to be run through templating + * @param {string} templateDir Directory where metadata templates are stored + * @param {string|string[]} targetDir (List of) Directory where built definitions will be saved + * @param {AssetItem} metadata main JSON file that was read from file system + * @param {TemplateMap} templateVariables variables to be replaced in the metadata * @param {string} templateName name of the template to be built - * @returns {Promise<void>} Promise + * @returns {Promise.<string[][]>} list of extracted files with path-parts provided as an array */ - static async buildDefinitionForExtracts( + static buildTemplateForNested( templateDir, targetDir, metadata, - variables, + templateVariables, templateName ) { - // clone metadata to ensure the main file is not modified by what we do in here - metadata = JSON.parse(JSON.stringify(metadata)); + return this._buildForNested( + templateDir, + targetDir, + metadata, + templateVariables, + templateName, + 'template' + ); + } + + /** + * helper for {@link MetadataType.buildDefinition} + * handles extracted code if any are found for complex types + * + * @param {string} templateDir Directory where metadata templates are stored + * @param {string|string[]} targetDir (List of) Directory where built definitions will be saved + * @param {AssetItem} metadata main JSON file that was read from file system + * @param {TemplateMap} templateVariables variables to be replaced in the metadata + * @param {string} templateName name of the template to be built + * @param {'definition'|'template'} mode defines what we use this helper for + * @returns {Promise.<string[][]>} list of extracted files with path-parts provided as an array + */ + static async _buildForNested( + templateDir, + targetDir, + metadata, + templateVariables, + templateName, + mode + ) { + // * because asset's _mergeCode() is overwriting 'metadata', clone it to ensure the main file is not modified by what we do in here + metadata = structuredClone(metadata); // #1 text extracts // define asset's subtype - const subType = this.getSubtype(metadata); + const subType = this._getSubtype(metadata); // get HTML from filesystem const fileList = await this._mergeCode(metadata, templateDir, subType, templateName); // replace template variables with their values for (const extractedFile of fileList) { try { - extractedFile.content = Mustache.render(extractedFile.content, variables); - } catch (ex) { + if (mode === 'definition') { + // replace template variables with their values + extractedFile.content = this.applyTemplateValues( + extractedFile.content, + templateVariables + ); + } else if (mode === 'template') { + // replace template values with corresponding variable names + extractedFile.content = this.applyTemplateNames( + extractedFile.content, + templateVariables + ); + } + } catch { throw new Error( `${this.definition.type}:: Error applying template variables on ${ metadata[this.definition.keyField] }: ${extractedFile.fileName}.${extractedFile.fileExt}.` ); } + + // apply templating to subfolders + extractedFile.subFolder = extractedFile.subFolder + .map((el) => (el === templateName ? metadata[this.definition.keyField] : el)) + .map((el) => this.applyTemplateValues(el, templateVariables)); + + // apply templating to filenames of extracted code + extractedFile.fileName = extractedFile.fileName + .split('.') + .map((el) => (el === templateName ? metadata[this.definition.keyField] : el)) + .join('.'); } // #2 binary extracts - if (metadata.fileProperties && metadata.fileProperties.extension) { + if (metadata?.fileProperties?.extension) { // to handle uploaded files that bear the same name, SFMC engineers decided to add a number after the fileName // however, their solution was not following standards: fileName="header.png (4) " and then extension="png (4) " const fileExt = metadata.fileProperties.extension.split(' ')[0]; - const filecontent = await File.readFile( + const filecontent = await File.readFilteredFilename( [templateDir, this.definition.type, subType], - metadata.customerKey, + templateName, fileExt, 'base64' ); + + // keep old name if creating templates, otherwise use new name + const fileName = + mode === 'definition' ? metadata[this.definition.keyField] : templateName; + fileList.push({ subFolder: [this.definition.type, subType], - fileName: metadata.customerKey, + fileName: fileName, fileExt: fileExt, content: filecontent, encoding: 'base64', }); } + const nestedFilePaths = []; // write to file (#1 + #2) const targetDirArr = Array.isArray(targetDir) ? targetDir : [targetDir]; for (const targetDir of targetDirArr) { for (const extractedFile of fileList) { + if (extractedFile.fileExt === 'ssjs') { + const ssjs = Util.getSsjs(extractedFile?.content); + if (ssjs) { + extractedFile.content = ssjs; + } + } File.writeToFile( [targetDir, ...extractedFile.subFolder], extractedFile.fileName, @@ -529,190 +1246,551 @@ class Asset extends MetadataType { extractedFile.content, extractedFile.encoding || null ); + nestedFilePaths.push([ + File.normalizePath([targetDir, ...extractedFile.subFolder]), + extractedFile.fileName + + '.' + + this.definition.type + + '-meta.' + + extractedFile.fileExt, + ]); } } + return nestedFilePaths; } /** - * parses retrieved Metadata before saving - * @param {AssetItem} metadata a single asset definition - * @returns {CodeExtractItem} parsed metadata definition + * generic script that retrieves the folder path from cache and updates the given metadata with it after retrieve + * + * @param {MetadataTypeItem} metadata a single script activity definition + * @param {boolean} [hideWarning] when checking content blocks we do want to set the folder path but if we cant, lets not cludder the log with warnings about it */ - static parseMetadata(metadata) { - // folder + static setFolderPath(metadata, hideWarning = false) { try { - metadata.r__folder_Path = Util.getFromCache( - this.cache, - 'folder', - metadata.category.id, - 'ID', - 'Path' - ); - delete metadata.category; + // we get folders type "asset" from EID and MID to accomodate for shared assets. That however is an issue if we are retrieving a local asset with the same folder. + const folderId = metadata.category.id; + const folderMap = cache.getCache().folder; + if (!folderMap) { + throw new Error('No folders found in cache'); + } + const potentialFolders = []; + for (const folder of Object.values(folderMap)) { + if (folder.ID === folderId) { + if ( + (metadata.memberId && metadata.memberId === folder?.Client?.ID) || + folder?.Client?.ID === this.buObject.mid + ) { + metadata.r__folder_Path = folder.Path; + delete metadata.category; + return; + } else { + potentialFolders.push(folder); + } + } + } + if (potentialFolders.length >= 1) { + metadata.r__folder_Path = potentialFolders[0].Path; + delete metadata.category; + } else { + throw new Error(`No folders found with ID ${folderId}`); + } } catch (ex) { - // ! if we don't catch this error here we end up saving the actual asset but not its corresponding JSON - Util.logger.debug(ex.message); - Util.logger.warn( - `Could not find folder with ID ${metadata.category.id} for '${metadata.name}' (${metadata.customerKey})` + if (!hideWarning) { + Util.logger.warn( + ` - ${this.definition.type} '${metadata[this.definition.nameField]}' (${ + metadata[this.definition.keyField] + }): Could not find folder (${ex.message})` + ); + } + } + } + + /** + * Asset-specific script that retrieves the folder ID from cache and updates the given metadata with it before deploy + * + * @param {MetadataTypeItem} metadata a single item + */ + static setFolderId(metadata) { + if (!metadata.r__folder_Path) { + throw new Error( + `Dependent folder could not be found because r__folder_Path is not set` ); } - // extract HTML for selected subtypes and convert payload for easier processing in MetadataType.saveResults() - metadata = this._extractCode(metadata); - return metadata; + metadata.category = { + id: cache.getFolderId(metadata.r__folder_Path), + }; + delete metadata.r__folder_Path; + } + + /** + * helper for {@link Asset.preDeployTasks} that loads extracted code content back into JSON + * + * @param {AssetItem} metadata a single asset definition + * @returns {Promise.<void>} fileList for templating (disregarded during deployment) + */ + static async _preDeployTasksBocks(metadata) { + switch (metadata.assetType.name) { + case 'templatebasedemail': // message + case 'htmlemail': + case 'webpage': { + // metadata.views.html.slots.<>.blocks.<>.content (optional) + if (metadata?.views?.html?.slots) { + await this._preDeployTasksBocks_slots(metadata.views.html.slots); + } + break; + } + case 'template': { + // metadata.slots.<>.blocks.<>.content (optional) + if (metadata?.slots) { + await this._preDeployTasksBocks_slots(metadata.slots); + } + + break; + } + } + } + + /** + * helper for {@link Asset.preDeployTasks} that loads extracted code content back into JSON + * + * @param {object} metadataSlots metadata.views.html.slots or deeper slots.<>.blocks.<>.slots + * @returns {Promise.<void>} - + */ + static async _preDeployTasksBocks_slots(metadataSlots) { + for (const slot in metadataSlots) { + if (Object.prototype.hasOwnProperty.call(metadataSlots, slot)) { + const slotObj = metadataSlots[slot]; + // found slot + if (slotObj.blocks) { + for (const block in slotObj.blocks) { + if (Object.prototype.hasOwnProperty.call(slotObj.blocks, block)) { + const asset = slotObj.blocks[block]; + if (asset.r__asset_key) { + // by only running the following if r__asset_key was set, we simply skip anything that wasnt resolved during retrieve + asset.customerKey = asset.r__asset_key; + asset.id = cache.searchForField( + 'asset', + asset.r__asset_key, + 'customerKey', + 'id' + ); + asset.objectID = cache.searchForField( + 'asset', + asset.r__asset_key, + 'customerKey', + 'objectID' + ); + delete asset.r__asset_key; + asset.thumbnail = { + thumbnailUrl: '/v1/assets/' + asset.id + '/thumbnail', + }; + } + if (asset.r__folder_Path) { + // if we convert this into a folder path then renamed folders might end up blocking deployments, therefore, we instead omit this detail from now on + delete asset.r__folder_Path; + } + await this._preDeployTasksBocks(asset); + } + } + } + } + } } + /** - * helper for this.preDeployTasks() that loads extracted code content back into JSON + * helper for {@link Asset.preDeployTasks} that loads extracted code content back into JSON + * * @param {AssetItem} metadata a single asset definition * @param {string} deployDir directory of deploy files - * @param {AssetSubType} subType asset-subtype name + * @param {string} subType asset-subtype name; full list in AssetSubType * @param {string} [templateName] name of the template used to built defintion (prior applying templating) - * @returns {Promise<MetadataType.CodeExtract[]>} fileList for templating (disregarded during deployment) + * @param {boolean} [fileListOnly] does not read file contents nor update metadata if true + * @returns {Promise.<CodeExtract[]>} fileList for templating (disregarded during deployment) */ - static async _mergeCode(metadata, deployDir, subType, templateName) { + static async _mergeCode(metadata, deployDir, subType, templateName, fileListOnly = false) { const subtypeExtension = `.${this.definition.type}-${subType}-meta`; const fileList = []; let subDirArr; let readDirArr; - + // unfortunately, asset's key can contain spaces at beginning/end which can break the file system when folders are created with it + const customerKey = metadata.customerKey.trim(); + const templateFileName = templateName || customerKey; switch (metadata.assetType.name) { - case 'webpage': // asset case 'templatebasedemail': // message - case 'htmlemail': // message + case 'htmlemail': { + // message // this complex type always creates its own subdir per asset subDirArr = [this.definition.type, subType]; - readDirArr = [ - deployDir, - ...subDirArr, - templateName ? templateName : metadata.customerKey, - ]; + readDirArr = [deployDir, ...subDirArr, templateFileName]; // metadata.views.html.content (mandatory) + // the main content can be empty (=not set up yet) hence check if we did extract sth or else readFile() will print error msgs + const fileName = 'views.html.content' + subtypeExtension; if ( - File.existsSync( - File.normalizePath([...readDirArr, `index${subtypeExtension}.html`]) - ) + (await File.pathExists( + File.normalizePath([...readDirArr, `${fileName}.html`]) + )) && + metadata.views.html ) { - // the main content can be empty (=not set up yet) hence check if we did extract sth or else readFile() will print error msgs - metadata.views.html.content = await File.readFile( - readDirArr, - 'index' + subtypeExtension, - 'html' - ); + if (!fileListOnly) { + metadata.views.html.content = await File.readFilteredFilename( + readDirArr, + fileName, + 'html' + ); + } if (templateName) { // to use this method in templating, store a copy of the info in fileList fileList.push({ - subFolder: [...subDirArr, metadata.customerKey], - fileName: 'index' + subtypeExtension, + subFolder: [...subDirArr, templateFileName], + fileName: fileName, fileExt: 'html', content: metadata.views.html.content, }); } } + // metadata.views.html.content (optional) + // the main content can be empty (=not set up yet) hence check if we did extract sth or else readFile() will print error msgs + const fileNamePreheader = 'views.preheader.content' + subtypeExtension; + if ( + (await File.pathExists( + File.normalizePath([...readDirArr, `${fileNamePreheader}.amp`]) + )) && + metadata.views.preheader + ) { + if (!fileListOnly) { + metadata.views.preheader.content = await File.readFilteredFilename( + readDirArr, + fileNamePreheader, + 'amp' + ); + } + + if (templateName) { + // to use this method in templating, store a copy of the info in fileList + fileList.push({ + subFolder: [...subDirArr, templateFileName], + fileName: fileNamePreheader, + fileExt: 'amp', + content: metadata.views.preheader.content, + }); + } + } + + // metadata.views.text.content (optional) + // the main content can be empty (=not set up yet) hence check if we did extract sth or else readFile() will print error msgs + const fileNameText = 'views.text.content' + subtypeExtension; + if ( + (await File.pathExists( + File.normalizePath([...readDirArr, `${fileNameText}.amp`]) + )) && + metadata.views.text + ) { + if (!fileListOnly) { + metadata.views.text.content = await File.readFilteredFilename( + readDirArr, + fileNameText, + 'amp' + ); + } + + if (templateName) { + // to use this method in templating, store a copy of the info in fileList + fileList.push({ + subFolder: [...subDirArr, templateFileName], + fileName: fileNameText, + fileExt: 'amp', + content: metadata.views.text.content, + }); + } + } else if (metadata.views.text) { + // ensure the text version gets generated from html + metadata.views.text.data = { + email: { + options: { + generateFrom: 'html', + }, + }, + }; + metadata.views.text.generateFrom = 'html'; + } // metadata.views.html.slots.<>.blocks.<>.content (optional) - if (metadata.views && metadata.views.html && metadata.views.html.slots) { + if (metadata?.views?.html?.slots) { await this._mergeCode_slots( + 'views.html.slots', metadata.views.html.slots, readDirArr, subtypeExtension, subDirArr, fileList, - metadata.customerKey, - templateName + customerKey, + templateName, + fileListOnly + ); + } + break; + } + case 'template': { + // template-template + // this complex type always creates its own subdir per asset + subDirArr = [this.definition.type, subType]; + readDirArr = [deployDir, ...subDirArr, templateFileName]; + const fileName = 'content' + subtypeExtension; + + const fileExtArr = ['html']; + for (const ext of fileExtArr) { + if ( + await File.pathExists( + File.normalizePath([...readDirArr, `${fileName}.${ext}`]) + ) + ) { + // the main content can be empty (=not set up yet) hence check if we did extract sth or else readFile() will print error msgs + if (!fileListOnly) { + metadata.content = await File.readFilteredFilename( + readDirArr, + fileName, + ext + ); + } + if (templateName) { + // to use this method in templating, store a copy of the info in fileList + fileList.push({ + subFolder: [...subDirArr, templateFileName], + fileName: fileName, + fileExt: ext, + content: metadata.content, + }); + } + // break loop when found + break; + } + } + + // metadata.slots.<>.blocks.<>.content (optional) + if (metadata?.slots) { + await this._mergeCode_slots( + 'slots', + metadata.slots, + readDirArr, + subtypeExtension, + subDirArr, + fileList, + customerKey, + templateName, + fileListOnly ); } + break; - case 'textonlyemail': // message + } + case 'textonlyemail': { + // message // metadata.views.text.content subDirArr = [this.definition.type, subType]; readDirArr = [deployDir, ...subDirArr]; if ( - File.existsSync( + await File.pathExists( File.normalizePath([ ...readDirArr, - `${ - templateName ? templateName : metadata.customerKey - }${subtypeExtension}.html`, + `${templateFileName}${subtypeExtension}.amp`, ]) ) ) { // the main content can be empty (=not set up yet) hence check if we did extract sth or else readFile() will print error msgs - metadata.views.text.content = await File.readFile( - readDirArr, - (templateName ? templateName : metadata.customerKey) + subtypeExtension, - 'html' - ); - + if (!fileListOnly) { + metadata.views.text.content = await File.readFilteredFilename( + readDirArr, + templateFileName + subtypeExtension, + 'amp' + ); + } if (templateName) { // to use this method in templating, store a copy of the info in fileList fileList.push({ subFolder: subDirArr, - fileName: metadata.customerKey + subtypeExtension, - fileExt: 'html', + fileName: templateFileName + subtypeExtension, + fileExt: 'amp', content: metadata.views.text.content, }); } } break; - case 'freeformblock': // block - case 'htmlblock': // block - case 'textblock': // block - case 'smartcaptureblock': // other - case 'codesnippetblock': // other - // metadata.content + } + case 'webpage': { + // asset + // this complex type always creates its own subdir per asset subDirArr = [this.definition.type, subType]; - readDirArr = [deployDir, ...subDirArr]; + readDirArr = [deployDir, ...subDirArr, templateFileName]; + + // metadata.views.html.slots.<>.blocks.<>.content (optional) (pre & post 20222) + if (metadata?.views?.html?.slots) { + await this._mergeCode_slots( + 'views.html.slots', + metadata.views.html.slots, + readDirArr, + subtypeExtension, + subDirArr, + fileList, + customerKey, + templateName, + fileListOnly + ); + } + + // +++ old webpages / pre-2022 +++ + // metadata.views.html.content (mandatory) if ( - File.existsSync( + (await File.pathExists( File.normalizePath([ ...readDirArr, - `${ - templateName ? templateName : metadata.customerKey - }${subtypeExtension}.html`, + `views.html.content${subtypeExtension}.html`, ]) + )) && // the main content can be empty (=not set up yet) hence check if we did extract sth or else readFile() will print error msgs + metadata.views?.html + ) { + if (!fileListOnly) { + metadata.views.html.content = await File.readFilteredFilename( + readDirArr, + 'views.html.content' + subtypeExtension, + 'html' + ); + } + if (templateName) { + // to use this method in templating, store a copy of the info in fileList + fileList.push({ + subFolder: [...subDirArr, templateFileName], + fileName: 'views.html.content' + subtypeExtension, + fileExt: 'html', + content: metadata.views.html.content, + }); + } + } + + // +++ new webpages / 2022+ +++ + // metadata.content + if ( + await File.pathExists( + File.normalizePath([...readDirArr, `content${subtypeExtension}.html`]) ) ) { // the main content can be empty (=not set up yet) hence check if we did extract sth or else readFile() will print error msgs - metadata.content = await File.readFile( - readDirArr, - (templateName ? templateName : metadata.customerKey) + subtypeExtension, - 'html' - ); + if (!fileListOnly) { + metadata.content = await File.readFilteredFilename( + readDirArr, + 'content' + subtypeExtension, + 'html' + ); + } if (templateName) { // to use this method in templating, store a copy of the info in fileList fileList.push({ - subFolder: subDirArr, - fileName: metadata.customerKey + subtypeExtension, + subFolder: [...subDirArr, templateFileName], + fileName: 'content' + subtypeExtension, fileExt: 'html', - content: metadata.content, + content: metadata.views.html.content, }); } } + + break; + } + case 'jscoderesource': // coderesource + case 'csscoderesource': // coderesource + case 'jsoncoderesource': // coderesource + case 'rsscoderesource': // coderesource + case 'textcoderesource': // coderesource + case 'xmlcoderesource': // coderesource + case 'buttonblock': // block - Button Block + case 'freeformblock': // block + case 'htmlblock': // block + case 'icemailformblock': // block - Interactive Content Email Form + case 'imageblock': // block - Image Block + case 'textblock': // block + case 'smartcaptureblock': // other + case 'codesnippetblock': { + // other + // metadata.content + subDirArr = [this.definition.type, subType]; + readDirArr = [deployDir, ...subDirArr]; + const fileExtArr = [ + 'html', + 'ssjs', + 'amp', + 'js', + 'css', + 'rss', + 'txt', + 'xml', + 'jsonc', + ]; + for (const ext of fileExtArr) { + if ( + await File.pathExists( + File.normalizePath([ + ...readDirArr, + `${templateFileName}${subtypeExtension}.${ext}`, + ]) + ) + ) { + // the main content can be empty (=not set up yet) hence check if we did extract sth or else readFile() will print error msgs + if (!fileListOnly) { + metadata.content = await File.readFilteredFilename( + readDirArr, + templateFileName + subtypeExtension, + ext + ); + if (ext === 'ssjs') { + metadata.content = `<script runat="server">\n${metadata.content}</script>`; + } + } + if (templateName) { + // to use this method in templating, store a copy of the info in fileList + fileList.push({ + subFolder: subDirArr, + fileName: templateFileName + subtypeExtension, + fileExt: ext, + content: metadata.content, + }); + } + // break loop when found + break; + } + } break; + } } return fileList; } + /** - * helper for this.preDeployTasks() that loads extracted code content back into JSON - * @param {Object} metadataSlots metadata.views.html.slots or deeper slots.<>.blocks.<>.slots + * helper for {@link Asset.preDeployTasks} that loads extracted code content back into JSON + * + * @param {string} prefix usually the customerkey + * @param {object} metadataSlots metadata.views.html.slots or deeper slots.<>.blocks.<>.slots * @param {string[]} readDirArr directory of deploy files * @param {string} subtypeExtension asset-subtype name ending on -meta * @param {string[]} subDirArr directory of files w/o leading deploy dir - * @param {Object[]} fileList directory of files w/o leading deploy dir + * @param {object[]} fileList directory of files w/o leading deploy dir * @param {string} customerKey external key of template (could have been changed if used during templating) * @param {string} [templateName] name of the template used to built defintion (prior applying templating) - * @returns {Promise<void>} - + * @param {boolean} [fileListOnly] does not read file contents nor update metadata if true + * @returns {Promise.<void>} - */ static async _mergeCode_slots( + prefix, metadataSlots, readDirArr, subtypeExtension, subDirArr, fileList, customerKey, - templateName + templateName, + fileListOnly = false ) { + const templateFileName = templateName || customerKey; + for (const slot in metadataSlots) { if (Object.prototype.hasOwnProperty.call(metadataSlots, slot)) { const slotObj = metadataSlots[slot]; @@ -720,9 +1798,10 @@ class Asset extends MetadataType { if (slotObj.blocks) { for (const block in slotObj.blocks) { if (Object.prototype.hasOwnProperty.call(slotObj.blocks, block)) { - const fileName = `${slot}-${block}${subtypeExtension}`; + const asset = slotObj.blocks[block]; + const fileName = `${prefix}.[${slot}-${block}]${subtypeExtension}`; if ( - File.existsSync( + await File.pathExists( File.normalizePath([ ...readDirArr, 'blocks', @@ -732,31 +1811,48 @@ class Asset extends MetadataType { ) { // the main content can be empty (=not set up yet) hence check if we did extract sth or else readFile() will print error msgs // if an extracted block was found, save it back into JSON - slotObj.blocks[block].content = await File.readFile( - [...readDirArr, 'blocks'], - fileName, - 'html' - ); + if (!fileListOnly) { + asset.content = await File.readFilteredFilename( + [...readDirArr, 'blocks'], + fileName, + 'html' + ); + } if (templateName) { // to use this method in templating, store a copy of the info in fileList fileList.push({ - subFolder: [...subDirArr, customerKey, 'blocks'], + subFolder: [...subDirArr, templateFileName, 'blocks'], fileName: fileName, fileExt: 'html', - content: slotObj.blocks[block].content, + content: asset.content, }); } } - if (slotObj.blocks[block].slots) { + if (asset.slots) { // * recursion: each block can have slots of its own await this._mergeCode_slots( - slotObj.blocks[block].slots, + `${prefix}.[${slot}-${block}]`, + asset.slots, readDirArr, subtypeExtension, subDirArr, fileList, customerKey, - templateName + templateName, + fileListOnly + ); + } else if (asset?.views?.html?.slots) { + // * recursion: each block can have slots of its own + await this._mergeCode_slots( + `${prefix}.[${slot}-${block}]`, + asset.views.html.slots, + readDirArr, + subtypeExtension, + subDirArr, + fileList, + customerKey, + templateName, + fileListOnly ); } } @@ -765,206 +1861,1130 @@ class Asset extends MetadataType { } } } + /** - * helper for this.parseMetadata() that finds code content in JSON and extracts it + * helper for {@link Asset.postRetrieveTasks} that finds code content in JSON and extracts it * to allow saving that separately and formatted + * * @param {AssetItem} metadata a single asset definition * @returns {CodeExtractItem} { json: metadata, codeArr: object[], subFolder: string[] } */ static _extractCode(metadata) { const codeArr = []; + let subType; + // unfortunately, asset's key can contain spaces at beginning/end which can break the file system when folders are created with it + const customerKey = metadata.customerKey.trim(); switch (metadata.assetType.name) { - case 'webpage': // asset - case 'templatebasedemail': // message - case 'htmlemail': // message + case 'templatebasedemail': // message-templatebasedemail + case 'htmlemail': { + // message-htmlemail // metadata.views.html.content (mandatory) - if (metadata.views.html.content && metadata.views.html.content.length) { + if (metadata.views?.html?.content?.length) { codeArr.push({ subFolder: null, - fileName: 'index', + fileName: 'views.html.content', fileExt: 'html', content: metadata.views.html.content, }); delete metadata.views.html.content; } + // metadata.views.preheader.content (optional) + if (metadata.views?.preheader?.content?.length) { + codeArr.push({ + subFolder: null, + fileName: 'views.preheader.content', + fileExt: 'amp', + content: metadata.views.preheader.content, + }); + delete metadata.views.preheader.content; + } + + // metadata.views.text.content (optional) + if (metadata.views?.text?.content?.length) { + codeArr.push({ + subFolder: null, + fileName: 'views.text.content', + fileExt: 'amp', + content: metadata.views.text.content, + }); + delete metadata.views.text.content; + } // metadata.views.html.slots.<>.blocks.<>.content (optional) - if (metadata.views && metadata.views.html && metadata.views.html.slots) { - this._extractCode_slots(metadata.views.html.slots, codeArr); + if (metadata.views?.html?.slots) { + this._extractCode_slots('views.html.slots', metadata.views.html.slots, codeArr); + } + + return { + json: metadata, + codeArr: codeArr, + subFolder: [customerKey], + }; + } + case 'template': { + // template-template + // metadata.content + const fileExt = 'html'; + if (metadata?.content?.length) { + codeArr.push({ + subFolder: null, + fileName: 'content', + fileExt: fileExt, + content: metadata.content, + }); + delete metadata.content; + } + // metadata.slots.<>.blocks.<>.content (optional) + if (metadata.slots) { + this._extractCode_slots('slots', metadata.slots, codeArr); } - return { json: metadata, codeArr: codeArr, subFolder: [metadata.customerKey] }; - case 'textonlyemail': // message + return { + json: metadata, + codeArr: codeArr, + subFolder: [customerKey], + }; + } + case 'textonlyemail': { + // message-textonlyemail // metadata.views.text.content - if (metadata.views.text.content && metadata.views.text.content.length) { + if (metadata.views?.text?.content?.length) { codeArr.push({ subFolder: null, - fileName: metadata.customerKey, - fileExt: 'html', + fileName: customerKey, + fileExt: 'amp', content: metadata.views.text.content, }); delete metadata.views.text.content; } return { json: metadata, codeArr: codeArr, subFolder: null }; - case 'freeformblock': // block - case 'htmlblock': // block - case 'textblock': // block - case 'smartcaptureblock': // other - case 'codesnippetblock': // other + } + case 'webpage': { + // asset-webpage + // metadata.views.html.content (pre & post 20222) + if (metadata.views?.html?.content?.length) { + codeArr.push({ + subFolder: null, + fileName: 'views.html.content', + fileExt: 'html', + content: metadata.views.html.content, + }); + delete metadata.views.html.content; + } + + // +++ old webpages / pre-2022 +++ + // metadata.views.html.slots.<>.blocks.<>.content (optional) + if (metadata.views?.html?.slots) { + this._extractCode_slots('views.html.slots', metadata.views.html.slots, codeArr); + } + + // +++ new webpages / 2022+ +++ // metadata.content - if (metadata.content && metadata.content.length) { + if (metadata?.content?.length) { codeArr.push({ subFolder: null, - fileName: metadata.customerKey, + fileName: 'content', fileExt: 'html', content: metadata.content, }); delete metadata.content; } + return { + json: metadata, + codeArr: codeArr, + subFolder: [customerKey], + }; + } + case 'jscoderesource': // coderesource + case 'csscoderesource': // coderesource + case 'jsoncoderesource': // coderesource + case 'rsscoderesource': // coderesource + case 'textcoderesource': // coderesource + case 'xmlcoderesource': { + // metadata.content + const content = metadata?.content; + const fileExt = metadata.assetType.name + .replace('coderesource', '') + .replace('text', 'txt') + .replace('json', 'jsonc'); + + if (content?.length) { + codeArr.push({ + subFolder: null, + fileName: customerKey, + fileExt: fileExt, + content: content, + }); + delete metadata.content; + } return { json: metadata, codeArr: codeArr, subFolder: null }; - default: + } + case 'buttonblock': // block-buttonblock + case 'freeformblock': // block-freeformblock + case 'htmlblock': // block-htmlblock + case 'icemailformblock': // block-icemailformblock - Interactive Content Email Form + case 'imageblock': // block-imageblock - Image Block + case 'textblock': // block-textblock + case 'smartcaptureblock': // other-smartcaptureblock + case 'codesnippetblock': { + // other-codesnippetblock + // metadata.content + let fileExt; + let content = metadata?.content; + const ssjs = Util.getSsjs(metadata?.content); + + if (ssjs) { + fileExt = 'ssjs'; + content = ssjs; + } else if ( + metadata.assetType.name === 'codesnippetblock' && // extracted code snippets should end on the right extension + content?.includes('%%[') + ) { + fileExt = 'amp'; + } else { + fileExt = 'html'; + } + if (content?.length) { + codeArr.push({ + subFolder: null, + fileName: customerKey, + fileExt: fileExt, + content: content, + }); + delete metadata.content; + } + return { json: metadata, codeArr: codeArr, subFolder: null }; + } + default: { + subType = this._getSubtype(metadata); + if (!this.definition.binarySubtypes.includes(subType)) { + Util.logger.debug( + 'not processed metadata.assetType.name: ' + metadata.assetType.name + ); + } return { json: metadata, codeArr: codeArr, subFolder: null }; + } } } + /** - * @param {Object} metadataSlots metadata.views.html.slots or deeper slots.<>.blocks.<>.slots - * @param {Object[]} codeArr to be extended array for extracted code + * helper for {@link Asset.postRetrieveTasks} via {@link Asset._extractCode} + * + * @param {string} prefix usually the customerkey + * @param {object} metadataSlots metadata.views.html.slots or deeper slots.<>.blocks.<>.slots + * @param {object[]} codeArr to be extended array for extracted code * @returns {void} */ - static _extractCode_slots(metadataSlots, codeArr) { + static _extractCode_slots(prefix, metadataSlots, codeArr) { for (const slot in metadataSlots) { if (Object.prototype.hasOwnProperty.call(metadataSlots, slot)) { const slotObj = metadataSlots[slot]; // found slot for (const block in slotObj.blocks) { if (Object.prototype.hasOwnProperty.call(slotObj.blocks, block)) { - if (slotObj.blocks[block].content) { + const asset = slotObj.blocks[block]; + if (asset.content) { // found content block - const code = slotObj.blocks[block].content; + const code = asset.content; codeArr.push({ subFolder: ['blocks'], - fileName: `${slot}-${block}`, + fileName: `${prefix}.[${slot}-${block}]`, fileExt: 'html', content: code, }); - delete slotObj.blocks[block].content; + delete asset.content; + } + // clean up fields from the other content block + if (asset.id) { + try { + asset.r__asset_key = cache.searchForField( + 'asset', + asset.id, + 'id', + 'customerKey' + ); + // only delete this if we found the asset in cache, otherwise ignore + delete asset.id; + delete asset.objectID; + delete asset.customerKey; + delete asset.thumbnail; + } catch { + Util.logger.debug( + ` - asset id:${asset.id} / key:${asset.customerKey} / name:${asset.name} not found in cache` + ); + } + } + if (asset.category?.id) { + // if we convert this into a folder path then renamed folders might end up blocking deployments, therefore, we instead omit this detail from now on + delete asset.category; } - if (slotObj.blocks[block].slots) { + + if (asset.slots) { // * recursion: each block can have slots of its own - this._extractCode_slots(slotObj.blocks[block].slots, codeArr); + this._extractCode_slots( + `${prefix}.[${slot}-${block}]`, + asset.slots, + codeArr + ); } } } } } } + /** * Returns file contents mapped to their fileName without '.json' ending - * @param {string} dir directory that contains '.json' files to be read - * @returns {Object} fileName => fileContent map + * + * @param {string} dir directory with json files, e.g. /retrieve/cred/bu/asset, /deploy/cred/bu/asset, /template/asset + * @param {boolean} [_] unused parameter + * @param {string[]} [selectedSubType] asset, message, ... + * @returns {Promise.<MetadataTypeMap>} fileName => fileContent map */ - static getJsonFromFS(dir) { + static async getJsonFromFS(dir, _, selectedSubType) { const fileName2FileContent = {}; try { for (const subtype of this.definition.subTypes) { + if ( + selectedSubType && + !selectedSubType.includes('asset-' + subtype) && + !selectedSubType.includes('asset') + ) { + continue; + } const currentdir = File.normalizePath([dir, subtype]); - if (File.existsSync(currentdir)) { - const files = File.readdirSync(currentdir, { withFileTypes: true }); - - files.forEach((dirent) => { - try { - let thisDir = currentdir; - let fileName = dirent.name; - if (dirent.isDirectory()) { - // complex types with more than one extracted piece of code are saved in their - // own subfolder (with folder name = CustomerKey) - // this section aims to find that json in the subfolder - const subfolderFiles = File.readdirSync( - File.normalizePath([currentdir, dirent.name]) - ); - subfolderFiles.forEach((subFileName) => { - if (subFileName.endsWith('-meta.json')) { - fileName = subFileName; - thisDir = File.normalizePath([currentdir, dirent.name]); - } - }); - } - if (fileName.endsWith('-meta.json')) { - const fileContent = File.readJSONFile( - thisDir, - fileName, - true, - false - ); - // subtype will change the metadata suffix length - const fileNameWithoutEnding = fileName.slice( - 0, - -17 - subtype.length - ); + await this._getJsonFromFS(currentdir, subtype, fileName2FileContent); + } + } catch (ex) { + // this will catch issues with readdir + Util.metadataLogger('debug', this.definition.type, 'getJsonFromFS', ex); + throw ex; + } + return fileName2FileContent; + } + + /** + * helper for {@link Asset.getJsonFromFS} that reads the file system for metadata files + * + * @param {string} currentdir directory to scan + * @param {string} subtype single subtype of asset + * @param {MetadataTypeMap} fileName2FileContent fileName => fileContent map + */ + static async _getJsonFromFS(currentdir, subtype, fileName2FileContent) { + if (await File.pathExists(currentdir)) { + const fileEnding = `.asset-${subtype}-meta.json`; + const fileEndingLength = fileEnding.length; + const files = await File.readdir(currentdir, { withFileTypes: true }); + for (const dirent of files) { + const fileName = dirent.name; + try { + if (dirent.isDirectory()) { + await this._getJsonFromFS( + File.normalizePath([currentdir, fileName]), + subtype, + fileName2FileContent + ); + } else if (fileName.endsWith('.json')) { + const errorDir = currentdir.split('\\').join('/'); + const fileContent = await File.readJSONFile(currentdir, fileName, false); + // ! convert numbers to string to allow numeric keys to be checked properly + const key = Number.isInteger(fileContent[this.definition.keyField]) + ? fileContent[this.definition.keyField].toString() + : fileContent[this.definition.keyField]; + if (fileName.endsWith(fileEnding)) { + // subtype will change the metadata suffix length + const fileNameWithoutEnding = File.reverseFilterIllegalFilenames( + fileName.slice(0, -fileEndingLength) + ); + if (key === fileNameWithoutEnding) { fileName2FileContent[fileNameWithoutEnding] = fileContent; + } else { + Util.logger.error( + ` ☇ skipping ${this.definition.type} ${key}: Name of the metadata file and the JSON-key (${this.definition.keyField}) must match. Expected: ${key}${fileEnding}. Actual: ` + + Util.getGrayMsg(`${errorDir}/`) + + fileName + ); } - } catch (ex) { - // by catching this in the loop we gracefully handle the issue and move on to the next file - Util.metadataLogger('debug', this.definition.type, 'getJsonFromFS', ex); + } else { + Util.logger.error( + ` ☇ skipping ${this.definition.type} ${key}: Name of the metadata file must end on the extended metadata suffix. Expected: ${key}${fileEnding}. Actual: ` + + Util.getGrayMsg(`${errorDir}/`) + + fileName + ); } - }); + } + } catch (ex) { + // by catching this in the loop we gracefully handle the issue and move on to the next file + Util.metadataLogger('debug', this.definition.type, 'getJsonFromFS', ex); } } - } catch (ex) { - // this will catch issues with readdirSync - Util.metadataLogger('debug', this.definition.type, 'getJsonFromFS', ex); - throw new Error(ex); } - return fileName2FileContent; } + /** * check template directory for complex types that open subfolders for their subtypes + * * @param {string} templateDir Directory where metadata templates are stored * @param {string} templateName name of the metadata file - * @returns {AssetSubType} subtype name + * @returns {Promise.<string>} AssetSubType name */ - static findSubType(templateDir, templateName) { + static async findSubType(templateDir, templateName) { const typeDirArr = [this.definition.type]; let subType; for (const st of this.definition.subTypes) { const fileNameFull = templateName + '.' + this.definition.type + `-${st}-meta.json`; if ( - File.existsSync( + (await File.pathExists( File.normalizePath([templateDir, ...typeDirArr, st, fileNameFull]) - ) || - File.existsSync( + )) || + (await File.pathExists( File.normalizePath([templateDir, ...typeDirArr, st, templateName, fileNameFull]) - ) + )) ) { subType = st; break; } } - if (!subType) { - throw new Error( - `Could not find asset with name ${templateName} in ${File.normalizePath([ - templateDir, - ...typeDirArr, - ])}` - ); - } return subType; } + /** * optional method used for some types to try a different folder structure + * * @param {string} templateDir Directory where metadata templates are stored * @param {string[]} typeDirArr current subdir for this type * @param {string} templateName name of the metadata template * @param {string} fileName name of the metadata template file w/o extension - * @returns {AssetItem} metadata + * @returns {Promise.<string>} metadata in string form */ static async readSecondaryFolder(templateDir, typeDirArr, templateName, fileName) { // handles subtypes that create 1 folder per asset -> currently causes the below File.ReadFile to error out typeDirArr.push(templateName); - return await File.readFile([templateDir, ...typeDirArr], fileName, 'json'); + return await File.readFilteredFilename([templateDir, ...typeDirArr], fileName, 'json'); + } + + /** + * should return only the json for all but asset, query and script that are saved as multiple files + * additionally, the documentation for dataExtension and automation should be returned + * + * @param {string[]} keyArr customerkey of the metadata + * @returns {Promise.<string[]>} list of all files that need to be committed in a flat array ['path/file1.ext', 'path/file2.ext'] + */ + static async getFilesToCommit(keyArr) { + const basePath = File.normalizePath([ + this.properties.directories.retrieve, + this.buObject.credential, + this.buObject.businessUnit, + ]); + + const fileList = ( + await Promise.all( + keyArr.map(async (key) => { + // get subType, path an fileName by scanning the retrieve folder + let subType; + let filePath; + let fileName; + for (const st of this.definition.subTypes) { + fileName = `${key}.${this.definition.type}-${st}-meta.json`; + if ( + await File.pathExists( + File.normalizePath([basePath, this.definition.type, st, fileName]) + ) + ) { + subType = st; + filePath = [basePath, this.definition.type, st]; + break; + } else if ( + await File.pathExists( + File.normalizePath([ + basePath, + this.definition.type, + st, + key, + fileName, + ]) + ) + ) { + subType = st; + filePath = [basePath, this.definition.type, st, key]; + break; + } + } + if ( + Array.isArray(filePath) && + (await File.pathExists(File.normalizePath([...filePath, fileName]))) + ) { + // #1 load json to be able to find extracted text files & binary files + const metadata = await File.readJSONFile(filePath, fileName, false); + // #2 find all extracted text files + const fileListNested = ( + await this._mergeCode(metadata, basePath, subType, metadata.customerKey) + ).map((item) => + File.normalizePath([ + basePath, + ...item.subFolder, + `${item.fileName}.${item.fileExt}`, + ]) + ); + // ensure we dont overlook other versions when using this logic to auto-delete older files + const fileListNestedSet = new Set(fileListNested); + for (const filePath of fileListNested) { + // allowed file extensions at this point are only html, ssjs and amp + const baseFilePath = filePath.replace(/\.[^/.]+$/, ''); + fileListNestedSet.add(`${baseFilePath}.html`); + fileListNestedSet.add(`${baseFilePath}.ssjs`); + fileListNestedSet.add(`${baseFilePath}.amp`); + } + + const response = [ + File.normalizePath([...filePath, fileName]), + ...fileListNestedSet, + ]; + // #3 get binary file + const binaryFilePath = await this._readExtendedFileFromFS( + metadata, + subType, + basePath, + false + ); + if (binaryFilePath) { + response.push(binaryFilePath); + } + + return response; + } else { + return []; + } + }) + ) + ).flat(); + return fileList; + } + + /** + * helper to allow us to select single metadata entries via REST + * + * @private + * @param {string} key customer key + * @returns {Promise.<string>} id value or null + */ + static async _getIdForSingleRetrieve(key) { + const name = key.startsWith('name:') ? key.slice(5) : null; + const filter = name + ? '?$filter=name%20eq%20' + encodeURIComponent(name) + : '?$filter=customerKey%20eq%20' + encodeURIComponent(key); + + const results = await this.client.rest.get('/asset/v1/content/assets/' + filter); + const items = results?.items || []; + const found = items.find((item) => + name ? item[this.definition.nameField] === name : item[this.definition.keyField] === key + ); + return found?.id || null; + } + + /** + * helper to allow us to select single metadata entries via REST + * + * @private + * @param {string} id id field + * @returns {Promise.<string>} key value or null + */ + static async _getKeyForSingleRetrieve(id) { + const results = await this.client.rest.get('/asset/v1/content/assets/' + id); + return results?.customerKey || null; + } + + /** + * Delete a metadata item from the specified business unit + * + * @param {string} key Identifier of item + * @returns {Promise.<boolean>} deletion success flag + */ + static async deleteByKey(key) { + // delete only works with the query's object id + let id; + if (key?.startsWith('id:')) { + id = key.slice(3); + // we need to get the actual key so that postDeletetTasks know what to do + key = await this._getKeyForSingleRetrieve(id); + } else { + id = key ? await this._getIdForSingleRetrieve(key) : null; + } + if (!id) { + await this.deleteNotFound(key); + + return false; + } + return super.deleteByKeyREST('/asset/v1/content/assets/' + id, key); + } + + /** + * clean up after deleting a metadata item + * cannot use the generic method due to the complexity of how assets are saved to disk + * + * @param {string} key Identifier of metadata item + * @returns {Promise.<void>} - + */ + static async postDeleteTasks(key) { + if (key?.startsWith('id:')) { + // sad + } + const fileArr = await this.getFilesToCommit([key]); + if (!Array.isArray(fileArr) || fileArr.length === 0) { + Util.logger.verbose(` - ${this.definition.type} ${key} does not exist on disk`); + return; + } + + // check if asset sits in its own folder + const ownFolderIndex = + fileArr[0].indexOf(key + '\\') > 0 + ? fileArr[0].indexOf(key + '\\') + : fileArr[0].indexOf(key + '/'); + if (ownFolderIndex > 0) { + fileArr.push(fileArr[0].slice(0, ownFolderIndex + key.length)); + } + + for (const filePath of fileArr) { + await File.remove(filePath); + } + } + + /** + * get name & key for provided id + * + * @param {string} id Identifier of metadata + * @returns {Promise.<{key:string, name:string, path:string, folder:string, mid:number, error:string, isShared:boolean}>} key, name and path of metadata; null if not found + */ + static async resolveId(id) { + let response; + const json = { + key: '', + isShared: false, + name: '', + path: '', + folder: '', + mid: 0, + legacyId: 0, + error: '', + sharedWith: [], + }; + try { + response = await this.client.rest.get( + 'asset/v1/content/assets/' + + id + + '?$fields=id,customerKey,name,memberId,legacyData,sharingProperties' + ); + } catch (ex) { + if (ex.response?.status !== 404) { + throw ex; + } + } + if (response?.id) { + const item = response; + const subType = this.#getMainSubtype(item.assetType.name); + + // prep response object + json.key = item[this.definition.keyField]; + json.name = item[this.definition.nameField]; + json.mid = item.memberId; + json.isShared = item.memberId != this.buObject.mid; + json.sharedWith = item.sharingProperties?.sharedWith || null; + json.legacyId = item.legacyData?.legacyId; + + const ownerBUName = json.isShared + ? Util.inverseGet( + this.properties.credentials[this.buObject.credential].businessUnits, + json.mid + ) + : this.buObject.businessUnit; + + // find path for code of content block, fall back to json if not found; undefined if not even the json exists + let path = await this.#getPath(subType, item, ownerBUName); + + if (!json.sharedWith) { + delete json.sharedWith; + } + if (!json.isShared && !path) { + // if not shared, we should have the file on disk; attempt download + if (!cache.getCache()?.folder) { + // folders not cached yet but required to fill json.path + Folder.client = this.client; + Folder.buObject = this.buObject; + Folder.properties = this.properties; + const result = await Folder.retrieveForCache(null, ['asset', 'asset-shared']); + if (!cache.getCache()) { + cache.initCache(this.buObject); + } + cache.setMetadata('folder', result.metadata); + } + + await this.retrieve( + File.normalizePath([ + this.properties.directories.retrieve, + this.buObject.credential, + this.buObject.businessUnit, + ]), + null, + [subType], + json.key + ); + // try again + path = await this.#getPath(subType, item, this.buObject.businessUnit); + } + + if (path) { + json.path = path; + delete json.error; + } else { + json.error = 'file not found on local disk'; + delete json.path; + } + const fileContent = await this.#getJson(subType, item); + if (fileContent?.r__folder_Path) { + json.folder = fileContent.r__folder_Path; + } + if (!json.legacyId) { + delete json.legacyId; + } + + if (Util.OPTIONS.json) { + // for automated processing by VSCode extension, optionally print the json + console.log(JSON.stringify(json, null, 2)); // eslint-disable-line no-console + } else { + Util.logger.info(` - ID: ${id}`); + Util.logger.info(` - Key: ${item[this.definition.keyField]}`); + Util.logger.info(` - Name: ${item[this.definition.nameField]}`); + + if (json.isShared) { + Util.logger.warn(' - Shared from: ' + ownerBUName + ' (' + json.mid + ')'); + } + if (json.sharedWith && Array.isArray(json.sharedWith)) { + Util.logger.warn( + ` - Shared with: ${json.sharedWith + .map( + (mid) => + Util.inverseGet( + this.properties.credentials[this.buObject.credential] + .businessUnits, + mid + ) + + ' (' + + mid + + ')' + ) + .toSorted() + .join(', ')}` + ); + } + if (json.legacyId) { + Util.logger.info(` - Legacy ID: ${json.legacyId}`); + } + Util.logger.info(` - How to use:`); + Util.logger.info(` %%= ContentBlockByKey("${json.key}") =%%`); + + if (json.folder) { + Util.logger.info( + ` %%= ContentBlockByName("${ + json.folder + .split('/') + .map((s) => s.replaceAll(Util.folderNameSlashEscapeChar, '/')) + .join('\\') + + '\\' + + json.name + }") =%%` + ); + if (json.folder.includes('&') || json.name.includes('&')) { + Util.logger.warn( + ` - ContentBlockByName will fail because your path or name contains the & or & symbol. Please replace it with 'and' or remove it.` + ); + } + } + Util.logger.info( + ' - local link: ' + + (path || + `404. Try running mcdev r ${this.buObject.credential}/${ownerBUName} ${this.definition.type}-${subType} ${item[this.definition.keyField]}`) + ); + } + return json; + } else { + json.error = 'id not found'; + delete json.key; + delete json.mid; + delete json.name; + delete json.path; + delete json.folder; + delete json.isShared; + delete json.legacyId; + delete json.sharedWith; + if (Util.OPTIONS.json) { + console.log(JSON.stringify(json, null, 2)); // eslint-disable-line no-console + return json; + } + Util.logger.error(` - ${this.definition.type} with id ${id} not found on BU`); + return json; + } + } + + /** + * helper for {@link Asset.resolveId} that finds the path to the asset's code + * + * @param {string} subType asset subtype + * @param {object} item api response for metadata + * @param {string} buName owner business unit name + * @returns {Promise.<string>} path to the asset's code + */ + static async #getPath(subType, item, buName) { + const pathBase1 = `./retrieve/${this.buObject.credential}/${buName}/${this.definition.type}/${subType}/${item[this.definition.keyField]}.${this.definition.type}-${subType}-meta.`; + const pathBase2 = `./retrieve/${this.buObject.credential}/${buName}/${this.definition.type}/${subType}/${item[this.definition.keyField]}/${item[this.definition.keyField]}.${this.definition.type}-${subType}-meta.`; + const paths = []; + for (const ext of ['html', 'ssjs', 'amp', 'json']) { + paths.push(pathBase1 + ext, pathBase2 + ext); + } + const path = await Util.findAsync(paths, async (p) => await File.pathExists(p)); + return path; + } + + /** + * helper for {@link Asset.resolveId} that loads the JSON file for the asset + * + * @param {string} subType asset subtype + * @param {object} item api response for metadata + * @returns {Promise.<object>} JS object of the asset we loaded from disk + */ + static async #getJson(subType, item) { + const mid = item.memberId; + const buName = + mid === this.buObject.mid + ? this.buObject.businessUnit + : Object.keys( + this.properties.credentials[this.buObject.credential].businessUnits + ).find( + (buName) => + this.properties.credentials[this.buObject.credential].businessUnits[ + buName + ] == mid + ); + const pathBase1 = `./retrieve/${this.buObject.credential}/${buName}/${this.definition.type}/${subType}/${item[this.definition.keyField]}.${this.definition.type}-${subType}-meta.`; + const pathBase2 = `./retrieve/${this.buObject.credential}/${buName}/${this.definition.type}/${subType}/${item[this.definition.keyField]}/${item[this.definition.keyField]}.${this.definition.type}-${subType}-meta.`; + const paths = [pathBase1 + 'json', pathBase2 + 'json']; + + const path = await Util.findAsync(paths, async (p) => await File.pathExists(p)); + const pathArr = path.split('/'); + const fileName = pathArr.pop().slice(0, -5); + const fileContent = await File.readJSONFile(pathArr.join('/'), fileName, false); + return fileContent; + } + + /** + * + * @param {MetadataTypeItem} item single metadata item + * @param {string} retrieveDir directory where metadata is saved + * @param {Set.<string>} [findAssetKeys] list of keys that were found referenced via ContentBlockByX; if set, method only gets keys and runs no updates + * @returns {Promise.<MetadataTypeItem>} key of the item that was updated + */ + static async replaceCbReference(item, retrieveDir, findAssetKeys) { + const responseItem = structuredClone(item); + const parentName = `${this.definition.type} ${item[this.definition.keyField]}`; + let changes = false; + let error; + + // *** type specific logic *** + const subType = this.#getMainSubtype(item.assetType.name); + /** @type {CodeExtract[]} */ + const fileList = await this._mergeCode( + item, + retrieveDir, + subType, + item[this.definition.keyField], + false + ); + const fileListChanged = []; + for (const file of fileList) { + try { + file.content = ReplaceCbReference.replaceReference( + file.content, + parentName, + findAssetKeys + ); + changes = true; + fileListChanged.push(file); + } catch (ex) { + if (ex.code !== 200) { + error = ex; + } + } + } + if (!findAssetKeys) { + // save what was changed regardless of other errors + for (const extractedFile of fileListChanged) { + File.writeToFile( + [retrieveDir, ...extractedFile.subFolder], + extractedFile.fileName, + extractedFile.fileExt, + extractedFile.content, + extractedFile.encoding || null + ); + } + } + + if (error) { + throw error; + } + + if (!changes) { + const ex = new Error('No changes made to the code.'); + // @ts-expect-error custom error object + ex.code = 200; + throw ex; + } + + // *** finish *** + // replaceReference will throw an error if nothing was updated which will end execution here + // no error means we have a new item to deploy and need to update the item in our retrieve folder + return responseItem; + } + + /** + * this iterates over all items found in the retrieve folder and executes the type-specific method for replacing references + * + * @param {MetadataTypeMap} metadataMap list of metadata (keyField => metadata) + * @param {string} retrieveDir retrieve dir including cred and bu + * @param {Set.<string>} [findAssetKeys] list of keys that were found referenced via ContentBlockByX; if set, method only gets keys and runs no updates + * @returns {Promise.<string[]>} Returns list of keys for which references were replaced + */ + static async replaceCbReferenceLoop(metadataMap, retrieveDir, findAssetKeys) { + const keysForDeploy = []; + if (!metadataMap) { + // if a type was skipped e.g. because it shall only be looked at on the parent then we would expect metadataMap to be undefined + return keysForDeploy; + } + + const fromDescription = Util.OPTIONS.referenceFrom + .map((from) => 'ContentBlockBy' + Util.capitalizeFirstLetter(from)) + .join(' and '); + + if (Object.keys(metadataMap).length) { + Util.logger.debug(` - Searching in ${this.definition.type} `); + const deployMap = {}; + + for (const key in metadataMap) { + const item = metadataMap[key]; + if (this.isFiltered(item, true) || this.isFiltered(item, false)) { + // we would not have saved these items to disk but they exist in the cache and hence need to be skipped here + + continue; + } + + try { + // add key but make sure to turn it into string or else numeric keys will be filtered later + deployMap[key] = await this.replaceCbReference( + item, + retrieveDir, + findAssetKeys + ); + + // ! this method is equal to the super version except that it does not run saveToDisk here + // await this.saveToDisk(deployMap, key, baseDir); + if (findAssetKeys) { + keysForDeploy.push(...[...findAssetKeys].map((key) => key + '')); + } else { + keysForDeploy.push(key + ''); + Util.logger.info( + ` - added ${this.definition.type} to update queue: ${key}` + ); + } + } catch (ex) { + if (ex.code !== 200) { + // dont print error if we simply did not find relevant content blocks + Util.logger.errorStack( + ex, + 'issue with ' + this.definition.type + ' ' + key + ); + } + if (!findAssetKeys) { + Util.logger.info( + Util.getGrayMsg( + ` ☇ skipping ${this.definition.type} ${ + item[this.definition.keyField] + }: no ${fromDescription} found` + ) + ); + } + } + } + if (!findAssetKeys) { + Util.logger.info( + `Found ${keysForDeploy.length} ${this.definition.type}${keysForDeploy.length === 1 ? '' : 's'} to update` + ); + } + } + return keysForDeploy; + } + + /** + * + * @param {string[]} keyArr limit retrieval to given metadata type + * @param {string} retrieveDir retrieve dir including cred and bu + * @param {Set.<string>} findAssetKeys list of keys that were found referenced via ContentBlockByX; if set, method only gets keys and runs no updates + * @returns {Promise.<Set.<string>>} found asset keys + */ + static async getCbReferenceKeys(keyArr, retrieveDir, findAssetKeys) { + if (!Object.prototype.hasOwnProperty.call(this, 'replaceCbReference')) { + // only types that have a replaceCbReference method actually have ampscript/ssjs + return; + } + if (!this.getJsonFromFSCache) { + // avoid re-reading the same files in every recursive iteration + this.getJsonFromFSCache = await this.getJsonFromFS( + File.normalizePath([retrieveDir, this.definition.type]) + ); + } + // get all metadata of the current type; then filter by keys in selectedTypes + const metadataMap = Util.filterObjByKeys(this.getJsonFromFSCache, [...findAssetKeys]); + const newKeysFound = new Set( + await this.replaceCbReferenceLoop(metadataMap, retrieveDir, findAssetKeys) + ); + if (newKeysFound.size) { + const keysToCrawl = []; + for (const value of newKeysFound) { + if (!keyArr.includes(value)) { + keyArr.push(value); + keysToCrawl.push(value); + } + } + Util.logger.info(Util.getGrayMsg(` - asset: ${keysToCrawl.join(', ')}`)); + + if (keysToCrawl.length) { + findAssetKeys = new Set([ + ...findAssetKeys, + ...(await this.getCbReferenceKeys(keyArr, retrieveDir, new Set(keysToCrawl))), + ]); + } + } + return findAssetKeys; + } + + /** + * optional helper for {@link this.getDependentTypes} + * + * @param {object} metadataItem metadata json read from filesystem + * @param {TypeKeyCombo} dependentTypeKeyCombo list started in this.getDependentTypes + */ + static getDependentFilesExtra(metadataItem, dependentTypeKeyCombo) { + const dependentKeyArr = []; + // search: + // - metadata.views.html.slots + // - metadata.slots + if (metadataItem.views?.html?.slots) { + this._getDependentFilesExtra(metadataItem.views.html.slots, dependentKeyArr); + } + if (metadataItem.slots) { + this._getDependentFilesExtra(metadataItem.slots, dependentKeyArr); + } + if (dependentKeyArr.length) { + dependentTypeKeyCombo.asset ||= []; + dependentTypeKeyCombo.asset.push(...dependentKeyArr); + } + } + + /** + * @param {object} slots metadata.views.html.slots or deeper slots.<>.blocks.<>.slots + * @param {string[]} dependentKeyArr list of found keys + */ + static _getDependentFilesExtra(slots, dependentKeyArr) { + for (const slot in slots) { + for (const block in slots[slot].blocks) { + const asset = slots[slot].blocks[block]; + if (asset.r__asset_key) { + dependentKeyArr.push(asset.r__asset_key); + } + if (asset.views?.html?.slots) { + // * recursion: each block can have slots of its own + this._getDependentFilesExtra(asset.views.html.slots, dependentKeyArr); + } + if (asset.slots) { + // * recursion: each block can have slots of its own + this._getDependentFilesExtra(asset.slots, dependentKeyArr); + } + } + } + } + + /** + * helper for {@link MetadataType.createOrUpdate} + * + * @param {MetadataTypeItem} metadataItem to be deployed item + * @returns {MetadataTypeItem} cached item or undefined + */ + static getCacheMatchedByName(metadataItem) { + let cacheMatchedByName; + + if (Util.OPTIONS.matchName) { + // make sure to run the search ONLY if OPTIONS.matchName is true and definition.allowMatchingByName signals support + const assetCache = cache.getCache()?.asset; + const potentials = []; + for (const key in assetCache) { + const cachedAsset = assetCache[key]; + if ( + cachedAsset[this.definition.nameField] === + metadataItem[this.definition.nameField] && + cachedAsset.assetType.id === metadataItem.assetType.id + ) { + potentials.push(cachedAsset); + } + } + let deployFolderPath; + if (potentials.length >= 1) { + deployFolderPath = cache.searchForField( + 'folder', + metadataItem.category.id, + 'ID', + 'Path' + ); + } + if (potentials.length > 1) { + const potentialsWithMatchingFolder = potentials.filter( + (el) => el.category.id === metadataItem.category.id + ); + throw new Error( + `found multiple name matches in cache. New folder: "${deployFolderPath}". Identified keys: ${potentials.map((p) => p[this.definition.keyField]).join(', ')}. ` + + (potentialsWithMatchingFolder.length + ? `Folder for ${potentialsWithMatchingFolder[0][this.definition.keyField]} matches the new folder. ` + : '') + ); + } else if (potentials.length === 1) { + if (potentials[0].category.id === metadataItem.category.id) { + cacheMatchedByName = potentials[0]; + + Util.logger.info( + Util.getGrayMsg( + ` - found ${this.definition.type} ${metadataItem[this.definition.keyField]} in cache by name "${metadataItem[this.definition.nameField]}" and folder "${deployFolderPath}": ${cacheMatchedByName[this.definition.keyField]}` + ) + ); + } else { + const cacheFolderPath = cache.searchForField( + 'folder', + potentials[0].category.id, + 'ID', + 'Path' + ); + throw new Error( + `found match in cache by name but folder is different. New folder: "${deployFolderPath}". Existing: "${cacheFolderPath}": Identified key: ${potentials[0][this.definition.keyField]}` + ); + } + } else { + Util.logger.debug( + ` - no name-match found for ${this.definition.type} ${metadataItem[this.definition.keyField]}. Creating new asset instead.` + ); + } + } + return cacheMatchedByName; } } // Assign definition to static attributes -Asset.definition = require('../MetadataTypeDefinitions').asset; -module.exports = Asset; +import MetadataTypeDefinitions from '../MetadataTypeDefinitions.js'; + +Asset.definition = MetadataTypeDefinitions.asset; + +export default Asset; diff --git a/lib/metadataTypes/AttributeGroup.js b/lib/metadataTypes/AttributeGroup.js index e8154c955..4c20e3d96 100644 --- a/lib/metadataTypes/AttributeGroup.js +++ b/lib/metadataTypes/AttributeGroup.js @@ -1,33 +1,124 @@ 'use strict'; -const MetadataType = require('./MetadataType'); +import MetadataType from './MetadataType.js'; +import { Util } from '../util/util.js'; +import cache from '../util/cache.js'; + +/** + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItem} MetadataTypeItem + * @typedef {import('../../types/mcdev.d.js').MetadataTypeMapObj} MetadataTypeMapObj + */ /** * AttributeGroup MetadataType + * * @augments MetadataType */ class AttributeGroup extends MetadataType { + /** + * Retrieves Metadata of schema attribute groups. + * + * @param {string} retrieveDir Directory where retrieved metadata directory will be saved + * @param {void | string[]} [_] unused parameter + * @param {void | string[]} [__] unused parameter + * @param {string} [key] customer key of single item to retrieve + * @returns {Promise.<MetadataTypeMapObj>} Promise of metadata + */ + static async retrieve(retrieveDir, _, __, key) { + return super.retrieveREST( + retrieveDir, + '/hub/v1/contacts/schema/attributeGroups', + null, + key + ); + } + /** * Retrieves Metadata of schema attribute groups for caching. - * @returns {Promise<Object>} Promise of metadata + * + * @returns {Promise.<MetadataTypeMapObj>} Promise of metadata */ static retrieveForCache() { - return super.retrieveREST(null, '/hub/v1/contacts/schema/attributeGroups', null); + return super.retrieveREST(null, '/hub/v1/contacts/schema/attributeGroups'); } /** - * Retrieves Metadata of schema attribute groups. - * @param {String} retrieveDir Directory where retrieved metadata directory will be saved - * @returns {Promise<Object>} Promise of metadata + * manages post retrieve steps + * + * @param {MetadataTypeItem} metadata a single metadata + * @returns {MetadataTypeItem} metadata */ - static retrieve(retrieveDir) { - return super.retrieveREST(retrieveDir, '/hub/v1/contacts/schema/attributeGroups', null); + static postRetrieveTasks(metadata) { + // Member ID + delete metadata.mID; + + // attributeSet + metadata.r__attributeSet_key = metadata.attributeSetIdentifiers.map((attributeSet) => { + try { + const key = cache.searchForField( + 'attributeSet', + attributeSet.definitionID, + 'definitionID', + 'definitionKey' + ); + if (key !== attributeSet.definitionKey) { + Util.logger.debug( + `AttributeSet key mismatch. Overwriting ${attributeSet.definitionKey} with ${key}` + ); + } + return key; + } catch (ex) { + Util.logger.warn( + ` - ${this.definition.type} ${metadata[this.definition.keyField]} (for ${ + attributeSet.definitionKey + }): ${ex.message}` + ); + return attributeSet; + } + }); + delete metadata.attributeSetIdentifiers; + + // requiredRelationships + // TODO: implement + + // description is not returned by API when empty. Set to empty string to propose the field as an option to users + metadata.description ||= ''; + + // applicationKey is only used by system generated attribute groups and otherwise it's empty. + if (metadata.applicationKey === '') { + // remove useless field + delete metadata.applicationKey; + } + + // connectingID.identifierType seems to be always set to 'FullyQualifiedName' - to be sure we check it here and remove it if it's the case + if (metadata.connectingID?.identifierType === 'FullyQualifiedName') { + // remove useless field + delete metadata.connectingID; + } + + // containsSchemaAttributes is only true for system generated attribute groups and otherwise it's false. + if (!metadata.containsSchemaAttributes) { + delete metadata.containsSchemaAttributes; + } + + // isSystemDefined is only true for system generated attribute groups and cannot be deployed + if (!metadata.isSystemDefined) { + delete metadata.isSystemDefined; + } + + return metadata; } + + /** + * prepares for deployment + * + * @param {MetadataTypeItem} metadata a single item + * @returns {MetadataTypeItem} Promise + */ } // Assign definition to static attributes -AttributeGroup.definition = require('../MetadataTypeDefinitions').attributeGroup; -AttributeGroup.cache = {}; -AttributeGroup.client = undefined; +import MetadataTypeDefinitions from '../MetadataTypeDefinitions.js'; +AttributeGroup.definition = MetadataTypeDefinitions.attributeGroup; -module.exports = AttributeGroup; +export default AttributeGroup; diff --git a/lib/metadataTypes/AttributeSet.js b/lib/metadataTypes/AttributeSet.js new file mode 100644 index 000000000..5d8d96bde --- /dev/null +++ b/lib/metadataTypes/AttributeSet.js @@ -0,0 +1,376 @@ +'use strict'; + +import AttributeGroup from './AttributeGroup.js'; +import MetadataType from './MetadataType.js'; +import { Util } from '../util/util.js'; +import cache from '../util/cache.js'; + +/** + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItem} MetadataTypeItem + * @typedef {import('../../types/mcdev.d.js').MetadataTypeMap} MetadataTypeMap + * @typedef {import('../../types/mcdev.d.js').MetadataTypeMapObj} MetadataTypeMapObj + */ + +/** + * AttributeSet MetadataType + * + * @augments MetadataType + */ +class AttributeSet extends MetadataType { + static systemValueDefinitions; + + /** + * Retrieves Metadata of schema set Definitions. + * + * @param {string} retrieveDir Directory where retrieved metadata directory will be saved + * @param {void | string[]} [_] unused parameter + * @param {void | string[]} [__] unused parameter + * @param {string} [key] customer key of single item to retrieve + * @returns {Promise.<MetadataTypeMapObj>} Promise + */ + static async retrieve(retrieveDir, _, __, key) { + if (retrieveDir && !cache.getCache()?.attributeGroup) { + // ! attributeGroup and attributeSet both link to each other. caching attributeGroup here "manually", assuming that it's quicker than the other way round + Util.logger.info(' - Caching dependent Metadata: attributeGroup'); + AttributeGroup.buObject = this.buObject; + AttributeGroup.client = this.client; + AttributeGroup.properties = this.properties; + const result = await AttributeGroup.retrieveForCache(); + cache.setMetadata('attributeGroup', result.metadata); + } + return super.retrieveREST(retrieveDir, '/hub/v1/contacts/schema/setDefinitions', null, key); + } + + /** + * Retrieves Metadata of schema set definitions for caching. + * + * @returns {Promise.<MetadataTypeMapObj>} Promise + */ + static retrieveForCache() { + return super.retrieveREST(null, '/hub/v1/contacts/schema/setDefinitions'); + } + + /** + * used to identify updated shared data extensions that are used in attributeSets. + * helper for DataExtension.#fixShared_onBU + * + * @param {Object.<string, string>} sharedDataExtensionMap ID-Key relationship of shared data extensions + * @param {object} fixShared_fields DataExtensionField.fixShared_fields + * @returns {Promise.<string[]>} Promise of list of shared dataExtension IDs + */ + static async fixShared_retrieve(sharedDataExtensionMap, fixShared_fields) { + if (!Object.keys(sharedDataExtensionMap).length) { + return []; + } + const result = await super.retrieveREST(null, '/hub/v1/contacts/schema/setDefinitions'); + const metadataMap = result?.metadata; + if (metadataMap && Object.keys(metadataMap).length) { + const sharedDeIds = Object.keys(metadataMap) + .filter( + (asKey) => + metadataMap[asKey].storageLogicalType === 'ExactTargetSchema' || + metadataMap[asKey].storageLogicalType === 'DataExtension' + ) + .filter((asKey) => { + // check if dataExtension ID is found on any attributeSet of this BU + if (sharedDataExtensionMap[metadataMap[asKey].storageReferenceID.value]) { + Util.logger.debug( + ` shared dataExtension ID ${metadataMap[asKey].storageReferenceID.value} found in attributeSet ${asKey}` + ); + return true; + } else { + return false; + } + }) + .filter((asKey) => { + // check if any of the dataExtension fields dont exist on the attributeSet or are out of date + const deKey = + sharedDataExtensionMap[metadataMap[asKey].storageReferenceID.value]; + const asFields = metadataMap[asKey].valueDefinitions; + const deFields = Object.values(fixShared_fields[deKey]); + return deFields.some((deField) => { + const search = asFields.filter((asf) => asf.name === deField.Name); + if (!search.length) { + Util.logger.debug( + Util.getGrayMsg( + ` - Field ${deField.Name} not found in attributeSet; Note: only first recognized difference is printed to log` + ) + ); + return true; + } + const asField = search[0]; + if (asField.dataType !== deField.FieldType) { + Util.logger.debug( + Util.getGrayMsg( + ` - Field ${deField.Name} FieldType changed (old: ${asField.dataType}; new: ${deField.FieldType}); Note: only first recognized difference is printed to log` + ) + ); + return true; + } + asField.defaultValue ||= ''; + if ( + (asField.defaultValue && deField.DefaultValue === '') || + (deField.FieldType === 'Boolean' && + deField.DefaultValue !== '' && + (deField.DefaultValue + ? 'True' + : 'False' !== asField.defaultValue)) || + (deField.FieldType !== 'Boolean' && + deField.DefaultValue !== asField.defaultValue) + ) { + Util.logger.debug( + ` - Field ${deField.Name} DefaultValue changed (old: ${asField.defaultValue}; new: ${deField.DefaultValue}); Note: only first recognized difference is printed to log` + ); + return true; + } + // some field types don't carry the length property. reset to 0 to ease comparison + asField.length ||= 0; + if (asField.length !== deField.MaxLength) { + Util.logger.debug( + ` - Field ${deField.Name} MaxLength changed (old: ${asField.length}; new: ${deField.MaxLength}); Note: only first recognized difference is printed to log` + ); + return true; + } + if (asField.isNullable !== deField.IsRequired) { + Util.logger.debug( + ` - Field ${deField.Name} IsRequired changed (old: ${asField.isNullable}; new: ${deField.IsRequired}); Note: only first recognized difference is printed to log` + ); + return true; + } + if (asField.isPrimaryKey !== deField.IsPrimaryKey) { + Util.logger.debug( + ` - Field ${deField.Name} IsPrimaryKey changed (old: ${asField.isPrimaryKey}; new: ${deField.IsPrimaryKey}); Note: only first recognized difference is printed to log` + ); + return true; + } + return false; + }); + }) + .map((key) => metadataMap[key].storageReferenceID.value) + .filter(Boolean); + return sharedDeIds; + } else { + // nothing to do - return empty array + return []; + } + } + + /** + * Builds map of metadata entries mapped to their keyfields + * + * @param {object} body json of response body + * @param {string} [singleRetrieve] key of single item to filter by + * @returns {MetadataTypeMap} keyField => metadata map + */ + static parseResponseBody(body, singleRetrieve) { + const metadataCache = super.parseResponseBody(body); + + // make sure we add the entire list to cache before running postRetrieveTasks because of the self-references this type is using + // usually, the cache is only written into after all postRetrieveTasks have been run + cache.setMetadata(this.definition.type, metadataCache); + + const metadataStructure = super.parseResponseBody(body, singleRetrieve); + return metadataStructure; + } + + /** + * manages post retrieve steps + * + * @param {MetadataTypeItem} metadata a single metadata + * @returns {MetadataTypeItem} metadata + */ + static postRetrieveTasks(metadata) { + // folder + if (metadata.storageLogicalType === 'DataExtension') { + // attributeSet created for Group Connect do not have a folder + super.setFolderPath(metadata); + } + + // source + switch (metadata.storageLogicalType) { + case 'ExactTargetSchema': // synced / shared DEs + case 'DataExtension': { + // shared / local DEs + try { + metadata.r__dataExtension_key = cache.searchForField( + 'dataExtension', + metadata.storageReferenceID.value, + 'ObjectID', + 'CustomerKey' + ); + // TODO: check if fields in metadata.sendAttributeStorageName exist in data extension --> error + // TODO: check if fields in data extension exist in metadata.sendAttributeStorageName --> warn + + delete metadata.storageReferenceID; + delete metadata.storageName; + delete metadata.storageObjectInformation; // type ExactTargetSchema only + } catch (ex) { + Util.logger.warn( + ` - ${this.definition.type} ${metadata[this.definition.keyField]}: ${ + ex.message + }` + ); + } + break; + } + case 'MobileAttributes': { + // TODO: implement + // "storageName": "_MobileAddress", + + break; + } + case 'EnterpriseAttributes': { + // TODO: implement + // "storageName": "_EnterpriseAttribute", + + break; + } + case 'PushAttributes': { + // TODO: implement + // "storageName": "_PushAddress", + + break; + } + } + + // relationships to attributeGroups & AttributeSet + if (Array.isArray(metadata.relationships)) { + for (const relationship of metadata.relationships) { + for (const type of ['left', 'right']) { + if ( + relationship[type + 'Item']?.connectingID?.identifierType === + 'FullyQualifiedName' + ) { + delete relationship[type + 'Item'].connectingID; + } + let relationshipObj = null; + switch (relationship[type + 'Item'].relationshipType) { + case 'AttributeGroup': { + try { + relationship[type + 'Item'].r__attributeGroup_key = + cache.searchForField( + 'attributeGroup', + relationship[type + 'Item']?.identifier, + 'definitionID', + 'definitionKey' + ); + delete relationship[type + 'Item']?.identifier; + } catch (ex) { + Util.logger.warn( + ` - ${this.definition.type} ${ + metadata[this.definition.keyField] + }: ${ex.message}` + ); + } + // get relationship fieldnames + relationshipObj = { + valueDefinitions: this._getSystemValueDefinitions(), + }; + break; + } + case 'AttributeSet': { + try { + relationship[type + 'Item'].r__attributeSet_key = + cache.searchForField( + 'attributeSet', + relationship[type + 'Item']?.identifier, + 'definitionID', + 'definitionKey' + ); + delete relationship[type + 'Item']?.identifier; + + // get relationship fieldnames + // check if its a self-reference to metadata.valueDefinitions or if it's a reference to another attributeSet + relationshipObj = + relationship[type + 'Item'].r__attributeSet_key === + metadata.definitionKey + ? metadata + : cache.getByKey( + 'attributeSet', + relationship[type + 'Item'].r__attributeSet_key + ); + } catch (ex) { + Util.logger.warn( + ` - ${this.definition.type} ${ + metadata[this.definition.keyField] + }: ${ex.message}` + ); + } + break; + } + } + try { + // get relationship fieldnames + // resolve field values + for (const attr of relationship.relationshipAttributes) { + const id = attr[type + 'AttributeID']; + const valueDefinition = relationshipObj.valueDefinitions.find( + (item) => item.valueDefinitionID === id + ); + if (valueDefinition) { + attr['c__' + type + 'FullyQualifiedName'] = + valueDefinition.fullyQualifiedName; + delete attr[type + 'AttributeID']; + delete attr[type + 'ConnectingID']; + } else { + throw new Error( + `Could not find ${type}AttributeID ${id} of relationship ${relationship.relationshipID}` + ); + } + } + } catch (ex) { + Util.logger.warn( + ` - ${this.definition.type} ${metadata[this.definition.nameField]} / ${ + metadata[this.definition.keyField] + }: ${ex.message}` + ); + } + } + } + } + + // Member ID + delete metadata.customObjectOwnerMID; + + // remove duplicate ID fields (main field is definitionID) + delete metadata.setDefinitionID; + if (metadata.dataRetentionProperties?.setDefinitionID) { + delete metadata.dataRetentionProperties?.setDefinitionID; + } + + // connectingID.identifierType seems to be always set to 'FullyQualifiedName' - to be sure we check it here and remove it if it's the case + if (metadata.connectingID?.identifierType === 'FullyQualifiedName') { + // remove useless field + delete metadata.connectingID; + } + + return metadata; + } + + /** + * helper for {@link AttributeSet.postRetrieveTasks} + * + * @returns {object[]} all system value definitions + */ + static _getSystemValueDefinitions() { + this.systemValueDefinitions ||= {}; + if (!this.systemValueDefinitions[this.buObject.mid]) { + this.systemValueDefinitions[this.buObject.mid] = Object.values( + cache.getCache()['attributeSet'] + ) + .flatMap((item) => { + if (item.isSystemDefined) { + return item.valueDefinitions; + } + }) + .filter(Boolean); + } + return this.systemValueDefinitions[this.buObject.mid]; + } +} + +// Assign definition to static attributes +import MetadataTypeDefinitions from '../MetadataTypeDefinitions.js'; +AttributeSet.definition = MetadataTypeDefinitions.attributeSet; + +export default AttributeSet; diff --git a/lib/metadataTypes/Automation.js b/lib/metadataTypes/Automation.js index 5c38cc067..617326c32 100644 --- a/lib/metadataTypes/Automation.js +++ b/lib/metadataTypes/Automation.js @@ -1,165 +1,362 @@ 'use strict'; -const MetadataType = require('./MetadataType'); -const Util = require('../util/util'); -const File = require('../util/file'); -const Definitions = require('../MetadataTypeDefinitions'); +import MetadataType from './MetadataType.js'; +import { Util } from '../util/util.js'; +import File from '../util/file.js'; +import Definitions from '../MetadataTypeDefinitions.js'; +import cache from '../util/cache.js'; +import pLimit from 'p-limit'; +import Retriever from '../Retriever.js'; /** - * @typedef {Object} AutomationActivity - * @property {string} name name (not key) of activity - * @property {string} [objectTypeId] Id of assoicated activity type; see this.definition.activityTypeMapping - * @property {string} [activityObjectId] Object Id of assoicated metadata item - * @property {number} displayOrder order within step; starts with 1 or higher number - * @property {string} r__type see this.definition.activityTypeMapping - * - * @typedef {Object} AutomationStep - * @property {string} name description - * @property {string} [annotation] equals AutomationStep.name - * @property {number} step step iterator - * @property {number} [stepNumber] step iterator, automatically set during deployment - * @property {AutomationActivity[]} activities - - * - * @typedef {Object} AutomationSchedule REST format - * @property {number} typeId ? - * @property {string} startDate example: '2021-05-07T09:00:00' - * @property {string} endDate example: '2021-05-07T09:00:00' - * @property {string} icalRecur example: 'FREQ=DAILY;UNTIL=20790606T160000;INTERVAL=1' - * @property {string} timezoneName example: 'W. Europe Standard Time'; see this.definition.timeZoneMapping - * @property {number} [timezoneId] see this.definition.timeZoneMapping - * - * @typedef {Object} AutomationScheduleSoap SOAP format - * @property {Object} Recurrence - - * @property {Object} Recurrence.$ {'xsi:type': keyStem + 'lyRecurrence'} - * @property {'ByYear'} [Recurrence.YearlyRecurrencePatternType] * currently not supported by tool * - * @property {'ByMonth'} [Recurrence.MonthlyRecurrencePatternType] * currently not supported by tool * - * @property {'ByWeek'} [Recurrence.WeeklyRecurrencePatternType] * currently not supported by tool * - * @property {'ByDay'} [Recurrence.DailyRecurrencePatternType] - - * @property {'Interval'} [Recurrence.MinutelyRecurrencePatternType] - - * @property {'Interval'} [Recurrence.HourlyRecurrencePatternType] - - * @property {number} [Recurrence.YearInterval] 1..n * currently not supported by tool * - * @property {number} [Recurrence.MonthInterval] 1..n * currently not supported by tool * - * @property {number} [Recurrence.WeekInterval] 1..n * currently not supported by tool * - * @property {number} [Recurrence.DayInterval] 1..n - * @property {number} [Recurrence.HourInterval] 1..n - * @property {number} [Recurrence.MinuteInterval] 1..n - * @property {number} _interval internal variable for CLI output only - * @property {Object} TimeZone - - * @property {number} TimeZone.ID AutomationSchedule.timezoneId - * @property {string} _timezoneString internal variable for CLI output only - * @property {string} StartDateTime AutomationSchedule.startDate - * @property {string} EndDateTime AutomationSchedule.endDate - * @property {string} _StartDateTime AutomationSchedule.startDate; internal variable for CLI output only - * @property {'EndOn'|'EndAfter'} RecurrenceRangeType set to 'EndOn' if AutomationSchedule.icalRecur contains 'UNTIL'; otherwise to 'EndAfter' - * @property {number} Occurrences only exists if RecurrenceRangeType=='EndAfter' - * - * @typedef {Object} AutomationItem - * @property {string} [id] Object Id - * @property {string} key key - * @property {string} name name - * @property {string} description - - * @property {'scheduled'|'triggered'} type Starting Source = Schedule / File Drop - * @property {'Scheduled'|'Running'} status - - * @property {AutomationSchedule} [schedule] only existing if type=scheduled - * @property {Object} [fileTrigger] only existing if type=triggered - * @property {string} fileTrigger.fileNamingPattern - - * @property {string} fileTrigger.fileNamePatternTypeId - - * @property {string} fileTrigger.folderLocationText - - * @property {string} fileTrigger.queueFiles - - * @property {Object} [startSource] - - * @property {AutomationSchedule} [startSource.schedule] rewritten to AutomationItem.schedule - * @property {Object} [startSource.fileDrop] rewritten to AutomationItem.fileTrigger - * @property {string} startSource.fileDrop.fileNamingPattern - - * @property {string} startSource.fileDrop.fileNamePatternTypeId - - * @property {string} startSource.fileDrop.folderLocation - - * @property {string} startSource.fileDrop.queueFiles - - * @property {number} startSource.typeId - - * @property {AutomationStep[]} steps - - * @property {string} r__folder_Path folder path - * @property {string} [categoryId] holds folder ID, replaced with r__folder_Path during retrieve - * - * @typedef {Object.<string, AutomationItem>} AutomationMap + * @typedef {import('../../types/mcdev.d.js').BuObject} BuObject + * @typedef {import('../../types/mcdev.d.js').CodeExtract} CodeExtract + * @typedef {import('../../types/mcdev.d.js').CodeExtractItem} CodeExtractItem + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItem} MetadataTypeItem + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItemDiff} MetadataTypeItemDiff + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItemObj} MetadataTypeItemObj + * @typedef {import('../../types/mcdev.d.js').MetadataTypeMap} MetadataTypeMap + * @typedef {import('../../types/mcdev.d.js').MetadataTypeMapObj} MetadataTypeMapObj + * @typedef {import('../../types/mcdev.d.js').SDKError} SDKError + * @typedef {import('../../types/mcdev.d.js').SoapRequestParams} SoapRequestParams + * @typedef {import('../../types/mcdev.d.js').TemplateMap} TemplateMap + * @typedef {import('../../types/mcdev.d.js').TypeKeyCombo} TypeKeyCombo + */ + +/** + * @typedef {import('../../types/mcdev.d.js').AutomationItem} AutomationItem + * @typedef {import('../../types/mcdev.d.js').AutomationItemObj} AutomationItemObj + * @typedef {import('../../types/mcdev.d.js').AutomationMap} AutomationMap + * @typedef {import('../../types/mcdev.d.js').AutomationMapObj} AutomationMapObj + * @typedef {import('../../types/mcdev.d.js').AutomationSchedule} AutomationSchedule + * @typedef {import('../../types/mcdev.d.js').AutomationScheduleSoap} AutomationScheduleSoap */ /** * Automation MetadataType + * * @augments MetadataType */ class Automation extends MetadataType { + static notificationUpdates = {}; + static createdKeyMap; + static _skipNotificationRetrieve = false; + /** @type {AutomationMap} */ + static _cachedMetadataMap; + /** * Retrieves Metadata of Automation - * @param {string} retrieveDir Directory where retrieved metadata directory will be saved - * @returns {Promise<{metadata:AutomationMap,type:string}>} Promise of metadata + * + * @param {string} [retrieveDir] Directory where retrieved metadata directory will be saved + * @param {void | string[]} [_] unused parameter + * @param {void | string[]} [__] unused parameter + * @param {string} [key] customer key of single item to retrieve + * @returns {Promise.<AutomationMapObj>} Promise of metadata */ - static async retrieve(retrieveDir) { - const results = await new Promise((resolve, reject) => { - this.client.SoapClient.retrieve('Program', ['ObjectID'], (ex, response) => - ex ? reject(ex) : resolve(response.body.Results) + static async retrieve(retrieveDir, _, __, key) { + let metadataMap; + if (key && this._cachedMetadataMap?.[key]) { + metadataMap = { [key]: this._cachedMetadataMap[key] }; + delete this._cachedMetadataMap; + } else if (!key && this._cachedMetadataMap) { + metadataMap = this._cachedMetadataMap; + delete this._cachedMetadataMap; + } else { + /** @type {SoapRequestParams} */ + let requestParams = null; + const objectIds = []; + if (key?.startsWith('id:')) { + objectIds.push(key.slice(3)); + } else if (key) { + requestParams = { + filter: { + leftOperand: 'CustomerKey', + operator: 'equals', + rightOperand: key, + }, + }; + } + const results = await this.client.soap.retrieveBulk( + 'Program', + ['ObjectID'], + requestParams ); - }); - const details = ( - await Promise.all( - results.map((a) => - this.client.RestClient.get({ - uri: '/automation/v1/automations/' + a.ObjectID, - }) - ) + if (results?.Results?.length) { + objectIds.push(...results.Results.map((item) => item.ObjectID)); + } + + // the API seems to handle 50 concurrent requests nicely + const response = objectIds.length + ? await this.retrieveRESTcollection( + objectIds.map((objectID) => ({ + id: objectID, + uri: '/automation/v1/automations/' + objectID, + })), + 10, + !key + ) + : null; + metadataMap = response?.metadata || {}; + } + + if (!this._skipNotificationRetrieve && Object.keys(metadataMap).length) { + // attach notification and wait timezone information to each automation that has any + await this.#getAutomationLegacyREST(metadataMap); + } + + // * retrieveDir can be empty when we use it in the context of postDeployTasks + if (retrieveDir) { + this.retrieveDir = retrieveDir; + const savedMetadataMap = await this.saveResults(metadataMap, retrieveDir, null, null); + Util.logger.info( + `Downloaded: ${this.definition.type} (${Object.keys(savedMetadataMap).length})` + + Util.getKeysString(key) + ); + if (Object.keys(savedMetadataMap).length) { + await this.runDocumentOnRetrieve(key, savedMetadataMap); + } else if (key) { + this.postDeleteTasks(key); + } + } + return { metadata: metadataMap, type: this.definition.type }; + } + + /** + * helper for {@link this.retrieveRESTcollection} + * + * @param {SDKError} ex exception + * @param {string} key id or key of item + * @param {string} url url to call for retry + * @returns {Promise.<any>} can return retry-result + */ + static async handleRESTErrors(ex, key, url) { + try { + if (ex.message == 'socket hang up' || ex.code == 'ERR_BAD_RESPONSE') { + // one more retry; it's a rare case but retrying again should solve the issue gracefully + Util.logger.info( + ` - Connection problem (Code: ${ex.code}). Retrying once + ${ + ex.endpoint + ? Util.getGrayMsg( + ' - ' + ex.endpoint.split('rest.marketingcloudapis.com')[1] + ) + : '' + }` + ); + Util.logger.errorStack(ex); + return await this.client.rest.get(url); + } + } catch { + // no extra action needed, handled below + } + // if we do get here, we should log the error and continue instead of failing to download all automations + Util.logger.error(` ☇ skipping ${this.definition.type} ${key}: ${ex.message} ${ex.code}`); + return null; + } + + /** + * helper for {@link Automation.retrieve} to get Automation Notifications + * + * @param {MetadataTypeMap} metadataMap keyField => metadata map + * @param {boolean} [skipNotification] skip notification retrieval + * @returns {Promise.<object>} Promise of automation legacy api response + */ + static async #getAutomationLegacyREST(metadataMap, skipNotification = false) { + Util.logger.info(Util.getGrayMsg(` Retrieving additional automation details...`)); + + // get list of keys that we retrieved so far + const foundKeys = Object.keys(metadataMap); + + // get encodedAutomationID to retrieve notification information + const iteratorBackup = this.definition.bodyIteratorField; + this.definition.bodyIteratorField = 'entry'; + const automationLegacyMapObj = await super.retrieveREST( + undefined, + `/legacy/v1/beta/bulk/automations/automation/definition/` + ); + this.definition.bodyIteratorField = iteratorBackup; + // notification + const notificationLegacyMap = Object.keys(automationLegacyMapObj.metadata) + .filter((key) => foundKeys.includes(key)) + // ! using the `id` field to retrieve notifications does not work. instead one needs to use the URL in the `notifications` field + .map((key) => ({ + id: automationLegacyMapObj.metadata[key].id, + key, + })); + // created / modified / paused / wait activities + const extendedDetailsLegacyMap = Object.keys(automationLegacyMapObj.metadata) + .filter((key) => foundKeys.includes(key)) + .map((key) => ({ + id: automationLegacyMapObj.metadata[key].id, + key, + })); + + const rateLimit = pLimit(5); + + // get wait activities for automations using it + await Promise.all( + extendedDetailsLegacyMap.map((automationLegacy) => + // notifications + rateLimit(async () => { + // this is a file so extended is at another endpoint + try { + /** @type {AutomationItem} */ + const item = metadataMap[automationLegacy.key]; + item.legacyId = automationLegacy.id; + + const extended = await this.client.rest.get( + `/legacy/v1/beta/bulk/automations/automation/definition/` + + automationLegacy.id + ); + // set those for {@link schedule} + item.type ||= extended.automationType; + item.status ||= extended.status; + + // created + item.createdName = extended.createdBy?.name; + item.createdDate = extended.createdDate; + + // last modified + item.modifiedName = extended.lastSavedBy?.name; + item.modifiedDate = extended.lastSaveDate; + + // last paused + item.pausedName = extended.lastPausedBy?.name; + item.pausedDate = extended.lastPausedDate; + + // schedule id for activating the schedule + if (extended?.scheduleObject?.id && item.schedule) { + // save schedule id in cached metadata for retrieval during scheduling + item.schedule.id = extended.scheduleObject.id; + item.schedule.description = extended.scheduleObject.description; + item.schedule.icalRecur ||= extended.scheduleObject.iCalRecur; + item.schedule.startDate ||= extended.scheduleObject.startDate; + item.schedule.timezoneName ||= extended.scheduleObject.timeZone; + } + + // add timezone to wait activities + if (Array.isArray(extended?.processes)) { + for (const step of extended.processes) { + // steps + if (!Array.isArray(step?.workers)) { + continue; + } + for (const activity of step.workers) { + // activties + if ( + activity.objectTypeId === 467 && + activity.serializedObject + ) { + // wait activities + const waitObj = JSON.parse(activity.serializedObject); + if (waitObj.timeZone) { + // add timezone to the wait activity + item.steps[step.sequence].activities[ + activity.sequence + ].timeZone = waitObj.timeZone; + } + // * wait activities are not supported in the new API + } + } + } + } + } catch (ex) { + Util.logger.debug( + ` ☇ issue retrieving extended details for automation ${automationLegacy.key}: ${ex.message} ${ex.code}` + ); + } + }) ) - ).map((b) => b.body); - const parsed = this.parseResponseBody({ items: details }); + ); - const savedMetadata = await this.saveResults(parsed, retrieveDir, null, null); + if (skipNotification) { + return; + } + // get notifications for each automation + let found = 0; + let skipped = 0; + const notificationPromiseMap = await Promise.all( + notificationLegacyMap.map((automationLegacy) => + // notifications + rateLimit(async () => { + // this is a file so extended is at another endpoint + try { + const notificationsResult = await this.client.rest.get( + '/legacy/v1/beta/automations/notifications/' + automationLegacy.id + ); + if (Array.isArray(notificationsResult?.workers)) { + metadataMap[automationLegacy.key].notifications = + notificationsResult.workers.map((n) => ({ + email: n.definition.split(',').map((item) => item.trim()), + message: n.body, + type: n.notificationType, + })); + found++; + } else { + if ( + !notificationsResult || + typeof notificationsResult !== 'object' || + Object.keys(notificationsResult).length !== 1 || + !notificationsResult?.programId + ) { + throw new TypeError(JSON.stringify(notificationsResult)); + } + // * if there are no automation notifications, the API returns a single object with the programId + } + } catch (ex) { + Util.logger.debug( + ` ☇ issue retrieving Notifications for automation ${automationLegacy.key}: ${ex.message} ${ex.code}` + ); + skipped++; + } + }) + ) + ); Util.logger.info( - `Downloaded: ${this.definition.type} (${Object.keys(savedMetadata).length})` + Util.getGrayMsg(` Notifications found for ${found} automation${found === 1 ? '' : 's'}`) + ); + Util.logger.debug( + `Notifications not found for ${skipped} automation${skipped === 1 ? '' : 's'}` ); - return { metadata: savedMetadata, type: this.definition.type }; + return notificationPromiseMap; } + /** * Retrieves Metadata of Automation - * @returns {Promise<{metadata:AutomationMap,type:string}>} Promise of metadata + * + * @returns {Promise.<AutomationMapObj>} Promise of metadata */ static async retrieveChangelog() { - const results = await new Promise((resolve, reject) => { - this.client.SoapClient.retrieve( - 'Program', - ['ObjectID'], - - (ex, response) => (ex ? reject(ex) : resolve(response.body.Results)) - ); - }); + const results = await this.client.soap.retrieveBulk('Program', ['ObjectID']); const details = []; - ( - await Promise.all( - results.map(async (a) => { - const options = { - filter: { - leftOperand: 'ProgramID', - operator: 'equals', - rightOperand: a.ObjectID, - }, - }; - - return new Promise((resolve, reject) => { - this.client.SoapClient.retrieve( - 'Automation', - [ - 'ProgramID', - 'Name', - 'CustomerKey', - 'LastSaveDate', - 'LastSavedBy', - 'CreatedBy', - 'CreatedDate', - ], - options, - (ex, response) => (ex ? reject(ex) : resolve(response.body.Results)) - ); - }); - }) - ) - ).forEach((item) => { - details.push(...item); - }); + for (const item of results.Results + ? await Promise.all( + results.Results.map((a) => + this.client.soap.retrieveBulk( + 'Automation', + [ + 'ProgramID', + 'Name', + 'CustomerKey', + 'CategoryID', + 'LastSaveDate', + 'LastSavedBy', + 'CreatedBy', + 'CreatedDate', + ], + { + filter: { + leftOperand: 'ProgramID', + operator: 'equals', + rightOperand: a.ObjectID, + }, + } + ) + ) + ) + : []) { + details.push(...item.Results); + } details.map((item) => { item.key = item.CustomerKey; }); @@ -171,86 +368,100 @@ class Automation extends MetadataType { /** * Retrieves automation metadata for caching - * @returns {Promise<{metadata:AutomationMap,type:string}>} Promise of metadata + * + * @returns {Promise.<AutomationMapObj>} Promise of metadata */ static async retrieveForCache() { - const results = await new Promise((resolve) => { - this.client.SoapClient.retrieve( - 'Program', - ['ObjectID', 'CustomerKey', 'Name'], - (error, response) => { - if (error) { - throw new Error(error); - } else { - resolve(response.body.Results); - } - } - ); - }); + let results = {}; + if (this._cachedMetadataMap) { + results.Results = Object.values(this._cachedMetadataMap); + delete this._cachedMetadataMap; + } else { + // get automations for cache + results = await this.client.soap.retrieveBulk('Program', [ + 'ObjectID', + 'CustomerKey', + 'Name', + ]); + } + /** @type {AutomationMap} */ const resultsConverted = {}; - for (const m of results) { - resultsConverted[m.CustomerKey] = { - id: m.ObjectID, - key: m.CustomerKey, - name: m.Name, - }; + if (Array.isArray(results?.Results)) { + // get encodedAutomationID to retrieve notification information + const keyBackup = this.definition.keyField; + const iteratorBackup = this.definition.bodyIteratorField; + this.definition.keyField = 'key'; + this.definition.bodyIteratorField = 'entry'; + const automationsLegacy = await super.retrieveREST( + undefined, + `/legacy/v1/beta/bulk/automations/automation/definition/` + ); + this.definition.keyField = keyBackup; + this.definition.bodyIteratorField = iteratorBackup; + + // merge encodedAutomationID into results + for (const m of results.Results) { + const key = m.CustomerKey || m.key; + resultsConverted[key] = { + id: m.ObjectID || m.id, + key: key, + name: m.Name || m.name, + programId: automationsLegacy.metadata[key]?.id, + status: automationsLegacy.metadata[key]?.status, + }; + } } return { metadata: resultsConverted, type: this.definition.type }; } /** * Retrieve a specific Automation Definition by Name + * + * @deprecated Use `retrieve` followed by `build` instead. `retrieveAsTemplate` will be removed in a future version. * @param {string} templateDir Directory where retrieved metadata directory will be saved * @param {string} name name of the metadata file - * @param {Util.TemplateMap} templateVariables variables to be replaced in the metadata - * @returns {Promise<{metadata:AutomationMap,type:string}>} Promise of metadata + * @param {TemplateMap} templateVariables variables to be replaced in the metadata + * @returns {Promise.<AutomationItemObj>} Promise of metadata */ static async retrieveAsTemplate(templateDir, name, templateVariables) { - const results = await new Promise((resolve) => { - this.client.SoapClient.retrieve( - 'Program', - ['ObjectID', 'Name'], - { - filter: { - leftOperand: 'Name', - operator: 'equals', - rightOperand: name, - }, - }, - (error, response) => { - if (error) { - throw new Error(error); - } else { - resolve(response.body.Results); - } - } - ); + Util.logDeprecated('retrieveAsTemplate', `'retrieve' followed by 'build'`); + const results = await this.client.soap.retrieve('Program', ['ObjectID', 'Name'], { + filter: { + leftOperand: 'Name', + operator: 'equals', + rightOperand: name, + }, }); - if (results && results[0]) { + if (Array.isArray(results?.Results)) { // eq-operator returns a similar, not exact match and hence might return more than 1 entry - const [metadata] = results.filter((item) => item.Name === name); + const metadata = results.Results.find((item) => item.Name === name); if (!metadata) { Util.logger.error(`${this.definition.type} '${name}' not found on server.`); return; } - const details = ( - await this.client.RestClient.get({ - uri: '/automation/v1/automations/' + metadata.ObjectID, - }) - ).body; + let details = await this.client.rest.get( + '/automation/v1/automations/' + metadata.ObjectID + ); + const metadataMap = this.parseResponseBody({ items: [details] }); + if (Object.keys(metadataMap).length) { + // attach notification and wait timezone information to each automation that has any + await this.#getAutomationLegacyREST(metadataMap); + details = Object.values(metadataMap)[0]; + } + let val = null; let originalKey; // if parsing fails, we should just save what we get try { - const parsedDetails = this.parseMetadata(details); + const parsedDetails = this.postRetrieveTasks(details); originalKey = parsedDetails[this.definition.keyField]; if (parsedDetails !== null) { val = JSON.parse( Util.replaceByObject(JSON.stringify(parsedDetails), templateVariables) ); } - } catch (ex) { - val = JSON.parse(JSON.stringify(details)); + } catch { + val = structuredClone(details); } if (val === null) { throw new Error( @@ -259,14 +470,12 @@ class Automation extends MetadataType { } // remove all fields not listed in Definition for templating this.keepTemplateFields(val); - File.writeJSONToFile( + await File.writeJSONToFile( [templateDir, this.definition.type].join('/'), originalKey + '.' + this.definition.type + '-meta', val ); - Util.logger.info( - `Automation.retrieveAsTemplate:: Written Metadata to filesystem (${name})` - ); + Util.logger.info(`- templated ${this.definition.type}: ${name}`); return { metadata: val, type: this.definition.type }; } else if (results) { Util.logger.error(`${this.definition.type} '${name}' not found on server.`); @@ -276,39 +485,439 @@ class Automation extends MetadataType { throw new Error(JSON.stringify(results)); } } + + /** + * helper for {@link Automation.postRetrieveTasks} and {@link Automation.execute} + * + * @param {AutomationItem} metadata a single automation + * @returns {boolean} true if the automation schedule is valid + */ + static #isValidSchedule(metadata) { + if (metadata.type === 'scheduled' && metadata.schedule?.startDate) { + try { + if (this.definition.timeZoneMapping[metadata.schedule.timezoneName]) { + // if we found the id in our list, remove the redundant data + delete metadata.schedule.timezoneId; + } + } catch { + Util.logger.debug( + `- Schedule name '${metadata.schedule.timezoneName}' not found in definition.timeZoneMapping` + ); + } + return true; + } else { + return false; + } + } + /** * manages post retrieve steps + * * @param {AutomationItem} metadata a single automation - * @param {string} [_] unused - * @param {Boolean} [isTemplating] signals that we are retrieving templates - * @returns {AutomationItem} metadata + * @returns {AutomationItem | void} parsed item */ - static postRetrieveTasks(metadata, _, isTemplating) { - // if retrieving template, replace the name with customer key if that wasn't already the case - if (isTemplating) { - const warningMsg = null; - this.overrideKeyWithName(metadata, warningMsg); + static postRetrieveTasks(metadata) { + // folder + this.setFolderPath(metadata); + // automations are often skipped due to lack of support. + if (metadata.type == 'automationtriggered' && metadata.automationTrigger) { + const automationTrigger = metadata.automationTrigger; + if (automationTrigger.fileTransferLocationId) { + try { + automationTrigger.r__fileLocation_name = cache.searchForField( + 'fileLocation', + automationTrigger.fileTransferLocationId, + 'id', + 'name' + ); + delete automationTrigger.fileTransferLocationId; + } catch (ex) { + Util.logger.warn(` - automation ${metadata.key}: ${ex.message}`); + } + } + if (automationTrigger.fileNamePatternType) { + try { + automationTrigger.fileNamePatternType = Util.inverseGet( + this.definition.fileNameOperatorMapping, + automationTrigger.fileNamePatternType + ); + } catch { + Util.logger.warn( + ` - Unknown File naming Pattern '${automationTrigger.fileNamePatternType}' in Automation '${metadata.name}'` + ); + } + } + } + try { + if (metadata.type === 'scheduled' && metadata.schedule?.startDate) { + // Starting Source == 'Schedule' + + if (!this.#isValidSchedule(metadata)) { + return; + } + // type 'Running' is temporary status only, overwrite with Scheduled for storage. + if (metadata.type === 'scheduled' && metadata.status === 'Running') { + metadata.status = 'Scheduled'; + } + } else if (metadata.type === 'triggered' && metadata.fileTrigger) { + // Starting Source == 'File Drop' + // Do nothing for now + } + if (metadata.steps) { + let i = 0; + + for (const step of metadata.steps) { + i++; + + const stepNumber = step.stepNumber || step.step || i; + delete step.stepNumber; + delete step.step; + + for (const activity of step.activities) { + try { + // get metadata type of activity + activity.r__type = Util.inverseGet( + this.definition.activityTypeMapping, + activity.objectTypeId + ); + delete activity.objectTypeId; + } catch { + Util.logger.warn( + ` - Unknown activity type '${activity.objectTypeId}'` + + ` in step ${stepNumber}.${activity.displayOrder}` + + ` of Automation '${metadata.name}'` + ); + continue; + } + + // if no activityObjectId then either serialized activity + // (config in Automation ) or unconfigured so no further action to be taken + if ( + activity.activityObjectId === '00000000-0000-0000-0000-000000000000' || + activity.activityObjectId == null + ) { + Util.logger.debug( + ` - skipping ${ + metadata[this.definition.keyField] + } activity ${stepNumber}.${ + activity.displayOrder + } due to missing activityObjectId: ${JSON.stringify(activity)}` + ); + // empty if block + continue; + } else if (this.definition.customDeployTypes.includes(activity.r__type)) { + if (activity.r__type === 'wait') { + // convert 12 to 24 hrs system + let waitTime24; + const [waitDuration, waitUnit] = activity.name.split(' '); + if (waitUnit === 'AM' || waitUnit === 'PM') { + waitTime24 = waitDuration; + if (waitUnit === 'PM') { + waitTime24 = + (Number(waitTime24.split(':')[0]) + 12).toString() + + ':00'; + } + activity.name = waitTime24; + } + } + continue; + } else if (!this.definition.dependencies.includes(activity.r__type)) { + Util.logger.debug( + ` - skipping ${ + metadata[this.definition.keyField] + } activity ${stepNumber}.${ + activity.displayOrder + } because the type ${ + activity.r__type + } is not set up as a dependency for ${this.definition.type}` + ); + continue; + } + // / if managed by cache we can update references to support deployment + if ( + Definitions[activity.r__type]?.['idField'] && + cache.getCache()[activity.r__type] + ) { + try { + activity.r__key = cache.searchForField( + activity.r__type, + activity.activityObjectId, + Definitions[activity.r__type].idField, + Definitions[activity.r__type].keyField + ); + delete activity.name; + } catch (ex) { + // getFromCache throws error where the dependent metadata is not found + Util.logger.warn( + ` - Missing ${activity.r__type} activity '${activity.name}'` + + ` in step ${stepNumber}.${activity.displayOrder}` + + ` of Automation '${metadata.name}' (${ex.message})` + ); + } + } else { + Util.logger.warn( + ` - Missing ${activity.r__type} activity '${activity.name}'` + + ` in step ${stepNumber}.${activity.displayOrder}` + + ` of Automation '${metadata.name}' (Not Found in Cache)` + ); + } + } + // In some cases the displayOrder and array order are not equal which leads to a different order every time we retrieve & deployed the automation. To prevent that, we sort the activities by displayOrder on retrieve + step.activities.sort((a, b) => a.displayOrder - b.displayOrder); + } + } + return structuredClone(metadata); + } catch (ex) { + Util.logger.warn( + ` - ${this.definition.typeName} '${metadata[this.definition.nameField]}': ${ + ex.message + }` + ); + return null; } - return this.parseMetadata(metadata); } + /** + * a function to active the schedule of an automation + * + * @param {string[]} keyArr customerkey of the metadata + * @returns {Promise.<string[]>} Returns list of keys that were executed + */ + static async schedule(keyArr) { + return this.#schedulePause('schedule', keyArr); + } + /** + * a function to pause the schedule of an automation + * + * @param {string[]} keyArr customerkey of the metadata + * @returns {Promise.<string[]>} Returns list of keys that were executed + */ + static async pause(keyArr) { + return this.#schedulePause('pause', keyArr); + } + /** + * a function to active the schedule of an automation + * + * @param {'schedule'|'pause'} mode what to do + * @param {string[]} keyArr customerkey of the metadata + * @returns {Promise.<string[]>} Returns list of keys that were executed + */ + static async #schedulePause(mode, keyArr) { + const metadataMap = {}; + for (const key of keyArr) { + metadataMap[key] = { key, schedule: {} }; + } + await this.#getAutomationLegacyREST(metadataMap, true); + for (const key of keyArr) { + const item = metadataMap[key]; + if (!item.type) { + Util.logger.error( + ` ☇ skipping ${Util.getTypeKeyName(this.definition, item)}: automation not found.` + ); + delete metadataMap[key]; + } else if (item.type !== 'scheduled') { + Util.logger.error( + ` ☇ skipping ${Util.getTypeKeyName(this.definition, item)}: cannot ${mode} an automation of type '${item.type}'.` + ); + delete metadataMap[key]; + } + } + if (!Object.keys(metadataMap).length) { + Util.logger.error(`No ${this.definition.type} to ` + mode); + return []; + } + Util.logger.info(`${mode === 'schedule' ? 'Activating' : 'Pausing'} automations`); + const promiseResults = []; + for (const key of Object.keys(metadataMap)) { + /** @type {AutomationItem} */ + const item = metadataMap[key]; + if (item.status === (mode === 'schedule' ? 'Scheduled' : 'PausedSchedule')) { + // schedule + Util.logger.info( + ` ☇ skipping ${Util.getTypeKeyName(this.definition, item)}: already ${mode === 'schedule' ? 'activated' : 'paused'}.` + ); + continue; + } + if (mode === 'schedule') { + try { + this._checkSchedule(item.schedule, true); + } catch (ex) { + Util.logger.error( + ` ☇ skipping ${this.definition.type} ${key} (${item.schedule.description}): ${ex.message}` + ); + continue; + } + } + // schedule + promiseResults.push( + this.#schedulePauseItem( + mode, + key, + item.legacyId, + item.schedule.id, + item.schedule.description + ) + ); + } + const results = await Promise.all(promiseResults); + const updatedKeyArr = results + .filter(Boolean) + .filter((r) => r.response?.id) + .map((r) => r.key); + Util.logger.info( + `${mode === 'schedule' ? 'Activated' : 'Paused'} ${updatedKeyArr.length} of ${keyArr.length} items` + ); + + if (updatedKeyArr.length) { + Util.logger.info( + Util.getGrayMsg( + `Caching ${this.definition.type} post-${mode === 'schedule' ? 'activation' : 'pausing'} to update local files.` + ) + ); + // re-retrieve the items that were activated / paused + const retriever = new Retriever(this.properties, this.buObject); + try { + await retriever.retrieve([this.definition.type], updatedKeyArr); + } catch (ex) { + Util.logger.warn( + `Could not re-retrieve ${mode === 'schedule' ? 'activated' : 'paused'} ${this.definition.type}s: ${ex.message}` + ); + } + } + + return updatedKeyArr; + } + + /** + * helper for {@link Automation.schedule} + * + * @param {'schedule'|'pause'} mode what to do + * @param {string} key automation key + * @param {string} automationLegacyId automation id + * @param {string} [scheduleLegacyId] schedule id + * @param {string} [description] schedule description + * @returns {Promise.<{key:string, response:object}>} metadata key and API response + */ + static async #schedulePauseItem(mode, key, automationLegacyId, scheduleLegacyId, description) { + if (!scheduleLegacyId) { + const extended = await this.client.rest.get( + `/legacy/v1/beta/bulk/automations/automation/definition/` + automationLegacyId + ); + /** @type {AutomationSchedule} */ + const scheduleObjectLegacy = extended.scheduleObject; + if (scheduleObjectLegacy?.id) { + scheduleLegacyId = scheduleObjectLegacy.id; + if (mode === 'schedule') { + // convert legacy API schedule to new schedule + /** @type {AutomationSchedule} */ + const scheduleObject = { + id: scheduleObjectLegacy.id, + typeId: null, + endDate: null, + startDate: scheduleObjectLegacy.startDate, + timezoneName: scheduleObjectLegacy.timeZone, + icalRecur: scheduleObjectLegacy.iCalRecur, + }; + try { + this._checkSchedule(scheduleObject); + } catch (ex) { + Util.logger.error( + ` ☇ skipping ${this.definition.type} ${key}: ${ex.message}` + ); + return null; + } + } + description = scheduleObjectLegacy.description; + } else { + Util.logger.error( + ` ☇ skipping ${this.definition.type} ${key}: no valid schedule settings found.` + ); + return null; + } + } + let response; + try { + response = await this.client.rest.post( + '/legacy/v1/beta/bulk/automations/automation/definition/?action=' + + (mode === 'schedule' ? 'schedule' : 'pauseSchedule'), + { + id: automationLegacyId, + scheduleObject: { + id: scheduleLegacyId, + }, + } + ); + if (response?.id === automationLegacyId) { + const item = { [this.definition.keyField]: key }; + Util.logger.info( + ` - ${mode === 'schedule' ? '✅ activated' : '🛑 paused'} scheduled ${Util.getTypeKeyName(this.definition, item)}${mode === 'schedule' ? ' (' + description + ')' : ''}` + ); + } + } catch (ex) { + Util.logger.error( + ` ☇ error ${mode === 'schedule' ? 'activating' : 'pausing'} ${this.definition.type} ${key} (${description}): ${ex.message}` + ); + } + + return { key, response }; + } /** - * Deploys automation - the saved file is the original one due to large differences required for deployment - * @param {AutomationMap} metadata metadata mapped by their keyField - * @param {string} targetBU name/shorthand of target businessUnit for mapping - * @param {string} retrieveDir directory where metadata after deploy should be saved - * @returns {Promise<AutomationMap>} Promise + * a function to start query execution via API + * + * @param {string[]} keyArr customerkey of the metadata + * @returns {Promise.<string[]>} Returns list of keys that were executed */ - static async deploy(metadata, targetBU, retrieveDir) { - const orignalMetadata = JSON.parse(JSON.stringify(metadata)); - const upsertResults = await this.upsert(metadata, targetBU); - await this.postDeployTasks(upsertResults, orignalMetadata); - await this.saveResults(upsertResults, retrieveDir, null); - return upsertResults; + static async execute(keyArr) { + /** @type {AutomationMap} */ + const metadataMap = {}; + for (const key of keyArr) { + // runOnce + const objectId = await this.#getObjectIdForSingleRetrieve(key); + /** @type {AutomationItem} */ + metadataMap[key] = { key, id: objectId }; + } + if (!Object.keys(metadataMap).length) { + Util.logger.error(`No ${this.definition.type} to execute`); + return; + } + Util.logger.info( + `Starting automations to run once (use --schedule or --execute=schedule to schedule instead): ${Object.keys(metadataMap).length}` + ); + const promiseResults = []; + for (const key of Object.keys(metadataMap)) { + // schedule + runOnce + promiseResults.push(super.executeSOAP(metadataMap[key])); + } + const results = await Promise.all(promiseResults); + const executedKeyArr = results + .filter(Boolean) + .filter((r) => r.response.OverallStatus === 'OK') + .map((r) => r.key); + Util.logger.info(`Executed ${executedKeyArr.length} of ${keyArr.length} items`); + return executedKeyArr; + } + + /** + * Standardizes a check for multiple messages but adds query specific filters to error texts + * + * @param {object} ex response payload from REST API + * @returns {string[]} formatted Error Message + */ + static getErrorsREST(ex) { + const errors = super.getErrorsREST(ex); + if (errors?.length > 0) { + return errors.map((msg) => + msg + .split('403 Forbidden') + .join('403 Forbidden: Please check if the automation is currently running.') + ); + } + return errors; } /** * Creates a single automation + * * @param {AutomationItem} metadata single metadata entry * @returns {Promise} Promise */ @@ -319,76 +928,110 @@ class Automation extends MetadataType { /** * Updates a single automation + * * @param {AutomationItem} metadata single metadata entry * @param {AutomationItem} metadataBefore metadata mapped by their keyField * @returns {Promise} Promise */ static update(metadata, metadataBefore) { - metadata.id = metadataBefore.id; + if (metadataBefore.status === 'Running') { + Util.logger.error( + ` ☇ error updating ${this.definition.type} ${ + metadata[this.definition.keyField] || metadata[this.definition.nameField] + } / ${ + metadata[this.definition.nameField] + }: You cannot update an automation that's currently running. Please wait a bit and retry.` + ); + return null; + } const uri = '/automation/v1/automations/' + metadata.id; return super.updateREST(metadata, uri); } /** - * Gets executed before deploying metadata + * helper for {@link Automation.preDeployTasks} and {@link Automation.execute} + * * @param {AutomationItem} metadata metadata mapped by their keyField - * @returns {Promise<AutomationItem>} Promise */ - static async preDeployTasks(metadata) { - if (this.validateDeployMetadata(metadata)) { - try { - metadata.categoryId = Util.getFromCache( - this.cache, - 'folder', - metadata.r__folder_Path, - 'Path', - 'ID' - ); - if (metadata.r__folder_Path !== 'my automations') { - Util.logger.warn( - `Automation '${ - metadata[this.definition.nameField] - }' is located in subfolder ${ - metadata.r__folder_Path - }. Please note that creating automation folders is not supported via API and hence you will have to create it manually in the GUI if you choose to deploy this automation.` - ); - } - delete metadata.r__folder_Path; - } catch (ex) { - throw new Error( - `Folder '${metadata.r__folder_Path}' was not found on the server. Please create this manually in the GUI. Automation-folders cannot be deployed automatically.` + static #preDeploySchedule(metadata) { + delete metadata.schedule.rangeTypeId; + delete metadata.schedule.pattern; + delete metadata.schedule.scheduledTime; + delete metadata.schedule.scheduledStatus; + if (this.definition.timeZoneMapping[metadata.schedule.timezoneName]) { + metadata.schedule.timezoneId = + this.definition.timeZoneMapping[metadata.schedule.timezoneName]; + } else { + Util.logger.error( + `Could not find timezone ${metadata.schedule.timezoneName} in definition.timeZoneMapping` + ); + } + + // the upsert API needs this to be named scheduleTypeId; the retrieve API returns it as typeId + metadata.schedule.scheduleTypeId = metadata.schedule.typeId; + delete metadata.schedule.typeId; + + // prep startSource + metadata.startSource = { schedule: metadata.schedule, typeId: 1 }; + } + + /** + * Gets executed before deploying metadata + * + * @param {AutomationItem} metadata metadata mapped by their keyField + * @returns {Promise.<AutomationItem>} Promise + */ + static async preDeployTasks(metadata) { + if (metadata.notifications) { + this.notificationUpdates[metadata.key] = metadata.notifications; + } else { + const cached = cache.getByKey(this.definition.type, metadata.key); + if (cached?.notifications) { + // if notifications existed but are no longer present in the deployment package, we need to run an empty update call to remove them + this.notificationUpdates[metadata.key] = []; + } + } + if (metadata.type == 'automationtriggered' && metadata.automationTrigger) { + const automationTrigger = metadata.automationTrigger; + + if (automationTrigger.r__fileLocation_name) { + automationTrigger.fileTransferLocationId = cache.searchForField( + 'fileLocation', + automationTrigger.r__fileLocation_name, + 'name', + 'id' ); + delete automationTrigger.r__fileLocation_name; + } + if ( + automationTrigger.fileNamePatternType && + typeof automationTrigger.fileNamePatternType === 'string' + ) { + automationTrigger.fileNamePatternType = + this.definition.fileNameOperatorMapping[automationTrigger.fileNamePatternType]; } - if (metadata.type === 'scheduled' && metadata.schedule && metadata.schedule.startDate) { + } + if (this.validateDeployMetadata(metadata)) { + // folder + this.setFolderId(metadata); + + if (metadata.type === 'scheduled' && metadata?.schedule?.startDate) { // Starting Source == 'Schedule' - delete metadata.schedule.rangeTypeId; - delete metadata.schedule.pattern; - delete metadata.schedule.scheduledTime; - delete metadata.schedule.scheduledStatus; - if (this.definition.timeZoneMapping[metadata.schedule.timezoneName]) { - metadata.schedule.timezoneId = - this.definition.timeZoneMapping[metadata.schedule.timezoneName]; - } else { - Util.logger.error( - `Could not find timezone ${metadata.schedule.timezoneName} in definition.timeZoneMapping` - ); - } - delete metadata.schedule.timezoneName; - // the upsert API needs this to be named scheduleTypeId; the retrieve API returns it as typeId - metadata.schedule.scheduleTypeId = metadata.schedule.typeId; - delete metadata.schedule.typeId; + this.#preDeploySchedule(metadata); + // * run _buildSchedule here but only to check if things look ok - do not use the returned schedule object for deploy + this._checkSchedule(metadata.schedule); - // prep startSource - metadata.startSource = { schedule: metadata.schedule, typeId: 1 }; + delete metadata.schedule.timezoneName; + delete metadata.startSource.schedule.timezoneName; } else if (metadata.type === 'triggered' && metadata.fileTrigger) { // Starting Source == 'File Drop' // prep startSource metadata.startSource = { fileDrop: { - filenamePattern: metadata.fileTrigger.fileNamingPattern, - filenamePatternTypeId: metadata.fileTrigger.fileNamePatternTypeId, + fileNamePattern: metadata.fileTrigger.fileNamingPattern, + fileNamePatternTypeId: metadata.fileTrigger.fileNamePatternTypeId, folderLocation: metadata.fileTrigger.folderLocationText, queueFiles: metadata.fileTrigger.queueFiles, }, @@ -399,315 +1042,322 @@ class Automation extends MetadataType { delete metadata.schedule; delete metadata.type; let i = 0; - for (const step of metadata.steps) { - for (const activity of step.activities) { - if (activity.name && this.definition.dependencies.includes(activity.r__type)) { - // automations can have empty placeholder for activities with only their type defined - activity.activityObjectId = Util.getFromCache( - this.cache, - activity.r__type, - activity.name, - Definitions[activity.r__type].nameField, - Definitions[activity.r__type].idField - ); + if (metadata.steps) { + for (const step of metadata.steps) { + let displayOrder = 0; + for (const activity of step.activities) { + activity.displayOrder = ++displayOrder; + if ( + activity.r__key && + this.definition.dependencies.includes(activity.r__type) + ) { + // automations can have empty placeholder for activities with only their type defined + activity.activityObjectId = cache.searchForField( + activity.r__type, + activity.r__key, + Definitions[activity.r__type].keyField, + Definitions[activity.r__type].idField + ); + activity.name = cache.searchForField( + activity.r__type, + activity.r__key, + Definitions[activity.r__type].keyField, + Definitions[activity.r__type].nameField + ); + } + if (activity.r__type === 'wait') { + const [waitDuration, waitUnit] = activity.name.split(' '); + const waitDurationNumber = Number(waitDuration); + const allowedWaitUnits = [ + 'Minutes', + 'Hours', + 'Days', + 'Weeks', + 'Months', + 'Years', + ]; + if ( + waitDurationNumber && + waitUnit && + allowedWaitUnits.includes(waitUnit) + ) { + // @ts-expect-error - serializedObject is only used to create/update wait activities + activity.serializedObject = JSON.stringify({ + duration: waitDurationNumber, + durationUnits: waitUnit, + }); + } else if (!waitUnit) { + // // convert 24 hrs based time in waitDuration back into 12 hrs based time + // let waitTime12 = waitDuration; + // waitTime12 = + // Number(waitTime12) > 12 + // ? (Number(waitTime12) - 12).toString() + ' AM' + // : waitTime12 + ' PM'; + // @ts-expect-error - serializedObject is only used to create/update wait activities + activity.serializedObject = JSON.stringify({ + specifiedTime: waitDuration, + timeZone: activity.timeZone || 'GMT Standard Time', + }); + } + } + activity.objectTypeId = + this.definition.activityTypeMapping[activity.r__type]; + delete activity.r__key; + delete activity.r__type; } - activity.objectTypeId = this.definition.activityTypeMapping[activity.r__type]; - delete activity.r__type; + step.annotation = step.name; + step.stepNumber = i; + delete step.name; + delete step.step; + i++; } - step.annotation = step.name; - step.stepNumber = i; - delete step.name; - delete step.step; - i++; } + + if (!Util.OPTIONS.matchName) { + // make sure the name is unique + const thisCache = cache.getCache()[this.definition.type]; + const relevantNames = Object.keys(thisCache).map((key) => ({ + type: null, + key: key, + name: thisCache[key][this.definition.nameField], + })); + // if the name is already in the folder for a different key, add a number to the end + metadata[this.definition.nameField] = this.findUniqueName( + metadata[this.definition.keyField], + metadata[this.definition.nameField], + relevantNames + ); + } + return metadata; } else { return null; } } + /** * Validates the automation to be sure it can be deployed. * Whitelisted Activites are deployed but require configuration + * * @param {AutomationItem} metadata single automation record - * @returns {Boolean} result if automation can be deployed based on steps + * @returns {boolean} result if automation can be deployed based on steps */ static validateDeployMetadata(metadata) { let deployable = true; + const errors = []; if (metadata.steps) { + let stepNumber = 0; for (const step of metadata.steps) { + stepNumber++; + let displayOrder = 0; + for (const activity of step.activities) { + displayOrder++; // check if manual deploy required. if so then log warning if (this.definition.manualDeployTypes.includes(activity.r__type)) { Util.logger.warn( - `Automation '${ - metadata.name - }' requires additional manual configuration: '${ - activity.name - }' in step ${step.stepNumber || step.step}.${activity.displayOrder}` + `- ${this.definition.type} '${metadata.name}' requires additional manual configuration: '${activity.r__key || activity.name}' in step ${stepNumber}.${displayOrder}` ); } // cannot deploy because it is not supported - else if (!this.definition.dependencies.includes(activity.r__type)) { - Util.logger.error( - `Automation '${ - metadata.name - }' cannot be deployed as the following activity is not supported: '${ - activity.name - }' in step ${step.stepNumber || step.step}.${activity.displayOrder}` + else if ( + !this.definition.customDeployTypes.includes(activity.r__type) && + !this.definition.dependencies.includes(activity.r__type) + ) { + errors.push( + ` • not supported ${activity.r__type} activity '${activity.r__key || activity.name}' in step ${stepNumber}.${displayOrder}` ); deployable = false; } } } } + if (!deployable) { + Util.logger.error( + ` ☇ skipping ${this.definition.type} ${metadata[this.definition.keyField]} / ${ + metadata[this.definition.nameField] + }:` + ); + for (const error of errors) { + Util.logger.error(error); + } + } return deployable; } + /** + * helper for {@link MetadataType.updateREST} and {@link MetadataType.updateSOAP} that removes old files after the key was changed + * + * @param {MetadataTypeItem} metadataEntry a single metadata Entry + * @returns {Promise.<void>} - + */ + static async _postChangeKeyTasks(metadataEntry) { + super._postChangeKeyTasks(metadataEntry, true); + } + /** * Gets executed after deployment of metadata type - * @param {AutomationMap} metadata metadata mapped by their keyField - * @param {AutomationMap} originalMetadata metadata to be updated (contains additioanl fields) - * @returns {Promise<void>} - + * + * @param {AutomationMap} metadataMap metadata mapped by their keyField + * @returns {Promise.<void>} - */ - static async postDeployTasks(metadata, originalMetadata) { - for (const key in metadata) { - // need to put schedule on here if status is scheduled + static async postDeployTasks(metadataMap) { + for (const key in metadataMap) { + const item = metadataMap[key]; - if (originalMetadata[key] && originalMetadata[key].type === 'scheduled') { - // Starting Source == 'Schedule': Try starting the automation - if (originalMetadata[key].status === 'Scheduled') { - let schedule = null; - try { - schedule = this._buildSchedule(originalMetadata[key].schedule); - } catch (ex) { - Util.logger.error( - `Could not create schedule for automation ${originalMetadata[key].name} to start it: ${ex.message}` - ); - } - if (schedule !== null) { - try { - await Util.retryOnError( - `Retrying ${this.definition.type}`, - async () => { - await new Promise((resolve, reject) => { - this.client.SoapClient.schedule( - 'Automation', - schedule, - { - Interaction: { - ObjectID: metadata[key].id, - }, - }, - 'start', - null, - (error, response) => { - if ( - error || - (response.body.Results && - response.body.Results[0] && - response.body.Results[0].StatusCode && - response.body.Results[0].StatusCode === - 'Error') - ) { - reject( - error || - response.body.Results[0].StatusMessage - ); - } else { - resolve(response.body.Results); - } - } - ); - }); - const intervalString = - (schedule._interval > 1 ? `${schedule._interval} ` : '') + - (schedule.RecurrenceType === 'Daily' - ? 'Day' - : schedule.RecurrenceType.slice(0, -2) + - (schedule._interval > 1 ? 's' : '')); - Util.logger.warn( - `Automation '${ - originalMetadata[key].name - }' deployed Active: runs every ${intervalString} starting ${ - schedule._StartDateTime - .split('T') - .join(' ') - .split('.')[0] - } ${schedule._timezoneString}` - ); - } - ); - } catch (ex) { - Util.logger.error( - `Could not start automation '${originalMetadata[key].name}': ${ex.message}` - ); - } - } - } else { - Util.logger.warn(`Automation '${originalMetadata[key].name}' deployed Paused`); + const oldKey = Util.changedKeysMap?.[this.definition.type]?.[key] || key; + delete Util.changedKeysMap?.[this.definition.type]?.[key]; + + if (!item.type) { + // create response does not return the type attribute + if (item.startSource?.schedule) { + // rewrite upsert reponse into retrieve format + item.schedule = item.startSource.schedule; + delete item.startSource; + } + const scheduleHelper = item.schedule; + + // el.type + item.type = scheduleHelper + ? 'scheduled' + : item.fileTrigger + ? 'triggered' + : undefined; + + // el.schedule.timezoneName + if (item.type === 'scheduled') { + // not existing for triggered automations + scheduleHelper.timezoneName ||= Util.inverseGet( + this.definition.timeZoneMapping, + scheduleHelper.timezoneId + ); } + + // @ts-expect-error - string vs enum + item.status ||= Util.inverseGet(this.definition.statusMapping, item.statusId); + } + // need to put schedule on here if status is scheduled + if (Util.OPTIONS.schedule) { + await Automation.#schedulePauseItem( + 'schedule', + oldKey || key, + metadataMap[key]?.legacyId + ); } - if (metadata[key].startSource) { - metadata[key].schedule = metadata[key].startSource.schedule; - delete metadata[key].startSource; + // need to update notifications separately if there are any + await Automation.#updateNotificationInfoREST(metadataMap, key); + + // rewrite upsert to retrieve fields + if (item.steps) { + for (const step of item.steps) { + step.name = step.annotation; + delete step.annotation; + } } - if (metadata[key].schedule) { - metadata[key].schedule.typeId = metadata[key].schedule.scheduleTypeId; - delete metadata[key].schedule.scheduleTypeId; + } + + if (Util.OPTIONS.execute) { + Util.logger.info(`Executing: ${this.definition.type}`); + await this.execute(Object.keys(metadataMap)); + } + Util.logger.debug( + `Caching all ${this.definition.type} post-deploy to ensure we have all fields` + ); + + // post-deploy re-retrieve + // dont use retrieveForCache here because that is simplified for automations + const typeCache = await this.retrieve(); + // update values in upsertResults with retrieved values before saving to disk + for (const key of Object.keys(metadataMap)) { + if (typeCache.metadata[key]) { + metadataMap[key] = typeCache.metadata[key]; } } } /** - * parses retrieved Metadata before saving - * @param {AutomationItem} metadata a single automation definition - * @returns {Array} Array with one metadata object and one sql string + * helper for {@link Automation.postDeployTasks} + * + * @param {AutomationMap} metadataMap metadata mapped by their keyField + * @param {string} key current customer key + * @returns {Promise.<void>} - */ - static parseMetadata(metadata) { - // automations are often skipped due to lack of support. - try { - metadata.r__folder_Path = Util.getFromCache( - this.cache, - 'folder', - metadata.categoryId, - 'ID', - 'Path' - ); - delete metadata.categoryId; - if (metadata.r__folder_Path !== 'my automations') { - Util.logger.verbose( - `Automation '${metadata[this.definition.nameField]}' is located in subfolder ${ - metadata.r__folder_Path - }. Please note that creating automation folders is not supported via API and hence you will have to create it manually in the GUI if you choose to deploy this automation.` - ); - } - } catch (ex) { - // * don't exit on missing folder for automation - Util.logger.warn( - `${this.definition.typeName} '${metadata[this.definition.nameField]}': ${ - ex.message - }` - ); - } - try { - if (metadata.type === 'scheduled' && metadata.schedule && metadata.schedule.startDate) { - // Starting Source == 'Schedule' - + static async #updateNotificationInfoREST(metadataMap, key) { + if (this.notificationUpdates[key]) { + // create & update automation calls return programId as 'legacyId'; retrieve does not return it + const programId = metadataMap[key]?.legacyId; + if (programId) { + const notificationBody = { + programId, + workers: this.notificationUpdates[key].map((notification) => ({ + programId, + notificationType: notification.type, + definition: Array.isArray(notification.email) + ? notification.email.join(',') + : notification.email, + body: notification.message, + channelType: 'Account', + })), + }; try { - if (this.definition.timeZoneMapping[metadata.schedule.timezoneName]) { - // if we found the id in our list, remove the redundant data - delete metadata.schedule.timezoneId; - } - } catch (ex) { - Util.logger.debug( - `Schedule name '${metadata.schedule.timezoneName}' not found in definition.timeZoneMapping` + const result = await this.client.rest.post( + '/legacy/v1/beta/automations/notifications/' + programId, + notificationBody ); - } - try { - // type 'Running' is temporary status only, overwrite with Scheduled for storage. - if (metadata.type === 'scheduled' && metadata.status === 'Running') { - metadata.status === 'Scheduled'; + if (result) { + // should be empty if all OK + throw new Error(result); } } catch (ex) { - Util.metadataLogger( - 'error', - this.definition.type, - 'parseMetadata', - `${metadata.name} does not have a valid schedule setting. ` + Util.logger.error( + `Error updating notifications for automation '${metadataMap[key].name}': ${ex.message} (${ex.code}))` ); - return null; - } - } else if (metadata.type === 'triggered' && metadata.fileTrigger) { - // Starting Source == 'File Drop' - // Do nothing for now - } - if (metadata.steps) { - for (const step of metadata.steps) { - for (const activity of step.activities) { - try { - // get metadata type of activity - activity.r__type = Util.inverseGet( - this.definition.activityTypeMapping, - activity.objectTypeId - ); - delete activity.objectTypeId; - // if no activityObjectId then either serialized activity - // (config in Automation ) or unconfigured so no further action to be taken - if ( - activity.activityObjectId === - '00000000-0000-0000-0000-000000000000' || - activity.activityObjectId == null || - !this.definition.dependencies.includes(activity.r__type) - ) { - // empty if block - } - // / if managed by cache we can update references to support deployment - else if ( - Definitions[activity.r__type] && - Definitions[activity.r__type]['idField'] && - this.cache[activity.r__type] - ) { - try { - activity.activityObjectId = Util.getFromCache( - this.cache, - activity.r__type, - activity.activityObjectId, - Definitions[activity.r__type].idField, - Definitions[activity.r__type].nameField - ); - } catch (e) { - // getFromCache throws error where the dependent metadata is not found - Util.logger.error( - `Missing ${activity.r__type} activity '${activity.name}'` + - ` in step ${step.stepNumber || step.step}.${ - activity.displayOrder - }` + - ` of Automation '${metadata.name}' (${e.message})` - ); - return null; - } - } else { - Util.logger.error( - `Missing ${activity.r__type} activity '${activity.name}'` + - ` in step ${step.stepNumber || step.step}.${ - activity.displayOrder - }` + - ` of Automation '${metadata.name}' (Not Found in Cache)` - ); - return null; - } - } catch (ex) { - Util.logger.warn( - `Excluding automation '${metadata.name}' from retrieve (ObjectType ${activity.objectTypeId} is unknown)` - ); - return null; - } - } } + Util.logger.info( + Util.getGrayMsg( + ` - updated notifications for automation '${metadataMap[key].name}'` + ) + ); } - return JSON.parse(JSON.stringify(metadata)); + } + } + + /** + * generic script that retrieves the folder path from cache and updates the given metadata with it after retrieve + * + * @param {MetadataTypeItem} metadata a single script activity definition + */ + static setFolderPath(metadata) { + const folderIdField = metadata[this.definition.folderIdField] + ? this.definition.folderIdField + : 'CategoryID'; + try { + metadata.r__folder_Path = cache.searchForField( + 'folder', + metadata[folderIdField], + 'ID', + 'Path' + ); + delete metadata[folderIdField]; } catch (ex) { Util.logger.warn( - `${this.definition.typeName} '${metadata[this.definition.nameField]}': ${ - ex.message - }` + ` - ${this.definition.type} '${metadata[this.definition.nameField]}' (${ + metadata[this.definition.keyField] + }): Could not find folder (${ex.message})` ); - return null; } } /** * Builds a schedule object to be used for scheduling an automation * based on combination of ical string and start/end dates. + * * @param {AutomationSchedule} scheduleObject child of automation metadata used for scheduling - * @returns {AutomationScheduleSoap} Schedulable object for soap API (currently not rest supported) + * @param {boolean} [errorOnNotSchedulable] used if run for schedule command + * @returns {void} throws and error in case of problems */ - static _buildSchedule(scheduleObject) { - /** - * @type {AutomationScheduleSoap} - */ - const schedule = { Recurrence: {}, TimeZone: { IDSpecified: true } }; + static _checkSchedule(scheduleObject, errorOnNotSchedulable = false) { // build recurrence const recurHelper = {}; // ical values are split by ; then have key values split by = @@ -715,103 +1365,45 @@ class Automation extends MetadataType { const a = obj.split('='); recurHelper[a[0]] = a[1]; } - // the ical schedule is all in caps but soap objects require Title Case. - const keyStem = recurHelper.FREQ.charAt(0) + recurHelper.FREQ.slice(1, -2).toLowerCase(); - - const patternType = recurHelper['BYMONTH'] - ? 'ByMonth' - : recurHelper['BYWEEK'] - ? 'ByWeek' - : recurHelper['BYDAY'] - ? 'ByDay' - : 'Interval'; - schedule.Recurrence[keyStem + 'lyRecurrencePatternType'] = patternType; - schedule.Recurrence['$'] = { - 'xsi:type': keyStem + 'lyRecurrence', - }; - schedule.RecurrenceType = keyStem + 'ly'; - if (keyStem === 'Dai') { - schedule.Recurrence['DayInterval'] = recurHelper.INTERVAL; - } else { - schedule.Recurrence[keyStem + 'Interval'] = recurHelper.INTERVAL; + if (recurHelper.INTERVAL) { + recurHelper.INTERVAL = Number.parseInt(recurHelper.INTERVAL); } - schedule._interval = recurHelper.INTERVAL; // for CLI output only - if (!['Minute', 'Hour', 'Dai'].includes(keyStem)) { - // todo: add support for weekly - // todo: add support for monthly - // todo: add support for yearly + if (recurHelper.FREQ === 'MINUTELY' && recurHelper.INTERVAL && recurHelper.INTERVAL < 5) { throw new Error( - 'Scheduling automatically not supported for Weekly, Monthly and Yearly, please configure manually.' + 'The smallest interval you can configure is 5 minutes. Please adjust your schedule.' ); } - if (this.definition.timeZoneMapping[scheduleObject.timezoneName]) { scheduleObject.timezoneId = this.definition.timeZoneMapping[scheduleObject.timezoneName]; } else { - Util.logger.error( + throw new Error( `Could not find timezone ${scheduleObject.timezoneName} in definition.timeZoneMapping` ); } - schedule.TimeZone.ID = scheduleObject.timezoneId; - schedule._timezoneString = this.definition.timeZoneDifference[scheduleObject.timezoneId]; - - // add tz to input date to ensure Date() creates a date object with the right tz - const inputStartDateString = scheduleObject.startDate + schedule._timezoneString; - if (new Date(inputStartDateString) > new Date()) { - // if start date is in future take this - schedule.StartDateTime = scheduleObject.startDate; - schedule._StartDateTime = schedule.StartDateTime; // store copy for CLI output - } else { - // if start date is in past calculate new start date - const scheduledDate = new Date(inputStartDateString); - const futureDate = new Date(); - - if (keyStem === 'Dai') { - // keep time from template and start today if possible - if (scheduledDate.getHours() <= futureDate.getHours()) { - // hour on template has already passed today, start tomorrow - futureDate.setDate(futureDate.getDate() + 1); + if (recurHelper.COUNT == 1) { + const timezoneString = this.definition.timeZoneDifference[scheduleObject.timezoneId]; + // add tz to input date to ensure Date() creates a date object with the right tz + const inputStartDateString = scheduleObject.startDate + timezoneString; + if (new Date(inputStartDateString) > new Date()) { + const msg = + 'The automation will run only once. Please make sure this is intended and that the start date is in the future.'; + if (errorOnNotSchedulable) { + throw new Error(msg); + } else { + Util.logger.warn(msg); } - futureDate.setHours(scheduledDate.getHours()); - futureDate.setMinutes(scheduledDate.getMinutes()); - } else if (keyStem === 'Hour') { - // keep minute and start next possible hour - if (scheduledDate.getMinutes() <= futureDate.getMinutes()) { - futureDate.setHours(futureDate.getHours() + 1); + } else { + const msg = `The automation will run only once but its start date is in the past. While this can be saved, it cannot be scheduled.`; + if (errorOnNotSchedulable) { + throw new Error(msg); + } else { + Util.logger.warn(msg); } - futureDate.setMinutes(scheduledDate.getMinutes()); - } else if (keyStem === 'Minute') { - // schedule in next 15 minutes randomly to avoid that all automations run at exactly - // earliest start 1 minute from now - // the same time which would slow performance - futureDate.setMinutes(futureDate.getMinutes() + 1 + Math.ceil(Math.random() * 15)); - } - // return time as Dateobject - schedule.StartDateTime = futureDate; - const localTimezoneOffset = schedule.StartDateTime.getTimezoneOffset() / -60; - schedule._StartDateTime = this._calcTime(localTimezoneOffset, schedule.StartDateTime); // store copy for CLI output - } - - // The Create/Update API expects dates to be in US-Central time - // The retrieve API returns the date in whatever timezone one chose, hence we need to convert this upon upsert - schedule.StartDateTime = this._calcTime( - this.properties.options.serverTimeOffset, - schedule.StartDateTime, - schedule._timezoneString - ); - - if (recurHelper.UNTIL) { - schedule.RecurrenceRangeType = 'EndOn'; - schedule.EndDateTime = scheduleObject.endDate; - } else { - schedule.RecurrenceRangeType = 'EndAfter'; - schedule.Occurrences = recurHelper.COUNT; + } } - - return schedule; } /** @@ -824,27 +1416,342 @@ class Automation extends MetadataType { */ static _calcTime(offsetServer, dateInput, offsetInput) { // get UTC time in msec - let utc; - if ('string' === typeof dateInput) { - utc = new Date(dateInput + offsetInput).getTime(); - } else { - utc = dateInput.getTime(); - } + const utc = + 'string' === typeof dateInput + ? new Date(dateInput + offsetInput).getTime() + : dateInput.getTime(); // create new Date object reflecting SFMC's servertime const dateServer = new Date(utc + 3600000 * offsetServer); - // return time as a string without trailing "Z" - return dateServer.toISOString().slice(0, -1); + // return time as a string without trailing "Z" and without miliseconds (separated by .) + return dateServer.toISOString().slice(0, -1).split('.')[0]; + } + + /** + * Experimental: Only working for DataExtensions: + * Saves json content to a html table in the local file system. Will create the parent directory if it does not exist. + * The json's first level of keys must represent the rows and the secend level the columns + * + * @private + * @param {AutomationItem} json dataextension + * @param {object[][]} tabled prepped array for output in tabular format + * @returns {string} file content + */ + static _generateDocMd(json, tabled) { + let output = `## ${json.key}\n\n`; + if (json.key !== json.name) { + output += `**Name** (not equal to External Key)**:** ${json.name}\n\n`; + } + + output += + `**Description:** ${json.description || 'n/a'}\n\n` + + `**Folder:** ${ + json.r__folder_Path || + '_Hidden! Could not find folder with ID ' + json.categoryId + '_' + }/\n\n`; + const automationType = { scheduled: 'Schedule', triggered: 'File Drop' }; + output += `**Started by:** ${automationType[json.type] || 'Not defined'}\n\n`; + output += `**Status:** ${json.status}\n\n`; + if (json.type === 'scheduled' || json.schedule) { + const tz = + this.definition.timeZoneDifference[ + this.definition.timeZoneMapping[json?.schedule?.timezoneName] + ]; + + if (json.schedule?.icalRecur) { + output += `**Schedule:**\n\n`; + output += `* Start: ${json.schedule.startDate.split('T').join(' ')} ${tz}\n`; + output += `* End: ${json.schedule.endDate.split('T').join(' ')} ${tz}\n`; + output += `* Timezone: ${json.schedule.timezoneName}\n`; + + const ical = {}; + for (const item of json.schedule.icalRecur.split(';')) { + const temp = item.split('='); + ical[temp[0]] = temp[1]; + } + const frequency = ical.FREQ.slice(0, -2).toLowerCase(); + + output += `* Recurrence: `; + output += + ical.COUNT == 1 + ? 'run only once' + : `every${ical.INTERVAL > 1 ? ' ' + ical.INTERVAL : ''} ${ + frequency === 'dai' ? 'day' : frequency + }${ical.INTERVAL > 1 ? 's' : ''}${ + ical.COUNT + ? ` for ${ical.COUNT} times` + : ical.UNTIL + ? ' until end date' + : '' + }`; + output += '\n'; + } else if (json.schedule) { + output += `**Schedule:** Not defined\n`; + } + } else if (json.type === 'triggered' && json.fileTrigger) { + output += `**File Trigger:**\n\n`; + output += `* Queue Files: ${json.fileTrigger.queueFiles}\n`; + output += `* Published: ${json.fileTrigger.isPublished}\n`; + output += `* Pattern: ${json.fileTrigger.fileNamingPattern}\n`; + output += `* Folder: ${json.fileTrigger.folderLocationText}\n`; + } + // add empty line to ensure the following notifications are rendered properly + output += '\n'; + if (json.notifications?.length) { + output += `**Notifications:**\n\n`; + // ensure notifications are sorted by type regardless of how the API returns it + const notifications = {}; + for (const n of json.notifications) { + notifications[n.type] = + (Array.isArray(n.email) ? n.email.join(',') : n.email) + + (n.message ? ` ("${n.message}")` : ''); + } + if (notifications.Complete) { + output += `* Complete: ${notifications.Complete}\n`; + } + if (notifications.Error) { + output += `* Error: ${notifications.Error}\n`; + } + } else { + output += `**Notifications:** _none_\n\n`; + } + + // show table with automation steps + if (tabled && tabled.length) { + // add empty line to ensure the following table is rendered properly + output += '\n'; + let tableSeparator = ''; + const row1 = []; + for (const column of tabled[0]) { + row1.push( + `| ${column.title}${ + column.description + ? `<br>_<small>${column.description.replaceAll('\n', '<br>')}</small>_` + : '' + } ` + ); + tableSeparator += '| --- '; + } + output += row1.join('') + `|\n${tableSeparator}|\n`; + for (let i = 1; i < tabled.length; i++) { + for (const activity of tabled[i]) { + output += activity + ? `| _${activity.i}: ${activity.type}_<br>${activity.key} ` + : '| - '; + } + output += '|\n'; + } + } + return output; + } + + /** + * Saves json content to a html table in the local file system. Will create the parent directory if it does not exist. + * The json's first level of keys must represent the rows and the secend level the columns + * + * @private + * @param {string} directory directory the file will be written to + * @param {string} filename name of the file without '.json' ending + * @param {AutomationItem} json dataextension.columns + * @param {'html'|'md'} mode html or md + * @returns {Promise.<void>} Promise of success of saving the file + */ + static async _writeDoc(directory, filename, json, mode) { + await File.ensureDir(directory); + + const tabled = []; + if (json.steps && json.steps.length) { + tabled.push( + json.steps.map((step, index) => ({ + title: `Step ${index + 1}`, + description: step.name || '-', + })) + ); + let maxActivities = 0; + for (const step of json.steps) { + if (step.activities.length > maxActivities) { + maxActivities = step.activities.length; + } + } + for (let activityIndex = 0; activityIndex < maxActivities; activityIndex++) { + tabled.push( + json.steps.map((step, stepIndex) => + step.activities[activityIndex] + ? { + i: stepIndex + 1 + '.' + (activityIndex + 1), + key: + step.activities[activityIndex].r__key || + (step.activities[activityIndex].timeZone + ? `${step.activities[activityIndex].name}<br>${step.activities[activityIndex].timeZone}` + : step.activities[activityIndex].name), + type: step.activities[activityIndex].r__type, + } + : null + ) + ); + } + } + let output; + if (mode === 'md') { + output = this._generateDocMd(json, tabled); + try { + // write to disk + await File.writeToFile(directory, filename + '.automation-doc', mode, output); + } catch (ex) { + Util.logger.error(`Automation.writeDeToX(${mode}):: error | ` + ex.message); + } + } + } + + /** + * Parses metadata into a readable Markdown/HTML format then saves it + * + * @param {AutomationMap} [metadata] a list of dataExtension definitions + * @returns {Promise.<void>} - + */ + static async document(metadata) { + if (['md', 'both'].includes(this.properties.options.documentType)) { + if (!metadata) { + metadata = ( + await this.readBUMetadataForType( + File.normalizePath([ + this.properties.directories.retrieve, + this.buObject.credential, + this.buObject.businessUnit, + ]), + true + ) + ).automation; + } + const docPath = File.normalizePath([ + this.properties.directories.retrieve, + this.buObject.credential, + this.buObject.businessUnit, + this.definition.type, + ]); + if (!metadata || !Object.keys(metadata).length) { + // as part of retrieve & manual execution we could face an empty folder + return; + } + + const docLimit = pLimit(100); + await Promise.all( + Object.keys(metadata).map((key) => + docLimit(() => this._writeDoc(docPath + '/', key, metadata[key], 'md')) + ) + ); + } + } + + /** + * should return only the json for all but asset, query and script that are saved as multiple files + * additionally, the documentation for dataExtension and automation should be returned + * + * @param {string[]} keyArr customerkey of the metadata + * @returns {Promise.<string[]>} list of all files that need to be committed in a flat array ['path/file1.ext', 'path/file2.ext'] + */ + static async getFilesToCommit(keyArr) { + if (this.properties.metaDataTypes.documentOnRetrieve.includes(this.definition.type)) { + // document automation is active. assume we want to commit the MD file as well + const path = File.normalizePath([ + this.properties.directories.retrieve, + this.buObject.credential, + this.buObject.businessUnit, + this.definition.type, + ]); + + const fileList = keyArr.flatMap((key) => [ + File.normalizePath([path, `${key}.${this.definition.type}-meta.json`]), + File.normalizePath([path, `${key}.${this.definition.type}-doc.md`]), + ]); + return fileList; + } else { + // document automation is not active upon retrieve, run default method instead + return super.getFilesToCommit(keyArr); + } + } + + /** + * helper to allow us to select single metadata entries via REST + * + * @param {string} key customer key + * @returns {Promise.<string>} objectId or enpty string + */ + static async #getObjectIdForSingleRetrieve(key) { + const response = await this.client.soap.retrieve('Program', ['ObjectID'], { + filter: { + leftOperand: 'CustomerKey', + operator: 'equals', + rightOperand: key, + }, + }); + return response?.Results?.length ? response.Results[0].ObjectID : null; + } + + /** + * Delete a metadata item from the specified business unit + * + * @param {string} key Identifier of data extension + * @returns {Promise.<boolean>} deletion success status + */ + static async deleteByKey(key) { + // the delete endpoint returns a general exception if the automation does not exist; handle it gracefully instead by adding a retrieve first + const objectId = key ? await this.#getObjectIdForSingleRetrieve(key) : null; + if (!objectId) { + await this.deleteNotFound(key); + return false; + } + return super.deleteByKeySOAP(key, 'CustomerKey'); + } + + /** + * clean up after deleting a metadata item + * + * @param {string} customerKey Identifier of metadata item + * @returns {Promise.<void>} - + */ + static async postDeleteTasks(customerKey) { + // delete local copy: retrieve/cred/bu/.../...-meta.json + // delete local copy: retrieve/cred/bu/.../...-doc.md + await super.postDeleteTasks(customerKey, [`${this.definition.type}-doc.md`]); + } + + /** + * helper for {@link MetadataType.getNestedValue} - adjusted for automation activities + * + * @param {any} obj the metadataItem to search in (or the result) + * @param {string[]} nestedKeyParts key in dot-notation split into parts + * @param {string} dependentType used for types that need custom handling + * @returns {(string) | (string)[]} result + */ + static getNestedValueHelper(obj, nestedKeyParts, dependentType) { + if (nestedKeyParts.length == 0) { + // key was found; append '' to ensure we always return a string + return obj + ''; + } + // get most left key + const key = nestedKeyParts.shift(); + if (!obj[key]) { + // key was not found + return; + } + if (Array.isArray(obj[key])) { + return obj[key].flatMap((x) => + this.getNestedValueHelper(x, [...nestedKeyParts], dependentType) + ); + } else { + if (nestedKeyParts.length == 0) { + // key was found if length is 0 and search field (r__type) is equal the current type, else, keep going + return obj[key] === dependentType ? obj.r__key : undefined; + } else { + return this.getNestedValueHelper(obj[key], [...nestedKeyParts], dependentType); + } + } } } // Assign definition to static attributes Automation.definition = Definitions.automation; -Automation.cache = {}; -/** - * @type {Util.ET_Client} - */ -Automation.client = undefined; -module.exports = Automation; +export default Automation; diff --git a/lib/metadataTypes/Campaign.js b/lib/metadataTypes/Campaign.js index 56998c142..cb39f6d41 100644 --- a/lib/metadataTypes/Campaign.js +++ b/lib/metadataTypes/Campaign.js @@ -1,122 +1,90 @@ 'use strict'; -const MetadataType = require('./MetadataType'); -const Util = require('../util/util'); -const File = require('../util/file'); +import MetadataType from './MetadataType.js'; +import { Util } from '../util/util.js'; +import File from '../util/file.js'; + +/** + * @typedef {import('../../types/mcdev.d.js').BuObject} BuObject + * @typedef {import('../../types/mcdev.d.js').CodeExtract} CodeExtract + * @typedef {import('../../types/mcdev.d.js').CodeExtractItem} CodeExtractItem + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItem} MetadataTypeItem + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItemDiff} MetadataTypeItemDiff + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItemObj} MetadataTypeItemObj + * @typedef {import('../../types/mcdev.d.js').MetadataTypeMap} MetadataTypeMap + * @typedef {import('../../types/mcdev.d.js').MetadataTypeMapObj} MetadataTypeMapObj + * @typedef {import('../../types/mcdev.d.js').SoapRequestParams} SoapRequestParams + * @typedef {import('../../types/mcdev.d.js').TemplateMap} TemplateMap + */ /** * Campaign MetadataType + * * @augments MetadataType */ class Campaign extends MetadataType { /** * Retrieves Metadata of campaigns. Afterwards, starts metadata retrieval for their campaign assets - * @param {String} retrieveDir Directory where retrieved metadata directory will be saved - * @returns {Promise} Promise + * + * @param {string} retrieveDir Directory where retrieved metadata directory will be saved + * @param {void | string[]} [_] unused parameter + * @param {void | string[]} [__] unused parameter + * @param {string} [key] customer key of single item to retrieve + * @returns {Promise.<MetadataTypeMapObj>} Promise */ - static retrieve(retrieveDir) { - return new Promise((resolve) => { - const config = { - props: null, - options: {}, - }; - this.client.campaign(config).get(async (error, response) => { - if (error) { - throw new Error(error); - } - // Save metadata structure - const metadata = Campaign.parseResponseBody(response.body); - // Util.logger.info('Campaign.retrieve:: Parsed Response'); - // Write metadata to local filesystem - for (const metadataEntry in metadata) { - File.writeJSONToFile( - retrieveDir + '/campaign/' + metadataEntry + '/', - metadataEntry + '.' + this.definition.type + '-meta', - metadata[metadataEntry] - ); - } - const campaignAssetPromises = []; - for (const campaign in metadata) { - try { - campaignAssetPromises.push( - Campaign._retrieveCampaignAsset( - retrieveDir, - metadata[campaign].id, - metadata[campaign].name - ) - ); - } catch (ex) { - Util.logger.error(ex.message); - } - } - const values = await Promise.all(campaignAssetPromises); - Util.logger.info( - `Downloaded: ${this.definition.type} (${Object.keys(metadata).length})` - ); - resolve({ metadata: values, type: 'campaign' }); - }); - }); + static async retrieve(retrieveDir, _, __, key) { + const res = await super.retrieveREST( + retrieveDir, + '/legacy/v1/beta2/data/campaign/', + null, + key + ); + // get assignments + Util.logger.info(`Retrieving: campaignAsset`); + const campaignAssets = await Promise.all( + Object.keys(res.metadata).map((key) => + this.getAssetTags(retrieveDir, res.metadata[key].campaignId, key) + ) + ); + Util.logger.info( + `Downloaded: campaignAsset (${campaignAssets.flat().length})` + Util.getKeysString(key) + ); + + return res; } /** - * Retrieves campaign asset for a specific campaign - * @param {String} retrieveDir Directory where retrieved metadata directory will be saved - * @param {Number} id id of the parent campaign - * @param {String} name name of the parent campaign - * @returns {Promise} Promise + * Retrieves event definition metadata for caching + * + * @returns {Promise.<MetadataTypeMapObj>} Promise of metadata */ - static _retrieveCampaignAsset(retrieveDir, id, name) { - return new Promise((resolve, reject) => { - const config = { - props: { id: id }, - options: {}, - }; - this.client.campaignAsset(config).get((error, response) => { - if (error) { - reject(error); - } else { - const assets = Campaign._parseAssetResponseBody(response.body); - - for (const asset in assets) { - File.writeJSONToFile( - retrieveDir + '/campaign/' + name + '/assets/', - asset + '.campaignAsset-meta', - assets[asset] - ); - } - resolve(assets); - } - }); - }); + static retrieveForCache() { + return super.retrieveREST(null, '/legacy/v1/beta2/data/campaign/'); } /** * Parses campaign asset response body and returns metadata entries mapped to their id - * @param {Object} body response body of metadata retrieval - * @returns {Object} keyField => metadata map + * + * @param {string} retrieveDir folder where to save + * @param {string} campaignId of camapaign to retrieve + * @param {string} name of camapaign for saving + * @returns {Promise.<MetadataTypeMapObj>} Campaign Asset Object */ - static _parseAssetResponseBody(body) { - const metadataStructure = {}; - if (body.items) { - for (let i = 0; i < body.items.length; i++) { - const item = body.items[i]; - // if needed: Makes sure files can be saved on windows operating systems - // .replace(/[/\\?%*:|"<>]/g, '-'); - const key = item.id; - metadataStructure[key] = item; - } - } else { - Util.logger.debug( - `Campaign._parseAssetResponseBody:: Format of 'body' parameter wrong: `, - body + static async getAssetTags(retrieveDir, campaignId, name) { + const res = await this.client.rest.getBulk(`/hub/v1/campaigns/${campaignId}/assets`); + + for (const asset of res.items) { + await File.writeJSONToFile( + `${retrieveDir}/campaign/${name}/assets/`, + asset.id + '.campaignAsset-meta', + asset ); } - return metadataStructure; + return res.items; } } // Assign definition to static attributes -Campaign.definition = require('../MetadataTypeDefinitions').campaign; -Campaign.client = undefined; -Campaign.cache = {}; +import MetadataTypeDefinitions from '../MetadataTypeDefinitions.js'; +Campaign.definition = MetadataTypeDefinitions.campaign; -module.exports = Campaign; +export default Campaign; diff --git a/lib/metadataTypes/ContentArea.js b/lib/metadataTypes/ContentArea.js index 9f6773dcc..d94fa94c4 100644 --- a/lib/metadataTypes/ContentArea.js +++ b/lib/metadataTypes/ContentArea.js @@ -1,55 +1,92 @@ 'use strict'; -const MetadataType = require('./MetadataType'); -const Util = require('../util/util'); +import MetadataType from './MetadataType.js'; +import { Util } from '../util/util.js'; +import cache from '../util/cache.js'; + +/** + * @typedef {import('../../types/mcdev.d.js').BuObject} BuObject + * @typedef {import('../../types/mcdev.d.js').CodeExtract} CodeExtract + * @typedef {import('../../types/mcdev.d.js').CodeExtractItem} CodeExtractItem + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItem} MetadataTypeItem + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItemDiff} MetadataTypeItemDiff + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItemObj} MetadataTypeItemObj + * @typedef {import('../../types/mcdev.d.js').MetadataTypeMap} MetadataTypeMap + * @typedef {import('../../types/mcdev.d.js').MetadataTypeMapObj} MetadataTypeMapObj + * @typedef {import('../../types/mcdev.d.js').SoapRequestParams} SoapRequestParams + * @typedef {import('../../types/mcdev.d.js').TemplateMap} TemplateMap + */ /** * ContentArea MetadataType + * * @augments MetadataType */ class ContentArea extends MetadataType { /** * Retrieves SOAP based metadata of metadata type into local filesystem. executes callback with retrieved metadata - * @param {String} retrieveDir Directory where retrieved metadata directory will be saved - * @returns {Promise<Object>} Promise of metadata + * + * @param {string} retrieveDir Directory where retrieved metadata directory will be saved + * @param {void | string[]} [_] unused parameter + * @param {void | string[]} [__] unused parameter + * @param {string} [key] customer key of single item to retrieve + * @returns {Promise.<MetadataTypeMapObj>} Promise of metadata */ - static retrieve(retrieveDir) { + static retrieve(retrieveDir, _, __, key) { Util.logger.warn( - 'Classic Content Areas are deprecated and will be discontinued by SFMC in the near future. Ensure that you migrate any existing Content Areas to Content Builder as soon as possible.' + ' - Classic Content Areas are deprecated and will be discontinued by SFMC in the near future. Ensure that you migrate any existing Content Areas to Content Builder as soon as possible.' ); + /** @type {SoapRequestParams} */ + let requestParams = null; + if (key) { + requestParams = { + filter: { + leftOperand: 'CustomerKey', + operator: 'equals', + rightOperand: key, + }, + }; + } // !dont activate `await File.initPrettier('html');` as we only want to retrieve for migration and formatting might mess with the outcome - return super.retrieveSOAPgeneric(retrieveDir); - } - /** - * manages post retrieve steps - * @param {Object} metadata a single query - * @returns {Object[]} Array with one metadata object and one query string - */ - static postRetrieveTasks(metadata) { - return this.parseMetadata(metadata); + return super.retrieveSOAP(retrieveDir, requestParams, key); } + /** - * parses retrieved Metadata before saving - * @param {Object} metadata a single query activity definition - * @returns {Array} Array with one metadata object and one sql string + * generic script that retrieves the folder path from cache and updates the given metadata with it after retrieve + * + * @param {MetadataTypeItem} metadata a single script activity definition */ - static parseMetadata(metadata) { - // folder + static setFolderPath(metadata) { try { - metadata.r__folder_Path = Util.getFromCache( - this.cache, + metadata.r__folder_Path = cache.searchForField( 'folder', - metadata.CategoryID, + metadata[this.definition.folderIdField], 'ID', 'Path' ); + delete metadata[this.definition.folderIdField]; } catch (ex) { - Util.logger.debug(`Classic Content Area '${metadata.CustomerKey}': ${ex.message}`); + Util.logger.debug( + ` - ${this.definition.type} '${metadata[this.definition.nameField]}' (${ + metadata[this.definition.keyField] + }): Could not find folder (${ex.message})` + ); // classic content blocks that reside in the main folder are // saved with CategoryID=0, instead of to the actual ID of // their parent root folder. metadata.r__folder_Path = 'my contents'; } + } + + /** + * parses retrieved Metadata before saving + * + * @param {MetadataTypeItem} metadata a single item + * @returns {MetadataTypeItem} parsed item + */ + static postRetrieveTasks(metadata) { + // folder + this.setFolderPath(metadata); // extract code const codeArr = [ @@ -67,6 +104,7 @@ class ContentArea extends MetadataType { } // Assign definition to static attributes -ContentArea.definition = require('../MetadataTypeDefinitions').contentArea; +import MetadataTypeDefinitions from '../MetadataTypeDefinitions.js'; +ContentArea.definition = MetadataTypeDefinitions.contentArea; -module.exports = ContentArea; +export default ContentArea; diff --git a/lib/metadataTypes/DataExtension.js b/lib/metadataTypes/DataExtension.js index 4b1ffc933..ee4efe0e5 100644 --- a/lib/metadataTypes/DataExtension.js +++ b/lib/metadataTypes/DataExtension.js @@ -1,149 +1,229 @@ 'use strict'; -const jsonToTable = require('json-to-table'); -const MetadataType = require('./MetadataType'); -const DataExtensionField = require('./DataExtensionField'); -const Folder = require('./Folder'); -const Util = require('../util/util'); -const File = require('../util/file'); +import jsonToTable from 'json-to-table'; +import MetadataType from './MetadataType.js'; +import AttributeSet from './AttributeSet.js'; +import DataExtensionField from './DataExtensionField.js'; +import Folder from './Folder.js'; +import { Util } from '../util/util.js'; +import File from '../util/file.js'; +import auth from '../util/auth.js'; +import cache from '../util/cache.js'; +import pLimit from 'p-limit'; +import { checkbox } from '@inquirer/prompts'; /** - * @typedef {Object} DataExtensionItem - * @property {string} CustomerKey key - * @property {string} Name name - * @property {string} Description - - * @property {'true'|'false'} IsSendable - - * @property {'true'|'false'} IsTestable - - * @property {Object} SendableDataExtensionField - - * @property {string} SendableDataExtensionField.Name - - * @property {Object} SendableSubscriberField - - * @property {string} SendableSubscriberField.Name - - * @property {DataExtensionField.DataExtensionFieldItem[]} Fields list of DE fields - * @property {'dataextension'|'salesforcedataextension'|'synchronizeddataextension'|'shared_dataextension'|'shared_salesforcedataextension'} r__folder_ContentType retrieved from associated folder - * @property {string} r__folder_Path folder path in which this DE is saved - * @property {string} [CategoryID] holds folder ID, replaced with r__folder_Path during retrieve - * @property {string} [r__dataExtensionTemplate_Name] name of optionally associated DE template - * @property {Object} [Template] - - * @property {string} [Template.CustomerKey] key of optionally associated DE teplate - * - * @typedef {Object.<string, DataExtensionItem>} DataExtensionMap + * @typedef {import('../../types/mcdev.d.js').BuObject} BuObject + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItem} MetadataTypeItem + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItemDiff} MetadataTypeItemDiff + * @typedef {import('../../types/mcdev.d.js').MetadataTypeMap} MetadataTypeMap + * @typedef {import('../../types/mcdev.d.js').SoapRequestParams} SoapRequestParams + * @typedef {import('../../types/mcdev.d.js').TemplateMap} TemplateMap + */ + +/** + * @typedef {import('../../types/mcdev.d.js').DataExtensionFieldItem} DataExtensionFieldItem + * @typedef {import('../../types/mcdev.d.js').DataExtensionFieldMap} DataExtensionFieldMap + * @typedef {import('../../types/mcdev.d.js').DataExtensionItem} DataExtensionItem + * @typedef {import('../../types/mcdev.d.js').DataExtensionMap} DataExtensionMap */ /** * DataExtension MetadataType + * * @augments MetadataType */ class DataExtension extends MetadataType { + /** @type {Object.<string, DataExtensionFieldMap>} key: deKey, value: deFieldMap */ + static oldFields; + /** * Upserts dataExtensions after retrieving them from source and target to compare * if create or update operation is needed. - * @param {DataExtensionMap} desToDeploy dataExtensions mapped by their customerKey - * @param {Object} _ - - * @param {Util.BuObject} buObject properties for auth - * @returns {Promise} Promise + * + * @param {DataExtensionMap} metadataMap dataExtensions mapped by their customerKey + * @param {string} deployDir directory where deploy metadata are saved + * @returns {Promise.<MetadataTypeMap>} keyField => metadata map */ - static async upsert(desToDeploy, _, buObject) { - Util.logger.info('- Retrieve target metadata for comparison with deploy metadata'); - const results = await this.retrieveForCache(buObject, null, true); - const targetMetadata = results.metadata; - Util.logger.info('- Retrieved target metadata'); - /** @type {Promise[]} */ - const deCreatePromises = []; - /** @type {Promise[]} */ - const deUpdatePromises = []; - for (const dataExtension in desToDeploy) { - if (desToDeploy[dataExtension].Name.startsWith('_')) { - Util.logger.warn( - '- Cannot Upsert Strongly Typed Data Extensions - skipping ' + - desToDeploy[dataExtension].Name - ); - continue; - } - if ( - buObject.eid !== buObject.mid && - desToDeploy[dataExtension].r__folder_Path.startsWith('Shared Items') - ) { - // this needs to be run before executing preDeployTasks() - Util.logger.warn( - `- Cannot Create/Update a Shared Data Extension from the Child BU - skipping ${desToDeploy[dataExtension].Name}` + static async upsert(metadataMap, deployDir) { + /** @type {object[]} */ + const metadataToCreate = []; + /** @type {object[]} */ + const metadataToUpdate = []; + let filteredByPreDeploy = 0; + for (const metadataKey in metadataMap) { + try { + metadataMap[metadataKey] = await this.validation( + 'deploy', + metadataMap[metadataKey], + deployDir ); - continue; - } - if ( - desToDeploy[dataExtension].r__folder_Path.startsWith('Synchronized Data Extensions') - ) { - // this needs to be run before executing preDeployTasks() - Util.logger.warn( - `- Cannot Create/Update a Synchronized Data Extension. Please use Contact Builder to maintain these - skipping ${desToDeploy[dataExtension].Name}` + if (!metadataMap[metadataKey]) { + filteredByPreDeploy++; + continue; + } + metadataMap[metadataKey] = await this.preDeployTasks(metadataMap[metadataKey]); + + await this.createOrUpdate( + metadataMap, + metadataKey, + false, + metadataToUpdate, + metadataToCreate ); - continue; - } - try { - desToDeploy[dataExtension] = await this.preDeployTasks(desToDeploy[dataExtension]); } catch (ex) { - // problem with retrieving folder for this DE found // output error & remove from deploy list Util.logger.error( - `- dataExtension ${desToDeploy[dataExtension].Name}: ${ex.message}` + ` ☇ skipping ${this.definition.type} ${ + metadataMap[metadataKey][this.definition.keyField] + } / ${metadataMap[metadataKey][this.definition.nameField]}: ${ex.message}` ); - delete desToDeploy[dataExtension]; + delete metadataMap[metadataKey]; // skip rest of handling for this DE + filteredByPreDeploy++; continue; } - if (targetMetadata[dataExtension]) { - // data extension already exists in target and needs to be updated - deUpdatePromises.push(DataExtension.update(desToDeploy[dataExtension])); - } else { - // data extension does not exist in target and has to be created - deCreatePromises.push(DataExtension.create(desToDeploy[dataExtension])); - } } - if (deUpdatePromises.length) { + const createLimit = pLimit(10); + const createResults = ( + await Promise.allSettled( + metadataToCreate + .filter((r) => r !== undefined && r !== null) + .map((metadataEntry) => createLimit(() => this.create(metadataEntry))) + ) + ) + .filter((r) => r !== undefined && r !== null) + .filter(this.#filterUpsertResults); + + if (Util.OPTIONS.noUpdate && metadataToUpdate.length > 0) { Util.logger.info( - '- Please note that Data Retention Policies can only be set during creation, not during update.' + ` ☇ skipping update of ${metadataToUpdate.length} ${this.definition.type}${metadataToUpdate.length == 1 ? '' : 's'}: --noUpdate flag is set` ); } - const createResults = (await Promise.allSettled(deCreatePromises)).filter( - this._filterUpsertResults - ); - const updateResults = (await Promise.allSettled(deUpdatePromises)).filter( - this._filterUpsertResults - ); + const updateLimit = pLimit(10); + const updateResults = Util.OPTIONS.noUpdate + ? [] + : ( + await Promise.allSettled( + metadataToUpdate + .filter((r) => r !== undefined && r !== null) + .map((metadataEntry) => + updateLimit(() => this.update(metadataEntry.after)) + ) + ) + ) + .filter((r) => r !== undefined && r !== null) + .filter(this.#filterUpsertResults); const successfulResults = [...createResults, ...updateResults]; - - Util.metadataLogger( - 'info', - this.definition.type, - 'upsert', - `${createResults.length} of ${deCreatePromises.length} created / ${updateResults.length} of ${deUpdatePromises.length} updated` + Util.logger.info( + `${this.definition.type} upsert: ${createResults.length} of ${metadataToCreate.length} created / ${updateResults.length} of ${metadataToUpdate.length} updated` + + (filteredByPreDeploy > 0 ? ` / ${filteredByPreDeploy} filtered` : '') ); + let upsertResults; if (successfulResults.length > 0) { const metadataResults = successfulResults - .map((r) => r.value.body.Results[0].Object) + .map((r) => (r.status === 'fulfilled' ? r.value.Results[0].Object : null)) + .filter(Boolean) .map((r) => { // if only one fields added will return object otherwise array - if (r.Fields && r.Fields.Field && Array.isArray(r.Fields.Field)) { + if (Array.isArray(r?.Fields?.Field)) { r.Fields = r.Fields.Field; - } else if (r.Fields && r.Fields.Field) { + } else if (r?.Fields?.Field) { r.Fields = [r.Fields.Field]; } return r; }); - const formattedResults = super.parseResponseBody({ Results: metadataResults }); - return formattedResults; + upsertResults = super.parseResponseBody({ Results: metadataResults }); } else { - return {}; + upsertResults = {}; + } + await this.postDeployTasks(upsertResults, metadataMap, { + created: createResults.length, + updated: updateResults.length, + }); + return upsertResults; + } + + /** + * helper for {@link MetadataType.upsert} + * + * @param {MetadataTypeMap} metadataMap list of metadata + * @param {string} metadataKey key of item we are looking at + * @param {boolean} hasError error flag from previous code + * @param {MetadataTypeItemDiff[]} metadataToUpdate list of items to update + * @param {MetadataTypeItem[]} metadataToCreate list of items to create + * @returns {Promise.<'create'|'update'|'skip'>} action to take + */ + static async createOrUpdate( + metadataMap, + metadataKey, + hasError, + metadataToUpdate, + metadataToCreate + ) { + const action = await super.createOrUpdate( + metadataMap, + metadataKey, + hasError, + metadataToUpdate, + metadataToCreate + ); + + if (action === 'update') { + // Update dataExtension + Columns if they already exist; Create them if not + // Modify columns for update call + DataExtensionField.client = this.client; + DataExtensionField.properties = this.properties; + DataExtension.oldFields ||= {}; + DataExtension.oldFields[metadataMap[metadataKey][this.definition.keyField]] = + await DataExtensionField.prepareDeployColumnsOnUpdate( + metadataMap[metadataKey].Fields, + Util.matchedByName?.[this.definition.type]?.[metadataKey] || metadataKey + ); + + if ( + metadataMap[metadataKey][this.definition.keyField] !== metadataKey && + metadataMap[metadataKey].Fields.length + ) { + // changeKeyValue / changeKeyField used + Util.logger.warn( + ` - ${this.definition.type} ${metadataKey}: Cannot change fields while updating the key. Skipping field update in favor of key update.` + ); + metadataMap[metadataKey].Fields.length = 0; + } + + // convert simple array into object.Array.object format to cope with how the XML body in the SOAP call needs to look like: + // <Fields> + // <Field> + // <CustomerKey>SubscriberKey</CustomerKey> + // .. + // </Field> + // </Fields> + metadataMap[metadataKey].Fields = { Field: metadataMap[metadataKey].Fields }; + } else if (action === 'create') { + this.#cleanupRetentionPolicyFields(metadataMap[metadataKey]); + + // convert simple array into object.Array.object format to cope with how the XML body in the SOAP call needs to look like: + // <Fields> + // <Field> + // <CustomerKey>SubscriberKey</CustomerKey> + // .. + // </Field> + // </Fields> + metadataMap[metadataKey].Fields = { Field: metadataMap[metadataKey].Fields }; } + return action; } /** - * helper for upsert() - * @param {Object} res - - * @returns {Boolean} true: keep, false: discard + * helper for {@link DataExtension.upsert} + * + * @param {object} res - + * @returns {boolean} true: keep, false: discard */ - static _filterUpsertResults(res) { + static #filterUpsertResults(res) { if (res.status === 'rejected') { // promise rejects, whole request failed Util.logger.error('- error upserting dataExtension: ' + res.reason); @@ -155,12 +235,12 @@ class DataExtension extends MetadataType { } else if (res.value.results) { Util.logger.error( '- error upserting dataExtension: ' + - (res.value.results[0].Object ? res.value.results[0].Object.Name : '') + + (res.value.Results[0].Object ? res.value.Results[0].Object.Name : '') + '. ' + - res.value.results[0].StatusMessage + res.value.Results[0].StatusMessage ); return false; - } else if (res.status === 'fulfilled' && res.value && res.value.faultstring) { + } else if (res.status === 'fulfilled' && res?.value?.faultstring) { // can happen that the promise does not reject, but that it resolves an error Util.logger.error('- error upserting dataExtension: ' + res.value.faultstring); return false; @@ -171,21 +251,11 @@ class DataExtension extends MetadataType { /** * Create a single dataExtension. Also creates their columns in 'dataExtension.columns' + * * @param {DataExtensionItem} metadata single metadata entry * @returns {Promise} Promise */ static async create(metadata) { - this._cleanupRetentionPolicyFields(metadata); - - // convert simple array into object.Array.object format to cope with how the XML body in the SOAP call needs to look like: - // <Fields> - // <Field> - // <CustomerKey>SubscriberKey</CustomerKey> - // .. - // </Field> - // </Fields> - metadata.Fields = { Field: metadata.Fields }; - return super.createSOAP(metadata); } @@ -193,11 +263,11 @@ class DataExtension extends MetadataType { * SFMC saves a date in "RetainUntil" under certain circumstances even * if that field duplicates whats in the period fields * during deployment, that extra value is not accepted by the APIs which is why it needs to be removed - * @private + * * @param {DataExtensionItem} metadata single metadata entry * @returns {void} */ - static _cleanupRetentionPolicyFields(metadata) { + static #cleanupRetentionPolicyFields(metadata) { if ( metadata.DataRetentionPeriodLength && metadata.DataRetentionPeriodUnitOfMeasure && @@ -205,262 +275,763 @@ class DataExtension extends MetadataType { ) { metadata.RetainUntil = ''; Util.logger.warn( - `RetainUntil date was reset automatically because RetentionPeriod info was found in: ${metadata.CustomerKey}` + ` - RetainUntil date was reset automatically because RetentionPeriod info was found in: ${metadata.CustomerKey}` ); } } + /** * Updates a single dataExtension. Also updates their columns in 'dataExtension.columns' + * * @param {DataExtensionItem} metadata single metadata entry + * @param {boolean} [handleOutside] if the API reponse is irregular this allows you to handle it outside of this generic method * @returns {Promise} Promise */ - static async update(metadata) { - // Update dataExtension + Columns if they already exist; Create them if not - // Modify columns for update call - DataExtensionField.cache = this.metadata; - DataExtensionField.client = this.client; - DataExtensionField.properties = this.properties; - DataExtension.oldFields = DataExtension.oldFields || {}; - DataExtension.oldFields[metadata.CustomerKey] = - await DataExtensionField.prepareDeployColumnsOnUpdate( - metadata.Fields, - metadata.CustomerKey - ); - - // convert simple array into object.Array.object format to cope with how the XML body in the SOAP call needs to look like: - // <Fields> - // <Field> - // <CustomerKey>SubscriberKey</CustomerKey> - // .. - // </Field> - // </Fields> - - metadata.Fields = { Field: metadata.Fields }; - return super.updateSOAP(metadata); + static async update(metadata, handleOutside) { + return super.updateSOAP(metadata, handleOutside); } + /** * Gets executed after deployment of metadata type + * * @param {DataExtensionMap} upsertedMetadata metadata mapped by their keyField - * @returns {void} + * @param {DataExtensionMap} originalMetadata metadata to be updated (contains additioanl fields) + * @param {{created: number, updated: number}} createdUpdated counter representing successful creates/updates + * @returns {Promise.<void>} - */ - static postDeployTasks(upsertedMetadata) { - if (!DataExtension.oldFields) { - // only run postDeploy if we are in update mode - return; - } - // somewhat of a workardoun but it ensures we get the field list from the server rather than whatever we might have in cache got returned during update/add. This ensures a complete and correctly ordered field list + static async postDeployTasks(upsertedMetadata, originalMetadata, createdUpdated) { for (const key in upsertedMetadata) { const item = upsertedMetadata[key]; - const isUpdate = - this.cache && - this.cache.dataExtension && - this.cache.dataExtension[item.CustomerKey]; - if (isUpdate) { - const cachedVersion = this.cache.dataExtension[item.CustomerKey]; - // restore retention values that are typically not returned by the update call - item.RowBasedRetention = cachedVersion.RowBasedRetention; - item.ResetRetentionPeriodOnImport = cachedVersion.ResetRetentionPeriodOnImport; - item.DeleteAtEndOfRetentionPeriod = cachedVersion.DeleteAtEndOfRetentionPeriod; - item.RetainUntil = cachedVersion.RetainUntil; - - // ensure we have th - const existingFields = DataExtension.oldFields[item[this.definition.nameField]]; - if (item.Fields !== '' && existingFields) { - // TODO should be replaced by a manual sort using existingFields - // ! this is inefficient because it triggers a new download of the fields during the saveResults() step - item.Fields.length = 0; + + const oldKey = Util.changedKeysMap?.[this.definition.type]?.[key] || key; + delete Util.changedKeysMap?.[this.definition.type]?.[key]; + + const cachedVersion = createdUpdated.updated + ? cache.getByKey(this.definition.type, key) + : null; + if (cachedVersion) { + // UPDATE + + const existingFields = DataExtension.oldFields[item[this.definition.keyField]]; + + // @ts-expect-error Fields is a special case that cannot be properly typed; emtpy string is required for SOAP API + if (item.Fields === '') { + // if no fields were updated, we need to set Fields to "empty string" for the API to work + // reset here to get the correct field list + item.Fields = Object.keys(existingFields) + .map((el) => existingFields[el]) + .toSorted((a, b) => a.Ordinal - b.Ordinal); + } else if (existingFields) { + // get list of updated fields + /** @type {DataExtensionFieldItem[]} */ // @ts-ignore Fields.Field is a special case that cannot be properly typed; only required for SOAP API + const updatedFieldsArr = originalMetadata[oldKey].Fields.Field.filter( + (field) => field.ObjectID && field.ObjectID !== '' + ); + // convert existing fields obj into array and sort + /** @type {DataExtensionFieldItem[]} */ + const finalFieldsArr = Object.keys(existingFields) + .map((el) => { + /** @type {DataExtensionFieldItem} */ + const existingField = existingFields[el]; + // check if the current field was updated and then override with it. otherwise use existing value + const field = + updatedFieldsArr.find( + (field) => field.ObjectID === existingField.ObjectID + ) || existingField; + // field does not have a ordinal value because we rely on array order + field.Ordinal = existingField.Ordinal; + // updating FieldType is not supported by API and hence removed + field.FieldType = existingField.FieldType; + return field; + }) + .toSorted((a, b) => a.Ordinal - b.Ordinal); + + // get list of new fields + /** @type {DataExtensionFieldItem[]} */ // @ts-ignore Fields.Field is a special case that cannot be properly typed; only required for SOAP API + const newFieldsArr = originalMetadata[oldKey].Fields.Field.filter( + (field) => !field.ObjectID + ); + // push new fields to end of list + if (newFieldsArr.length) { + finalFieldsArr.push(...newFieldsArr); + } + + // sort Fields entry to the end of the object for saving in .json + delete item.Fields; + item.Fields = finalFieldsArr; } - // sort Fields entry to the end of the object for saving in .json - const fieldsBackup = item.Fields; - delete item.Fields; - item.Fields = fieldsBackup; + } + // UPDATE + CREATE + for (const field of item.Fields) { + DataExtensionField.postRetrieveTasksDE(field); } } + await this.#fixShared(upsertedMetadata, originalMetadata, createdUpdated); } /** - * Retrieves dataExtension metadata. Afterwards starts retrieval of dataExtensionColumn metadata retrieval - * @param {string} retrieveDir Directory where retrieved metadata directory will be saved - * @param {string[]} [additionalFields] Returns specified fields even if their retrieve definition is not set to true - * @param {Util.BuObject} buObject properties for auth - * @param {void} [_] - - * @param {boolean} [isDeploy] used to signal that fields shall be retrieve in caching mode - * @returns {Promise<{metadata:DataExtensionMap,type:string}>} Promise of item map + * takes care of updating attribute groups on child BUs after an update to Shared DataExtensions + * helper for {@link DataExtension.postDeployTasks} + * fixes an issue where shared data extensions are not visible in data designer on child BU; SF known issue: https://issues.salesforce.com/#q=W-11031095 + * + * @param {DataExtensionMap} upsertedMetadata metadata mapped by their keyField + * @param {DataExtensionMap} originalMetadata metadata to be updated (contains additioanl fields) + * @param {{created: number, updated: number}} createdUpdated counter representing successful creates/updates + * @returns {Promise.<void>} - */ - static async retrieve(retrieveDir, additionalFields, buObject, _, isDeploy) { - let metadata = await this._retrieveAll(additionalFields); - // in case of cache dont get fields - if (isDeploy || (metadata && retrieveDir)) { - // get fields from API - const fieldsObj = await this._retrieveFields(null, additionalFields); - const fieldKeys = Object.keys(fieldsObj); - // add fields to corresponding DE - fieldKeys.forEach((key) => { - const field = fieldsObj[key]; - if (metadata[field?.DataExtension?.CustomerKey]) { - metadata[field.DataExtension.CustomerKey].Fields.push(field); - } else { - Util.logger.warn(`Issue retrieving data extension fields. key='${key}'`); + static async #fixShared(upsertedMetadata, originalMetadata, createdUpdated) { + if (this.buObject.eid !== this.buObject.mid) { + // only if we were executing a deploy on parent bu could we be deploying shared data extensions + Util.logger.debug(`Skipping fixShared logic because we are not executing on Parent BU`); + return; + } + if (createdUpdated.updated === 0) { + // only if updates were made could the issue in https://issues.salesforce.com/#q=W-11031095 affect data designer + Util.logger.debug(`Skipping fixShared logic because nothing was updated`); + return; + } + + // find all shared data extensions + if (!this.deployedSharedKeys?.length) { + Util.logger.debug( + `Skipping fixShared logic because no Shared Data Extensions were updated` + ); + return; + } + + const sharedDataExtensionsKeys = this.deployedSharedKeys; + this.deployedSharedKeys = null; + + if (Util.OPTIONS.fixShared) { + // select which BUs to run this for + const selectedBuNames = await this.#fixShared_getBUs(); + + // backup settings + const buObjectBak = this.buObject; + const clientBak = this.client; + + // get dataExtension ID-Key relationship + /** @type {Object.<string, string>} */ + const sharedDataExtensionMap = {}; + for (const key of sharedDataExtensionsKeys) { + try { + const id = cache.searchForField( + 'dataExtension', + key, + 'CustomerKey', + 'ObjectID', + this.buObject.eid + ); + sharedDataExtensionMap[id] = key; + } catch { + continue; } - }); + } + + // run the fix-data-model logic + Util.logger.info( + `Fixing Shared Data Extensions details in data models of child BUs` + + Util.getKeysString(sharedDataExtensionsKeys) + ); - // sort fields by Ordinal value (API returns field unsorted) - for (const metadataEntry in metadata) { - metadata[metadataEntry].Fields.sort(DataExtensionField.sortDeFields); + for (const buName of selectedBuNames) { + await this.#fixShared_onBU(buName, buObjectBak, clientBak, sharedDataExtensionMap); } + Util.logger.info(`Finished fixing Shared Data Extensions details in data models`); - // remove attributes that we do not want to retrieve - // * do this after sorting on the DE's field list - fieldKeys.forEach((key) => { - DataExtensionField.postRetrieveTasks(fieldsObj[key], true); - }); + // restore settings + this.buObject = buObjectBak; + this.client = clientBak; + } else { + Util.logger.warn( + 'Shared Data Extensions were updated but --fixShared option is not set. This can result in your changes not being visible in attribute groups on child BUs.' + ); + Util.logger.info( + 'We recommend to re-run your deployment with the --fixShared option unless you are sure your Shared Data Extension is not used in attribute groups on any child BU.' + ); } - if (!retrieveDir && buObject.eid !== buObject.mid) { - // for caching, we want to retrieve shared DEs as well from the instance parent BU - Util.logger.info('- Caching dependent Metadata: dataExtension (shared via _ParentBU_)'); - /** @type {Util.BuObject} */ - const buObjectParentBu = { - clientId: this.properties.credentials[buObject.credential].clientId, - clientSecret: this.properties.credentials[buObject.credential].clientSecret, - tenant: this.properties.credentials[buObject.credential].tenant, - eid: this.properties.credentials[buObject.credential].eid, - mid: this.properties.credentials[buObject.credential].eid, - businessUnit: Util.parentBuName, - credential: buObject.credential, - }; - const clientBackup = this.client; - try { - this.client = await Util.getETClient(buObjectParentBu); - } catch (ex) { - Util.logger.error(ex.message); - return; + } + + /** + * helper for {@link DataExtension.#fixShared} + * + * @returns {Promise.<string[]>} list of selected BU names + */ + static async #fixShared_getBUs() { + const buListObj = this.properties.credentials[this.buObject.credential].businessUnits; + const fixBuPreselected = []; + const availableBuNames = Object.keys(buListObj).filter( + (buName) => buName !== Util.parentBuName + ); + if (typeof Util.OPTIONS.fixShared === 'string') { + if (Util.OPTIONS.fixShared === '*') { + // pre-select all BUs + fixBuPreselected.push(...availableBuNames); + } else { + // pre-select BUs from comma-separated list + fixBuPreselected.push( + ...Util.OPTIONS.fixShared + .split(',') + .filter(Boolean) + .map((bu) => bu.trim()) + .filter((bu) => availableBuNames.includes(bu)) + ); } - const metadataParentBu = await this._retrieveAll(additionalFields); - - // get shared folders to match our shared / synched Data Extensions - Util.logger.info('- Caching dependent Metadata: folder (shared via _ParentBU_)'); - Folder.cache = {}; - Folder.client = this.client; - Folder.properties = this.properties; - const result = await Folder.retrieveForCache(buObjectParentBu); - const parentCache = { - folder: result.metadata, - }; + } + if (Util.skipInteraction && fixBuPreselected.length) { + // assume programmatic use case or user that wants to skip the wizard. Use pre-selected BUs + return fixBuPreselected; + } - // get the types and clean out non-shared ones - const folderTypesFromParent = require('../MetadataTypeDefinitions').folder - .folderTypesFromParent; - for (const metadataEntry in metadataParentBu) { - try { - // get the data extension type from the folder - const folderContentType = Util.getFromCache( - parentCache, - 'folder', - metadataParentBu[metadataEntry].CategoryID, - 'ID', - 'ContentType' + const buList = availableBuNames.map((name) => ({ + name, + value: name, + checked: fixBuPreselected.includes(name), + })); + let answer = null; + + try { + answer = await checkbox({ + message: + 'Please select BUs that have access to the updated Shared Data Extensions:', + pageSize: 10, + choices: buList, + }); + } catch (ex) { + Util.logger.info(ex); + } + return answer; + } + + /** + * helper for {@link DataExtension.#fixShared} + * + * @param {string} childBuName name of child BU to fix + * @param {BuObject} buObjectParent bu object for parent BU + * @param {object} clientParent SDK for parent BU + * @param {Object.<string, string>} sharedDataExtensionMap ID-Key relationship of shared data extensions + * @returns {Promise.<string[]>} updated shared DE keys on BU + */ + static async #fixShared_onBU( + childBuName, + buObjectParent, + clientParent, + sharedDataExtensionMap + ) { + /** @type {BuObject} */ + const buObjectChildBu = { + eid: this.properties.credentials[buObjectParent.credential].eid, + mid: this.properties.credentials[buObjectParent.credential].businessUnits[childBuName], + businessUnit: childBuName, + credential: this.buObject.credential, + }; + const clientChildBu = auth.getSDK(buObjectChildBu); + + try { + // check if shared data Extension is used in an attributeSet on current BU + AttributeSet.properties = this.properties; + AttributeSet.buObject = buObjectChildBu; + AttributeSet.client = clientChildBu; + const sharedDeIdsUsedOnBU = await AttributeSet.fixShared_retrieve( + sharedDataExtensionMap, + DataExtensionField.fixShared_fields + ); + if (sharedDeIdsUsedOnBU.length) { + let sharedDataExtensionsKeys = sharedDeIdsUsedOnBU.map( + (deId) => sharedDataExtensionMap[deId] + ); + Util.logger.info( + ` - Fixing dataExtensions on BU ${childBuName} ` + + Util.getKeysString(sharedDataExtensionsKeys) + ); + + for (const deId of sharedDeIdsUsedOnBU) { + // dont use Promise.all to ensure order of execution; otherwise, switched BU contexts in one step will affect the next + const fixed = await this.#fixShared_item( + deId, + sharedDataExtensionMap[deId], + buObjectChildBu, + clientChildBu, + buObjectParent, + clientParent ); - if (!folderTypesFromParent.includes(folderContentType)) { - Util.logger.verbose( - `removing ${metadataEntry} because r__folder_ContentType '${folderContentType}' identifies this DE as not being shared` + if (!fixed) { + // remove from list of shared DEs that were fixed + sharedDataExtensionsKeys = sharedDataExtensionsKeys.filter( + (key) => key !== sharedDataExtensionMap[deId] ); - delete metadataParentBu[metadataEntry]; } - } catch (ex) { + } + if (sharedDataExtensionsKeys.length) { Util.logger.debug( - `removing ${metadataEntry} because of error while retrieving r__folder_ContentType: ${ex.message}` + ` - Fixed ${sharedDataExtensionsKeys.length}/${ + sharedDeIdsUsedOnBU.length + }: ${sharedDataExtensionsKeys.join(', ')}` ); - delete metadataParentBu[metadataEntry]; } + return sharedDataExtensionsKeys; + } else { + Util.logger.info( + Util.getGrayMsg( + ` - No matching attributeSet found for given Shared Data Extensions keys found on BU ${childBuName}` + ) + ); + return []; } + } catch (ex) { + Util.logger.error(ex.message); + return []; + } + } - // revert client to current default - this.client = clientBackup; - Folder.client = clientBackup; - Folder.cache = this.cache; + /** + * method that actually takes care of triggering the update for a particular BU-sharedDe combo + * helper for {@link DataExtension.#fixShared_onBU} + * + * @param {string} deId data extension ObjectID + * @param {string} deKey dataExtension key + * @param {BuObject} buObjectChildBu BU object for Child BU + * @param {object} clientChildBu SDK for child BU + * @param {BuObject} buObjectParent BU object for Parent BU + * @param {object} clientParent SDK for parent BU + * @returns {Promise.<boolean>} flag that signals if the fix was successful + */ + static async #fixShared_item( + deId, + deKey, + buObjectChildBu, + clientChildBu, + buObjectParent, + clientParent + ) { + try { + // add field via child BU + const randomSuffix = await DataExtension.#fixShared_item_addField( + buObjectChildBu, + clientChildBu, + deKey, + deId + ); - // make sure to overwrite parent bu DEs with local ones - metadata = { ...metadataParentBu, ...metadata }; + // get field ID from parent BU (it is not returned on child BU) + const fieldObjectID = await DataExtension.#fixShared_item_getFieldId( + randomSuffix, + buObjectParent, + clientParent, + deKey + ); + + // delete field via child BU + await DataExtension.#fixShared_item_deleteField( + randomSuffix, + buObjectChildBu, + clientChildBu, + deKey, + fieldObjectID + ); + + Util.logger.info( + ` - Fixed dataExtension ${deKey} on BU ${buObjectChildBu.businessUnit}` + ); + + return true; + } catch (ex) { + Util.logger.error( + `- error fixing dataExtension ${deKey} on BU ${buObjectChildBu.businessUnit}: ${ex.message}` + ); + return false; } + } + /** + * add a new field to the shared DE to trigger an update to the data model + * helper for {@link DataExtension.#fixShared_item} + * + * @param {BuObject} buObjectChildBu BU object for Child BU + * @param {object} clientChildBu SDK for child BU + * @param {string} deKey dataExtension key + * @param {string} deId dataExtension ObjectID + * @returns {Promise.<string>} randomSuffix + */ + static async #fixShared_item_addField(buObjectChildBu, clientChildBu, deKey, deId) { + this.buObject = buObjectChildBu; + this.client = clientChildBu; + const randomSuffix = Util.OPTIONS._runningTest + ? '_randomNumber_' + : Math.floor(Math.random() * 9999999999).toString(); + // add a new field to the shared DE to trigger an update to the data model + const soapType = this.definition.soapType || this.definition.type; + const payload = { + CustomerKey: deKey, + ObjectID: deId, + Fields: { + Field: [ + { + Name: 'TriggerUpdate' + randomSuffix, + IsRequired: false, + IsPrimaryKey: false, + FieldType: 'Boolean', + ObjectID: null, + }, + ], + }, + }; + await this.client.soap.update(Util.capitalizeFirstLetter(soapType), payload, null); + return randomSuffix; + } + + /** + * get ID of the field added by {@link DataExtension.#fixShared_item_addField} on the shared DE via parent BU + * helper for {@link DataExtension.#fixShared_item} + * + * @param {string} randomSuffix - + * @param {BuObject} buObjectParent BU object for Parent BU + * @param {object} clientParent SDK for parent BU + * @param {string} deKey dataExtension key + * @returns {Promise.<string>} fieldObjectID + */ + static async #fixShared_item_getFieldId(randomSuffix, buObjectParent, clientParent, deKey) { + DataExtensionField.buObject = buObjectParent; + DataExtensionField.client = clientParent; + const fieldKey = `[${deKey}].[TriggerUpdate${randomSuffix}]`; + const fieldResponse = await DataExtensionField.retrieveForCacheDE( + { + filter: { + leftOperand: 'CustomerKey', + operator: 'equals', + rightOperand: fieldKey, + }, + }, + ['Name', 'ObjectID'] + ); + const fieldObjectID = fieldResponse.metadata[fieldKey]?.ObjectID; + return fieldObjectID; + } + + /** + * delete the field added by {@link DataExtension.#fixShared_item_addField} + * helper for {@link DataExtension.#fixShared_item} + * + * @param {string} randomSuffix - + * @param {BuObject} buObjectChildBu BU object for Child BU + * @param {object} clientChildBu SDK for child BU + * @param {string} deKey dataExtension key + * @param {string} fieldObjectID field ObjectID + * @returns {Promise} - + */ + static async #fixShared_item_deleteField( + randomSuffix, + buObjectChildBu, + clientChildBu, + deKey, + fieldObjectID + ) { + DataExtensionField.buObject = buObjectChildBu; + DataExtensionField.client = clientChildBu; + await DataExtensionField.deleteByKeySOAP( + deKey + '.TriggerUpdate' + randomSuffix, + fieldObjectID + ); + } + + /** + * Retrieves dataExtension metadata. Afterwards starts retrieval of dataExtensionColumn metadata retrieval + * + * @param {string} retrieveDir Directory where retrieved metadata directory will be saved + * @param {string[]} [additionalFields] Returns specified fields even if their retrieve definition is not set to true + * @param {void | string[]} [_] unused parameter + * @param {string} [key] customer key of single item to retrieve + * @returns {Promise.<{metadata: DataExtensionMap, type: string}>} Promise of item map + */ + static async retrieve(retrieveDir, additionalFields, _, key) { + /** @type {SoapRequestParams} */ + let requestParams = null; + /** @type {SoapRequestParams} */ + let fieldOptions = null; + if (key) { + requestParams = { + filter: { + leftOperand: 'CustomerKey', + operator: 'equals', + rightOperand: key, + }, + }; + fieldOptions = { + filter: { + leftOperand: 'DataExtension.CustomerKey', + operator: 'equals', + rightOperand: key, + }, + }; + } + let metadataMap = await this._retrieveAll(additionalFields, requestParams); + // in case of cache dont get fields + if (metadataMap && retrieveDir) { + // get fields from API + await this.attachFields(metadataMap, fieldOptions, additionalFields); + } + if (!retrieveDir && this.buObject.eid !== this.buObject.mid) { + const metadataParentBu = await this.retrieveSharedForCache(additionalFields); + + // make sure to overwrite parent bu DEs with local ones + metadataMap = { ...metadataParentBu, ...metadataMap }; + } if (retrieveDir) { - const savedMetadata = await this.saveResults(metadata, retrieveDir, null); + const savedMetadata = await super.saveResults(metadataMap, retrieveDir, null); Util.logger.info( - `Downloaded: ${this.definition.type} (${Object.keys(savedMetadata).length})` + `Downloaded: ${this.definition.type} (${Object.keys(savedMetadata).length})` + + Util.getKeysString(key) ); - if (this.properties.metaDataTypes.documentOnRetrieve.includes(this.definition.type)) { - await this.document(buObject, savedMetadata); + if (Object.keys(savedMetadata).length > 0) { + await this.runDocumentOnRetrieve(key, savedMetadata); + } else if (key) { + this.postDeleteTasks(key); } } - return { metadata: metadata, type: 'dataExtension' }; + return { metadata: metadataMap, type: 'dataExtension' }; + } + + /** + * get shared dataExtensions from parent BU and merge them into the cache + * helper for {@link DataExtension.retrieve} and for AttributeSet.fixShared_retrieve + * + * @param {string[]} [additionalFields] Returns specified fields even if their retrieve definition is not set to true + * @returns {Promise.<DataExtensionMap>} keyField => metadata map + */ + static async retrieveSharedForCache(additionalFields = []) { + // for caching, we want to retrieve shared DEs as well from the instance parent BU + Util.logger.info(' - Caching dependent Metadata: dataExtension (shared via _ParentBU_)'); + const buObjectBak = this.buObject; + const clientBak = this.client; + /** @type {BuObject} */ + const buObjectParentBu = { + eid: this.properties.credentials[this.buObject.credential].eid, + mid: this.properties.credentials[this.buObject.credential].eid, + businessUnit: Util.parentBuName, + credential: this.buObject.credential, + }; + try { + this.buObject = buObjectParentBu; + this.client = auth.getSDK(buObjectParentBu); + } catch (ex) { + Util.logger.error(ex.message); + return; + } + const metadataParentBu = await this._retrieveAll(additionalFields); + + // get shared folders to match our shared / synched Data Extensions + const subTypeArr = this.definition.dependencies + .filter((item) => item.startsWith('folder-')) + .map((item) => item.slice(7)) + .filter((item) => Folder.definition.folderTypesFromParent.includes(item)); + Util.logger.info(' - Caching dependent Metadata: folder (shared via _ParentBU_)'); + Util.logSubtypes(subTypeArr, ' '); + Folder.client = this.client; + Folder.buObject = this.buObject; + Folder.properties = this.properties; + const result = await Folder.retrieveForCache(null, subTypeArr); + cache.mergeMetadata('folder', result.metadata, this.buObject.eid); + + // get the types and clean out non-shared ones + const folderTypesFromParent = MetadataTypeDefinitions.folder.folderTypesFromParent; + for (const metadataEntry in metadataParentBu) { + try { + // get the data extension type from the folder + const folderContentType = cache.searchForField( + 'folder', + metadataParentBu[metadataEntry].CategoryID, + 'ID', + 'ContentType', + this.buObject.eid + ); + if (!folderTypesFromParent.includes(folderContentType)) { + // Util.logger.verbose( + // `removing ${metadataEntry} because r__folder_ContentType '${folderContentType}' identifies this DE as not being shared` + // ); + delete metadataParentBu[metadataEntry]; + } + } catch (ex) { + Util.logger.debug( + `removing dataExtension ${metadataEntry} because of error while retrieving r__folder_ContentType: ${ex.message}` + ); + delete metadataParentBu[metadataEntry]; + } + } + + // revert client to current default + this.client = clientBak; + this.buObject = buObjectBak; + Folder.client = clientBak; + Folder.buObject = buObjectBak; + + return metadataParentBu; + } + + /** + * helper to retrieve all dataExtension fields and attach them to the dataExtension metadata + * + * @param {DataExtensionMap} metadata already cached dataExtension metadata + * @param {SoapRequestParams} [fieldOptions] optionally filter results + * @param {string[]} [additionalFields] Returns specified fields even if their retrieve definition is not set to true + * @returns {Promise.<void>} - + */ + static async attachFields(metadata, fieldOptions, additionalFields) { + const fieldsObj = await this._retrieveFields(fieldOptions, additionalFields); + const fieldKeys = Object.keys(fieldsObj); + + // add fields to corresponding DE + for (const key of fieldKeys) { + const field = fieldsObj[key]; + if (metadata[field?.DataExtension?.CustomerKey]) { + metadata[field.DataExtension.CustomerKey].Fields.push(field); + } else { + // field was retrieved for which we do not have the right dataExtension. This might be due to us having to resort to not using a DE filter to avoid the "String or binary data would be truncated." error + } + } + + // sort fields by Ordinal value (API returns field unsorted) + for (const metadataEntry in metadata) { + metadata[metadataEntry].Fields.sort(DataExtensionField.sortDeFields); + } + + // remove attributes that we do not want to retrieve + // * do this after sorting on the DE's field list + for (const key of fieldKeys) { + DataExtensionField.postRetrieveTasksDE(fieldsObj[key]); + } } + /** * Retrieves dataExtension metadata. Afterwards starts retrieval of dataExtensionColumn metadata retrieval + * * @param {string[]} [additionalFields] Returns specified fields even if their retrieve definition is not set to true - * @returns {Promise<{metadata:DataExtensionMap,type:string}>} Promise of item map + * @returns {Promise.<{metadata: DataExtensionMap, type: string}>} Promise of item map */ static async retrieveChangelog(additionalFields) { const metadata = await this._retrieveAll(additionalFields); return { metadata: metadata, type: 'dataExtension' }; } + /** * manages post retrieve steps + * * @param {DataExtensionItem} metadata a single dataExtension - * @param {string} [_] unused - * @param {boolean} [isTemplating] signals that we are retrieving templates - * @returns {DataExtensionItem} metadata + * @returns {Promise.<DataExtensionItem>} metadata */ - static async postRetrieveTasks(metadata, _, isTemplating) { - if (!metadata.Fields || !metadata.Fields.length) { - // assume we were in deploy mode. retrieve fields. - const tempList = {}; - tempList[metadata[this.definition.keyField]] = metadata; - await this._retrieveFieldsForSingleDe(tempList, metadata[this.definition.keyField]); - } - // if retrieving template, replace the name with customer key if that wasn't already the case - if (isTemplating) { - const warningMsg = - 'Ensure that Queries that write into this DE are updated with the new key before deployment.'; - this.overrideKeyWithName(metadata, warningMsg); - } + static async postRetrieveTasks(metadata) { // Error during deploy if SendableSubscriberField.Name = '_SubscriberKey' even though it is retrieved like that // Therefore map it to 'Subscriber Key'. Retrieving afterward still results in '_SubscriberKey' + if (metadata.SendableSubscriberField?.Name === '_SubscriberKey') { + metadata.SendableSubscriberField.Name = 'Subscriber Key'; + } + this.setFolderPath(metadata); + + // DataExtensionTemplate + if (metadata.Template?.CustomerKey) { + try { + metadata.r__dataExtensionTemplate_name = cache.searchForField( + 'dataExtensionTemplate', + metadata.Template.CustomerKey, + 'CustomerKey', + 'Name' + ); + delete metadata.Template; + } catch (ex) { + Util.logger.debug(ex.message); + // Let's allow retrieving such DEs but warn that they cannot be deployed to another BU. + // Deploying to same BU still works! + // A workaround exists but it's likely not beneficial to explain to users: + // Create a DE based on the not-supported template on the target BU, retrieve it, copy the Template.CustomerKey into the to-be-deployed DE (or use mcdev-templating), done + Util.logger.warn( + ` - Issue with dataExtension '${ + metadata[this.definition.nameField] + }': Could not find specified DataExtension Template. Please note that DataExtensions based on SMSMessageTracking and SMSSubscriptionLog cannot be deployed automatically across BUs at this point.` + ); + } + } + // remove the date fields manually here because we need them in the changelog but not in the saved json + delete metadata.CreatedDate; + delete metadata.ModifiedDate; + + // Retention policy if ( - metadata.SendableSubscriberField && - metadata.SendableSubscriberField.Name === '_SubscriberKey' + metadata.RowBasedRetention === false && + metadata.DeleteAtEndOfRetentionPeriod === false && + metadata.RetainUntil === '' ) { - metadata.SendableSubscriberField.Name = 'Subscriber Key'; + // Note: RetainUntil expected to NOT have a value + metadata.c__retentionPolicy = 'none'; + delete metadata.RetainUntil; + delete metadata.ResetRetentionPeriodOnImport; + } else if ( + metadata.RowBasedRetention === false && + metadata.DeleteAtEndOfRetentionPeriod === false + ) { + // Note: RetainUntil expected to have a value + metadata.c__retentionPolicy = 'allRecordsAndDataextension'; + } else if ( + metadata.RowBasedRetention === false && + metadata.DeleteAtEndOfRetentionPeriod === true + ) { + // Note: RetainUntil expected to have a value + metadata.c__retentionPolicy = 'allRecords'; + } else if ( + metadata.RowBasedRetention === true && + metadata.DeleteAtEndOfRetentionPeriod === false + ) { + // Note: RetainUntil expected to NOT have a value + metadata.c__retentionPolicy = 'individialRecords'; + delete metadata.RetainUntil; + } + delete metadata.RowBasedRetention; + delete metadata.DeleteAtEndOfRetentionPeriod; + + if (metadata.RetainUntil) { + const retainUntil = new Date(metadata.RetainUntil); + metadata.c__retainUntil = `${retainUntil.getFullYear()}-${retainUntil.getMonth() + 1}-${retainUntil.getDate()}`; } - return this._parseMetadata(JSON.parse(JSON.stringify(metadata))); + delete metadata.RetainUntil; + if (metadata.DataRetentionPeriodUnitOfMeasure) { + metadata.c__dataRetentionPeriodUnitOfMeasure = Util.inverseGet( + this.definition.dataRetentionPeriodUnitOfMeasureMapping, + metadata.DataRetentionPeriodUnitOfMeasure + ); + delete metadata.DataRetentionPeriodUnitOfMeasure; + } + + return metadata; } /** * Helper to retrieve Data Extension Fields + * * @private - * @param {Object} [options] options (e.g. continueRequest) + * @param {SoapRequestParams} [options] options (e.g. continueRequest) * @param {string[]} [additionalFields] Returns specified fields even if their retrieve definition is not set to true - * @returns {Promise<DataExtensionField.DataExtensionFieldMap>} Promise of items + * @returns {Promise.<DataExtensionFieldMap>} Promise of items */ static async _retrieveFields(options, additionalFields) { if (!options) { // dont print this during updates or templating which retrieves fields DE-by-DE - Util.logger.info('- Caching dependent Metadata: dataExtensionField'); + Util.logger.info(' - Caching dependent Metadata: dataExtensionField'); } - DataExtensionField.cache = this.metadata; DataExtensionField.client = this.client; DataExtensionField.properties = this.properties; - const response = await DataExtensionField.retrieveForCache(options, additionalFields); + const response = await DataExtensionField.retrieveForCacheDE(options, additionalFields); return response.metadata; } + /** * helps retrieving fields during templating and deploy where we dont want the full list + * * @private * @param {DataExtensionMap} metadata list of DEs * @param {string} customerKey external key of single DE - * @returns {Promise<void>} updates are made directly to `metadata` + * @returns {Promise.<void>} - */ static async _retrieveFieldsForSingleDe(metadata, customerKey) { + /** @type {SoapRequestParams} */ const fieldOptions = { filter: { leftOperand: 'DataExtension.CustomerKey', @@ -470,41 +1041,64 @@ class DataExtension extends MetadataType { }; const fieldsObj = await this._retrieveFields(fieldOptions); - DataExtensionField.cache = this.metadata; DataExtensionField.client = this.client; DataExtensionField.properties = this.properties; const fieldArr = DataExtensionField.convertToSortedArray(fieldsObj); // remove attributes that we do not want to retrieve // * do this after sorting on the DE's field list - fieldArr.forEach((field) => { - DataExtensionField.postRetrieveTasks(field, true); - }); + for (const field of fieldArr) { + DataExtensionField.postRetrieveTasksDE(field); + } metadata[customerKey].Fields = fieldArr; } + /** + * helper for {@link MetadataType.updateREST} and {@link MetadataType.updateSOAP} that removes old files after the key was changed + * + * @param {MetadataTypeItem} metadataEntry a single metadata Entry + * @returns {Promise.<void>} - + */ + static async _postChangeKeyTasks(metadataEntry) { + return super._postChangeKeyTasks(metadataEntry, true); + } + /** * prepares a DataExtension for deployment + * * @param {DataExtensionItem} metadata a single data Extension - * @returns {Promise<DataExtensionItem>} Promise of updated single DE + * @returns {Promise.<DataExtensionItem>} Promise of updated single DE */ static async preDeployTasks(metadata) { + if (metadata.Name?.startsWith('_')) { + throw new Error(`Cannot Upsert Strongly Typed Data Extensions`); + } + if ( + !Util.OPTIONS._fixSharedOnBu && + this.buObject.eid !== this.buObject.mid && + metadata.r__folder_Path?.startsWith('Shared Items') + ) { + throw new Error(`Cannot Create/Update a Shared Data Extension from the Child BU`); + } + if (metadata.r__folder_ContentType === 'shared_dataextension') { + this.deployedSharedKeys ||= []; + this.deployedSharedKeys.push(metadata.CustomerKey); + } + if (metadata.r__folder_Path?.startsWith('Synchronized Data Extensions')) { + throw new Error( + `Cannot Create/Update a Synchronized Data Extension. Please use Contact Builder to maintain these` + ); + } + // folder - metadata.CategoryID = Util.getFromCache( - this.cache, - 'folder', - metadata.r__folder_Path, - 'Path', - 'ID' - ); - delete metadata.r__folder_Path; + super.setFolderId(metadata); // DataExtensionTemplate - if (metadata.r__dataExtensionTemplate_Name) { + if (metadata.r__dataExtensionTemplate_name) { // remove templated fields for (const templateField of this.definition.templateFields[ - metadata.r__dataExtensionTemplate_Name + metadata.r__dataExtensionTemplate_name ]) { for (let index = 0; index < metadata.Fields.length; index++) { const element = metadata.Fields[index]; @@ -519,25 +1113,23 @@ class DataExtension extends MetadataType { // get template's CustomerKey try { metadata.Template = { - CustomerKey: Util.getFromCache( - this.cache, + CustomerKey: cache.searchForField( 'dataExtensionTemplate', - metadata.r__dataExtensionTemplate_Name, + metadata.r__dataExtensionTemplate_name, 'Name', 'CustomerKey' ), }; - delete metadata.r__dataExtensionTemplate_Name; + delete metadata.r__dataExtensionTemplate_name; } catch (ex) { Util.logger.debug(ex.message); - // It is assumed that non-supported types would not have been converted to r__dataExtensionTemplate_Name upon retrieve. + // It is assumed that non-supported types would not have been converted to r__dataExtensionTemplate_name upon retrieve. // Deploying to same BU therefore still works! // A workaround for cross-BU deploy exists but it's likely not beneficial to explain to users: // Create a DE based on the not-supported template on the target BU, retrieve it, copy the Template.CustomerKey into the to-be-deployed DE (or use mcdev-templating), done throw new Error( - `Skipping DataExtension '${ - metadata[this.definition.nameField] - }': Could not find specified DataExtension Template. Please note that DataExtensions based on SMSMessageTracking and SMSSubscriptionLog cannot be deployed automatically across BUs at this point.` + `Could not find specified DataExtension Template. Please note that DataExtensions based on SMSMessageTracking and SMSSubscriptionLog cannot be deployed automatically across BUs at this point.`, + { cause: ex } ); } } @@ -555,15 +1147,65 @@ class DataExtension extends MetadataType { metadata.SendableSubscriberField.Name = 'Subscriber Key'; } + // Retention policy + switch (metadata.c__retentionPolicy) { + case 'none': { + metadata.RowBasedRetention = false; + metadata.DeleteAtEndOfRetentionPeriod = false; + metadata.ResetRetentionPeriodOnImport = false; + break; + } + case 'allRecordsAndDataextension': { + metadata.RowBasedRetention = false; + metadata.DeleteAtEndOfRetentionPeriod = false; + break; + } + case 'allRecords': { + metadata.RowBasedRetention = false; + metadata.DeleteAtEndOfRetentionPeriod = true; + break; + } + case 'individialRecords': { + metadata.RowBasedRetention = true; + metadata.DeleteAtEndOfRetentionPeriod = false; + break; + } + default: { + Util.logger.debug( + ` - dataExtension '${ + metadata[this.definition.nameField] + }': Unknown retention policy: ${metadata.c__retentionPolicy}` + ); + } + } + delete metadata.c__retentionPolicy; + + if (metadata.c__retainUntil) { + const retainUntil = new Date(metadata.c__retainUntil); + metadata.RetainUntil = `${retainUntil.getMonth() + 1}/${retainUntil.getDate()}/${retainUntil.getFullYear()} 12:00:00 AM`; + delete metadata.c__retainUntil; + } else { + metadata.RetainUntil = ''; + } + + if (metadata.c__dataRetentionPeriodUnitOfMeasure) { + metadata.DataRetentionPeriodUnitOfMeasure = + this.definition.dataRetentionPeriodUnitOfMeasureMapping[ + metadata.c__dataRetentionPeriodUnitOfMeasure + ]; + delete metadata.c__dataRetentionPeriodUnitOfMeasure; + } + return metadata; } /** * Saves json content to a html table in the local file system. Will create the parent directory if it does not exist. * The json's first level of keys must represent the rows and the secend level the columns + * * @private * @param {DataExtensionItem} json single dataextension - * @param {Array} tabled prepped array for output in tabular format + * @param {object[][]} tabled prepped array for output in tabular format * @returns {string} file content */ static _generateDocHtml(json, tabled) { @@ -577,37 +1219,34 @@ class DataExtension extends MetadataType { output += `<p><b>Description:</b> ${json.Description || 'n/a'}</p>`; output += `<p><b>Folder:</b> ${ - json.r__folder_Path - ? json.r__folder_Path - : '<i>Hidden! Could not find folder with ID ' + json.CategoryID + '</i>' + json.r__folder_Path || + '<i>Hidden! Could not find folder with ID ' + json.CategoryID + '</i>' }</p>`; output += `<p><b>Fields in table:</b> ${tabled.length - 1}</p>`; output += '<p><b>Sendable:</b> '; - if (json.IsSendable === 'true') { - output += - 'Yes (<i>' + - json.SendableDataExtensionField.Name + - '</i> to <i>' + - json.SendableSubscriberField.Name + - '</i>)</p>\n\n'; - } else { - output += `No</p>\n\n`; - } - output += `<p><b>Testable:</b> ${json.IsTestable === 'true' ? 'Yes' : 'No'}</p>\n\n`; - if (json.r__dataExtensionTemplate_Name) { - output += `<p><b>Template:</b> ${json.r__dataExtensionTemplate_Name}</p>`; + output += + json.IsSendable === true + ? 'Yes (<i>' + + json.SendableDataExtensionField.Name + + '</i> to <i>' + + json.SendableSubscriberField.Name + + '</i>)</p>\n\n' + : `No</p>\n\n`; + output += `<p><b>Testable:</b> ${json.IsTestable === true ? 'Yes' : 'No'}</p>\n\n`; + if (json.r__dataExtensionTemplate_name) { + output += `<p><b>Template:</b> ${json.r__dataExtensionTemplate_name}</p>`; } output += '<table><thead><tr>'; - tabled[0].forEach((element) => { + for (const element of tabled[0]) { output += '<th>' + element + '</th>'; - }); + } output += '</tr><thead><tbody>'; for (let i = 1; i < tabled.length; i++) { output += '<tr>'; - tabled[i].forEach((field) => { + for (const field of tabled[i]) { output += `<td>${field}</td>`; - }); + } output += '</tr>'; } output += '</tbody></table>'; @@ -618,9 +1257,10 @@ class DataExtension extends MetadataType { * Experimental: Only working for DataExtensions: * Saves json content to a html table in the local file system. Will create the parent directory if it does not exist. * The json's first level of keys must represent the rows and the secend level the columns + * * @private * @param {DataExtensionItem} json dataextension - * @param {Array} tabled prepped array for output in tabular format + * @param {object[][]} tabled prepped array for output in tabular format * @returns {string} file content */ static _generateDocMd(json, tabled) { @@ -632,37 +1272,63 @@ class DataExtension extends MetadataType { output += `**Description:** ${json.Description || 'n/a'}\n\n` + `**Folder:** ${ - json.r__folder_Path - ? json.r__folder_Path - : '_Hidden! Could not find folder with ID ' + json.CategoryID + '_' + json.r__folder_Path || + '_Hidden! Could not find folder with ID ' + json.CategoryID + '_' }/\n\n` + `**Fields in table:** ${tabled.length - 1}\n\n`; output += '**Sendable:** '; - if (json.IsSendable === 'true') { - output += - 'Yes (`' + - json.SendableDataExtensionField.Name + - '` to `' + - json.SendableSubscriberField.Name + - '`)\n\n'; - } else { - output += `No\n\n`; + output += + json.IsSendable === true + ? 'Yes (`' + + json.SendableDataExtensionField.Name + + '` to `' + + json.SendableSubscriberField.Name + + '`)\n\n' + : `No\n\n`; + output += `**Testable:** ${json.IsTestable === true ? 'Yes' : 'No'}\n\n`; + if (json.r__dataExtensionTemplate_name) { + output += `**Template:** ${json.r__dataExtensionTemplate_name}\n\n`; } - output += `**Testable:** ${json.IsTestable === 'true' ? 'Yes' : 'No'}\n\n`; - if (json.r__dataExtensionTemplate_Name) { - output += `**Template:** ${json.r__dataExtensionTemplate_Name}\n\n`; + // Retention + output += `**Retention Policy:** ${json.c__retentionPolicy}\n\n`; + switch (json.c__retentionPolicy) { + case 'allRecords': + case 'allRecordsAndDataextension': { + if (json.DataRetentionPeriodLength) { + // if period length was selected, show it plus the optional reset-on-import; the retain-until date IS returned by the api but does not matter for documentation + output += `- **Retention Period:** ${json.DataRetentionPeriodLength} ${json.c__dataRetentionPeriodUnitOfMeasure}\n`; + output += `- **Reset Retention Period on import:** ${json.ResetRetentionPeriodOnImport ? 'yes' : 'no'}\n`; + } else { + // if a date was selected instead, the GUI auto-deselects reset-on-import + output += `- **Retain Until:** ${json.c__retainUntil}\n`; + } + // add empty line after retention: + output += `\n`; + break; + } + case 'individialRecords': { + output += `- **Retention Period:** ${json.DataRetentionPeriodLength} ${json.c__dataRetentionPeriodUnitOfMeasure}\n`; + output += `- **Reset Retention Period on import:** ${json.ResetRetentionPeriodOnImport ? 'yes' : 'no'}\n`; + // add empty line after retention: + output += `\n`; + break; + } + case 'none': { + // nothing else to do + break; + } } let tableSeparator = ''; - tabled[0].forEach((column) => { + for (const column of tabled[0]) { output += `| ${column} `; tableSeparator += '| --- '; - }); + } output += `|\n${tableSeparator}|\n`; for (let i = 1; i < tabled.length; i++) { - tabled[i].forEach((field) => { + for (const field of tabled[i]) { output += `| ${field} `; - }); + } output += '|\n'; } return output; @@ -671,28 +1337,32 @@ class DataExtension extends MetadataType { /** * Saves json content to a html table in the local file system. Will create the parent directory if it does not exist. * The json's first level of keys must represent the rows and the secend level the columns + * * @private * @param {string} directory directory the file will be written to * @param {string} filename name of the file without '.json' ending * @param {DataExtensionItem} json dataextension.columns * @param {'html'|'md'} mode html or md * @param {string[]} [fieldsToKeep] list of keys(columns) to show. This will also specify - * @returns {Promise<boolean>} Promise of success of saving the file + * @returns {Promise.<void>} Promise of success of saving the file */ static async _writeDoc(directory, filename, json, mode, fieldsToKeep) { - if (!File.existsSync(directory)) { - File.mkdirpSync(directory); - } let fieldsJson = Object.values(json.Fields); if (fieldsToKeep) { + /** @type {DataExtensionFieldItem[]} */ const newJson = []; - fieldsJson.forEach((element) => { + for (const element of fieldsJson) { const newJsonElement = {}; - fieldsToKeep.forEach((field) => { - newJsonElement[field] = element[field]; - }); + for (const field of fieldsToKeep) { + if (field === 'MaxLength' && element.FieldType === 'Decimal') { + newJsonElement.MaxLength = `${element.MaxLength},${element.Scale}`; + } else { + newJsonElement[field] = element[field]; + } + } + // @ts-ignore for document the fields have less values and that leads to an error here. newJson.push(newJsonElement); - }); + } fieldsJson = newJson; } const tabled = jsonToTable(fieldsJson); @@ -704,41 +1374,46 @@ class DataExtension extends MetadataType { } try { // write to disk - await File.writeToFile(directory, filename + '.dataExtension', mode, output); + await File.writeToFile(directory, filename + '.dataExtension-doc', mode, output); } catch (ex) { Util.logger.error(`DataExtension.writeDeToX(${mode}):: error | ` + ex.message); } } + /** * Parses metadata into a readable Markdown/HTML format then saves it - * @param {Util.BuObject} buObject properties for auth - * @param {DataExtensionMap} [metadata] a list of dataExtension definitions - * @param {boolean} [isDeploy] used to skip non-supported message during deploy - * @returns {Promise<void>} - + * + * @param {DataExtensionMap} [metadataMap] a list of dataExtension definitions + * @returns {Promise.<any>} - */ - static async document(buObject, metadata, isDeploy) { - if (!metadata) { - metadata = this.readBUMetadataForType( - File.normalizePath([ - this.properties.directories.retrieve, - buObject.credential, - buObject.businessUnit, - ]), - true - ).dataExtension; + static async document(metadataMap) { + try { + if (!metadataMap) { + metadataMap = ( + await this.readBUMetadataForType( + File.normalizePath([ + this.properties.directories.retrieve, + this.buObject.credential, + this.buObject.businessUnit, + ]), + true + ) + ).dataExtension; + } + } catch (ex) { + Util.logger.error(ex.message); + return; } const docPath = File.normalizePath([ - this.properties.directories.dataExtension, - buObject.credential, - buObject.businessUnit, + this.properties.directories.retrieve, + this.buObject.credential, + this.buObject.businessUnit, + this.definition.type, ]); - if (!metadata || !Object.keys(metadata).length) { + if (!metadataMap || !Object.keys(metadataMap).length) { // as part of retrieve & manual execution we could face an empty folder return; } - if (!isDeploy) { - File.removeSync(docPath); - } const columnsToIterateThrough = ['IsNullable', 'IsPrimaryKey']; const columnsToPrint = [ 'Name', @@ -748,130 +1423,93 @@ class DataExtension extends MetadataType { 'IsNullable', 'DefaultValue', ]; - for (const customerKey in metadata) { - if (metadata[customerKey].Fields && metadata[customerKey].Fields.length) { - metadata[customerKey].Fields.forEach((field) => { - field.IsNullable = (!(field.IsRequired === 'true')).toString(); - columnsToIterateThrough.forEach((key) => { - if (field[key] === 'true') { - field[key] = '+'; - } else if (field[key] === 'false') { - field[key] = '-'; + + const docLimit = pLimit(100); + + return Promise.all( + Object.keys(metadataMap).map((key) => { + if (metadataMap[key]?.Fields?.length) { + for (const field of metadataMap[key].Fields) { + field.IsNullable = !Util.isTrue(field.IsRequired); + for (const prop of columnsToIterateThrough) { + if (Util.isTrue(field[prop])) { + field[prop] = '+'; + } else if (Util.isFalse(field[prop])) { + field[prop] = '-'; + } } - }); - }); + } - if (['html', 'both'].includes(this.properties.options.documentType)) { - this._writeDoc( - docPath + '/', - customerKey, - metadata[customerKey], - 'html', - columnsToPrint - ); - } - if (['md', 'both'].includes(this.properties.options.documentType)) { - this._writeDoc( - docPath + '/', - customerKey, - metadata[customerKey], - 'md', - columnsToPrint - ); + if (['html', 'both'].includes(this.properties.options.documentType)) { + return docLimit(() => + this._writeDoc( + docPath + '/', + key, + metadataMap[key], + 'html', + columnsToPrint + ) + ); + } + if (['md', 'both'].includes(this.properties.options.documentType)) { + return docLimit(() => + this._writeDoc( + docPath + '/', + key, + metadataMap[key], + 'md', + columnsToPrint + ) + ); + } } - } - } - if (['html', 'both'].includes(this.properties.options.documentType)) { - Util.logger.info(`Created ${docPath}/*.dataExtension.html`); - } - if (['md', 'both'].includes(this.properties.options.documentType)) { - Util.logger.info(`Created ${docPath}/*.dataExtension.md`); - } + }) + ); } /** - * Delete a data extension from the specified business unit - * @param {Object} buObject references credentials + * Delete a metadata item from the specified business unit + * * @param {string} customerKey Identifier of data extension - * @returns {Promise<void>} - + * @returns {Promise.<boolean>} deletion success status */ - static async deleteByKey(buObject, customerKey) { - let client; - try { - client = await Util.getETClient(buObject); - } catch (ex) { - Util.logger.error(ex.message); - return; - } - const config = { - props: { CustomerKey: customerKey }, - }; + static deleteByKey(customerKey) { + return super.deleteByKeySOAP(customerKey, undefined, 310007); + } - client.dataExtension(config).delete((error, response) => { - if (error && error.results && error.results[0]) { - if (error.results[0].ErrorCode === '310007') { - Util.logger.error( - 'mcdev.deleteDE:: It seems the DataExtension you were trying to delete does not exist on the given BU or its External Key was changed.' - ); - } else { - Util.logger.error('mcdev.deleteDE:: ' + error.results[0].StatusMessage); - } - } else if (error) { - Util.logger.error('mcdev.deleteDE:: ' + JSON.stringify(error)); - } else if ( - response && - response.body && - response.body.Results && - response.body.Results[0] - ) { - Util.logger.info( - `mcdev.deleteDE:: Success: ${response.body.Results[0].StatusMessage} (${customerKey})` - ); - // delete local copy: retrieve/cred/bu/dataExtension/...json - const jsonFile = File.normalizePath([ - this.properties.directories.retrieve, - buObject.credential, - buObject.businessUnit, - this.definition.type, - `${customerKey}.${this.definition.type}-meta.json`, - ]); - if (File.existsSync(jsonFile)) { - File.unlinkSync(jsonFile); - } - // delete local copy: doc/dataExtension/cred/bu/...md - const mdFile = File.normalizePath([ - this.properties.directories.dataExtension, - buObject.credential, - buObject.businessUnit, - `${customerKey}.${this.definition.type}.md`, - ]); - if (File.existsSync(mdFile)) { - File.unlinkSync(mdFile); - } - } else { - Util.logger.info('mcdev.deleteDE:: Success: ' + JSON.stringify(response)); - } - }); + /** + * clean up after deleting a metadata item + * + * @param {string} customerKey Identifier of metadata item + * @returns {Promise.<void>} - promise + */ + static async postDeleteTasks(customerKey) { + // delete local copy: retrieve/cred/bu/dataExtension/...-meta.json + // delete local copy: doc/dataExtension/cred/bu/...md + await super.postDeleteTasks(customerKey, [`${this.definition.type}-doc.md`]); } /** * Retrieves folder metadata into local filesystem. Also creates a uniquePath attribute for each folder. - * @param {Object} buObject properties for auth - * @param {void} [_] - - * @param {boolean} [isDeploy] used to signal that fields shall be retrieve in caching mode - * @returns {Promise} Promise + * + * @returns {Promise.<{metadata: DataExtensionMap, type: string}>} Promise */ - static async retrieveForCache(buObject, _, isDeploy) { - return this.retrieve(null, ['ObjectID', 'CustomerKey', 'Name'], buObject, null, isDeploy); + static async retrieveForCache() { + return this.retrieve(null, ['ObjectID', 'CustomerKey', 'Name']); } + /** * Retrieves dataExtension metadata in template format. + * + * @deprecated Use `retrieve` followed by `build` instead. `retrieveAsTemplate` will be removed in a future version. * @param {string} templateDir Directory where retrieved metadata directory will be saved * @param {string} name name of the metadata item - * @param {Util.TemplateMap} templateVariables variables to be replaced in the metadata - * @returns {Promise<{metadata:DataExtensionMap,type:string}>} Promise of items + * @param {TemplateMap} templateVariables variables to be replaced in the metadata + * @returns {Promise.<{metadata: DataExtensionItem, type: string}>} Promise of items */ static async retrieveAsTemplate(templateDir, name, templateVariables) { + Util.logDeprecated('retrieveAsTemplate', `'retrieve' followed by 'build'`); + /** @type {SoapRequestParams} */ const options = { filter: { leftOperand: 'Name', @@ -879,14 +1517,13 @@ class DataExtension extends MetadataType { rightOperand: name, }, }; - /** @type DataExtensionMap */ - // const metadata = super.parseResponseBody(response.body); + const metadata = await this._retrieveAll(null, options); if (!Object.keys(metadata).length) { Util.logger.error(`${this.definition.type} '${name}' not found on server.`); Util.logger.info('Downloaded: dataExtension (0)'); - return { metadata: {}, type: 'dataExtension' }; + return { metadata: null, type: 'dataExtension' }; } const customerKey = Object.keys(metadata)[0]; await this._retrieveFieldsForSingleDe(metadata, customerKey); @@ -897,17 +1534,15 @@ class DataExtension extends MetadataType { metadata[key].Fields.sort((a, b) => a.Ordinal - b.Ordinal); const originalKey = key; - const metadataCleaned = JSON.parse( - JSON.stringify( - await this.postRetrieveTasks(metadata[key], null, !!templateVariables) - ) + const metadataCleaned = structuredClone( + await this.postRetrieveTasks(metadata[key]) ); this.keepTemplateFields(metadataCleaned); const metadataTemplated = JSON.parse( Util.replaceByObject(JSON.stringify(metadataCleaned), templateVariables) ); - File.writeJSONToFile( + await File.writeJSONToFile( [templateDir, this.definition.type].join('/'), originalKey + '.' + this.definition.type + '-meta', metadataTemplated @@ -916,28 +1551,25 @@ class DataExtension extends MetadataType { Util.metadataLogger('error', this.definition.type, 'retrieve', ex, key); } } + Util.logger.info(`- templated ${this.definition.type}: ${customerKey}`); - Util.logger.info( - `DataExtension.retrieveAsTemplate:: All records written to filesystem (${customerKey})` - ); - return { metadata: metadata, type: 'dataExtension' }; + return { metadata: metadata[customerKey], type: 'dataExtension' }; } /** - * parses retrieved Metadata before saving - * @private - * @param {DataExtensionItem} metadata a single dataExtension definition - * @returns {DataExtensionItem} a single dataExtension definition + * dataExtension logic that retrieves the folder path from cache and updates the given metadata with it after retrieve + * it also sets the content type which is basically the subtype + * + * @param {MetadataTypeItem} metadata a single script activity definition */ - static _parseMetadata(metadata) { + static setFolderPath(metadata) { let error = false; let verbose = false; // data extension type (from folder) try { - metadata.r__folder_ContentType = Util.getFromCache( - this.cache, + metadata.r__folder_ContentType = cache.searchForField( 'folder', - metadata.CategoryID, + metadata[this.definition.folderIdField], 'ID', 'ContentType' ); @@ -947,23 +1579,26 @@ class DataExtension extends MetadataType { metadata.r__folder_ContentType = 'synchronizeddataextension'; } else { error = true; - Util.logger.warn(`Data Extension '${metadata.Name}': ${ex.message}`); + Util.logger.warn( + ` - ${this.definition.type} '${metadata[this.definition.nameField]}' (${ + metadata[this.definition.keyField] + }): Could not find folder (${ex.message})` + ); } } // folder try { - metadata.r__folder_Path = Util.getFromCache( - this.cache, + metadata.r__folder_Path = cache.searchForField( 'folder', - metadata.CategoryID, + metadata[this.definition.folderIdField], 'ID', 'Path' ); - delete metadata.CategoryID; + delete metadata[this.definition.folderIdField]; } catch (ex) { if (/(_Salesforce)(_\d\d?\d?)?$/.test(metadata.Name)) { metadata.r__folder_Path = 'Synchronized Data Extensions'; - delete metadata.CategoryID; + delete metadata[this.definition.folderIdField]; if (!verbose) { Util.logger.verbose( @@ -971,65 +1606,150 @@ class DataExtension extends MetadataType { ); } } else if (!error) { - Util.logger.error(`Data Extension '${metadata.Name}': ${ex.message}`); - } - } - // DataExtensionTemplate - if (metadata.Template && metadata.Template.CustomerKey) { - try { - metadata.r__dataExtensionTemplate_Name = Util.getFromCache( - this.cache, - 'dataExtensionTemplate', - metadata.Template.CustomerKey, - 'CustomerKey', - 'Name' - ); - delete metadata.Template; - } catch (ex) { - Util.logger.debug(ex.message); - // Let's allow retrieving such DEs but warn that they cannot be deployed to another BU. - // Deploying to same BU still works! - // A workaround exists but it's likely not beneficial to explain to users: - // Create a DE based on the not-supported template on the target BU, retrieve it, copy the Template.CustomerKey into the to-be-deployed DE (or use mcdev-templating), done Util.logger.warn( - `Issue with DataExtension '${ - metadata[this.definition.nameField] - }': Could not find specified DataExtension Template. Please note that DataExtensions based on SMSMessageTracking and SMSSubscriptionLog cannot be deployed automatically across BUs at this point.` + ` - ${this.definition.type} '${metadata[this.definition.nameField]}' (${ + metadata[this.definition.keyField] + }): ${ex.message}` ); } } - - return metadata; } /** * Retrieves dataExtension metadata and cleans it + * * @private * @param {string[]} [additionalFields] Returns specified fields even if their retrieve definition is not set to true - * @param {Object} [options] e.g. filter - * @returns {Promise<DataExtensionMap>} keyField => metadata map + * @param {SoapRequestParams} [options] e.g. filter + * @returns {Promise.<DataExtensionMap>} keyField => metadata map */ static async _retrieveAll(additionalFields, options) { - const metadata = (await super.retrieveSOAPgeneric(null, null, options, additionalFields)) - .metadata; + const { metadata } = await super.retrieveSOAP(null, options, null, additionalFields); for (const key in metadata) { // some system data extensions do not have CategoryID which throws errors in other places. These do not need to be parsed - if (!metadata[key].CategoryID) { - delete metadata[key]; - } else { + if (metadata[key].CategoryID) { metadata[key].Fields = []; + } else { + delete metadata[key]; } } return metadata; } + + /** + * should return only the json for all but asset, query and script that are saved as multiple files + * additionally, the documentation for dataExtension and automation should be returned + * + * @param {string[]} keyArr customerkey of the metadata + * @returns {Promise.<string[]>} list of all files that need to be committed in a flat array ['path/file1.ext', 'path/file2.ext'] + */ + static async getFilesToCommit(keyArr) { + if (this.properties.metaDataTypes.documentOnRetrieve.includes(this.definition.type)) { + // document dataExtension is active. assume we want to commit the MD file as well + const path = File.normalizePath([ + this.properties.directories.retrieve, + this.buObject.credential, + this.buObject.businessUnit, + this.definition.type, + ]); + + const fileList = keyArr.flatMap((key) => [ + File.normalizePath([path, `${key}.${this.definition.type}-meta.json`]), + File.normalizePath([path, `${key}.${this.definition.type}-doc.md`]), + ]); + return fileList; + } else { + // document dataExtension is not active upon retrieve, run default method instead + return super.getFilesToCommit(keyArr); + } + } + /** + * helper for {@link MetadataType.createOrUpdate} + * + * @param {MetadataTypeItem} metadataItem to be deployed item + * @returns {MetadataTypeItem} cached item or undefined + */ + static getCacheMatchedByName(metadataItem) { + let cacheMatchedByName; + + if (Util.OPTIONS.matchName) { + // make sure to run the search ONLY if OPTIONS.matchName is true and definition.allowMatchingByName signals support + const typeCache = cache.getCache()?.[this.definition.type]; + const potentials = []; + for (const key in typeCache) { + const cachedItem = typeCache[key]; + if ( + cachedItem[this.definition.nameField] === + metadataItem[this.definition.nameField] + ) { + potentials.push(cachedItem); + } + } + if (potentials.length > 1) { + // ! SFMC disallows having 2 dataExtensions with the same name because that would cause a conflict in queries and in ampscript/ssjs which all use dataExtension NAMES instead of keys in their scripts + // ! When trying to create a duplicate it results in the error Code 310007 ("A data extension named xyz already exists.") + Util.logger.debug(` - Multiple name matches found? This should never happen.`); + } else if (potentials.length === 1) { + // only one item found, confirm that it's in the same folder + const deployFolderPath = cache.searchForField( + 'folder', + metadataItem[this.definition.folderIdField], + 'ID', + 'Path' + ); + if ( + potentials[0][this.definition.folderIdField] === + metadataItem[this.definition.folderIdField] + ) { + cacheMatchedByName = potentials[0]; + + Util.logger.info( + Util.getGrayMsg( + ` - found ${this.definition.type} ${metadataItem[this.definition.keyField]} in cache by name "${metadataItem[this.definition.nameField]}" and folder "${deployFolderPath}": ${cacheMatchedByName[this.definition.keyField]}` + ) + ); + } else if ( + Util.OPTIONS.ignoreFolder && + potentials[0][this.definition.folderIdField] !== + metadataItem[this.definition.folderIdField] + ) { + cacheMatchedByName = potentials[0]; + + const cacheFolderPath = cache.searchForField( + 'folder', + potentials[0][this.definition.folderIdField], + 'ID', + 'Path' + ); + + Util.logger.info( + Util.getGrayMsg( + ` - found ${this.definition.type} ${metadataItem[this.definition.keyField]} in cache by name "${metadataItem[this.definition.nameField]}" and but folder is different (--ignoreFolder). New folder: "${deployFolderPath}". Old: "${cacheFolderPath}"` + ) + ); + } else { + const cacheFolderPath = cache.searchForField( + 'folder', + potentials[0][this.definition.folderIdField], + 'ID', + 'Path' + ); + throw new Error( + `found ${this.definition.type} ${metadataItem[this.definition.keyField]} in cache by name but folder is different. New folder: "${deployFolderPath}". Old: "${cacheFolderPath}": Identified key: ${potentials[0][this.definition.keyField]}` + ); + } + } else { + Util.logger.debug( + ` - no name-match found for ${this.definition.type} ${metadataItem[this.definition.keyField]}. Creating new ${this.definition.type} instead.` + ); + } + } + return cacheMatchedByName; + } } // Assign definition to static attributes -DataExtension.definition = require('../MetadataTypeDefinitions').dataExtension; -/** - * @type {Util.ET_Client} - */ -DataExtension.client = undefined; -DataExtension.cache = {}; +import MetadataTypeDefinitions from '../MetadataTypeDefinitions.js'; +DataExtension.definition = MetadataTypeDefinitions.dataExtension; -module.exports = DataExtension; +export default DataExtension; diff --git a/lib/metadataTypes/DataExtensionField.js b/lib/metadataTypes/DataExtensionField.js index 31d5a3104..54fddbf5b 100644 --- a/lib/metadataTypes/DataExtensionField.js +++ b/lib/metadataTypes/DataExtensionField.js @@ -1,53 +1,100 @@ 'use strict'; -const Util = require('../util/util'); +import MetadataType from './MetadataType.js'; +import { Util } from '../util/util.js'; +import DataExtension from './DataExtension.js'; +import { confirm } from '@inquirer/prompts'; /** - * @typedef {Object} DataExtensionFieldItem - * @property {string} [ObjectID] id - * @property {string} [CustomerKey] key in format [DEkey].[FieldName] - * @property {Object} [DataExtension] - - * @property {string} DataExtension.CustomerKey key of DE - * @property {string} Name name of field - * @property {string} [Name_new] custom attribute that is only used when trying to rename a field from Name to Name_new - * @property {string} DefaultValue empty string for not set - * @property {'true'|'false'} IsRequired - - * @property {'true'|'false'} IsPrimaryKey - - * @property {string} Ordinal 1, 2, 3, ... - * @property {'Text'|'Number'|'Date'|'Boolean'|'Decimal'|'EmailAddress'|'Phone'|'Locale'} FieldType can only be set on create - * @property {string} Scale the number of places after the decimal that the field can hold; example: "0","1", ... - * - * @typedef {Object.<string, DataExtensionFieldItem>} DataExtensionFieldMap + * @typedef {import('../../types/mcdev.d.js').BuObject} BuObject + * @typedef {import('../../types/mcdev.d.js').CodeExtract} CodeExtract + * @typedef {import('../../types/mcdev.d.js').CodeExtractItem} CodeExtractItem + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItem} MetadataTypeItem + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItemDiff} MetadataTypeItemDiff + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItemObj} MetadataTypeItemObj + * @typedef {import('../../types/mcdev.d.js').MetadataTypeMap} MetadataTypeMap + * @typedef {import('../../types/mcdev.d.js').MetadataTypeMapObj} MetadataTypeMapObj + * @typedef {import('../../types/mcdev.d.js').SoapRequestParams} SoapRequestParams + * @typedef {import('../../types/mcdev.d.js').TemplateMap} TemplateMap */ -const MetadataType = require('./MetadataType'); +/** + * @typedef {import('../../types/mcdev.d.js').DataExtensionFieldMap} DataExtensionFieldMap + * @typedef {import('../../types/mcdev.d.js').DataExtensionFieldItem} DataExtensionFieldItem + */ /** * DataExtensionField MetadataType + * * @augments MetadataType */ class DataExtensionField extends MetadataType { + static fixShared_fields; + /** * Retrieves all records and saves it to disk + * * @param {string} retrieveDir Directory where retrieved metadata directory will be saved * @param {string[]} [additionalFields] Returns specified fields even if their retrieve definition is not set to true - * @param {Object} buObject properties for auth - * @returns {Promise<{metadata:DataExtensionFieldMap,type:string}>} Promise of items + * @returns {Promise.<{metadata: DataExtensionFieldMap, type: string}>} Promise of items + */ + static async retrieve(retrieveDir, additionalFields) { + return super.retrieveSOAP(retrieveDir, null, null, additionalFields); + } + /** + * Retrieves all records and saves it to disk + * + * @returns {Promise.<MetadataTypeMapObj>} Promise of items + */ + static async retrieveForCache() { + const cachedDEs = cache.getCache().dataExtension; + if (cachedDEs) { + await DataExtension.attachFields(cachedDEs); + } + return; + } + /** + * helps retrieving fields for a single DE. Use when needing field data for one DE only. + * + * @param {string} customerKey external key of single DE + * @returns {Promise.<object>} Promise of items */ - static async retrieve(retrieveDir, additionalFields, buObject) { - return super.retrieveSOAPgeneric(retrieveDir, buObject, null, additionalFields); + static async retrieveFieldsForSingleDe(customerKey) { + /** @type {SoapRequestParams} */ + const fieldOptions = { + filter: { + leftOperand: 'DataExtension.CustomerKey', + operator: 'equals', + rightOperand: customerKey, + }, + }; + const response = await DataExtensionField.retrieveForCacheDE(fieldOptions); + return DataExtensionField.convertToSortedArray(response.metadata).reduce((acc, field) => { + acc[field.CustomerKey] = field; + return acc; + }, {}); } + /** * Retrieves all records for caching - * @param {Object} [options] required for the specific request (filter for example) + * + * @param {SoapRequestParams} [requestParams] required for the specific request (filter for example) * @param {string[]} [additionalFields] Returns specified fields even if their retrieve definition is not set to true - * @returns {Promise<{metadata:DataExtensionFieldMap,type:string}>} Promise of items + * @returns {Promise.<{metadata: DataExtensionFieldMap, type: string}>} Promise of items */ - static async retrieveForCache(options, additionalFields) { - return super.retrieveSOAPgeneric(null, null, options, additionalFields); + static async retrieveForCacheDE(requestParams, additionalFields) { + let response; + response = await super.retrieveSOAP(null, requestParams, null, additionalFields); + if (!response) { + // try again but without filters as a workaround for the "String or binary data would be truncated." issue + response = await super.retrieveSOAP(null, {}, null, additionalFields); + } + return response; } + /** - * helper for DataExtension.js that sorts the fields into an array + * helper for DataExtension.retrieveFieldsForSingleDe that sorts the fields into an array + * * @param {DataExtensionFieldMap} fieldsObj customerKey-based list of fields for one dataExtension * @returns {DataExtensionFieldItem[]} sorted array of field objects */ @@ -56,63 +103,70 @@ class DataExtensionField extends MetadataType { Object.keys(fieldsObj) .map((field) => fieldsObj[field]) // the API returns the fields not sorted - .sort(this.sortDeFields) + .toSorted(this.sortDeFields) ); } /** * sorting method to ensure `Ordinal` is respected + * * @param {DataExtensionFieldItem} a - * @param {DataExtensionFieldItem} b - - * @returns {boolean} sorting based on Ordinal + * @returns {number} sorting based on Ordinal */ static sortDeFields(a, b) { return a.Ordinal - b.Ordinal; } + /** - * manages post retrieve steps + * manages post retrieve steps; only used by DataExtension class + * * @param {DataExtensionFieldItem} metadata a single item - * @param {boolean} forDataExtension when used by DataExtension class we remove more fields * @returns {DataExtensionFieldItem} metadata */ - static postRetrieveTasks(metadata, forDataExtension) { - return this._parseMetadata(metadata, forDataExtension); - } + static postRetrieveTasksDE(metadata) { + // remove fields according to definition + this.keepRetrieveFields(metadata); - /** - * parses retrieved Metadata before saving - * @private - * @param {DataExtensionFieldItem} metadata a single record - * @param {boolean} forDataExtension when used by DataExtension class we remove more fields - * @returns {DataExtensionFieldItem} parsed metadata definition - */ - static _parseMetadata(metadata, forDataExtension) { - if (forDataExtension) { - // remove fields according to definition - this.keepRetrieveFields(metadata); - - // remove fields that we do not need after association to a DE - delete metadata.CustomerKey; - delete metadata.DataExtension; - delete metadata.Ordinal; - if (metadata.FieldType !== 'Decimal') { - // remove scale - it's only used for "Decimal" to define the digits behind the decimal - delete metadata.Scale; - } + // remove fields that we do not need after association to a DE + delete metadata.CustomerKey; + delete metadata.DataExtension; + delete metadata.Ordinal; + if (metadata.FieldType !== 'Decimal') { + // remove scale - it's only used for "Decimal" to define the digits behind the decimal + delete metadata.Scale; } return metadata; } + /** * Mofifies passed deployColumns for update by mapping ObjectID to their target column's values. * Removes FieldType field if its the same in deploy and target column, because it results in an error even if its of the same type * * @param {DataExtensionFieldItem[]} deployColumns Columns of data extension that will be deployed * @param {string} deKey external/customer key of Data Extension - * @returns {Object<string,DataExtensionFieldItem>} existing fields by their original name to allow re-adding FieldType after update + * @returns {Promise.<DataExtensionFieldMap>} existing fields by their original name to allow re-adding FieldType after update */ static async prepareDeployColumnsOnUpdate(deployColumns, deKey) { + // create list of DE keys that had changes to their fields to be able to use it as a filter in the --fixShared logic + this.fixShared_fields ||= {}; + this.fixShared_fields[deKey] ||= {}; + + // get row count to know which field restrictions apply + let hasData = false; + try { + const rowset = await this.client.rest.get( + `/data/v1/customobjectdata/key/${deKey}/rowset?$page=1&$pagesize=1` + ); + const rowCount = rowset.count; + hasData = rowCount > 0; + Util.logger.debug(`dataExtension ${deKey} row count: ${rowCount}`); + } catch (ex) { + Util.logger.debug(`Could not retrieve rowcount for ${deKey}: ${ex.message}`); + } + // retrieve existing fields to enable updating them - const response = await this.retrieveForCache( + const response = await this.retrieveForCacheDE( { filter: { leftOperand: 'DataExtension.CustomerKey', @@ -126,24 +180,26 @@ class DataExtensionField extends MetadataType { const fieldsObj = response.metadata; // ensure fields can be updated properly by their adding ObjectId based on Name-matching - /** @type {Object<string,DataExtensionFieldItem>} */ + /** @type {DataExtensionFieldMap} */ const existingFieldByName = {}; - Object.keys(fieldsObj).forEach((key) => { - existingFieldByName[fieldsObj[key].Name] = fieldsObj[key]; - }); + for (const key of Object.keys(fieldsObj)) { + // make sure we stringify the name in case it looked numeric and then lowercase it for easy comparison as the server is comparing field names case-insensitive + existingFieldByName[(fieldsObj[key].Name + '').toLowerCase()] = fieldsObj[key]; + } for (let i = deployColumns.length - 1; i >= 0; i--) { const item = deployColumns[i]; - const itemOld = existingFieldByName[item.Name]; + // make sure we stringify the name in case it looked numeric and then lowercase it for easy comparison as the server is comparing field names case-insensitive + const itemOld = existingFieldByName[(item.Name + '').toLowerCase()]; if (itemOld) { // field is getting updated --- // Updating to a new FieldType will result in an error; warn & afterwards remove it if (itemOld.FieldType !== item.FieldType) { - Util.logger.warn( - `- The Field Type of an existing field cannot be changed. Keeping the original value for [${deKey}].[${item.Name}]: '${itemOld.FieldType}'` + // applicable: with or without data but simply ignored by API + Util.logger.error( + ` - The Field Type of an existing field cannot be changed. [${deKey}].[${item.Name}]: '${itemOld.FieldType}'` ); - item.FieldType = itemOld.FieldType; } if (item.FieldType !== 'Decimal') { // remove scale - it's only used for "Decimal" to define the digits behind the decimal @@ -152,34 +208,38 @@ class DataExtensionField extends MetadataType { delete item.FieldType; if (itemOld.MaxLength > item.MaxLength) { - Util.logger.warn( - `- The length of an existing field cannot be decreased. Keeping the original value for [${deKey}].[${item.Name}]: '${itemOld.MaxLength}'` + // applicable: with or without data (Code 310007) + Util.logger.error( + ` - The length of an existing field cannot be decreased. [${deKey}].[${item.Name}]: '${itemOld.MaxLength}'` ); - item.MaxLength = itemOld.MaxLength; } if (Util.isFalse(itemOld.IsRequired) && Util.isTrue(item.IsRequired)) { - Util.logger.warn( - `- A field cannot be changed to be required on update after it was created to allow nulls: [${deKey}].[${item.Name}]` + // applicable: with or without data (Code 310007) + Util.logger.error( + ` - A field cannot be changed to be required on update after it was created to allow nulls. [${deKey}].[${item.Name}]` ); - item.IsRequired = itemOld.IsRequired; } // enable renaming if (item.Name_new) { + Util.logger.info( + ` - Found Name_new='${item.Name_new}' for field ${deKey}.${item.Name} - trying to rename.` + ); item.Name = item.Name_new; delete item.Name_new; - Util.logger.warn( - `Found 'Name_new' value '${item.Name_new}' for ${deKey}.${item.Name} - trying to rename.` - ); } // check if any changes were found let changeFound = false; - Object.keys(item).forEach((key) => { + for (const key of Object.keys(item)) { if (item[key] !== itemOld[key]) { changeFound = true; } - }); + } + // share fields with fixShared logic + this.fixShared_fields[deKey][item.Name] = structuredClone(item); + this.fixShared_fields[deKey][item.Name].FieldType = itemOld.FieldType; + if (!changeFound) { deployColumns.splice(i, 1); Util.logger.verbose(`no change - removed field [${deKey}].[${item.Name}]`); @@ -190,45 +250,204 @@ class DataExtensionField extends MetadataType { item.ObjectID = itemOld.ObjectID; } else { // field is getting added --- - if (Util.isTrue(item.IsRequired) && item.DefaultValue === '') { - Util.logger.warn( - `- Adding new fields to an existing table requires that these fields are either not-required (nullable) or have a default value set. Changing [${deKey}].[${item.Name}] to be not-required` - ); - item.IsRequired = 'false'; + + if (hasData && Util.isTrue(item.IsRequired) && item.DefaultValue === '') { + // applicable: with data only + if (Util.isFalse(item.IsPrimaryKey)) { + Util.logger.warn( + ` - Adding new fields to an existing table requires that these fields are either not-required (nullable) or have a default value set. Changing [${deKey}].[${item.Name}] to be not-required` + ); + item.IsRequired = false; + } else { + Util.logger.error( + `- You cannot add a new primary key field to an existing table that has data. [${deKey}].[${item.Name}]` + ); + } } if (item.Name_new) { - Util.logger.warn( - `Found 'Name_new' value '${item.Name_new}' for ${deKey}.${item.Name} but could not find a corresponding DE field on the server - adding new field instead of updating.` + Util.logger.info( + ` - Found Name_new='${item.Name_new}' for field ${deKey}.${item.Name} but could not find a corresponding DE field on the server - adding new field instead of updating.` ); delete item.Name_new; } // Field doesn't exist in target, therefore Remove ObjectID if present delete item.ObjectID; + + this.fixShared_fields[deKey][item.Name] = structuredClone(item); } + if (Util.isTrue(item.IsPrimaryKey) && Util.isFalse(item.IsRequired)) { + // applicable: with or without data + Util.logger.warn( + `- Primary Key field [${deKey}].[${item.Name}] cannot be not-required (nullable). Changing field to be required!` + ); + item.IsRequired = true; + } + + // filter bad manual changes to the json if (!Util.isTrue(item.IsRequired) && !Util.isFalse(item.IsRequired)) { Util.logger.error( - `- Invalid value for 'IsRequired' of [${deKey}].[${item.Name}]. Found '${item.IsRequired}' instead of 'true'/'false'. Removing field from deploy!` + `- Invalid value for 'IsRequired' of [${deKey}].[${item.Name}]. Found '${item.IsRequired}' instead of 'true'/'false'.` ); - deployColumns.splice(i, 1); } if (!Util.isTrue(item.IsPrimaryKey) && !Util.isFalse(item.IsPrimaryKey)) { Util.logger.error( - `- Invalid value for 'IsPrimaryKey' of [${deKey}].[${item.Name}]. Found '${item.IsPrimaryKey}' instead of 'true'/'false'. Removing field from deploy!` + `- Invalid value for 'IsPrimaryKey' of [${deKey}].[${item.Name}]. Found '${item.IsPrimaryKey}' instead of 'true'/'false'.` ); - deployColumns.splice(i, 1); } } - Util.logger.debug( - `${deployColumns.length} Fields added/updated for [${deKey}]: ` + - deployColumns.map((item) => item.Name).join(', ') + + Util.logger.info( + Util.getGrayMsg( + ` - Found ${deployColumns.length} added/updated Fields for ${deKey}${ + deployColumns.length ? ': ' : '' + }` + deployColumns.map((item) => item.Name).join(', ') + ) ); - return deployColumns.length ? existingFieldByName : null; + + return existingFieldByName; + } + + /** + * Delete a metadata item from the specified business unit + * + * @param {string} customerKey Identifier of data extension + * @returns {Promise.<boolean>} deletion success status + */ + static async deleteByKey(customerKey) { + return this.deleteByKeySOAP(customerKey); + } + + /** + * Delete a data extension from the specified business unit + * + * @param {string} customerKey Identifier of metadata + * @param {string} [fieldId] for programmatic deletes only one can pass in the ID directly + * @returns {Promise.<boolean>} deletion success flag + */ + static async deleteByKeySOAP(customerKey, fieldId) { + const [deKey, fieldName] = customerKey.split('.'); + customerKey = `[${deKey}].[${fieldName}]`; + + let fieldObjectID = fieldId; + let deletionQueue; + + // get the object id + if (!fieldObjectID) { + if (deKey === '*') { + const response = await this.retrieveForCacheDE( + { + filter: { + leftOperand: 'Name', + operator: 'equals', + rightOperand: fieldName, + }, + }, + ['Name', 'ObjectID', 'DataExtension.CustomerKey'] + ); + deletionQueue = Object.values(response.metadata).map((item) => ({ + fieldObjectID: item.ObjectID, + fieldName: fieldName, + deKey: item.DataExtension.CustomerKey, + })); + Util.logger.info( + ` - Found ${deletionQueue.length} Data Extensions with field ${fieldName} in your BU:\n - ${deletionQueue + .map((item) => item.deKey) + .toSorted() + .join('\n - ')}` + ); + if (deletionQueue.length > 0 && !Util.skipInteraction) { + const massDelete = await confirm({ + message: `Do you really want to delete that field from all of the above Data Extensions?`, + default: false, + }); + if (!massDelete) { + Util.logger.info( + ` ☇ skipping deletion of ${fieldName} based on user-choice.` + ); + return false; + } + } + } else { + const response = await this.retrieveForCacheDE( + { + filter: { + leftOperand: 'CustomerKey', + operator: 'equals', + rightOperand: customerKey, + }, + }, + ['Name', 'ObjectID'] + ); + fieldObjectID = response.metadata[customerKey]?.ObjectID; + } + } + if (!fieldObjectID && !deletionQueue) { + Util.logger.error(`Could not find ${customerKey} on your BU`); + return false; + } else if (!deletionQueue) { + deletionQueue = [ + { + fieldObjectID: fieldObjectID, + fieldName: fieldName, + deKey: deKey, + }, + ]; + } + + let success = true; + const fieldDeletedFromDEKeys = []; + for (const item of deletionQueue) { + // normal code + const keyObj = { + CustomerKey: item.deKey, + Fields: { + Field: { + ObjectID: item.fieldObjectID, + }, + }, + }; + try { + // ! we really do need to delete from DataExtension not DataExtensionField here! + await this.client.soap.delete('DataExtension', keyObj, null); + if (!fieldId) { + Util.logger.info( + ` - deleted ${this.definition.type}: ${item.deKey}.${item.fieldName}` + ); + } + fieldDeletedFromDEKeys.push(item.deKey); + // return true; + } catch (ex) { + const errorMsg = ex?.results?.length + ? `${ex.results[0].StatusMessage} (Code ${ex.results[0].ErrorCode})` + : ex?.json?.Results?.length + ? `${ex.json.Results[0].StatusMessage} (Code ${ex.json.Results[0].ErrorCode})` + : ex.message; + Util.logger.error( + `- error deleting ${this.definition.type} ${item.deKey}.${item.fieldName}: ${errorMsg}` + ); + + success = false; + } + } + + const uniqueDEKeys = [...new Set(fieldDeletedFromDEKeys)]; + if (uniqueDEKeys.length > 0) { + Util.logger.info( + Util.getGrayMsg( + `To refresh your local files, run mcdev r ${this.buObject.credential}/${this.buObject.businessUnit} -m ${uniqueDEKeys + .map((key) => 'dataExtension:"' + key + '"') + .toSorted() + .join(' ')}` + ) + ); + } + return success; } } // Assign definition to static attributes -DataExtensionField.definition = require('../MetadataTypeDefinitions').dataExtensionField; -DataExtensionField.cache = {}; -DataExtensionField.client = undefined; +import MetadataTypeDefinitions from '../MetadataTypeDefinitions.js'; +import cache from '../util/cache.js'; +DataExtensionField.definition = MetadataTypeDefinitions.dataExtensionField; -module.exports = DataExtensionField; +export default DataExtensionField; diff --git a/lib/metadataTypes/DataExtensionTemplate.js b/lib/metadataTypes/DataExtensionTemplate.js index c050324af..101a64ddf 100644 --- a/lib/metadataTypes/DataExtensionTemplate.js +++ b/lib/metadataTypes/DataExtensionTemplate.js @@ -1,23 +1,53 @@ 'use strict'; -const MetadataType = require('./MetadataType'); +import MetadataType from './MetadataType.js'; + +/** + * @typedef {import('../../types/mcdev.d.js').BuObject} BuObject + * @typedef {import('../../types/mcdev.d.js').CodeExtract} CodeExtract + * @typedef {import('../../types/mcdev.d.js').CodeExtractItem} CodeExtractItem + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItem} MetadataTypeItem + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItemDiff} MetadataTypeItemDiff + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItemObj} MetadataTypeItemObj + * @typedef {import('../../types/mcdev.d.js').MetadataTypeMap} MetadataTypeMap + * @typedef {import('../../types/mcdev.d.js').MetadataTypeMapObj} MetadataTypeMapObj + * @typedef {import('../../types/mcdev.d.js').SoapRequestParams} SoapRequestParams + * @typedef {import('../../types/mcdev.d.js').TemplateMap} TemplateMap + */ /** * DataExtensionTemplate MetadataType + * * @augments MetadataType */ class DataExtensionTemplate extends MetadataType { /** * Retrieves SOAP based metadata of metadata type into local filesystem. executes callback with retrieved metadata - * @param {String} retrieveDir Directory where retrieved metadata directory will be saved - * @returns {Promise<Object>} Promise of metadata + * + * @param {string} retrieveDir Directory where retrieved metadata directory will be saved + * @param {void | string[]} [_] unused parameter + * @param {void | string[]} [__] unused parameter + * @param {string} [key] customer key of single item to retrieve + * @returns {Promise.<MetadataTypeMapObj>} Promise of metadata */ - static retrieve(retrieveDir) { - return super.retrieveSOAPgeneric(retrieveDir); + static retrieve(retrieveDir, _, __, key) { + /** @type {SoapRequestParams} */ + let requestParams = null; + if (key) { + requestParams = { + filter: { + leftOperand: 'CustomerKey', + operator: 'equals', + rightOperand: key, + }, + }; + } + return super.retrieveSOAP(retrieveDir, requestParams, key); } } // Assign definition to static attributes -DataExtensionTemplate.definition = require('../MetadataTypeDefinitions').dataExtensionTemplate; +import MetadataTypeDefinitions from '../MetadataTypeDefinitions.js'; +DataExtensionTemplate.definition = MetadataTypeDefinitions.dataExtensionTemplate; -module.exports = DataExtensionTemplate; +export default DataExtensionTemplate; diff --git a/lib/metadataTypes/DataExtract.js b/lib/metadataTypes/DataExtract.js index 443e2e63a..e0f9ebc4b 100644 --- a/lib/metadataTypes/DataExtract.js +++ b/lib/metadataTypes/DataExtract.js @@ -1,98 +1,110 @@ 'use strict'; -const MetadataType = require('./MetadataType'); -const Util = require('../util/util'); -const File = require('../util/file'); +import MetadataType from './MetadataType.js'; +import { Util } from '../util/util.js'; +import File from '../util/file.js'; +import cache from '../util/cache.js'; + +/** + * @typedef {import('../../types/mcdev.d.js').BuObject} BuObject + * @typedef {import('../../types/mcdev.d.js').CodeExtract} CodeExtract + * @typedef {import('../../types/mcdev.d.js').CodeExtractItem} CodeExtractItem + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItem} MetadataTypeItem + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItemDiff} MetadataTypeItemDiff + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItemObj} MetadataTypeItemObj + * @typedef {import('../../types/mcdev.d.js').MetadataTypeMap} MetadataTypeMap + * @typedef {import('../../types/mcdev.d.js').MetadataTypeMapObj} MetadataTypeMapObj + * @typedef {import('../../types/mcdev.d.js').SoapRequestParams} SoapRequestParams + * @typedef {import('../../types/mcdev.d.js').TemplateMap} TemplateMap + */ /** * DataExtract MetadataType + * * @augments MetadataType */ class DataExtract extends MetadataType { /** * Retrieves Metadata of Data Extract Activity. * Endpoint /automation/v1/dataextracts/ returns all Data Extracts - * @param {String} retrieveDir Directory where retrieved metadata directory will be saved - * @returns {Promise<Object>} Promise of metadata + * + * @param {string} retrieveDir Directory where retrieved metadata directory will be saved + * @param {void | string[]} [_] unused parameter + * @param {void | string[]} [__] unused parameter + * @param {string} [key] customer key of single item to retrieve + * @returns {Promise.<MetadataTypeMapObj>} Promise of metadata */ - static async retrieve(retrieveDir) { - return super.retrieveREST(retrieveDir, '/automation/v1/dataextracts/', null); + static async retrieve(retrieveDir, _, __, key) { + return super.retrieveREST(retrieveDir, '/automation/v1/dataextracts/', null, key); } + /** * Retrieves Metadata of Data Extract Activity for caching - * @returns {Promise<Object>} Promise of metadata + * + * @returns {Promise.<MetadataTypeMapObj>} Promise of metadata */ static async retrieveForCache() { - return super.retrieveREST(null, '/automation/v1/dataextracts/', null); + return super.retrieveREST(null, '/automation/v1/dataextracts/'); } /** * Retrieve a specific dataExtract Definition by Name - * @param {String} templateDir Directory where retrieved metadata directory will be saved - * @param {String} name name of the metadata file - * @param {Object} templateVariables variables to be replaced in the metadata - * @returns {Promise<Object>} Promise of metadata + * + * @deprecated Use `retrieve` followed by `build` instead. `retrieveAsTemplate` will be removed in a future version. + * @param {string} templateDir Directory where retrieved metadata directory will be saved + * @param {string} name name of the metadata file + * @param {TemplateMap} templateVariables variables to be replaced in the metadata + * @returns {Promise.<MetadataTypeItemObj>} Promise of metadata */ static async retrieveAsTemplate(templateDir, name, templateVariables) { - const options = { - uri: '/automation/v1/dataextracts/?$filter=name%20eq%20' + name.split(' ').join('%20'), - }; - - const res = await this.client.RestClient.get(options); - if (res.body && Array.isArray(res.body.items) && res.body.items.length) { + Util.logDeprecated('retrieveAsTemplate', `'retrieve' followed by 'build'`); + const res = await this.client.rest.get( + '/automation/v1/dataextracts/?$filter=name%20eq%20' + encodeURIComponent(name) + ); + if (Array.isArray(res.items) && res.items.length) { // eq-operator returns a similar, not exact match and hence might return more than 1 entry - const [metadata] = res.body.items.filter((item) => item.name === name); + const metadata = res.items.find((item) => item.name === name); if (!metadata) { Util.logger.error(`No ${this.definition.typeName} found with name "${name}"`); return; } // get full definition - const extended = await this.client.RestClient.get({ - uri: '/automation/v1/dataextracts/' + metadata.id, - }); - const originalKey = extended.body[this.definition.keyField]; + const extended = await this.client.rest.get( + '/automation/v1/dataextracts/' + metadata[this.definition.idField] + ); + const originalKey = extended[this.definition.keyField]; const val = JSON.parse( Util.replaceByObject( - JSON.stringify(this.parseMetadata(extended.body)), + JSON.stringify(this.postRetrieveTasks(extended)), templateVariables ) ); // remove all fields listed in Definition for templating this.keepTemplateFields(val); - File.writeJSONToFile( + await File.writeJSONToFile( [templateDir, this.definition.type].join('/'), originalKey + '.' + this.definition.type + '-meta', JSON.parse(Util.replaceByObject(JSON.stringify(val), templateVariables)) ); - Util.logger.info( - `Dataextracts.retrieveAsTemplate:: Written Metadata to filesystem (${name})` - ); + Util.logger.info(`- templated ${this.definition.type}: ${name}`); return { metadata: val, type: this.definition.type }; - } else if (res.body && res.body.items) { + } else if (res?.items) { Util.logger.error(`No ${this.definition.typeName} found with name "${name}"`); } else { throw new Error( `Encountered unknown error when retrieveing ${ this.definition.typeName - } "${name}": ${JSON.stringify(res.body)}` + } "${name}": ${JSON.stringify(res)}` ); } } - /** - * manages post retrieve steps - * @param {Object} fileTransfer a single fileTransfer - * @returns {Object[]} metadata - */ - static postRetrieveTasks(fileTransfer) { - return this.parseMetadata(fileTransfer); - } - /** * Creates a single Data Extract - * @param {Object} dataExtract a single Data Extract + * + * @param {MetadataTypeItem} dataExtract a single Data Extract * @returns {Promise} Promise */ static create(dataExtract) { @@ -101,7 +113,8 @@ class DataExtract extends MetadataType { /** * Updates a single Data Extract - * @param {Object} dataExtract a single Data Extract + * + * @param {MetadataTypeItem} dataExtract a single Data Extract * @returns {Promise} Promise */ static update(dataExtract) { @@ -113,12 +126,27 @@ class DataExtract extends MetadataType { /** * prepares a dataExtract for deployment - * @param {Object} metadata a single dataExtract activity definition - * @returns {Object} metadata object + * + * @param {MetadataTypeItem} metadata a single dataExtract activity definition + * @returns {MetadataTypeItem} metadata object */ static preDeployTasks(metadata) { - metadata.dataExtractTypeId = Util.getFromCache( - this.cache, + // dataExtension + if (metadata.r__dataExtension_key) { + const deField = metadata.dataFields.find((field) => field.name === 'DECustomerKey'); + if (deField) { + deField.value = cache.searchForField( + 'dataExtension', + metadata.r__dataExtension_key, + 'CustomerKey', + 'CustomerKey' + ); + delete metadata.r__dataExtension_key; + } + } + + // dataExtractType + metadata.dataExtractTypeId = cache.searchForField( 'dataExtractType', metadata.r__dataExtractType_name, 'name', @@ -127,27 +155,136 @@ class DataExtract extends MetadataType { delete metadata.r__dataExtractType_name; return metadata; } + /** - * parses retrieved Metadata before saving - * @param {Object} metadata a single dataExtract activity definition - * @returns {Array} Array with one metadata object and one sql string + * Gets executed after deployment of metadata type + * + * @param {MetadataTypeMap} upsertResults metadata mapped by their keyField as returned by update/create + * @returns {Promise.<void>} - */ - static parseMetadata(metadata) { - metadata.r__dataExtractType_name = Util.getFromCache( - this.cache, - 'dataExtractType', - metadata.dataExtractTypeId, - 'extractId', - 'name' + static async postDeployTasks(upsertResults) { + // re-retrieve all upserted items to ensure we have all fields (createdDate and modifiedDate are otherwise not present) + Util.logger.debug( + `Caching all ${this.definition.type} post-deploy to ensure we have all fields` ); - delete metadata.dataExtractTypeId; - return JSON.parse(JSON.stringify(metadata)); + const typeCache = await this.retrieveForCache(); + // update values in upsertResults with retrieved values before saving to disk + for (const key of Object.keys(upsertResults)) { + if (typeCache.metadata[key]) { + upsertResults[key] = typeCache.metadata[key]; + } + } + } + + /** + * manages post retrieve steps + * + * @param {MetadataTypeItem} metadata a single item + * @returns {MetadataTypeItem} metadata + */ + static postRetrieveTasks(metadata) { + // user + try { + metadata.createdBy = cache.searchForField( + 'user', + metadata.createdBy, + 'AccountUserID', + 'Name' + ); + } catch (ex) { + Util.logger.verbose( + ` - ${this.definition.type} ${metadata[this.definition.nameField]} (${ + metadata[this.definition.keyField] + }): ${ex.message}.` + ); + } + + try { + metadata.modifiedBy = cache.searchForField( + 'user', + metadata.modifiedBy, + 'AccountUserID', + 'Name' + ); + } catch (ex) { + Util.logger.verbose( + ` - ${this.definition.type} ${metadata[this.definition.nameField]} (${ + metadata[this.definition.keyField] + }): ${ex.message}.` + ); + } + // dataExtension + const deField = metadata.dataFields.find((field) => field.name === 'DECustomerKey'); + if (deField && deField.value) { + try { + metadata.r__dataExtension_key = cache.searchForField( + 'dataExtension', + deField.value, + 'CustomerKey', + 'CustomerKey' + ); + delete deField.value; + } catch (ex) { + Util.logger.warn( + ` - ${this.definition.type} ${metadata[this.definition.keyField]}: ${ex.message}` + ); + } + } + + // dataExtractType + try { + metadata.r__dataExtractType_name = cache.searchForField( + 'dataExtractType', + metadata.dataExtractTypeId, + 'extractId', + 'name' + ); + delete metadata.dataExtractTypeId; + } catch (ex) { + Util.logger.warn( + ` - ${this.definition.type} ${metadata[this.definition.keyField]}: ${ex.message}` + ); + } + return metadata; + } + + /** + * helper to allow us to select single metadata entries via REST + * + * @private + * @param {string} key customer key + * @returns {Promise.<string>} objectId or enpty string + */ + static async _getObjectIdForSingleRetrieve(key) { + const name = key.startsWith('name:') ? key.slice(5) : null; + const filter = name ? '?$filter=name%20eq%20' + encodeURIComponent(name) : ''; + const results = await this.client.rest.get('/automation/v1/dataextracts/' + filter); + const items = results?.items || []; + const found = items.find((item) => + name ? item[this.definition.nameField] === name : item[this.definition.keyField] === key + ); + return found?.dataExtractDefinitionId || null; + } + + /** + * Delete a metadata item from the specified business unit + * + * @param {string} key Identifier of data extension + * @returns {Promise.<boolean>} deletion success flag + */ + static async deleteByKey(key) { + // delete only works with the query's object id + const objectId = key ? await this._getObjectIdForSingleRetrieve(key) : null; + if (!objectId) { + await this.deleteNotFound(key); + return false; + } + return super.deleteByKeyREST('/automation/v1/dataextracts/' + objectId, key); } } // Assign definition to static attributes -DataExtract.definition = require('../MetadataTypeDefinitions').dataExtract; -DataExtract.cache = {}; -DataExtract.client = undefined; +import MetadataTypeDefinitions from '../MetadataTypeDefinitions.js'; +DataExtract.definition = MetadataTypeDefinitions.dataExtract; -module.exports = DataExtract; +export default DataExtract; diff --git a/lib/metadataTypes/DataExtractType.js b/lib/metadataTypes/DataExtractType.js index 31a3d0ea7..4d5f1f61a 100644 --- a/lib/metadataTypes/DataExtractType.js +++ b/lib/metadataTypes/DataExtractType.js @@ -1,34 +1,53 @@ 'use strict'; -const MetadataType = require('./MetadataType'); +import MetadataType from './MetadataType.js'; + +/** + * @typedef {import('../../types/mcdev.d.js').BuObject} BuObject + * @typedef {import('../../types/mcdev.d.js').CodeExtract} CodeExtract + * @typedef {import('../../types/mcdev.d.js').CodeExtractItem} CodeExtractItem + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItem} MetadataTypeItem + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItemDiff} MetadataTypeItemDiff + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItemObj} MetadataTypeItemObj + * @typedef {import('../../types/mcdev.d.js').MetadataTypeMap} MetadataTypeMap + * @typedef {import('../../types/mcdev.d.js').MetadataTypeMapObj} MetadataTypeMapObj + * @typedef {import('../../types/mcdev.d.js').SoapRequestParams} SoapRequestParams + * @typedef {import('../../types/mcdev.d.js').TemplateMap} TemplateMap + */ /** * DataExtractType MetadataType * Only for Caching No retrieve/upsert is required * as this is a configuration in the EID + * * @augments MetadataType */ class DataExtractType extends MetadataType { /** * Retrieves Metadata of Data Extract Type. - * @param {String} retrieveDir Directory where retrieved metadata directory will be saved - * @returns {Promise<Object>} Promise of metadata + * + * @param {string} retrieveDir Directory where retrieved metadata directory will be saved + * @param {void | string[]} [_] unused parameter + * @param {void | string[]} [__] unused parameter + * @param {string} [key] customer key of single item to retrieve + * @returns {Promise.<MetadataTypeMapObj>} Promise of metadata */ - static retrieve(retrieveDir) { - return super.retrieveREST(retrieveDir, '/automation/v1/dataextracttypes/', null); + static retrieve(retrieveDir, _, __, key) { + return super.retrieveREST(retrieveDir, '/automation/v1/dataextracttypes/', null, key); } + /** * Retrieves Metadata of Data Extract Type for caching. - * @returns {Promise<Object>} Promise of metadata + * + * @returns {Promise.<MetadataTypeMapObj>} Promise of metadata */ static retrieveForCache() { - return super.retrieveREST(null, '/automation/v1/dataextracttypes/', null); + return super.retrieveREST(null, '/automation/v1/dataextracttypes/'); } } // Assign definition to static attributes -DataExtractType.definition = require('../MetadataTypeDefinitions').dataExtractType; -DataExtractType.cache = {}; -DataExtractType.client = undefined; +import MetadataTypeDefinitions from '../MetadataTypeDefinitions.js'; +DataExtractType.definition = MetadataTypeDefinitions.dataExtractType; -module.exports = DataExtractType; +export default DataExtractType; diff --git a/lib/metadataTypes/DataFilter.js b/lib/metadataTypes/DataFilter.js new file mode 100644 index 000000000..a9e8c1692 --- /dev/null +++ b/lib/metadataTypes/DataFilter.js @@ -0,0 +1,708 @@ +'use strict'; + +import MetadataType from './MetadataType.js'; +import { Util } from '../util/util.js'; +import cache from '../util/cache.js'; +import DataExtensionField from './DataExtensionField.js'; +import Folder from './Folder.js'; +import { XMLBuilder, XMLParser } from 'fast-xml-parser'; +import File from '../util/file.js'; + +/** + * @typedef {import('../../types/mcdev.d.js').BuObject} BuObject + * @typedef {import('../../types/mcdev.d.js').CodeExtract} CodeExtract + * @typedef {import('../../types/mcdev.d.js').CodeExtractItem} CodeExtractItem + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItem} MetadataTypeItem + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItemDiff} MetadataTypeItemDiff + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItemObj} MetadataTypeItemObj + * @typedef {import('../../types/mcdev.d.js').MetadataTypeMap} MetadataTypeMap + * @typedef {import('../../types/mcdev.d.js').MetadataTypeMapObj} MetadataTypeMapObj + * @typedef {import('../../types/mcdev.d.js').SoapRequestParams} SoapRequestParams + * @typedef {import('../../types/mcdev.d.js').TemplateMap} TemplateMap + * @typedef {import('../../types/mcdev.d.js').DataFilterItem} DataFilterItem + * @typedef {import('../../types/mcdev.d.js').DataExtensionFieldMap} DataExtensionFieldMap + * @typedef {import('../../types/mcdev.d.js').DataExtensionFieldItem} DataExtensionFieldItem + * @typedef {import('../../types/mcdev.d.js').DataFilterMap} DataFilterMap + * @typedef {import('../../types/mcdev.d.js').MultiMetadataTypeMap} MultiMetadataTypeMap + * @typedef {import('../../types/mcdev.d.js').FilterConditionSet} FilterConditionSet + * @typedef {import('../../types/mcdev.d.js').FilterCondition} FilterCondition + */ + +/** + * DataFilter (FilterDefinition) MetadataType + * + * @augments MetadataType + */ +class DataFilter extends MetadataType { + static cache = {}; // type internal cache for various things + static deIdKeyMap; + static hidden = false; + /** + * Retrieves all records and saves it to disk + * + * @param {string} retrieveDir Directory where retrieved metadata directory will be saved + * @param {string[]} [_] unused parameter + * @param {string[]} [__] unused parameter + * @param {string} [key] customer key of single item to retrieve + * @returns {Promise.<{metadata: DataFilterMap, type: string}>} Promise of items + */ + static async retrieve(retrieveDir, _, __, key) { + Util.logBeta(this.definition.type); + /** @type {DataFilterMap} */ + const filterDefinitionMap = {}; + + const objectId = key ? await this._getObjectIdForSingleRetrieve(key) : null; + if (objectId) { + const metadataMapSingle = await super.retrieveREST( + null, + '/email/v1/filters/filterdefinition/' + objectId, + null, + key + ); + Object.assign(filterDefinitionMap, metadataMapSingle.metadata); + } else { + const filterFolders = await this._getFilterFolderIds(); + + for (const folderId of filterFolders) { + const metadataMapFolder = await super.retrieveREST( + null, + 'email/v1/filters/filterdefinition/category/' + + folderId + + '?derivedFromType=1,2,3,4&', + null, + key + ); + if (Object.keys(metadataMapFolder.metadata).length) { + Object.assign(filterDefinitionMap, metadataMapFolder.metadata); + if (filterDefinitionMap[key]) { + // if key was found we can stop checking other folders + break; + } + } + } + } + // /** @type {DataFilterMap} */ + // const filterDefinitionMap = metadataTypeMapObj.metadata; + for (const item of Object.values(filterDefinitionMap)) { + // description is not returned when empty + item.description ||= ''; + } + if (retrieveDir) { + // custom dataExtensionField caching + await this._cacheDeFields(filterDefinitionMap, 'retrieve'); + // await this._cacheContactAttributes(filterDefinitionMap); + // await this._cacheMeasures(filterDefinitionMap); + + const savedMetadata = await this.saveResults(filterDefinitionMap, retrieveDir); + Util.logger.info( + `Downloaded: ${this.definition.type} (${Object.keys(savedMetadata).length})` + + Util.getKeysString(key) + ); + } + + return { metadata: filterDefinitionMap, type: this.definition.type }; + } + /** + * helper for {@link DataFilter.retrieve} + * + * @param {boolean} [recached] indicates if this is a recursive call after cache refresh + * @returns {Promise.<number[]>} Array of folder IDs + */ + static async _getFilterFolderIds(recached = false) { + const fromCache = + this.cache[this.buObject.mid]?.folderFilter || cache.getCache().folder + ? Object.values( + this.cache[this.buObject.mid]?.folderFilter || cache.getCache().folder + ) + .filter((item) => item.ContentType === 'filterdefinition') + .filter( + (item) => + (!this.hidden && item.Path.startsWith('Data Filters')) || + (this.hidden && !item.Path.startsWith('Data Filters')) + ) // only retrieve from Data Filters folder + .map((item) => item.ID) + : []; + if (fromCache.length) { + return fromCache; + } + if (recached) { + Util.logger.debug('_getFilterFolderIds: could not find filterdefinition folders'); + return []; + } + + const subTypeArr = ['hidden', 'filterdefinition']; + Util.logger.info(` - Caching dependent Metadata: folder`); + Util.logSubtypes(subTypeArr); + + Folder.client = this.client; + Folder.buObject = this.buObject; + Folder.properties = this.properties; + this.cache[this.buObject.mid] ||= {}; + this.cache[this.buObject.mid].folderFilter = ( + await Folder.retrieveForCache(null, subTypeArr) + ).metadata; + return this._getFilterFolderIds(true); + } + /** + * helper for {@link DataFilter._cacheMeasures} + * + * @returns {Promise.<number[]>} Array of folder IDs + */ + static async _getMeasureFolderIds() { + const fromCache = + this.cache[this.buObject.mid]?.folderMeasure || cache.getCache().folder + ? Object.values( + this.cache[this.buObject.mid]?.folderMeasure || cache.getCache().folder + ) + .filter((item) => item.ContentType === 'measure') + .map((item) => item.ID) + : []; + if (fromCache.length) { + return fromCache; + } + + const subTypeArr = ['measure']; + Util.logger.info(` - Caching dependent Metadata: folder`); + Util.logSubtypes(subTypeArr); + + Folder.client = this.client; + Folder.buObject = this.buObject; + Folder.properties = this.properties; + this.cache[this.buObject.mid] ||= {}; + this.cache[this.buObject.mid].folderMeasure ||= {}; + this.cache[this.buObject.mid].folderMeasure = ( + await Folder.retrieveForCache(null, subTypeArr) + ).metadata; + return this._getMeasureFolderIds(); + } + + /** + * helper for {@link DataFilter.retrieve}. uses cached dataExtensions to resolve dataExtensionFields + * + * @param {DataFilterMap} metadataTypeMap - + * @param {'retrieve'|'deploy'} [mode] - + */ + static async _cacheDeFields(metadataTypeMap, mode) { + const deKeys = + mode === 'retrieve' + ? Object.values(metadataTypeMap) + .filter((item) => item.derivedFromObjectTypeName === 'DataExtension') + .filter((item) => item.derivedFromObjectId) + .map((item) => { + try { + const deKey = cache.searchForField( + 'dataExtension', + item.derivedFromObjectId, + 'ObjectID', + 'CustomerKey' + ); + if (deKey) { + this.deIdKeyMap ||= {}; + this.deIdKeyMap[item.derivedFromObjectId] = deKey; + return deKey; + } + } catch { + return null; + } + }) + .filter(Boolean) + : Object.values(metadataTypeMap) + .filter((item) => item.r__source_dataExtension_key) + .map((item) => item.r__source_dataExtension_key) + .filter( + (deKey) => + !this.cache[this.buObject.mid]?.dataExtensionField || + !this.cache[this.buObject.mid]?.dataExtensionField[deKey] + ) + .filter(Boolean); + if (deKeys.length) { + const deKeysUnique = [...new Set(deKeys)]; + Util.logger.info(' - Caching dependent Metadata: dataExtensionField'); + // only proceed with the download if we have dataExtension keys + const fieldOptions = {}; + for (const deKey of deKeysUnique) { + fieldOptions.filter = fieldOptions.filter + ? { + leftOperand: { + leftOperand: 'DataExtension.CustomerKey', + operator: 'equals', + rightOperand: deKey, + }, + operator: 'OR', + rightOperand: fieldOptions.filter, + } + : { + leftOperand: 'DataExtension.CustomerKey', + operator: 'equals', + rightOperand: deKey, + }; + } + DataExtensionField.buObject = this.buObject; + DataExtensionField.client = this.client; + DataExtensionField.properties = this.properties; + this.saveDataExtensionFieldCacheToMap( + (await DataExtensionField.retrieveForCacheDE(fieldOptions, ['Name', 'ObjectID'])) + .metadata + ); + } + } + /** + * helper for {@link DataFilter._cacheDeFields} + * + * @param {DataExtensionFieldMap} deFieldCache - + */ + static saveDataExtensionFieldCacheToMap(deFieldCache) { + this.cache[this.buObject.mid] ||= {}; + this.cache[this.buObject.mid].dataExtensionField ||= {}; + + if (!deFieldCache) { + return; + } + for (const field of Object.values(deFieldCache)) { + if (!field?.DataExtension?.CustomerKey) { + continue; + } + if ( + !this.cache[this.buObject.mid].dataExtensionField[field.DataExtension.CustomerKey] + ) { + /** @type {Object.<string, DataExtensionFieldItem[]>} */ + this.cache[this.buObject.mid].dataExtensionField[field.DataExtension.CustomerKey] = + []; + } + this.cache[this.buObject.mid].dataExtensionField[field.DataExtension.CustomerKey].push( + field + ); + } + } + /** + * helper for {@link DataFilter.retrieve} + * + * @param {DataFilterMap} metadataTypeMap - + */ + static async _cacheContactAttributes(metadataTypeMap) { + if (this.cache[this.buObject.mid]?.contactAttributes) { + return; + } + const subscriberFilters = Object.values(metadataTypeMap) + .filter((item) => item.derivedFromObjectTypeName === 'SubscriberAttributes') + .filter((item) => item.derivedFromObjectId); + if (subscriberFilters.length) { + Util.logger.info(' - Caching dependent Metadata: contactAttributes'); + const response = await this.client.rest.get('/email/v1/Contacts/Attributes/'); + const keyFieldBackup = this.definition.keyField; + this.definition.keyField = 'id'; + this.cache[this.buObject.mid] ||= {}; + this.cache[this.buObject.mid].contactAttributes = this.parseResponseBody(response); + this.definition.keyField = keyFieldBackup; + } + } + /** + * helper for {@link DataFilter.retrieve} + * + * @param {DataFilterMap} metadataTypeMap - + */ + static async _cacheMeasures(metadataTypeMap) { + if (this.cache?.[this.buObject.mid]?.measures) { + return; + } + const subscriberFilters = Object.values(metadataTypeMap) + .filter((item) => item.derivedFromObjectTypeName === 'SubscriberAttributes') + .filter((item) => item.derivedFromObjectId); + const measureFolders = await this._getMeasureFolderIds(); + if (subscriberFilters.length) { + Util.logger.info(' - Caching dependent Metadata: measure'); + const response = { items: [] }; + for (const folderId of measureFolders) { + const metadataMapFolder = await this.client.rest.getBulk( + 'email/v1/Measures/category/' + folderId + '/', + 250 // 250 is what the GUI is using + ); + if (Object.keys(metadataMapFolder.items).length) { + response.items.push(...metadataMapFolder.items); + } + } + + const keyFieldBackup = this.definition.keyField; + this.definition.keyField = 'measureID'; + this.cache[this.buObject.mid] ||= {}; + this.cache[this.buObject.mid].measures = this.parseResponseBody(response); + this.definition.keyField = keyFieldBackup; + } + } + + /** + * Retrieves all records for caching + * + * @returns {Promise.<{metadata: DataFilterMap, type: string}>} Promise of items + */ + static async retrieveForCache() { + return this.retrieve(null); + } + + /** + * parses retrieved Metadata before saving + * + * @param {DataFilterItem} metadata a single record + * @returns {Promise.<DataFilterItem>} parsed metadata definition + */ + static async postRetrieveTasks(metadata) { + // if (metadata.derivedFromType > 4) { + // // GUI only shows types 1,2,3,4; lets mimic that here. + // // type 6 seems to be journey related. Maybe we need to change that again in the future + // return; + // } + // folder + super.setFolderPath(metadata); + + // parse XML filter for further processing in JSON format + const xmlToJson = new XMLParser({ + preserveOrder: false, // XML parser returns undefined if this is true + ignoreAttributes: false, + allowBooleanAttributes: true, + }); + metadata.c__filterDefinition = xmlToJson.parse( + metadata.filterDefinitionXml + )?.FilterDefinition; + delete metadata.filterDefinitionXml; + switch (metadata.derivedFromType) { + case 1: { + // if (metadata.c__filterDefinition['@_Source'] === 'SubscriberAttribute') { + // if ( + // metadata.derivedFromObjectId && + // metadata.derivedFromObjectId !== '00000000-0000-0000-0000-000000000000' + // ) { + // // Lists + // try { + // metadata.r__source_list_PathName = cache.getListPathName( + // metadata.derivedFromObjectId, + // 'ObjectID' + // ); + // } catch { + // Util.logger.warn( + // ` - skipping ${this.definition.type} ${metadata.key}: list ${metadata.derivedFromObjectId} not found on current or Parent BU` + // ); + // } + // } else { + // // SubscriberAttributes + // // - nothing to do + // } + // } + // // SubscriberAttributes + // this._postRetrieve_resolveAttributeIds(metadata); + // delete metadata.derivedFromObjectId; + // delete metadata.derivedFromObjectName; + // delete metadata.derivedFromObjectTypeName; + // delete metadata.derivedFromType; + // delete metadata.c__filterDefinition['@_Source']; + break; + } + case 2: { + // DataExtension + XXX? + if ( + metadata.c__filterDefinition['@_Source'] === 'Meta' || + metadata.derivedFromObjectId === '00000000-0000-0000-0000-000000000000' + ) { + // TODO - weird so far not understood case of Source=Meta + // sample: <FilterDefinition Source=\"Meta\"><Include><ConditionSet Operator=\"OR\" ConditionSetName=\"Individual Filter Grouping\"><Condition ID=\"55530cec-1df4-e611-80cc-1402ec7222b4\" isParam=\"false\" isPathed=\"true\" pathAttrGroupID=\"75530cec-1df4-e611-80cc-1402ec7222b4\" Operator=\"Equal\"><Value><![CDATA[994607]]></Value></Condition><Condition ID=\"55530cec-1df4-e611-80cc-1402ec7222b4\" isParam=\"false\" isPathed=\"true\" pathAttrGroupID=\"75530cec-1df4-e611-80cc-1402ec7222b4\" Operator=\"Equal\"><Value><![CDATA[3624804]]></Value></Condition></ConditionSet></Include><Exclude></Exclude></FilterDefinition> + } else if (metadata.c__filterDefinition['@_Source'] === 'DataExtension') { + // DataExtension + try { + metadata.r__source_dataExtension_key = + this.deIdKeyMap?.[metadata.derivedFromObjectId] || + cache.searchForField( + 'dataExtension', + metadata.derivedFromObjectId, + 'ObjectID', + 'CustomerKey' + ); + delete metadata.derivedFromObjectName; + delete metadata.derivedFromObjectTypeName; + } catch { + Util.logger.debug( + ` - skipping ${this.definition.type} ${metadata.key}: dataExtension ${metadata.derivedFromObjectId} not found on BU` + ); + return; + } + this._resolveFields(metadata, 'postRetrieve'); + + delete metadata.derivedFromObjectId; + delete metadata.derivedFromType; + delete metadata.c__filterDefinition['@_Source']; + delete metadata.c__filterDefinition['@_SourceID']; + } + break; + } + } + + return metadata; + } + + /** + * helper for {@link postRetrieveTasks} + * + * @param {DataFilterItem} metadata - + * @param {'postRetrieve'|'preDeploy'} mode - + * @param {DataExtensionFieldItem[]} [fieldCache] - + * @param {FilterConditionSet} [filter] - + * @returns {void} + */ + static _resolveFields(metadata, mode, fieldCache, filter) { + if (!filter) { + return this._resolveFields( + metadata, + mode, + this.cache[this.buObject.mid].dataExtensionField[ + metadata.r__source_dataExtension_key + ], + metadata.c__filterDefinition?.ConditionSet + ); + } + if (filter.Condition) { + const conditionsArr = Array.isArray(filter.Condition) + ? filter.Condition + : [filter.Condition]; + if (mode === 'postRetrieve') { + for (const condition of conditionsArr) { + this._postRetrieve_resolveFieldIdsCondition(metadata, condition, fieldCache); + } + } else if (mode === 'preDeploy') { + for (const condition of conditionsArr) { + this._preDeploy_resolveFieldNamesCondition(metadata, condition, fieldCache); + } + } + } + if (filter.ConditionSet) { + const conditionSet = Array.isArray(filter.ConditionSet) + ? filter.ConditionSet + : [filter.ConditionSet]; + for (const cs of conditionSet) { + this._resolveFields(metadata, mode, fieldCache, cs); + } + } + } + /** + * helper for {@link _resolveFields} + * + * @param {DataFilterItem} metadata - + * @param {FilterCondition} condition - + * @param {DataExtensionFieldItem[]} fieldCache - + * @returns {void} + */ + static _postRetrieve_resolveFieldIdsCondition(metadata, condition, fieldCache) { + condition.r__dataExtensionField_name = fieldCache.find( + (field) => field.ObjectID === condition['@_ID'] + )?.Name; + if (condition.r__dataExtensionField_name) { + delete condition['@_ID']; + } else { + Util.logger.warn( + ` - ${this.definition.type} ${metadata[this.definition.keyField]}: could not resolve dataExtensionField with ID ${condition['@_ID']} in condition` + ); + } + if (['IsEmpty', 'IsNotEmpty'].includes(condition['@_Operator'])) { + delete condition.Value; + } + } + /** + * helper for {@link _resolveFields} + * + * @param {DataFilterItem} metadata - + * @param {FilterCondition} condition - + * @param {DataExtensionFieldItem[]} fieldCache - + * @returns {void} + */ + static _preDeploy_resolveFieldNamesCondition(metadata, condition, fieldCache) { + condition['@_ID'] = fieldCache.find( + (field) => field.Name === condition.r__dataExtensionField_name + )?.ObjectID; + if (condition['@_ID']) { + delete condition.r__dataExtensionField_name; + } else { + throw new Error( + ` - ${this.definition.type} ${metadata[this.definition.keyField]}: could not resolve dataExtensionField with Name ${condition.r__dataExtensionField_name} in condition` + ); + } + if (['IsEmpty', 'IsNotEmpty'].includes(condition['@_Operator'])) { + condition.Value ||= ''; + } else if (condition?.Value && typeof condition.Value !== 'object') { + // allow adding cdata + // @ts-ignore + condition.Value = { cdata: condition.Value }; + } + } + /** + * helper for {@link postRetrieveTasks} + * + * @param {DataFilterItem} metadata - + * @param {object} [filter] - + * @returns {void} + */ + static _postRetrieve_resolveAttributeIds(metadata, filter) { + if (!filter) { + return this._postRetrieve_resolveAttributeIds( + metadata, + metadata.c__filterDefinition?.ConditionSet + ); + } + const contactAttributes = this.cache[this.buObject.mid]?.contactAttributes; + const measures = this.cache[this.buObject.mid]?.measures; + const conditionsArr = Array.isArray(filter.Condition) + ? filter.Condition + : [filter.Condition]; + for (const condition of conditionsArr) { + condition['@_ID'] += ''; + if (condition['@_SourceType'] === 'Measure' && measures[condition['@_ID']]) { + condition.r__measure = measures[condition['@_ID']]?.name; + delete condition['@_ID']; + } else if ( + condition['@_SourceType'] !== 'Measure' && + contactAttributes[condition['@_ID']] + ) { + condition.r__contactAttribute = contactAttributes[condition['@_ID']]?.name; + delete condition['@_ID']; + } + if (['IsEmpty', 'IsNotEmpty'].includes(condition['@_Operator'])) { + delete condition.Value; + } + } + if (filter.ConditionSet) { + this._postRetrieve_resolveAttributeIds(metadata, filter.ConditionSet); + } + } + + /** + * prepares a item for deployment + * + * @param {DataFilterItem} metadata a single record + * @returns {Promise.<DataFilterItem>} Promise of updated single item + */ + static async preDeployTasks(metadata) { + // folder + super.setFolderId(metadata); + + // disable updates to r__source_dataExtension_key + // the API and GUI prevent changes to the source data extensions. + // to avoid confusion and accidental changes, we will reset the values from cache before deployment + const normalizedKey = File.reverseFilterIllegalFilenames( + metadata[this.definition.keyField] + ); + const cachedVersion = cache.getByKey(this.definition.type, normalizedKey); + + // DataExtension + if (metadata.r__source_dataExtension_key) { + metadata.derivedFromObjectId = cache.searchForField( + 'dataExtension', + metadata.r__source_dataExtension_key, + 'CustomerKey', + 'ObjectID' + ); + if ( + cachedVersion && + cachedVersion.derivedFromObjectId !== metadata.derivedFromObjectId + ) { + throw new Error( + `Updating r__source_dataExtension_key is not allowed. You need to delete and re-create the dataFilter to change this.` + ); + } + metadata.derivedFromObjectName = cache.searchForField( + 'dataExtension', + metadata.r__source_dataExtension_key, + 'CustomerKey', + 'Name' + ); + metadata.derivedFromObjectTypeName = 'DataExtension'; + metadata.derivedFromType = 2; + metadata.c__filterDefinition['@_Source'] = 'DataExtension'; + metadata.c__filterDefinition['@_SourceID'] = metadata.derivedFromObjectId; + this._resolveFields(metadata, 'preDeploy'); + + delete metadata.r__source_dataExtension_key; + } + + const jsonToXml = new XMLBuilder({ + preserveOrder: false, // XML Builder returns undefined if this is true + ignoreAttributes: false, + cdataPropName: 'cdata', + }); + metadata.filterDefinitionXml = jsonToXml.build({ + FilterDefinition: metadata.c__filterDefinition, + }); + delete metadata.c__filterDefinition; + return metadata; + } + + /** + * MetadataType upsert, after retrieving from target and comparing to check if create or update operation is needed. + * + * @param {MetadataTypeMap} metadataMap metadata mapped by their keyField + * @param {string} deployDir directory where deploy metadata are saved + * @param {boolean} [runUpsertSequentially] when a type has self-dependencies creates need to run one at a time and created/changed keys need to be cached to ensure following creates/updates have thoses keys available + * @returns {Promise.<MetadataTypeMap>} keyField => metadata map + */ + static async upsert(metadataMap, deployDir, runUpsertSequentially = false) { + Util.logBeta(this.definition.type); + await this._cacheDeFields(metadataMap, 'deploy'); + return super.upsert(metadataMap, deployDir, runUpsertSequentially); + } + /** + * Creates a single item + * + * @param {DataFilterItem} metadata a single item + * @returns {Promise.<DataFilterItem>} Promise + */ + static create(metadata) { + return super.createREST(metadata, '/email/v1/filters/filterdefinition/'); + } + /** + * Updates a single item + * + * @param {DataFilterItem} metadata a single item + * @returns {Promise.<DataFilterItem>} Promise + */ + static update(metadata) { + return super.updateREST( + metadata, + '/email/v1/filters/filterdefinition/' + metadata[this.definition.idField] + ); + } + + /** + * helper to allow us to select single metadata entries via REST + * + * @private + * @param {string} key customer key + * @returns {Promise.<string>} objectId or empty string + */ + static async _getObjectIdForSingleRetrieve(key) { + const name = key.startsWith('name:') ? key.slice(5) : null; + const response = await this.client.soap.retrieve(this.definition.soapType, ['ObjectID'], { + filter: { + leftOperand: name ? 'Name' : 'CustomerKey', + operator: 'equals', + rightOperand: name || key, + }, + }); + return response?.Results?.length ? response.Results[0].ObjectID : null; + } + + /** + * Delete a metadata item from the specified business unit + * + * @param {string} key Identifier of data extension + * @returns {Promise.<boolean>} deletion success flag + */ + static async deleteByKey(key) { + // delete only works with the query's object id + const objectId = key ? await this._getObjectIdForSingleRetrieve(key) : null; + if (!objectId) { + await this.deleteNotFound(key); + return false; + } + return super.deleteByKeyREST('/email/v1/filters/filterdefinition/' + objectId, key); + } +} +// Assign definition to static attributes +import MetadataTypeDefinitions from '../MetadataTypeDefinitions.js'; +DataFilter.definition = MetadataTypeDefinitions.dataFilter; + +export default DataFilter; diff --git a/lib/metadataTypes/DataFilterHidden.js b/lib/metadataTypes/DataFilterHidden.js new file mode 100644 index 000000000..d41898dbc --- /dev/null +++ b/lib/metadataTypes/DataFilterHidden.js @@ -0,0 +1,18 @@ +'use strict'; + +// const TYPE = require('../../types/mcdev.d'); +import DataFilter from './DataFilter.js'; + +/** + * DataFilterHidden (FilterDefinitionHidden) MetadataType + * + * @augments DataFilter + */ +class DataFilterHidden extends DataFilter { + static hidden = true; +} +// Assign definition to static attributes +import MetadataTypeDefinitions from '../MetadataTypeDefinitions.js'; +DataFilterHidden.definition = MetadataTypeDefinitions.dataFilterHidden; + +export default DataFilterHidden; diff --git a/lib/metadataTypes/DeliveryProfile.js b/lib/metadataTypes/DeliveryProfile.js new file mode 100644 index 000000000..2c94f7ebf --- /dev/null +++ b/lib/metadataTypes/DeliveryProfile.js @@ -0,0 +1,47 @@ +'use strict'; + +import MetadataType from './MetadataType.js'; + +/** + * @typedef {import('../../types/mcdev.d.js').BuObject} BuObject + * @typedef {import('../../types/mcdev.d.js').CodeExtract} CodeExtract + * @typedef {import('../../types/mcdev.d.js').CodeExtractItem} CodeExtractItem + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItem} MetadataTypeItem + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItemDiff} MetadataTypeItemDiff + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItemObj} MetadataTypeItemObj + * @typedef {import('../../types/mcdev.d.js').MetadataTypeMap} MetadataTypeMap + * @typedef {import('../../types/mcdev.d.js').MetadataTypeMapObj} MetadataTypeMapObj + * @typedef {import('../../types/mcdev.d.js').SoapRequestParams} SoapRequestParams + * @typedef {import('../../types/mcdev.d.js').TemplateMap} TemplateMap + */ + +/** + * DeliveryProfile MetadataType + * + * @augments MetadataType + */ +class DeliveryProfile extends MetadataType { + /** + * Retrieves SOAP based metadata of metadata type into local filesystem. executes callback with retrieved metadata + * + * @param {string} retrieveDir Directory where retrieved metadata directory will be saved + * @param {void | string[]} [_] not used + * @param {void | string[]} [__] unused parameter + * @param {string} [key] customer key of single item to retrieve + * @returns {Promise.<MetadataTypeMapObj>} Promise of metadata + */ + static retrieve(retrieveDir, _, __, key) { + return super.retrieveREST( + retrieveDir, + '/legacy/v1/beta/messaging/deliverypolicy/', + null, + key + ); + } +} + +// Assign definition to static attributes +import MetadataTypeDefinitions from '../MetadataTypeDefinitions.js'; +DeliveryProfile.definition = MetadataTypeDefinitions.deliveryProfile; + +export default DeliveryProfile; diff --git a/lib/metadataTypes/Discovery.js b/lib/metadataTypes/Discovery.js index 7f95baa10..9a9c46202 100644 --- a/lib/metadataTypes/Discovery.js +++ b/lib/metadataTypes/Discovery.js @@ -1,49 +1,66 @@ 'use strict'; -const MetadataType = require('./MetadataType'); -const Util = require('../util/util'); +import MetadataType from './MetadataType.js'; +import { Util } from '../util/util.js'; + +/** + * @typedef {import('../../types/mcdev.d.js').BuObject} BuObject + * @typedef {import('../../types/mcdev.d.js').CodeExtract} CodeExtract + * @typedef {import('../../types/mcdev.d.js').CodeExtractItem} CodeExtractItem + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItem} MetadataTypeItem + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItemDiff} MetadataTypeItemDiff + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItemObj} MetadataTypeItemObj + * @typedef {import('../../types/mcdev.d.js').MetadataTypeMap} MetadataTypeMap + * @typedef {import('../../types/mcdev.d.js').MetadataTypeMapObj} MetadataTypeMapObj + * @typedef {import('../../types/mcdev.d.js').SoapRequestParams} SoapRequestParams + * @typedef {import('../../types/mcdev.d.js').TemplateMap} TemplateMap + */ /** * ImportFile MetadataType + * * @augments MetadataType */ class Discovery extends MetadataType { /** * Retrieves API endpoint * documentation: https://developer.salesforce.com/docs/atlas.en-us.noversion.mc-apis.meta/mc-apis/routes.htm - * @param {String} retrieveDir Directory where retrieved metadata directory will be saved - * @param {String[]} [_] not used - * @param {Object} buObject properties for auth - * @returns {Promise} Promise + * + * @param {string} retrieveDir Directory where retrieved metadata directory will be saved + * @param {void | string[]} [_] not used + * @param {void | string[]} [__] unused parameter + * @param {string} [key] customer key of single item to retrieve + * @returns {Promise.<MetadataTypeMapObj>} Promise */ - static async retrieve(retrieveDir, _, buObject) { - if (buObject.eid !== buObject.mid) { - // don't run for BUs other than Parent BU - Util.logger.warn('Skipping Discovery retrieval on non-parent BU'); - return; - } else { - const res = await Promise.all( - Object.keys(this.definition.endPointMapping).map((endpoint) => - this.client.RestClient.get({ - uri: this.definition.endPointMapping[endpoint], - headers: {}, - }) + static async retrieve(retrieveDir, _, __, key) { + if (key) { + Util.logger.error('Discovery.retrieve() does not support key parameter'); + } + if (this.buObject.eid === this.buObject.mid) { + const res = await this.client.rest.getCollection( + Object.keys(this.definition.endPointMapping).map( + (endpoint) => this.definition.endPointMapping[endpoint] ) ); + const metadataStructure = {}; for (const [i, v] of res.entries()) { - v.body.key = Object.keys(this.definition.endPointMapping)[i]; - metadataStructure[v.body.key] = v.body; + v.key = Object.keys(this.definition.endPointMapping)[i]; + metadataStructure[v.key] = v; } - await this.saveResults(metadataStructure, retrieveDir, null); + await super.saveResults(metadataStructure, retrieveDir, null); Util.logger.info('Downloaded: ' + this.definition.type); return { metadata: metadataStructure, type: this.definition.type }; + } else { + // don't run for BUs other than Parent BU + Util.logger.warn(' - Skipping Discovery retrieval on non-parent BU'); + return; } } } // Assign definition to static attributes -Discovery.definition = require('../MetadataTypeDefinitions').discovery; -Discovery.client = undefined; +import MetadataTypeDefinitions from '../MetadataTypeDefinitions.js'; +Discovery.definition = MetadataTypeDefinitions.discovery; -module.exports = Discovery; +export default Discovery; diff --git a/lib/metadataTypes/DomainVerification.js b/lib/metadataTypes/DomainVerification.js new file mode 100644 index 000000000..e7da4585c --- /dev/null +++ b/lib/metadataTypes/DomainVerification.js @@ -0,0 +1,306 @@ +'use strict'; + +import MetadataType from './MetadataType.js'; +import { Util } from '../util/util.js'; +import cache from '../util/cache.js'; + +/** + * @typedef {import('../../types/mcdev.d.js').BuObject} BuObject + * @typedef {import('../../types/mcdev.d.js').CodeExtract} CodeExtract + * @typedef {import('../../types/mcdev.d.js').CodeExtractItem} CodeExtractItem + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItem} MetadataTypeItem + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItemDiff} MetadataTypeItemDiff + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItemObj} MetadataTypeItemObj + * @typedef {import('../../types/mcdev.d.js').MetadataTypeMap} MetadataTypeMap + * @typedef {import('../../types/mcdev.d.js').MetadataTypeMapObj} MetadataTypeMapObj + * @typedef {import('../../types/mcdev.d.js').SoapRequestParams} SoapRequestParams + * @typedef {import('../../types/mcdev.d.js').TemplateMap} TemplateMap + * @typedef {import('../../types/mcdev.d.js').DomainVerificationItem} DomainVerificationItem + */ + +/** + * DomainVerification MetadataType + * + * @augments MetadataType + */ +class DomainVerification extends MetadataType { + /** + * Retrieves Metadata ofDomainVerification. + * Endpoint /automation/v1/dataextracts/ returns all items + * + * @param {string} retrieveDir Directory where retrieved metadata directory will be saved + * @param {void | string[]} [_] unused parameter + * @param {void | string[]} [__] unused parameter + * @param {string} [key] customer key of single item to retrieve + * @returns {Promise.<MetadataTypeMapObj>} Promise of metadata + */ + static async retrieve(retrieveDir, _, __, key) { + return super.retrieveREST(retrieveDir, '/messaging/v1/domainverification/', null, key); + } + + /** + * Retrieves Metadata of DomainVerification for caching + * + * @returns {Promise.<MetadataTypeMapObj>} Promise of metadata + */ + static async retrieveForCache() { + return super.retrieveREST(null, '/messaging/v1/domainverification/'); + } + + /** + * Creates a single item + * + * @param {DomainVerificationItem} metadataItem a single item + * @returns {Promise} Promise + */ + static create(metadataItem) { + return metadataItem.domain === 'bulk' && + (Array.isArray(metadataItem.addresses) || + (metadataItem.deTable && metadataItem.deColumn)) + ? this.createRESTBulk(metadataItem, '/messaging/v1/domainverification/') // bulk/insert + : super.createREST(metadataItem, '/messaging/v1/domainverification/'); + } + + /** + * Creates a multiple metadata entries via REST + * + * @param {MetadataTypeItem} metadataEntry a single metadata Entry + * @param {string} uri rest endpoint for POST + * @returns {Promise.<object> | null} Promise of API response or null in case of an error + */ + static async createRESTBulk(metadataEntry, uri) { + if (metadataEntry.deTable || metadataEntry.deColumn) { + Util.logger.error( + 'It seems the deTable/deColumn approach does not work. Supply emails via addresses-array instead' + ); + return; + } + const createResults = {}; + for (const address of metadataEntry.addresses) { + if (cache.getByKey(this.definition.type, address)) { + Util.logger.warn(` - ${this.definition.type} ${address} already exists`); + continue; + } + const item = { domain: address }; + if (await this.createREST(item, uri)) { + createResults[address] = true; + } + } + if (Object.keys(createResults).length) { + // trigger re-retrieve to get all fields + await this.postDeployTasks(createResults); + await this.saveResults( + createResults, + [ + this.properties.directories.retrieve, + this.buObject.credential, + this.buObject.businessUnit, + ].join('/'), + null + ); + } + Util.logger.info( + `${this.definition.type} bulk load: ${Object.keys(createResults).length} of ${metadataEntry.addresses.length} created` + ); + if (Object.keys(createResults).length) { + Util.logger.warn('Please ignore the next message about filtering 1 item'); + return `bulk successfully added.`; + } else { + return null; + } + } + + /** + * helper for {@link MetadataType.createREST} + * + * @param {DomainVerificationItem} metadataEntry a single metadata Entry + * @param {object} apiResponse varies depending on the API call + * @returns {Promise.<DomainVerificationItem>} apiResponse + */ + static async postCreateTasks(metadataEntry, apiResponse) { + if (apiResponse && apiResponse === `${metadataEntry.domain} successfully added.`) { + return metadataEntry; + } else { + throw new Error(apiResponse); + } + } + + /** + * helper for {@link update} + * + * @param {DomainVerificationItem} metadataEntry a single metadata Entry + * @param {object} apiResponse varies depending on the API call + * @returns {Promise.<DomainVerificationItem>} apiResponse, potentially modified + */ + static async postUpdateTasks(metadataEntry, apiResponse) { + if (apiResponse && apiResponse === `1 records successfully updated!`) { + metadataEntry.domain = metadataEntry.emailAddress; + return metadataEntry; + } else { + throw new Error(apiResponse); + } + } + + /** + * Updates a single item; replaces super.updateREST because we need to send metadataItem as an array for some reason and also get an array back + * + * @param {DomainVerificationItem} metadataItem a single item + * @returns {Promise.<DomainVerificationItem>} Promise + */ + static async update(metadataItem) { + const uri = '/messaging/v1/domainverification/update'; + + this.removeNotUpdateableFields(metadataItem); + try { + // set to empty object in case API returned nothing to be able to update it in helper classes + let response = (await this.client.rest.post(uri, [metadataItem])) || {}; + this.getErrorsREST(response); + response = await this.postUpdateTasks(metadataItem, response); + // some times, e.g. automation dont return a key in their update response and hence we need to fall back to name + Util.logger.info(` - updated ${Util.getTypeKeyName(this.definition, metadataItem)}`); + return metadataItem; + } catch (ex) { + const parsedErrors = this.getErrorsREST(ex); + Util.logger.error( + ` ☇ error updating ${Util.getTypeKeyName(this.definition, metadataItem)}:` + ); + for (const msg of parsedErrors) { + Util.logger.error(' • ' + msg); + } + return null; + } + } + /** + * manages post retrieve steps + * + * @param {DomainVerificationItem} metadataItem a single item + * @returns {DomainVerificationItem|void} metadata + */ + static postRetrieveTasks(metadataItem) { + if (typeof metadataItem === 'string' && metadataItem === 'bulk successfully added.') { + // this is a hack for bulk-creation only + return; + } + if (metadataItem.status !== 'Verified') { + Util.logger.warn( + Util.getMsgPrefix(this.definition, metadataItem) + + ` is not verified. Current status: ${metadataItem.status}` + ); + } + if (!metadataItem.isSendable) { + Util.logger.warn( + Util.getMsgPrefix(this.definition, metadataItem) + ` is not sendable.` + ); + } + return metadataItem; + } + + /** + * Gets executed after deployment of metadata type + * + * @param {MetadataTypeMap} upsertResults metadata mapped by their keyField as returned by update/create + * @returns {Promise.<void>} - + */ + static async postDeployTasks(upsertResults) { + // re-retrieve all upserted items to ensure we have all fields (createdDate and modifiedDate are otherwise not present) + if (!Object.keys(upsertResults).length) { + return; + } + Util.logger.debug( + `Caching all ${this.definition.type} post-deploy to ensure we have all fields` + ); + const typeCache = await this.retrieveForCache(); + // update values in upsertResults with retrieved values before saving to disk + for (const key of Object.keys(upsertResults)) { + if (typeCache.metadata[key]) { + upsertResults[key] = typeCache.metadata[key]; + } + } + } + + /** + * prepares a single item for deployment + * + * @param {DomainVerificationItem} metadata a single item + * @returns {Promise.<DomainVerificationItem>} Promise + */ + static async preDeployTasks(metadata) { + if (metadata.domainType && metadata.domainType !== 'UserDomain') { + throw new Error( + `Can only delete entries of type 'UserDomain'. Found: ${metadata.domainType}` + ); + } + // prep for update which uses emailAddress instead of domain + metadata.emailAddress = metadata.domain; + + return metadata; + } + + /** + * Gets executed before deleting a list of keys for the current type + * + * @returns {Promise.<void>} - + */ + static async preDeleteTasks() { + if (!cache.getCache()) { + cache.initCache(this.buObject); + } + if (!cache.getCache()?.[this.definition.type]) { + const cached = await this.retrieveForCache(); + if (cached) { + cache.setMetadata(this.definition.type, cached?.metadata); + } + } + } + + /** + * Delete a metadata item from the specified business unit + * + * @param {string} key Identifier of data extension + * @returns {Promise.<boolean>} deletion success flag + */ + static async deleteByKey(key) { + const metadataItem = cache.getByKey(this.definition.type, key); + if (!metadataItem) { + await this.deleteNotFound(key); + return false; + } + if (metadataItem.domainType !== 'UserDomain') { + Util.logger.error( + ` - ${this.definition.type} ${key}: Can only delete entries of type UserDomain. Found: ${metadataItem.domainType}` + ); + return false; + } + try { + const response = await this.client.rest.post( + '/messaging/v1/domainverification/delete', + [ + { + emailAddress: metadataItem.domain, + domainType: metadataItem.domainType, + }, + ] + ); + if (response === '1 records successfully updated!') { + Util.logger.info(` - deleted ${this.definition.type}: ${key}`); + this.postDeleteTasks(key); + return true; + } else { + Util.logger.error( + ` - Deleting ${this.definition.type} '${key}' failed: ` + response + ); + return false; + } + } catch (ex) { + Util.logger.errorStack(ex, ` - Deleting ${this.definition.type} '${key}' failed`); + + return false; + } + } +} + +// Assign definition to static attributes +import MetadataTypeDefinitions from '../MetadataTypeDefinitions.js'; +DomainVerification.definition = MetadataTypeDefinitions.domainVerification; + +export default DomainVerification; diff --git a/lib/metadataTypes/Email.js b/lib/metadataTypes/Email.js index 245beb5ba..bc8c63791 100644 --- a/lib/metadataTypes/Email.js +++ b/lib/metadataTypes/Email.js @@ -1,54 +1,80 @@ 'use strict'; -const MetadataType = require('./MetadataType'); -const Util = require('../util/util'); +import MetadataType from './MetadataType.js'; +import { Util } from '../util/util.js'; + +/** + * @typedef {import('../../types/mcdev.d.js').BuObject} BuObject + * @typedef {import('../../types/mcdev.d.js').CodeExtract} CodeExtract + * @typedef {import('../../types/mcdev.d.js').CodeExtractItem} CodeExtractItem + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItem} MetadataTypeItem + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItemDiff} MetadataTypeItemDiff + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItemObj} MetadataTypeItemObj + * @typedef {import('../../types/mcdev.d.js').MetadataTypeMap} MetadataTypeMap + * @typedef {import('../../types/mcdev.d.js').MetadataTypeMapObj} MetadataTypeMapObj + * @typedef {import('../../types/mcdev.d.js').SoapRequestParams} SoapRequestParams + * @typedef {import('../../types/mcdev.d.js').TemplateMap} TemplateMap + */ /** * Email MetadataType + * * @augments MetadataType */ class Email extends MetadataType { /** * Retrieves SOAP based metadata of metadata type into local filesystem. executes callback with retrieved metadata - * @param {String} retrieveDir Directory where retrieved metadata directory will be saved - * @returns {Promise<Object>} Promise of metadata + * + * @param {string} retrieveDir Directory where retrieved metadata directory will be saved + * @param {void | string[]} [_] unused parameter + * @param {void | string[]} [__] unused parameter + * @param {string} [key] customer key of single item to retrieve + * @returns {Promise.<MetadataTypeMapObj>} Promise of metadata */ - static retrieve(retrieveDir) { - Util.logger.warn( - 'Classic E-Mails are deprecated and will be discontinued by SFMC in the near future. Ensure that you migrate any existing E-Mails to Content Builder as soon as possible.' - ); + static retrieve(retrieveDir, _, __, key) { + /** @type {SoapRequestParams} */ + let requestParams = null; + if (key) { + requestParams = { + filter: { + leftOperand: 'CustomerKey', + operator: 'equals', + rightOperand: key, + }, + }; + } // !dont activate `await File.initPrettier('html');` as we only want to retrieve for migration and formatting might mess with the outcome - return super.retrieveSOAPgeneric(retrieveDir, null); + return super.retrieveSOAP(retrieveDir, requestParams, key); } + /** - * manages post retrieve steps - * @param {Object} metadata a single query - * @returns {Object[]} Array with one metadata object and one query string + * Helper for writing Metadata to disk, used for Retrieve and deploy + * + * @param {MetadataTypeMap} results metadata results from deploy + * @param {string} retrieveDir directory where metadata should be stored after deploy/retrieve + * @param {string} [overrideType] for use when there is a subtype (such as folder-queries) + * @param {TemplateMap} [templateVariables] variables to be replaced in the metadata + * @returns {Promise.<MetadataTypeMap>} Promise of saved metadata */ - static postRetrieveTasks(metadata) { - return this.parseMetadata(metadata); + static async saveResults(results, retrieveDir, overrideType, templateVariables) { + if (Object.keys(results).length) { + // only execute the following if records were found + Util.logger.warn( + ' - Classic E-Mails are deprecated and will be discontinued by SFMC in the near future. Ensure that you migrate any existing E-Mails to Content Builder as soon as possible.' + ); + } + return super.saveResults(results, retrieveDir, overrideType, templateVariables); } + /** - * parses retrieved Metadata before saving - * @param {Object} metadata a single query activity definition - * @returns {Array} Array with one metadata object and one sql string + * manages post retrieve steps + * + * @param {MetadataTypeItem} metadata a single query + * @returns {MetadataTypeItem} Array with one metadata object and one query string */ - static parseMetadata(metadata) { + static postRetrieveTasks(metadata) { // folder - try { - metadata.r__folder_Path = Util.getFromCache( - this.cache, - 'folder', - metadata.CategoryID, - 'ID', - 'Path' - ); - delete metadata.CategoryID; - } catch (ex) { - Util.logger.warn( - `Classic E-Mail '${metadata.Name}'/'${metadata.CustomerKey}': ${ex.message}` - ); - } + super.setFolderPath(metadata); // extract code const codeArr = [ @@ -66,6 +92,7 @@ class Email extends MetadataType { } // Assign definition to static attributes -Email.definition = require('../MetadataTypeDefinitions').email; +import MetadataTypeDefinitions from '../MetadataTypeDefinitions.js'; +Email.definition = MetadataTypeDefinitions.email; -module.exports = Email; +export default Email; diff --git a/lib/metadataTypes/EmailSend.js b/lib/metadataTypes/EmailSend.js new file mode 100644 index 000000000..1b87bbace --- /dev/null +++ b/lib/metadataTypes/EmailSend.js @@ -0,0 +1,418 @@ +'use strict'; + +import MetadataType from './MetadataType.js'; +import { Util } from '../util/util.js'; +import cache from '../util/cache.js'; + +/** + * @typedef {import('../../types/mcdev.d.js').BuObject} BuObject + * @typedef {import('../../types/mcdev.d.js').CodeExtract} CodeExtract + * @typedef {import('../../types/mcdev.d.js').CodeExtractItem} CodeExtractItem + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItem} MetadataTypeItem + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItemDiff} MetadataTypeItemDiff + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItemObj} MetadataTypeItemObj + * @typedef {import('../../types/mcdev.d.js').MetadataTypeMap} MetadataTypeMap + * @typedef {import('../../types/mcdev.d.js').MetadataTypeMapObj} MetadataTypeMapObj + * @typedef {import('../../types/mcdev.d.js').SoapRequestParams} SoapRequestParams + * @typedef {import('../../types/mcdev.d.js').TemplateMap} TemplateMap + */ + +/** + * MessageSendActivity MetadataType + * + * @augments MetadataType + */ +class EmailSend extends MetadataType { + /** + * Retrieves SOAP based metadata of metadata type into local filesystem. executes callback with retrieved metadata + * + * @param {string} [retrieveDir] Directory where retrieved metadata directory will be saved + * @param {void | string[]} [_] unused parameter + * @param {void | string[]} [__] unused parameter + * @param {string} [key] customer key of single item to retrieve + * @returns {Promise.<MetadataTypeMapObj>} Promise of metadata + */ + static retrieve(retrieveDir, _, __, key) { + /** @type {SoapRequestParams} */ + let requestParams = { + filter: { + leftOperand: { + // somehow that parameter controls visible (non deleted?) email send activities + leftOperand: 'IsPlatformObject', + operator: 'equals', + rightOperand: false, + }, + operator: 'AND', + rightOperand: { + leftOperand: 'Description', + operator: 'notEquals', + rightOperand: 'SFSendDefinition', + }, + }, + }; + if (key) { + // move original filter down one level into rightOperand and add key filter into leftOperand + requestParams = { + filter: { + leftOperand: { + leftOperand: 'CustomerKey', + operator: 'equals', + rightOperand: key, + }, + operator: 'AND', + rightOperand: requestParams.filter, + }, + }; + } + return super.retrieveSOAP(retrieveDir, requestParams, key); + } + + /** + * Updates a single item + * + * @param {MetadataTypeItem} metadataItem a single item + * @returns {Promise} Promise + */ + static update(metadataItem) { + return super.updateSOAP(metadataItem); + } + + /** + * Creates a single item + * + * @param {MetadataTypeItem} metadataItem a single item + * @returns {Promise} Promise + */ + static create(metadataItem) { + return super.createSOAP(metadataItem); + } + + /** + * Delete a metadata item from the specified business unit + * + * @param {string} key Identifier of data extension + * @returns {Promise.<boolean>} deletion success status + */ + static deleteByKey(key) { + return super.deleteByKeySOAP(key, undefined, 42002); + } + + /** + * prepares a single item for deployment + * + * @param {MetadataTypeItem} metadata a single script activity definition + * @returns {Promise.<MetadataTypeItem>} Promise + */ + static async preDeployTasks(metadata) { + // re-add IsPlatformObject, required for visibility + metadata.IsPlatformObject = false; + // folder + super.setFolderId(metadata); + // email; in case we still have Email.ID, keep it but warn + metadata.Email ||= {}; + if (metadata.r__email_name) { + // classic + metadata.Email.ID = cache.searchForField('email', metadata.r__email_name, 'Name', 'ID'); + delete metadata.r__email_name; + } else if (metadata.r__asset_key) { + // content builder + // * this ignores r__asset_name_readOnly on purpose\ as that is only unique per parent folder but useful during PR reviews + // will try to find the key with the bu mid at the end, if unable, will try to find the key without it + try { + // check asset key as provided + metadata.Email.ID = cache.searchForField( + 'asset', + metadata.r__asset_key, + 'customerKey', + 'legacyData.legacyId' + ); + delete metadata.r__asset_key; + delete metadata.r__asset_name_readOnly; + } catch { + // if we deploy to another BU, try applying the BU's MID to the end, which we do in preDeployTasks for assets + + // get suffix to update customer key at the end + const suffix = '-' + this.buObject.mid; + + metadata.Email.ID = cache.searchForField( + 'asset', + metadata.r__asset_key.slice(0, Math.max(0, 36 - suffix.length)) + suffix, + 'customerKey', + 'legacyData.legacyId' + ); + delete metadata.r__asset_key; + delete metadata.r__asset_name_readOnly; + } + } else if (metadata.Email.ID) { + Util.logger.warn( + ` - ${this.definition.type} ${metadata[this.definition.nameField]} (${ + metadata[this.definition.keyField] + }): Email.ID was provided manually in your deployment file. We recommend using r__asset_key instead.` + ); + try { + // content builder - test only + cache.searchForField( + 'asset', + metadata.Email.ID, + 'legacyData.legacyId', + 'customerKey' + ); + } catch { + try { + // classic - test only + cache.searchForField('email', metadata.Email.ID, 'ID', 'Name'); + } catch { + throw new Error( + ` ☇ skipping ${this.definition.type} ${metadata.Name} (${metadata.CustomerKey}): Could not find email with ID ${metadata.Email.ID} in Content Builder or Classic Emails.` + ); + } + } + } + // Target Audience DataExtension + // normalize first because this can be an array + if (!metadata.SendDefinitionList) { + metadata.SendDefinitionList = []; + } else if (!Array.isArray(metadata.SendDefinitionList)) { + metadata.SendDefinitionList = [metadata.SendDefinitionList]; + } + // Target Audience source + // - DataSourceTypeID=CustomObject --> DataExtension is source; list is also defined + // - DataSourceTypeID=List --> List is source; DE is not defined + for (const sdl of metadata.SendDefinitionList) { + // get DataExtension (optional) + if (sdl.r__dataExtension_key) { + if (sdl.DataSourceTypeID !== 'CustomObject') { + throw new Error( + `Expecting DataSourceTypeID to equal 'CustomObject' when r__dataExtension_key is defined; Found '${sdl.DataSourceTypeID}'` + ); + } + sdl.CustomObjectID = cache.searchForField( + 'dataExtension', + sdl.r__dataExtension_key, + 'CustomerKey', + 'ObjectID' + ); + delete sdl.r__dataExtension_key; + } else if (sdl.DataSourceTypeID === 'CustomObject') { + throw new Error( + `Expecting r__dataExtension_key to be defined if DataSourceTypeID='CustomObject'` + ); + } + if (!sdl.SalesForceObjectID || sdl.SalesForceObjectID === '') { + // otherwise this causes error 42117 / invalid ObjectID + delete sdl.SalesForceObjectID; + } + // get List (required) + if (sdl.r__list_PathName) { + sdl.List = { + ID: cache.getListObjectId(sdl.r__list_PathName, 'ID'), + }; + delete sdl.r__list_PathName; + } else if (sdl.SendDefinitionListType === 'SourceList') { + // dont throw an error for type 'ExclusionList' + throw new Error( + `Field SendDefinitionList.r__list_PathName was not defined. Please try re-retrieving this ESD from your source BU.` + ); + } + } + + // sender profile + if (metadata.r__senderProfile_key) { + cache.searchForField( + 'senderProfile', + metadata.r__senderProfile_key, + 'CustomerKey', + 'CustomerKey' + ); + metadata.SenderProfile = { + CustomerKey: metadata.r__senderProfile_key, + }; + delete metadata.r__senderProfile_key; + } + // send classification + if (metadata.r__sendClassification_key) { + cache.searchForField( + 'sendClassification', + metadata.r__sendClassification_key, + 'CustomerKey', + 'CustomerKey' + ); + metadata.SendClassification = { + CustomerKey: metadata.r__sendClassification_key, + }; + delete metadata.r__sendClassification_key; + } + // delivery profile + if (metadata.r__deliveryProfile_key) { + cache.searchForField('deliveryProfile', metadata.r__deliveryProfile_key, 'key', 'key'); + metadata.DeliveryProfile = { + CustomerKey: metadata.r__deliveryProfile_key, + }; + delete metadata.r__deliveryProfile_key; + } + + return metadata; + } + + /** + * manages post retrieve steps + * + * @param {MetadataTypeItem} metadata a single query + * @returns {MetadataTypeItem} Array with one metadata object and one query string + */ + static postRetrieveTasks(metadata) { + // remove IsPlatformObject, always has to be 'false' + delete metadata.IsPlatformObject; + // folder + super.setFolderPath(metadata); + + // email + if (metadata.Email?.ID) { + try { + // content builder + const contentBuilderEmailName = cache.searchForField( + 'asset', + metadata.Email.ID, + 'legacyData.legacyId', + 'name' + ); + metadata.r__asset_name_readOnly = contentBuilderEmailName; + const contentBuilderEmailKey = cache.searchForField( + 'asset', + metadata.Email.ID, + 'legacyData.legacyId', + 'customerKey' + ); + metadata.r__asset_key = contentBuilderEmailKey; + delete metadata.Email; + } catch { + try { + // classic + const classicEmail = cache.searchForField( + 'email', + metadata.Email.ID, + 'ID', + 'Name' + ); + metadata.r__email_name = classicEmail; + delete metadata.Email; + } catch { + Util.logger.warn( + ` - ${this.definition.type} ${metadata[this.definition.nameField]} (${ + metadata[this.definition.keyField] + }): Could not find email with ID ${ + metadata.Email.ID + } Content Builder or Classic Emails.` + ); + } + } + } + // Target Audience DataExtension + // normalize first because this can be an array + if (!metadata.SendDefinitionList) { + metadata.SendDefinitionList = []; + } else if (!Array.isArray(metadata.SendDefinitionList)) { + metadata.SendDefinitionList = [metadata.SendDefinitionList]; + } + // Target Audience DataExtension + for (const sdl of metadata.SendDefinitionList) { + // get DataExtension keys + if (sdl.CustomObjectID) { + try { + sdl.r__dataExtension_key = cache.searchForField( + 'dataExtension', + sdl.CustomObjectID, + 'ObjectID', + 'CustomerKey' + ); + delete sdl.CustomObjectID; + } catch { + Util.logger.warn( + ` - ${this.definition.type} ${metadata[this.definition.nameField]} (${ + metadata[this.definition.keyField] + }): Could not find Target Audience (DataExtension) with ObjectID ${ + sdl.CustomObjectID + }.` + ); + } + } + // List + if (sdl.List?.ID) { + try { + sdl.r__list_PathName = cache.getListPathName(sdl.List.ID, 'ID'); + delete sdl.List; + } catch (ex) { + Util.logger.warn( + ` - ${this.definition.type} ${metadata[this.definition.nameField]} (${ + metadata[this.definition.keyField] + }): ${ex.message}` + ); + } + } + if (!sdl.SalesForceObjectID) { + // otherwise this causes error 42117 / invalid ObjectID + delete sdl.SalesForceObjectID; + } + } + + // sender profile + if (metadata.SenderProfile?.CustomerKey) { + try { + cache.searchForField( + 'senderProfile', + metadata.SenderProfile.CustomerKey, + 'CustomerKey', + 'CustomerKey' + ); + metadata.r__senderProfile_key = metadata.SenderProfile.CustomerKey; + delete metadata.SenderProfile; + } catch (ex) { + Util.logger.warn( + ` - ${this.definition.type} ${metadata.CustomerKey}: ${ex.message}` + ); + } + } + // send classification + if (metadata.SendClassification?.CustomerKey) { + try { + cache.searchForField( + 'sendClassification', + metadata.SendClassification.CustomerKey, + 'CustomerKey', + 'CustomerKey' + ); + metadata.r__sendClassification_key = metadata.SendClassification.CustomerKey; + delete metadata.SendClassification; + } catch (ex) { + Util.logger.warn( + ` - ${this.definition.type} ${metadata.CustomerKey}: ${ex.message}` + ); + } + } + // delivery profile + if (metadata.DeliveryProfile?.CustomerKey) { + try { + cache.searchForField( + 'deliveryProfile', + metadata.DeliveryProfile.CustomerKey, + 'key', + 'key' + ); + metadata.r__deliveryProfile_key = metadata.DeliveryProfile.CustomerKey; + delete metadata.DeliveryProfile; + } catch (ex) { + Util.logger.warn( + ` - ${this.definition.type} ${metadata.CustomerKey}: ${ex.message}` + ); + } + } + + return metadata; + } +} + +// Assign definition to static attributes +import MetadataTypeDefinitions from '../MetadataTypeDefinitions.js'; +EmailSend.definition = MetadataTypeDefinitions.emailSend; + +export default EmailSend; diff --git a/lib/metadataTypes/EmailSendDefinition.js b/lib/metadataTypes/EmailSendDefinition.js deleted file mode 100644 index 09d90738c..000000000 --- a/lib/metadataTypes/EmailSendDefinition.js +++ /dev/null @@ -1,266 +0,0 @@ -'use strict'; - -const MetadataType = require('./MetadataType'); -const Util = require('../util/util'); - -/** - * MessageSendActivity MetadataType - * @augments MetadataType - */ -class EmailSendDefinition extends MetadataType { - /** - * Retrieves SOAP based metadata of metadata type into local filesystem. executes callback with retrieved metadata - * @param {String} retrieveDir Directory where retrieved metadata directory will be saved - * @param {void} _ - - * @param {Object} buObject properties for auth - * @returns {Promise<Object>} Promise of metadata - */ - static retrieve(retrieveDir, _, buObject) { - const options = { - filter: { - leftOperand: { - // somehow that parameter controls visible (non deleted?) email send activities - leftOperand: 'IsPlatformObject', - operator: 'equals', - rightOperand: false, - }, - operator: 'AND', - rightOperand: { - leftOperand: 'Description', - operator: 'notEquals', - rightOperand: 'SFSendDefinition', - }, - }, - }; - return super.retrieveSOAPgeneric(retrieveDir, buObject, options); - } - - /** - * Updates a single item - * @param {Object} metadataItem a single item - * @returns {Promise} Promise - */ - static update(metadataItem) { - return super.updateSOAP(metadataItem); - } - - /** - * Creates a single item - * @param {Object} metadataItem a single item - * @returns {Promise} Promise - */ - static create(metadataItem) { - return super.createSOAP(metadataItem); - } - - /** - * prepares a single item for deployment - * @param {Object} metadata a single script activity definition - * @returns {Promise} Promise - */ - static async preDeployTasks(metadata) { - // re-add IsPlatformObject, required for visibility - metadata.IsPlatformObject = false; - // folder - try { - metadata.CategoryID = Util.getFromCache( - this.cache, - 'folder', - metadata.r__folder_Path, - 'Path', - 'ID' - ); - delete metadata.r__folder_Path; - } catch (ex) { - Util.logger.error(`${this.definition.typeName} '${metadata.key}': ${ex.message}`); - } - // email - try { - metadata.Email = {}; - if (metadata.r__email_Name) { - // classic - metadata.Email.ID = Util.getFromCache( - this.cache, - 'email', - metadata.r__email_Name, - 'Name', - 'ID' - ); - delete metadata.r__email_Name; - } else if (metadata.r__assetMessage_Key) { - // content builder - // * this ignores r__assetMessage_Name on purpose as that is only unique per parent folder but useful during PR reviews - metadata.Email.ID = Util.getFromCache( - this.cache, - 'asset', - metadata.r__assetMessage_Key, - 'customerKey', - 'legacyData.legacyId' - ); - delete metadata.r__assetMessage_Key; - delete metadata.r__assetMessage_Name; - } - } catch (ex) { - Util.logger.error(`${this.definition.typeName} '${metadata.key}': ${ex.message}`); - } - // Target Audience DataExtension - // normalize first because this can be an array - if (!metadata.SendDefinitionList) { - metadata.SendDefinitionList = []; - } else if (!Array.isArray(metadata.SendDefinitionList)) { - metadata.SendDefinitionList = [metadata.SendDefinitionList]; - } - // Target Audience source - // - DataSourceTypeID=CustomObject --> DataExtension is source; list is also defined - // - DataSourceTypeID=List --> List is source; DE is not defined - for (const sdl of metadata.SendDefinitionList) { - // get DataExtension (optional) - if (sdl.r__dataExtension_Key) { - if (sdl.DataSourceTypeID !== 'CustomObject') { - throw new Error( - `Skipping ${metadata.Name} (${metadata.CustomerKey}): Expecting DataSourceTypeID to equal 'CustomObject' when r__dataExtension_Key is defined; Found '${sdl.DataSourceTypeID}'` - ); - } - sdl.CustomObjectID = Util.getFromCache( - this.cache, - 'dataExtension', - sdl.r__dataExtension_Key, - 'CustomerKey', - 'ObjectID' - ); - delete sdl.r__dataExtension_Key; - } else if (sdl.DataSourceTypeID === 'CustomObject') { - throw new Error( - `Skipping ${metadata.Name} (${metadata.CustomerKey}): Expecting r__dataExtension_Key to be defined if DataSourceTypeID='CustomObject'` - ); - } - // get List (required) - if (sdl.r__list_PathName) { - sdl.List = { - ID: Util.getListObjectIdFromCache(this.cache, sdl.r__list_PathName, 'ID'), - }; - delete sdl.r__list_PathName; - } else { - throw new Error( - `Field SendDefinitionList.r__list_PathName was not defined. Please try re-retrieving this ESD from your source BU.` - ); - } - } - - return metadata; - } - - /** - * manages post retrieve steps - * @param {Object} metadata a single query - * @returns {Object[]} Array with one metadata object and one query string - */ - static postRetrieveTasks(metadata) { - return this.parseMetadata(metadata); - } - /** - * parses retrieved Metadata before saving - * @param {Object} metadata a single query activity definition - * @returns {Array} Array with one metadata object and one sql string - */ - static parseMetadata(metadata) { - // remove IsPlatformObject, always has to be 'false' - delete metadata.IsPlatformObject; - // folder - try { - metadata.r__folder_Path = Util.getFromCache( - this.cache, - 'folder', - metadata.CategoryID, - 'ID', - 'Path' - ); - delete metadata.CategoryID; - } catch (ex) { - Util.logger.warn( - `${this.definition.typeName} '${metadata.Name}'/'${metadata.CustomerKey}': ${ex.message}` - ); - } - // email - try { - // classic - const classicEmail = Util.getFromCache( - this.cache, - 'email', - metadata.Email.ID, - 'ID', - 'Name' - ); - metadata.r__email_Name = classicEmail; - delete metadata.Email; - } catch (ex) { - try { - // content builder - const contentBuilderEmailName = Util.getFromCache( - this.cache, - 'asset', - metadata.Email.ID, - 'legacyData.legacyId', - 'name' - ); - metadata.r__assetMessage_Name = contentBuilderEmailName; - const contentBuilderEmailKey = Util.getFromCache( - this.cache, - 'asset', - metadata.Email.ID, - 'legacyData.legacyId', - 'customerKey' - ); - metadata.r__assetMessage_Key = contentBuilderEmailKey; - delete metadata.Email; - } catch (ex) { - Util.logger.warn( - `${this.definition.typeName} '${metadata.Name}'/'${metadata.CustomerKey}': Could not find email with ID ${metadata.Email.ID} in Classic nor in Content Builder.` - ); - } - } - // Target Audience DataExtension - // normalize first because this can be an array - if (!metadata.SendDefinitionList) { - metadata.SendDefinitionList = []; - } else if (!Array.isArray(metadata.SendDefinitionList)) { - metadata.SendDefinitionList = [metadata.SendDefinitionList]; - } - // Target Audience DataExtension - for (const sdl of metadata.SendDefinitionList) { - // get DataExtension keys - if (sdl.CustomObjectID) { - try { - sdl.r__dataExtension_Key = Util.getFromCache( - this.cache, - 'dataExtension', - sdl.CustomObjectID, - 'ObjectID', - 'CustomerKey' - ); - delete sdl.CustomObjectID; - } catch (ex) { - Util.logger.warn( - `${this.definition.typeName} '${metadata.Name}'/'${metadata.CustomerKey}': Could not find Target Audience (DataExtension) with ObjectID ${sdl.CustomObjectID}.` - ); - } - } - // List - try { - sdl.r__list_PathName = Util.getListPathNameFromCache(this.cache, sdl.List.ID, 'ID'); - delete sdl.List; - } catch (ex) { - Util.logger.warn( - `${this.definition.typeName} '${metadata.Name}'/'${metadata.CustomerKey}': ${ex.message}` - ); - } - } - - return metadata; - } -} - -// Assign definition to static attributes -EmailSendDefinition.definition = require('../MetadataTypeDefinitions').emailSendDefinition; - -module.exports = EmailSendDefinition; diff --git a/lib/metadataTypes/Event.js b/lib/metadataTypes/Event.js new file mode 100644 index 000000000..f404d5f15 --- /dev/null +++ b/lib/metadataTypes/Event.js @@ -0,0 +1,1309 @@ +'use strict'; + +import MetadataType from './MetadataType.js'; +import { Util } from '../util/util.js'; +import File from '../util/file.js'; +import cache from '../util/cache.js'; +import deepEqual from 'deep-equal'; +import pLimit from 'p-limit'; + +/** + * @typedef {import('../../types/mcdev.d.js').BuObject} BuObject + * @typedef {import('../../types/mcdev.d.js').CodeExtract} CodeExtract + * @typedef {import('../../types/mcdev.d.js').CodeExtractItem} CodeExtractItem + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItem} MetadataTypeItem + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItemDiff} MetadataTypeItemDiff + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItemObj} MetadataTypeItemObj + * @typedef {import('../../types/mcdev.d.js').MetadataTypeMap} MetadataTypeMap + * @typedef {import('../../types/mcdev.d.js').MetadataTypeMapObj} MetadataTypeMapObj + * @typedef {import('../../types/mcdev.d.js').SoapRequestParams} SoapRequestParams + * @typedef {import('../../types/mcdev.d.js').TemplateMap} TemplateMap + * + * @typedef {import('../../types/mcdev.d.js').ReferenceObject} ReferenceObject + * @typedef {import('../../types/mcdev.d.js').SfObjectField} SfObjectField + * @typedef {import('../../types/mcdev.d.js').configurationArguments} configurationArguments + * @typedef {import('../../types/mcdev.d.js').Conditions} Conditions + * @typedef {import('../../types/mcdev.d.js').DataExtensionItem} DataExtensionItem + */ + +/** + * Event MetadataType + * + * @augments MetadataType + */ +class Event extends MetadataType { + static reCacheDataExtensions = []; + static createdKeys = []; + + /** + * Retrieves Metadata of Event Definition. + * Endpoint /interaction/v1/eventDefinitions return all Event Definitions with all details. + * Currently it is not needed to loop over Imports with endpoint /interaction/v1/eventDefinitions/{id} + * + * @param {string} retrieveDir Directory where retrieved metadata directory will be saved + * @param {void | string[]} [_] unused parameter + * @param {void | string[]} [__] unused parameter + * @param {string} [key] customer key of single item to retrieve + * @returns {Promise.<MetadataTypeMapObj>} Promise of metadata + */ + static async retrieve(retrieveDir, _, __, key) { + try { + return await super.retrieveREST( + retrieveDir, + `/interaction/v1/eventDefinitions${ + key ? '/key:' + encodeURIComponent(key) : '' + }?extras=all`, + null, + key + ); + } catch (ex) { + // if the event does not exist, the API returns the error "Request failed with status code 400 (ERR_BAD_REQUEST)" which would otherwise bring execution to a hold + if (key && ex.code === 'ERR_BAD_REQUEST') { + Util.logger.info( + `Downloaded: ${this.definition.type} (0)${Util.getKeysString(key)}` + ); + this.postDeleteTasks(key); + } else { + throw ex; + } + } + return; + } + + /** + * Retrieves event definition metadata for caching + * + * @returns {Promise.<MetadataTypeMapObj>} Promise of metadata + */ + static retrieveForCache() { + return this.retrieve(null); + } + + /** + * Retrieve a specific Event Definition by Name + * + * @deprecated Use `retrieve` followed by `build` instead. `retrieveAsTemplate` will be removed in a future version. + * @param {string} templateDir Directory where retrieved metadata directory will be saved + * @param {string} name name of the metadata file + * @param {TemplateMap} templateVariables variables to be replaced in the metadata + * @returns {Promise.<MetadataTypeItemObj>} Promise of metadata + */ + static async retrieveAsTemplate(templateDir, name, templateVariables) { + Util.logDeprecated('retrieveAsTemplate', `'retrieve' followed by 'build'`); + const res = await this.client.rest.get( + '/interaction/v1/eventDefinitions?name=' + encodeURIComponent(name) + ); + const event = res.items.filter((item) => item.name === name); + try { + if (!event || event.length === 0) { + throw new Error(`No Event Definitions Found with name "${name}"`); + } else if (event.length > 1) { + throw new Error( + `Multiple Event Definitions with name "${name}"` + + `please rename to be unique to avoid issues` + ); + } else if (event?.length === 1) { + const originalKey = event[0][this.definition.keyField]; + const metadataItemTemplated = Util.replaceByObject( + await this.postRetrieveTasks(event[0]), + templateVariables + ); + + if (!metadataItemTemplated.r__dataExtension_key) { + throw new Error( + `Event.postRetrieveTasks:: No Data Extension found for ${this.definition.type}: ${metadataItemTemplated.name}. This cannot be templated.` + ); + } + + // remove all fields listed in Definition for templating + this.keepTemplateFields(metadataItemTemplated); + await File.writeJSONToFile( + [templateDir, this.definition.type].join('/'), + originalKey + '.' + this.definition.type + '-meta', + metadataItemTemplated + ); + Util.logger.info(` - templated ${this.definition.type}: ${name}`); + return { metadata: metadataItemTemplated, type: this.definition.type }; + } else { + throw new Error( + `Encountered unknown error when retrieveing ${ + this.definition.typeName + } "${name}": ${JSON.stringify(res.body)}` + ); + } + } catch (ex) { + Util.logger.error('Event.retrieveAsTemplate:: ' + ex); + return null; + } + } + + /** + * Delete a metadata item from the specified business unit + * + * @param {string} key Identifier of item + * @returns {Promise.<boolean>} deletion success status + */ + static async deleteByKey(key) { + return await super.deleteByKeyREST( + '/interaction/v1/eventDefinitions/key:' + encodeURIComponent(key), + key, + 30000 + ); + } + + /** + * Deploys metadata - merely kept here to be able to print {@link Util.logBeta} once per deploy + * + * @param {MetadataTypeMap} metadata metadata mapped by their keyField + * @param {string} deployDir directory where deploy metadata are saved + * @param {string} retrieveDir directory where metadata after deploy should be saved + * @returns {Promise.<MetadataTypeMap>} Promise of keyField => metadata map + */ + static async deploy(metadata, deployDir, retrieveDir) { + Util.logBeta(this.definition.type); + const metadataMap = await super.deploy(metadata, deployDir, retrieveDir); + + this.createdKeys.length = 0; // reset createdKeys after deploy to ensure it's not used in future retrieves + return metadataMap; + } + + /** + * Creates a single Event Definition + * + * @param {MetadataTypeItem} metadata a single Event Definition + * @returns {Promise} Promise + */ + static create(metadata) { + this.createdKeys.push(metadata[this.definition.keyField]); + return super.createREST(metadata, '/interaction/v1/eventDefinitions/'); + } + + /** + * Updates a single Event Definition (using PUT method since PATCH isn't supported) + * + * @param {MetadataTypeItem} metadataEntry a single Event Definition + * @returns {Promise} Promise + */ + static async update(metadataEntry) { + return super.updateREST( + metadataEntry, + '/interaction/v1/eventDefinitions/key:' + + encodeURIComponent(metadataEntry[this.definition.keyField]), + 'put' + ); + } + + /** + * prepares an event definition for deployment + * + * @param {MetadataTypeItem} metadata a single eventDefinition + * @returns {Promise.<MetadataTypeItem>} parsed version + */ + static async preDeployTasks(metadata) { + // Note: lots has to be done in createOrUpdate based on what action is required + metadata.arguments ||= {}; + metadata.arguments.eventDefinitionKey = metadata.eventDefinitionKey; + + // standard values + metadata.isVisibleInPicker ||= false; + if (metadata.isVisibleInPicker && !metadata.sourceApplicationExtensionId) { + Util.logger.warn( + ` - ${this.definition.type} ${metadata[this.definition.keyField]}: isVisibleInPicker is true but sourceApplicationExtensionId is missing. Setting isVisibleInPicker to false.` + ); + metadata.isVisibleInPicker = false; + } + metadata.isPlatformObject ||= false; + metadata.mode ||= 'Production'; + switch (metadata.type) { + case 'APIEvent': { + metadata.entrySourceGroupConfigUrl ||= + 'jb:///data/entry/api-event/entrysourcegroupconfig.json'; + metadata.iconUrl ||= '/images/icon_journeyBuilder-event-api-blue.svg'; + break; + } + case 'SalesforceObjectTriggerV2': { + metadata.iconUrl ||= '/events/js/salesforce-event/images/SF-Event-Icon.svg'; + break; + } + case 'AutomationAudience': { + metadata.iconUrl ||= '/images/icon-data-extension.svg'; + break; + } + } + + // filter + if (!metadata.filterDefinitionId) { + metadata.filterDefinitionId = '00000000-0000-0000-0000-000000000000'; + } + + // automation + if (metadata.r__automation_key) { + metadata.automationId = cache.searchForField( + 'automation', + metadata.r__automation_key, + 'key', + 'id' + ); + if (metadata.arguments) { + metadata.arguments.automationId = metadata.automationId; + } + } else if (!metadata.automationId) { + // if no automation was linked during retrieve we remove the field and hence need to re-set it before deployment + metadata.automationId = '00000000-0000-0000-0000-000000000000'; + if (metadata.arguments) { + metadata.arguments.automationId = metadata.automationId; + } + } + + // dataExteension + // is resolved in createOrUpdate + + const warnings = await this.preDeployTasks_SalesforceEntryEvents( + metadata.type, + metadata.configurationArguments + ); + if (warnings) { + Util.logger.warn( + ` - ${this.definition.type} '${metadata[this.definition.nameField]}' (${metadata[this.definition.keyField]}): ${warnings}` + ); + } + + await this.compareSalesforceEntryEvents_dataExtension( + metadata.type, + metadata.configurationArguments?.eventDataSummary, + metadata.r__dataExtension_key + ); + + return metadata; + } + + /** + * helper for {@link MetadataType.upsert} + * + * @param {MetadataTypeMap} metadataMap list of metadata + * @param {string} metadataKey key of item we are looking at + * @param {boolean} hasError error flag from previous code + * @param {MetadataTypeItemDiff[]} metadataToUpdate list of items to update + * @param {MetadataTypeItem[]} metadataToCreate list of items to create + * @returns {Promise.<'create'|'update'|'skip'>} action to take + */ + static async createOrUpdate( + metadataMap, + metadataKey, + hasError, + metadataToUpdate, + metadataToCreate + ) { + const createOrUpdateAction = await super.createOrUpdate( + metadataMap, + metadataKey, + hasError, + metadataToUpdate, + metadataToCreate + ); + const metadataItem = metadataMap[metadataKey]; + if (createOrUpdateAction === 'update') { + if (metadataItem.r__dataExtension_key) { + metadataItem.dataExtensionId = cache.searchForField( + 'dataExtension', + metadataItem.r__dataExtension_key, + 'CustomerKey', + 'ObjectID' + ); + metadataItem.dataExtensionName = cache.searchForField( + 'dataExtension', + metadataItem.r__dataExtension_key, + 'CustomerKey', + 'Name' + ); + metadataItem.arguments.dataExtensionId = metadataItem.dataExtensionId; + if (metadataItem.schema) { + metadataItem.schema.id = metadataItem.dataExtensionId; + metadataItem.schema.name = metadataItem.dataExtensionName; + } + } + if (metadataItem.schema?.fields?.length) { + const normalizedKey = File.reverseFilterIllegalFilenames( + metadataMap[metadataKey][this.definition.keyField] + ); + const cachedVersion = cache.getByKey(this.definition.type, normalizedKey); + if (cachedVersion?.schema?.fields?.length) { + const cacheClone = structuredClone(cachedVersion); + cacheClone.schema.fields = cacheClone.schema.fields.map((field) => { + delete field.isDevicePreference; + return field; + }); + if (!deepEqual(metadataItem?.schema?.fields, cacheClone?.schema?.fields)) { + Util.logger.warn( + ` - ${this.definition.type} ${metadataItem[this.definition.keyField]}: schema fields differ from server version. Resetting as this will not be reflected on dataExtension.` + ); + metadataItem.schema.fields = cacheClone.schema.fields; + } + } + } + } else if (createOrUpdateAction === 'create') { + let deFound; + try { + if (metadataItem.r__dataExtension_key) { + metadataItem.dataExtensionId = cache.searchForField( + 'dataExtension', + metadataItem.r__dataExtension_key, + 'CustomerKey', + 'ObjectID' + ); + metadataItem.dataExtensionName = cache.searchForField( + 'dataExtension', + metadataItem.r__dataExtension_key, + 'CustomerKey', + 'Name' + ); + if (metadataItem.schema) { + Util.logger.info( + ` - ${this.definition.type} ${metadataItem[this.definition.keyField]}: dataExtension ${metadataItem.r__dataExtension_key} found, ignoring schema-section in ${this.definition.type} json` + ); + } + deFound = true; + } else { + deFound = false; + } + } catch { + deFound = false; + } + if (!deFound) { + if (metadataItem.r__dataExtension_key) { + if (!metadataItem.schema) { + // make sure we skip this item + this.removeFromDeployment(metadataKey, metadataToUpdate, metadataToCreate); + throw new Error( + `related dataExtension ${metadataItem.r__dataExtension_key} not found` + ); + } + metadataItem.schema.name = metadataItem.r__dataExtension_key; + } + if (!metadataItem.schema) { + this.removeFromDeployment(metadataKey, metadataToUpdate, metadataToCreate); + throw new Error(`no related dataExtension and no schema found`); + } + + Util.logger.warn( + `Data Extension ${metadataItem.schema.name || metadataItem[this.definition.keyField]} not found on BU. Creating it automatically based on schema-definition.` + ); + // we want the event api to create the DE for us based on the schema + this.reCacheDataExtensions.push({ + eventKey: metadataItem[this.definition.keyField], + deKey: metadataItem.schema.name || metadataItem[this.definition.keyField], + }); + } + } + return createOrUpdateAction; + } + + /** + * helper for {@link createOrUpdate} + * + * @param {string} metadataKey key of item we are looking at + * @param {MetadataTypeItemDiff[]} metadataToUpdate list of items to update + * @param {MetadataTypeItem[]} metadataToCreate list of items to create + */ + static removeFromDeployment(metadataKey, metadataToUpdate, metadataToCreate) { + const removeUpdate = metadataToUpdate.findIndex( + (el) => el.after[this.definition.keyField] === metadataKey + ); + if (removeUpdate !== -1) { + metadataToUpdate.splice(removeUpdate, 1); + } + const removeCreate = metadataToCreate.findIndex( + (el) => el[this.definition.keyField] === metadataKey + ); + if (removeCreate !== -1) { + metadataToCreate.splice(removeCreate, 1); + } + } + + /** + * Gets executed after deployment of metadata type + * + * @param {MetadataTypeMap} upsertResults metadata mapped by their keyField as returned by update/create + * @param {MetadataTypeMap} originalMetadata metadata to be updated (contains additioanl fields) + * @param {{created: number, updated: number}} createdUpdated counter representing successful creates/updates + * @returns {Promise.<void>} - + */ + static async postDeployTasks(upsertResults, originalMetadata, createdUpdated) { + // CREATE ONLY - if dataExtensions were auto-created + if (this.reCacheDataExtensions.length && createdUpdated.created > 0) { + Util.logger.warn(' - Re-caching dependent Metadata: dataExtension'); + const deRetrieve = await DataExtension.retrieveForCache(); + cache.setMetadata('dataExtension', deRetrieve.metadata); + const reDownloadDeKeys = []; + // try to update key & name of the auto-generated dataExtension + for (const { eventKey, deKey } of this.reCacheDataExtensions) { + if (!upsertResults[eventKey]) { + continue; + } + const eventItem = upsertResults[eventKey]; + const newDeKey = cache.searchForField( + 'dataExtension', + eventItem.dataExtensionId, + 'ObjectID', + 'CustomerKey' + ); + // get dataExtension from cache which conveniently already has the ObjectID set + const deObj = cache.getByKey('dataExtension', newDeKey); + const oldName = deObj[DataExtension.definition.nameField]; + // prepare a clone of the DE to update name & key to match the event + const clone = structuredClone(deObj); + clone[DataExtension.definition.keyField] = deKey; + clone[DataExtension.definition.nameField] = deKey; + try { + // update DE on server + await DataExtension.update(clone, true); + Util.logger.info( + ` - changed dataExtension ${newDeKey} (${oldName}) key/name to ${deKey}` + ); + // update cache + deObj[DataExtension.definition.keyField] = deKey; + deObj[DataExtension.definition.nameField] = deKey; + + reDownloadDeKeys.push(deObj[DataExtension.definition.keyField]); + } catch { + // fallback, set DE key to value of DE name + const clone = structuredClone(deObj); + clone[DataExtension.definition.keyField] = oldName; + try { + // update DE on server + await DataExtension.update(clone, true); + Util.logger.info( + ` - changed dataExtension ${newDeKey} (${oldName}) key to ${oldName}` + ); + // update cache + deObj[DataExtension.definition.keyField] = + deObj[DataExtension.definition.nameField]; + + reDownloadDeKeys.push(deObj[DataExtension.definition.keyField]); + } catch { + Util.logger.debug( + ` - failed to change dataExtension ${newDeKey} (${oldName}) key/name` + ); + } + } + } + this.reCacheDataExtensions.length = 0; + + // ensure we have downloaded auto-created DEs + if (reDownloadDeKeys.length) { + const retriever = new Retriever(this.properties, this.buObject); + await retriever.retrieve(['dataExtension'], reDownloadDeKeys); + } + } + + // re-retrieve all upserted items to ensure we have all fields (createdDate and modifiedDate are otherwise not present) + Util.logger.debug( + `Caching all ${this.definition.type} post-deploy to ensure we have all fields` + ); + const typeCache = await this.retrieveForCache(); + // update values in upsertResults with retrieved values before saving to disk + for (const key of Object.keys(upsertResults)) { + if (typeCache.metadata[key]) { + upsertResults[key] = typeCache.metadata[key]; + } + } + } + + /** + * parses retrieved Metadata before saving + * + * @param {MetadataTypeItem} metadata a single event definition + * @returns {Promise.<MetadataTypeItem>} parsed metadata + */ + static async postRetrieveTasks(metadata) { + try { + metadata.createdBy = cache.searchForField( + 'user', + metadata.createdBy, + 'AccountUserID', + 'Name' + ); + } catch (ex) { + Util.logger.verbose( + ` - ${this.definition.type} ${metadata[this.definition.nameField]} (${ + metadata[this.definition.keyField] + }): ${ex.message}.` + ); + } + + try { + metadata.modifiedBy = cache.searchForField( + 'user', + metadata.modifiedBy, + 'AccountUserID', + 'Name' + ); + } catch (ex) { + Util.logger.verbose( + ` - ${this.definition.type} ${metadata[this.definition.nameField]} (${ + metadata[this.definition.keyField] + }): ${ex.message}.` + ); + } + + // filter + if ( + metadata?.filterDefinitionId && + metadata.filterDefinitionId === '00000000-0000-0000-0000-000000000000' + ) { + // if no filter is linked this placeholder value is set which holds no value + delete metadata.filterDefinitionId; + } + + // automation + if (metadata?.automationId) { + if (metadata?.automationId === '00000000-0000-0000-0000-000000000000') { + // if no automation is linked this placeholder value is set which holds no value + delete metadata.automationId; + } else { + try { + metadata.r__automation_key = cache.searchForField( + 'automation', + metadata.automationId, + 'id', + 'key' + ); + delete metadata.automationId; + delete metadata.arguments?.automationId; + } catch (ex) { + Util.logger.warn( + ` - ${this.definition.type} ${metadata[this.definition.nameField]} (${ + metadata[this.definition.keyField] + }): ${ex.message}.` + ); + } + } + } + + // dataExtension + try { + metadata.r__dataExtension_key = cache.searchForField( + 'dataExtension', + metadata.dataExtensionId, + 'ObjectID', + 'CustomerKey' + ); + delete metadata.dataExtensionId; + delete metadata.dataExtensionName; + delete metadata.arguments.dataExtensionId; + if (metadata.schema) { + delete metadata.schema.id; + } + } catch (ex) { + Util.logger.verbose( + ` - ${this.definition.type} ${metadata[this.definition.nameField]} (${ + metadata[this.definition.keyField] + }): ${ex.message}.` + ); + } + if (!metadata.isPlatformObject) { + delete metadata.isPlatformObject; + } + if (metadata.mode === 'Production') { + delete metadata.mode; + } + if (!this.createdKeys.includes(metadata[this.definition.keyField])) { + if (metadata.interactionCount === 0 && metadata.publishedInteractionCount === 0) { + Util.logger.warn( + ` - ${this.definition.type} '${metadata[this.definition.nameField]}' (${metadata[this.definition.keyField]}): is not used and could therefore be deleted. Associated Journeys: ${metadata.interactionCount}. Active Journeys: ${metadata.publishedInteractionCount}.` + ); + } else if (metadata.publishedInteractionCount === 0) { + Util.logger.info( + Util.getGrayMsg( + ` - ${this.definition.type} '${metadata[this.definition.nameField]}' (${metadata[this.definition.keyField]}): is currently inactive. Associated Journeys: ${metadata.interactionCount}. Active Journeys: ${metadata.publishedInteractionCount}.` + ) + ); + } + } + + try { + await this.postRetrieveTasks_SalesforceEntryEvents( + metadata.type, + metadata.configurationArguments, + metadata.eventDefinitionKey, + metadata.publishedInteractionCount >= 1 + ); + } catch (ex) { + const msg = ` - ${this.definition.type} '${metadata[this.definition.nameField]}' (${metadata[this.definition.keyField]}) with ${metadata.publishedInteractionCount} active journeys: ${ex.message}`; + Util.logger.warn(metadata.publishedInteractionCount === 0 ? Util.getGrayMsg(msg) : msg); + } + try { + await this.compareSalesforceEntryEvents_dataExtension( + metadata.type, + metadata.configurationArguments?.eventDataSummary, + metadata.r__dataExtension_key + ); + } catch (ex) { + const msg = ` - ${this.definition.type} '${metadata[this.definition.nameField]}' (${metadata[this.definition.keyField]}) with ${metadata.publishedInteractionCount} active journeys: ${ex.message}`; + Util.logger.warn(metadata.publishedInteractionCount === 0 ? Util.getGrayMsg(msg) : msg); + } + + return metadata; + } + static sfObjects = { + /** @type {string[]} */ + workflowObjects: null, + /** @type {Object.<string, ReferenceObject[]>} object-name > object data */ + referencedObjects: {}, + /** @type {Object.<string, Object.<string, SfObjectField>>} object-name > field-name > field data */ + objectFields: {}, + /** @type {Object.<string, Promise.<any>>} */ + loadingFields: {}, + /** @type {Object.<string, Promise.<any>>} */ + loadingRelatedObjects: {}, + /** @type {Promise.<any>} */ + loadingWorkflowObjects: null, + }; + + /** + * helper for {@link checkSalesforceEntryEvents} that retrieves information about SF object fields + * + * @param {string} objectAPIName salesforce object api name + */ + static async getSalesforceObjects(objectAPIName) { + if (!objectAPIName) { + return; + } + + // 1 get all available Salesforce objects + // similar response to /jbint/getWorkflowObjects + if (!this.sfObjects.workflowObjects) { + if (!this.sfObjects.loadingWorkflowObjects) { + this.sfObjects.loadingWorkflowObjects = this._getWorkflowObjects(); + } + await this.sfObjects.loadingWorkflowObjects; + } + + // 2 get objects related to the selected object + // same response as /jbint/getRelatedObjects?type=<objectAPIName> + if (!this.sfObjects.referencedObjects?.[objectAPIName]) { + if (!this.sfObjects.loadingRelatedObjects[objectAPIName]) { + this.sfObjects.loadingRelatedObjects[objectAPIName] = + this._getRelatedSfObjects(objectAPIName); + } + await this.sfObjects.loadingRelatedObjects[objectAPIName]; + + // 3 get fields + const rateLimit = pLimit(20); + const uniqueSfObjectNames = this.sfObjects.referencedObjects[objectAPIName] + ? [ + ...new Set( + Object.values(this.sfObjects.referencedObjects[objectAPIName]) + .map((el) => el.referenceObjectName) + .toSorted() + ), + ] + : []; + await Promise.all( + uniqueSfObjectNames.map((objectAPIName) => + rateLimit(async () => { + this.sfObjects.loadingFields[objectAPIName] ||= + this._getSalesforceObjectFields(objectAPIName); + return this.sfObjects.loadingFields[objectAPIName]; + }) + ) + ); + + // 4 create Common fields + const contactLeadName = 'Contacts and Leads'; + if ( + this.sfObjects.objectFields['Contact'] && + this.sfObjects.objectFields['Lead'] && + !this.sfObjects.workflowObjects.includes(contactLeadName) + ) { + Util.logger.verbose( + Util.getGrayMsg(' - Constructing Common / Contacts and Leads object') + ); + // add fake entry to workflowObjects to allow testing for this easily + this.sfObjects.workflowObjects.push(contactLeadName); + + // construct fields object for it + this.sfObjects.objectFields[contactLeadName] = {}; + const contactFieldNames = Object.keys(this.sfObjects.objectFields['Contact']); + const leadFieldNames = Object.keys(this.sfObjects.objectFields['Lead']); + for (const fieldName of contactFieldNames.filter((item) => + leadFieldNames.includes(item) + )) { + // copy the value from contact - while thats not perfectly correct it will hopefully be sufficient for what we need to check + this.sfObjects.objectFields[contactLeadName][fieldName] = structuredClone( + this.sfObjects.objectFields['Contact'][fieldName] + ); + this.sfObjects.objectFields[contactLeadName][fieldName].objectname = 'Common'; + + // do not delete fields from Contact or Lead because it depends on the environment where we have to look for those + } + // create duplicate to also reference this via "Common" + this.sfObjects.objectFields['Common'] = + this.sfObjects.objectFields[contactLeadName]; + } + } + return; + } + /** + * helper that allows skipping to run this again in multi-key retrieval + */ + static async _getWorkflowObjects() { + Util.logger.info(Util.getGrayMsg(' - Caching Salesforce Objects')); + const workflowObjectsResponse = await this.client.rest.get( + `/data/v1/integration/member/salesforce/workflowobjects` + ); + this.sfObjects.workflowObjects = workflowObjectsResponse + ? workflowObjectsResponse.map((o) => o.apiname) + : []; + } + /** + * helper that allows skipping to run this again in multi-key retrieval + * + * @param {string} objectAPIName SF entry object of the current event + */ + static async _getRelatedSfObjects(objectAPIName) { + Util.logger.info( + Util.getGrayMsg(' - Caching Related Salesforce Objects for ' + objectAPIName) + ); + try { + const referenceObjectsResponse = await this.client.rest.get( + `/data/v1/integration/member/salesforce/object/${objectAPIName}/referenceobjects` + ); + // add itself first so that we get the fields for objectAPIName as well + const selfReference = { + referenceObjectName: objectAPIName, + relationshipName: objectAPIName, + }; + this.sfObjects.referencedObjects[objectAPIName] = referenceObjectsResponse + ? [selfReference, ...referenceObjectsResponse] + : [selfReference]; + if ( + referenceObjectsResponse.some((el) => el.referenceObjectName === 'Lead') && + referenceObjectsResponse.some((el) => el.referenceObjectName === 'Contact') + ) { + // add fake object "Common" to referenced objects for testing + this.sfObjects.referencedObjects[objectAPIName].push({ + displayname: 'Common', + relationshipIdName: 'Id', + relationshipName: 'Common', + isPolymorphic: false, + referenceObjectName: 'Common', + }); + } + } catch (ex) { + if (ex.code === 'ERR_BAD_RESPONSE') { + throw new Error( + `Could not find Salesforce entry object ${objectAPIName} on connected org.`, + { cause: ex } + ); + } + } + } + /** + * helper that allows skipping to run this again in multi-key retrieval + * + * @param {string} objectAPIName SF object for which to get the fields + */ + static async _getSalesforceObjectFields(objectAPIName) { + if (this.sfObjects.objectFields[objectAPIName] || objectAPIName === 'Common') { + return; + } + Util.logger.verbose( + Util.getGrayMsg(' - Caching Fields for Salesforce Object ' + objectAPIName) + ); + + const referenceObjectsFieldsResponse = await this.client.rest.get( + `/legacy/v1/beta/integration/member/salesforce/object/${objectAPIName}` + ); + if (referenceObjectsFieldsResponse?.sfobjectfields?.length) { + Util.logger.debug( + `Found ${referenceObjectsFieldsResponse?.sfobjectfields?.length} fields for Salesforce Object ${objectAPIName}` + ); + this.sfObjects.objectFields[objectAPIName] = {}; + // !add default fields that are somehow not always returned by this legacy beta API + for (const field of this.defaultSalesforceFields) { + // @ts-expect-error hack to work around shortcomings of legacy beta API + this.sfObjects.objectFields[objectAPIName][field] = { + label: field, + name: field, + }; + } + // add fields returned by API + for (const field of referenceObjectsFieldsResponse.sfobjectfields) { + this.sfObjects.objectFields[objectAPIName][field.name] = field; + } + } else { + Util.logger.warn( + `Could not cache fields for Salesforce Object '${objectAPIName}'. This is likely caused by insufficient access of your MC-Connect integration user. Please check assigned permission sets / the profile.` + ); + } + return; + } + + static defaultSalesforceFields = [ + 'Id', + 'Name', + 'FirstName', + 'LastName', + 'Phone', + 'CreatedById', + 'CreatedDate', + 'IsDeleted', + 'LastModifiedById', + 'LastModifiedDate', + 'SystemModstamp', + ]; + + /** + * + * @param {configurationArguments} ca trigger[0].configurationArguments + * @param {boolean} isPublished if the current item is published it means we do not need to do contact vs common checks + * @returns {string} warnings or null + */ + static checkSalesforceEntryEvents(ca, isPublished) { + // 1 check eventDataConfig + const edcObjects = ca.eventDataConfig.objects.toSorted((a, b) => + a.dePrefix.localeCompare(b.dePrefix) + ); + const warnings = []; + const errors = []; + const dePrefixFields = {}; + const dePrefixRelationshipMap = {}; + const dePrefixReferenceObjectMap = {}; + // SFMC only uses "Common" to aggreagate Contacts and Leads if that was actively selected in the entry event. Also, already published journeys/events continue to work even if fields would later be changed, leading to a shift from or to the "common" fake-object. + const checkCommon = + ca.whoToInject === 'Contact ID/Lead ID (Contacts and Leads)' && !isPublished; + for (const object of edcObjects) { + // create secondary object to quickly check eventDataSummary against + dePrefixFields[object.dePrefix] = object.fields; + + // if the current object is the entry object then relationshipName and referenceObject are set to empty strings because it's not "referencing" a "relationship" but just listing its own fields + dePrefixRelationshipMap[object.dePrefix] = + object.relationshipName === '' + ? object.dePrefix.split(':')[0] + : object.relationshipName; + dePrefixReferenceObjectMap[object.dePrefix] = + object.referenceObject === '' + ? object.dePrefix.split(':')[0] + : object.referenceObject; + + // 1.1 check if fields in eventDataConfig exist in Salesforce + // if it has no value this is the entry-source object itself + const referencedObject = + object.referenceObject === '' ? ca.objectAPIName : object.referenceObject; + // sort list of fields alphabetically + object.fields.sort(); + // check if object was cached earlier + if (!this.sfObjects.workflowObjects.includes(referencedObject)) { + errors.push(`Salesforce object ${referencedObject} not found on connected org.`); + } else if ( + !this.sfObjects.objectFields[referencedObject] || + !Object.keys(this.sfObjects.objectFields[referencedObject]).length + ) { + // check if we found fields for the object + const msg = + `Fields for Salesforce object ${referencedObject} could not be checked. Fields selected in entry event: ` + + object.fields.join(', '); + if (Util.OPTIONS.ignoreSfFields) { + warnings.push(` (--ignoreSfFields) ` + msg); + } else { + errors.push( + msg + + ` (you can use --ignoreSfFields to skip this error in case you are convinced it is a false positive)` + ); + } + } else { + // check if the fields selected in the eventDefinition are actually available + for (const fieldName of object.fields) { + if ( + checkCommon && + (referencedObject === 'Contact' || referencedObject === 'Lead') && + this.sfObjects.objectFields['Common'][fieldName] + ) { + errors.push( + `Salesforce object field ${referencedObject}.${fieldName} needs to be referenced as Common.${fieldName}` + ); + } else if (!this.sfObjects.objectFields[referencedObject][fieldName]) { + // TODO reactivate after switch to new API + // errors.push( + // `Salesforce object field ${referencedObject}.${fieldName} not available on connected org.` + // ); + } + // 1.2 check if all fields in eventDataConfig are listed in the eventDataSummary + if (!ca.eventDataSummary.includes(object.dePrefix + fieldName)) { + // we could auto-create eventDataSummary but frankly this is good for code reviews and for searching for fields + errors.push( + `Field ${object.dePrefix + fieldName} is listed under eventDataConfig${object.referenceObject ? ` for referenceObject ` + object.referenceObject : ''} but not in eventDataSummary` + ); + } + } + } + } + + // 2 compare eventDataConfig with eventDataSummary + // check if all fields in eventDataSummary are listed in the eventDataConfig + + for (let fieldName of ca.eventDataSummary) { + // we could auto-create eventDataSummary but frankly this is good for code reviews and for searching for fields + const fieldPath = fieldName.split(':'); + fieldName = fieldPath.pop(); + const dePrefix = fieldPath.join(':') + ':'; + if (!dePrefixFields[dePrefix]) { + errors.push( + `Field ${dePrefix + fieldName} is listed under eventDataSummary but object ${dePrefix} was not found in eventDataConfig` + ); + } else if (!dePrefixFields[dePrefix]?.includes(fieldName)) { + errors.push( + `Field ${dePrefix + fieldName} is listed under eventDataSummary but not in eventDataConfig` + ); + } + } + + // 3 check contactKey + // check against referencedObjects + const referencedContactObj = this.sfObjects.referencedObjects[ca.objectAPIName].find( + (el) => + el.relationshipName === + (ca.contactKey.relationshipName == '' + ? ca.contactKey.referenceObjectName + : ca.contactKey.relationshipName) + ); + if (referencedContactObj) { + if ( + ca.contactKey.isPolymorphic && + referencedContactObj.isPolymorphic !== ca.contactKey.isPolymorphic + ) { + errors.push( + `configurationArguments.contactKey states an incorrect isPolimorphic value. Should be ${referencedContactObj.isPolymorphic}` + ); + } + if (referencedContactObj.referenceObjectName !== ca.contactKey.referenceObjectName) { + errors.push( + `configurationArguments.contactKey states an incorrect referenceObjectName value. Should be ${referencedContactObj.referenceObjectName}` + ); + } + // * if contactKey uses "Common" then there is no fieldName attribute but instead relationshipIdName needs to be checked + if ( + checkCommon && + ca.contactKey.referenceObjectName === 'Contact' && + this.sfObjects.objectFields['Common'][ + ca.contactKey.fieldName || ca.contactKey.relationshipIdName + ] + ) { + errors.push( + `configurationArguments.contactKey should be referencing Common instead of Contact` + ); + } else if ( + !this.sfObjects.objectFields[ca.contactKey.referenceObjectName]?.[ + ca.contactKey.fieldName || ca.contactKey.relationshipIdName + ] + ) { + errors.push( + `configurationArguments.contactKey states the invalid fieldName '${ca.contactKey.fieldName || ca.contactKey.relationshipIdName}' value that does not exist on ${ca.contactKey.referenceObjectName}` + ); + } + } else { + errors.push( + `configurationArguments.contactKey references ${ + ca.contactKey.relationshipName == '' + ? ca.contactKey.referenceObjectName + : ca.contactKey.relationshipName + } which is not found in related salesforce objects` + ); + } + + // 4 check passThroughArgument + const dePrefixCommon = ca.objectAPIName + ':Common'; + for (const key of Object.keys(ca.passThroughArgument.fields)) { + const fieldPath = ca.passThroughArgument.fields[key].split(':'); + const fieldName = fieldPath.pop(); + const dePrefix = fieldPath.join(':') + ':'; + // it seems these fields do NOT need to be in the eventDataConfig + const relationshipName = dePrefixRelationshipMap[dePrefix]; + const referenceObject = dePrefixReferenceObjectMap[dePrefix]; + + if (!this.sfObjects.objectFields[referenceObject]?.[fieldName]) { + errors.push( + `Field ${dePrefix + fieldName} is listed under passThroughArgument.fields.${key} but is not available on connected org.` + ); + } else if ( + checkCommon && + (relationshipName === 'Contact' || relationshipName === 'Lead') && + this.sfObjects.objectFields['Common']?.[fieldName] + ) { + errors.push( + `Field ${dePrefix + fieldName} is listed under passThroughArgument.fields.${key} but needs to be referenced as ${dePrefixCommon}.${fieldName}` + ); + } + } + + // 5.a check primaryObjectFilterCriteria + this.checkSfFilterFieldsExist( + ca.primaryObjectFilterCriteria.conditions, + errors, + 'primaryObjectFilterCriteria' + ); + + // 5.b check relatedObjectFilterCriteria + this.checkSfFilterFieldsExist( + ca.relatedObjectFilterCriteria.conditions, + errors, + 'relatedObjectFilterCriteria' + ); + + // 6.a remove primaryObjectFilterSummary (and auto-generate it again in preDeploy from primaryObjectFilterCriteria) + // TODO + // 6.b remove relatedObjectFilterSummary (and auto-generate it again in preDeploy from relatedObjectFilterCriteria) + // TODO + + // 7 remove eventDataSummary (and auto-generate it again in preDeploy from eventDataConfig) + // TODO + + // 8 remove evaluationCriteriaSummary (and auto-generate it again in preDeploy from salesforceTriggerCriteria) + // TODO + + // throw error if problems were found + if (errors?.length) { + // add a line break + if (errors.length > 1) { + errors.unshift(``); + } + throw new Error(errors.join('\n · ')); + } + if (warnings?.length) { + // add a line break + if (warnings.length > 1) { + warnings.unshift(``); + } + return warnings.join('\n · '); + } else { + return null; + } + } + + /** + * + * @param {object[]} conditions - + * @param {string[]} errors list of errors + * @param {'primaryObjectFilterCriteria'|'relatedObjectFilterCriteria'} context used to improve error logs + */ + static checkSfFilterFieldsExist(conditions, errors, context) { + for (const condition of conditions) { + if ( + condition.fieldName & condition.referenceObjectName && + !this.sfObjects.objectFields[condition.referenceObjectName]?.[condition.fieldName] + ) { + errors.push( + `Field ${condition.referenceObjectName}.${condition.fieldName} is listed under ${context} but is not available on connected org.` + ); + } else if (condition.conditions) { + this.checkSfFilterFieldsExist(condition.conditions, errors, context); + } + } + } + + static requiredConfigurationArguments = [ + 'applicationExtensionKey', + 'contactKey', + 'contactPersonType', + 'eventDataConfig', + 'objectAPIName', + 'passThroughArgument', + 'primaryObjectFilterCriteria', + 'relatedObjectFilterCriteria', + 'salesforceTriggerCriteria', + 'version', + 'whoToInject', + ]; + /** + * + * @param {string} triggerType e.g. SalesforceObjectTriggerV2, APIEvent, ... + * @param {configurationArguments} ca trigger[0].configurationArguments + * @param {string} key of event / journey + * @param {boolean} isPublished if the current item is published it means we do not need to do contact vs common checks + * @param {string} [type] optionally provide metadatype for error on missing configurationArguments attributes + * @returns {Promise.<void>} - + */ + static async postRetrieveTasks_SalesforceEntryEvents(triggerType, ca, key, isPublished, type) { + if (triggerType !== 'SalesforceObjectTriggerV2' || !ca) { + return; + } + // normalize payload because these fields are sometimes set as strings and sometimes as objects + // @ts-expect-error journeys SOMETIMES spell it "Api" and this script aims to auto-correct that + if (ca.objectApiName) { + // on event only the uppercase version is used. lets make sure we normalize that here. + // @ts-expect-error journeys SOMETIMES spell it "Api" and this script aims to auto-correct that + ca.objectAPIName = ca.objectApiName; + // @ts-expect-error journeys SOMETIMES spell it "Api" and this script aims to auto-correct that + delete ca.objectApiName; + } + + // check if everything important is there or else MC Connect cannot publish this AND other journeys + for (const attribute of this.requiredConfigurationArguments) { + if (!ca[attribute]) { + Util.logger.error( + ` - ${type || this.definition.type} ${key}: required field configurationArguments.${attribute} not set` + ); + } + } + + // normalize payload because these fields are sometimes set as strings and sometimes as objects + ca.contactKey = + 'string' === typeof ca.contactKey ? JSON.parse(ca.contactKey) : ca.contactKey; + ca.eventDataConfig = + 'string' === typeof ca.eventDataConfig + ? JSON.parse(ca.eventDataConfig) + : ca.eventDataConfig; + ca.eventDataSummary = + 'string' === typeof ca.eventDataSummary + ? // @ts-expect-error transforming this from API-string-format to from mcdev-format + ca.eventDataSummary.split('; ').filter(Boolean).toSorted() + : ca.eventDataSummary; + ca.passThroughArgument = + 'string' === typeof ca.passThroughArgument + ? JSON.parse(ca.passThroughArgument) + : ca.passThroughArgument; + ca.primaryObjectFilterCriteria = + 'string' === typeof ca.primaryObjectFilterCriteria + ? JSON.parse(ca.primaryObjectFilterCriteria) + : ca.primaryObjectFilterCriteria; + ca.relatedObjectFilterCriteria = + 'string' === typeof ca.relatedObjectFilterCriteria + ? JSON.parse(ca.relatedObjectFilterCriteria) + : ca.relatedObjectFilterCriteria; + + // get info about salesforce objects if not already cached + // * SF product team actually sometimes sets this field with uppercase "API" and sometimes with "Api"... Great job, guys! + await this.getSalesforceObjects(ca.objectAPIName); + + // check if whats on the journey matches what SF Core offers + this.checkSalesforceEntryEvents(ca, isPublished); + } + /** + * + * @param {string} triggerType e.g. SalesforceObjectTriggerV2, APIEvent, ... + * @param {string[]} eventDataSummary eventDataConfig in simplified string-form + * @param {string} deKey key of associated dataExtension + * @returns {Promise.<void>} - + */ + static async compareSalesforceEntryEvents_dataExtension( + triggerType, + eventDataSummary, + + deKey + ) { + if (triggerType !== 'SalesforceObjectTriggerV2' || !eventDataSummary) { + return; + } + + /** @type {DataExtensionItem} */ + const deItem = deKey ? cache.getByKey('dataExtension', deKey) : null; + if (!deItem) { + return; + } + + eventDataSummary = + 'string' === typeof eventDataSummary + ? // @ts-expect-error transforming this from API-string-format to from mcdev-format + eventDataSummary.split('; ').filter(Boolean).toSorted() + : eventDataSummary; + + const errors = []; + for (const fieldName of eventDataSummary) { + if (!deItem.Fields.find((field) => field.Name === fieldName)) { + errors.push( + `Field ${fieldName} was not found in associated dataExtension ${deKey}` + ); + } + } + if (errors?.length) { + // add a line break + if (errors.length > 1) { + errors.unshift(``); + } + throw new Error(errors.join('\n · ')); + } + } + + /** + * + * @param {string} triggerType e.g. SalesforceObjectTriggerV2, APIEvent, ... + * @param {configurationArguments} ca trigger[0].configurationArguments + * @returns {Promise.<string>} - + */ + static async preDeployTasks_SalesforceEntryEvents(triggerType, ca) { + if (triggerType !== 'SalesforceObjectTriggerV2' || !ca) { + return; + } + + // check if everything important is there or else MC Connect cannot publish this AND other journeys + const missingFields = []; + for (const attribute of this.requiredConfigurationArguments) { + if (!ca[attribute]) { + missingFields.push(attribute); + } + } + if (missingFields.length) { + throw new Error( + `required field not set: \n -` + + missingFields + .map((attribute) => `configurationArguments.${attribute}`) + .join('\n - ') + ); + } + + // get info about salesforce objects if not already cached + await this.getSalesforceObjects(ca.objectAPIName); + + // check if whats on the journey matches what SF Core offers + + const warnings = this.checkSalesforceEntryEvents(ca, false); + + // normalize payload because these fields are sometimes set as strings and sometimes as objects + // @ts-expect-error reverting this back from mcdev-format to API format + ca.contactKey = + 'object' === typeof ca.contactKey ? JSON.stringify(ca.contactKey) : ca.contactKey; + // @ts-expect-error reverting this back from mcdev-format to API format + ca.eventDataConfig = + 'object' === typeof ca.eventDataConfig + ? JSON.stringify(ca.eventDataConfig) + : ca.eventDataConfig; + // @ts-expect-error reverting this back from mcdev-format to API format + ca.eventDataSummary = Array.isArray(ca.eventDataSummary) + ? ca.eventDataSummary.join('; ') + '; ' + : ca.eventDataSummary; + // @ts-expect-error reverting this back from mcdev-format to API format + ca.passThroughArgument = + 'object' === typeof ca.passThroughArgument + ? JSON.stringify(ca.passThroughArgument) + : ca.passThroughArgument; + // @ts-expect-error reverting this back from mcdev-format to API format + ca.primaryObjectFilterCriteria = + 'object' === typeof ca.primaryObjectFilterCriteria + ? JSON.stringify(ca.primaryObjectFilterCriteria) + : ca.primaryObjectFilterCriteria; + // @ts-expect-error reverting this back from mcdev-format to API format + ca.relatedObjectFilterCriteria = + 'object' === typeof ca.relatedObjectFilterCriteria + ? JSON.stringify(ca.relatedObjectFilterCriteria) + : ca.relatedObjectFilterCriteria; + + // @ts-expect-error journeys SOMETIMES spell it "Api" and this script aims to auto-correct that + if (ca.objectApiName) { + // on event only the uppercase version is used. lets make sure we normalize that here. + // @ts-expect-error journeys SOMETIMES spell it "Api" and this script aims to auto-correct that + ca.objectAPIName = ca.objectApiName; + // @ts-expect-error journeys SOMETIMES spell it "Api" and this script aims to auto-correct that + delete ca.objectApiName; + } + return warnings; + } +} + +// Assign definition to static attributes +import MetadataTypeDefinitions from '../MetadataTypeDefinitions.js'; +import DataExtension from './DataExtension.js'; +import Retriever from './../Retriever.js'; +Event.definition = MetadataTypeDefinitions.event; + +export default Event; diff --git a/lib/metadataTypes/EventDefinition.js b/lib/metadataTypes/EventDefinition.js deleted file mode 100644 index 35290769f..000000000 --- a/lib/metadataTypes/EventDefinition.js +++ /dev/null @@ -1,192 +0,0 @@ -'use strict'; - -const MetadataType = require('./MetadataType'); -const Util = require('../util/util'); -const File = require('../util/file'); - -/** - * EventDefinition MetadataType - * @augments MetadataType - */ -class EventDefinition extends MetadataType { - /** - * Retrieves Metadata of Event Definition. - * Endpoint /interaction/v1/EventDefinitions return all Event Definitions with all details. - * Currently it is not needed to loop over Imports with endpoint /interaction/v1/EventDefinitions/{id} - * @param {String} retrieveDir Directory where retrieved metadata directory will be saved - * @returns {Promise<Object>} Promise of metadata - */ - static retrieve(retrieveDir) { - return super.retrieveREST(retrieveDir, '/interaction/v1/EventDefinitions/', null); - } - - /** - * Retrieves event definition metadata for caching - * @returns {Promise<Object>} Promise of metadata - */ - static retrieveForCache() { - return super.retrieveREST(null, '/interaction/v1/EventDefinitions/', null); - } - - /** - * Retrieve a specific Event Definition by Name - * @param {String} templateDir Directory where retrieved metadata directory will be saved - * @param {String} name name of the metadata file - * @param {Object} templateVariables variables to be replaced in the metadata - * @returns {Promise<Object>} Promise of metadata - */ - static async retrieveAsTemplate(templateDir, name, templateVariables) { - // todo template based on name - const options = { - uri: '/interaction/v1/EventDefinitions?name=' + encodeURIComponent(name), - }; - const res = await this.client.RestClient.get(options); - const event = res.body.items.filter((item) => item.name === name); - try { - if (!event || event.length === 0) { - throw new Error(`No Event Definitions Found with name "${name}"`); - } else if (event.length > 1) { - throw new Error( - `Multiple Event Definitions with name "${name}"` + - `please rename to be unique to avoid issues` - ); - } else if (event && event.length === 1) { - const originalKey = event[0][this.definition.keyField]; - const eventDef = JSON.parse( - Util.replaceByObject( - JSON.stringify(this.parseMetadata(event[0])), - templateVariables - ) - ); - if (!eventDef.dataExtensionId) { - throw new Error( - `EventDefinition.parseMetadata:: ` + - `No Data Extension found for ` + - `event: ${eventDef.name}. ` + - `This cannot be templated` - ); - } - - // remove all fields listed in Definition for templating - this.keepTemplateFields(eventDef); - File.writeJSONToFile( - [templateDir, this.definition.type].join('/'), - originalKey + '.' + this.definition.type + '-meta', - JSON.parse(Util.replaceByObject(JSON.stringify(eventDef), templateVariables)) - ); - Util.logger.info( - `EventDefinition.retrieveAsTemplate:: Written Metadata to filesystem (${name})` - ); - return { metadata: eventDef, type: this.definition.type }; - } else { - throw new Error( - `Encountered unknown error when retrieveing ${ - this.definition.typeName - } "${name}": ${JSON.stringify(res.body)}` - ); - } - } catch (ex) { - Util.logger.error('EventDefinition.retrieveAsTemplate:: ' + ex); - return null; - } - } - - /** - * manages post retrieve steps - * @param {Object} eventDef a single importDef - * @returns {Object[]} metadata - */ - static postRetrieveTasks(eventDef) { - const val = this.parseMetadata(eventDef); - this.keepRetrieveFields(val); - return val; - } - - /** - * Creates a single Event Definition - * @param {Object} EventDefinition a single Event Definition - * @returns {Promise} Promise - */ - static create(EventDefinition) { - return super.createREST(EventDefinition, '/interaction/v1/EventDefinitions/'); - } - - /** - * Updates a single Event Definition (using PUT method since PATCH isn't supported) - * @param {Object} EventDefinition a single Event Definition - * @returns {Promise} Promise - */ - static async update(EventDefinition) { - this.removeNotUpdateableFields(EventDefinition); - const options = { - uri: '/interaction/v1/EventDefinitions/' + EventDefinition.id, - json: EventDefinition, - headers: {}, - }; - try { - const response = await this.client.RestClient.put(options); - super.checkForErrors(response); - return response; - } catch (ex) { - Util.metadataLogger( - 'error', - this.definition.type, - 'updateREST', - ex, - EventDefinition.name - ); - return null; - } - } - - /** - * prepares an event definition for deployment - * @param {Object} metadata a single eventDefinition - * @returns {Promise} Promise - */ - static async preDeployTasks(metadata) { - metadata.dataExtensionId = Util.getFromCache( - this.cache, - 'dataExtension', - metadata.dataExtensionName, - 'Name', - 'ObjectID' - ); - metadata.arguments.dataExtensionId = metadata.dataExtensionId; - return metadata; - } - - /** - * parses retrieved Metadata before saving - * @param {Object} metadata a single event definition - * @returns {Array} Array with one metadata object and one sql string - */ - static parseMetadata(metadata) { - try { - metadata.dataExtensionId = Util.getFromCache( - this.cache, - 'dataExtension', - metadata.dataExtensionId, - 'ObjectID', - 'CustomerKey' - ); - metadata.arguments.dataExtensionId = metadata.dataExtensionId; - return JSON.parse(JSON.stringify(metadata)); - } catch (ex) { - Util.metadataLogger( - 'verbose', - this.definition.type, - 'parseMetadata', - `No related Data Extension found for Event '${metadata.name}'. Consider deleting the event definition` - ); - return metadata; - } - } -} - -// Assign definition to static attributes -EventDefinition.definition = require('../MetadataTypeDefinitions').eventDefinition; -EventDefinition.cache = {}; -EventDefinition.client = undefined; - -module.exports = EventDefinition; diff --git a/lib/metadataTypes/FileLocation.js b/lib/metadataTypes/FileLocation.js new file mode 100644 index 000000000..b75899d9e --- /dev/null +++ b/lib/metadataTypes/FileLocation.js @@ -0,0 +1,290 @@ +'use strict'; + +import MetadataType from './MetadataType.js'; +import { Util } from '../util/util.js'; + +/** + * @typedef {import('../../types/mcdev.d.js').BuObject} BuObject + * @typedef {import('../../types/mcdev.d.js').CodeExtract} CodeExtract + * @typedef {import('../../types/mcdev.d.js').CodeExtractItem} CodeExtractItem + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItem} MetadataTypeItem + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItemDiff} MetadataTypeItemDiff + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItemObj} MetadataTypeItemObj + * @typedef {import('../../types/mcdev.d.js').MetadataTypeMap} MetadataTypeMap + * @typedef {import('../../types/mcdev.d.js').MetadataTypeMapObj} MetadataTypeMapObj + * @typedef {import('../../types/mcdev.d.js').SoapRequestParams} SoapRequestParams + * @typedef {import('../../types/mcdev.d.js').TemplateMap} TemplateMap + */ + +/** + * ImportFile MetadataType + * + * @augments MetadataType + */ +class FileLocation extends MetadataType { + static cache = {}; + /** + * Retrieves Metadata of FileLocation + * Endpoint /automation/v1/ftplocations/ return all FileLocations + * + * @param {string} retrieveDir Directory where retrieved metadata directory will be saved + * @param {void | string[]} [_] unused parameter + * @param {void | string[]} [__] unused parameter + * @param {string} [key] customer key of single item to retrieve + * @returns {Promise.<MetadataTypeMapObj>} Promise + */ + static async retrieve(retrieveDir, _, __, key) { + try { + const dataItems = await super.retrieveREST( + null, + '/data/v1/filetransferlocation' + (key ? '/' + encodeURIComponent(key) : 's'), + null, + key + ); + this.cache[this.buObject.mid] ||= {}; + this.cache[this.buObject.mid].dataItems = dataItems.metadata; + } catch (ex) { + if (ex.code === 'ERR_BAD_REQUEST') { + // if retrieve-by-key comes up empty, the data-endpoint returns a code 400 + Util.logger.debug(ex.message); + } else { + Util.logger.warn(ex.message); + } + } + const items = await super.retrieveREST( + retrieveDir, + '/automation/v1/ftplocations/', + null, + key + ); + + return items; + } + + /** + * Retrieves folder metadata into local filesystem. Also creates a uniquePath attribute for each folder. + * + * @returns {Promise.<MetadataTypeMapObj>} Promise + */ + static async retrieveForCache() { + return this.retrieve(null); + } + + /** + * Creates a single item + * + * @param {MetadataTypeItem} metadata a single item + * @returns {Promise.<MetadataTypeItem>} Promise + */ + static create(metadata) { + return this.createREST(metadata, '/data/v1/filetransferlocation'); + } + /** + * Updates a single item + * + * @param {MetadataTypeItem} metadata a single item + * @returns {Promise.<MetadataTypeItem>} Promise + */ + static update(metadata) { + return this.updateREST( + metadata, + '/data/v1/filetransferlocation/' + + encodeURIComponent(metadata[this.definition.keyField]) + ); + } + + /** + * helper for {@link MetadataType.parseResponseBody} that creates a custom key field for this type based on mobileCode and keyword + * + * @param {MetadataTypeItem} metadata single item + */ + static createCustomKeyField(metadata) { + if (metadata.fileTransferLocation) { + const fileTransferLocation = metadata.fileTransferLocation; + for (const key of Object.keys(metadata)) { + delete metadata[key]; + } + Object.assign(metadata, fileTransferLocation); + } else { + if (!metadata.customerKey && this.cache[this.buObject.mid]?.dataItems) { + const nameMatch = Object.values(this.cache[this.buObject.mid].dataItems).find( + (item) => item.name === metadata.name + ); + if (nameMatch) { + Object.assign(metadata, nameMatch); + } + } + if (!this.definition.locationTypeIdMappingDeployable[metadata.locationTypeId]) { + // old file location types are only returned by the automation-endpoint which does not return customerKey field - but also these are not updatable and hence we can improvise here + + metadata.customerKey ||= metadata.name; + } + } + } + + /** + * Creates a single metadata entry via REST + * + * @param {MetadataTypeItem} metadataEntry a single metadata Entry + * @param {string} uri rest endpoint for POST + * @param {boolean} [handleOutside] if the API reponse is irregular this allows you to handle it outside of this generic method + * @returns {Promise.<object> | null} Promise of API response or null in case of an error + */ + static async createREST(metadataEntry, uri, handleOutside) { + this.removeNotCreateableFields(metadataEntry); + const createPayload = { fileTransferLocation: metadataEntry }; + try { + // set to empty object in case API returned nothing to be able to update it in helper classes + let response = (await this.client.rest.post(uri, createPayload)) || {}; + response = await this.postCreateTasks(metadataEntry, response); + if (!handleOutside) { + Util.logger.info( + ` - created ${Util.getTypeKeyName(this.definition, metadataEntry)}` + ); + } + return response; + } catch (ex) { + const parsedErrors = this.getErrorsREST(ex); + Util.logger.error( + ` ☇ error creating ${Util.getTypeKeyName(this.definition, metadataEntry)}:` + ); + if (parsedErrors.length) { + for (const msg of parsedErrors) { + Util.logger.error(' • ' + msg); + } + } else if (ex?.message) { + Util.logger.debug(ex.message); + } + return null; + } + } + + /** + * helper for {@link MetadataType.createREST} + * + * @param {MetadataTypeItem} _ a single metadata Entry + * @param {object} apiResponse varies depending on the API call + * @returns {Promise.<object>} apiResponse, potentially modified + */ + static async postCreateTasks(_, apiResponse) { + return apiResponse?.fileTransferLocation || apiResponse; + } + + /** + * Updates a single metadata entry via REST + * + * @param {MetadataTypeItem} metadataEntry a single metadata Entry + * @param {string} uri rest endpoint for PATCH + * @param {'patch'|'post'|'put'} [httpMethod] defaults to 'patch'; some update requests require PUT instead of PATCH + * @param {boolean} [handleOutside] if the API reponse is irregular this allows you to handle it outside of this generic method + * @returns {Promise.<object> | null} Promise of API response or null in case of an error + */ + static async updateREST(metadataEntry, uri, httpMethod = 'patch', handleOutside) { + this.removeNotUpdateableFields(metadataEntry); + const updatePayload = { fileTransferLocation: metadataEntry }; + try { + // set to empty object in case API returned nothing to be able to update it in helper classes + let response = (await this.client.rest[httpMethod](uri, updatePayload)) || {}; + await this._postChangeKeyTasks(metadataEntry); + this.getErrorsREST(response); + response = await this.postUpdateTasks(metadataEntry, response); + // some times, e.g. automation dont return a key in their update response and hence we need to fall back to name + if (!handleOutside) { + Util.logger.info( + ` - updated ${Util.getTypeKeyName(this.definition, metadataEntry)}` + ); + } + return response; + } catch (ex) { + const parsedErrors = this.getErrorsREST(ex); + Util.logger.error( + ` ☇ error updating ${Util.getTypeKeyName(this.definition, metadataEntry)}:` + ); + for (const msg of parsedErrors) { + Util.logger.error(' • ' + msg); + } + return null; + } + } + + /** + * helper for {@link MetadataType.updateREST} and {@link MetadataType.updateSOAP} + * + * @param {MetadataTypeItem} _ a single metadata Entry + * @param {object} apiResponse varies depending on the API call + * @returns {Promise.<object>} apiResponse, potentially modified + */ + static postUpdateTasks(_, apiResponse) { + return apiResponse?.fileTransferLocation || apiResponse; + } + /** + * prepares a import definition for deployment + * + * @param {MetadataTypeItem} metadata a single importDef + * @returns {Promise.<MetadataTypeItem>} Promise + */ + static async preDeployTasks(metadata) { + if (metadata.c__locationType) { + metadata.locationTypeId = this.definition.locationTypeMapping[metadata.c__locationType]; + if (this.definition.locationTypeMappingDeployable[metadata.c__locationType]) { + metadata.locationType = + this.definition.locationTypeMappingDeployable[metadata.c__locationType]; + } else { + throw new Error( + `Only FileLocations of types ${Object.keys(this.definition.locationTypeMappingDeployable).join(', ')} can be deployed via mcdev.` + ); + } + } + return metadata; + } + + /** + * manages post retrieve steps + * + * @param {MetadataTypeItem} metadata a single item + * @returns {MetadataTypeItem} parsed metadata + */ + static postRetrieveTasks(metadata) { + if (metadata.locationTypeId !== undefined) { + try { + metadata.c__locationType = Util.inverseGet( + this.definition.locationTypeMapping, + metadata.locationTypeId + ); + delete metadata.locationTypeId; + } catch { + Util.logger.info( + 'Please report this new & unknown locationTypeId to the mcdev developer team via github: ' + + metadata.locationTypeId + ); + } + } else if (metadata.locationType) { + // assuming create/update of new types + metadata.c__locationType = Util.inverseGet( + this.definition.locationTypeMappingDeployable, + metadata.locationType + ); + } + return metadata; + } + + /** + * Delete a metadata item from the specified business unit + * + * @param {string} key Identifier of item + * @returns {Promise.<boolean>} deletion success flag + */ + static async deleteByKey(key) { + return super.deleteByKeyREST( + '/data/v1/filetransferlocation/' + encodeURIComponent(key), + key, + 400 + ); + } +} + +// Assign definition to static attributes +import MetadataTypeDefinitions from '../MetadataTypeDefinitions.js'; +FileLocation.definition = MetadataTypeDefinitions.fileLocation; + +export default FileLocation; diff --git a/lib/metadataTypes/FileTransfer.js b/lib/metadataTypes/FileTransfer.js index b62a68e19..cf35364b6 100644 --- a/lib/metadataTypes/FileTransfer.js +++ b/lib/metadataTypes/FileTransfer.js @@ -1,99 +1,110 @@ 'use strict'; -const MetadataType = require('./MetadataType'); -const Util = require('../util/util'); -const File = require('../util/file'); +import MetadataType from './MetadataType.js'; +import { Util } from '../util/util.js'; +import File from '../util/file.js'; +import cache from '../util/cache.js'; + +/** + * @typedef {import('../../types/mcdev.d.js').BuObject} BuObject + * @typedef {import('../../types/mcdev.d.js').CodeExtract} CodeExtract + * @typedef {import('../../types/mcdev.d.js').CodeExtractItem} CodeExtractItem + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItem} MetadataTypeItem + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItemDiff} MetadataTypeItemDiff + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItemObj} MetadataTypeItemObj + * @typedef {import('../../types/mcdev.d.js').MetadataTypeMap} MetadataTypeMap + * @typedef {import('../../types/mcdev.d.js').MetadataTypeMapObj} MetadataTypeMapObj + * @typedef {import('../../types/mcdev.d.js').SoapRequestParams} SoapRequestParams + * @typedef {import('../../types/mcdev.d.js').TemplateMap} TemplateMap + */ /** * FileTransfer MetadataType + * * @augments MetadataType */ class FileTransfer extends MetadataType { /** * Retrieves Metadata of FileTransfer Activity. * Endpoint /automation/v1/filetransfers/ returns all File Transfers - * @param {String} retrieveDir Directory where retrieved metadata directory will be saved - * @returns {Promise} Promise + * + * @param {string} retrieveDir Directory where retrieved metadata directory will be saved + * @param {void | string[]} [_] unused parameter + * @param {void | string[]} [__] unused parameter + * @param {string} [key] customer key of single item to retrieve + * @returns {Promise.<MetadataTypeMapObj>} Promise */ - static async retrieve(retrieveDir) { - return super.retrieveREST(retrieveDir, '/automation/v1/filetransfers/', null); + static async retrieve(retrieveDir, _, __, key) { + return super.retrieveREST(retrieveDir, '/automation/v1/filetransfers/', null, key); } + /** * Retrieves Metadata of FileTransfer Activity for caching - * @returns {Promise} Promise + * + * @returns {Promise.<MetadataTypeMapObj>} Promise */ static async retrieveForCache() { - return super.retrieveREST(null, '/automation/v1/filetransfers/', null); + return super.retrieveREST(null, '/automation/v1/filetransfers/'); } /** * Retrieve a specific File Transfer Definition by Name - * @param {String} templateDir Directory where retrieved metadata directory will be saved - * @param {String} name name of the metadata file - * @param {Object} templateVariables variables to be replaced in the metadata - * @returns {Promise} Promise + * + * @deprecated Use `retrieve` followed by `build` instead. `retrieveAsTemplate` will be removed in a future version. + * @param {string} templateDir Directory where retrieved metadata directory will be saved + * @param {string} name name of the metadata file + * @param {TemplateMap} templateVariables variables to be replaced in the metadata + * @returns {Promise.<MetadataTypeItemObj>} Promise */ static async retrieveAsTemplate(templateDir, name, templateVariables) { - const options = { - uri: '/automation/v1/filetransfers/?$filter=name%20eq%20' + name.split(' ').join('%20'), - }; - - const res = await this.client.RestClient.get(options); - if (res.body && Array.isArray(res.body.items) && res.body.items.length) { + Util.logDeprecated('retrieveAsTemplate', `'retrieve' followed by 'build'`); + const res = await this.client.rest.get( + '/automation/v1/filetransfers/?$filter=name%20eq%20' + encodeURIComponent(name) + ); + if (Array.isArray(res?.items) && res?.items?.length) { // eq-operator returns a similar, not exact match and hence might return more than 1 entry - const [metadata] = res.body.items.filter((item) => item.name === name); + const metadata = res.items.find((item) => item.name === name); if (!metadata) { Util.logger.error(`No ${this.definition.typeName} found with name "${name}"`); return; } // get full definition - const extended = await this.client.RestClient.get({ - uri: '/automation/v1/filetransfers/' + metadata.id, - }); - const originalKey = extended.body[this.definition.keyField]; + const extended = await this.client.rest.get( + '/automation/v1/filetransfers/' + metadata[this.definition.idField] + ); + const originalKey = extended[this.definition.keyField]; const val = JSON.parse( Util.replaceByObject( - JSON.stringify(this.parseMetadata(extended.body)), + JSON.stringify(this.postRetrieveTasks(extended)), templateVariables ) ); // remove all fields listed in Definition for templating this.keepTemplateFields(val); - File.writeJSONToFile( + await File.writeJSONToFile( [templateDir, this.definition.type].join('/'), originalKey + '.' + this.definition.type + '-meta', JSON.parse(Util.replaceByObject(JSON.stringify(val), templateVariables)) ); - Util.logger.info( - `FileTransfer.retrieveAsTemplate:: Written Metadata to filesystem (${name})` - ); + Util.logger.info(`- templated ${this.definition.type}: ${name}`); return { metadata: val, type: this.definition.type }; - } else if (res.body && res.body.items) { + } else if (res?.items) { Util.logger.error(`No ${this.definition.typeName} found with name "${name}"`); } else { throw new Error( `Encountered unknown error when retrieveing ${ this.definition.typeName - } "${name}": ${JSON.stringify(res.body)}` + } "${name}": ${JSON.stringify(res)}` ); } } - /** - * manages post retrieve steps - * @param {Object} metadata a single fileTransfer activity definition - * @returns {Object[]} metadata - */ - static postRetrieveTasks(metadata) { - const values = this.parseMetadata(metadata); - return values; - } - /** * Creates a single File Transfer - * @param {Object} fileTransfer a single File Transfer + * + * @param {MetadataTypeItem} fileTransfer a single File Transfer * @returns {Promise} Promise */ static create(fileTransfer) { @@ -102,7 +113,8 @@ class FileTransfer extends MetadataType { /** * Updates a single File Transfer - * @param {Object} fileTransfer a single File Transfer + * + * @param {MetadataTypeItem} fileTransfer a single File Transfer * @returns {Promise} Promise */ static update(fileTransfer) { @@ -111,40 +123,88 @@ class FileTransfer extends MetadataType { /** * prepares a fileTransfer for deployment - * @param {Object} metadata a single fileTransfer activity definition + * + * @param {MetadataTypeItem} metadata a single fileTransfer activity definition * @returns {Promise} Promise */ static async preDeployTasks(metadata) { - metadata.fileTransferLocationId = Util.getFromCache( - this.cache, - 'ftpLocation', - metadata.r__ftpLocation_name, - 'name', - 'id' - ); + if (metadata.r__fileLocation_name) { + metadata.fileTransferLocationId = cache.searchForField( + 'fileLocation', + metadata.r__fileLocation_name, + 'name', + 'id' + ); + delete metadata.r__fileLocation_name; + } else { + throw new Error( + 'r__fileLocation_name not set. Please ensure the source is properly set up and re-retrieve it first.' + ); + } return metadata; } + /** - * parses retrieved Metadata before saving - * @param {Object} metadata a single fileTransfer activity definition - * @returns {Array} Array with one metadata object and one sql string + * manages post retrieve steps + * + * @param {MetadataTypeItem} metadata a single fileTransfer activity definition + * @returns {MetadataTypeItem} parsed metadata */ - static parseMetadata(metadata) { - metadata.r__ftpLocation_name = Util.getFromCache( - this.cache, - 'ftpLocation', - metadata.fileTransferLocationId, - 'id', - 'name' - ); - delete metadata.fileTransferLocationId; + static postRetrieveTasks(metadata) { + try { + metadata.r__fileLocation_name = cache.searchForField( + 'fileLocation', + metadata.fileTransferLocationId, + 'id', + 'name' + ); + delete metadata.fileTransferLocationId; + } catch (ex) { + Util.logger.warn( + ` - FileTransfer '${metadata[this.definition.keyField]}': ${ex.message}` + ); + } + return metadata; } + + /** + * helper to allow us to select single metadata entries via REST + * + * @private + * @param {string} key customer key + * @returns {Promise.<string>} objectId or enpty string + */ + static async _getObjectIdForSingleRetrieve(key) { + const name = key.startsWith('name:') ? key.slice(5) : null; + const filter = name ? '?$filter=name%20eq%20' + encodeURIComponent(name) : ''; + const results = await this.client.rest.get('/automation/v1/filetransfers/' + filter); + const items = results?.items || []; + const found = items.find((item) => + name ? item[this.definition.nameField] === name : item[this.definition.keyField] === key + ); + return found?.id || null; + } + + /** + * Delete a metadata item from the specified business unit + * + * @param {string} key Identifier of data extension + * @returns {Promise.<boolean>} deletion success flag + */ + static async deleteByKey(key) { + // delete only works with the query's object id + const objectId = key ? await this._getObjectIdForSingleRetrieve(key) : null; + if (!objectId) { + await this.deleteNotFound(key); + return false; + } + return super.deleteByKeyREST('/automation/v1/filetransfers/' + objectId, key); + } } // Assign definition to static attributes -FileTransfer.definition = require('../MetadataTypeDefinitions').fileTransfer; -FileTransfer.cache = {}; -FileTransfer.client = undefined; +import MetadataTypeDefinitions from '../MetadataTypeDefinitions.js'; +FileTransfer.definition = MetadataTypeDefinitions.fileTransfer; -module.exports = FileTransfer; +export default FileTransfer; diff --git a/lib/metadataTypes/Filter.js b/lib/metadataTypes/Filter.js index 658fa493d..2a633d9f4 100644 --- a/lib/metadataTypes/Filter.js +++ b/lib/metadataTypes/Filter.js @@ -1,9 +1,34 @@ 'use strict'; -const MetadataType = require('./MetadataType'); +import MetadataType from './MetadataType.js'; +import { Util } from '../util/util.js'; +import cache from '../util/cache.js'; +import File from '../util/file.js'; + +const dataTypes = { + 1: 'List', + 2: 'DataExtension', + 3: 'Group Wizard', + 4: 'Behavioral Data', +}; + +/** + * @typedef {import('../../types/mcdev.d.js').BuObject} BuObject + * @typedef {import('../../types/mcdev.d.js').CodeExtract} CodeExtract + * @typedef {import('../../types/mcdev.d.js').CodeExtractItem} CodeExtractItem + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItem} MetadataTypeItem + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItemDiff} MetadataTypeItemDiff + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItemObj} MetadataTypeItemObj + * @typedef {import('../../types/mcdev.d.js').MetadataTypeMap} MetadataTypeMap + * @typedef {import('../../types/mcdev.d.js').MetadataTypeMapObj} MetadataTypeMapObj + * @typedef {import('../../types/mcdev.d.js').SoapRequestParams} SoapRequestParams + * @typedef {import('../../types/mcdev.d.js').TemplateMap} TemplateMap + * @typedef {import('../../types/mcdev.d.js').FilterItem} FilterItem + */ /** * Filter MetadataType + * * @augments MetadataType */ class Filter extends MetadataType { @@ -12,15 +37,323 @@ class Filter extends MetadataType { * Endpoint /automation/v1/filters/ returns all Filters, * but only with some of the fields. So it is needed to loop over * Filters with the endpoint /automation/v1/filters/{id} - * @param {String} retrieveDir Directory where retrieved metadata directory will be saved + * + * @param {string} retrieveDir Directory where retrieved metadata directory will be saved + * @param {void | string[]} [_] unused parameter + * @param {void | string[]} [__] unused parameter + * @param {string} [key] customer key of single item to retrieve + * @returns {Promise.<MetadataTypeMapObj>} Promise + */ + static async retrieve(retrieveDir, _, __, key) { + const objectId = key ? await this._getObjectIdForSingleRetrieve(key) : ''; + return super.retrieveREST(retrieveDir, '/automation/v1/filters/' + objectId, null, key); + } + /** + * parses retrieved Metadata before saving + * + * @param {FilterItem} metadata a single record + * @returns {FilterItem} parsed metadata definition + */ + static postRetrieveTasks(metadata) { + // folder + super.setFolderPath(metadata); + + try { + // filterDefinition + metadata.r__dataFilter_key = cache.searchForField( + 'dataFilter', + metadata.filterDefinitionId, + 'id', + 'key' + ); + delete metadata.filterDefinitionId; + } catch { + try { + // filterDefinitionHidden - auto-generated for filtered dataExtensions + metadata.r__dataFilter_key = cache.searchForField( + 'dataFilterHidden', + metadata.filterDefinitionId, + 'id', + 'key' + ); + delete metadata.filterDefinitionId; + } catch { + // ignore + } + } + + // rest API does not return description property when it's empty but we always want this as part of our json + metadata.description ||= ''; + + this._postRetrieve_dataTypeMapping('source', metadata); + this._postRetrieve_dataTypeMapping('destination', metadata); + return metadata; + } + + /** + * helper for postRetrieveTasks to map data types + * + * @param {'source'|'destination'} target we are processing source and destinations + * @param {FilterItem} metadata single record + */ + static _postRetrieve_dataTypeMapping(target, metadata) { + try { + switch (metadata[`${target}TypeId`]) { + // case 1: { + // // List + // // TODO + // break; + case 2: { + // dataExtension + metadata[`r__${target}_dataExtension_key`] = cache.searchForField( + 'dataExtension', + metadata[`${target}ObjectId`], + 'ObjectID', + 'CustomerKey' + ); + delete metadata[`${target}ObjectId`]; + delete metadata[`${target}TypeId`]; + break; + } + // case 3: { + // // GroupWizard + // // TODO + // break; + // } + // case 4: { + // // BehavioralData + // // TODO + // break; + // } + default: { + Util.logger.warn( + ` - Filter '${metadata.name}' (${ + metadata.customerKey + }): Unsupported ${target} type '${dataTypes[metadata[`${target}TypeId`]]}'` + ); + } + } + } catch (ex) { + Util.logger.warn( + ` - filter '${metadata.name}' (${metadata.customerKey}): ${target} not found (${ex.message})` + ); + } + } + /** + * helper for preDeployTasks to map data types + * + * @param {'source'|'destination'} target we are processing source and destinations + * @param {FilterItem} metadata single record + * @param {FilterItem} cachedVersion cached version of the metadata + */ + static _preDeploy_dataTypeMapping(target, metadata, cachedVersion) { + // TODO List / TypeId==1 + + // dataExtension + if (metadata[`r__${target}_dataExtension_key`]) { + metadata[`${target}TypeId`] = 2; + + metadata[`${target}ObjectId`] = cache.searchForField( + 'dataExtension', + metadata[`r__${target}_dataExtension_key`], + 'CustomerKey', + 'ObjectID' + ); + if ( + cachedVersion && + cachedVersion[`${target}ObjectId`] !== metadata[`${target}ObjectId`] + ) { + throw new Error( + `Updating r__${target}_dataExtension_key is not allowed. You need to delete and re-create the filter to change this.` + ); + // metadata[`${target}ObjectId`] = cachedVersion[`${target}ObjectId`]; + } + if (target === 'source') { + // this seems to be duplicated in update calls from the GUI + metadata.filterDefinitionSourceTypeId = metadata[`${target}TypeId`]; + metadata.sourceId = null; + } else if (target === 'destination') { + const deItem = cache.getByKey( + 'dataExtension', + metadata[`r__${target}_dataExtension_key`] + ); + metadata.resultDEDescription = deItem?.Description || ''; + metadata.resultDEName = deItem?.Name || ''; + metadata.resultDEKey = deItem?.CustomerKey || ''; + + metadata.resultGroupFolderId = null; + metadata.resultGroupName = null; + } + delete metadata[`r__${target}_dataExtension_key`]; + } + + // TODO GroupWizard / TypeId==3 + + // TODO BehavioralData / TypeId==4 + } + + /** + * Creates a single item + * this uses soap API because the rest api does not allow hotlinking to an existing target DE + * + * @param {FilterItem} item a single item + * @returns {Promise} Promise + */ + static async create(item) { + // create: POST automation/v1/filters/ + // {"filterDefinitionId":"4b9adc79-8f56-488c-9910-ab7ad7afc13a","name":"jb_talent_flat_2_gui","description":"","categoryId":"5319","sourceId":null,"resultGroupFolderId":null,"resultGroupName":null,"filterDefinitionSourceTypeId":2,"folderLocationText":"Filter","customerKey":"jb_talent_flat_2_gui","resultDEName":"jb_talent_flat_2_gui","resultDEKey":"jb_talent_flat_2_gui","resultDEDescription":""} + // return super.createREST(item, '/automation/v1/filters/'); + + let response = null; + try { + response = await super.createSOAP(this.preCreateSOAPItem(item), true); + + Util.logger.info(` - created ${Util.getTypeKeyName(this.definition, item)}`); + } catch (ex) { + this._handleSOAPErrors(ex, 'creating', item, false); + } + return this.postCreateTasks(item, response); + } + + /** + * helper that converts the rest item into a soap item + * + * @param {FilterItem} item a single item + * @returns {object} SOAP formatted filter item + */ + static preCreateSOAPItem(item) { + return { + FilterDefinitionID: item.filterDefinitionId, + Name: item.name, + Description: item.description || '', + // CategoryID: item.categoryId, + CustomerKey: item.customerKey, + DestinationTypeID: item.destinationTypeId, + DestinationObjectID: item.destinationObjectId, + SourceTypeID: item.sourceTypeId, + SourceObjectID: item.sourceObjectId, + }; + } + + /** + * helper that runs update on all create calls to ensure all fields are set + * + * @param {FilterItem} restItem original rest item + * @param {object} response SOAP response + * @returns {Promise.<FilterItem>} created item + */ + static async postCreateTasks(restItem, response) { + Util.logger.debug( + ` - running post create tasks for ${Util.getTypeKeyName(this.definition, restItem)} to set the folder ID` + ); + if (!response) { + return response; + } + const soapItem = response.Results?.[0].Object; + restItem.filterActivityId = soapItem.FilterActivityID; + return super.updateREST( + restItem, + '/automation/v1/filters/' + restItem[this.definition.idField], + undefined, + true + ); + } + + /** + * Updates a single item + * + * @param {MetadataTypeItem} item a single item * @returns {Promise} Promise */ - static async retrieve(retrieveDir) { - return super.retrieveREST(retrieveDir, '/automation/v1/filters/', null); + static update(item) { + return super.updateREST(item, '/automation/v1/filters/' + item[this.definition.idField]); + } + + /** + * prepares a record for deployment + * + * @param {FilterItem} metadata a single record + * @returns {Promise.<FilterItem>} Promise of updated single record + */ + static async preDeployTasks(metadata) { + // folder + super.setFolderId(metadata); + + // disable updates to r__dataFilter_key, r__source_dataExtension_key, r__destination_dataExtension_key + // technically, the API allows changing the reference to the dataFilter but the GUI does not. + // the API and GUI prevent changes to the source & destination data extensions. + // to avoid confusion and accidental changes, we will reset the values from cache before deployment + const normalizedKey = File.reverseFilterIllegalFilenames( + metadata[this.definition.keyField] + ); + const cachedVersion = cache.getByKey(this.definition.type, normalizedKey); + + // filterDefinition + if (metadata.r__dataFilter_key) { + metadata.filterDefinitionId = cache.searchForField( + 'dataFilter', + metadata.r__dataFilter_key, + 'key', + 'id' + ); + if (cachedVersion && cachedVersion.filterDefinitionId !== metadata.filterDefinitionId) { + throw new Error( + `Updating r__dataFilter_key is not allowed. You need to delete and re-create the filter to change this.` + ); + } + delete metadata.r__dataFilter_key; + } + if (!metadata.description) { + metadata.description = ''; + } + + metadata.resultGroupFolderId = null; + metadata.sourceId = null; + + this._preDeploy_dataTypeMapping('source', metadata, cachedVersion); + this._preDeploy_dataTypeMapping('destination', metadata, cachedVersion); + + return metadata; + } + + /** + * helper to allow us to select single metadata entries via REST + * + * @private + * @param {string} key customer key + * @returns {Promise.<string>} objectId or empty string + */ + static async _getObjectIdForSingleRetrieve(key) { + const name = key.startsWith('name:') ? key.slice(5) : null; + const response = await this.client.soap.retrieve(this.definition.soapType, ['ObjectID'], { + filter: { + leftOperand: name ? 'Name' : 'CustomerKey', + operator: 'equals', + rightOperand: name || key, + }, + }); + return response?.Results?.length ? response.Results[0].ObjectID : ''; + } + + /** + * Delete a metadata item from the specified business unit + * + * @param {string} key Identifier of data extension + * @returns {Promise.<boolean>} deletion success flag + */ + static async deleteByKey(key) { + // delete only works with the query's object id + const objectId = key ? await this._getObjectIdForSingleRetrieve(key) : null; + if (!objectId) { + await this.deleteNotFound(key); + return false; + } + return super.deleteByKeyREST('/automation/v1/filters/' + objectId, key); } } // Assign definition to static attributes -Filter.definition = require('../MetadataTypeDefinitions').filter; +import MetadataTypeDefinitions from '../MetadataTypeDefinitions.js'; +Filter.definition = MetadataTypeDefinitions.filter; -module.exports = Filter; +export default Filter; diff --git a/lib/metadataTypes/Folder.js b/lib/metadataTypes/Folder.js index de4fe8520..c80694249 100644 --- a/lib/metadataTypes/Folder.js +++ b/lib/metadataTypes/Folder.js @@ -1,30 +1,62 @@ 'use strict'; -const MetadataType = require('./MetadataType'); -const toposort = require('toposort'); -const Util = require('../util/util'); -const File = require('../util/file'); +import MetadataType from './MetadataType.js'; +import toposort from 'toposort'; +import { Util } from '../util/util.js'; +import File from '../util/file.js'; +import cache from '../util/cache.js'; + +/** + * @typedef {import('../../types/mcdev.d.js').BuObject} BuObject + * @typedef {import('../../types/mcdev.d.js').CodeExtract} CodeExtract + * @typedef {import('../../types/mcdev.d.js').CodeExtractItem} CodeExtractItem + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItem} MetadataTypeItem + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItemDiff} MetadataTypeItemDiff + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItemObj} MetadataTypeItemObj + * @typedef {import('../../types/mcdev.d.js').MetadataTypeMap} MetadataTypeMap + * @typedef {import('../../types/mcdev.d.js').MetadataTypeMapObj} MetadataTypeMapObj + * @typedef {import('../../types/mcdev.d.js').SoapRequestParams} SoapRequestParams + * @typedef {import('../../types/mcdev.d.js').TemplateMap} TemplateMap + * + * @typedef {import('../../types/mcdev.d.js').ListItem} ListItem + * @typedef {import('../../types/mcdev.d.js').ListMap} ListMap + * @typedef {import('../../types/mcdev.d.js').ListIdMap} ListIdMap + */ /** * Folder MetadataType + * * @augments MetadataType */ class Folder extends MetadataType { /** * Retrieves metadata of metadata type into local filesystem. executes callback with retrieved metadata - * @param {String} retrieveDir Directory where retrieved metadata directory will be saved - * @param {String[]} [additionalFields] Returns specified fields even if their retrieve definition is not set to true - * @param {Object} buObject properties for auth - * @returns {Promise} Promise + * + * @param {string} retrieveDir Directory where retrieved metadata directory will be saved + * @param {string[]} [additionalFields] Returns specified fields even if their retrieve definition is not set to true + * @param {string[]} [subTypeArr] content type of folder + * @param {string} [key] customer key of single item to retrieve + * @returns {Promise.<{metadata: ListMap, type: string}>} Promise */ - static async retrieve(retrieveDir, additionalFields, buObject) { - const queryAllFolders = await this.retrieveHelper(additionalFields, true); - // if this is the parent, no need to query twice as QueryAllAccounts works. - - if (buObject.eid !== buObject.mid) { - queryAllFolders.push(...(await this.retrieveHelper(additionalFields, false))); + static async retrieve(retrieveDir, additionalFields, subTypeArr, key) { + if (key) { + Util.logger.error(`Folder.retrieve() does not support key parameter`); } + /** @type {ListItem[]} */ + const queryAllFolders = await this.retrieveHelper(additionalFields, false, subTypeArr); + if (this.buObject.eid !== this.buObject.mid) { + const selectedParentTypes = subTypeArr?.length + ? subTypeArr.filter((item) => this.definition.folderTypesFromParent.includes(item)) + : subTypeArr; + if (!subTypeArr?.length || selectedParentTypes.length) { + queryAllFolders.push( + ...(await this.retrieveHelper(additionalFields, true, selectedParentTypes)) + ); + } + } + const sortPairs = toposort(queryAllFolders.map((a) => [a.ParentFolder.ID, a.ID])); + /** @type {ListIdMap} */ const idMap = {}; for (const val of queryAllFolders) { // Contact Builder Lists create a folder called "Audiences" with the same Customer Key as the @@ -34,25 +66,25 @@ class Folder extends MetadataType { } // by default folders do not have an external key, we set this to ID plus EID as this will be unique else if (!val.CustomerKey) { - val.CustomerKey = [buObject.eid, val.ID].join('-'); + val.CustomerKey = [this.buObject.eid, val.ID].join('-'); } + // ensure name is a string and not a number (SFMC-SDK workaround) + val.Name = val.Name + ''; idMap[val.ID] = val; } // create root node for attaching, but will be deleted later + // @ts-expect-error we set an incomplete ListItem for ID==0 which is flagged by ts idMap[0] = { Name: '<ROOT>', }; for (const id of sortPairs) { if (!idMap[id]) { - Util.logger.debug(`Error: id ${id} not found in idMap-obj but in sortPairs-array.`); - if (Util.logger.level === 'debug') { - console.log(`Error: id ${id} not found in idMap-ob but in sortPairs-array.`); - } + Util.logger.debug(`id ${id} not found in idMap-obj but in sortPairs-array.`); } else if ( idMap[id].ParentFolder && - idMap[id].ParentFolder.ID && + Number.isSafeInteger(idMap[id].ParentFolder.ID) && idMap[id].Name !== '<ROOT>' ) { // if the parent folder can be found by ID @@ -61,25 +93,35 @@ class Folder extends MetadataType { if (idMap[idMap[id].ParentFolder.ID].Path) { const parent = idMap[idMap[id].ParentFolder.ID]; // we use / here not system separator as it is important to keep metadata consistent - idMap[id].Path = [parent.Path, idMap[id].Name].join( - Util.standardizedSplitChar - ); + // replace '/' in folder names with escape char to avoid confusion with the path separator + idMap[id].Path = [ + parent.Path, + idMap[id].Name.replaceAll('/', Util.folderNameSlashEscapeChar), + ].join(Util.standardizedSplitChar); idMap[id].ParentFolder.Path = parent.Path; } else { - idMap[id].Path = idMap[id].Name; + // replace '/' in folder names with escape char to avoid confusion with the path separator + idMap[id].Path = idMap[id].Name.replaceAll( + '/', + Util.folderNameSlashEscapeChar + ); } } else { - Util.logger.error( - `Skipping - Cannot find parent folder (${idMap[id].ParentFolder.ID}) of: ${idMap[id].Name} (${id}, type: ${idMap[id].ContentType})` + Util.logger.info( + Util.getGrayMsg( + ` ☇ skipping folder ${idMap[id].Name} (${id}, type: ${idMap[id].ContentType}): Cannot find parent folder (${idMap[id].ParentFolder.ID})` + ) ); + delete idMap[id]; } } // All folders except the artificial root have ParentFolder attribute. If they dont something else is wrong else if (idMap[id].Name !== '<ROOT>') { idMap[id].Path = ''; - Util.logger.error( - `Skipping - Folder ${idMap[id].Name} does not have a parent folder (type: ${idMap[id].ContentType})` + Util.logger.warn( + ` ☇ skipping folder ${idMap[id].Name} (${id}, type: ${idMap[id].ContentType}): Does not have a parent folder` ); + delete idMap[id]; } } @@ -93,13 +135,13 @@ class Folder extends MetadataType { } // build a new map using the customer key instead of id + /** @type {ListMap} */ const metadata = {}; for (const id in idMap) { // remove keys which are listed in other BUs and skip root if ( - idMap[id].Client && - idMap[id].Client.ID && - (buObject.mid == idMap[id].Client.ID || + idMap[id].Client?.ID && + (this.buObject.mid == idMap[id].Client.ID || this.definition.folderTypesFromParent.includes( idMap[id].ContentType.toLowerCase() )) @@ -132,33 +174,41 @@ class Folder extends MetadataType { } } if (retrieveDir) { - const savedMetadata = await this.saveResults(metadata, retrieveDir, buObject.mid); + const savedMetadata = await this.saveResults(metadata, retrieveDir); Util.logger.info( `Downloaded: ${this.definition.type} (${Object.keys(savedMetadata).length})` ); } - return { metadata: metadata, type: this.definition.type }; + return { metadata, type: this.definition.type }; } /** * Retrieves folder metadata for caching - * @param {Object} buObject properties for auth - * @returns {Promise} Promise + * + * @param {void | string[]} [_] parameter not used + * @param {string[]} [subTypeArr] content type of folder + * @returns {Promise.<{metadata: ListMap, type: string}>} Promise */ - static retrieveForCache(buObject) { - return this.retrieve(null, null, buObject); + static retrieveForCache(_, subTypeArr) { + return this.retrieve(null, null, subTypeArr, null); } /** * Folder upsert (copied from Metadata Upsert), after retrieving from target * and comparing to check if create or update operation is needed. * Copied due to having a dependency on itself, meaning the created need to be serial - * @param {Object} metadata metadata mapped by their keyField - * @returns {Promise<Object>} Promise of saved metadata + * + * @param {ListMap} metadata metadata mapped by their keyField + * @returns {Promise.<ListMap>} Promise of saved metadata */ static async upsert(metadata) { + const orignalMetadata = structuredClone(metadata); let updateCount = 0; + let updateFailedCount = 0; let createCount = 0; + let createFailedCount = 0; + let filteredByPreDeploy = 0; + /** @type {ListMap} */ const upsertResults = {}; const sortPairs = toposort( Object.keys(metadata).map((customerKey) => [ @@ -180,154 +230,351 @@ class Folder extends MetadataType { let existingId; try { // perform a secondary check based on path - existingId = Util.getFromCache( - this.cache, - 'folder', + // do not allow mapping folders from other BUs to avoid + // treating a same-path folder from another BU as already existing + const cachedVersion = cache.getFolderByPath( deployableMetadata.Path, - 'Path', - 'ID' + undefined, + false ); - } catch (ex) { + existingId = cachedVersion?.ID; + if ( + existingId && + !this.hasChangedGeneric( + cachedVersion, + metadata[metadataKey], + 'Path', + true + ) + ) { + Util.logger.verbose( + ` - skipping ${this.definition.type} ${ + cachedVersion?.Path || + metadata[metadataKey][this.definition.nameField] + }: no change detected` + ); + filteredByPreDeploy++; + continue; + } + } catch { // In case no path matching, then try to use CustomerKey - existingId = this.cache.folder[normalizedKey] - ? this.cache.folder[normalizedKey].ID - : null; + const cachedVersion = cache.getByKey('folder', normalizedKey); + existingId = cachedVersion?.ID; + if ( + existingId && + !this.hasChangedGeneric( + cachedVersion, + metadata[metadataKey], + 'Path', + true + ) + ) { + Util.logger.verbose( + ` - skipping ${this.definition.type} ${ + cachedVersion?.Path || + metadata[metadataKey][this.definition.nameField] + }: no change detected` + ); + filteredByPreDeploy++; + continue; + } + } + if (existingId && Util.OPTIONS.noUpdate) { + Util.logger.verbose( + ` - skipping ${this.definition.type} ${ + deployableMetadata?.Path || + deployableMetadata[this.definition.nameField] + }: --noUpdate flag is set` + ); + continue; } let result; // since deployableMetadata will be modified for deploy, make a copy for reference - const beforeMetadata = JSON.parse(JSON.stringify(deployableMetadata)); + const beforeMetadata = structuredClone(deployableMetadata); if (existingId) { // if an existing folder exists with the same name/path then use that deployableMetadata.ID = existingId; result = await this.update(deployableMetadata); - updateCount++; + if (result) { + updateCount++; + } else { + updateFailedCount++; + } } else { result = await this.create(deployableMetadata); - createCount++; + if (result) { + createCount++; + } else { + createFailedCount++; + } } - if (result && result.body && result.body.Results) { + if (result?.Results) { const parsed = this.parseResponseBody({ - Results: [result.body.Results[0].Object], + Results: [result.Results[0].Object], }); - if ( - !result.body.Results[0].Object.CustomerKey && - parsed['undefined'] - ) { + if (!result.Results[0].Object.CustomerKey && parsed['undefined']) { // when inserting folders without specifying a CustomerKey, this happens in parseResponseBody() parsed[normalizedKey] = parsed['undefined']; delete parsed['undefined']; } - this.cache.folder[normalizedKey] = Object.assign( - beforeMetadata, - parsed[normalizedKey] - ); + const newObject = { + [normalizedKey]: Object.assign( + beforeMetadata, + parsed[normalizedKey] + ), + }; + cache.mergeMetadata('folder', newObject); upsertResults[metadataKey] = beforeMetadata; } else { Util.logger.debug(result); throw new Error( - `'${beforeMetadata[metadataKey].Path}' was not deployed correctly` + `'${beforeMetadata.Path}' was not deployed correctly` ); } } } catch (ex) { - Util.metadataLogger('error', 'folder', 'upsert', ex, metadataKey); + Util.logger.errorStack(ex, `Upserting ${this.definition.type} failed`); } } } } // Logging - Util.metadataLogger( - 'info', - this.definition.type, - 'upsert', - `${createCount} created / ${updateCount} updated` + Util.logger.info( + `${this.definition.type} upsert: ${createCount} of ${ + createCount + createFailedCount + } created / ${updateCount} of ${updateCount + updateFailedCount} updated` + + (filteredByPreDeploy > 0 ? ` / ${filteredByPreDeploy} filtered` : '') ); if (updateCount) { Util.logger.warn( - `Folders are recognized for updates based on their CustomerKey or, if that is not given, their folder-path.` + ` - Folders are recognized for updates based on their CustomerKey or, if that is not given, their folder-path.` ); } + await this.postDeployTasks(upsertResults, orignalMetadata, { + created: createCount, + updated: updateCount, + }); return upsertResults; } /** * creates a folder based on metatadata - * @param {Object} metadata metadata of the folder - * @returns {Promise} Promise + * + * @param {ListItem} metadataEntry metadata of the folder + * @returns {Promise.<any>} Promise of api response */ - static async create(metadata) { - if (metadata.Parent && metadata.Parent.ID && metadata.Parent.ID === 0) { - Util.logger.error( - `${this.definition.type}-${metadata.ContentType}.create:: Cannot create Root Folder: ${metadata.Name}` + static async create(metadataEntry) { + if (metadataEntry?.ParentFolder?.ID === 0) { + Util.logger.debug( + `${this.definition.type}-${metadataEntry.ContentType}.create:: Cannot create Root Folder: ${metadataEntry.Name}` ); return {}; } - const path = metadata.Path; + const path = metadataEntry.Path; + let apiTypeSoap = false; try { - const response = await super.createSOAP(metadata, 'DataFolder', true); - if (response) { - response.body.Results[0].Object = metadata; - response.body.Results[0].Object.ID = response.body.Results[0].NewID; - response.body.Results[0].Object.CustomerKey = metadata.CustomerKey; - delete response.body.Results[0].Object.$; - - Util.logger.info(`- created folder: ${path}`); - return response; + if (this.definition.deployFolderTypesEmailRest.includes(metadataEntry.ContentType)) { + // * The SOAP endpoint for creating folders does not support folders for automations nor journeys. The Rest endpoint on the other hand errors out on certain characters in the folder names that are actually valid. We therefore only use Rest for the folder types that are not supported by SOAP. + const restPayload = { + parentCatId: metadataEntry.ParentFolder.ID, + name: metadataEntry.Name, + catType: metadataEntry.ContentType, + }; + const response = await super.createREST(restPayload, '/email/v1/category', true); + if (response?.categoryId) { + // convert the response to the same format as the SOAP response + + // set the new folder ID + metadataEntry.ID = response.categoryId; + // set the client ID to ensure we can find the newly created folders as parents for folders created afterwards inside of it + metadataEntry.Client = { + ID: metadataEntry.Client?.ID || this.buObject.mid, + }; + // the following is a bit of a hack to make the response look like the SOAP response; not sure if we actually need that anywhere like this --> future developers feel free to double check + const returnObject = { + Results: [ + { + Object: metadataEntry, + }, + ], + }; + + Util.logger.info(` - created folder: ${path}`); + return returnObject; + } else { + throw new Error(JSON.stringify(response)); + } + } else if ( + this.definition.deployFolderTypesAssetRest.includes(metadataEntry.ContentType) + ) { + // * The SOAP endpoint for creating folders does not support folders for automations nor journeys. The Rest endpoint on the other hand errors out on certain characters in the folder names that are actually valid. We therefore only use Rest for the folder types that are not supported by SOAP. + const restPayload = { + parentId: metadataEntry.ParentFolder.ID, + categoryType: metadataEntry.ContentType, + extendable: 1, + editable: 1, + name: metadataEntry.Name, + description: '', + }; + + const response = await super.createREST( + restPayload, + '/asset/v1/content/categories', + true + ); + if (response?.id) { + // convert the response to the same format as the SOAP response + + // set the new folder ID + metadataEntry.ID = response.id; + // set the client ID to ensure we can find the newly created folders as parents for folders created afterwards inside of it + metadataEntry.Client = { + ID: metadataEntry.Client?.ID || this.buObject.mid, + }; + // the following is a bit of a hack to make the response look like the SOAP response; not sure if we actually need that anywhere like this --> future developers feel free to double check + const returnObject = { + Results: [ + { + Object: metadataEntry, + }, + ], + }; + + Util.logger.info(` - created folder: ${path}`); + return returnObject; + } else { + throw new Error(JSON.stringify(response)); + } + } else { + apiTypeSoap = true; + const response = await super.createSOAP(metadataEntry, true); + if (response) { + // set the client ID to ensure we can find the newly created folders as parents for folders created afterwards inside of it + metadataEntry.Client = { + ID: metadataEntry.Client?.ID || this.buObject.mid, + }; + // set the new folder ID + metadataEntry.ID = response.Results[0].NewID; + response.Results[0].Object = metadataEntry; + delete response.Results[0].Object.$; + + Util.logger.info(` - created folder: ${path}`); + return response; + } } } catch (ex) { - if (ex && ex.results) { - Util.logger.error( - `${this.definition.type}-${metadata.ContentType}.create:: error creating: '${path}'. ${ex.results[0].StatusMessage}` - ); - } else if (ex) { - Util.logger.error( - `${this.definition.type}-${metadata.ContentType}.create:: error creating: '${path}'. ${ex.message}` - ); + if (apiTypeSoap) { + this._handleSOAPErrors(ex, 'creating', metadataEntry, false, 'Name'); + } else { + if (ex?.results) { + Util.logger.error( + `${this.definition.type}-${metadataEntry.ContentType}.create:: error creating: '${path}'. ${ex.results[0].StatusMessage}` + ); + } else if (ex) { + Util.logger.error( + `${this.definition.type}-${metadataEntry.ContentType}.create:: error creating: '${path}'. ${ex.message}` + ); + } } } } /** * Updates a single Folder. - * @param {Object} metadata single metadata entry - * @returns {Promise} Promise + * + * @param {MetadataTypeItem} metadataEntry single metadata entry + * @returns {Promise.<any>} Promise of api response */ - static async update(metadata) { - const path = metadata.Path; + static async update(metadataEntry) { + if (metadataEntry?.ParentFolder?.ID === 0) { + Util.logger.debug( + `${this.definition.type}-${metadataEntry.ContentType}.create:: Cannot create Root Folder: ${metadataEntry.Name}` + ); + return {}; + } + const path = metadataEntry.Path; + let apiTypeSoap = false; try { - const response = await super.updateSOAP(metadata, 'DataFolder', true); - if (response) { - response.body.Results[0].Object = metadata; - response.body.Results[0].Object.CustomerKey = metadata.CustomerKey; - delete response.body.Results[0].Object.$; - Util.logger.info(`- updated folder: ${path}`); - return response; + let response; + if (this.definition.deployFolderTypesAssetRest.includes(metadataEntry.ContentType)) { + // * The SOAP endpoint for creating folders does not support folders for automations nor journeys. The Rest endpoint on the other hand errors out on certain characters in the folder names that are actually valid. We therefore only use Rest for the folder types that are not supported by SOAP. + const restPayload = { + id: metadataEntry.ID, + parentId: metadataEntry.ParentFolder.ID, + // categoryType: metadataEntry.ContentType, + extendable: 1, // ? + editable: 1, // ? + name: metadataEntry.Name, + description: '', + }; + response = await super.updateREST( + restPayload, + '/asset/v1/content/categories/' + metadataEntry.ID, + 'put', + true + ); + if (response?.id) { + // convert the response to the same format as the SOAP response + + // set the client ID to ensure we can find the newly created folders as parents for folders created afterwards inside of it + metadataEntry.Client = { + ID: metadataEntry.Client?.ID || this.buObject.mid, + }; + // the following is a bit of a hack to make the response look like the SOAP response; not sure if we actually need that anywhere like this --> future developers feel free to double check + const returnObject = { + Results: [ + { + Object: metadataEntry, + }, + ], + }; + + Util.logger.info(` - updated folder: ${path}`); + return returnObject; + } else { + throw new Error(JSON.stringify(response)); + } + } else { + apiTypeSoap = true; + response = await super.updateSOAP(metadataEntry, true); + if (response.Results?.[0]?.StatusCode === 'OK') { + response.Results[0].Object = metadataEntry; + response.Results[0].Object.CustomerKey = metadataEntry.CustomerKey; + delete response.Results[0].Object.$; + Util.logger.info(` - updated folder: ${path}`); + return response; + } } } catch (ex) { - if (ex && ex.results) { - Util.logger.error( - `${this.definition.type}-${metadata.ContentType}.update:: error updating: '${path}'. ${ex.results[0].StatusMessage}` - ); - } else if (ex) { - Util.logger.error( - `${this.definition.type}-${metadata.ContentType}.update:: error updating: '${path}'. ${ex.message}` - ); + if (apiTypeSoap) { + this._handleSOAPErrors(ex, 'updating', metadataEntry, false, 'Name'); + } else { + if (ex?.results) { + Util.logger.error( + `${this.definition.type}-${metadataEntry.ContentType}.update:: error updating: '${path}'. ${ex.results[0].StatusMessage}` + ); + } else if (ex) { + Util.logger.error( + `${this.definition.type}-${metadataEntry.ContentType}.update:: error updating: '${path}'. ${ex.message}` + ); + } } } } /** * prepares a folder for deployment - * @param {Object} metadata a single folder definition - * @returns {Promise} Promise + * + * @param {ListItem} metadata a single folder definition + * @returns {Promise.<ListItem>} Promise of parsed folder metadata */ static async preDeployTasks(metadata) { if (!this.definition.deployFolderTypes.includes(metadata.ContentType.toLowerCase())) { Util.logger.warn( - `Folder ${metadata.Name} is of a type which does not support deployment (Type: ${metadata.ContentType}). Please create this manually in the Web-Interface.` + ` - Folder ${metadata.Name} is of a type which does not support deployment (Type: ${metadata.ContentType}). Please create this manually in the Web-Interface.` ); return; } @@ -352,14 +599,13 @@ class Folder extends MetadataType { ); return; } - // retreive ID based on the matching Path of the parent folder - else if (metadata.ParentFolder && metadata.ParentFolder.Path) { - metadata.ParentFolder.ID = Util.getFromCache( - this.cache, - 'folder', + // retrieve ID based on the matching Path of the parent folder + else if (metadata?.ParentFolder?.Path) { + // do not allow mapping folders to other BUs during deploy + metadata.ParentFolder.ID = cache.getFolderId( metadata.ParentFolder.Path, - 'Path', - 'ID' + undefined, + false ); return metadata; } else { @@ -375,41 +621,48 @@ class Folder extends MetadataType { /** * Returns file contents mapped to their filename without '.json' ending - * @param {String} dir directory that contains '.json' files to be read - * @param {boolean} [listBadKeys=false] do not print errors, used for badKeys() - * @returns {Object} fileName => fileContent map + * + * @param {string} dir directory with json files, e.g. /retrieve/cred/bu/folder, /deploy/cred/bu/folder, /template/folder + * @param {boolean} [listBadKeys] do not print errors, used for badKeys() + * @returns {Promise.<ListMap>} fileName => fileContent map */ - static getJsonFromFS(dir, listBadKeys) { + static async getJsonFromFS(dir, listBadKeys) { try { + /** @type {ListMap} */ const fileName2FileContent = {}; const directories = File.readDirectoriesSync(dir, 10, true); let newCounter = 0; + if (!Array.isArray(directories)) { + return fileName2FileContent; + } for (const subdir of directories) { // standardise to / and then remove the stem up until folder as this // should not be in the path for the metadata. In case no split then return empty as this is root const standardSubDir = File.reverseFilterIllegalFilenames( - subdir.replace(/\\/g, '/').split(/folder\//)[1] || '' + subdir.replaceAll('\\', '/').split(/folder\//)[1] || '' ); - for (const fileName of File.readdirSync(subdir)) { + for (const fileName of await File.readdir(subdir)) { try { if (fileName.endsWith('meta.json')) { - const fileContent = File.readJSONFile(subdir, fileName, true, false); + const fileContent = await File.readJSONFile(subdir, fileName, false); const fileNameWithoutEnding = File.reverseFilterIllegalFilenames( fileName.split(/\.(\w|-)+-meta.json/)[0] ); if (fileContent.Name === fileNameWithoutEnding) { + // replace '/' in folder names with escape char to match how paths are built during retrieve fileContent.Path = (standardSubDir ? standardSubDir + '/' : '') + - fileNameWithoutEnding; + fileNameWithoutEnding.replaceAll( + '/', + Util.folderNameSlashEscapeChar + ); fileContent.ParentFolder = { Path: standardSubDir, }; - const key = fileContent.CustomerKey - ? fileContent.CustomerKey - : `new-${++newCounter}`; + const key = fileContent.CustomerKey || `new-${++newCounter}`; if (fileName2FileContent[key]) { Util.logger.error( `Your have multiple folder-JSONs with the same CustomerKey '${key}' - skipping ${fileName}` @@ -439,72 +692,74 @@ class Folder extends MetadataType { return fileName2FileContent; } catch (ex) { Util.metadataLogger('error', this.definition.type, 'getJsonFromFS', ex); - throw new Error(ex); + throw ex; } } /** * Helper to retrieve the folders as promise - * @param {String[]} [additionalFields] Returns specified fields even if their retrieve definition is not set to true - * @param {Boolean} [queryAllAccounts] which queryAllAccounts setting to use - * @returns {Promise<Object>} soap object + * + * @param {string[]} [additionalFields] Returns specified fields even if their retrieve definition is not set to true + * @param {boolean} [queryAllAccounts] which queryAllAccounts setting to use + * @param {string[]} [contentTypeList] content type of folder + * @returns {Promise.<ListItem[]>} soap object */ - static async retrieveHelper(additionalFields, queryAllAccounts) { - const options = { queryAllAccounts: !!queryAllAccounts }; - let status = 'MoreDataAvailable'; - const Results = []; - do { - let response; - await Util.retryOnError(`Retrying ${this.definition.type}`, async () => { - response = await new Promise((resolve, reject) => { - // filtered out path as we need them to be stored locally, but do not want to try and retrieve - this.client.SoapClient.retrieve( - 'DataFolder', - this.getFieldNamesToRetrieve(additionalFields).filter( - (field) => !field.includes('Path') - ), - options, - (ex, response) => (ex ? reject(ex) : resolve(response)) - ); - }); - }); - // merge results with existing - Results.push(...response.body.Results); - // set status for calling again if required - status = response.body.OverallStatus; - options.continueRequest = response.body.RequestID; - if (status === 'MoreDataAvailable') { - Util.logger.info( - '- more than ' + - Results.length + - ' folders in Business Unit - loading next batch...' - ); - } - } while (status === 'MoreDataAvailable'); - return Results; + static async retrieveHelper(additionalFields, queryAllAccounts, contentTypeList) { + const options = { QueryAllAccounts: !!queryAllAccounts }; + if (contentTypeList) { + const newFilter = { + leftOperand: 'ContentType', + operator: contentTypeList.length === 1 ? 'equals' : 'IN', + rightOperand: + contentTypeList.length === 1 ? contentTypeList[0] : contentTypeList.toSorted(), + }; + options.filter = options.filter + ? { + leftOperand: newFilter, + operator: 'OR', + rightOperand: options.filter, + } + : newFilter; + } + const response = await this.client.soap.retrieveBulk( + 'DataFolder', + this.getFieldNamesToRetrieve(additionalFields).filter( + (field) => !field.includes('Path') + ), + options + ); + return response.Results ?? []; } + /** * Gets executed after retreive of metadata type - * @param {Object} metadata metadata mapped by their keyField - * @returns {Object[]} cloned metadata + * + * @param {ListItem} metadata metadata mapped by their keyField + * @returns {ListItem} cloned metadata */ static postRetrieveTasks(metadata) { - return JSON.parse(JSON.stringify(metadata)); + return structuredClone(metadata); } + /** * Helper for writing Metadata to disk, used for Retrieve and deploy - * @param {Object} results metadata results from deploy - * @param {String} retrieveDir directory where metadata should be stored after deploy/retrieve - * @param {Number} mid current mid for this credential / business unit - * @returns {Promise<Object>} Promise of saved metadata + * + * @param {ListMap} results metadata results from deploy + * @param {string} retrieveDir directory where metadata should be stored after deploy/retrieve + * @returns {Promise.<ListMap>} Promise of saved metadata */ - static async saveResults(results, retrieveDir, mid) { + static async saveResults(results, retrieveDir) { + /** @type {ListMap} */ const savedResults = {}; for (const metadataEntry in results) { try { // skip saving shared folders as they technically live in parent. - // ! Warning: our result set does not have Client.ID in it - bad check? - if (results[metadataEntry].Client && mid != results[metadataEntry].Client.ID) { + if ( + results[metadataEntry].Client && + this.buObject.mid != results[metadataEntry].Client.ID + ) { + // deploy: folders auto-generated by deploy do not have .Client set and hence this check will be skipped + // retrieve: Client.ID is set to the MID of the BU that the folder belongs to; we only want folders of the current BU saved here continue; } else if ( results[metadataEntry] && @@ -555,7 +810,7 @@ class Folder extends MetadataType { } // Assign definition to static attributes -Folder.definition = require('../MetadataTypeDefinitions').folder; -Folder.client = undefined; +import MetadataTypeDefinitions from '../MetadataTypeDefinitions.js'; +Folder.definition = MetadataTypeDefinitions.folder; -module.exports = Folder; +export default Folder; diff --git a/lib/metadataTypes/FtpLocation.js b/lib/metadataTypes/FtpLocation.js deleted file mode 100644 index a727c2b48..000000000 --- a/lib/metadataTypes/FtpLocation.js +++ /dev/null @@ -1,34 +0,0 @@ -'use strict'; - -const MetadataType = require('./MetadataType'); - -/** - * ImportFile MetadataType - * @augments MetadataType - */ -class FtpLocation extends MetadataType { - /** - * Retrieves Metadata of FtpLocation - * Endpoint /automation/v1/ftplocations/ return all FtpLocations - * @param {String} retrieveDir Directory where retrieved metadata directory will be saved - * @returns {Promise} Promise - */ - static retrieve(retrieveDir) { - return super.retrieveREST(retrieveDir, '/automation/v1/ftplocations/', null); - } - - /** - * Retrieves folder metadata into local filesystem. Also creates a uniquePath attribute for each folder. - * @returns {Promise} Promise - */ - static async retrieveForCache() { - return super.retrieveREST(null, '/automation/v1/ftplocations/', null); - } -} - -// Assign definition to static attributes -FtpLocation.definition = require('../MetadataTypeDefinitions').ftpLocation; -FtpLocation.cache = {}; -FtpLocation.client = undefined; - -module.exports = FtpLocation; diff --git a/lib/metadataTypes/ImportFile.js b/lib/metadataTypes/ImportFile.js index 24821a390..ff5909c12 100644 --- a/lib/metadataTypes/ImportFile.js +++ b/lib/metadataTypes/ImportFile.js @@ -1,11 +1,27 @@ 'use strict'; -const MetadataType = require('./MetadataType'); -const Util = require('../util/util'); -const File = require('../util/file'); +import MetadataType from './MetadataType.js'; +import { Util } from '../util/util.js'; +import File from '../util/file.js'; +import cache from '../util/cache.js'; + +/** + * @typedef {import('../../types/mcdev.d.js').BuObject} BuObject + * @typedef {import('../../types/mcdev.d.js').CodeExtract} CodeExtract + * @typedef {import('../../types/mcdev.d.js').CodeExtractItem} CodeExtractItem + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItem} MetadataTypeItem + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItemDiff} MetadataTypeItemDiff + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItemObj} MetadataTypeItemObj + * @typedef {import('../../types/mcdev.d.js').MetadataTypeMap} MetadataTypeMap + * @typedef {import('../../types/mcdev.d.js').MetadataTypeMapObj} MetadataTypeMapObj + * @typedef {import('../../types/mcdev.d.js').SoapRequestParams} SoapRequestParams + * @typedef {import('../../types/mcdev.d.js').TemplateMap} TemplateMap + * @typedef {import('../../types/mcdev.d.js').SDKError} SDKError + */ /** * ImportFile MetadataType + * * @augments MetadataType */ class ImportFile extends MetadataType { @@ -13,37 +29,134 @@ class ImportFile extends MetadataType { * Retrieves Metadata of Import File. * Endpoint /automation/v1/imports/ return all Import Files with all details. * Currently it is not needed to loop over Imports with endpoint /automation/v1/imports/{id} - * @param {String} retrieveDir Directory where retrieved metadata directory will be saved - * @returns {Promise} Promise + * + * @param {string} [retrieveDir] Directory where retrieved metadata directory will be saved + * @param {void | string[]} [_] unused parameter + * @param {void | string[]} [__] unused parameter + * @param {string} [key] customer key of single item to retrieve + * @returns {Promise.<MetadataTypeMapObj>} Promise + */ + static async retrieve(retrieveDir, _, __, key) { + let objectId = null; + if (key) { + // using '?$filter=customerKey%20eq%20' + encodeURIComponent(key) would also work but that just retrieves more data for no reason + objectId = await this._getObjectIdForSingleRetrieve(key); + if (!objectId) { + // avoid running the rest request below by returning early + Util.logger.info( + `Downloaded: ${this.definition.type} (0)${Util.getKeysString(key)}` + ); + this.postDeleteTasks(key); + return { metadata: {}, type: this.definition.type }; + } + } + Util.logger.debug(' - retrieving extended metadata for SMS imports'); + const smsImportResults = await this.client.rest.getBulk( + '/legacy/v1/beta/mobile/imports/', + 50 + ); + this.smsImports = {}; + if (smsImportResults.totalResults > 0 && smsImportResults.entry.length > 0) { + if (smsImportResults.entry.filter((item) => !!item.sourceObjectId).length > 0) { + // imports from data extensions require additional information (item.sourceFile != '_CustomObject' and item.sourceObjectId is not set) + Util.logger.info( + Util.getGrayMsg( + ` - Caching dependent Metadata: dataExtension (source for SMS imports)` + ) + ); + } + const sourceObject = {}; + for (const item of smsImportResults.entry) { + // this api does not show the key but the name is assumed to be unique + this.smsImports[item.name] = item; + + if (!item.sourceObjectId) { + continue; + } + try { + if (!sourceObject[item.sourceObjectId]) { + sourceObject[item.sourceObjectId] = await this.client.rest.get( + '/legacy/v1/beta/object/' + item.sourceObjectId + ); + } + item.sourceObjectKey = sourceObject[item.sourceObjectId].key; + } catch { + Util.logger.warn( + `endpoint /legacy/v1/beta/object/${item.sourceObjectId} does not exist` + ); + } + } + } + + return super.retrieveREST( + retrieveDir, + '/automation/v1/imports/' + (objectId || ''), + null, + key + ); + } + + /** + * helper for {@link MetadataType.retrieveRESTcollection} + * + * @param {SDKError} ex exception + * @param {string} key id or key of item + * @param {string} url url to call for retry + * @returns {Promise.<any>} can return retry-result */ - static retrieve(retrieveDir) { - return super.retrieveREST(retrieveDir, '/automation/v1/imports/', null); + static async handleRESTErrors(ex, key, url) { + try { + if (ex.code == 'ERR_BAD_RESPONSE') { + // one more retry; it's a rare case but retrying again should solve the issue gracefully + Util.logger.info( + ` - Connection problem (Code: ${ex.code}). Retrying once${ + ex.endpoint + ? Util.getGrayMsg( + ' - ' + ex.endpoint.split('rest.marketingcloudapis.com')[1] + ) + : '' + }` + ); + Util.logger.errorStack(ex); + return await this.client.rest.get(url); + } + } catch { + // no extra action needed, handled below + } + // if we do get here, we should log the error and continue instead of failing to download all automations + Util.logger.error(` ☇ skipping ${this.definition.type} ${key}: ${ex.message} ${ex.code}`); + return null; } /** * Retrieves import definition metadata for caching - * @returns {Promise} Promise + * + * @param {void | string[]} [_] parameter not used + * @param {void | string[]} [__] parameter not used + * @param {string} [key] customer key of single item to retrieve + * @returns {Promise.<MetadataTypeMapObj>} Promise */ - static async retrieveForCache() { - return super.retrieveREST(null, '/automation/v1/imports/', null); + static retrieveForCache(_, __, key) { + return this.retrieve(null, null, null, key); } /** * Retrieve a specific Import Definition by Name - * @param {String} templateDir Directory where retrieved metadata directory will be saved - * @param {String} name name of the metadata file - * @param {Object} templateVariables variables to be replaced in the metadata - * @returns {Promise} Promise + * + * @deprecated Use `retrieve` followed by `build` instead. `retrieveAsTemplate` will be removed in a future version. + * @param {string} templateDir Directory where retrieved metadata directory will be saved + * @param {string} name name of the metadata file + * @param {TemplateMap} templateVariables variables to be replaced in the metadata + * @returns {Promise.<MetadataTypeItemObj>} Promise */ static async retrieveAsTemplate(templateDir, name, templateVariables) { - const options = { - uri: '/automation/v1/imports/?$filter=name%20eq%20' + name.split(' ').join('%20'), - }; - - const res = await this.client.RestClient.get(options); - if (res.body && Array.isArray(res.body.items) && res.body.items.length) { + Util.logDeprecated('retrieveAsTemplate', `'retrieve' followed by 'build'`); + // using '?$filter=name%20eq%20' + encodeURIComponent(name) would also work but that just retrieves more data for no reason + const cache = await this.retrieveForCache(null, null, 'name:' + name); + const metadataArr = Object.values(cache?.metadata); + if (Array.isArray(metadataArr) && metadataArr.length) { // eq-operator returns a similar, not exact match and hence might return more than 1 entry - const [metadata] = res.body.items.filter((item) => item.name === name); + const metadata = metadataArr.find((item) => item.name === name); if (!metadata) { Util.logger.error(`No ${this.definition.typeName} found with name "${name}"`); return; @@ -51,46 +164,59 @@ class ImportFile extends MetadataType { const originalKey = metadata[this.definition.keyField]; const val = JSON.parse( Util.replaceByObject( - JSON.stringify(this.parseMetadata(metadata)), + JSON.stringify(this.postRetrieveTasks(metadata)), templateVariables ) ); // remove all fields listed in Definition for templating this.keepTemplateFields(val); - File.writeJSONToFile( + await File.writeJSONToFile( [templateDir, this.definition.type].join('/'), originalKey + '.' + this.definition.type + '-meta', JSON.parse(Util.replaceByObject(JSON.stringify(val), templateVariables)) ); - Util.logger.info( - `ImportFile.retrieveAsTemplate:: Written Metadata to filesystem (${name})` - ); + Util.logger.info(`- templated ${this.definition.type}: ${name}`); return { metadata: val, type: this.definition.type }; - } else if (res.body && res.body.items) { + } else if (metadataArr) { Util.logger.error(`No ${this.definition.typeName} found with name "${name}"`); } else { throw new Error( `Encountered unknown error when retrieveing ${ this.definition.typeName - } "${name}": ${JSON.stringify(res.body)}` + } "${name}": ${JSON.stringify(metadataArr)}` ); } } /** - * manages post retrieve steps - * @param {Object} importDef a single importDef - * @returns {Object[]} metadata + * helper to allow us to select single metadata entries via REST + * + * @private + * @param {string} key customer key + * @returns {Promise.<string>} objectId or enpty string */ - static postRetrieveTasks(importDef) { - const val = this.parseMetadata(importDef); - return val; + static async _getObjectIdForSingleRetrieve(key) { + const response = await this.client.soap.retrieve('ImportDefinition', ['ObjectID'], { + filter: key.startsWith('name:') + ? { + leftOperand: 'Name', + operator: 'equals', + rightOperand: key.slice(5), + } + : { + leftOperand: 'CustomerKey', + operator: 'equals', + rightOperand: key, + }, + }); + return response?.Results?.length ? response.Results[0].ObjectID : null; } /** * Creates a single Import File - * @param {Object} importFile a single Import File + * + * @param {MetadataTypeItem} importFile a single Import File * @returns {Promise} Promise */ static create(importFile) { @@ -99,7 +225,8 @@ class ImportFile extends MetadataType { /** * Updates a single Import File - * @param {Object} importFile a single Import File + * + * @param {MetadataTypeItem} importFile a single Import File * @returns {Promise} Promise */ static update(importFile) { @@ -109,100 +236,339 @@ class ImportFile extends MetadataType { ); } + /** + * Deploys metadata + * + * @param {MetadataTypeMap} metadataMap metadata mapped by their keyField + * @param {string} deployDir directory where deploy metadata are saved + * @param {string} retrieveDir directory where metadata after deploy should be saved + * @returns {Promise.<MetadataTypeMap>} Promise of keyField => metadata map + */ + static async deploy(metadataMap, deployDir, retrieveDir) { + if ( + Object.values(metadataMap).filter((item) => item.destination.c__type === 'SMS').length > + 0 + ) { + Util.logger.info(`Caching dependent Metadata: dataExtension (source for SMS imports)`); + + const dataExtensionLegacyResult = await this.client.rest.getBulk( + '/legacy/v1/beta/object/', + 500 + ); + this.dataExtensionsLegacy = {}; + if (dataExtensionLegacyResult?.entry?.length) { + for (const item of dataExtensionLegacyResult.entry) { + this.dataExtensionsLegacy[item.key] = item; + } + } + } + + return super.deploy(metadataMap, deployDir, retrieveDir); + } + /** * prepares a import definition for deployment - * @param {Object} metadata a single importDef - * @returns {Promise} Promise + * + * @param {MetadataTypeItem} metadata a single importDef + * @returns {Promise.<MetadataTypeItem>} Promise */ static async preDeployTasks(metadata) { - metadata.fileTransferLocationId = Util.getFromCache( - this.cache, - 'ftpLocation', - metadata.r__ftpLocation_name, - 'name', - 'id' - ); - delete metadata.r__ftpLocation_name; + if (metadata.source?.r__fileLocation_name) { + const fileLocation = cache.getByKey( + 'fileLocation', + metadata.source?.r__fileLocation_name + ); + if (!fileLocation) { + throw new Error( + `fileLocation ${metadata.source?.r__fileLocation_name} not found in cache` + ); + } - if (metadata.c__destinationType === 'DataExtension') { - try { - metadata.destinationObjectId = Util.getFromCache( - this.cache, - 'dataExtension', - metadata.r__dataExtension_CustomerKey, - 'CustomerKey', - 'ObjectID' + metadata.fileTransferLocationId = fileLocation.id; + metadata.fileTransferLocationTypeId = fileLocation.locationTypeId; + delete metadata.source.r__fileLocation_name; + } + + switch (metadata.destination.c__type) { + case 'DataExtension': { + if (metadata.destination.r__dataExtension_key) { + metadata.destinationObjectId = cache.searchForField( + 'dataExtension', + metadata.destination.r__dataExtension_key, + 'CustomerKey', + 'ObjectID' + ); + delete metadata.destination.r__dataExtension_key; + } else { + throw new Error('Import Destination DataExtension not defined'); + } + if (metadata.source.c__type === 'DataExtension' && metadata.r__dataExtension_key) { + // only happens for dataimport activities (summer24 release) + metadata.source.sourceCustomObjectId = cache.searchForField( + 'dataExtension', + metadata.r__dataExtension_key, + 'CustomerKey', + 'ObjectID' + ); + metadata.source.sourceDataExtensionName = cache.searchForField( + 'dataExtension', + metadata.r__dataExtension_key, + 'CustomerKey', + 'Name' + ); + delete metadata.r__dataExtension_key; + } + break; + } + case 'List': { + if (metadata.destination.r__list_PathName) { + metadata.destinationObjectId = cache.getListObjectId( + metadata.destination.r__list_PathName, + 'ObjectID' + ); + // destinationId is also needed for List types + metadata.destinationId = cache.getListObjectId( + metadata.destination.r__list_PathName, + 'ID' + ); + delete metadata.destination.r__list_PathName; + } else { + throw new Error('Import Destination List not defined'); + } + break; + } + case 'SMS': { + if (metadata.destination.r__mobileKeyword_key) { + // code + const codeObj = cache.getByKey( + 'mobileCode', + metadata.destination.r__mobileKeyword_key.split('.')[0] + ); + if (!codeObj) { + throw new Error( + `mobileCode ${metadata.destination.r__mobileKeyword_key} not found in cache` + ); + } + metadata.code = codeObj; + + // keyword + const keywordObj = cache.getByKey( + 'mobileKeyword', + metadata.destination.r__mobileKeyword_key + ); + if (!keywordObj) { + throw new Error( + `mobileKeyword ${metadata.destination.r__mobileKeyword_key} not found in cache` + ); + } + metadata.keyword = keywordObj; + } else { + Util.logger.error( + ` - importFile ${metadata[this.definition.keyField]}: No code or keyword info found. Please re-download this from the source.` + ); + } + + // destination + metadata.destinationObjectId = '00000000-0000-0000-0000-000000000000'; + metadata.destinationObjectType = 'MobileSubscription'; + // source + if (this.dataExtensionsLegacy[metadata.source.r__dataExtension_key]) { + metadata.sourceObjectId = + this.dataExtensionsLegacy[metadata.source.r__dataExtension_key].id; + metadata.sourceObjectName = + this.dataExtensionsLegacy[ + metadata.source.r__dataExtension_key + ].dataExtensionName; + delete metadata.source.r__dataExtension_key; + } + + throw new Error( + `Import Destination Type ${metadata.destination.c__type} not fully supported.` ); - delete metadata.r__dataExtension_CustomerKey; - } catch (ex) { - throw new Error(`ImportFile ${metadata.customerKey}: ${ex.message}`); } - } else if (metadata.c__destinationType === 'List') { - try { - metadata.destinationObjectId = Util.getListObjectIdFromCache( - this.cache, - metadata.r__list_PathName, - 'ObjectID' + default: { + // e.g. WhatsApp + throw new Error( + `Import Destination Type ${metadata.destination.c__type} not fully supported.` ); - delete metadata.r__list_PathName; - } catch (ex) { - throw new Error(`ImportFile ${metadata.customerKey}: ${ex.message}`); } } - // When the destinationObjectTypeId is 584 is refers to Mobile Connect which is not supported as an Import Type + if (metadata.c__blankFileProcessing) { + // omit this if not set + metadata.blankFileProcessingType = + this.definition.blankFileProcessingTypeMapping[metadata.c__blankFileProcessing]; + } + // When the destinationObjectTypeId is 584 it refers to Mobile Connect which is not supported as an Import Type metadata.destinationObjectTypeId = - this.definition.destinationObjectTypeMapping[metadata.c__destinationType]; + this.definition.destinationObjectTypeMapping[metadata.destination.c__type]; metadata.subscriberImportTypeId = this.definition.subscriberImportTypeMapping[metadata.c__subscriberImportType]; metadata.updateTypeId = this.definition.updateTypeMapping[metadata.c__dataAction]; + + delete metadata.destination; + delete metadata.source; return metadata; } /** - * parses retrieved Metadata before saving - * @param {Object} metadata a single import definition - * @returns {Object} parsed metadata definition + * manages post retrieve steps + * + * @param {MetadataTypeItem} metadata a single item + * @returns {MetadataTypeItem} parsed metadata */ - static parseMetadata(metadata) { - metadata.r__ftpLocation_name = Util.getFromCache( - this.cache, - 'ftpLocation', - metadata.fileTransferLocationId, - 'id', - 'name' - ); - delete metadata.fileTransferLocationId; + static postRetrieveTasks(metadata) { + metadata.destination = { + // * When the destinationObjectTypeId is 584 it refers to Mobile Connect which is not supported as an Import Type + c__type: Util.inverseGet( + this.definition.destinationObjectTypeMapping, + metadata.destinationObjectTypeId + ), + }; + // destination.c__type SMS & DataExtension both set fileNamingPattern to _CustomObject and they both define a DE as source + metadata.source = { + c__type: + metadata.fileNamingPattern === '_CustomObject' || + metadata.fileSpec === '_CustomObject' + ? 'DataExtension' + : 'File Location', + }; - // * When the destinationObjectTypeId is 584 it refers to Mobile Connect which is not supported as an Import Type - metadata.c__destinationType = Util.inverseGet( - this.definition.destinationObjectTypeMapping, - metadata.destinationObjectTypeId - ); - delete metadata.destinationObjectTypeId; - if (metadata.c__destinationType === 'DataExtension') { + if (metadata.fileTransferLocationId !== '00000000-0000-0000-0000-000000000000') { try { - metadata.r__dataExtension_CustomerKey = Util.getFromCache( - this.cache, - 'dataExtension', - metadata.destinationObjectId, - 'ObjectID', - 'CustomerKey' + metadata.source.r__fileLocation_name = cache.searchForField( + 'fileLocation', + metadata.fileTransferLocationId, + 'id', + 'name' ); - delete metadata.destinationObjectId; + delete metadata.fileTransferLocationId; } catch (ex) { - Util.logger.error(`ImportFile ${metadata.customerKey}: ${ex.message}`); + Util.logger.warn(` - importFile ${metadata.customerKey}: ${ex.message}`); } - } else if (metadata.c__destinationType === 'List') { - try { - metadata.r__list_PathName = Util.getListPathNameFromCache( - this.cache, - metadata.destinationObjectId, - 'ObjectID' - ); + } + + switch (metadata.destination.c__type) { + case 'DataExtension': { + try { + metadata.destination.r__dataExtension_key = cache.searchForField( + 'dataExtension', + metadata.destinationObjectId, + 'ObjectID', + 'CustomerKey' + ); + delete metadata.destinationObjectId; + } catch (ex) { + Util.logger.warn(` - importFile ${metadata.customerKey}: ${ex.message}`); + } + if ( + metadata.source.c__type === 'DataExtension' && + metadata.sourceCustomObjectId !== '' + ) { + // only happens for dataimport activities (summer24 release) + try { + metadata.source.r__dataExtension_key = cache.searchForField( + 'dataExtension', + metadata.sourceCustomObjectId, + 'ObjectID', + 'CustomerKey' + ); + delete metadata.sourceCustomObjectId; + delete metadata.sourceDataExtensionName; + } catch (ex) { + Util.logger.warn(` - importFile ${metadata.customerKey}: ${ex.message}`); + } + } + + break; + } + case 'List': { + try { + metadata.destination.r__list_PathName = cache.getListPathName( + metadata.destinationObjectId, + 'ObjectID' + ); + delete metadata.destinationObjectId; + } catch (ex) { + Util.logger.warn(` - importFile ${metadata.customerKey}: ${ex.message}`); + } + + break; + } + case 'SMS': { + if (this.smsImports[metadata.name]) { + const smsImport = this.smsImports[metadata.name]; + + // code + try { + cache.searchForField('mobileCode', smsImport.code?.code, 'code', 'code'); + } catch (ex) { + Util.logger.warn(` - importFile ${metadata.customerKey}: ${ex.message}`); + } + // keyword + try { + cache.searchForField( + 'mobileKeyword', + smsImport.keyword?.keyword, + 'c__codeKeyword', + 'c__codeKeyword' + ); + } catch (ex) { + Util.logger.warn(` - importFile ${metadata.customerKey}: ${ex.message}`); + } + + // code + keyword + metadata.destination.r__mobileKeyword_key = + smsImport.code?.code + '.' + smsImport.keyword?.keyword; + // source dataExtension + if (smsImport.sourceObjectKey) { + metadata.source.r__dataExtension_key = smsImport.sourceObjectKey; + } + } else { + Util.logger.warn( + ` - importFile ${metadata.customerKey}: Could not find mobile code and keyword nor source for this SMS import activity.` + ); + } + // remove empty desitination delete metadata.destinationObjectId; - } catch (ex) { - Util.logger.error(`ImportFile ${metadata.customerKey}: ${ex.message}`); + + break; } + case 'WhatsApp': { + if ( + metadata.source.c__type === 'DataExtension' && + metadata.sourceCustomObjectId !== '' + ) { + // only happens for dataimport activities (summer24 release) + try { + metadata.source.r__dataExtension_key = cache.searchForField( + 'dataExtension', + metadata.sourceCustomObjectId, + 'ObjectID', + 'CustomerKey' + ); + delete metadata.sourceCustomObjectId; + delete metadata.sourceDataExtensionName; + } catch (ex) { + Util.logger.warn(` - importFile ${metadata.customerKey}: ${ex.message}`); + } + } + break; + } + default: { + Util.logger.debug( + ` - importFile ${metadata.customerKey}: Destination Type ${metadata.destinationObjectTypeId} not fully supported. Deploy might fail.` + ); + } + } + delete metadata.destinationObjectTypeId; + + if (metadata.blankFileProcessingType !== undefined) { + // omit this if not set + metadata.c__blankFileProcessing = Util.inverseGet( + this.definition.blankFileProcessingTypeMapping, + metadata.blankFileProcessingType + ); + delete metadata.blankFileProcessingType; } metadata.c__subscriberImportType = Util.inverseGet( @@ -217,11 +583,26 @@ class ImportFile extends MetadataType { delete metadata.updateTypeId; return metadata; } + + /** + * Delete a metadata item from the specified business unit + * + * @param {string} key Identifier of data extension + * @returns {Promise.<boolean>} deletion success flag + */ + static async deleteByKey(key) { + // delete only works with the query's object id + const objectId = key ? await this._getObjectIdForSingleRetrieve(key) : null; + if (!objectId) { + await this.deleteNotFound(key); + return false; + } + return super.deleteByKeyREST('/automation/v1/imports/' + objectId, key); + } } // Assign definition to static attributes -ImportFile.definition = require('../MetadataTypeDefinitions').importFile; -ImportFile.cache = {}; -ImportFile.client = undefined; +import MetadataTypeDefinitions from '../MetadataTypeDefinitions.js'; +ImportFile.definition = MetadataTypeDefinitions.importFile; -module.exports = ImportFile; +export default ImportFile; diff --git a/lib/metadataTypes/Interaction.js b/lib/metadataTypes/Interaction.js deleted file mode 100644 index 0c9a86ad2..000000000 --- a/lib/metadataTypes/Interaction.js +++ /dev/null @@ -1,24 +0,0 @@ -'use strict'; - -const MetadataType = require('./MetadataType'); - -/** - * Script MetadataType - * @augments MetadataType - */ -class Interaction extends MetadataType { - /** - * Retrieves Metadata of Interaction - * Endpoint /interaction/v1/interactions?extras=all&pageSize=50000 return 50000 Scripts with all details. - * @param {String} retrieveDir Directory where retrieved metadata directory will be saved - * @returns {Promise} Promise - */ - static retrieve(retrieveDir) { - return super.retrieveREST(retrieveDir, '/interaction/v1/interactions?extras=all', null); - } -} - -// Assign definition to static attributes -Interaction.definition = require('../MetadataTypeDefinitions').interaction; - -module.exports = Interaction; diff --git a/lib/metadataTypes/Journey.js b/lib/metadataTypes/Journey.js new file mode 100644 index 000000000..fc5aad77a --- /dev/null +++ b/lib/metadataTypes/Journey.js @@ -0,0 +1,3359 @@ +'use strict'; + +import MetadataType from './MetadataType.js'; +import TransactionalEmail from './TransactionalEmail.js'; +import DataExtensionField from './DataExtensionField.js'; +import TriggeredSend from './TriggeredSend.js'; +import Event from './Event.js'; +import { Util } from '../util/util.js'; +import cache from '../util/cache.js'; +import File from '../util/file.js'; +import ReplaceCbReference from '../util/replaceContentBlockReference.js'; +import Retriever from '../Retriever.js'; +import pLimit from 'p-limit'; +import yoctoSpinner from 'yocto-spinner'; + +/** + * @typedef {import('../../types/mcdev.d.js').BuObject} BuObject + * @typedef {import('../../types/mcdev.d.js').CodeExtract} CodeExtract + * @typedef {import('../../types/mcdev.d.js').CodeExtractItem} CodeExtractItem + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItem} MetadataTypeItem + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItemDiff} MetadataTypeItemDiff + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItemObj} MetadataTypeItemObj + * @typedef {import('../../types/mcdev.d.js').MetadataTypeMap} MetadataTypeMap + * @typedef {import('../../types/mcdev.d.js').MetadataTypeMapObj} MetadataTypeMapObj + * @typedef {import('../../types/mcdev.d.js').SoapRequestParams} SoapRequestParams + * @typedef {import('../../types/mcdev.d.js').TemplateMap} TemplateMap + * @typedef {import('../../types/mcdev.d.js').TypeKeyCombo} TypeKeyCombo + */ + +/** + * Journey MetadataType + * id: A unique id of the journey assigned by the journey’s API during its creation + * key: A unique id of the journey within the MID. Can be generated by the developer + * definitionId: A unique UUID provided by Salesforce Marketing Cloud. Each version of a journey has a unique DefinitionID while the Id and Key remain the same. Version 1 will have id == definitionId + * + * @augments MetadataType + */ +class Journey extends MetadataType { + /** + * Retrieves Metadata of Journey + * + * @param {string} retrieveDir Directory where retrieved metadata directory will be saved + * @param {void | string[]} [_] unused parameter + * @param {void | string[]} [__] unused parameter + * @param {string} [key] customer key of single item to retrieve + * @returns {Promise.<MetadataTypeMapObj>} Promise + */ + static async retrieve(retrieveDir, _, __, key) { + const extrasDefault = 'activities'; + + let singleKey = ''; + let mode = 'all'; + const additionalParams = new URLSearchParams(); + if (Util.OPTIONS.onlyPublished) { + Util.logger.info(' - Retrieving only published versions of journeys'); + additionalParams.set('status', 'Published'); + } + if (key) { + if (key.startsWith('%23')) { + // correct the format + key = 'id:' + key.slice(3); + } + if (key.startsWith('id:')) { + // ! allow selecting journeys by ID because that's what users see in the URL + // if the key started with %23 assume an ID was copied from the URL but the user forgot to prefix it with id: + + // remove id: or %23 + singleKey = key.slice(3); + if (singleKey.startsWith('%23')) { + // in the journey URL the Id is prefixed with an HTML-encoded "#" which could accidentally be copied by users + // despite the slicing above, this still needs testing here because users might have prefixed the ID with id: but did not know to remove the #23 + singleKey = singleKey.slice(3); + // correct the format to ensure we show sth readable in the "Downloaded" log + key = 'id:' + singleKey; + } + if (singleKey.includes('/')) { + // in the journey URL the version is appended after the ID, separated by a forward-slash. Needs to be removed from the ID for the retrieve as we always aim to retrieve the latest version only + singleKey = singleKey.split('/')[0]; + } + mode = 'id'; + } else if (key.startsWith('name:')) { + additionalParams.set('nameOrDescription', key.slice(5)); + mode = 'name'; + } else { + // assume actual key was provided + singleKey = 'key:' + encodeURIComponent(key); + mode = 'key'; + } + } + + try { + const uri = `/interaction/v1/interactions/`; + if ( + (!Util.OPTIONS.onlyPublished && singleKey && (mode === 'key' || mode === 'id')) || + !retrieveDir + ) { + // full details for retrieve, only base data for caching; reduces caching time from minutes to seconds + const extras = retrieveDir && singleKey ? extrasDefault : ''; + + // caching or single retrieve + return await super.retrieveREST( + retrieveDir, + `${uri}${singleKey}?extras=${extras}${key && key.includes('/') ? '&versionNumber=' + key.split('/')[1] : ''}`, + null, + key + ); + } else { + const url = + uri + (additionalParams.size > 0 ? '?' + additionalParams.toString() : ''); + // retrieve all + const results = this.definition.restPagination + ? await this.client.rest.getBulk(url, this.definition.restPageSize || 500) + : await this.client.rest.get(url); + + if (results.items?.length) { + // empty results will come back without "items" defined + Util.logger.info( + Util.getGrayMsg( + ` - ${results.items?.length} ${this.definition.type}s found. Retrieving details...` + ) + ); + } + // full details for retrieve + const extras = extrasDefault; + let details = []; + let parsed; + if (retrieveDir) { + const searchName = mode === 'name' ? key.slice(5) : null; + const foundKey = []; + let journey; + // get extra details for saving this + if (Util.OPTIONS.onlyPublished && mode === 'key') { + journey = results.items.find( + (a) => a[this.definition.keyField] === singleKey.slice(4) + ); + } else if (Util.OPTIONS.onlyPublished && mode === 'id') { + journey = results.items.find( + (a) => a[this.definition.idField] === singleKey + ); + } else { + details = results.items + ? await Promise.all( + results.items.map(async (a) => { + if (mode === 'name') { + // when filtering by name, the API in fact does a LIKE search with placeholders left and right of the search term - and also searches the description field. + if (searchName === a[this.definition.nameField]) { + foundKey.push(a[this.definition.keyField]); + } else { + // skip because the name does not match + return null; + } + } + try { + return await this.client.rest.get( + `${uri}key:${a[this.definition.keyField]}?extras=${extras}` + + `&versionNumber=${a.version}` + ); + } catch (ex) { + // if we do get here, we should log the error and continue instead of failing to download all automations + Util.logger.warn( + ` ☇ skipping ${this.definition.type} ${ + a[this.definition.nameField] + } (${a[this.definition.keyField]}): ${ex.message} (${ + ex.code + })${ + ex.endpoint + ? Util.getGrayMsg( + ' - ' + + ex.endpoint.split( + 'rest.marketingcloudapis.com' + )[1] + ) + : '' + }` + ); + return null; + } + }) + ) + : []; + } + if (Util.OPTIONS.onlyPublished && journey) { + details.push( + await this.client.rest.get( + `${uri}${singleKey}?extras=${extras}` + + `&versionNumber=${journey.version}` + ) + ); + } + parsed = this.parseResponseBody({ items: details.filter(Boolean) }); + // * retrieveDir is mandatory in this method as it is not used for caching (there is a seperate method for that) + const savedMetadata = await this.saveResults(parsed, retrieveDir, null, null); + Util.logger.info( + `Downloaded: ${this.definition.type} (${Object.keys(savedMetadata).length})` + + Util.getKeysString( + mode === 'name' ? `${foundKey.join(', ')} (${key})` : key + ) + ); + } else { + // limit to main details for caching + parsed = this.parseResponseBody(results); + } + + return { + metadata: parsed, + type: this.definition.type, + }; + } + } catch (ex) { + // if the interaction does not exist, the API returns an error code which would otherwise bring execution to a hold + if ( + [ + 'Interaction matching key not found.', // might be outdated + 'Interaction matching criteria not found.', // seen in 2025-05 + 'Must provide a valid ID or Key parameter', + ].includes(ex.message) || + (key && ex.code === 'ERR_BAD_REQUEST') + ) { + Util.logger.info( + `Downloaded: ${this.definition.type} (0)${Util.getKeysString( + mode === 'id' ? singleKey : key, + mode === 'id' + )}` + ); + if (mode === 'key') { + this.postDeleteTasks(key); + } + } else { + throw ex; + } + } + } + + /** + * Delete a metadata item from the specified business unit + * + * @param {string} key Identifier of item + * @returns {Promise.<boolean>} deletion success status + */ + static async deleteByKey(key) { + let version; + let id; + let cachedJourney; + + if (key.startsWith('id:') || key.startsWith('%23')) { + // ! allow selecting journeys by ID because that's what users see in the URL + // if the key started with %23 assume an ID was copied from the URL but the user forgot to prefix it with id: + + // remove id: or %23 + id = key.slice(3); + if (id.startsWith('%23')) { + // in the journey URL the Id is prefixed with an HTML-encoded "#" which could accidentally be copied by users + // despite the slicing above, this still needs testing here because users might have prefixed the ID with id: but did not know to remove the #23 + id = id.slice(3); + } + if (id.includes('/')) { + // in the journey URL the version is appended after the ID, separated by a forward-slash. + [id, version] = id.split('/'); + } + try { + const response = await this.client.rest.get( + `/interaction/v1/interactions/${encodeURIComponent(id)}?extras=activities` + ); + const results = this.parseResponseBody(response, key); + cachedJourney = results[key]; + } catch { + // handle below + } + } else { + if (key.includes('/')) { + // in the journey URL the version is appended after the ID, separated by a forward-slash. + [key, version] = key.split('/'); + } + + // delete by key with specified version does not work, therefore we need to get the ID first + try { + const response = await this.client.rest.get( + `/interaction/v1/interactions/key:${encodeURIComponent(key)}?extras=activities` + ); + const results = this.parseResponseBody(response, key); + cachedJourney = results[key]; + id = cachedJourney?.id; + } catch { + // handle below + } + } + if (!cachedJourney?.key) { + await this.deleteNotFound(key); + return false; + } + switch (cachedJourney.definitionType) { + case 'Multistep': { + if (version && version !== '*' && version > cachedJourney.version) { + Util.logger.error( + `The chosen version (${version}) is higher than the latest known version (${cachedJourney.version}). Please choose a lower version.` + ); + return false; + } + if (version !== '*') { + if (!/^\d+$/.test(version)) { + Util.logger.error( + 'Version is required for deleting journeys to avoid accidental deletion of the wrong item. Please append it at the end of the key or id, separated by forward-slash. Example for deleting version 4: ' + + key + + '/4' + ); + return false; + } + Util.logger.warn( + `Deleting Journeys via this command breaks following retrieve-by-key/id requests until you've deployed/created a new draft version! You can get still get the latest available version of your journey by retrieving all journeys on this BU.` + ); + } + + return super.deleteByKeyREST( + '/interaction/v1/interactions/' + + id + + (version === '*' ? '' : `?versionNumber=${version}`), + key + ); + // break; + } + case 'Quicksend': { + // Quicksend doesnt have versions + const isDeleted = await super.deleteByKeyREST( + '/interaction/v1/interactions/' + id, + key + ); + return isDeleted; + } + case 'Transactional': { + // Transactional dont have versions + const isDeleted = await super.deleteByKeyREST( + '/interaction/v1/interactions/' + id, + key + ); + const transactionalEmailKey = + cachedJourney.activities[0]?.configurationArguments?.triggeredSendKey; + if (isDeleted) { + const msg = []; + if (cachedJourney.activities[0]?.configurationArguments?.triggeredSendKey) { + msg.push( + `transactionalEmail "${cachedJourney.activities[0].configurationArguments.triggeredSendKey}"` + ); + } + } + if (isDeleted && transactionalEmailKey) { + Util.logger.info( + ` - deleted ${TransactionalEmail.definition.type}: ${transactionalEmailKey} (SFMC auto-deletes the related transactionalEmail of ${this.definition.type} ${key})` + ); + TransactionalEmail.buObject = this.buObject; + TransactionalEmail.properties = this.properties; + TransactionalEmail.client = this.client; + TransactionalEmail.postDeleteTasks(transactionalEmailKey); + } + return isDeleted; + } + } + } + + /** + * Deploys metadata + * + * @param {MetadataTypeMap} metadataMap metadata mapped by their keyField + * @param {string} deployDir directory where deploy metadata are saved + * @param {string} retrieveDir directory where metadata after deploy should be saved + * @returns {Promise.<MetadataTypeMap>} Promise of keyField => metadata map + */ + static async deploy(metadataMap, deployDir, retrieveDir) { + Util.logBeta(this.definition.type); + + let needTransactionalEmail = false; + for (const key in metadataMap) { + if (metadataMap[key].definitionType == 'Transactional') { + needTransactionalEmail = true; + break; + } + } + if (needTransactionalEmail && !cache.getCache()?.transactionalEmail) { + // ! interaction and transactionalEmail both link to each other. caching transactionalEmail here "manually", assuming that it's quicker than the other way round + Util.logger.info(' - Caching dependent Metadata: transactionalEmail'); + TransactionalEmail.buObject = this.buObject; + TransactionalEmail.client = this.client; + TransactionalEmail.properties = this.properties; + const result = await TransactionalEmail.retrieveForCache(); + cache.setMetadata('transactionalEmail', result.metadata); + } + return super.deploy(metadataMap, deployDir, retrieveDir); + } + + /** + * Updates a single item + * + * @param {MetadataTypeItem} metadata a single item + * @returns {Promise} Promise + */ + static update(metadata) { + return super.updateREST( + metadata, + '/interaction/v1/interactions/key:' + metadata.key, + 'put' + ); + } + + /** + * Creates a single item + * + * @param {MetadataTypeItem} metadata a single item + * @returns {Promise} Promise + */ + static create(metadata) { + return super.createREST(metadata, '/interaction/v1/interactions/'); + } + + /** + * Helper for writing Metadata to disk, used for Retrieve and deploy + * + * @param {MetadataTypeMap} results metadata results from deploy + * @param {string} retrieveDir directory where metadata should be stored after deploy/retrieve + * @param {string} [overrideType] for use when there is a subtype (such as folder-queries) + * @param {TemplateMap} [templateVariables] variables to be replaced in the metadata + * @returns {Promise.<MetadataTypeMap>} Promise of saved metadata + */ + static async saveResults(results, retrieveDir, overrideType, templateVariables) { + if (Object.keys(results).length) { + // only execute the following if records were found + await this._postRetrieveTasksBulk(results); + } + return super.saveResults(results, retrieveDir, overrideType, templateVariables); + } + + /** + * helper for Journey's {@link Journey.saveResults}. Gets executed after retreive of metadata type and + * + * @param {MetadataTypeMap} metadataMap key=customer key, value=metadata + */ + static async _postRetrieveTasksBulk(metadataMap) { + let needTransactionalEmail = false; + for (const key in metadataMap) { + if (metadataMap[key].definitionType == 'Transactional') { + needTransactionalEmail = true; + break; + } + } + if (needTransactionalEmail && !cache.getCache()?.transactionalEmail) { + // ! interaction and transactionalEmail both link to each other. caching transactionalEmail here "manually", assuming that it's quicker than the other way round + Util.logger.info(' - Caching dependent Metadata: transactionalEmail'); + TransactionalEmail.buObject = this.buObject; + TransactionalEmail.client = this.client; + TransactionalEmail.properties = this.properties; + const result = await TransactionalEmail.retrieveForCache(); + cache.setMetadata('transactionalEmail', result.metadata); + } + } + + /** + * manages post retrieve steps + * + * @param {MetadataTypeItem} metadata a single item + * @returns {Promise.<MetadataTypeItem>} Array with one metadata object + */ + static async postRetrieveTasks(metadata) { + // folder + if (metadata.r__folder_Path && Util.OPTIONS.publish) { + // if we re-retrieve this as part of deploy with --publish then the cached version will already have been processed + return metadata; + } + super.setFolderPath(metadata); + + switch (metadata.definitionType) { + case 'Quicksend': // Single Send Journey + case 'Multistep': { + // Single Send Journey + // ~~~ TRIGGERS ~~~~ + // event && triggers[].type === 'ContactAudience' + // Multi-Step Journey + // ~~~ TRIGGERS ~~~~ + // event / definitionType==='Multistep' && channel==='' && triggers[].type === 'EmailAudience'|'APIEvent' + if (metadata.triggers?.length > 0) { + const search = ['arguments', 'metaData']; + for (const area of search) { + const config = metadata.triggers[0][area]; + if (config?.eventDefinitionId) { + // trigger found; there can only be one entry in this array + try { + const edKey = cache.searchForField( + 'event', + config.eventDefinitionId, + 'id', + 'eventDefinitionKey' + ); + if (config.eventDefinitionKey !== edKey) { + Util.logger.debug( + `eventDefinitionKey not matching eventDefinitionId. Overwriting '${config.eventDefinitionKey}' with the correct key '${edKey}'.` + ); + } + config.r__event_key = edKey; + + delete config.eventDefinitionKey; + delete config.eventDefinitionId; + } catch (ex) { + const msg = ` - ${this.definition.type} ${metadata[this.definition.nameField]} (${ + metadata[this.definition.keyField] + }) ${metadata.status}: ${ex.message}.`; + Util.logger.warn( + metadata.status === 'Published' ? msg : Util.getGrayMsg(msg) + ); + } + } + if (config?.dataExtensionId) { + try { + config.r__dataExtension_key = cache.searchForField( + 'dataExtension', + config.dataExtensionId, + 'ObjectID', + 'CustomerKey' + ); + delete config.dataExtensionId; + } catch (ex) { + Util.logger.warn( + ` - ${this.definition.type} ${metadata[this.definition.nameField]} (${ + metadata[this.definition.keyField] + }): ${ex.message}.` + ); + } + } + } + try { + await Event.postRetrieveTasks_SalesforceEntryEvents( + metadata.triggers[0].type, + metadata.triggers[0].configurationArguments, + metadata.key, + metadata.status === 'Published', + this.definition.type + ); + } catch (ex) { + const msg = ` - ${this.definition.type} '${metadata[this.definition.nameField]}' (${metadata[this.definition.keyField]}) ${metadata.status}: ${ex.message}`; + Util.logger.warn( + metadata.status === 'Published' ? msg : Util.getGrayMsg(msg) + ); + } + } + // ~~~ ACTIVITIES ~~~~ + + await this._postRetrieveTasks_activities(metadata); + + // TODO: journey template id? / metaData.templateId + break; + } + case 'Transactional': { + // Transactional Send Journey + // ~~~ TRIGGERS ~~~~ + // ! journeys so far only supports transactional EMAIL messages. SMS and Push do not create their own journey. + // ! transactional (email) journeys only have a dummy trigger without real content. + // transactionalEmail / definitionType==='Transactional' && channel==='email' && triggers[].type === 'transactional-api' + // --> nothing to do here + + // ~~~ ACTIVITIES ~~~~ + // ! transactional (email) journeys only have one activity (type=EMAILV2) which links back to the transactionalEmail () + switch (metadata.channel) { + case 'email': { + if (metadata.activities?.length > 0) { + const activity = metadata.activities[0]; + // trigger found; there can only be one entry in this array + + if (activity.configurationArguments?.triggeredSendId) { + try { + const tEmailKey = cache.searchForField( + 'transactionalEmail', + activity.configurationArguments?.triggeredSendId, + 'definitionId', + 'definitionKey' + ); + if ( + activity.configurationArguments?.triggeredSendKey && + tEmailKey != + activity.configurationArguments?.triggeredSendKey + ) { + Util.logger.debug( + `triggeredSendKey not matching triggeredSendId. Overwriting '${activity.configurationArguments.triggeredSendKey}' with the correct key '${tEmailKey}'.` + ); + } + activity.configurationArguments.r__transactionalEmail_key = + tEmailKey; + delete activity.configurationArguments.triggeredSendKey; + delete activity.configurationArguments.triggeredSendId; + } catch (ex) { + Util.logger.warn( + ` - ${this.definition.type} ${ + metadata[this.definition.nameField] + } (${metadata[this.definition.keyField]}): ${ex.message}.` + ); + } + } + if ( + activity.metaData?.highThroughput?.definitionKey && + activity.configurationArguments?.r__transactionalEmail_key && + activity.metaData?.highThroughput?.definitionKey != + activity.configurationArguments.r__transactionalEmail_key + ) { + Util.logger.warn( + ` - ${this.definition.type} ${ + metadata[this.definition.nameField] + } (${metadata[this.definition.keyField]}): activities[0].metaData.highThroughput.definitionKey not matching key in activities[0].configurationArguments.r__transactionalEmail_key.` + ); + } else if ( + activity.configurationArguments?.r__transactionalEmail_key && + metadata.status === 'Published' + ) { + // as long as status is Draft, we wont have r__transactionalEmail_key set as that record will not have been created + delete activity.metaData.highThroughput.definitionKey; + } + + await this._postRetrieveTasks_activities(metadata); + + if (activity.metaData?.highThroughput?.dataExtensionId) { + try { + activity.metaData.highThroughput.r__dataExtension_key = + cache.searchForField( + 'dataExtension', + activity.metaData.highThroughput.dataExtensionId, + 'ObjectID', + 'CustomerKey' + ); + delete activity.metaData.highThroughput.dataExtensionId; + } catch (ex) { + Util.logger.warn( + ` - ${this.definition.type} ${ + metadata[this.definition.nameField] + } (${metadata[this.definition.keyField]}): ${ex.message}.` + ); + } + } + } + + break; + } + default: { + // it is expected that we'll see 'sms' and 'push' here in the future + Util.logger.warn( + ` - ${this.definition.type} ${metadata[this.definition.nameField]} (${ + metadata[this.definition.keyField] + }): channel ${ + metadata.channel + } is not supported yet. Please open a ticket at https://github.com/Accenture/sfmc-devtools/issues/new/choose to request it` + ); + } + } + + break; + } + default: { + Util.logger.warn( + ` - ${this.definition.type} ${metadata[this.definition.nameField]} (${ + metadata[this.definition.keyField] + }): definitionType ${ + metadata.definitionType + } is not supported yet. Please open a ticket at https://github.com/Accenture/sfmc-devtools/issues/new/choose to request it` + ); + } + } + + return metadata; + } + + /** + * helper for {@link Journey.postRetrieveTasks} + * + * @private + * @param {MetadataTypeItem} metadata a single item + */ + static async _postRetrieveTasks_activities(metadata) { + if (!metadata.activities) { + return; + } + for (const activity of metadata.activities) { + switch (activity.type) { + case 'EMAILV2': { + // triggeredSend + email+asset + const configurationArguments = activity.configurationArguments; + if (configurationArguments) { + try { + // configurationArguments.triggeredSendKey && configurationArguments.triggeredSendId are only set on a running journey; if a journey is new, they do not exist + if (configurationArguments.triggeredSendId) { + // triggeredSendKey is not always set but triggeredSendId is + const tsKey = cache.searchForField( + 'triggeredSend', + configurationArguments.triggeredSendId, + 'ObjectID', + 'CustomerKey' + ); + if (configurationArguments.triggeredSendKey != tsKey) { + Util.logger.debug( + `triggeredSendKey not matching triggeredSendId. Overwriting '${configurationArguments.triggeredSendKey}' with the correct key '${tsKey}'.` + ); + configurationArguments.triggeredSendKey = tsKey; + } + configurationArguments.r__triggeredSend_key = + configurationArguments.triggeredSendKey; + delete configurationArguments.triggeredSendKey; + delete configurationArguments.triggeredSendId; + } else if (configurationArguments.triggeredSendKey) { + // very rare case but it's been seen that no triggeredSendId was saved + Util.logger.debug( + `triggeredSendKey found on activity but no triggeredSendId present on journey. Checking key directly...` + ); + configurationArguments.r__triggeredSend_key = cache.searchForField( + 'triggeredSend', + configurationArguments.triggeredSendKey, + 'CustomerKey', + 'CustomerKey' + ); + delete configurationArguments.triggeredSendKey; + } + } catch (ex) { + Util.logger.warn( + ` - ${this.definition.type} '${metadata[this.definition.nameField]}' (${ + metadata[this.definition.keyField] + }) activity-key=${activity.key}: ${ex.message}` + ); + } + } + if ( + configurationArguments?.triggeredSend && + 'string' === typeof configurationArguments?.triggeredSend + ) { + // sometimes, the API returns this object as a string for unknown reasons. Good job, product team! + configurationArguments.triggeredSend = JSON.parse( + configurationArguments?.triggeredSend + ); + } + const triggeredSend = configurationArguments?.triggeredSend; + if (triggeredSend) { + // this section is likely only relevant for QuickSends and not for Multi-Step Journeys + // triggeredSend key + if (configurationArguments.r__transactionalEmail_key) { + const linkedTE = cache.getByKey( + 'transactionalEmail', + configurationArguments.r__transactionalEmail_key + ); + if (linkedTE) { + if (linkedTE.subscriptions) { + triggeredSend.autoAddSubscribers = + linkedTE.subscriptions.autoAddSubscriber; + triggeredSend.autoUpdateSubscribers = + linkedTE.subscriptions.updateSubscriber; + + // List + if (linkedTE.subscriptions?.list) { + triggeredSend.publicationListId = cache.searchForField( + 'list', + linkedTE.subscriptions.list, + 'CustomerKey', + 'ID' + ); + } else if (linkedTE.subscriptions.r__list_PathName) { + delete triggeredSend.publicationListId; + triggeredSend.r__list_PathName = { + publicationList: + linkedTE.subscriptions.r__list_PathName, + }; + } + + // dataExtension + if (linkedTE.subscriptions.dataExtension) { + try { + activity.metaData.highThroughput.r__dataExtension_key = + cache.searchForField( + 'dataExtension', + linkedTE.subscriptions.dataExtension, + 'CustomerKey', + 'CustomerKey' + ); + delete activity.metaData.highThroughput.dataExtensionId; + } catch (ex) { + Util.logger.warn( + ` - ${this.definition.type} ${ + metadata[this.definition.nameField] + } (${metadata[this.definition.keyField]}): ${ex.message}.` + ); + } + } else if (linkedTE.subscriptions.r__dataExtension_key) { + activity.metaData.highThroughput.r__dataExtension_key = + linkedTE.subscriptions.r__dataExtension_key; + delete activity.metaData.highThroughput.dataExtensionId; + } + } + if (linkedTE.options) { + triggeredSend.isTrackingClicks = + linkedTE.options.trackLinks || false; + triggeredSend.ccEmail = linkedTE.options.cc || ''; + triggeredSend.bccEmail = linkedTE.options.bcc || ''; + } + + // send classification + if (linkedTE.classification) { + try { + const scKey = cache.searchForField( + 'sendClassification', + linkedTE.classification, + 'CustomerKey', + 'CustomerKey' + ); + triggeredSend.r__sendClassification_key = scKey; + delete triggeredSend.sendClassificationId; + } catch (ex) { + Util.logger.warn( + ` - transactionalEmail ${linkedTE.definitionKey}: ${ex.message} (sendClassification key ${linkedTE.classification})` + ); + } + } else if (linkedTE.r__sendClassification_key) { + triggeredSend.r__sendClassification_key = + linkedTE.r__sendClassification_key; + } + + // senderProfile + deliveryProfile from sendClassification + if (triggeredSend.r__sendClassification_key) { + const sc = cache.getByKey( + 'sendClassification', + triggeredSend.r__sendClassification_key + ); + + if (sc.SenderProfile?.ObjectID) { + triggeredSend.r__senderProfile_key = cache.searchForField( + 'senderProfile', + sc.SenderProfile.ObjectID, + 'ObjectID', + 'CustomerKey' + ); + delete triggeredSend.senderProfileId; + } else if (sc.r__senderProfile_key) { + triggeredSend.r__senderProfile_key = + sc.r__senderProfile_key; + delete triggeredSend.senderProfileId; + } + if (sc.DeliveryProfile?.ObjectID) { + triggeredSend.r__deliveryProfile_key = cache.searchForField( + 'deliveryProfile', + sc.DeliveryProfile.ObjectID, + 'ObjectID', + 'key' + ); + delete triggeredSend.deliveryProfileId; + } else if (sc.r__deliveryProfile_key) { + triggeredSend.r__deliveryProfile_key = + sc.r__deliveryProfile_key; + delete triggeredSend.deliveryProfileId; + } + } + } + } else if (configurationArguments.r__triggeredSend_key) { + // if we have a key set outside of this detailed triggeredSend config then lets overwrite what we've got here with what we cached from the related TS as it will be more current; but we cannot retrieve all info unfortunately + triggeredSend.r__triggeredSend_key = + configurationArguments.r__triggeredSend_key; + delete triggeredSend.id; + delete triggeredSend.key; + const linkedTS = cache.getByKey( + 'triggeredSend', + configurationArguments.r__triggeredSend_key + ); + if (linkedTS) { + triggeredSend.emailId = linkedTS.Email?.ID; + triggeredSend.dynamicEmailSubject = linkedTS.DynamicEmailSubject; + triggeredSend.emailSubject = linkedTS.EmailSubject; + // only the bccEmail field can be retrieved for triggeredSends, not the ccEmail field; for some reason BccEmail can be retrieved but does not return a value even if stored correctly in the journey. + // triggeredSend.bccEmail = linkedTS.BccEmail; + triggeredSend.isMultipart = linkedTS.IsMultipart; + triggeredSend.autoAddSubscribers = linkedTS.AutoAddSubscribers; + triggeredSend.autoUpdateSubscribers = + linkedTS.AutoUpdateSubscribers; + triggeredSend.isTrackingClicks = !linkedTS.SuppressTracking; + triggeredSend.suppressTracking = linkedTS.SuppressTracking; + triggeredSend.triggeredSendStatus = linkedTS.TriggeredSendStatus; + // from name & email are set in the senderProfile, not in the triggeredSend + // triggeredSend.fromName = linkedTS.FromName; + // triggeredSend.fromAddress = linkedTS.FromAddress; + + // List + if (linkedTS.List?.ID) { + triggeredSend.publicationListId = linkedTS.List.ID; + } else if (linkedTS.r__list_PathName) { + delete triggeredSend.publicationListId; + triggeredSend.r__list_PathName = { + publicationList: linkedTS.r__list_PathName, + }; + } + if (linkedTS.SenderProfile?.CustomerKey) { + try { + const spKey = cache.searchForField( + 'senderProfile', + linkedTS.SenderProfile.ObjectID, + 'ObjectID', + 'CustomerKey' + ); + triggeredSend.r__senderProfile_key = spKey; + delete triggeredSend.senderProfileId; + } catch (ex) { + Util.logger.warn( + ` - triggeredSend ${linkedTS.CustomerKey}: ${ex.message} (senderProfile key ${linkedTS.SenderProfile.CustomerKey})` + ); + } + } else if (linkedTS.r__senderProfile_key) { + triggeredSend.r__senderProfile_key = + linkedTS.r__senderProfile_key; + } + // send classification + if (linkedTS.SendClassification?.CustomerKey) { + try { + const scKey = cache.searchForField( + 'sendClassification', + linkedTS.SendClassification.ObjectID, + 'ObjectID', + 'CustomerKey' + ); + triggeredSend.r__sendClassification_key = scKey; + delete triggeredSend.sendClassificationId; + } catch (ex) { + Util.logger.warn( + ` - triggeredSend ${linkedTS.CustomerKey}: ${ex.message} (sendClassification key ${linkedTS.SendClassification.CustomerKey})` + ); + } + } else if (linkedTS.r__sendClassification_key) { + triggeredSend.r__sendClassification_key = + linkedTS.r__sendClassification_key; + } + if (linkedTS.c__priority) { + delete triggeredSend.priority; + triggeredSend.c__priority = linkedTS.c__priority; + } + if (linkedTS.Email?.ID) { + triggeredSend.emailId = linkedTS.Email.ID; + } else if (linkedTS.r__asset_key) { + delete triggeredSend.emailId; + triggeredSend.r__asset_name_readOnly = + linkedTS.r__asset_name_readOnly; + triggeredSend.r__asset_key = linkedTS.r__asset_key; + } + } + } else if (triggeredSend.id) { + // triggeredSendKey is not always set but id is + const tsKey = cache.searchForField( + 'triggeredSend', + triggeredSend.id, + 'ObjectID', + 'CustomerKey' + ); + if (triggeredSend.key != tsKey) { + Util.logger.debug( + `key not matching id. Overwriting '${triggeredSend.key}' with the correct key '${tsKey}'.` + ); + triggeredSend.key = tsKey; + } + triggeredSend.r__triggeredSend_key = triggeredSend.key; + delete triggeredSend.key; + delete triggeredSend.id; + } else if (triggeredSend.key) { + // very rare case but it's been seen that no id was saved + Util.logger.debug( + `key found on triggeredSend but no id present on journey activity. Checking key directly...` + ); + triggeredSend.r__triggeredSend_key = cache.searchForField( + 'triggeredSend', + triggeredSend.key, + 'CustomerKey', + 'CustomerKey' + ); + delete triggeredSend.key; + } + + if (typeof triggeredSend.ccEmail === 'string') { + triggeredSend.ccEmail = triggeredSend.ccEmail + .split(';') + .filter((el) => el !== ''); + } + if (typeof triggeredSend.bccEmail === 'string') { + triggeredSend.bccEmail = triggeredSend.bccEmail + .split(';') + .filter((el) => el !== ''); + } + + // List (optional) + triggeredSend.r__list_PathName ||= {}; + if (triggeredSend.publicationListId) { + try { + triggeredSend.r__list_PathName.publicationList = + cache.getListPathName(triggeredSend.publicationListId, 'ID'); + delete triggeredSend.publicationListId; + } catch (ex) { + Util.logger.warn( + ` - ${this.definition.typeName} '${metadata.name}'/'${metadata.key}': ${ex.message}` + ); + // save this TSD because it could be fixed by the user + } + } + if ( + triggeredSend.suppressionLists && + Array.isArray(triggeredSend.suppressionLists) && + triggeredSend.suppressionLists.length + ) { + triggeredSend.r__list_PathName.suppressionLists = + triggeredSend.suppressionLists.map((sList) => { + try { + return cache.getListPathName(sList.id, 'ID'); + } catch (ex) { + Util.logger.warn( + ` - ${this.definition.typeName} '${metadata.name}'/'${metadata.key}': ${ex.message}` + ); + // save this TSD because it could be fixed by the user + } + }); + delete triggeredSend.suppressionLists; + } + if (!Object.keys(triggeredSend.r__list_PathName).length) { + // in case we found no linked lists, remove this empty shell + delete triggeredSend.r__list_PathName; + } + + // DataExtension (optional) + triggeredSend.r__dataExtension_key = {}; + if ( + triggeredSend.domainExclusions && + Array.isArray(triggeredSend.domainExclusions) && + triggeredSend.domainExclusions.length + ) { + let errors = 0; + triggeredSend.r__dataExtension_key.domainExclusions = + triggeredSend.domainExclusions.map((de) => { + try { + return cache.searchForField( + 'dataExtension', + de.id, + 'ObjectID', + 'CustomerKey' + ); + } catch (ex) { + errors++; + Util.logger.warn( + ` - ${this.definition.typeName} '${metadata.name}'/'${metadata.key}': ${ex.message}` + ); + // save this TSD because it could be fixed by the user + } + }); + if (!errors) { + delete triggeredSend.domainExclusions; // array with id & name of DE + } + } + if (!Object.keys(triggeredSend.r__dataExtension_key).length) { + // in case we found no linked dataExtensions, remove this empty shell + delete triggeredSend.r__dataExtension_key; + } + + // sender profile + if (triggeredSend.senderProfileId) { + try { + triggeredSend.r__senderProfile_key = cache.searchForField( + 'senderProfile', + triggeredSend.senderProfileId, + 'ObjectID', + 'CustomerKey' + ); + delete triggeredSend.senderProfileId; + } catch (ex) { + Util.logger.warn( + ` - ${this.definition.type} '${metadata[this.definition.nameField]}' (${ + metadata[this.definition.keyField] + }): ${ex.message}` + ); + } + } + // send classification + if (triggeredSend.sendClassificationId) { + try { + triggeredSend.r__sendClassification_key = cache.searchForField( + 'sendClassification', + triggeredSend.sendClassificationId, + 'ObjectID', + 'CustomerKey' + ); + delete triggeredSend.sendClassificationId; + } catch (ex) { + Util.logger.warn( + ` - ${this.definition.type} '${metadata[this.definition.nameField]}' (${ + metadata[this.definition.keyField] + }): ${ex.message}` + ); + } + } + // delivery profile + if (triggeredSend.deliveryProfileId) { + try { + triggeredSend.r__deliveryProfile_key = cache.searchForField( + 'deliveryProfile', + triggeredSend.deliveryProfileId, + 'ObjectID', + 'key' + ); + delete triggeredSend.deliveryProfileId; + } catch { + Util.logger.warn( + ` - ${this.definition.type} '${metadata[this.definition.nameField]}' (${ + metadata[this.definition.keyField] + }): Dependent deliveryProfile was not found. Please note that this can only be resolved if you have at least ONE Send Classification set up on the target BU that uses this Delivery Profile.` + ); + } + } + // message priority + if (triggeredSend.priority) { + triggeredSend.c__priority = Util.inverseGet( + this.definition.priorityMapping, + triggeredSend.priority + ); + delete triggeredSend.priority; + } + // email + if (triggeredSend.emailId) { + try { + // content builder + triggeredSend.r__asset_name_readOnly = cache.searchForField( + 'asset', + triggeredSend.emailId, + 'legacyData.legacyId', + 'name' + ); + triggeredSend.r__asset_key = cache.searchForField( + 'asset', + triggeredSend.emailId, + 'legacyData.legacyId', + 'customerKey' + ); + delete triggeredSend.emailId; + } catch { + try { + // classic + triggeredSend.r__email_name = cache.searchForField( + 'email', + triggeredSend.emailId, + 'ID', + 'Name' + ); + delete triggeredSend.emailId; + } catch { + const msg = ` - ${this.definition.type} '${metadata[this.definition.nameField]}' (${ + metadata[this.definition.keyField] + }): Could not find email with ID ${triggeredSend.emailId} in Classic nor in Content Builder.`; + Util.logger.warn( + metadata.status === 'Published' ? msg : Util.getGrayMsg(msg) + ); + } + } + } + + // sort attributes of triggeredSend alphabetically to allow for easier pull request reviews + configurationArguments.triggeredSend = + Util.sortObjectAttributes(triggeredSend); + } + break; + } + case 'SMSSYNC': { + const configurationArguments = activity.configurationArguments; + if (configurationArguments) { + // mobileMessage + try { + if (configurationArguments.messageId) { + configurationArguments.r__mobileMessage_key = cache.searchForField( + 'mobileMessage', + configurationArguments.messageId, + 'id', + 'id' + ); + delete configurationArguments.messageId; + } + } catch (ex) { + Util.logger.warn( + ` - ${this.definition.type} '${metadata[this.definition.nameField]}' (${ + metadata[this.definition.keyField] + }) activity-key=${activity.key}: ${ex.message}` + ); + } + // mobileKeyword + configurationArguments.r__mobileKeyword_key = {}; + try { + if (configurationArguments.keywordId) { + configurationArguments.r__mobileKeyword_key.current = + cache.searchForField( + 'mobileKeyword', + configurationArguments.keywordId, + 'id', + 'c__codeKeyword' + ); + delete configurationArguments.keywordId; + } + } catch (ex) { + Util.logger.warn( + ` - ${this.definition.type} '${metadata[this.definition.nameField]}' (${ + metadata[this.definition.keyField] + }) activity-key=${activity.key}: ${ex.message}` + ); + } + try { + if (configurationArguments.nextKeywordId) { + configurationArguments.r__mobileKeyword_key.next = + cache.searchForField( + 'mobileKeyword', + configurationArguments.nextKeywordId, + 'id', + 'c__codeKeyword' + ); + delete configurationArguments.nextKeywordId; + } + } catch (ex) { + Util.logger.warn( + ` - ${this.definition.type} '${metadata[this.definition.nameField]}' (${ + metadata[this.definition.keyField] + }) activity-key=${activity.key}: ${ex.message}` + ); + } + if (!Object.keys(configurationArguments.r__mobileKeyword_key).length) { + // in case we found no linked dataExtensions, remove this empty shell + delete configurationArguments.r__mobileKeyword_key; + } + // mobileCode + try { + if (configurationArguments.codeId) { + configurationArguments.r__mobileCode_key = cache.searchForField( + 'mobileCode', + configurationArguments.codeId, + 'id', + 'code' + ); + delete configurationArguments.codeId; + } + } catch (ex) { + Util.logger.warn( + ` - ${this.definition.type} '${metadata[this.definition.nameField]}' (${ + metadata[this.definition.keyField] + }) activity-key=${activity.key}: ${ex.message}` + ); + } + + try { + // asset-asset: jsonmessage + if (configurationArguments.assetId) { + configurationArguments.r__asset_name_readOnly = + cache.searchForField( + 'asset', + configurationArguments.assetId, + 'id', + 'name' + ); + + configurationArguments.r__asset_key = cache.searchForField( + 'asset', + configurationArguments.assetId, + 'id', + 'customerKey' + ); + delete configurationArguments.assetId; + } + } catch (ex) { + Util.logger.warn( + ` - ${this.definition.type} '${metadata[this.definition.nameField]}' (${ + metadata[this.definition.keyField] + }) activity-key=${activity.key}: ${ex.message}` + ); + } + + // applicationExtensionId always equal "00000000-0000-0000-0000-000000000000" + delete configurationArguments.applicationExtensionId; + } + break; + } + case 'UPDATECONTACTDATA': { + const contactFields = + activity?.arguments?.activityData?.updateContactFields ?? []; + let tempCachedFields = false; + for (const contactField of contactFields) { + try { + contactField.r__dataExtension_key = cache.searchForField( + 'dataExtension', + contactField.dataExtensionId, + 'ObjectID', + 'CustomerKey' + ); + delete contactField.dataExtensionId; + } catch (ex) { + Util.logger.warn( + ` - ${this.definition.type} '${metadata[this.definition.nameField]}' (${ + metadata[this.definition.keyField] + }) activity-key=${activity.key}: ${ex.message}` + ); + } + // Don't replace the field Id with the name if DE CustomerKey was not found + try { + if (!cache.getCache().dataExtensionField) { + tempCachedFields = true; + DataExtensionField.buObject = this.buObject; + DataExtensionField.client = this.client; + DataExtensionField.properties = this.properties; + const fields = await DataExtensionField.retrieveFieldsForSingleDe( + contactField.r__dataExtension_key + ); + cache.setMetadata('dataExtensionField', fields); + } + contactField.r__dataExtensionField_name = cache.searchForField( + 'dataExtensionField', + contactField.field, + 'ObjectID', + 'Name' + ); + delete contactField.field; + } catch (ex) { + Util.logger.warn( + ` - ${this.definition.type} '${metadata[this.definition.nameField]}' (${ + metadata[this.definition.keyField] + }) activity-key=${activity.key}: ${ex.message}` + ); + } + } + if (tempCachedFields) { + // reset dataExtensionField caching to trigger re-caching + cache.clearCache(this.buObject.mid, 'dataExtensionField'); + } + } + } + } + + // apply sorting by activity key to work around the API shuffling activities around + metadata.activities = metadata.activities.toSorted((a, b) => a.key.localeCompare(b.key)); + } + + /** + * prepares a TSD for deployment + * ! BETA RELEASE of journey support (v4.3.0); it so far only resolves a limited amount of dependencies and will likely break during cross-BU deployments! + * + * @param {MetadataTypeItem} metadata of a single TSD + * @returns {Promise.<MetadataTypeItem>} metadata object + */ + static async preDeployTasks(metadata) { + if (metadata.status !== 'Draft') { + metadata.status = 'Draft'; + } + + // folder + super.setFolderId(metadata); + + switch (metadata.definitionType) { + case 'Quicksend': + case 'Multistep': { + // Multi-Step Journey + // ~~~ TRIGGERS ~~~~ + + // event / definitionType==='Multistep' && channel==='' && triggers[].type === 'EmailAudience'|'APIEvent' + + if (metadata.triggers?.length > 0) { + const search = ['arguments', 'metaData']; + for (const area of search) { + const config = metadata.triggers[0][area]; + if (config?.r__event_key) { + // trigger found; there can only be one entry in this array + config.eventDefinitionId = cache.searchForField( + 'event', + config.r__event_key, + 'eventDefinitionKey', + 'id' + ); + config.eventDefinitionKey = config.r__event_key; + delete config.r__event_key; + } + if (config?.r__dataExtension_key) { + // trigger found; there can only be one entry in this array + config.dataExtensionId = cache.searchForField( + 'dataExtension', + config.r__dataExtension_key, + 'CustomerKey', + 'ObjectID' + ); + delete config.r__dataExtension_key; + } + } + const warnings = await Event.preDeployTasks_SalesforceEntryEvents( + metadata.triggers[0].type, + metadata.triggers[0].configurationArguments + ); + if (warnings) { + Util.logger.warn( + ` - ${this.definition.type} '${metadata[this.definition.nameField]}' (${metadata[this.definition.keyField]}): ${warnings}` + ); + } + } + + // transactionalEmail / definitionType==='Transactional' && channel==='email' && triggers[].type === 'transactional-api' + + // ~~~ ACTIVITIES ~~~~ + + await this._preDeployTasks_activities(metadata); + + break; + } + case 'Transactional': { + const cachedVersion = cache.getByKey('journey', metadata.key); + if (cachedVersion?.status === 'Published') { + if (Util.OPTIONS.publish) { + Util.logger.info( + ` - ${this.definition.type} ${metadata.key}: --publish option used. Automatically pausing journey to allow for updates.` + ); + + const pausedKeys = await this.pause([metadata.key], { + metadata: cache.getCache().journey, + type: this.definition.type, + }); + if (!pausedKeys?.length || pausedKeys[0] !== metadata.key) { + Util.logger.error( + ` - failed to pause ${this.definition.typeName}: ${metadata.key}` + ); + throw new Error( + `Cannot update transactional-send journey in Published status. Automatic pausing failed.` + ); + } + + cachedVersion.status = 'Paused'; + } else { + throw new Error( + `Cannot update transactional-send journey in Published status. Run deploy with --publish to auto-pause & republish the journey.` + ); + } + } + + // Transactional Send Journey + // ~~~ TRIGGERS ~~~~ + // ! journeys so far transactional EMAIL messages. SMS and Push do not create their own journey. + // ! transactional (email) journeys only have a dummy trigger without real content. + + // transactionalEmail / definitionType==='Transactional' && channel==='email' && triggers[].type === 'transactional-api' + // --> nothing to do here + + // ~~~ ACTIVITIES ~~~~ + // ! transactional (email) journeys only have one activity (type=EMAILV2) which links back to the transactionalEmail () + switch (metadata.channel) { + case 'email': { + const activity = metadata.activities[0]; + if (activity.configurationArguments?.r__transactionalEmail_key) { + // trigger found; there can only be one entry in this array + try { + activity.configurationArguments.triggeredSendId = + cache.searchForField( + 'transactionalEmail', + activity.configurationArguments.r__transactionalEmail_key, + 'definitionKey', + 'definitionId' + ); + activity.configurationArguments.triggeredSendKey = + activity.configurationArguments.r__transactionalEmail_key; + } catch (ex) { + const isCreateMode = !cachedVersion; + if ( + (isCreateMode && !Util.OPTIONS.publish) || + (!isCreateMode && cachedVersion.status === 'Draft') + ) { + // no need to add a log entry if the publish-option was provided + Util.logger.info( + ` - ${this.definition.type} ${metadata[this.definition.nameField]} (${ + metadata[this.definition.keyField] + }): To activate this transactional journey (and create the associated transactionalEmail record), please run 'mcdev publish ${this.buObject.credential}/${this.buObject.businessUnit} -m journey:"${metadata.key}" ' or click on "Activate" in the GUI.` + ); + } else if (!isCreateMode) { + // block deployment if we are in update mode + throw ex; + } + } + if (activity.metaData?.highThroughput) { + // this is crucial for pinging the /interaction/v1/interactions/transactional/create endpoint that creates the transactionalEmail + activity.metaData.highThroughput.definitionKey = + activity.configurationArguments.r__transactionalEmail_key; + } + delete activity.configurationArguments.r__transactionalEmail_key; + } + + if (activity.metaData?.highThroughput?.r__dataExtension_key) { + // if this is set during create, we expect that the DE is already present (part of current deployment or already existing) + activity.metaData.highThroughput.dataExtensionId = cache.searchForField( + 'dataExtension', + activity.metaData.highThroughput.r__dataExtension_key, + 'CustomerKey', + 'ObjectID' + ); + delete activity.metaData.highThroughput.r__dataExtension_key; + } + + await this._preDeployTasks_activities(metadata); + + break; + } + default: { + // it is expected that we'll see 'sms' and 'push' here in the future + throw new Error( + `channel ${metadata.channel} is not supported yet. Please open a ticket at https://github.com/Accenture/sfmc-devtools/issues/new/choose to request it` + ); + } + } + + break; + } + default: { + throw new Error( + `definitionType ${metadata.definitionType} is not supported yet. Please open a ticket at https://github.com/Accenture/sfmc-devtools/issues/new/choose to request it` + ); + } + } + return metadata; + } + + /** + * helper for {@link Journey.preDeployTasks} + * + * @private + * @param {MetadataTypeItem} metadata a single item + */ + static async _preDeployTasks_activities(metadata) { + for (const activity of metadata.activities) { + switch (activity.type) { + case 'EMAILV2': { + // triggeredSend + email+asset + const configurationArguments = activity.configurationArguments; + if (configurationArguments?.r__triggeredSend_key) { + // triggeredSendKey is not always set but triggeredSendId is + try { + configurationArguments.triggeredSendId = cache.searchForField( + 'triggeredSend', + configurationArguments.r__triggeredSend_key, + 'CustomerKey', + 'ObjectID' + ); + configurationArguments.triggeredSendKey = + configurationArguments.r__triggeredSend_key; + delete configurationArguments.r__triggeredSend_key; + } catch { + Util.logger.warn( + ` - ${this.definition.type} '${metadata[this.definition.nameField]}' (${metadata[this.definition.keyField]}): Could not find triggeredSend with key ${configurationArguments.r__triggeredSend_key}. Attempting to let the API auto-create it` + ); + } + } + const triggeredSend = configurationArguments?.triggeredSend; + if (triggeredSend) { + // triggeredSend key + if ( + !configurationArguments.r__triggeredSend_key && + triggeredSend.r__triggeredSend_key + ) { + try { + // key is not always set but id is + triggeredSend.id = cache.searchForField( + 'triggeredSend', + triggeredSend.r__triggeredSend_key, + 'CustomerKey', + 'ObjectID' + ); + triggeredSend.key = triggeredSend.r__triggeredSend_key; + } catch { + Util.logger.warn( + ` - ${this.definition.type} '${metadata[this.definition.nameField]}' (${metadata[this.definition.keyField]}): Could not find triggeredSend with key ${triggeredSend.r__triggeredSend_key}. Attempting to let the API auto-create it` + ); + } + delete triggeredSend.r__triggeredSend_key; + } + + if (triggeredSend.ccEmail !== undefined) { + triggeredSend.ccEmail = Array.isArray(triggeredSend.ccEmail) + ? triggeredSend.ccEmail?.join(';') + : triggeredSend.ccEmail; + } + if (triggeredSend.bccEmail !== undefined) { + triggeredSend.bccEmail = Array.isArray(triggeredSend.bccEmail) + ? triggeredSend.bccEmail?.join(';') + : triggeredSend.bccEmail; + } + + // List (optional) + if (triggeredSend.r__list_PathName) { + if (triggeredSend.r__list_PathName.publicationList) { + triggeredSend.publicationListId = cache.getListObjectId( + triggeredSend.r__list_PathName.publicationList, + 'ID' + ); + } + if (triggeredSend.r__list_PathName.suppressionLists?.length) { + triggeredSend.suppressionLists = + triggeredSend.r__list_PathName.suppressionLists.map( + (listPathName) => { + const id = cache.getListObjectId(listPathName, 'ID'); + const name = cache.getListObjectId( + listPathName, + 'ListName' + ); + return { id, name }; + } + ); + } + delete triggeredSend.r__list_PathName; + } + // DataExtension (optional) + if (triggeredSend.r__dataExtension_key?.length) { + triggeredSend.domainExclusions = triggeredSend.r__dataExtension_key.map( + (key) => { + const id = cache.searchForField( + 'dataExtension', + key, + 'CustomerKey', + 'ObjectID' + ); + const name = cache.searchForField( + 'dataExtension', + key, + 'CustomerKey', + 'Name' + ); + return { id, name }; + } + ); + } + + // sender profile + if (triggeredSend.r__senderProfile_key) { + triggeredSend.senderProfileId = cache.searchForField( + 'senderProfile', + triggeredSend.r__senderProfile_key, + 'CustomerKey', + 'ObjectID' + ); + delete triggeredSend.r__senderProfile_key; + } + // send classification + if (triggeredSend.r__sendClassification_key) { + triggeredSend.sendClassificationId = cache.searchForField( + 'sendClassification', + triggeredSend.r__sendClassification_key, + 'CustomerKey', + 'ObjectID' + ); + delete triggeredSend.r__sendClassification_key; + } + // delivery profile + if (triggeredSend.r__deliveryProfile_key) { + // remove it because we cannot resolve it and it should be set by selecting the sendClassification + try { + triggeredSend.deliveryProfileId = cache.searchForField( + 'deliveryProfile', + triggeredSend.r__deliveryProfile_key, + 'key', + 'ObjectID' + ); + delete triggeredSend.r__deliveryProfile_key; + } catch (ex) { + Util.logger.error( + `Could not find the ID for Delivery Profile '${triggeredSend.r__deliveryProfile_key}'. Please note that this can only be resolved if you have at least ONE Send Classification set up on the target BU that uses a Delivery Profile with this key.` + ); + throw ex; + } + } + + // message priority + if (triggeredSend.c__priority) { + triggeredSend.priority = + this.definition.priorityMapping[triggeredSend.c__priority]; + delete triggeredSend.c__priority; + } + + // email + if (triggeredSend.r__asset_key) { + triggeredSend.emailId = cache.searchForField( + 'asset', + triggeredSend.r__asset_key, + 'customerKey', + 'legacyData.legacyId' + ); + delete triggeredSend.r__asset_key; + delete triggeredSend.r__asset_name_readOnly; + } else if (triggeredSend.r__email_name) { + // classic + triggeredSend.emailId = cache.searchForField( + 'email', + triggeredSend.r__email_name, + 'Name', + 'ID' + ); + delete triggeredSend.r__email_name; + } + } + + break; + } + case 'SMSSYNC': { + const configurationArguments = activity.configurationArguments; + if (configurationArguments) { + // mobileMessage + if (configurationArguments.r__mobileMessage_key) { + configurationArguments.messageId = cache.searchForField( + 'mobileMessage', + configurationArguments.r__mobileMessage_key, + 'id', + 'id' + ); + delete configurationArguments.r__mobileMessage_key; + } + // mobileKeyword + if (configurationArguments.r__mobileKeyword_key?.current) { + configurationArguments.keywordId = cache.searchForField( + 'mobileKeyword', + configurationArguments.r__mobileKeyword_key.current, + 'c__codeKeyword', + 'id' + ); + } + if (configurationArguments.r__mobileKeyword_key?.next) { + configurationArguments.nextKeywordId = cache.searchForField( + 'mobileKeyword', + configurationArguments.r__mobileKeyword_key.next, + 'c__codeKeyword', + 'id' + ); + } + delete configurationArguments.r__mobileKeyword_key; + // mobileCode + if (configurationArguments.r__mobileCode_key) { + configurationArguments.codeId = cache.searchForField( + 'mobileCode', + configurationArguments.r__mobileCode_key, + 'code', + 'id' + ); + delete configurationArguments.r__mobileCode_key; + } + // asset-asset: jsonmessage + if (configurationArguments.r__asset_key) { + configurationArguments.assetId = cache.searchForField( + 'asset', + configurationArguments.r__asset_key, + 'customerKey', + 'id' + ); + delete configurationArguments.r__asset_key; + delete configurationArguments.r__asset_name_readOnly; + } + + // applicationExtensionId always equal "00000000-0000-0000-0000-000000000000" + configurationArguments.applicationExtensionId = + '00000000-0000-0000-0000-000000000000'; + } + + break; + } + case 'UPDATECONTACTDATA': { + const contactFields = + activity?.arguments?.activityData?.updateContactFields ?? []; + let tempCachedFields = false; + for (const contactField of contactFields) { + try { + contactField.dataExtensionId = cache.searchForField( + 'dataExtension', + contactField.r__dataExtension_key, + 'CustomerKey', + 'ObjectID' + ); + } catch (ex) { + Util.logger.warn( + ` - ${this.definition.type} '${metadata[this.definition.nameField]}' (${ + metadata[this.definition.keyField] + }) activity-key=${activity.key}: ${ex.message}` + ); + } + try { + if (!cache.getCache().dataExtensionField) { + tempCachedFields = true; + DataExtensionField.buObject = this.buObject; + DataExtensionField.client = this.client; + DataExtensionField.properties = this.properties; + const fields = await DataExtensionField.retrieveFieldsForSingleDe( + contactField.r__dataExtension_key + ); + cache.setMetadata('dataExtensionField', fields); + } + contactField.field = cache.searchForField( + 'dataExtensionField', + `[${contactField.r__dataExtension_key}].[${contactField.r__dataExtensionField_name}]`, + 'CustomerKey', + 'ObjectID' + ); + delete contactField.r__dataExtensionField_name; + delete contactField.r__dataExtension_key; + } catch (ex) { + Util.logger.warn( + ` - ${this.definition.type} '${metadata[this.definition.nameField]}'(${ + metadata[this.definition.keyField] + }) activity - key=${activity.key}: ${ex.message} ` + ); + } + } + if (tempCachedFields) { + // reset dataExtensionField caching to trigger re-caching + cache.clearCache(this.buObject.mid, 'dataExtensionField'); + } + } + } + } + } + + /** + * helper for {@link MetadataType.upsert} + * + * @param {MetadataTypeMap} metadataMap list of metadata + * @param {string} metadataKey key of item we are looking at + * @param {boolean} hasError error flag from previous code + * @param {MetadataTypeItemDiff[]} metadataToUpdate list of items to update + * @param {MetadataTypeItem[]} metadataToCreate list of items to create + * @returns {Promise.<'create'|'update'|'skip'>} action to take + */ + static async createOrUpdate( + metadataMap, + metadataKey, + hasError, + metadataToUpdate, + metadataToCreate + ) { + const action = await super.createOrUpdate( + metadataMap, + metadataKey, + hasError, + metadataToUpdate, + metadataToCreate + ); + if (action === 'update') { + const normalizedKey = File.reverseFilterIllegalFilenames( + metadataMap[metadataKey][this.definition.keyField] + ); + const cachedVersion = cache.getByKey(this.definition.type, normalizedKey); + if (cachedVersion) { + if ( + cachedVersion.status === 'Draft' || + cachedVersion.definitionType !== 'Multistep' + ) { + // we can update journeys either if there is a draft version or if the type is not multistep. transactional and quicksend journeys do not have versions. + // add version to ensure we update the correct one + metadataMap[metadataKey].version = cachedVersion.version; + // update modifiedDate field to bypass API-error "Another user recently modified this journey. Refresh to edit the latest version." + metadataMap[metadataKey].modifiedDate = cachedVersion.modifiedDate; + } else { + // remove last entry from metadataToUpdate again + metadataToUpdate.pop(); + Util.logger.info( + Util.getGrayMsg( + ` - Found ${this.definition.type} ${ + metadataMap[metadataKey][this.definition.nameField] + } (${ + metadataMap[metadataKey][this.definition.keyField] + }) on BU, but it is not in Draft status. Will create new version.` + ) + ); + metadataToCreate.push(metadataMap[metadataKey]); + return 'create'; + } + } + } + return action; + } + + /** + * + * @param {MetadataTypeItem} item single metadata item + * @param {string} [_] parameter not used + * @param {Set.<string>} [findAssetKeys] list of keys that were found referenced via ContentBlockByX; if set, method only gets keys and runs no updates + * @returns {Promise.<MetadataTypeItem>} key of the item that was updated + */ + static async replaceCbReference(item, _, findAssetKeys) { + const parentName = `${this.definition.type} ${item[this.definition.keyField]}`; + let changes = false; + let error; + + // *** type specific logic ** + + // find email activities with triggeredSend configurationArguments + const activities = item.activities.filter((activity) => activity.type === 'EMAILV2'); + if (!activities) { + const ex = new Error('No changes made to the code.'); + // @ts-expect-error custom error object + ex.code = 200; + throw ex; + } + + for (const activity of activities) { + if (activity.arguments) { + try { + activity.arguments.emailSubjectDataBound = ReplaceCbReference.replaceReference( + activity.arguments.emailSubjectDataBound, + parentName, + findAssetKeys + ); + changes = true; + } catch (ex) { + if (ex.code !== 200) { + error = ex; + } + } + } + const triggeredSend = activity.configurationArguments?.triggeredSend; + if (triggeredSend) { + // the following is very similar but not equal to the variables in TriggeredSend.js + if (triggeredSend.bccEmail !== undefined) { + try { + let bccEmail = Array.isArray(triggeredSend.bccEmail) + ? triggeredSend.bccEmail.join(';') + : triggeredSend.bccEmail; + bccEmail = ReplaceCbReference.replaceReference( + bccEmail, + parentName, + findAssetKeys + ); + triggeredSend.bccEmail = bccEmail.split(';').filter((el) => el !== ''); + changes = true; + } catch (ex) { + if (ex.code !== 200) { + error = ex; + } + } + } + if (triggeredSend.ccEmail !== undefined) { + try { + let ccEmail = Array.isArray(triggeredSend.ccEmail) + ? triggeredSend.ccEmail?.join(';') + : triggeredSend.ccEmail; + ccEmail = ReplaceCbReference.replaceReference( + ccEmail, + parentName, + findAssetKeys + ); + triggeredSend.ccEmail = ccEmail.split(';').filter((el) => el !== ''); + changes = true; + } catch (ex) { + if (ex.code !== 200) { + error = ex; + } + } + } + try { + triggeredSend.dynamicEmailSubject = ReplaceCbReference.replaceReference( + triggeredSend.dynamicEmailSubject, + parentName, + findAssetKeys + ); + changes = true; + } catch (ex) { + if (ex.code !== 200) { + error = ex; + } + } + try { + triggeredSend.emailSubject = ReplaceCbReference.replaceReference( + triggeredSend.emailSubject, + parentName, + findAssetKeys + ); + changes = true; + } catch (ex) { + if (ex.code !== 200) { + error = ex; + } + } + try { + triggeredSend.preHeader = ReplaceCbReference.replaceReference( + triggeredSend.preHeader, + parentName, + findAssetKeys + ); + changes = true; + } catch (ex) { + if (ex.code !== 200) { + error = ex; + } + } + try { + triggeredSend.exclusionFilter = ReplaceCbReference.replaceReference( + triggeredSend.exclusionFilter, + parentName, + findAssetKeys + ); + changes = true; + } catch (ex) { + if (ex.code !== 200) { + error = ex; + } + } + } + } + + if (error) { + throw error; + } + + if (!changes) { + const ex = new Error('No changes made to the code.'); + // @ts-expect-error custom error object + ex.code = 200; + throw ex; + } + + // *** finish *** + // replaceReference will throw an error if nothing was updated which will end execution here + // no error means we have a new item to deploy and need to update the item in our retrieve folder + return item; + } + + /** + * Gets executed after deployment of metadata type + * + * @param {MetadataTypeMap} upsertResults metadata mapped by their keyField as returned by update/create + */ + static async postDeployTasks(upsertResults) { + if (!upsertResults || !Object.keys(upsertResults).length) { + // nothing to do. skip here to avoid unnecessary logs / api calls + return; + } + // override the response from update by createdDate from cache (the date from update-response is incorrect) + for (const [key, journey] of Object.entries(upsertResults)) { + const cachedJourney = cache.getByKey(this.definition.type, key); + if (cachedJourney) { + journey.createdDate = cachedJourney.createdDate; + } + } + let postDeployFlags = 0; + if (Util.OPTIONS.publish) { + postDeployFlags++; + } + if (Util.OPTIONS.validate) { + postDeployFlags++; + } + if (postDeployFlags > 1) { + Util.logger.warn( + `Please provide only one of the following options (--publish, --validate). Flags are processed in this order and only the first one found is executed.` + ); + } + + if (Util.OPTIONS.publish) { + Util.logger.info(`Publishing: ${this.definition.type}`); + // pubslih + const idArr = Object.values(upsertResults).map( + (item) => 'id:' + item.id + '/' + item.version + ); + await this.publish(idArr, upsertResults); + } else if (Util.OPTIONS.validate) { + Util.logger.info(`Validating: ${this.definition.type}`); + // pubslih + const idArr = Object.values(upsertResults).map( + (item) => 'id:' + item.id + '/' + item.version + ); + await this.validate(idArr); + } + } + + /** + * a function to publish the journey via API + * + * @param {string[]} keyArr keys or ids of the metadata + * @param {MetadataTypeMap} [upsertResults] metadata mapped by their keyField as returned by update/create; needs to be refreshed after publish + * @returns {Promise.<string[]>} Returns list of updated keys/ids that were published. Success could only be seen with a delay in the UI because the publish-endpoint is async + */ + static async publish(keyArr, upsertResults) { + const resultsTransactional = []; + // works only with objectId + const statusUrls = []; + const executedKeyArr = []; + const refreshTransactionalKeys = []; + const metadataMap = upsertResults + ? { metadata: upsertResults } + : await this.retrieveForCache(); + + const publishedJourneyCounter = { + multiStep: 0, + transactional: 0, + }; + + // does not matter definitionType we run first, but the logs look bad if we dont sort them + const processingOrder = { + Transactional: `Publishing transactional journey…`, + Multistep: `Publishing multi-step journey…`, + }; + for (const definitionType of Object.keys(processingOrder)) { + const spinner = yoctoSpinner({ + text: processingOrder[definitionType], + }); + + for (let key of keyArr) { + let objectId; + let version; + let journey; + if (!key) { + continue; + } + if (key.startsWith('%23')) { + // if the key started with %23 assume an ID was copied from the URL but the user forgot to prefix it with id: + // correct the format + key = 'id:' + key.slice(3); + } + if (key.startsWith('id:')) { + // ! allow selecting journeys by ID because that's what users see in the URL + // remove id + objectId = key.slice(3); + if (objectId.startsWith('%23')) { + // in the journey URL the Id is prefixed with an HTML-encoded "#" which could accidentally be copied by users + // despite the slicing above, this still needs testing here because users might have prefixed the ID with id: but did not know to remove the #23 + objectId = objectId.slice(3); + // correct the format to ensure we show sth readable in the "Downloaded" log + // objectId = objectId; + // update this here to show it in the log + key = 'id:' + objectId; + } + if (objectId.includes('/')) { + version = objectId.split('/')[1]; + // in the journey URL the version is appended after the ID, separated by a forward-slash. Needs to be removed from the ID for caching as we always aim to retrieve the latest version only + objectId = objectId.split('/')[0]; + } else { + // if we didn't find a version we need to cache this from the API after all + if (key.includes('/')) { + // in the journey URL the version is appended after the ID, separated by a forward-slash. Needs to be removed from the key for caching as we always aim to retrieve the latest version only + key = key.split('/')[0]; + } + } + journey = Object.values(metadataMap.metadata).find((el) => el.id === objectId); + if (!journey) { + Util.logger.info( + ` ☇ skipping ${this.definition.type} ${key}: not found on server (1)` + ); + continue; + } + } else { + // key assumed + journey = metadataMap.metadata[key]; + } + + if (journey && journey.definitionType !== definitionType) { + // to allow consistent log output we enforce publishing is sorted by definitionType + if (!processingOrder[journey.definitionType]) { + throw new Error( + `${this.definition.type} type ${journey.definitionType} not supported yet by publish method` + ); + } + continue; + } + + if (!journey) { + Util.logger.info( + ` ☇ skipping ${this.definition.type} ${key}: not found on server (2)` + ); + continue; + } + + if (!version) { + version = journey.version; + } + if (journey.status === 'Published') { + // api would return error code 30000 and ask to open a support case when in fact we simply already have a transactionalEmail created based on this status + if (journey.definitionType === 'Transactional') { + Util.logger.info( + ` ☇ skipping ${this.definition.type} ${ + journey[this.definition.nameField] + } (${journey[this.definition.keyField]}): already published. Queueing for refresh.` + ); + refreshTransactionalKeys.push(journey.key); + } else { + Util.logger.warn( + ` ☇ skipping ${this.definition.type} ${ + journey[this.definition.nameField] + } (${journey[this.definition.keyField]}): already published.` + ); + } + continue; + } else if ( + journey.status === 'Paused' && + journey.definitionType === 'Transactional' + ) { + Util.logger.info( + ` ☇ skipping ${this.definition.type} ${ + journey[this.definition.nameField] + } (${journey[this.definition.keyField]}): currently paused. Queueing for refresh.` + ); + refreshTransactionalKeys.push(journey.key); + continue; + } + + switch (journey.definitionType) { + case 'Transactional': { + resultsTransactional.push( + (async () => { + spinner.start(); + try { + const response = await this.client.rest.post( + `/interaction/v1/interactions/transactional/create`, + { definitionId: journey.id } + ); + if (response.errors?.length) { + throw new Error(JSON.stringify(response)); + } else { + spinner.stop(); + Util.logger.info( + ` - published ${this.definition.type}: ${ + journey[this.definition.nameField] + } (${journey[this.definition.keyField]}) by creating the matching transactionalEmail` + ); + statusUrls.push({ key, statusUrl: response.statusUrl }); + } + spinner.start(); + return journey[this.definition.keyField]; + } catch (ex) { + spinner.stop(); + if ( + ex.response.status === 400 && + ex.response?.data?.errors?.length === 1 && + ex.response?.data?.errors?.[0]?.errorCode === '121500' + ) { + Util.logger.error( + `Failed to publish ${ + journey[this.definition.nameField] + } (${journey[this.definition.keyField]}): Make sure the Event Definition Key, Data Extension and E-Mail are saved to the journey` + ); + } else { + Util.logger.error( + `Failed to publish ${ + journey[this.definition.nameField] + } (${journey[this.definition.keyField]}): ${ex.message}` + ); + if (ex.response?.data?.errors?.length) { + Util.logger.error( + JSON.stringify(ex.response?.data?.errors, null, 2) + ); + } + } + spinner.start(); + } + })() + ); + break; + } + case 'Multistep': { + // SF Event, Api Event Journeys + // ! for SF-triggered journeys this cannot be asynchronous or it will cause a race-condition (see #1627 for details); the requests are accepted but then processed sequentually anyways, eliminating potential speed gains. + // It is unknown if the same would happen for API-event journeys but given that it's the same endpoint, lets not risk it and run this sequentially + let statusUrl; + try { + const response = await this.client.rest.post( + `/interaction/v1/interactions/publishAsync/${journey.id}?versionNumber=${version}`, + {} + ); // payload is empty for this request + if (response.statusUrl && response.statusId) { + Util.logger.info( + ` - ${this.definition.type} queued for publishing: ${journey[this.definition.keyField]}/${version} / ${journey[this.definition.nameField]}` + ); + statusUrl = response.statusUrl; + } else { + throw new Error(response); + } + if (Util.OPTIONS.skipStatusCheck) { + Util.logger.warn( + ` - Skipping status check for publishing journey ${key} due to --skipStatusCheck flag` + ); + } + if (!Util.OPTIONS.skipStatusCheck && statusUrl) { + spinner.start(); + + await Util.sleep(1000); + executedKeyArr.push( + await this._checkPublishStatus( + statusUrl, + journey[this.definition.keyField], + journey[this.definition.nameField], + spinner + ) + ); + publishedJourneyCounter.multiStep++; + } else { + // no guarantees if the journey was actually published + executedKeyArr.push(key); + publishedJourneyCounter.multiStep++; + } + } catch (ex) { + switch (ex.message) { + case 'Cannot publish interaction in Published status.': { + Util.logger.info( + ` - ${this.definition.type} ${key}/${version} is already published.` + ); + + break; + } + case 'Cannot publish interaction in Stopped status.': { + Util.logger.warn( + ` - ${this.definition.type} ${key}/${version} is stopped. Please create a new version and publish that.` + ); + + break; + } + case 'Cannot publish interaction in Paused status.': { + Util.logger.warn( + ` - ${this.definition.type} ${key}/${version} is already published but currently paused. Run 'mcdev resume' instead.` + ); + + break; + } + default: { + Util.logger.error( + `Failed to publish ${this.definition.type} ${key}: ${ex.message}` + ); + } + } + } + break; + } + default: { + throw new Error( + `${this.definition.type} type ${journey.definitionType} not supported yet by publish method` + ); + } + } + } // for loop + + // when all relevant keys have been iterated over per definitionType, ensure we wait for async tasks and update the counter + switch (definitionType) { + case 'Transactional': { + if (resultsTransactional.length) { + const transactionalKeyArr = ( + await Promise.all(resultsTransactional) + ).filter(Boolean); + spinner.stop(); + + // if all publish actions failed, we don't need to re-retrieve anything here + if (transactionalKeyArr.length) { + executedKeyArr.push(...transactionalKeyArr); + publishedJourneyCounter.transactional = transactionalKeyArr.length; + // reset transactionalEmail cache to trigger re-caching it. + cache.clearCache(this.buObject.mid, 'transactionalEmail'); + } + } + break; + } + case 'Multistep': { + // all done; executed synchronously + break; + } + } + } // processing order + + // reload published journeys including their events/transactionalEmails + await this._reRetrieve( + executedKeyArr, + publishedJourneyCounter.transactional, + publishedJourneyCounter.multiStep, + upsertResults + ); + + Util.logger.info( + `Published ${executedKeyArr.filter(Boolean).length} of ${keyArr.length} items` + ); + + if (refreshTransactionalKeys.length) { + // in case we tried to publish a transactional journey that was already published we will instead run a refresh for those + executedKeyArr.push( + ...(await this.refresh(refreshTransactionalKeys, null, upsertResults)) + ); + } + + // good practice to return the published keys in alphabetical order + return executedKeyArr.filter(Boolean).toSorted(); + } + + /** + * + * @param {string[]} executedKeyArr list of journey keys + * @param {number} transactionalCounter how many transactiona-send journeys did we expect to refresh + * @param {number} multiStepCounter how many multi-step journeys did we expect to refresh + * @param {MetadataTypeMap} [upsertResults] metadata mapped by their keyField returned by update/create; needs to be refreshed after publish + * @returns {Promise.<void>} - + */ + static async _reRetrieve( + executedKeyArr, + transactionalCounter, + multiStepCounter, + upsertResults + ) { + if (!executedKeyArr.filter(Boolean).length) { + return; + } + Util.logger.info('Re-retrieving published journeys'); + const retriever = new Retriever(this.properties, this.buObject); + try { + // we need to retrieve the updated journeys and all dependencies + const updatedJourneyRetrieve = await retriever.retrieve( + ['journey'], + executedKeyArr.filter(Boolean) + ); + + /** @type {MetadataTypeItem[]} */ + const updatedJourneys = + updatedJourneyRetrieve?.journey?.length > 1 + ? Object.values( + updatedJourneyRetrieve?.journey.reduce( + (previousValue, currentValue) => + Object.assign(previousValue, currentValue), + {} + ) + ) + : Object.values(updatedJourneyRetrieve?.journey[0]); + + if (updatedJourneys) { + // regardless of upsert vs publish-only mode, we need to retrieve the events/transactionalEmail and their dependencies + const updatedEvents = []; + const updatedTransactionalEmails = []; + for (const journey of updatedJourneys) { + if (upsertResults?.[journey[this.definition.keyField]]) { + // update upsertResults with journeys retrieved here to ensure we save the right thing to disk - if it was provided to the method + upsertResults[journey[this.definition.keyField]] = journey; + } + + // multi-step journeys + updatedEvents.push(journey.triggers?.[0]?.metaData?.r__event_key); + // transactional-send journeys + updatedTransactionalEmails.push( + journey.activities?.[0]?.configurationArguments?.r__transactionalEmail_key + ); + } + /** @type {TypeKeyCombo} */ + const eventTransEmailCombo = {}; + if (updatedEvents.filter(Boolean).length) { + eventTransEmailCombo.event = updatedEvents.filter(Boolean); + } else if (multiStepCounter) { + Util.logger.error(`Could not find events for the published journeys`); + } + if (updatedTransactionalEmails.filter(Boolean).length) { + eventTransEmailCombo.transactionalEmail = + updatedTransactionalEmails.filter(Boolean); + Util.logger.info('Retrieving relevant transactionalEmails'); + } else if (transactionalCounter) { + Util.logger.error( + `Could not find transactional Emails for the published journeys` + ); + } + + const toBeRetrievedTypes = Object.keys(eventTransEmailCombo); + if (toBeRetrievedTypes.length) { + Util.logger.info( + 'Retrieving relevant ' + + toBeRetrievedTypes.map((item) => item + 's').join(', ') + ); + await retriever.retrieve(toBeRetrievedTypes, eventTransEmailCombo); + // TODO find r__automation_key in events and retrieve these automations as well + } + } + } catch (ex) { + Util.logger.errorStack(ex, 'retrieve failed'); + } + } + + /** + * helper for {@link Journey.publish} and {@link Journey.validate} + * + * @param {string} statusUrl URL to check the status of the publish request + * @param {string} key journey-key or id for log messages + * @param {string} name journey-name for log messages + * @param {import('yocto-spinner').Spinner} spinner reference to spinner to allow stopping it when done + * @param {number} [tries] number of tries used to check the status + * @returns {Promise.<string>} key of the item that was published successfully + */ + static async _checkPublishStatus(statusUrl, key, name, spinner, tries = 1) { + const action = statusUrl.includes('/validateStatus') ? 'validating' : 'publishing'; + try { + const response = await this.client.rest.get(statusUrl); + switch (response.status) { + case 'ValidateCompleted': + case 'PublishCompleted': { + spinner.stop(); + const action = statusUrl.includes('/validateStatus') + ? '🔎 validation successful -' + : '🚀 published'; + + Util.logger.info(` - ${action} ${this.definition.type}: ${key} / ${name}`); + this._showPublishStatusDetails(response); + return key; + } + case 'ValidateInProcess': + case 'PublishInProcess': { + Util.logger.debug( + ` - ${action} ${this.definition.type} still in progress: ${key} / ${name}` + ); + if (tries < 50) { + await (tries < 10 ? Util.sleep(2000) : Util.sleep(5000)); + return await this._checkPublishStatus( + statusUrl, + key, + name, + spinner, + tries + 1 + ); + } else { + return; + } + } + case 'Error': { + spinner.stop(); + Util.logger.error( + ` - ${action} ${this.definition.type} failed: ${key} / ${name}` + ); + this._showPublishStatusDetails(response); + return; + } + // No default + } + } catch (ex) { + Util.logger.error(`Failed to check status of ${key}: ${ex.message}`); + } + } + + /** + * helper for {@link Journey._checkPublishStatus} + * + * @param {{status:string, errors:Array, warnings:Array}} response publishStatus response + */ + static _showPublishStatusDetails(response) { + const types = { errors: 'Errors', warnings: 'Warnings' }; + const messages = { errors: [], warnings: [] }; + for (const type in types) { + let counter = 1; + if (response[type] && response[type].length) { + messages[type].push(` ${types[type]}:`); + for (const msg of response[type]) { + messages[type].push( + ` #${counter++}: ${msg.errorDetail.split(' EmailID: ').join('\n EmailID: ').split(' Personalization error: ').join('\n Personalization error: ')}`, + Util.getGrayMsg(` Code: ${msg.errorCode}`) + ); + if (msg.additionalInfo && Object.keys(msg.additionalInfo).length) { + messages[type].push(Util.getGrayMsg(` Additional Info:`)); + for (const key in msg.additionalInfo) { + messages[type].push( + Util.getGrayMsg(` ${key}: ${msg.additionalInfo[key]}`) + ); + } + } + // add spacer line + messages[type].push(''); + } + } + } + for (const msg of messages.errors) { + Util.logger.error(msg); + } + for (const msg of messages.warnings) { + Util.logger.warn(' ' + msg); + } + } + + /** + * a function to validate the journey via API + * + * @param {string[]} keyArr keys or ids of the metadata + * @returns {Promise.<string[]>} Returns list of updated keys/ids that were published. Success could only be seen with a delay in the UI because the publish-endpoint is async + */ + static async validate(keyArr) { + // works only with objectId + const executedKeyArr = []; + const metadataMap = await this.retrieveForCache(); + + for (let key of keyArr) { + let objectId; + let version; + let journey; + if (!key) { + continue; + } + if (key.startsWith('%23')) { + // if the key started with %23 assume an ID was copied from the URL but the user forgot to prefix it with id: + // correct the format + key = 'id:' + key.slice(3); + } + if (key.startsWith('id:')) { + // ! allow selecting journeys by ID because that's what users see in the URL + // remove id + objectId = key.slice(3); + if (objectId.startsWith('%23')) { + // in the journey URL the Id is prefixed with an HTML-encoded "#" which could accidentally be copied by users + // despite the slicing above, this still needs testing here because users might have prefixed the ID with id: but did not know to remove the #23 + objectId = objectId.slice(3); + // correct the format to ensure we show sth readable in the "Downloaded" log + // objectId = objectId; + // update this here to show it in the log + key = 'id:' + objectId; + } + if (objectId.includes('/')) { + version = objectId.split('/')[1]; + // in the journey URL the version is appended after the ID, separated by a forward-slash. Needs to be removed from the ID for caching as we always aim to retrieve the latest version only + objectId = objectId.split('/')[0]; + } else { + // if we didn't find a version we need to cache this from the API after all + if (key.includes('/')) { + // in the journey URL the version is appended after the ID, separated by a forward-slash. Needs to be removed from the key for caching as we always aim to retrieve the latest version only + key = key.split('/')[0]; + } + } + journey = Object.values(metadataMap.metadata).find((el) => el.id === objectId); + if (!journey) { + Util.logger.info( + ` ☇ skipping ${this.definition.type} ${key}: not found on server (1)` + ); + continue; + } + } else { + // key assumed + journey = metadataMap.metadata[key]; + } + + if (!journey) { + Util.logger.info( + ` ☇ skipping ${this.definition.type} ${key}: not found on server (2)` + ); + continue; + } + if (!version) { + version = journey.version; + } + if (journey.status === 'Published') { + // api would return error code 30000 and ask to open a support case when in fact we simply already have a transactionalEmail created based on this status + Util.logger.error( + ` ☇ skipping ${this.definition.type} ${ + journey[this.definition.nameField] + } (${journey[this.definition.keyField]}): already published` + ); + continue; + } + + switch (journey.definitionType) { + case 'Multistep': { + // SF Event, Api Event Journeys + // ! for SF-triggered journeys this cannot be asynchronous or it will cause a race-condition (see #1627 for details); the requests are accepted but then processed sequentually anyways, eliminating potential speed gains. + // It is unknown if the same would happen for API-event journeys but given that it's the same endpoint, lets not risk it and run this sequentially + let statusUrl; + try { + const response = await this.client.rest.post( + `/interaction/v1/interactions/validateAsync/${journey.id}?versionNumber=${version}`, + {} + ); // payload is empty for this request + if (response.statusUrl && response.statusId) { + Util.logger.info( + ` - ${this.definition.type} queued for validating: ${journey[this.definition.keyField]}/${version} / ${journey[this.definition.nameField]}` + ); + statusUrl = response.statusUrl; + } else { + throw new Error(response); + } + const spinner = yoctoSpinner({ + text: `Validating journey…`, + }).start(); + + await Util.sleep(1000); + executedKeyArr.push( + await this._checkPublishStatus( + statusUrl, + journey[this.definition.keyField], + journey[this.definition.nameField], + spinner + ) + ); + } catch (ex) { + switch (ex.message) { + case 'Cannot validate interaction in Published status.': { + Util.logger.info( + ` - ${this.definition.type} ${key}/${version} is already published. Can only validate Draft Journeys` + ); + + break; + } + case 'Cannot validate interaction in Stopped status.': { + Util.logger.warn( + ` - ${this.definition.type} ${key}/${version} is stopped. Can only validate Draft Journeys.` + ); + + break; + } + case 'Cannot validate interaction in Paused status.': { + Util.logger.warn( + ` - ${this.definition.type} ${key}/${version} is already published but currently paused. Can only validate Draft Journeys.` + ); + + break; + } + default: { + Util.logger.error( + `Failed to validate ${this.definition.type} ${key}: ${ex.message}` + ); + } + } + } + break; + } + default: { + Util.logger.info( + Util.getGrayMsg( + ` ☇ skipping ${this.definition.type} ${key}: type ${journey.definitionType} not supported yet by validate method` + ) + ); + continue; + } + } + } // for loop + + Util.logger.info( + `Validated ${executedKeyArr.filter(Boolean).length} of ${keyArr.length} items without errors` + ); + return executedKeyArr.filter(Boolean); + } + + /** + * audit latest or given journey version + * + * @param {string[]} keyArr customerkey of the metadata + * @returns {Promise.<string[]>} Returns list of keys that were paused + */ + static async audit(keyArr) { + let version; + const endpoint = '/interaction/v1/interactions/'; + const auditedKeyArr = []; + const apiLimit = pLimit(20); + const journeyCache = await this.retrieveForCache(); + + const ignoredLogProperties = [ + 'executionMode', + 'id', + 'originalDefinitionId', + 'publishRequestId', + ]; + const preformatedProperties = [ + 'action', + 'description', + 'errors', + 'key', + 'name', + 'publishedVersion', + 'publishStatus', + 'timeStamp', + 'user', + 'versionNumber', + ]; + + await Promise.allSettled( + keyArr.map((key) => + apiLimit(async () => { + [key, version] = key.split('/'); + if (!journeyCache.metadata[key]) { + Util.logger.error( + ` ☇ skipping audit log of ${this.definition.type} ${key}: not found on server` + ); + return; + } + const toBeAuditedVersions = []; + if (version === '*' || !version) { + switch (journeyCache.metadata[key].definitionType) { + case 'Transactional': + case 'Multistep': { + // transactional send journeys technically only have one version, but if you delete them and then create one with the same key their version number goes up and old audit logs are still available + // multi-step journey versions could be retrieved but then we lose info of any versions that might have been deleted. Therefore we add all versions starting with the latest and counting down to 1 + for (let i = journeyCache.metadata[key].version; i > 0; i--) { + toBeAuditedVersions.push(i); + } + } + } + } else { + toBeAuditedVersions.push(version); + } + + Util.logger.info( + ` - Audit log for ${this.definition.type} ${key} / ${journeyCache.metadata[key].name}` + ); + const rateLimitActivities = pLimit(1); + const auditedVersions = ( + await Promise.all( + toBeAuditedVersions.map((version) => + rateLimitActivities(async () => { + try { + const response = await this.client.rest.getBulk( + endpoint + + journeyCache.metadata[key].id + + `/audit/all?versionNumber=${version}` + ); + + Util.logger.info( + ` - Version ${version}:\n - ` + + response.items + .map((log) => { + let msg = + `${log.action} version ${log.versionNumber} - ${Util.getGrayMsg(log.timeStamp.replace('T', ' ').slice(0, 19))}: ${log.user.name}\n` + + (log.publishedVersion + ? ` Published Version: ` + + log.publishedVersion + + '\n' + : '') + + (log.publishStatus + ? ` Publish Status: ` + + log.publishStatus + + '\n' + : '') + + (log.key === key + ? '' + : ` Key: ` + log.key + '\n') + + (log.name === + journeyCache.metadata[key].name + ? '' + : ` Key: ` + log.key + '\n') + + (log.errors + ? ` Errors:\n • ` + + log.errors + .map((error) => + error.ErrorDetail.replaceAll( + /[\r\n]/g, + ' ' + ) + ) + .join('\n • ') + + '\n' + : ''); + for (const key in log) { + if ( + !ignoredLogProperties.includes( + key + ) && + !preformatedProperties.includes(key) + ) { + msg += + ` ${key}: ` + + log[key] + + '\n'; + } + } + return msg; + }) + .join(' - ') + ); + // Util.logger.info(JSON.stringify(auditLog, null, 2)); + return version; + } catch (ex) { + if (journeyCache.metadata[key].version > version) { + Util.logger.error( + ` - Retrieving audit log for ${this.definition.type} ${key} / ${journeyCache.metadata[key].name} - Version ${version} failed: Version was not found. The highest available version seems to be ${journeyCache.metadata[key].version}` + ); + } else { + Util.logger.error( + ` - Retrieving audit log for ${this.definition.type} ${key} / ${journeyCache.metadata[key].name} - Version ${version} failed: ${ex.message}` + ); + } + return; + } + }) + ) + ) + ).filter(Boolean); + if (auditedVersions.length === toBeAuditedVersions.length) { + auditedKeyArr.push(key); + } + }) + ) + ); + + return auditedKeyArr; + } + + /** + * stops latest journey version + * + * @param {string[]} keyArr customerkey of the metadata + * @returns {Promise.<string[]>} Returns list of keys that were paused + */ + static async stop(keyArr) { + let version; + const endpoint = '/interaction/v1/interactions/stop/'; + const stoppedKeyArr = []; + const stopTransactionalKeyArr = []; + const apiLimit = pLimit(20); + const journeyCache = await this.retrieveForCache(); + + const stoppableJourneyStatus = ['Paused', 'Published', 'Unpublished']; // 'Unpublished' is shown as 'Finishing' in the UI + + await Promise.allSettled( + keyArr.map((key) => + apiLimit(async () => { + [key, version] = key.split('/'); + if (journeyCache.metadata[key]) { + switch (journeyCache.metadata[key].definitionType) { + case 'Transactional': { + // transactional send journeys cannot be "stopped" but only "paused" + stopTransactionalKeyArr.push(key); + break; + } + case 'Multistep': { + const toBeStoppedVersions = []; + if (version === '*') { + const responseAllVersions = await this.client.rest.getBulk( + '/interaction/v1/interactions/?id=' + + journeyCache.metadata[key].id + + '&mostRecentVersionOnly=false', + this.definition.restPageSize || 500 + ); + if (responseAllVersions?.items?.length) { + // find all active versions + const allActiveVersions = responseAllVersions.items + .filter((item) => + stoppableJourneyStatus.includes(item.status) + ) + .map((item) => item.version); + if (allActiveVersions.length) { + toBeStoppedVersions.push(...allActiveVersions); + } + } + if (!toBeStoppedVersions.length) { + Util.logger.warn( + ` ☇ skipping stop of ${this.definition.type} ${key}: no active versions found` + ); + } + } else { + if (!version) { + version = journeyCache.metadata[key].version; + Util.logger.info( + Util.getGrayMsg( + ` - ${this.definition.type} ${key}: no version provided. Will try to stop latest version: Version ${version}. To stop all versions, append /* after the key.` + ) + ); + if ( + !stoppableJourneyStatus.includes( + journeyCache.metadata[key].status + ) + ) { + Util.logger.warn( + ` ☇ skipping stop of ${this.definition.type} ${key}: version ${version} has status "${journeyCache.metadata[key].status}" which cannot be stopped. To stop all versions, append /* after the key.` + ); + } + } + toBeStoppedVersions.push(version); + } + const rateLimitActivities = pLimit(2); + const stoppedVersions = ( + await Promise.all( + toBeStoppedVersions.map((version) => + rateLimitActivities(async () => { + try { + await this.client.rest.post( + endpoint + + journeyCache.metadata[key].id + + `?versionNumber=${version}`, + {} + ); + Util.logger.info( + ` - ⛔ stopped ${this.definition.type} ${key} / ${journeyCache.metadata[key].name} - Version ${version}` + ); + return version; + } catch (ex) { + Util.logger.error( + ` - stopping ${this.definition.type} ${key} / ${journeyCache.metadata[key].name} - Version ${version} failed: ${ex.message}` + ); + return; + } + }) + ) + ) + ).filter(Boolean); + if (stoppedVersions.length === toBeStoppedVersions.length) { + stoppedKeyArr.push(key); + } + + break; + } + default: { + Util.logger.error( + ` - Stopping ${this.definition.type} ${key} / ${journeyCache.metadata[key].name} failed: Unsupported definitionType '${journeyCache.metadata[key].definitionType}'` + ); + } + } + } else { + Util.logger.error( + ` ☇ skipping stop of ${this.definition.type} ${key}: not found on server` + ); + } + }) + ) + ); + stoppedKeyArr.push(...(await this.pause(stopTransactionalKeyArr))); + + return stoppedKeyArr; + } + + /** + * pauses selected journey versions + * + * @param {string[]} keyArr customerkey of the metadata + * @param {MetadataTypeMapObj} [journeyCache] metadata cache used by refresh to avoid recaching + * @returns {Promise.<string[]>} Returns list of keys that were paused + */ + static async pause(keyArr, journeyCache) { + let version; + const pausedKeyArr = []; + const apiLimit = pLimit(20); + journeyCache ||= await this.retrieveForCache(); + + await Promise.allSettled( + keyArr.map((key) => + apiLimit(async () => { + [key, version] = key.split('/'); + if (journeyCache.metadata[key]) { + if ( + (!version || journeyCache.metadata[key].version == version) && + journeyCache.metadata[key].status === 'Paused' + ) { + Util.logger.info( + ` ${this.definition.type} ${key} (${journeyCache.metadata[key].name}): already paused` + ); + // still add this key because technically this method is supposed to pause a journey and this journey is paused. mission accomplished. Also, we need that for _refreshItem() to function + pausedKeyArr.push(key); + return; + } else if ( + (!version || journeyCache.metadata[key].version == version) && + journeyCache.metadata[key].status !== 'Published' + ) { + Util.logger.error( + ` - Pausing ${this.definition.type} ${key} / ${journeyCache.metadata[key].name} failed: Cannot pause a journey in status ${journeyCache.metadata[key].status}` + ); + return; + } + switch (journeyCache.metadata[key].definitionType) { + case 'Transactional': { + try { + const response = await this.client.rest.post( + '/interaction/v1/interactions/transactional/pause', + { definitionId: journeyCache.metadata[key].id } + ); + if (response.errors?.length) { + throw new Error(JSON.stringify(response)); + } else { + Util.logger.info( + ` - 🛑 paused ${this.definition.type} ${key} / ${journeyCache.metadata[key].name}` + ); + pausedKeyArr.push(key); + } + } catch (ex) { + Util.logger.error( + ` - Pausing ${this.definition.type} ${key} / ${journeyCache.metadata[key].name} failed: ${ex.message}` + ); + } + break; + } + case 'Multistep': { + version ||= journeyCache.metadata[key].version; + try { + await this.client.rest.post( + '/interaction/v1/interactions/pause/' + + journeyCache.metadata[key].id + + (version === '*' + ? '?allVersions=true' + : `?versionNumber=${version}`), + {} + ); + Util.logger.info( + ` - 🛑 paused ${this.definition.type} ${key}/${version} / ${journeyCache.metadata[key].name}` + ); + pausedKeyArr.push(key); + } catch (ex) { + Util.logger.error( + ` - Pausing ${this.definition.type} ${key} / ${journeyCache.metadata[key].name} failed: ${ex.message}` + ); + } + break; + } + default: { + Util.logger.error( + ` - Pausing ${this.definition.type} ${key} / ${journeyCache.metadata[key].name} failed: Unsupported definitionType '${journeyCache.metadata[key].definitionType}'` + ); + } + } + } else { + Util.logger.error( + ` ☇ skipping pause of ${this.definition.type} ${key}: not found on server` + ); + } + }) + ) + ); + + return pausedKeyArr; + } + /** + * resumes selected journey versions + * + * @param {string[]} keyArr customerkey of the metadata + * @param {MetadataTypeMapObj} [journeyCache] metadata cache used by refresh to avoid recaching + * @returns {Promise.<string[]>} Returns list of keys that were resumed + */ + static async execute(keyArr, journeyCache) { + let version; + const endpoint = '/interaction/v1/interactions/resume/'; + const resumedKeyArr = []; + const apiLimit = pLimit(20); + journeyCache ||= await this.retrieveForCache(); + + await Promise.allSettled( + keyArr.map((key) => + apiLimit(async () => { + [key, version] = key.split('/'); + if (journeyCache.metadata[key]) { + if ( + (!version || journeyCache.metadata[key].version == version) && + journeyCache.metadata[key].status !== 'Paused' + ) { + Util.logger.error( + ` - Resuming ${this.definition.type} ${key} / ${journeyCache.metadata[key].name} failed: Cannot pause a journey in status ${journeyCache.metadata[key].status}` + ); + return; + } + switch (journeyCache.metadata[key].definitionType) { + case 'Transactional': { + try { + const response = await this.client.rest.post( + '/interaction/v1/interactions/transactional/resume', + { definitionId: journeyCache.metadata[key].id } + ); + if (response.errors?.length) { + throw new Error(JSON.stringify(response)); + } else { + Util.logger.info( + ` - ✅ resumed ${this.definition.type} ${key} / ${journeyCache.metadata[key].name}` + ); + resumedKeyArr.push(key); + } + } catch (ex) { + Util.logger.error( + ` - Resuming ${this.definition.type} ${key} / ${journeyCache.metadata[key].name} failed: ${ex.message}` + ); + } + break; + } + case 'Multistep': { + version ||= journeyCache.metadata[key].version; + try { + await this.client.rest.post( + endpoint + + journeyCache.metadata[key].id + + (version === '*' + ? '?allVersions=true' + : `?versionNumber=${version}`), + {} + ); + Util.logger.info( + ` - ✅ resumed ${this.definition.type} ${key}/${version}` + ); + resumedKeyArr.push(key); + } catch (ex) { + Util.logger.error( + ` - Resuming ${this.definition.type} ${key} / ${journeyCache.metadata[key].name} failed: ${ex.message}` + ); + } + break; + } + default: { + Util.logger.error( + ` - Resuming ${this.definition.type} ${key} / ${journeyCache.metadata[key].name} failed: Unsupported definitionType '${journeyCache.metadata[key].definitionType}'` + ); + } + } + } else { + Util.logger.error( + ` ☇ skipping resume of ${this.definition.type} ${key}: not found on server` + ); + } + }) + ) + ); + + return resumedKeyArr; + } + + /** + * TSD-specific refresh method that finds active TSDs and refreshes them + * + * @param {string[]} keyArr metadata keys + * @param {boolean} [_] whether to check if the key is valid + * @param {MetadataTypeMap} [upsertResults] metadata mapped by their keyField as returned by update/create; needs to be refreshed after publish + * @returns {Promise.<string[]>} Returns list of keys that were refreshed + */ + static async refresh(keyArr, _, upsertResults) { + console.time('Time'); // eslint-disable-line no-console + if (!Array.isArray(keyArr) || !keyArr.length) { + Util.logger.error('No refresh-keys provided'); + return []; + // keyArr = await this.getKeysForValidTSDs((await this.findRefreshableItems()).metadata); + // checkKey = false; + } + const journeyCache = upsertResults + ? { metadata: upsertResults, type: this.definition.type } + : await this.retrieveForCache(); + // then executes pause, publish, start on them. + Util.logger.info(`Refreshing ${keyArr.length} ${this.definition.typeName}...`); + Util.logger.debug(`Refreshing keys: ${keyArr.join(', ')}`); + const refreshedKeyArr = []; + const tsKeys = []; + const rateLimit = pLimit(10); + const transactionalJourneyKeys = []; + await Promise.all( + keyArr.map((key) => + rateLimit(async () => { + if (!journeyCache.metadata[key]) { + Util.logger.error( + ` ☇ skipping refresh of ${this.definition.type} ${key}: not found on server` + ); + return; + } + switch (journeyCache.metadata[key].definitionType) { + case 'Transactional': { + if ( + ['Paused', 'Published'].includes(journeyCache.metadata[key]?.status) + ) { + const result = await this._refreshItem(key, journeyCache); + if (result) { + refreshedKeyArr.push(key); + transactionalJourneyKeys.push(key); + } + } else { + Util.logger.error( + ` ☇ skipping refresh of ${this.definition.type} ${key}: Can only refresh journeys with status 'Published'. Found status: ${journeyCache.metadata[key]?.status}` + ); + } + break; + } + case 'Multistep': { + // find all published & paused versions + const responseAllVersions = await this.client.rest.getBulk( + '/interaction/v1/interactions/?id=' + + journeyCache.metadata[key].id + + '&mostRecentVersionOnly=false', + this.definition.restPageSize || 500 + ); + if (responseAllVersions?.items?.length) { + const allActiveVersions = responseAllVersions.items + .filter( + (item) => + item.status === 'Paused' || item.status === 'Published' + ) + .map((item) => item.version); + if (allActiveVersions.length) { + Util.logger.info( + Util.getGrayMsg( + ` - journey ${key} / ${journeyCache.metadata[key].name} Paused/Published version numbers: ` + + allActiveVersions.join(', ') + ) + ); + // get TS keys from email activities of paused/published versions + const rateLimitActivities = pLimit(2); + tsKeys.push( + ...( + await Promise.all( + allActiveVersions.map((version) => + rateLimitActivities(async () => { + const journey = await this.client.rest.get( + '/interaction/v1/interactions/' + + journeyCache.metadata[key]?.id + + '?extras=activities&versionNumber=' + + version + ); + // return all triggeredSends + // ! if somebody changed the key of the triggeredSend then the journey would have wrong info in triggeredSendKey. There is the alternative field triggeredSendId but that would be too costly to use here because we would need to retrieve all TSs to find the correct one. Also, changing TS keys is not a common practice. + return journey.activities + .filter( + (activity) => + activity.type === 'EMAILV2' && + activity.configurationArguments + ?.triggeredSendKey + ) + .map( + (activity) => + activity.configurationArguments + ?.triggeredSendKey + ); + }) + ) + ) + ).flat() + ); + + refreshedKeyArr.push(key); + } else { + Util.logger.error( + ` ☇ skipping refresh of ${this.definition.type} ${key}: no published/paused versions found` + ); + } + } + break; + } + default: { + Util.logger.error( + ` - Refreshing ${this.definition.type} ${key} / ${journeyCache.metadata[key].name} failed: Unsupported definitionType '${journeyCache.metadata[key].definitionType}'` + ); + } + } + }) + ) + ); + + if (tsKeys.length) { + // refresh TriggeredSends + TriggeredSend.buObject = this.buObject; + TriggeredSend.client = this.client; + TriggeredSend.properties = this.properties; + // hard-refresh all triggeredSends even if the TS was paused (inactive) before + await TriggeredSend.refresh(tsKeys, false); + } else { + Util.logger.info(Util.getGrayMsg('No triggeredSends found to refresh')); + } + + // reload refreshed transactional journeys including their transactionalEmails + if (transactionalJourneyKeys.length) { + // reset transactionalEmail cache to trigger re-caching it. + cache.clearCache(this.buObject.mid, 'transactionalEmail'); + + await this._reRetrieve(transactionalJourneyKeys, transactionalJourneyKeys.length, 0); + } + + Util.logger.info( + `Refreshed ${refreshedKeyArr.length} of ${keyArr.length} ${this.definition.type}` + ); + console.timeEnd('Time'); // eslint-disable-line no-console + return refreshedKeyArr; + } + /** + * helper for {@link Journey.refresh} that pauses, publishes and starts a triggered send + * + * @param {string} key external key of triggered send item + * @param {MetadataTypeMapObj} journeyCache metadata cache + * @returns {Promise.<boolean>} true if refresh was successful + */ + static async _refreshItem(key, journeyCache) { + // pause + const pausedKeys = await this.pause([key], journeyCache); + if (!pausedKeys?.length || pausedKeys[0] !== key) { + Util.logger.error(` - failed to pause ${this.definition.typeName}: ${key}`); + return false; + } + + // update cache or else resume (execute) will fail + journeyCache.metadata[key].status = 'Paused'; + + // resume + const resumedKeys = await this.execute([key], journeyCache); + if (!resumedKeys?.length || resumedKeys[0] !== key) { + Util.logger.error(` - failed to resume ${this.definition.typeName}: ${key}`); + return false; + } + + return true; + } +} + +// Assign definition to static attributes +import MetadataTypeDefinitions from '../MetadataTypeDefinitions.js'; +Journey.definition = MetadataTypeDefinitions.journey; + +export default Journey; diff --git a/lib/metadataTypes/List.js b/lib/metadataTypes/List.js index 7a75d4d40..71febde81 100644 --- a/lib/metadataTypes/List.js +++ b/lib/metadataTypes/List.js @@ -1,66 +1,225 @@ 'use strict'; -const MetadataType = require('./MetadataType'); -const Util = require('../util/util'); +import MetadataType from './MetadataType.js'; +import Folder from './Folder.js'; +import { Util } from '../util/util.js'; +import cache from '../util/cache.js'; +import auth from '../util/auth.js'; + +/** + * @typedef {import('../../types/mcdev.d.js').BuObject} BuObject + * @typedef {import('../../types/mcdev.d.js').CodeExtract} CodeExtract + * @typedef {import('../../types/mcdev.d.js').CodeExtractItem} CodeExtractItem + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItem} MetadataTypeItem + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItemDiff} MetadataTypeItemDiff + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItemObj} MetadataTypeItemObj + * @typedef {import('../../types/mcdev.d.js').MetadataTypeMap} MetadataTypeMap + * @typedef {import('../../types/mcdev.d.js').MetadataTypeMapObj} MetadataTypeMapObj + * @typedef {import('../../types/mcdev.d.js').SoapRequestParams} SoapRequestParams + * @typedef {import('../../types/mcdev.d.js').TemplateMap} TemplateMap + */ /** * List MetadataType + * * @augments MetadataType */ class List extends MetadataType { /** * Retrieves Metadata of Lists - * @param {String} retrieveDir Directory where retrieved metadata directory will be saved - * @returns {Promise} Promise + * + * @param {string} [retrieveDir] Directory where retrieved metadata directory will be saved + * @param {void | string[]} [_] unused parameter + * @param {void | string[]} [__] unused parameter + * @param {string} [key] customer key of single item to retrieve + * @returns {Promise.<MetadataTypeMapObj>} Promise */ - static retrieve(retrieveDir) { - return super.retrieveSOAPgeneric(retrieveDir); + static async retrieve(retrieveDir, _, __, key) { + /** @type {SoapRequestParams} */ + let requestParams = null; + if (key) { + requestParams = { + filter: { + leftOperand: { + leftOperand: 'CustomerKey', + operator: 'equals', + rightOperand: key, + }, + operator: 'OR', + rightOperand: { + // deviating from standard here by allowing to search without the rather weird key which includes the folder name! + leftOperand: 'ListName', + operator: 'equals', + rightOperand: key, + }, + }, + }; + } + const results = await super.retrieveSOAP(retrieveDir, requestParams, key); + return await this._retrieveParentAllSubs(results); } + /** * Gets metadata cache with limited fields and does not store value to disk - * @returns {Promise<Object>} Promise of metadata + * + * @returns {Promise.<MetadataTypeMapObj>} Promise of metadata */ static async retrieveForCache() { - const results = await this.retrieve(null); + const results = await this.retrieve(); + const subTypeArr = [ + 'list', + 'mysubs', + 'suppression_list', + 'publication', + 'contextual_suppression_list', + ]; + Util.logger.debug('folders not cached but required for list'); + Util.logger.info(' - Caching dependent Metadata: folder'); + Util.logSubtypes(subTypeArr); + Folder.client = this.client; + Folder.buObject = this.buObject; + Folder.properties = this.properties; + const result = await Folder.retrieveForCache(null, subTypeArr); + if (cache.getCache()?.folder) { + cache.mergeMetadata('folder', result.metadata); + } else { + cache.setMetadata('folder', result.metadata); + } for (const metadataEntry in results.metadata) { this.parseMetadata(results.metadata[metadataEntry], true); } return results; } + /** + * helper for {@link retrieveForCache} and {@link retrieve} + * + * @private + * @param {MetadataTypeMapObj} results metadata from retrieve for current BU + * @returns {Promise.<MetadataTypeMapObj>} Promise + */ + static async _retrieveParentAllSubs(results) { + if (this.buObject.eid !== this.buObject.mid) { + // for caching, we want to get the All Subscriber List from the Parent Account + Util.logger.debug(' - Checking MasterUnsubscribeBehavior for current BU'); + /** @type {BuObject} */ + const buObjectParentBu = { + eid: this.properties.credentials[this.buObject.credential].eid, + mid: this.properties.credentials[this.buObject.credential].eid, + businessUnit: Util.parentBuName, + credential: this.buObject.credential, + }; + const clientBackup = this.client; + const buObjectBackup = this.buObject; + try { + this.client = auth.getSDK(buObjectParentBu); + } catch (ex) { + Util.logger.error(ex.message); + return; + } + this.buObject = buObjectParentBu; + const buResult = await this.client.soap.retrieve( + 'BusinessUnit', + ['MasterUnsubscribeBehavior'], + { + QueryAllAccounts: true, + filter: { + leftOperand: 'ID', + operator: 'equals', + rightOperand: this.properties.credentials[this.buObject.credential].eid, + }, + } + ); + const masterUnsubscribeBehavior = buResult.Results[0]?.MasterUnsubscribeBehavior; + if (masterUnsubscribeBehavior === 'ENTIRE_ENTERPRISE') { + Util.logger.debug(` - BU uses ParentBU's All Subscriber List`); + Util.logger.info( + ' - Caching dependent Metadata: All Subscriber list (on _ParentBU_)' + ); + // do not use retrieveForCache here because (a) it does not support key-filtering and (b) it would cache folders on top which we do not need for the global all subscriber list + const metadataParentBu = await this.retrieve(null, null, null, 'All Subscribers'); + // manually set folder path of parent's All Subscriber List to avoid retrieving folders + for (const key of Object.keys(metadataParentBu.metadata)) { + metadataParentBu.metadata[key].r__folder_Path = 'my subscribers'; + } + // find & delete local All Subscriber list to avoid referencing the wrong one + for (const key of Object.keys(results.metadata)) { + if (results.metadata[key].ListName === 'All Subscribers') { + delete results.metadata[key]; + break; + } + } + + // revert to current default + this.client = clientBackup; + this.buObject = buObjectBackup; + + // make sure to overwrite parent bu DEs with local ones + return { + metadata: { ...metadataParentBu.metadata, ...results.metadata }, + type: results.type, + }; + } else if (masterUnsubscribeBehavior === 'BUSINESS_UNIT_ONLY') { + // revert client to current default + this.client = clientBackup; + + Util.logger.debug(' - BU uses own All Subscriber List'); + } + } + return results; + } + + /** + * Delete a metadata item from the specified business unit + * + * @param {string} customerKey Identifier of data extension + * @returns {Promise.<boolean>} deletion success status + */ + static deleteByKey(customerKey) { + return super.deleteByKeySOAP(customerKey); + } + /** * manages post retrieve steps - * @param {Object} list a single list - * @returns {Object[]} metadata + * + * @param {MetadataTypeItem} list a single list + * @returns {MetadataTypeItem} metadata */ static postRetrieveTasks(list) { return this.parseMetadata(list); } + /** * parses retrieved Metadata before saving - * @param {Object} metadata a single list definition - * @param {Boolean} [parseForCache] if set to true, the Category ID is kept - * @returns {Array} Array with one metadata object and one sql string + * + * @param {MetadataTypeItem} metadata a single list definition + * @param {boolean} [parseForCache] if set to true, the Category ID is kept + * @returns {MetadataTypeItem} Array with one metadata object and one sql string */ static parseMetadata(metadata, parseForCache) { - try { - metadata.r__folder_Path = Util.getFromCache( - this.cache, - 'folder', - metadata.Category, - 'ID', - 'Path' - ); - if (!parseForCache) { - delete metadata.Category; + if (!metadata.r__folder_Path) { + // if we cached all subs from parent bu, we don't need to parse the folder path again here + try { + metadata.r__folder_Path = cache.searchForField( + 'folder', + metadata.Category, + 'ID', + 'Path' + ); + if (!parseForCache) { + delete metadata.Category; + } + } catch (ex) { + Util.logger.warn( + ` - List ${metadata.ID}: '${metadata.CustomerKey}': ${ex.message}` + ); } - return metadata; - } catch (ex) { - Util.logger.warn(`List ${metadata.ID}: '${metadata.CustomerKey}': ${ex.message}`); } + return metadata; } } // Assign definition to static attributes -List.definition = require('../MetadataTypeDefinitions').list; +import MetadataTypeDefinitions from '../MetadataTypeDefinitions.js'; +List.definition = MetadataTypeDefinitions.list; -module.exports = List; +export default List; diff --git a/lib/metadataTypes/MetadataType.js b/lib/metadataTypes/MetadataType.js index 926ec7f66..ff8c65d7c 100644 --- a/lib/metadataTypes/MetadataType.js +++ b/lib/metadataTypes/MetadataType.js @@ -7,33 +7,45 @@ * in the generic version of the method */ +import { Util } from '../util/util.js'; +import File from '../util/file.js'; +import cache from '../util/cache.js'; +import deepEqual from 'deep-equal'; +import pLimit from 'p-limit'; +import Mustache from 'mustache'; +import MetadataTypeInfo from '../MetadataTypeInfo.js'; +import validationsRules from '../util/validations.js'; + /** - * @typedef {Object.<string, any>} MetadataTypeItem - * - * @typedef {Object} CodeExtractItem - * @property {MetadataTypeItem} json metadata of one item w/o code - * @property {CodeExtract[]} codeArr list of code snippets in this item - * @property {string[]} subFolder mostly set to null, otherwise list of subfolders - * -* @typedef {Object} CodeExtract - * @property {string[]} subFolder mostly set to null, otherwise subfolders path split into elements - * @property {string} fileName name of file w/o extension - * @property {string} fileExt file extension - * @property {string} content file content - * @property {'base64'} [encoding] optional for binary files + * @typedef {import('../../types/mcdev.d.js').BuObject} BuObject + * @typedef {import('../../types/mcdev.d.js').CodeExtract} CodeExtract + * @typedef {import('../../types/mcdev.d.js').CodeExtractItem} CodeExtractItem + * @typedef {import('../../types/mcdev.d.js').Mcdevrc} Mcdevrc + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItem} MetadataTypeItem + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItemDiff} MetadataTypeItemDiff + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItemObj} MetadataTypeItemObj + * @typedef {import('../../types/mcdev.d.js').MetadataTypeMap} MetadataTypeMap + * @typedef {import('../../types/mcdev.d.js').MetadataTypeMapObj} MetadataTypeMapObj + * @typedef {import('../../types/mcdev.d.js').MultiMetadataTypeList} MultiMetadataTypeList + * @typedef {import('../../types/mcdev.d.js').SoapRequestParams} SoapRequestParams + * @typedef {import('../../types/mcdev.d.js').TemplateMap} TemplateMap + * @typedef {import('../../types/mcdev.d.js').TypeKeyCombo} TypeKeyCombo + * @typedef {import('sfmc-sdk').default} SDK + * @typedef {import('../../types/mcdev.d.js').SDKError} SDKError + * @typedef {import('../../types/mcdev.d.js').SOAPError} SOAPError + * @typedef {import('../../types/mcdev.d.js').RestError} RestError + * @typedef {import('../../types/mcdev.d.js').ContentBlockConversionTypes} ContentBlockConversionTypes + */ +/** + * ensure that Mustache does not escape any characters * - * @typedef {Object.<string, MetadataTypeItem>} MetadataTypeMap - * - * @typedef {Object.<string, MetadataTypeMap>} MultiMetadataTypeMap + * @param {string} text - + * @returns {string} text */ - -const Util = require('../util/util'); -const File = require('../util/file'); - -// @ts-ignore -const Promise = require('bluebird'); -const Mustache = require('mustache'); +Mustache.escape = function (text) { + return text; +}; /** * MetadataType class that gets extended by their specific metadata type class. @@ -41,57 +53,50 @@ const Mustache = require('mustache'); * */ class MetadataType { - /** - * Instantiates a metadata constructor to avoid passing variables. - * - * @param {Util.ET_Client} client client for sfmc fuelsdk - * @param {string} businessUnit Name of business unit (corresponding to their keys in 'properties.json' file). Used to access correct directories - * @param {Object} cache metadata cache - * @param {Object} properties mcdev config - * @param {string} [subType] limit retrieve to specific subType - */ - constructor(client, businessUnit, cache, properties, subType) { - this.client = client; - this.businessUnit = businessUnit; - this.cache = cache; - this.properties = properties; - this.subType = subType; - } - /** * Returns file contents mapped to their filename without '.json' ending - * @param {string} dir directory that contains '.json' files to be read - * @param {boolean} [listBadKeys=false] do not print errors, used for badKeys() - * @returns {Object} fileName => fileContent map + * + * @param {string} dir directory with json files, e.g. /retrieve/cred/bu/event, /deploy/cred/bu/event, /template/event + * @param {boolean} [listBadKeys] do not print errors, used for badKeys() + * @param {string[]} [selectedSubType] asset, message, ... + * @returns {Promise.<MetadataTypeMap>} fileName => fileContent map */ - static getJsonFromFS(dir, listBadKeys) { + static async getJsonFromFS(dir, listBadKeys, selectedSubType) { const fileName2FileContent = {}; try { - const files = File.readdirSync(dir); - files.forEach((fileName) => { + const files = await File.readdir(dir); + for (const fileName of files) { try { if (fileName.endsWith('.json')) { - const fileContent = File.readJSONFile(dir, fileName, true, false); - const fileNameWithoutEnding = File.reverseFilterIllegalFilenames( - fileName.split(/\.(\w|-)+-meta.json/)[0] - ); - // We always store the filename using the External Key (CustomerKey or key) to avoid duplicate names. - // to ensure any changes are done to both the filename and external key do a check here - if ( - fileContent[this.definition.keyField] === fileNameWithoutEnding || - listBadKeys - ) { - fileName2FileContent[fileNameWithoutEnding] = fileContent; + const fileContent = await File.readJSONFile(dir, fileName, false); + // ! convert numbers to string to allow numeric keys to be checked properly + const key = Number.isInteger(fileContent[this.definition.keyField]) + ? fileContent[this.definition.keyField].toString() + : fileContent[this.definition.keyField]; + + // ensure filename includes extended metadata extension + const regex = new RegExp(/\.(\w|-)+-meta.json/); + const errorDir = dir.split('\\').join('/'); + if (regex.test(fileName)) { + const fileNameWithoutEnding = File.reverseFilterIllegalFilenames( + fileName.split(regex)[0] + ); + // We always store the filename using the External Key (CustomerKey or key) to avoid duplicate names. + // to ensure any changes are done to both the filename and external key do a check here + if (key === fileNameWithoutEnding || listBadKeys) { + fileName2FileContent[fileNameWithoutEnding] = fileContent; + } else { + Util.logger.error( + ` ☇ skipping ${this.definition.type} ${key}: Name of the metadata file and the JSON-key (${this.definition.keyField}) must match. Expected: ${key}.${this.definition.type}-meta.json. Actual: ` + + Util.getGrayMsg(`${errorDir}/`) + + fileName + ); + } } else { - Util.metadataLogger( - 'error', - this.definition.type, - 'getJsonFromFS', - 'Name of the Metadata and the External Identifier must match', - JSON.stringify({ - Filename: fileNameWithoutEnding, - ExternalIdentifier: fileContent[this.definition.keyField], - }) + Util.logger.error( + ` ☇ skipping ${this.definition.type} ${key}: Name of the metadata file must end on the extended metadata suffix. Expected: ${key}.${this.definition.type}-meta.json. Actual: ` + + Util.getGrayMsg(`${errorDir}/`) + + fileName ); } } @@ -99,26 +104,29 @@ class MetadataType { // by catching this in the loop we gracefully handle the issue and move on to the next file Util.metadataLogger('debug', this.definition.type, 'getJsonFromFS', ex); } - }); + } } catch (ex) { // this will catch issues with readdirSync Util.metadataLogger('debug', this.definition.type, 'getJsonFromFS', ex); - throw new Error(ex); + throw ex; } return fileName2FileContent; } /** * Returns fieldnames of Metadata Type. 'this.definition.fields' variable only set in child classes. + * * @param {string[]} [additionalFields] Returns specified fields even if their retrieve definition is not set to true + * @param {boolean} [isCaching] if true, then check if field should be skipped for caching * @returns {string[]} Fieldnames */ - static getFieldNamesToRetrieve(additionalFields) { + static getFieldNamesToRetrieve(additionalFields, isCaching) { const fieldNames = []; for (const fieldName in this.definition.fields) { if ( - (additionalFields && additionalFields.includes(fieldName)) || - this.definition.fields[fieldName].retrieving + additionalFields?.includes(fieldName) || + (this.definition.fields[fieldName].retrieving && + !(isCaching && this.definition.fields[fieldName].skipCache)) ) { fieldNames.push(fieldName); } @@ -132,564 +140,1360 @@ class MetadataType { /** * Deploys metadata - * @param {MetadataTypeMap} metadata metadata mapped by their keyField - * @param {string} deployDir directory where deploy metadata are saved - * @param {string} retrieveDir directory where metadata after deploy should be saved - * @param {Util.BuObject} buObject properties for auth - * @returns {Promise<Object>} Promise of keyField => metadata map - */ - static async deploy(metadata, deployDir, retrieveDir, buObject) { - const upsertResults = await this.upsert(metadata, deployDir, buObject); - await this.postDeployTasks(upsertResults, metadata); - const savedMetadata = await this.saveResults(upsertResults, retrieveDir, null); - if (this.properties.metaDataTypes.documentOnRetrieve.includes(this.definition.type)) { - // * do not await here as this might take a while and has no impact on the deploy - this.document(buObject, savedMetadata, true); + * + * @param {MetadataTypeMap} metadataMap metadata mapped by their keyField + * @param {string} deployDir directory where deploy metadata are saved, ending on cred/bu + * @param {string} retrieveDir directory where metadata after deploy should be saved, ending on cred/bu + * @returns {Promise.<MetadataTypeMap>} Promise of keyField => metadata map + */ + static async deploy(metadataMap, deployDir, retrieveDir) { + const upsertedMetadataMap = await this.upsert(metadataMap, deployDir); + if (retrieveDir) { + // deploy can be run with retrieveDir set to null for deploying auto-created foldes - these should not be saved to the retrieve-folder while everything else should + const savedMetadataMap = await this.saveResults(upsertedMetadataMap, retrieveDir, null); + if ( + this.properties.metaDataTypes.documentOnRetrieve.includes(this.definition.type) && + !this.definition.documentInOneFile + ) { + // * do not await here as this might take a while and has no impact on the deploy + // * this should only be run if documentation is on a per metadata record level. Types that document an overview into a single file will need a full retrieve to work instead + await this.document(savedMetadataMap, true); + } } - return upsertResults; + return upsertedMetadataMap; } /** * Gets executed after deployment of metadata type - * @param {MetadataTypeMap} metadata metadata mapped by their keyField + * + * @param {MetadataTypeMap} upsertResults metadata mapped by their keyField as returned by update/create * @param {MetadataTypeMap} originalMetadata metadata to be updated (contains additioanl fields) - * @returns {void} + * @param {{created: number, updated: number}} createdUpdated counter representing successful creates/updates + * @returns {Promise.<void>} - + */ + static async postDeployTasks(upsertResults, originalMetadata, createdUpdated) {} + + /** + * Gets executed before deleting a list of keys for the current type + * + * @param {string} keyArr metadata keys + * @returns {Promise.<void>} - + */ + static async preDeleteTasks(keyArr) {} + + /** + * helper for {@link MetadataType.createREST} + * + * @param {MetadataTypeItem} metadataEntry a single metadata Entry + * @param {object} apiResponse varies depending on the API call + * @param {MetadataTypeItem} metadataEntryWithAllFields like metadataEntry but before non-creatable fields were stripped + * @returns {Promise.<object>} apiResponse, potentially modified + */ + static async postCreateTasks(metadataEntry, apiResponse, metadataEntryWithAllFields) { + return apiResponse; + } + + /** + * helper for {@link MetadataType.updateREST} and {@link MetadataType.updateSOAP} + * + * @param {MetadataTypeItem} metadataEntry a single metadata Entry + * @param {object} apiResponse varies depending on the API call + * @param {MetadataTypeItem} metadataEntryWithAllFields like metadataEntry but before non-creatable fields were stripped + * @returns {Promise.<object>} apiResponse, potentially modified + */ + static postUpdateTasks(metadataEntry, apiResponse, metadataEntryWithAllFields) { + return apiResponse; + } + + /** + * helper for {@link MetadataType.createREST} when legacy API endpoints as these do not return the created item but only their new id + * + * @param {MetadataTypeItem} metadataEntry a single metadata Entry + * @param {object} apiResponse varies depending on the API call + * @returns {Promise.<void>} - */ - static postDeployTasks(metadata, originalMetadata) {} + static async postDeployTasks_legacyApi(metadataEntry, apiResponse) { + if (!apiResponse?.[this.definition.idField] && !metadataEntry?.[this.definition.idField]) { + return; + } + const id = + apiResponse?.[this.definition.idField] || metadataEntry?.[this.definition.idField]; + // re-retrieve created items because the API does not return any info for them except the new id (api key) + try { + const { metadata } = await this.retrieveForCache(null, null, 'id:' + id); + const item = Object.values(metadata)[0]; + // ensure the "created item" cli log entry has the new auto-generated value + metadataEntry[this.definition.keyField] = item[this.definition.keyField]; + // ensure postRetrieveTasks has the complete object in "apiResponse" + Object.assign(apiResponse, item); + // postRetrieveTasks will be run automatically on this via super.saveResult + } catch (ex) { + throw new Error( + `Could not get details for new ${this.definition.type} ${id} from server (${ex.message})`, + { cause: ex } + ); + } + } /** * Gets executed after retreive of metadata type + * * @param {MetadataTypeItem} metadata a single item * @param {string} targetDir folder where retrieves should be saved * @param {boolean} [isTemplating] signals that we are retrieving templates * @returns {MetadataTypeItem} cloned metadata */ static postRetrieveTasks(metadata, targetDir, isTemplating) { - return JSON.parse(JSON.stringify(metadata)); + return structuredClone(metadata); } + /** - * used to synchronize name and external key during retrieveAsTemplate + * generic script that retrieves the folder path from cache and updates the given metadata with it after retrieve + * * @param {MetadataTypeItem} metadata a single item - * @param {string} [warningMsg] optional msg to show the user - * @returns {void} */ - static overrideKeyWithName(metadata, warningMsg) { - if ( - this.definition.nameField && - this.definition.keyField && - metadata[this.definition.nameField] !== metadata[this.definition.keyField] - ) { + static setFolderPath(metadata) { + if (!this.definition.folderIdField) { + return; + } + try { + metadata.r__folder_Path = cache.searchForField( + 'folder', + metadata[this.definition.folderIdField], + 'ID', + 'Path' + ); + delete metadata[this.definition.folderIdField]; + } catch (ex) { Util.logger.warn( - `Reset external key of ${this.definition.type} ${ - metadata[this.definition.nameField] - } to its name (${metadata[this.definition.keyField]})` + Util.getMsgPrefix(this.definition, metadata) + + `: Could not find folder (${ex.message})` ); - if (warningMsg) { - Util.logger.warn(warningMsg); - } - // do this after printing to cli or we lost the info - metadata[this.definition.keyField] = metadata[this.definition.nameField]; } } + + /** + * generic script that retrieves the folder ID from cache and updates the given metadata with it before deploy + * + * @param {MetadataTypeItem} metadata a single item + */ + static setFolderId(metadata) { + if (!this.definition.folderIdField) { + return; + } + if (!metadata.r__folder_Path) { + throw new Error( + `Dependent folder could not be found because r__folder_Path is not set` + ); + } + metadata[this.definition.folderIdField] = cache.getFolderId(metadata.r__folder_Path); + delete metadata.r__folder_Path; + } + /** * Gets metadata from Marketing Cloud + * * @param {string} retrieveDir Directory where retrieved metadata directory will be saved * @param {string[]} [additionalFields] Returns specified fields even if their retrieve definition is not set to true - * @param {Util.BuObject} buObject properties for auth - * @param {string} [subType] optionally limit to a single subtype - * @returns {Promise<{metadata:MetadataTypeMap,type:string}>} metadata + * @param {string[]} [subTypeArr] optionally limit to a single subtype + * @param {string} [key] customer key of single item to retrieve + * @returns {Promise.<MetadataTypeMapObj>} metadata */ - static retrieve(retrieveDir, additionalFields, buObject, subType) { - Util.metadataLogger('error', this.definition.type, 'retrieve', `Not Supported`); - const metadata = {}; - return { metadata: null, type: this.definition.type }; + static async retrieve(retrieveDir, additionalFields, subTypeArr, key) { + Util.logNotSupported(this.definition, 'retrieve'); + return { metadata: {}, type: this.definition.type }; } + /** * Gets metadata from Marketing Cloud + * * @param {string[]} [additionalFields] Returns specified fields even if their retrieve definition is not set to true - * @param {Util.BuObject} buObject properties for auth - * @param {string} [subType] optionally limit to a single subtype - * @returns {Promise<{metadata:MetadataTypeMap,type:string}>} metadata + * @param {string[]} [subTypeArr] optionally limit to a single subtype + * @returns {Promise.<MetadataTypeMapObj>} metadata */ - static retrieveChangelog(additionalFields, buObject, subType) { - return this.retrieve(null, additionalFields, buObject, subType); + static retrieveChangelog(additionalFields, subTypeArr) { + return this.retrieveForCache(additionalFields, subTypeArr); } /** * Gets metadata cache with limited fields and does not store value to disk - * @param {Util.BuObject} buObject properties for auth - * @param {string} [subType] optionally limit to a single subtype - * @returns {Promise<{metadata:MetadataTypeMap,type:string}>} metadata + * + * @param {string[]} [additionalFields] Returns specified fields even if their retrieve definition is not set to true + * @param {string[]} [subTypeArr] optionally limit to a single subtype + * @param {string} [key] customer key of single item to retrieve + * @returns {Promise.<MetadataTypeMapObj>} metadata */ - static async retrieveForCache(buObject, subType) { - return this.retrieve(null, null, buObject, subType); + static async retrieveForCache(additionalFields, subTypeArr, key) { + return this.retrieve(null, additionalFields, subTypeArr, key); } + /** * Gets metadata cache with limited fields and does not store value to disk + * + * @deprecated Use `retrieve` followed by `build` instead. `retrieveAsTemplate` will be removed in a future version. * @param {string} templateDir Directory where retrieved metadata directory will be saved * @param {string} name name of the metadata file - * @param {Util.TemplateMap} templateVariables variables to be replaced in the metadata + * @param {TemplateMap} templateVariables variables to be replaced in the metadata * @param {string} [subType] optionally limit to a single subtype - * @returns {Promise<{metadata:MetadataTypeMap,type:string}>} metadata + * @returns {Promise.<MetadataTypeItemObj>} metadata */ - static retrieveAsTemplate(templateDir, name, templateVariables, subType) { - Util.logger.error('retrieveAsTemplate is not supported yet for ' + this.definition.type); - Util.metadataLogger( - 'debug', - this.definition.type, - 'retrieveAsTemplate', - `(${templateDir}, ${name}, ${templateVariables}) no templating function` - ); + static async retrieveAsTemplate(templateDir, name, templateVariables, subType) { + Util.logNotSupported(this.definition, 'retrieveAsTemplate'); + Util.logDeprecated('retrieveAsTemplate', `'retrieve' followed by 'build'`); return { metadata: null, type: this.definition.type }; } + /** + * Retrieve a specific Script by Name + * + * @param {string} templateDir Directory where retrieved metadata directory will be saved + * @param {string} uri rest endpoint for GET + * @param {TemplateMap} templateVariables variables to be replaced in the metadata + * @param {string} name name (not key) of the metadata item + * @returns {Promise.<{metadata: MetadataTypeItem, type: string}>} Promise + */ + static async retrieveTemplateREST(templateDir, uri, templateVariables, name) { + return this.retrieveREST(templateDir, uri, templateVariables, name); + } + + /** + * Gets metadata cache with limited fields and does not store value to disk + * + * @param {string} retrieveDir Directory where retrieved metadata directory will be saved + * @param {string} templateDir (List of) Directory where built definitions will be saved + * @param {string} key name of the metadata file + * @param {TemplateMap} templateVariables variables to be replaced in the metadata + * @returns {Promise.<MetadataTypeItemObj>} single metadata + */ + static async buildTemplate(retrieveDir, templateDir, key, templateVariables) { + // retrieve metadata template + let metadataStr; + const typeDirArr = [this.definition.type]; + const subType = await this.findSubType(retrieveDir, key); + if (subType) { + typeDirArr.push(subType); + } + const suffix = subType ? `-${subType}-meta` : '-meta'; + const fileName = key + '.' + this.definition.type + suffix; + try { + // ! do not load via readJSONFile to ensure we get a string, not parsed JSON + // templated files might contain illegal json before the conversion back to the file that shall be saved + metadataStr = await File.readFilteredFilename( + [retrieveDir, ...typeDirArr], + fileName, + 'json' + ); + if (!metadataStr) { + throw new Error('File not found'); + } + } catch (ex) { + try { + metadataStr = await this.readSecondaryFolder( + retrieveDir, + typeDirArr, + key, + fileName, + ex + ); + } catch { + // only happening for types that use readSecondaryFolder (e.g. asset) + // if we still have no metadataStr then we have to skip this metadata for all types and hence handle it outside of this catch + } + if (!metadataStr) { + Util.logger.warn( + Util.getGrayMsg(` ☇ skipped ${this.definition.type} ${key}: not found`) + ); + return; + } + } + + if (this.definition.stringifyFieldsBeforeTemplate) { + // numeric fields are returned as numbers by the SDK/API. If we try to replace them in buildTemplate it would break the JSON format - but not if we stringify them first because then the {{{var}}} is in quotes + const metadataTemp = JSON.parse(metadataStr); + for (const field of this.definition.stringifyFieldsBeforeTemplate) { + if (metadataTemp[field]) { + if (Array.isArray(metadataTemp[field])) { + for (let i = 0; i < metadataTemp[field].length; i++) { + metadataTemp[field][i] = metadataTemp[field][i].toString(); + } + } else if ('object' === typeof metadataTemp[field]) { + for (const subField in metadataTemp[field]) { + metadataTemp[field][subField] = + metadataTemp[field][subField].toString(); + } + } else { + metadataTemp[field] = metadataTemp[field].toString(); + } + } + } + metadataStr = JSON.stringify(metadataTemp); + } + // handle extracted code + // templating to extracted content is applied inside of buildTemplateForNested() + await this.buildTemplateForNested( + retrieveDir, + templateDir, + JSON.parse(metadataStr), + templateVariables, + key + ); + + const metadata = JSON.parse(Util.replaceByObject(metadataStr, templateVariables)); + this.keepTemplateFields(metadata); + + try { + // write to file + await File.writeJSONToFile([templateDir, ...typeDirArr], fileName, metadata); + Util.logger.info( + ` - templated ${this.definition.type}: ${key} (${ + metadata[this.definition.nameField] + })` + ); + + return { metadata: metadata, type: this.definition.type }; + } catch (ex) { + throw new Error(`${this.definition.type}:: ${ex.message}`, { cause: ex }); + } + } + /** * Gets executed before deploying metadata + * * @param {MetadataTypeItem} metadata a single metadata item * @param {string} deployDir folder where files for deployment are stored - * @returns {Promise<MetadataTypeItem>} Promise of a single metadata item + * @returns {Promise.<MetadataTypeItem>} Promise of a single metadata item */ static async preDeployTasks(metadata, deployDir) { return metadata; } + /** + * helper to find a new unique name during item creation + * + * @param {string} key key of the item + * @param {string} name name of the item + * @param {{ type: string; key: string; name: any; }[]} namesInFolder names of the items in the same folder + * @param {string} [subtype] itemType-name + * @returns {string} new name + */ + static findUniqueName(key, name, namesInFolder, subtype) { + let newName = name; + let suffix; + let i = 1; + while ( + namesInFolder.find( + (item) => + item.name === newName && item.key !== key && (!subtype || item.type === subtype) + ) + ) { + suffix = ' (' + i + ')'; + // for customer key max is 100 chars + newName = name.slice(0, Math.max(0, 100 - suffix.length)) + suffix; + i++; + } + return newName; + } + /** * Abstract create method that needs to be implemented in child metadata type + * * @param {MetadataTypeItem} metadata single metadata entry * @param {string} deployDir directory where deploy metadata are saved - * @returns {void} + * @returns {Promise.<object> | null} Promise of API response or null in case of an error */ - static create(metadata, deployDir) { - Util.metadataLogger('error', this.definition.type, 'create', 'create not supported'); + static async create(metadata, deployDir) { + Util.logNotSupported(this.definition, 'create', metadata); return; } /** * Abstract update method that needs to be implemented in child metadata type + * * @param {MetadataTypeItem} metadata single metadata entry * @param {MetadataTypeItem} [metadataBefore] metadata mapped by their keyField - * @returns {void} + * @returns {Promise.<object> | null} Promise of API response or null in case of an error */ - static update(metadata, metadataBefore) { - Util.metadataLogger('error', this.definition.type, 'update', 'update not supported'); + static async update(metadata, metadataBefore) { + Util.logNotSupported(this.definition, 'update', metadata); return; } + /** + * Abstract refresh method that needs to be implemented in child metadata type + * + * @param {string[]} [keyArr] metadata keys + * @param {boolean} [checkKey] whether to check if the key is valid + * @param {MetadataTypeMap} [upsertResults] metadata mapped by their keyField as returned by update/create; needs to be refreshed after publish + * @returns {Promise.<string[]>} Returns list of keys that were refreshed + */ + static async refresh(keyArr, checkKey = true, upsertResults) { + Util.logNotSupported(this.definition, 'refresh'); + return []; + } + + /** + * + * @param {string[]} keyArr limit retrieval to given metadata type + * @param {string} retrieveDir retrieve dir including cred and bu + * @param {Set.<string>} [findAssetKeys] list of keys that were found referenced via ContentBlockByX; if set, method only gets keys and runs no updates + * @returns {Promise.<Set.<string>>} found asset keys + */ + static async getCbReferenceKeys(keyArr, retrieveDir, findAssetKeys) { + if (!Object.prototype.hasOwnProperty.call(this, 'replaceCbReference')) { + // only types that have a replaceCbReference method actually have ampscript/ssjs + return; + } + // get all metadata of the current type; then filter by keys in selectedTypes + const metadataMap = Util.filterObjByKeys( + await this.getJsonFromFS(File.normalizePath([retrieveDir, this.definition.type])), + keyArr + ); + await this.replaceCbReferenceLoop(metadataMap, retrieveDir, findAssetKeys); + return findAssetKeys; + } + + /** + * this iterates over all items found in the retrieve folder and executes the type-specific method for replacing references + * + * @param {MetadataTypeMap} metadataMap list of metadata (keyField => metadata) + * @param {string} retrieveDir retrieve dir including cred and bu + * @param {Set.<string>} [findAssetKeys] list of keys that were found referenced via ContentBlockByX; if set, method only gets keys and runs no updates + * @returns {Promise.<string[]>} Returns list of keys for which references were replaced + */ + static async replaceCbReferenceLoop(metadataMap, retrieveDir, findAssetKeys) { + const keysForDeploy = []; + if (!metadataMap) { + // if a type was skipped e.g. because it shall only be looked at on the parent then we would expect metadataMap to be undefined + return keysForDeploy; + } + const fromDescription = Util.OPTIONS.referenceFrom + .map((from) => 'ContentBlockBy' + Util.capitalizeFirstLetter(from)) + .join(' and '); + + if (Object.keys(metadataMap).length) { + Util.logger.debug(` - Searching in ${this.definition.type} `); + const baseDir = [retrieveDir, ...this.definition.type.split('-')]; + const deployMap = {}; + + for (const key in metadataMap) { + const item = metadataMap[key]; + if (this.isFiltered(item, true) || this.isFiltered(item, false)) { + // we would not have saved these items to disk but they exist in the cache and hence need to be skipped here + + continue; + } + + try { + // add key but make sure to turn it into string or else numeric keys will be filtered later + deployMap[key] = await this.replaceCbReference( + item, + retrieveDir, + findAssetKeys + ); + keysForDeploy.push(key + ''); + if (!findAssetKeys) { + await this.saveToDisk(deployMap, key, baseDir); + + Util.logger.info( + ` - added ${this.definition.type} to update queue: ${key}` + ); + } + } catch (ex) { + if (ex.code !== 200) { + // dont print error if we simply did not find relevant content blocks + Util.logger.errorStack( + ex, + 'issue with ' + this.definition.type + ' ' + key + ); + } + if (!findAssetKeys) { + Util.logger.info( + Util.getGrayMsg( + ` ☇ skipping ${Util.getTypeKeyName(this.definition, item)}: no ${fromDescription} found` + ) + ); + } + } + } + if (!findAssetKeys) { + Util.logger.info( + `Found ${keysForDeploy.length} ${this.definition.type}${keysForDeploy.length === 1 ? '' : 's'} to update` + ); + } + } + return keysForDeploy; + } + + /** + * Abstract execute method that needs to be implemented in child metadata type + * + * @param {MetadataTypeItem} item single metadata item + * @param {string} [retrieveDir] directory where metadata is saved + * @param {Set.<string>} [findAssetKeys] list of keys that were found referenced via ContentBlockByX; if set, method only gets keys and runs no updates + * @returns {Promise.<MetadataTypeItem | CodeExtractItem>} key of the item that was updated + */ + static async replaceCbReference(item, retrieveDir, findAssetKeys) { + Util.logNotSupported(this.definition, 'replaceCbReference'); + return []; + } + + /** + * Abstract execute method that needs to be implemented in child metadata type + * + * @param {string[]} keyArr customerkey of the metadata + * @param {MetadataTypeMapObj} [cache] metadata cache used by refresh to avoid recaching + * @returns {Promise.<string[]>} Returns list of keys that were executed + */ + static async execute(keyArr, cache) { + Util.logNotSupported(this.definition, 'execute'); + return []; + } + + /** + * Abstract schedule method that needs to be implemented in child metadata type + * + * @param {string[]} keyArr customerkey of the metadata + * @param {MetadataTypeMapObj} [cache] metadata cache used by refresh to avoid recaching + * @returns {Promise.<string[]>} Returns list of keys that were executed + */ + static async schedule(keyArr, cache) { + Util.logNotSupported(this.definition, 'schedule'); + return []; + } + + /** + * Abstract pause method that needs to be implemented in child metadata type + * + * @param {string[]} keyArr customerkey of the metadata + * @param {MetadataTypeMapObj} [cache] metadata cache used by refresh to avoid recaching + * @returns {Promise.<string[]>} Returns list of keys that were paused + */ + static async pause(keyArr, cache) { + Util.logNotSupported(this.definition, 'pause'); + return []; + } + + /** + * Abstract stop method that needs to be implemented in child metadata type + * + * @param {string[]} keyArr customerkey of the metadata + * @returns {Promise.<string[]>} Returns list of keys that were stopped + */ + static async stop(keyArr) { + Util.logNotSupported(this.definition, 'stop'); + return []; + } + + /** + * test if metadata was actually changed or not to potentially skip it during deployment + * + * @param {MetadataTypeItem} cachedVersion cached version from the server + * @param {MetadataTypeItem} metadata item to upload + * @param {string} [fieldName] optional field name to use for identifying the record in logs + * @returns {boolean} true if metadata was changed + */ + static hasChanged(cachedVersion, metadata, fieldName) { + // should be set up type by type but the *_generic version is likely a good start for many types + return true; + } + + /** + * test if metadata was actually changed or not to potentially skip it during deployment + * + * @param {MetadataTypeItem} cachedVersion cached version from the server + * @param {MetadataTypeItem} metadataItem item to upload + * @param {string} [fieldName] optional field name to use for identifying the record in logs + * @param {boolean} [silent] optionally suppress logging + * @returns {boolean} true on first identified deviation or false if none are found + */ + static hasChangedGeneric(cachedVersion, metadataItem, fieldName, silent) { + if (!cachedVersion) { + return true; + } + // we do need the full set in other places and hence need to work with a clone here + const clonedMetada = structuredClone(metadataItem); + // keep copy of identifier in case it is among the non-updateable fields + const identifier = clonedMetada[fieldName || this.definition.keyField]; + this.removeNotUpdateableFields(clonedMetada); + // iterate over what we want to upload rather than what we cached to avoid false positives + for (const prop in clonedMetada) { + if (this.definition.ignoreFieldsForUpdateCheck?.includes(prop)) { + continue; + } + if ( + clonedMetada[prop] === null || + ['string', 'number', 'boolean'].includes(typeof clonedMetada[prop]) + ) { + // check simple variables directly + // check should ignore types to bypass string/number auto-conversions caused by SFMC-SDK + if (clonedMetada[prop] != cachedVersion[prop]) { + Util.logger.debug( + `${this.definition.type}:: ${ + identifier + }.${prop} changed: '${cachedVersion[prop]}' to '${clonedMetada[prop]}'` + ); + return true; + } + } else if (deepEqual(clonedMetada[prop], cachedVersion[prop])) { + // test complex objects here + Util.logger.debug( + `${this.definition.type}:: ${ + identifier + }.${prop} changed: '${cachedVersion[prop]}' to '${clonedMetada[prop]}'` + ); + return true; + } + } + if (!silent) { + Util.logger.verbose( + ` ☇ skipping ${this.definition.type} ${identifier} / ${ + clonedMetada[this.definition.nameField] || '' + }: no change detected` + ); + } + return false; + } + + /** + * helper for {@link MetadataType.upsert} to enforce max key length + * + * @param {string} metadataKey key of metadata + */ + static enforceMaxKeyLength(metadataKey) { + if (this.definition.maxKeyLength && metadataKey.length > this.definition.maxKeyLength) { + throw new Error( + `key exceeds maximum length of ${this.definition.maxKeyLength} characters for this type` + ); + } + } + /** * MetadataType upsert, after retrieving from target and comparing to check if create or update operation is needed. - * @param {MetadataTypeMap} metadata metadata mapped by their keyField + * + * @param {MetadataTypeMap} metadataMap metadata mapped by their keyField * @param {string} deployDir directory where deploy metadata are saved - * @param {Util.BuObject} [buObject] properties for auth - * @returns {Promise<MetadataTypeMap>} keyField => metadata map + * @param {boolean} [runUpsertSequentially] when a type has self-dependencies creates need to run one at a time and created/changed keys need to be cached to ensure following creates/updates have thoses keys available + * @returns {Promise.<MetadataTypeMap>} keyField => metadata map */ - static async upsert(metadata, deployDir, buObject) { + static async upsert(metadataMap, deployDir, runUpsertSequentially = false) { + const orignalMetadataMap = structuredClone(metadataMap); const metadataToUpdate = []; const metadataToCreate = []; - for (const metadataKey in metadata) { + let createResults = []; + let updateResults = []; + let filteredByPreDeploy = 0; + for (const metadataKey in metadataMap) { + let hasError = false; try { // preDeployTasks parsing - const deployableMetadata = await this.preDeployTasks( - metadata[metadataKey], - deployDir - ); - // if preDeploy returns nothing then it cannot be deployed so skip deployment - if (deployableMetadata) { - metadata[metadataKey] = deployableMetadata; - const normalizedKey = File.reverseFilterIllegalFilenames(metadataKey); - // Update if it already exists; Create it if not - if ( - Util.logger.level === 'debug' && - metadata[metadataKey][this.definition.idField] - ) { - // TODO: re-evaluate in future releases if & when we managed to solve folder dependencies once and for all - // only used if resource is excluded from cache and we still want to update it - // needed e.g. to rewire lost folders - Util.logger.warn( - 'Hotfix for non-cachable resource found in deploy folder. Trying update:' + let deployableMetadata; + try { + this.enforceMaxKeyLength(metadataKey); + metadataMap[metadataKey] = await this.validation( + 'deploy', + metadataMap[metadataKey], + deployDir + ); + if (metadataMap[metadataKey]) { + // only run unless we encountered a situation in our validation that made us want to filter this record + deployableMetadata = await this.preDeployTasks( + metadataMap[metadataKey], + deployDir + ); + } + } catch (ex) { + // do this in case something went wrong during pre-deploy steps to ensure the total counter is correct + hasError = true; + deployableMetadata = metadataMap[metadataKey]; + if (deployableMetadata) { + // * include ": ${ex.message}" in the error if this is ever turned back into Util.logger.error() + Util.logger.errorStack( + ex, + ` ☇ skipping ${this.definition.type} ${ + deployableMetadata[this.definition.keyField] + } / ${deployableMetadata[this.definition.nameField]}` ); - Util.logger.warn(JSON.stringify(metadata[metadataKey])); - metadataToUpdate.push({ - before: {}, - after: metadata[metadataKey], - }); - } else if (this.cache[this.definition.type][normalizedKey]) { - // normal way of processing update files - metadata[metadataKey][this.definition.idField] = - this.cache[this.definition.type][normalizedKey][ - this.definition.idField - ]; - metadataToUpdate.push({ - before: this.cache[this.definition.type][normalizedKey], - after: metadata[metadataKey], - }); } else { - metadataToCreate.push(metadata[metadataKey]); + Util.logger.errorStack( + ex, + ` ☇ skipping ${this.definition.type} ${metadataKey}` + ); } } + + // if preDeploy returns nothing then it cannot be deployed so skip deployment + if (deployableMetadata) { + metadataMap[metadataKey] = deployableMetadata; + // create normalizedKey off of whats in the json rather than from "metadataKey" because preDeployTasks might have altered something (type asset) + const action = await this.createOrUpdate( + metadataMap, + metadataKey, + hasError, + metadataToUpdate, + metadataToCreate + ); + if (runUpsertSequentially) { + if (action === 'create') { + // handle creates sequentially here becasue we might have interdepencies + const result = await this.create(metadataMap[metadataKey], deployDir); + if (result) { + createResults.push(result); + if (result[this.definition.idField]) { + // ensure we have the ID in the cache + metadataMap[metadataKey][this.definition.idField] = + result[this.definition.idField]; + } + + // make this newly created item available in cache for other itmes that might reference it + /** @type {MetadataTypeMap} */ + const newObject = { [metadataKey]: metadataMap[metadataKey] }; + cache.mergeMetadata(this.definition.type, newObject); + } + } else if (action === 'update' && !Util.OPTIONS.noUpdate) { + const metadataEntry = metadataToUpdate.find( + (el) => + el !== null && + el.after[this.definition.keyField] === + metadataMap[metadataKey][this.definition.keyField] + ); + if (!metadataEntry) { + Util.logger.error( + ` - ${this.definition.type} ${metadataKey} / ${metadataMap[metadataKey][this.definition.keyField]} not found in update list` + ); + continue; + } + // handle updates sequentially here becasue we might have interdepencies + // this is especially important when we use features like --matchName which are updates but change the key + const result = await this.update( + metadataEntry.after, + metadataEntry.before + ); + if (result) { + updateResults.push(result); + + // make this newly created item available in cache for other itmes that might reference it + const newObject = { + [metadataKey]: structuredClone(metadataMap[metadataKey]), + }; + + if (result.objectID) { + // required for assets + newObject[metadataKey].objectID = result.objectID; + } + cache.mergeMetadata(this.definition.type, newObject); + } + } + } + } else { + filteredByPreDeploy++; + } } catch (ex) { - Util.metadataLogger('error', this.definition.type, 'upsert', ex, metadataKey); + if ( + metadataMap[metadataKey] && + metadataMap[metadataKey][this.definition.nameField] + ) { + Util.logger.error( + ` ☇ skipping ${this.definition.type} ${metadataKey} / ${metadataMap[metadataKey][this.definition.nameField]}: ${ex.message}` + ); + } else { + Util.logger.errorStack(ex, `Upserting ${this.definition.type} failed`); + } + } + } + if (!runUpsertSequentially) { + // create + const createLimit = pLimit(10); + createResults = ( + await Promise.all( + metadataToCreate + .filter((r) => r !== undefined && r !== null) + .map((metadataEntry) => + createLimit(() => this.create(metadataEntry, deployDir)) + ) + ) + ).filter((r) => r !== undefined && r !== null); + + // update + if (Util.OPTIONS.noUpdate && metadataToUpdate.length) { + Util.logger.info( + ` ☇ skipping update of ${metadataToUpdate.length} ${this.definition.type}${metadataToUpdate.length == 1 ? '' : 's'}: --noUpdate flag is set` + ); + } else if (metadataToUpdate.length) { + const updateLimit = pLimit(10); + updateResults = ( + await Promise.all( + metadataToUpdate + .filter((r) => r !== undefined && r !== null) + .map((metadataEntry) => + updateLimit(() => + this.update(metadataEntry.after, metadataEntry.before) + ) + ) + ) + ).filter((r) => r !== undefined && r !== null); } } - const createResults = ( - await Promise.map( - metadataToCreate, - (metadataEntry) => this.create(metadataEntry, deployDir), - { concurrency: 10 } - ) - ).filter((r) => r !== undefined && r !== null); - const updateResults = ( - await Promise.map( - metadataToUpdate, - (metadataEntry) => this.update(metadataEntry.after, metadataEntry.before), - { concurrency: 10 } - ) - ).filter((r) => r !== undefined && r !== null); // Logging - Util.metadataLogger( - 'info', - this.definition.type, - 'upsert', - `${createResults.length} of ${metadataToCreate.length} created / ${updateResults.length} of ${metadataToUpdate.length} updated` + Util.logger.info( + `${this.definition.type} upsert: ${createResults.length} of ${metadataToCreate.length} created / ${updateResults.length} of ${metadataToUpdate.length} updated` + + (filteredByPreDeploy > 0 ? ` / ${filteredByPreDeploy} filtered` : '') ); - - // if Results then parse as SOAP + let upsertResults; if (this.definition.bodyIteratorField === 'Results') { + // if Results then parse as SOAP // put in Retrieve Format for parsing // todo add handling when response does not contain items. - // @ts-ignore const metadataResults = createResults .concat(updateResults) - .filter((r) => r !== undefined && r !== null) - .map((r) => r.body.Results) - .flat() + // TODO remove Object.keys check after create/update SOAP methods stop returning empty objects instead of null + .filter((r) => r !== undefined && r !== null && Object.keys(r).length !== 0) + .flatMap((r) => r.Results) .map((r) => r.Object); - return this.parseResponseBody({ Results: metadataResults }); + upsertResults = this.parseResponseBody({ Results: metadataResults }); } else { + // likely comming from one of the many REST APIs // put in Retrieve Format for parsing // todo add handling when response does not contain items. - // @ts-ignore - const metadataResults = createResults - .concat(updateResults) - .filter((r) => r !== undefined && r !== null && r.res && r.res.body) - .map((r) => r.res.body); - return this.parseResponseBody({ items: metadataResults }); + const metadataResults = createResults.concat(updateResults).filter(Boolean); + upsertResults = this.parseResponseBody(metadataResults); + } + await this.postDeployTasks(upsertResults, orignalMetadataMap, { + created: createResults.length, + updated: updateResults.length, + }); + return upsertResults; + } + + /** + * helper for {@link MetadataType.upsert} + * + * @param {MetadataTypeMap} metadataMap list of metadata + * @param {string} metadataKey key of item we are looking at + * @param {boolean} hasError error flag from previous code + * @param {MetadataTypeItemDiff[]} metadataToUpdate list of items to update + * @param {MetadataTypeItem[]} metadataToCreate list of items to create + * @returns {Promise.<'create' | 'update' | 'skip'>} action to take + */ + static async createOrUpdate( + metadataMap, + metadataKey, + hasError, + metadataToUpdate, + metadataToCreate + ) { + let normalizedKey = File.reverseFilterIllegalFilenames( + metadataMap[metadataKey][this.definition.keyField] + ); + + // Update if it already exists; Create it if not + const maxKeyLength = this.definition.maxKeyLength || 36; + + // make sure keySuffix always has a string value + Util.OPTIONS.keySuffix = Util.OPTIONS.keySuffix ? Util.OPTIONS.keySuffix.trim() : ''; + if (Util.OPTIONS.keySuffix && !cache.getByKey(this.definition.type, normalizedKey)) { + // to ensure we go into update mode like we would with appending the MID to asset-keys, recreated the normalized key here + const newKey = this.getNewKey( + this.definition.keyField, + metadataMap[metadataKey], + maxKeyLength + ); + + normalizedKey = File.reverseFilterIllegalFilenames(newKey); + } + const cacheMatchedByKey = cache.getByKey(this.definition.type, normalizedKey); + const cacheMatchedByName = cacheMatchedByKey + ? null + : this.getCacheMatchedByName(metadataMap[metadataKey]); + + if ( + Util.logger.level === 'debug' && + metadataMap[metadataKey][this.definition.idField] && + this.definition.idField !== this.definition.keyField + ) { + // TODO: re-evaluate in future releases if & when we managed to solve folder dependencies once and for all + // only used if resource is excluded from cache and we still want to update it + // needed e.g. to rewire lost folders + Util.logger.warn( + ' - Hotfix for non-cachable resource found in deploy folder. Trying update:' + ); + Util.logger.warn(JSON.stringify(metadataMap[metadataKey])); + if (hasError) { + metadataToUpdate.push(null); + return 'skip'; + } else { + metadataToUpdate.push({ + before: {}, + after: metadataMap[metadataKey], + }); + return 'update'; + } + } else if (cacheMatchedByKey || cacheMatchedByName) { + // normal way of processing update files + const cachedVersion = cacheMatchedByKey || cacheMatchedByName; + if (!cacheMatchedByKey && cacheMatchedByName) { + Util.matchedByName[this.definition.type] ||= {}; + Util.matchedByName[this.definition.type][metadataKey] = + cacheMatchedByName[this.definition.keyField]; + } + if (!this.hasChanged(cachedVersion, metadataMap[metadataKey])) { + hasError = true; + } + + if (Util.OPTIONS.changeKeyField) { + if (this.definition.keyField == this.definition.idField) { + Util.logger.error( + ` - --changeKeyField cannot be used for types that use their ID as key. Skipping change.` + ); + hasError = true; + } else if (this.definition.keyIsFixed) { + Util.logger.error( + ` - type ${this.definition.type} does not support --changeKeyField and --changeKeyValue. Skipping change.` + ); + hasError = true; + } else if (!metadataMap[metadataKey][Util.OPTIONS.changeKeyField]) { + Util.logger.error( + ` - --changeKeyField is set to ${Util.OPTIONS.changeKeyField} but no value was found in the metadata. Skipping change.` + ); + hasError = true; + } else if (Util.OPTIONS.changeKeyField === this.definition.keyField) { + // simple issue, used WARN to avoid signaling a problem to ci/cd and don't fail deploy + Util.logger.warn( + ` - --changeKeyField is set to the same value as the keyField for ${this.definition.type}. Skipping change.` + ); + } else if (metadataMap[metadataKey][Util.OPTIONS.changeKeyField]) { + const newKey = this.getNewKey( + Util.OPTIONS.changeKeyField, + metadataMap[metadataKey], + maxKeyLength + ); + + if ( + metadataMap[metadataKey][Util.OPTIONS.changeKeyField] + + '' + + Util.OPTIONS.keySuffix > + maxKeyLength + ) { + Util.logger.warn( + `${this.definition.type} ${this.definition.keyField} may not exceed ${maxKeyLength} characters. Truncated the value in field ${Util.OPTIONS.changeKeyField} to ${newKey}` + ); + } + if (metadataKey == newKey) { + Util.logger.warn( + ` - --changeKeyField(${Util.OPTIONS.changeKeyField}) is providing the current value of the key (${metadataKey}). Skipping change.` + ); + } else { + Util.logger.info( + ` - Changing ${this.definition.type} key from ${metadataKey} to ${newKey} via --changeKeyField=${Util.OPTIONS.changeKeyField}` + ); + metadataMap[metadataKey][this.definition.keyField] = newKey; + + // ensure we can delete the old file(s) after the successful update + Util.changedKeysMap[this.definition.type] ||= {}; + Util.changedKeysMap[this.definition.type][newKey] = metadataKey; + } + } + } else if (Util.OPTIONS.changeKeyValue) { + if (Util.OPTIONS.keySuffix !== '') { + Util.logger.warn(`Ignoring --keySuffix as --changeKeyValue is set.`); + } + // NOTE: trim twice while getting the newKey value to remove leading spaces before limiting the length + const newKey = Util.OPTIONS.changeKeyValue.trim().slice(0, maxKeyLength).trim(); + if (Util.OPTIONS.changeKeyValue.trim().length > maxKeyLength) { + Util.logger.warn( + `${this.definition.type} ${this.definition.keyField} may not exceed ${maxKeyLength} characters. Truncated your value to ${newKey}` + ); + } + if (this.definition.keyField == this.definition.idField) { + Util.logger.error( + ` - --changeKeyValue cannot be used for types that use their ID as key. Skipping change.` + ); + hasError = true; + } else if (this.definition.keyIsFixed) { + Util.logger.error( + ` - type ${this.definition.type} does not support --changeKeyField and --changeKeyValue. Skipping change.` + ); + hasError = true; + } else if (metadataKey == newKey) { + Util.logger.warn( + ` - --changeKeyValue is providing the current value of the key (${metadataKey}). Skipping change.` + ); + } else { + Util.logger.info( + ` - Changing ${this.definition.type} key from ${metadataKey} to ${newKey} via --changeKeyValue` + ); + metadataMap[metadataKey][this.definition.keyField] = newKey; + + // ensure we can delete the old file(s) after the successful update + Util.changedKeysMap[this.definition.type] ||= {}; + Util.changedKeysMap[this.definition.type][newKey] = metadataKey; + } + } else if (Util.OPTIONS.keySuffix && Util.OPTIONS.keySuffix !== '') { + // assume we simply want to append a suffix + const newKey = this.getNewKey( + this.definition.keyField, + metadataMap[metadataKey], + maxKeyLength + ); + Util.logger.info( + ` - Changing ${this.definition.type} key from ${metadataKey} to ${newKey} via --keySuffix=${Util.OPTIONS.keySuffix}` + ); + metadataMap[metadataKey][this.definition.keyField] = newKey; + + // ensure we can delete the old file(s) after the successful update + Util.changedKeysMap[this.definition.type] ||= {}; + Util.changedKeysMap[this.definition.type][newKey] = metadataKey; + } + + if (hasError) { + // do this in case something went wrong during pre-deploy steps to ensure the total counter is correct + metadataToUpdate.push(null); + return 'skip'; + } else { + // add ObjectId to allow actual update + metadataMap[metadataKey][this.definition.idField] = + cachedVersion[this.definition.idField]; + + metadataToUpdate.push({ + before: cachedVersion, + after: metadataMap[metadataKey], + }); + + return 'update'; + } + } else { + if (hasError) { + // do this in case something went wrong during pre-deploy steps to ensure the total counter is correct + metadataToCreate.push(null); + return 'skip'; + } else { + if (Util.OPTIONS.keySuffix && Util.OPTIONS.keySuffix !== '') { + // assume we simply want to append a suffix + const newKey = this.getNewKey( + this.definition.keyField, + metadataMap[metadataKey], + maxKeyLength + ); + Util.logger.info( + ` - Changing ${this.definition.type} key from ${metadataKey} to ${newKey} via --keySuffix=${Util.OPTIONS.keySuffix}` + ); + metadataMap[metadataKey][this.definition.keyField] = newKey; + } + + metadataToCreate.push(metadataMap[metadataKey]); + return 'create'; + } } } + /** + * helper for {@link MetadataType.createOrUpdate} + * + * @param {MetadataTypeItem} metadataItem to be deployed item + * @returns {MetadataTypeItem} cached item or undefined + */ + static getCacheMatchedByName(metadataItem) { + // not supported generically + return null; + } + /** * Creates a single metadata entry via REST + * * @param {MetadataTypeItem} metadataEntry a single metadata Entry * @param {string} uri rest endpoint for POST - * @returns {Promise} Promise + * @param {boolean} [handleOutside] if the API reponse is irregular this allows you to handle it outside of this generic method + * @returns {Promise.<object> | null} Promise of API response or null in case of an error */ - static async createREST(metadataEntry, uri) { + static async createREST(metadataEntry, uri, handleOutside) { + const metadataClone = structuredClone(metadataEntry); this.removeNotCreateableFields(metadataEntry); - const options = { - uri: uri, - json: metadataEntry, - headers: {}, - }; try { - let response; - await Util.retryOnError( - `Retrying ${this.definition.type}: ${metadataEntry[this.definition.nameField]}`, - async () => (response = await this.client.RestClient.post(options)) - ); - this.checkForErrors(response); - Util.logger.info( - `- created ${this.definition.type}: ${metadataEntry[this.definition.keyField]}` - ); + // set to empty object in case API returned nothing to be able to update it in helper classes + let response = (await this.client.rest.post(uri, metadataEntry)) || {}; + response = await this.postCreateTasks(metadataEntry, response, metadataClone); + if (!handleOutside) { + Util.logger.info( + ` - created ${Util.getTypeKeyName(this.definition, metadataEntry)}` + ); + } return response; } catch (ex) { + const parsedErrors = this.getErrorsREST(ex); Util.logger.error( - `- error creating ${this.definition.type}: ${ - metadataEntry[this.definition.keyField] - } (${ex.message})` + ` ☇ error creating ${Util.getTypeKeyName(this.definition, metadataEntry)}:` ); + if (parsedErrors.length) { + for (const msg of parsedErrors) { + Util.logger.error(' • ' + msg); + } + } else if (ex?.message) { + Util.logger.debug(ex.message); + } return null; } } /** * Creates a single metadata entry via fuel-soap (generic lib not wrapper) + * * @param {MetadataTypeItem} metadataEntry single metadata entry - * @param {string} [overrideType] can be used if the API type differs from the otherwise used type identifier * @param {boolean} [handleOutside] if the API reponse is irregular this allows you to handle it outside of this generic method - * @returns {Promise} Promise + * @returns {Promise.<object> | null} Promise of API response or null in case of an error */ - static async createSOAP(metadataEntry, overrideType, handleOutside) { + static async createSOAP(metadataEntry, handleOutside) { + const soapType = this.definition.soapType || this.definition.type; + this.removeNotCreateableFields(metadataEntry); try { - this.removeNotCreateableFields(metadataEntry); - let response; - await Util.retryOnError( - `Retrying to create ${this.definition.type}: ${ - metadataEntry[this.definition.nameField] - }`, - async () => - (response = await new Promise((resolve, reject) => { - this.client.SoapClient.create( - overrideType || - this.definition.type.charAt(0).toUpperCase() + - this.definition.type.slice(1), - metadataEntry, - null, - (error, response) => (error ? reject(error) : resolve(response)) - ); - })) + const response = await this.client.soap.create( + Util.capitalizeFirstLetter(soapType), + metadataEntry, + null ); + if (!handleOutside) { Util.logger.info( - `- created ${this.definition.type}: ${metadataEntry[this.definition.keyField]}` + ` - created ${Util.getTypeKeyName(this.definition, metadataEntry)}` ); } return response; } catch (ex) { - if (!handleOutside) { - let errorMsg; - if (ex.results && ex.results.length) { - errorMsg = `${ex.results[0].StatusMessage} (Code ${ex.results[0].ErrorCode})`; - } else { - errorMsg = ex.message; - } - Util.logger.error( - `- error creating ${this.definition.type} '${ - metadataEntry[this.definition.keyField] - }': ${errorMsg}` - ); - } else { - throw ex; - } - - return {}; + this._handleSOAPErrors(ex, 'creating', metadataEntry, handleOutside); + return null; } } /** * Updates a single metadata entry via REST + * * @param {MetadataTypeItem} metadataEntry a single metadata Entry * @param {string} uri rest endpoint for PATCH - * @returns {Promise} Promise + * @param {'patch'|'post'|'put'} [httpMethod] defaults to 'patch'; some update requests require PUT instead of PATCH + * @param {boolean} [handleOutside] if the API reponse is irregular this allows you to handle it outside of this generic method + * @returns {Promise.<object> | null} Promise of API response or null in case of an error */ - static async updateREST(metadataEntry, uri) { + static async updateREST(metadataEntry, uri, httpMethod = 'patch', handleOutside) { + const metadataClone = structuredClone(metadataEntry); this.removeNotUpdateableFields(metadataEntry); - const options = { - uri: uri, - json: metadataEntry, - headers: {}, - }; try { - let response; - await Util.retryOnError( - `Retrying ${this.definition.type}: ${metadataEntry[this.definition.nameField]}`, - async () => (response = await this.client.RestClient.patch(options)) - ); - this.checkForErrors(response); + // set to empty object in case API returned nothing to be able to update it in helper classes + let response = (await this.client.rest[httpMethod](uri, metadataEntry)) || {}; + await this._postChangeKeyTasks(metadataEntry); + this.getErrorsREST(response); + response = await this.postUpdateTasks(metadataEntry, response, metadataClone); // some times, e.g. automation dont return a key in their update response and hence we need to fall back to name - Util.logger.info( - `- updated ${this.definition.type}: ${ - metadataEntry[this.definition.keyField] || - metadataEntry[this.definition.nameField] - }` - ); + if (!handleOutside) { + Util.logger.info( + ` - updated ${Util.getTypeKeyName(this.definition, metadataEntry)}` + ); + } return response; } catch (ex) { + const parsedErrors = this.getErrorsREST(ex); Util.logger.error( - `- error updating ${this.definition.type}: ${ + ` ☇ error updating ${Util.getTypeKeyName(this.definition, metadataEntry)}:` + ); + for (const msg of parsedErrors) { + Util.logger.error(' • ' + msg); + } + return null; + } + } + + /** + * helper for {@link MetadataType.updateREST} and {@link MetadataType.updateSOAP} that removes old files after the key was changed + * + * @param {MetadataTypeItem} metadataEntry a single metadata Entry + * @param {boolean} [keepMap] some types require to check the old-key new-key relationship in their postDeployTasks; currently used by dataExtension only + * @returns {Promise.<void>} - + */ + static async _postChangeKeyTasks(metadataEntry, keepMap = false) { + if ( + (Util.OPTIONS.changeKeyField || Util.OPTIONS.changeKeyValue) && + Util.changedKeysMap?.[this.definition.type]?.[metadataEntry[this.definition.keyField]] + ) { + const oldKey = + Util.changedKeysMap?.[this.definition.type]?.[ metadataEntry[this.definition.keyField] - } (${ex.message})` + ]; + + // delete file(s) of old key + await this.postDeleteTasks(oldKey); + + // fix key in cache + const typeCache = cache.getCache()[this.definition.type]; + typeCache[metadataEntry[this.definition.keyField]] = typeCache[oldKey]; + delete typeCache[oldKey]; + + if (!keepMap) { + // clean entry from to-do list + delete Util.changedKeysMap?.[this.definition.type]?.[ + metadataEntry[this.definition.keyField] + ]; + } + } + } + + /** + * Updates a single metadata entry via fuel-soap (generic lib not wrapper) + * + * @param {MetadataTypeItem} metadataEntry single metadata entry + * @param {boolean} [handleOutside] if the API reponse is irregular this allows you to handle it outside of this generic method + * @returns {Promise.<object> | null} Promise of API response or null in case of an error + */ + static async updateSOAP(metadataEntry, handleOutside) { + const soapType = this.definition.soapType || this.definition.type; + const metadataClone = structuredClone(metadataEntry); + this.removeNotUpdateableFields(metadataEntry); + try { + let response = await this.client.soap.update( + Util.capitalizeFirstLetter(soapType), + metadataEntry, + null ); + if (!handleOutside) { + Util.logger.info( + ` - updated ${Util.getTypeKeyName(this.definition, metadataEntry)}` + ); + } + await this._postChangeKeyTasks(metadataEntry); + response = await this.postUpdateTasks(metadataEntry, response, metadataClone); + + return response; + } catch (ex) { + this._handleSOAPErrors(ex, 'updating', metadataEntry, handleOutside); return null; } } /** - * Updates a single metadata entry via fuel-soap (generic lib not wrapper) - * @param {MetadataTypeItem} metadataEntry single metadata entry - * @param {string} [overrideType] can be used if the API type differs from the otherwise used type identifier - * @param {boolean} [handleOutside] if the API reponse is irregular this allows you to handle it outside of this generic method - * @returns {Promise} Promise + * + * @param {SOAPError} ex error that occured + * @param {'creating'|'updating'|'retrieving'|'executing'|'pausing'} msg what to print in the log + * @param {MetadataTypeItem} [metadataEntry] single metadata entry + * @param {boolean} [handleOutside] if the API reponse is irregular this allows you to handle it outside of this generic method + * @param {string} [nameAttribute] name attribute to use in the error message instead of keyField + */ + static _handleSOAPErrors(ex, msg, metadataEntry, handleOutside, nameAttribute) { + if (handleOutside) { + throw ex; + } else { + const errorMsg = this.getSOAPErrorMsg(ex); + const name = metadataEntry + ? ` '${metadataEntry[nameAttribute || this.definition.keyField]}'` + : ''; + Util.logger.error(` ☇ error ${msg} ${this.definition.type}${name}: ${errorMsg}`); + } + } + + /** + * helper for {@link MetadataType._handleSOAPErrors} + * + * @param {SOAPError} ex error that occured + * @returns {string} error message + */ + static getSOAPErrorMsg(ex) { + if (ex?.json?.Results?.length) { + if (ex?.json?.Results[0].StatusMessage) { + return `${ex.json.Results[0].StatusMessage} (Code ${ex.json.Results[0].ErrorCode})`; + } else if (ex?.json?.Results[0].Result.StatusMessage) { + return `${ex.json.Results[0].Result.StatusMessage} (Code ${ex.json.Results[0].Result.ErrorCode})`; + } + } + return ex.message; + } + + /** + * Retrieves SOAP via generic fuel-soap wrapper based metadata of metadata type into local filesystem. executes callback with retrieved metadata + * + * @param {string} [retrieveDir] Directory where retrieved metadata directory will be saved + * @param {SoapRequestParams} [requestParams] required for the specific request (filter for example) + * @param {string} [singleRetrieve] key of single item to filter by + * @param {string[]} [additionalFields] Returns specified fields even if their retrieve definition is not set to true + * @returns {Promise.<MetadataTypeMapObj>} Promise of item map */ - static async updateSOAP(metadataEntry, overrideType, handleOutside) { + static async retrieveSOAP(retrieveDir, requestParams, singleRetrieve, additionalFields) { + requestParams ||= {}; + const fields = this.getFieldNamesToRetrieve(additionalFields, !retrieveDir); + const soapType = this.definition.soapType || this.definition.type; let response; try { - this.removeNotUpdateableFields(metadataEntry); - await Util.retryOnError( - `Retrying to update ${this.definition.type}: ${ - metadataEntry[this.definition.nameField] - }`, - async () => - (response = await new Promise((resolve, reject) => { - this.client.SoapClient.update( - overrideType || - this.definition.type.charAt(0).toUpperCase() + - this.definition.type.slice(1), - metadataEntry, - null, - (error, response) => (error ? reject(error) : resolve(response)) - ); - })) + response = await this.client.soap.retrieveBulk( + Util.capitalizeFirstLetter(soapType), + fields, + requestParams ); - if (!handleOutside) { - Util.logger.info( - `- updated ${this.definition.type}: ${metadataEntry[this.definition.keyField]}` - ); - } - return response; } catch (ex) { - if (!handleOutside) { - let errorMsg; - if (ex.results && ex.results.length) { - errorMsg = `${ex.results[0].StatusMessage} (Code ${ex.results[0].ErrorCode})`; - } else { - errorMsg = ex.message; - } - Util.logger.error( - `- error updating ${this.definition.type} '${ - metadataEntry[this.definition.keyField] - }': ${errorMsg}` - ); - } else { - throw ex; - } - - return {}; + this._handleSOAPErrors(ex, 'retrieving'); + return; } - } - /** - * Retrieves SOAP via generic fuel-soap wrapper based metadata of metadata type into local filesystem. executes callback with retrieved metadata - * @param {string} retrieveDir Directory where retrieved metadata directory will be saved - * @param {Util.BuObject} buObject properties for auth - * @param {Object} [options] required for the specific request (filter for example) - * @param {string[]} [additionalFields] Returns specified fields even if their retrieve definition is not set to true - * @param {string} [overrideType] can be used if the API type differs from the otherwise used type identifier - * @returns {Promise<{metadata:MetadataTypeMap,type:string}>} Promise of item map - */ - static async retrieveSOAPgeneric( - retrieveDir, - buObject, - options, - additionalFields, - overrideType - ) { - const fields = this.getFieldNamesToRetrieve(additionalFields); + const metadata = this.parseResponseBody(response); - const metadata = await this.retrieveSOAPBody(fields, options, overrideType); if (retrieveDir) { const savedMetadata = await this.saveResults(metadata, retrieveDir, null); Util.logger.info( - `Downloaded: ${this.definition.type} (${Object.keys(savedMetadata).length})` + `Downloaded: ${this.definition.type} (${Object.keys(savedMetadata).length})` + + Util.getKeysString(singleRetrieve) ); - if ( - buObject && - this.properties.metaDataTypes.documentOnRetrieve.includes(this.definition.type) - ) { - await this.document(buObject, savedMetadata); + if (Object.keys(savedMetadata).length > 0) { + await this.runDocumentOnRetrieve(singleRetrieve, savedMetadata); + } else if (singleRetrieve) { + this.postDeleteTasks(singleRetrieve); } } return { metadata: metadata, type: this.definition.type }; } - /** - * helper that handles batched retrieve via SOAP - * @param {string[]} fields list of fields that we want to see retrieved - * @param {Object} [options] required for the specific request (filter for example) - * @param {string} [type] optionally overwrite the API type of the metadata here - * @returns {Promise<MetadataTypeMap>} keyField => metadata map - */ - static async retrieveSOAPBody(fields, options, type) { - let status; - let batchCounter = 1; - const defaultBatchSize = 2500; // 2500 is the typical batch size - options = options || {}; - let metadata = {}; - do { - let resultsBatch; - await Util.retryOnError(`Retrying ${this.definition.type}`, async () => { - resultsBatch = await new Promise((resolve, reject) => { - this.client.SoapClient.retrieve( - type || this.definition.type, - fields, - options || {}, - (error, response) => { - if (error) { - Util.logger.debug(`SOAP.retrieve Error: ${error.message}`); - reject(error); - } - if (response) { - resolve(response.body); - } else { - // fallback, lets make sure surrounding methods know we got an empty result back - resolve({}); - } - } - ); - }); - }); - status = resultsBatch.OverallStatus; - if (status === 'MoreDataAvailable') { - options.continueRequest = resultsBatch.RequestID; - Util.logger.info( - `- more than ${batchCounter * defaultBatchSize} ${ - this.definition.typeName - }s found in Business Unit - loading next batch...` - ); - batchCounter++; - } - const metadataBatch = this.parseResponseBody(resultsBatch); - - metadata = { ...metadata, ...metadataBatch }; - } while (status === 'MoreDataAvailable'); - - return metadata; - } /** * Retrieves Metadata for Rest Types + * * @param {string} retrieveDir Directory where retrieved metadata directory will be saved * @param {string} uri rest endpoint for GET - * @param {string} [overrideType] force a metadata type (mainly used for Folders) - * @param {Util.TemplateMap} [templateVariables] variables to be replaced in the metadata - * @returns {Promise<{metadata:MetadataTypeMap,type:string}>} Promise of item map - */ - static async retrieveREST(retrieveDir, uri, overrideType, templateVariables) { - const options = { - uri: uri, - headers: {}, - }; - let moreResults; - let lastPage = null; - let results = {}; - do { - options.uri = this.paginate(options.uri, lastPage); - let response; - await Util.retryOnError(`Retrying ${this.definition.type}`, async () => { - response = await this.client.RestClient.get(options); - }); - const metadata = this.parseResponseBody(response.body); - results = Object.assign(results, metadata); - if ( - this.definition.restPagination && - Object.keys(metadata).length > 0 && - response.body.page * response.body.pageSize < response.body.count - ) { - lastPage = Number(response.body.page); - moreResults = true; - } else { - moreResults = false; - } - } while (moreResults); + * @param {TemplateMap} [templateVariables] variables to be replaced in the metadata + * @param {string} [singleRetrieve] key of single item to filter by + * @returns {Promise.<{metadata: (MetadataTypeMap | MetadataTypeItem), type: string}>} Promise of item map (single item for templated result) + */ + static async retrieveREST(retrieveDir, uri, templateVariables, singleRetrieve) { + const response = + this.definition.restPagination && !singleRetrieve + ? await this.client.rest.getBulk(uri, this.definition.restPageSize || 500) + : await this.client.rest.get(uri); + const results = this.parseResponseBody(response, singleRetrieve); // get extended metadata if applicable if (this.definition.hasExtended) { + const amount = Object.keys(results).length; + if (amount > 100) { + Util.logger.info( + Util.getGrayMsg( + ` - retrieving extended metadata for ${amount} ${this.definition.type}s...` + ) + ); + } else { + Util.logger.debug(' - retrieving extended metadata'); + } + const rateLimit = pLimit(this.definition.restConcurrentLimit || 5); const extended = await Promise.all( - Object.keys(results).map((key) => - this.client.RestClient.get({ - uri: uri + results[key][this.definition.idField], + Object.keys(results) + .map((key) => { + const url = uri.endsWith(results[key][this.definition.idField]) + ? null + : uri + results[key][this.definition.idField]; + return url ? { url, key } : null; }) - ) + .filter(Boolean) + .map((el) => + rateLimit(async () => { + try { + return await this.client.rest.get(el.url); + } catch (ex) { + return await this.handleRESTErrors(ex, el.key, el.url); + } + }) + ) ); for (const ext of extended) { - const key = ext.body[this.definition.keyField]; - results[key] = Object.assign(results[key], ext.body); + const key = ext[this.definition.keyField]; + results[key] = Object.assign(results[key], ext); } } @@ -697,40 +1501,215 @@ class MetadataType { const savedMetadata = await this.saveResults( results, retrieveDir, - overrideType, + null, templateVariables ); Util.logger.info( - `Downloaded: ${overrideType || this.definition.type} (${ - Object.keys(savedMetadata).length - })` + `Downloaded: ${this.definition.type} (${Object.keys(savedMetadata).length})` + + Util.getKeysString(singleRetrieve) + ); + if (Object.keys(savedMetadata).length > 0) { + await this.runDocumentOnRetrieve(singleRetrieve, savedMetadata); + } else if (singleRetrieve) { + await this.postDeleteTasks(singleRetrieve); + } + } + + return { + metadata: templateVariables ? Object.values(results)[0] : results, + type: this.definition.type, + }; + } + + /** + * + * @param {object[]} urlArray {uri: string, id: string} combo of URL and ID/key of metadata + * @param {number} [concurrentRequests] optionally set a different amount of concurrent requests + * @param {boolean} [logAmountOfUrls] if true, prints an info message about to-be loaded amount of metadata + * @returns {Promise.<{metadata: (MetadataTypeMap | MetadataTypeItem), type: string}>} Promise of item map (single item for templated result) + */ + static async retrieveRESTcollection(urlArray, concurrentRequests = 10, logAmountOfUrls = true) { + if (logAmountOfUrls) { + Util.logger.debug( + Util.getGrayMsg( + ` - ${urlArray?.length} ${this.definition.type}${ + urlArray?.length === 1 ? '' : 's' + } found. Retrieving details...` + ) + ); + } + const rateLimit = pLimit(concurrentRequests); + + const metadataArr = urlArray.length + ? await Promise.all( + urlArray.map(async (item) => + rateLimit(async () => { + try { + return await this.client.rest.get(item.uri); + } catch (ex) { + return await this.handleRESTErrors(ex, item.id, item.uri); + } + }) + ) + ) + : []; + const results = {}; + for (const item of metadataArr) { + this.createCustomKeyField(item); + const key = item[this.definition.keyField]; + results[key] = item; + } + return { + metadata: results, + type: this.definition.type, + }; + } + + /** + * helper for {@link this.retrieveRESTcollection} + * + * @param {RestError} ex exception + * @param {string} key id or key of item + * @param {string} url url to call for retry + * @returns {Promise.<any>} - + */ + static async handleRESTErrors(ex, key, url) { + // if the ID is too short, the system will throw the 400 error + Util.logger.debug(` ☇ skipping ${this.definition.type} ${key}: ${ex.message} ${ex.code}`); + + return null; + } + + /** + * Used to execute a query/automation etc. + * + * @param {string} uri REST endpoint where the POST request should be sent + * @param {string} key item key + * @returns {Promise.<{key:string, response:string}>} metadata key and API response (OK or error) + */ + static async executeREST(uri, key) { + try { + const response = await this.client.rest.post(uri, {}); // payload is empty for this request + if (response === 'OK') { + Util.logger.info(` - executed ${this.definition.type}: ${key}`); + } else { + throw new Error(response); + } + return { key, response }; + } catch (ex) { + Util.logger.error(`Failed to execute ${this.definition.type} ${key}: ${ex.message}`); + } + } + + /** + * Used to execute a query/automation etc. + * + * @param {MetadataTypeItem} [metadataEntry] single metadata entry + * @returns {Promise.<{key:string, response:object}>} metadata key and API response + */ + static async executeSOAP(metadataEntry) { + const soapType = this.definition.soapType || this.definition.type; + try { + const response = await this.client.soap.perform( + Util.capitalizeFirstLetter(soapType), + 'start', + { + ObjectID: metadataEntry[this.definition.idField], + } ); + if (response?.OverallStatus === 'OK') { + Util.logger.info( + ` - executed ${Util.getTypeKeyName(this.definition, metadataEntry)}` + ); + } else { + throw new Error(response?.OverallStatus); + } + return { key: metadataEntry[this.definition.keyField], response }; + } catch (ex) { + this._handleSOAPErrors(ex, 'executing', metadataEntry); + return null; } + } - return { metadata: results, type: overrideType || this.definition.type }; + /** + * helper for {@link MetadataType.retrieveREST} and {@link MetadataType.retrieveSOAP} + * + * @param {string|number} singleRetrieve key of single item to filter by + * @param {MetadataTypeMap} metadataMap saved metadata + * @returns {Promise.<void>} - + */ + static async runDocumentOnRetrieve(singleRetrieve, metadataMap) { + if ( + this.buObject && + this.properties.metaDataTypes.documentOnRetrieve.includes(this.definition.type) + ) { + if (!singleRetrieve || (singleRetrieve && !this.definition.documentInOneFile)) { + const count = Object.keys(metadataMap).length; + Util.logger.debug( + ` - Running document for ${count} record${count === 1 ? '' : 's'}` + ); + await this.document(metadataMap); + } else { + Util.logger.info( + Util.getGrayMsg( + ` - Skipped running document because you supplied keys and ${this.definition.type} is documented in a single file for all.` + ) + ); + } + } } + /** + * helper for {@link parseResponseBody} that creates a custom key field for this type based on mobileCode and keyword + * + * @param {MetadataTypeItem} metadata single item + */ + static createCustomKeyField(metadata) {} + /** * Builds map of metadata entries mapped to their keyfields - * @param {Object} body json of response body - * @returns {Promise<MetadataTypeMap>} keyField => metadata map + * + * @param {object} body json of response body + * @param {string} [singleRetrieve] key of single item to filter by + * @returns {MetadataTypeMap} keyField => metadata map */ - static parseResponseBody(body) { + static parseResponseBody(body, singleRetrieve) { const bodyIteratorField = this.definition.bodyIteratorField; const keyField = this.definition.keyField; const metadataStructure = {}; if (body !== null) { - // in some cases data is just an array - if (Array.isArray(bodyIteratorField)) { + if (Array.isArray(body)) { + // in some cases data is just an array for (const item of body) { + this.createCustomKeyField(item); const key = item[keyField]; metadataStructure[key] = item; } } else if (body[bodyIteratorField]) { for (const item of body[bodyIteratorField]) { + this.createCustomKeyField(item); const key = item[keyField]; metadataStructure[key] = item; } + } else if (singleRetrieve) { + // some types will return a single item intead of an array if the key is supported by their api + this.createCustomKeyField(body); + // ! currently, the id: prefix is only supported by journey (interaction) + if (singleRetrieve.startsWith('id:')) { + singleRetrieve = body[keyField]; + } + metadataStructure[singleRetrieve] = body; + return metadataStructure; + } + if ( + metadataStructure[singleRetrieve] && + (typeof singleRetrieve === 'string' || typeof singleRetrieve === 'number') + ) { + // in case we really just wanted one entry but couldnt do so in the api call, filter it here + const single = { [singleRetrieve]: metadataStructure[singleRetrieve] }; + return single; + } else if (singleRetrieve) { + return {}; } } return metadataStructure; @@ -738,12 +1717,13 @@ class MetadataType { /** * Deletes a field in a metadata entry if the selected definition property equals false. + * * @example * Removes field (or nested fields childs) that are not updateable * deleteFieldByDefinition(metadataEntry, 'CustomerKey', 'isUpdateable'); * @param {MetadataTypeItem} metadataEntry One entry of a metadataType * @param {string} fieldPath field path to be checked if it conforms to the definition (dot seperated if nested): 'fuu.bar' - * @param {'isCreateable'|'isUpdateable'|'retrieving'|'templating'} definitionProperty delete field if definitionProperty equals false for specified field. Options: [isCreateable | isUpdateable] + * @param {'isCreateable'|'isUpdateable'|'retrieving'|'template'} definitionProperty delete field if definitionProperty equals false for specified field. Options: [isCreateable | isUpdateable] * @param {string} origin string of parent object, required when using arrays as these are parsed slightly differently. * @returns {void} */ @@ -752,30 +1732,27 @@ class MetadataType { let fieldContent; try { fieldContent = fieldPath.split('.').reduce((field, key) => field[key], metadataEntry); - } catch (e) { + } catch { // when we hit fields that have dots in their name (e.g. interarction, metaData['simulation.id']) then this will fail // decided to skip these cases for now entirely return; } - let originHelper; - // revert back placeholder to dots + let originHelper; if (origin) { - originHelper = origin + '.' + fieldPath; + originHelper = this.definition.fields[origin + '.%'] + ? origin + '.%' + : origin + '.' + fieldPath; } else { originHelper = fieldPath; } - if ( - this.definition.fields[originHelper] && - this.definition.fields[originHelper].skipValidation - ) { - // skip if current field should not be validated + if (this.definition.fields[originHelper]?.skipValidation || originHelper === '@_xsi:type') { + // skip if current field should not be validated OR if field is internal helper field xsi:type return; } else if ( Array.isArray(fieldContent) && - this.definition.fields[originHelper] && - this.definition.fields[originHelper][definitionProperty] === true + this.definition.fields[originHelper]?.[definitionProperty] === true ) { for (const subObject of fieldContent) { // for simple arrays skip, only process object or array arrays further @@ -799,10 +1776,10 @@ class MetadataType { // Recursive call of this method if there are nested fields for (const subField in fieldContent) { this.deleteFieldByDefinition( - metadataEntry, - originHelper + '.' + subField, + fieldContent, + subField, definitionProperty, - null + originHelper ); } } else if (!this.definition.fields[originHelper]) { @@ -821,8 +1798,10 @@ class MetadataType { }, metadataEntry); } } + /** * Remove fields from metadata entry that are not createable + * * @param {MetadataTypeItem} metadataEntry metadata entry * @returns {void} */ @@ -834,6 +1813,7 @@ class MetadataType { /** * Remove fields from metadata entry that are not updateable + * * @param {MetadataTypeItem} metadataEntry metadata entry * @returns {void} */ @@ -845,6 +1825,7 @@ class MetadataType { /** * Remove fields from metadata entry that are not needed in the template + * * @param {MetadataTypeItem} metadataEntry metadata entry * @returns {void} */ @@ -856,6 +1837,7 @@ class MetadataType { /** * Remove fields from metadata entry that are not needed in the stored metadata + * * @param {MetadataTypeItem} metadataEntry metadata entry * @returns {void} */ @@ -867,9 +1849,10 @@ class MetadataType { /** * checks if the current metadata entry should be saved on retrieve or not + * * @static * @param {MetadataTypeItem} metadataEntry metadata entry - * @param {boolean} [include=false] true: use definition.include / options.include; false=exclude: use definition.filter / options.exclude + * @param {boolean} [include] true: use definition.include / options.include; false=exclude: use definition.filter / options.exclude * @returns {boolean} true: skip saving == filtered; false: continue with saving * @memberof MetadataType */ @@ -883,9 +1866,7 @@ class MetadataType { ); if (includeByDefinition === false || includeByConfig === false) { Util.logger.debug( - `Filtered ${this.definition.type} '${ - metadataEntry[this.definition.nameField] - }' (${metadataEntry[this.definition.keyField]}): not matching include filter` + `Filtered ${Util.getTypeKeyName(this.definition, metadataEntry)}: not matching include filter` ); return true; @@ -899,9 +1880,7 @@ class MetadataType { ); if (excludeByDefinition || excludeByConfig) { Util.logger.debug( - `Filtered ${this.definition.type} '${ - metadataEntry[this.definition.nameField] - }' (${metadataEntry[this.definition.keyField]}): matching exclude filter` + `Filtered ${Util.getTypeKeyName(this.definition, metadataEntry)}: matching exclude filter` ); return true; } @@ -909,16 +1888,18 @@ class MetadataType { // this metadata type has no filters defined or no match was found return false; } + /** * optionally filter by what folder something is in + * * @static - * @param {Object} metadataEntry metadata entry - * @param {boolean} [include=false] true: use definition.include / options.include; false=exclude: use definition.filter / options.exclude + * @param {object} metadataEntry metadata entry + * @param {boolean} [include] true: use definition.include / options.include; false=exclude: use definition.filter / options.exclude * @returns {boolean} true: filtered == do NOT save; false: not filtered == do save * @memberof MetadataType */ static isFilteredFolder(metadataEntry, include) { - if (metadataEntry.json && metadataEntry.json.r__folder_Path) { + if (metadataEntry.json?.r__folder_Path) { // r__folder_Path found in sub-object metadataEntry = metadataEntry.json; } else if (!metadataEntry.r__folder_Path) { @@ -928,11 +1909,10 @@ class MetadataType { // r__folder_Path found if (include) { - const errorMsg = `Filtered ${this.definition.type} '${ - metadataEntry[this.definition.nameField] - }' (${ - metadataEntry[this.definition.keyField] - }): not matching include filter for folder`; + const errorMsg = `Filtered ${Util.getTypeKeyName( + this.definition, + metadataEntry + )}: not matching include filter for folder`; // check include-only filters (== discard rest) const includeByDefinition = this._filterFolder( this.definition.include, @@ -952,16 +1932,14 @@ class MetadataType { return true; } } else { - const errorMsg = `Filtered ${this.definition.type} '${ - metadataEntry[this.definition.nameField] - }' (${metadataEntry[this.definition.keyField]}): matching exclude filter for folder`; + const errorMsg = `Filtered ${Util.getTypeKeyName(this.definition, metadataEntry)}: matching exclude filter for folder`; // check exclude-only filters (== keep rest) const excludeByDefinition = this._filterFolder( this.definition.filter, metadataEntry.r__folder_Path ); if (excludeByDefinition) { - Util.logger.debug(errorMsg + ' (project config)'); + Util.logger.debug(errorMsg + ' (Accenture SFMC DevTools default)'); return true; } @@ -970,17 +1948,19 @@ class MetadataType { metadataEntry.r__folder_Path ); if (excludeByConfig) { - Util.logger.debug(errorMsg + ' (Accenture SFMC DevTools default)'); + Util.logger.debug(errorMsg + ' (project config)'); return true; } } // this metadata type has no filters defined or no match was found return false; } + /** * internal helper + * * @private - * @param {Object} myFilter include/exclude filter object + * @param {object} myFilter include/exclude filter object * @param {string} r__folder_Path already determined folder path * @returns {?boolean} true: filter value found; false: filter value not found; null: no filter defined */ @@ -1006,15 +1986,17 @@ class MetadataType { // no filters matched return false; } + /** * internal helper + * * @private - * @param {Object} myFilter include/exclude filter object - * @param {Object} metadataEntry metadata entry + * @param {object} myFilter include/exclude filter object + * @param {object} metadataEntry metadata entry * @returns {?boolean} true: filter value found; false: filter value not found; null: no filter defined */ static _filterOther(myFilter, metadataEntry) { - // not possible to check r__folder_Path before parseMetadata was run; handled in `isFilteredFolder()` + // not possible to check r__folder_Path before postRetrieveTasks was run; handled in `isFilteredFolder()` if ( !myFilter || !Object.keys(myFilter).filter((item) => item !== 'r__folder_Path').length @@ -1037,42 +2019,32 @@ class MetadataType { return false; } - /** - * Paginates a URL - * @param {string} url url of the request - * @param {number} last Number of the page of the last request - * @returns {string} new url with pagination - */ - static paginate(url, last) { - if (this.definition.restPagination) { - const baseUrl = url.split('?')[0]; - const queryParams = new URLSearchParams(url.split('?')[1]); - // if no page add page - if (!queryParams.has('$page')) { - queryParams.append('$page', (1).toString()); - } - // if there is a page and a last value, then add to it. - else if (queryParams.has('$page') && last) { - queryParams.set('$page', (Number(last) + 1).toString()); - } - return baseUrl + '?' + decodeURIComponent(queryParams.toString()); - } else { - return url; - } - } /** * Helper for writing Metadata to disk, used for Retrieve and deploy + * * @param {MetadataTypeMap} results metadata results from deploy * @param {string} retrieveDir directory where metadata should be stored after deploy/retrieve * @param {string} [overrideType] for use when there is a subtype (such as folder-queries) - * @param {Util.TemplateMap} [templateVariables] variables to be replaced in the metadata - * @returns {Promise<MetadataTypeMap>} Promise of saved metadata + * @param {TemplateMap} [templateVariables] variables to be replaced in the metadata + * @returns {Promise.<MetadataTypeMap>} Promise of saved metadata */ static async saveResults(results, retrieveDir, overrideType, templateVariables) { const savedResults = {}; - const subtypeExtension = '.' + (overrideType || this.definition.type) + '-meta'; let filterCounter = 0; + let subtypeExtension; for (const originalKey in results) { + if (this.definition.type === 'asset') { + overrideType = + this.definition.type + + '-' + + Object.keys(this.definition.extendedSubTypes).find((type) => + this.definition.extendedSubTypes[type].includes( + results[originalKey].assetType.name + ) + ); + } + subtypeExtension = '.' + (overrideType || this.definition.type) + '-meta'; + try { if ( this.isFiltered(results[originalKey], true) || @@ -1082,9 +2054,9 @@ class MetadataType { filterCounter++; continue; } + // define directory into which the current metdata shall be saved const baseDir = [retrieveDir, ...(overrideType || this.definition.type).split('-')]; - results[originalKey] = await this.postRetrieveTasks( results[originalKey], retrieveDir, @@ -1105,146 +2077,259 @@ class MetadataType { filterCounter++; continue; } - - // for complex types like asset, script, query we need to save the scripts that were extracted from the JSON - if (results[originalKey].json && results[originalKey].codeArr) { - // replace market values with template variable placeholders (do not do it on .codeArr) - if (templateVariables) { - results[originalKey].json = Util.replaceByObject( - results[originalKey].json, - templateVariables - ); - results[originalKey].subFolder = Util.replaceByObject( - results[originalKey].subFolder, - templateVariables - ); - } - - const postRetrieveData = results[originalKey]; - if (postRetrieveData.subFolder) { - // very complex types have their own subfolder - baseDir.push(...postRetrieveData.subFolder); - } - // save extracted scripts - for (const script of postRetrieveData.codeArr) { - const dir = [...baseDir]; - if (script.subFolder) { - // some files shall be saved in yet a deeper subfolder - dir.push(...script.subFolder); - } - File.writePrettyToFile( - dir, - script.fileName + subtypeExtension, - script.fileExt, - script.content, - templateVariables - ); - } - // normalize results[metadataEntry] - results[originalKey] = postRetrieveData.json; - } else { - // not a complex type, run the the entire JSON through templating - // replace market values with template variable placeholders - if (templateVariables) { - results[originalKey] = Util.replaceByObject( - results[originalKey], - templateVariables - ); - } - } - - // we dont store Id on local disk, but we need it for caching logic, - // so its in retrieve but not in save. Here we put into the clone so that the original - // object used for caching doesnt have the Id removed. - const saveClone = JSON.parse(JSON.stringify(results[originalKey])); - if (!this.definition.keepId) { - delete saveClone[this.definition.idField]; - } - - if (templateVariables) { - this.keepTemplateFields(saveClone); - } else { - this.keepRetrieveFields(saveClone); + results[originalKey] = await this.validation( + 'retrieve', + results[originalKey], + retrieveDir + ); + if (!results[originalKey]) { + // we encountered a situation in our validation that made us want to filter this record + delete results[originalKey]; + filterCounter++; + continue; } - savedResults[originalKey] = saveClone; - File.writeJSONToFile( - // manage subtypes + savedResults[originalKey] = await this.saveToDisk( + results, + originalKey, baseDir, - originalKey + subtypeExtension, - saveClone + subtypeExtension, + templateVariables ); + if (!savedResults[originalKey]) { + // happens in case like-filter struck + delete savedResults[originalKey]; + filterCounter++; + continue; + } } catch (ex) { - console.log(ex.stack); - Util.metadataLogger('error', this.definition.type, 'saveResults', ex, originalKey); + Util.logger.debug(JSON.stringify(savedResults[originalKey])); + Util.logger.errorStack( + ex, + ` - Saving ${this.definition.type} ${originalKey} / ${results[originalKey][this.definition.nameField]} failed` + ); } } - if (filterCounter) { - if (this.definition.type !== 'asset') { - // interferes with progress bar in assets and is printed 1-by-1 otherwise - Util.logger.info( - `Filtered ${this.definition.type}: ${filterCounter} (downloaded but not saved to disk)` + if (filterCounter && this.definition.type !== 'asset') { + // interferes with progress bar in assets and is printed 1-by-1 otherwise + Util.logger.info( + ` - Filtered ${this.definition.type}: ${filterCounter} (downloaded but not saved to disk)` + ); + } + return savedResults; + } + + /** + * + * @param {MetadataTypeMap} results metadata results from deploy + * @param {string} originalKey key of metadata + * @param {string[]} baseDir [retrieveDir, ...overrideType.split('-')] + * @param {string} [subtypeExtension] e.g. ".asset-meta" or ".query-meta" + * @param {TemplateMap} [templateVariables] variables to be replaced in the metadata + * @returns {Promise.<MetadataTypeItem>} saved metadata + */ + static async saveToDisk(results, originalKey, baseDir, subtypeExtension, templateVariables) { + subtypeExtension ||= '.' + this.definition.type + '-meta'; + // for complex types like asset, script, query we need to save the scripts that were extracted from the JSON + if (results[originalKey].json && results[originalKey].codeArr) { + // replace market values with template variable placeholders (do not do it on .codeArr) + if (templateVariables) { + results[originalKey].json = Util.replaceByObject( + results[originalKey].json, + templateVariables + ); + results[originalKey].subFolder = Util.replaceByObject( + results[originalKey].subFolder, + templateVariables + ); + } + + const postRetrieveData = results[originalKey]; + // normalize results[metadataEntry] + results[originalKey] = postRetrieveData.json; + + if (Util.OPTIONS.like && !Util.fieldsLike(results[originalKey], this.definition)) { + Util.logger.debug(`Filtered ${originalKey} because of --like option`); + return; + } + + if (postRetrieveData.subFolder) { + // very complex types have their own subfolder + baseDir.push(...postRetrieveData.subFolder); + } + // save extracted scripts + await Promise.all( + postRetrieveData.codeArr.map(async (script) => { + const dir = [...baseDir]; + if (script.subFolder) { + // some files shall be saved in yet a deeper subfolder + dir.push(...script.subFolder); + } + return File.writePrettyToFile( + dir, + script.fileName + subtypeExtension, + script.fileExt, + script.content, + templateVariables + ); + }) + ); + } else { + // not a complex type, run the the entire JSON through templating + // replace market values with template variable placeholders + if (templateVariables) { + results[originalKey] = Util.replaceByObject( + results[originalKey], + templateVariables ); } + if (Util.OPTIONS.like && !Util.fieldsLike(results[originalKey], this.definition)) { + Util.logger.debug(`Filtered ${originalKey} because of --like option`); + return; + } } - return savedResults; + + // we dont store Id on local disk, but we need it for caching logic, + // so its in retrieve but not in save. Here we put into the clone so that the original + // object used for caching doesnt have the Id removed. + + const saveClone = structuredClone(results[originalKey]); + if (!this.definition.keepId && this.definition.idField !== this.definition.keyField) { + delete saveClone[this.definition.idField]; + } + + if (templateVariables) { + this.keepTemplateFields(saveClone); + } else { + this.keepRetrieveFields(saveClone); + } + + await File.writeJSONToFile( + // manage subtypes + baseDir, + originalKey + subtypeExtension, + saveClone + ); + if (templateVariables) { + Util.logger.info( + `- templated ${this.definition.type}: ${saveClone[this.definition.nameField]}` + ); + } + + return saveClone; + } + + /** + * helper for {@link MetadataType.buildDefinitionForNested} + * searches extracted file for template variable names and applies the market values + * + * @param {string} code code from extracted code + * @param {TemplateMap} templateVariables variables to be replaced in the metadata + * @returns {string} code with markets applied + */ + static applyTemplateValues(code, templateVariables) { + // replace template variables with their values + return Mustache.render(code, templateVariables, {}, ['{{{', '}}}']); + } + + /** + * helper for {@link MetadataType.buildTemplateForNested} + * searches extracted file for template variable values and applies the market variable names + * + * @param {string} code code from extracted code + * @param {TemplateMap} templateVariables variables to be replaced in the metadata + * @returns {string} code with markets applied + */ + static applyTemplateNames(code, templateVariables) { + // replace template variables with their values + return Util.replaceByObject(code, templateVariables); + } + + /** + * helper for {@link MetadataType.buildDefinition} + * handles extracted code if any are found for complex types (e.g script, asset, query) + * + * @param {string} templateDir Directory where metadata templates are stored + * @param {string | string[]} targetDir Directory where built definitions will be saved + * @param {MetadataTypeItem} metadata main JSON file that was read from file system + * @param {TemplateMap} variables variables to be replaced in the metadata + * @param {string} templateName name of the template to be built + * @returns {Promise.<string[][]>} list of extracted files with path-parts provided as an array + */ + static async buildDefinitionForNested( + templateDir, + targetDir, + metadata, + variables, + templateName + ) { + // generic version here does nothing. actual cases handled in type classes + return null; } + /** - * helper for buildDefinition - * handles extracted code if any are found for complex types (e.g script, asset, query) + * helper for {@link MetadataType.buildTemplate} + * handles extracted code if any are found for complex types + * * @param {string} templateDir Directory where metadata templates are stored - * @param {string} targetDir Directory where built definitions will be saved + * @param {string|string[]} targetDir (List of) Directory where built definitions will be saved * @param {MetadataTypeItem} metadata main JSON file that was read from file system - * @param {Util.TemplateMap} variables variables to be replaced in the metadata + * @param {TemplateMap} templateVariables variables to be replaced in the metadata * @param {string} templateName name of the template to be built - * @returns {Promise<void>} Promise + * @returns {Promise.<string[][]>} list of extracted files with path-parts provided as an array */ - static async buildDefinitionForExtracts( + static buildTemplateForNested( templateDir, targetDir, metadata, - variables, + templateVariables, templateName ) { // generic version here does nothing. actual cases handled in type classes return null; } + /** * check template directory for complex types that open subfolders for their subtypes + * * @param {string} templateDir Directory where metadata templates are stored * @param {string} templateName name of the metadata file - * @returns {string} subtype name + * @returns {Promise.<string>} subtype name */ - static findSubType(templateDir, templateName) { + static async findSubType(templateDir, templateName) { return null; } + /** * optional method used for some types to try a different folder structure + * * @param {string} templateDir Directory where metadata templates are stored * @param {string[]} typeDirArr current subdir for this type * @param {string} templateName name of the metadata template * @param {string} fileName name of the metadata template file w/o extension * @param {Error} ex error from first attempt - * @returns {Object} metadata + * @returns {Promise.<string>} metadata in string form */ static async readSecondaryFolder(templateDir, typeDirArr, templateName, fileName, ex) { // we just want to push the method into the catch here - throw new Error(ex); + return; } + /** * Builds definition based on template * NOTE: Most metadata files should use this generic method, unless custom * parsing is required (for example scripts & queries) + * * @param {string} templateDir Directory where metadata templates are stored - * @param {String|String[]} targetDir (List of) Directory where built definitions will be saved + * @param {string | string[]} targetDir (List of) Directory where built definitions will be saved * @param {string} templateName name of the metadata file - * @param {Util.TemplateMap} variables variables to be replaced in the metadata - * @returns {Promise<{metadata:MetadataTypeMap,type:string}>} Promise of item map + * @param {TemplateMap} variables variables to be replaced in the metadata + * @returns {Promise.<MetadataTypeMapObj>} Promise of item map */ static async buildDefinition(templateDir, targetDir, templateName, variables) { // retrieve metadata template let metadataStr; let typeDirArr = [this.definition.type]; - const subType = this.findSubType(templateDir, templateName); + const subType = await this.findSubType(templateDir, templateName); if (subType) { typeDirArr.push(subType); } @@ -1253,7 +2338,14 @@ class MetadataType { try { // ! do not load via readJSONFile to ensure we get a string, not parsed JSON // templated files might contain illegal json before the conversion back to the file that shall be saved - metadataStr = await File.readFile([templateDir, ...typeDirArr], fileName, 'json'); + metadataStr = await File.readFilteredFilename( + [templateDir, ...typeDirArr], + fileName, + 'json' + ); + if (!metadataStr) { + throw new Error('File not found'); + } } catch (ex) { try { metadataStr = await this.readSecondaryFolder( @@ -1263,24 +2355,28 @@ class MetadataType { fileName, ex ); - } catch (ex) { - throw new Error( - `${this.definition.type}:: Could not find ./${File.normalizePath([ - templateDir, - ...typeDirArr, - fileName + '.json', - ])}.` + } catch { + // only happening for types that use readSecondaryFolder (e.g. asset) + // if we still have no metadataStr then we have to skip this metadata for all types and hence handle it outside of this catch + } + if (!metadataStr) { + Util.logger.warn( + Util.getGrayMsg( + ` ☇ skipped ${this.definition.type} ${templateName}: template not found` + ) ); + return; } - // return; } let metadata; try { // update all initial variables & create metadata object - metadata = JSON.parse(Mustache.render(metadataStr, variables)); - typeDirArr = typeDirArr.map((el) => Mustache.render(el, variables)); - } catch (ex) { + metadata = JSON.parse(this.applyTemplateValues(metadataStr, variables)); + typeDirArr = typeDirArr + .map((el) => (el === templateName ? metadata[this.definition.keyField] : el)) + .map((el) => this.applyTemplateValues(el, variables)); + } catch { throw new Error( `${this.definition.type}:: Error applying template variables on ${ templateName + '.' + this.definition.type @@ -1288,10 +2384,21 @@ class MetadataType { ); } + // run validations before buildDefinitionForNested because that method writes extracted code to disk + metadata = await this.validation( + 'buildDefinition', + metadata, + Array.isArray(targetDir) ? targetDir[0] : targetDir + ); + if (!metadata) { + // we encountered a situation in our validation that made us want to filter this record + return; + } + // handle extracted code // run after metadata was templated and converted into JS-object - // templating to extracted content is applied inside of buildDefinitionForExtracts() - await this.buildDefinitionForExtracts( + // templating to extracted content is applied inside of buildDefinitionForNested() + await this.buildDefinitionForNested( templateDir, targetDir, metadata, @@ -1301,103 +2408,668 @@ class MetadataType { try { // write to file - let targetDirArr; - if (!Array.isArray(targetDir)) { - targetDirArr = [targetDir]; - } else { - targetDirArr = targetDir; - } + const targetDirArr = Array.isArray(targetDir) ? targetDir : [targetDir]; for (const targetDir of targetDirArr) { - File.writeJSONToFile( + await File.writeJSONToFile( [targetDir, ...typeDirArr], metadata[this.definition.keyField] + '.' + this.definition.type + suffix, metadata ); } Util.logger.info( - 'MetadataType[' + - this.definition.type + - '].buildDefinition:: Complete - ' + - metadata[this.definition.keyField] + ` - prepared deployment definition of ${Util.getTypeKeyName( + this.definition, + metadata + )}` ); + if ( + metadata.r__folder_Path && + (metadata.r__folder_Path.startsWith('Shared Content/') || + metadata.r__folder_Path.startsWith('Shared Items/')) + ) { + Util.logger.warn( + Util.getMsgPrefix(this.definition, metadata) + + ` is in a shared folder: ${metadata.r__folder_Path}` + ); + } return { metadata: metadata, type: this.definition.type }; } catch (ex) { - throw new Error(`${this.definition.type}:: ${ex.message}`); + Util.logger.error( + ` ☇ skipped ${Util.getTypeKeyName(this.definition, metadata)}: ${ex.message}` + ); } } + /** + * Standardizes a check for multiple messages * - * @param {Object} response response payload from REST API - * @returns {void} + * @param {object} ex response payload from REST API + * @returns {string[]} formatted Error Message */ - static checkForErrors(response) { - if (response && response.res.statusCode >= 400 && response.res.statusCode < 600) { - const errors = []; - if (response.body.errors) { - for (const errMsg of response.body.errors) { - errors.push(errMsg.message.split('<br />').join('')); + static getErrorsREST(ex) { + const errors = []; + if (ex?.response?.status >= 400 && ex?.response?.status < 600) { + if (ex.response.data.errors) { + for (const errMsg of ex.response.data.errors) { + errors.push( + ...errMsg.message + .split('<br />') + .map((el) => el.trim()) + .filter(Boolean) + ); } - } else if (response.body.validationErrors) { - for (const errMsg of response.body.validationErrors) { - errors.push(errMsg.message.split('<br />').join('')); + } else if (ex.response.data.validationErrors) { + for (const errMsg of ex.response.data.validationErrors) { + errors.push( + ...errMsg.message + .split('<br />') + .map((el) => el.trim()) + .filter(Boolean) + ); } - } else if (response.body.message) { - errors.push(response.body.message); + } else if (ex.response.data.message) { + errors.push(ex.response.data.message); + } else if (ex.response.data) { + errors.push(`Undefined Errors: ${JSON.stringify(ex.response.data)}`); + Util.logger.debug(JSON.stringify(ex.response.data)); } else { - errors.push(`Undefined Errors: ${JSON.stringify(response.body)}`); + errors.push(`${ex.response.status} ${ex.response.statusText}`); } - throw new Error( - `Errors on upserting metadata at ${response.res.request.path}: ${errors.join( - '<br />' - )}` - ); + Util.logger.debug(JSON.stringify(ex.config)); } + return errors; } /** * Gets metadata cache with limited fields and does not store value to disk - * @param {Util.BuObject} [buObject] properties for auth + * * @param {MetadataTypeMap} [metadata] a list of type definitions * @param {boolean} [isDeploy] used to skip non-supported message during deploy * @returns {void} */ - static document(buObject, metadata, isDeploy) { + static document(metadata, isDeploy) { if (!isDeploy) { - Util.logger.error(`Documenting type ${this.definition.type} is not supported.`); + Util.logNotSupported(this.definition, 'document'); } } /** - * Delete a data extension from the specified business unit - * @param {Util.BuObject} buObject references credentials + * get name & key for provided id + * + * @param {string} id Identifier of metadata + * @returns {Promise.<{key:string, name:string}>} key, name and path of metadata; null if not found + */ + static async resolveId(id) { + Util.logNotSupported(this.definition, 'resolveId'); + return; + } + + /** + * Delete a metadata item from the specified business unit + * * @param {string} customerKey Identifier of data extension - * @returns {void} - + * @returns {Promise.<boolean>} deletion success status */ - static deleteByKey(buObject, customerKey) { - Util.logger.error(`Deleting type ${this.definition.type} is not supported.`); + static async deleteByKey(customerKey) { + Util.logNotSupported(this.definition, 'delete'); + return false; } + /** - * Returns metadata of a business unit that is saved locally - * @param {string} readDir root directory of metadata. - * @param {boolean} [listBadKeys=false] do not print errors, used for badKeys() - * @param {Object} [buMetadata] Metadata of BU in local directory - * @returns {Object} Metadata of BU in local directory + * clean up after deleting a metadata item + * + * @param {string} customerKey Identifier of metadata item + * @param {string[]} [additionalExtensions] additional file extensions to delete on top of `${this.definition.type}-meta.json` + * @returns {Promise.<void>} - Promise */ - static readBUMetadataForType(readDir, listBadKeys, buMetadata) { - buMetadata = buMetadata || {}; - readDir = File.normalizePath([readDir, this.definition.type]); + static async postDeleteTasks(customerKey, additionalExtensions) { + // delete local copy: retrieve/cred/bu/type/...json + whatever additional extensions were passed + const extArr = [`${this.definition.type}-meta.json`, ...(additionalExtensions || [])]; + for (const ext of extArr) { + const jsonFile = File.normalizePath([ + this.properties.directories.retrieve, + this.buObject.credential, + this.buObject.businessUnit, + this.definition.type, + `${customerKey}.${ext}`, + ]); + await File.remove(jsonFile); + } + } + + /** + * Delete a data extension from the specified business unit + * + * @param {string} key Identifier of metadata + * @param {string} [overrideKeyField] optionally change the name of the key field if the api uses a different name + * @param {number} [codeNotFound] error code that is responded with if the item was not found + * @param {boolean} [handleOutside] if the API reponse is irregular this allows you to handle it outside of this generic method + * @returns {Promise.<boolean>} deletion success flag + */ + static async deleteByKeySOAP(key, overrideKeyField, codeNotFound, handleOutside) { + const metadata = { [overrideKeyField || this.definition.keyField]: key }; + const soapType = this.definition.soapType || this.definition.type; try { - if (File.existsSync(readDir)) { - // check if folder name is a valid metadataType, then check if the user limited to a certain type in the command params - buMetadata[this.definition.type] = this.getJsonFromFS(readDir, listBadKeys); - return buMetadata; + await this.client.soap.delete(Util.capitalizeFirstLetter(soapType), metadata, null); + if (!handleOutside) { + Util.logger.info(` - deleted ${this.definition.type}: ${key}`); + } + await this.postDeleteTasks(key); + + return true; + } catch (ex) { + if (handleOutside) { + throw ex; + } else if ( + codeNotFound && + (ex.results?.[0]?.ErrorCode == codeNotFound || + ex.json?.Results?.[0]?.ErrorCode == codeNotFound) + ) { + await this.deleteNotFound(key); } else { - throw new Error(`Directory '${readDir}' does not exist.`); + const errorMsg = ex?.results?.length + ? `${ex.results[0].StatusMessage} (Code ${ex.results[0].ErrorCode})` + : ex?.json?.Results?.length + ? `${ex.json.Results[0].StatusMessage} (Code ${ex.json.Results[0].ErrorCode})` + : ex.message; + Util.logger.error( + ` - Deleting ${this.definition.type} '${key}' failed: ${errorMsg}` + ); + } + + return false; + } + } + + /** + * Delete a data extension from the specified business unit + * + * @param {string} url endpoint + * @param {string} key Identifier of metadata + * @param {number} [codeNotFound] error code that is responded with if the item was not found + * @param {boolean} [handleOutside] if the API reponse is irregular this allows you to handle it outside of this generic method + * @returns {Promise.<boolean>} deletion success flag + */ + static async deleteByKeyREST(url, key, codeNotFound, handleOutside) { + try { + await this.client.rest.delete(url); + if (!handleOutside) { + Util.logger.info(` - deleted ${this.definition.type}: ${key}`); } + await this.postDeleteTasks(key); + + return true; } catch (ex) { - throw new Error(ex.message); + if (handleOutside) { + throw ex; + } else if ( + codeNotFound && + (ex.code === codeNotFound || ex.response?.status === codeNotFound) + ) { + await this.deleteNotFound(key); + } else { + Util.logger.errorStack(ex, ` - Deleting ${this.definition.type} '${key}' failed`); + } + + return false; + } + } + + /** + * helper for {@link deleteByKey}, {@link deleteByKeyREST}, {@link deleteByKeySOAP} + * + * @param {string} key Identifier of metadata + */ + static async deleteNotFound(key) { + Util.logger.error( + ` ☇ skipping deletion of ${this.definition.type} ${key}: not found on server` + ); + await this.postDeleteTasks(key); + } + + /** + * Returns metadata of a business unit that is saved locally + * + * @param {string} readDir root directory of metadata. + * @param {boolean} [listBadKeys] do not print errors, used for badKeys() + * @param {object} [buMetadata] Metadata of BU in local directory + * @returns {Promise.<object>} Metadata of BU in local directory + */ + static async readBUMetadataForType(readDir, listBadKeys, buMetadata) { + buMetadata ||= {}; + readDir = File.normalizePath([readDir, this.definition.type]); + if (await File.pathExists(readDir)) { + // check if folder name is a valid metadataType, then check if the user limited to a certain type in the command params + buMetadata[this.definition.type] = await this.getJsonFromFS(readDir, listBadKeys); + return buMetadata; + } else { + throw new Error(`Directory '${readDir}' does not exist.`); + } + } + + /** + * should return only the json for all but asset, query and script that are saved as multiple files + * additionally, the documentation for dataExtension and automation should be returned + * + * @param {string[]} keyArr customerkey of the metadata + * @returns {Promise.<string[]>} list of all files that need to be committed in a flat array ['path/file1.ext', 'path/file2.ext'] + */ + static async getFilesToCommit(keyArr) { + const typeExtension = '.' + this.definition.type + '-meta.json'; + const path = File.normalizePath([ + this.properties.directories.retrieve, + this.buObject.credential, + this.buObject.businessUnit, + this.definition.type, + ]); + + const fileList = keyArr.map((key) => + File.normalizePath([path, File.filterIllegalFilenames(key) + typeExtension]) + ); + return fileList; + } + + /** + * + * @param {string[]} keyArr customerkey of the metadata + * @param {TypeKeyCombo} multiTypeKeyList list of all keys that need to be deployed + * @param {TypeKeyCombo} notFoundList list of all keys that were not found + * @param {boolean} isFirstCall will not gray out the log message for type/keys that you initially selected but only for their dependencies + * @returns {Promise.<TypeKeyCombo>} list of all keys that need to be deployed + */ + static async getDependentFiles( + keyArr, + multiTypeKeyList = {}, + notFoundList = {}, + isFirstCall = false + ) { + if ( + !Object.prototype.hasOwnProperty.call(this, 'create') && + !Object.prototype.hasOwnProperty.call(this, 'update') + ) { + Util.logger.info( + Util.getGrayMsg( + ` ☇ skipping ${this.definition.type} (${keyArr.join(', ')}) as it is currently not supported to deploy it` + ) + ); + return; + } + // initialize key array for current type unless it already exists + multiTypeKeyList[this.definition.type] ||= []; + notFoundList[this.definition.type] ||= []; + + keyArr = keyArr + // make sure all keys are strings + .map((key) => key + '') + .filter( + (key) => + // make sure we don't retry components that we have already searched without result + !notFoundList[this.definition.type].includes(key) && + // make sure we don't search for components that we have already found + !multiTypeKeyList[this.definition.type].includes(key) && + // filter out ampscript code that was used instead of actual keys; relevant e.g. for domainVerifications mentioned in senderProfiles + !key.startsWith('%%') && + !key.endsWith('%%') + ); + if (!keyArr.length) { + return; + } + const msg = ` - ${this.definition.type}: ${keyArr.join(', ')}`; + Util.logger.info(isFirstCall ? msg : Util.getGrayMsg(msg)); + // get paths to jsons + const filePaths = (await this.getFilesToCommit(keyArr)) + .filter(Boolean) + .filter((path) => path.endsWith('.json')); + + /** @type {TypeKeyCombo} */ + const dependentTypeKeyCombo = {}; + for (const filePath of filePaths) { + let metadataItem; + try { + metadataItem = await File.readJson(filePath); + } catch { + Util.logger.debug( + `- Could not read ${filePath} while trying to find dependencies. Skipping` + ); + continue; + } + // store current key if JSON file was found; because otherwise we could not include it in the package anyways + multiTypeKeyList[this.definition.type].push( + metadataItem[this.definition.keyField] + '' + ); + + // get dependent keys for this type + if (this.definition.dependencyGraph) { + for (const depType in this.definition.dependencyGraph) { + MetadataTypeInfo[depType].properties = this.properties; + MetadataTypeInfo[depType].buObject = this.buObject; + + const dependentKeyArr = []; + for (const fieldReference of this.definition.dependencyGraph[depType]) { + // ! this assumes we always have keys in this; will fail for list + const foundKeys = this.getNestedValue( + metadataItem, + fieldReference, + depType + ); + if (foundKeys) { + dependentKeyArr.push(...foundKeys); + } + } + if (dependentKeyArr.length) { + dependentTypeKeyCombo[depType] ||= []; + dependentTypeKeyCombo[depType].push(...dependentKeyArr); + } + } + } + this.getDependentFilesExtra(metadataItem, dependentTypeKeyCombo); + } + if (Object.keys(dependentTypeKeyCombo).length) { + for (const type in dependentTypeKeyCombo) { + // ensure we don't have duplicates + dependentTypeKeyCombo[type] = [...new Set(dependentTypeKeyCombo[type])]; + // try to read the jsons for those dependant keys + await MetadataTypeInfo[type].getDependentFiles( + dependentTypeKeyCombo[type], + multiTypeKeyList, + notFoundList + ); + } + } else { + Util.logger.verbose( + ` - ${this.definition.type} ${keyArr.join(', ')}: No new dependencies found` + ); + } + const notFound = keyArr.filter( + (key) => !multiTypeKeyList[this.definition.type].includes(key) + ); + if (notFound && notFound.length) { + Util.logger.warn( + Util.getGrayMsg( + ` ☇ skipping ${this.definition.type} dependenc${notFound.length === 1 ? 'y' : 'ies'} ${notFound.join(', ')}: Not found on your in your project folder.` + ) + ); + // make sure we don't search for it twice + notFoundList[this.definition.type] ||= []; + notFoundList[this.definition.type].push(...notFound); + } + return multiTypeKeyList; + } + + /** + * optional helper for {@link this.getDependentTypes} + * + * @param {object} metadataItem metadata json read from filesystem + * @param {TypeKeyCombo} dependentTypeKeyCombo list started in this.getDependentTypes + */ + static getDependentFilesExtra(metadataItem, dependentTypeKeyCombo) {} + + /** + * helper for {@link MetadataType.getDependentFiles} + * + * @param {MetadataTypeItem} obj the metadataItem to search in + * @param {string} nestedKey e.g "my.field.here" + * @param {string} dependentType used for types that need custom handling + * @returns {(string)[]} result array or null if nothing was found + */ + static getNestedValue(obj, nestedKey, dependentType) { + const nestedKeyParts = nestedKey.split('.'); + const result = this.getNestedValueHelper(obj, nestedKeyParts, dependentType); + + // remove duplicates and null values + const resultArr = (Array.isArray(result) ? [...new Set(result)] : [result]).filter(Boolean); + // return array if entries were found or null otherwise + return resultArr.length ? resultArr : null; + } + + /** + * helper for {@link MetadataType.getNestedValue} + * + * @param {any} obj the metadataItem to search in (or the result) + * @param {string[]} nestedKeyParts key in dot-notation split into parts + * @param {string} dependentType used for types that need custom handling + * @returns {(string) | (string)[]} result + */ + static getNestedValueHelper(obj, nestedKeyParts, dependentType) { + if (nestedKeyParts.length == 0) { + // key was found; append '' to ensure we always return a string + return obj + ''; + } + // get most left key + const key = nestedKeyParts.shift(); + if (!obj[key]) { + // key was not found + return; + } + return Array.isArray(obj[key]) + ? obj[key].flatMap((x) => + this.getNestedValueHelper(x, [...nestedKeyParts], dependentType) + ) + : this.getNestedValueHelper(obj[key], [...nestedKeyParts], dependentType); + } + + /** + * + * @param {MetadataTypeMap} metadataMap metadata mapped by their keyField + * @returns {string[]} list of keys + */ + static getKeysForFixing(metadataMap) { + const keysForDeploy = []; + if (!metadataMap) { + // if a type was skipped e.g. because it shall only be looked at on the parent then we would expect metadataMap to be undefined + return keysForDeploy; + } + if (Object.keys(metadataMap).length) { + Util.logger.info( + `Searching for ${this.definition.type} keys among downloaded items that need fixing:` + ); + Util.OPTIONS.keySuffix = Util.OPTIONS.keySuffix ? Util.OPTIONS.keySuffix.trim() : ''; + const maxKeyLength = this.definition.maxKeyLength || 36; + + for (const item of Object.values(metadataMap)) { + if (this.isFiltered(item, true) || this.isFiltered(item, false)) { + // we would not have saved these items to disk but they exist in the cache and hence need to be skipped here + + continue; + } + if ( + (item[this.definition.nameField].endsWith(Util.OPTIONS.keySuffix) && + item[this.definition.nameField].length > maxKeyLength) || + (!item[this.definition.nameField].endsWith(Util.OPTIONS.keySuffix) && + item[this.definition.nameField].length + Util.OPTIONS.keySuffix.length > + maxKeyLength) + ) { + Util.logger.warn( + `Name of the item ${Util.getKeyName( + this.definition, + item + )} is too long for a key${Util.OPTIONS.keySuffix.length ? ' (including the suffix ' + Util.OPTIONS.keySuffix + ')' : ''}. Consider renaming your item. Key will be equal first ${maxKeyLength} characters of the name` + ); + } + const newKey = this.getNewKey(this.definition.nameField, item, maxKeyLength); + if (newKey != item[this.definition.keyField] && !this.definition.keyIsFixed) { + // add key but make sure to turn it into string or else numeric keys will be filtered later + keysForDeploy.push(item[this.definition.keyField] + ''); + Util.logger.info( + ` - added ${this.definition.type} to fixKey queue: ${Util.getKeyName( + this.definition, + item + )} >> ${newKey}` + ); + } else { + Util.logger.info( + Util.getGrayMsg( + ` ☇ skipping ${Util.getTypeKeyName( + this.definition, + item + )}: key does not need to be updated` + ) + ); + } + } + Util.logger.info(`Found ${keysForDeploy.length} ${this.definition.type} keys to fix`); + } + return keysForDeploy; + } + + /** + * helper for getKeysForFixing and createOrUpdate + * + * @param {string} baseField name of the field to start the new key with + * @param {MetadataTypeItem} metadataItem - + * @param {number} maxKeyLength - + * @returns {string} newKey + */ + static getNewKey(baseField, metadataItem, maxKeyLength) { + const keySuffix = Util.OPTIONS.keySuffix; + let newKey; + newKey = (metadataItem[baseField] + '').trim().slice(0, maxKeyLength).trim(); + if (keySuffix.length && !newKey.endsWith(keySuffix)) { + newKey = + (metadataItem[baseField] + '') + .trim() + .slice(0, maxKeyLength - keySuffix.length) + .trim() + keySuffix; + } + + return newKey; + } + + /** + * @typedef {'off'|'warn'|'error'} ValidationLevel + */ + /** + * @typedef {object} ValidationRules + * @property {ValidationLevel} [noGuidKeys] flags metadata that did not get a proper key + * @property {ValidationLevel} [noRootFolder] flags metadata that did not get a proper key + * @property {{type:string[], options: ValidationRules}[]} [overrides] flags metadata that did not get a proper key + */ + + /** + * Gets executed before deploying metadata + * + * @param {'retrieve'|'buildDefinition'|'deploy'} method used to select the right config + * @param {MetadataTypeItem | CodeExtractItem} originalItem a single metadata item + * @param {string} targetDir folder where files for deployment are stored + * @returns {Promise.<MetadataTypeItem | CodeExtractItem>} Promise of a single metadata item + */ + static async validation(method, originalItem, targetDir) { + if (!this.properties.options?.validation?.[method]) { + return originalItem; + } + // if the fix parameter was set, allow validation rules to override the metadata + /** @type {MetadataTypeItem | CodeExtractItem} */ + let item = Util.OPTIONS.fix ? originalItem : structuredClone(originalItem); + /** @type {MetadataTypeItem} */ + const metadataItem = item.json && item.codeArr ? item.json : item; + const codeArr = item.codeArr || null; + /** @type {ValidationRules} */ + const validationConfig = structuredClone(this.properties.options?.validation?.[method]); + + // check if the config contains overrides for the current type + const overrides = Array.isArray(validationConfig.overrides) + ? validationConfig.overrides + : [validationConfig.overrides]; + if (validationConfig.overrides) { + delete validationConfig.overrides; + for (const override of overrides) { + if ( + override.type?.includes(this.definition.type) && + override.options && + Object.keys(override.options) + ) { + Object.assign(validationConfig, override.options); + } + } } + + // get default and custom validation rules + const definition = this.definition; + const validationRules = await validationsRules( + this.definition, + metadataItem, + targetDir, + codeArr + ); + + // run validation rules + const info = []; + const warnings = []; + let fixed = false; + for (const rule of Object.keys(validationRules)) { + if ( + validationConfig[rule] && + validationConfig[rule] !== 'off' && + !this.definition.skipValidation?.[rule] + ) { + const fixable = Object.prototype.hasOwnProperty.call(validationRules[rule], 'fix'); + if (!fixable && validationConfig[rule] === 'fix') { + // reduce from fix to error if not fixable + validationConfig[rule] = 'error'; + } + const mode = Util.OPTIONS.fix && fixable ? 'fix' : validationConfig[rule]; + let passed; + + try { + passed = await (!Util.OPTIONS.skipValidation && mode === 'fix' + ? validationRules[rule].fix() + : validationRules[rule].passed()); + } catch (ex) { + Util.logger.errorStack( + ex, + `Error while running validation rule ${rule} (check log file for details!)` + ); + continue; + } + if (mode === 'fix') { + // potentially fixed really + fixed = true; + } + if (!passed) { + if (!Util.OPTIONS.skipValidation && mode === 'fix') { + if (passed === false) { + info.push('😎 auto-fixed: ' + validationRules[rule].failedMsg); + } else if (passed === null) { + // ensure this item no longer exists outside of the validation rule + item = null; + warnings.length = 0; + info.length = 0; + info.push( + `🚫 ☇ filtered item via validation rule fix: ` + + validationRules[rule].failedMsg + ); + break; + } + } else if ( + !Util.OPTIONS.skipValidation && + validationConfig[rule] === 'error' && + passed === false + ) { + throw new Error(validationRules[rule].failedMsg); + } else if ( + (Util.OPTIONS.skipValidation || validationConfig[rule] === 'warn') && + passed === false + ) { + warnings.push(validationRules[rule].failedMsg); + } + } + } + } + if (info.length) { + Util.logger.info( + Util.getMsgPrefix(this.definition, metadataItem) + + `:${info.length > 1 ? '\n ·' : ''} ${info.join('\n · ')}` + ); + } + if (warnings.length) { + Util.logger.warn( + Util.getMsgPrefix(this.definition, metadataItem) + + `:${warnings.length > 1 ? '\n ·' : ''} ${warnings.join('\n · ')}` + ); + } + // only return "fixed" item if --fix is set, otherwise return the original item + return !Util.OPTIONS.skipValidation && (Util.OPTIONS.fix || fixed) ? item : originalItem; } } @@ -1412,13 +3084,20 @@ MetadataType.definition = { type: '', }; /** - * @type {Util.ET_Client} + * @type {SDK} */ MetadataType.client = undefined; /** - * @type {MultiMetadataTypeMap} + * @type {Mcdevrc} */ -MetadataType.cache = {}; MetadataType.properties = null; +/** + * @type {string} + */ +MetadataType.subType = null; +/** + * @type {BuObject} + */ +MetadataType.buObject = null; -module.exports = MetadataType; +export default MetadataType; diff --git a/lib/metadataTypes/MobileCode.js b/lib/metadataTypes/MobileCode.js new file mode 100644 index 000000000..bdc5f785e --- /dev/null +++ b/lib/metadataTypes/MobileCode.js @@ -0,0 +1,57 @@ +'use strict'; + +import MetadataType from './MetadataType.js'; + +/** + * @typedef {import('../../types/mcdev.d.js').BuObject} BuObject + * @typedef {import('../../types/mcdev.d.js').CodeExtract} CodeExtract + * @typedef {import('../../types/mcdev.d.js').CodeExtractItem} CodeExtractItem + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItem} MetadataTypeItem + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItemDiff} MetadataTypeItemDiff + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItemObj} MetadataTypeItemObj + * @typedef {import('../../types/mcdev.d.js').MetadataTypeMap} MetadataTypeMap + * @typedef {import('../../types/mcdev.d.js').MetadataTypeMapObj} MetadataTypeMapObj + * @typedef {import('../../types/mcdev.d.js').SoapRequestParams} SoapRequestParams + * @typedef {import('../../types/mcdev.d.js').TemplateMap} TemplateMap + */ + +/** + * MobileCode MetadataType + * + * @augments MetadataType + */ +class MobileCode extends MetadataType { + /** + * Retrieves Metadata of Mobile Keywords + * Endpoint /legacy/v1/beta/mobile/code/ return all Mobile Codes with all details. + * + * @param {string} retrieveDir Directory where retrieved metadata directory will be saved + * @param {void | string[]} [_] unused parameter + * @param {void | string[]} [__] unused parameter + * @param {string} [key] customer key of single item to retrieve + * @returns {Promise.<MetadataTypeMapObj>} Promise of metadata + */ + static retrieve(retrieveDir, _, __, key) { + return super.retrieveREST( + retrieveDir, + '/legacy/v1/beta/mobile/code/' + (key ? `?$where=keyword%20eq%20%27${key}%27%20` : ''), + null, + key + ); + } + + /** + * Retrieves event definition metadata for caching + * + * @returns {Promise.<MetadataTypeMapObj>} Promise of metadata + */ + static retrieveForCache() { + return super.retrieveREST(null, '/legacy/v1/beta/mobile/code/'); + } +} + +// Assign definition to static attributes +import MetadataTypeDefinitions from '../MetadataTypeDefinitions.js'; +MobileCode.definition = MetadataTypeDefinitions.mobileCode; + +export default MobileCode; diff --git a/lib/metadataTypes/MobileKeyword.js b/lib/metadataTypes/MobileKeyword.js new file mode 100644 index 000000000..caf3fcc23 --- /dev/null +++ b/lib/metadataTypes/MobileKeyword.js @@ -0,0 +1,546 @@ +'use strict'; + +import MetadataType from './MetadataType.js'; +import { Util } from '../util/util.js'; +import File from '../util/file.js'; +import cache from '../util/cache.js'; + +/** + * @typedef {import('../../types/mcdev.d.js').BuObject} BuObject + * @typedef {import('../../types/mcdev.d.js').CodeExtract} CodeExtract + * @typedef {import('../../types/mcdev.d.js').CodeExtractItem} CodeExtractItem + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItem} MetadataTypeItem + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItemDiff} MetadataTypeItemDiff + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItemObj} MetadataTypeItemObj + * @typedef {import('../../types/mcdev.d.js').MetadataTypeMap} MetadataTypeMap + * @typedef {import('../../types/mcdev.d.js').MetadataTypeMapObj} MetadataTypeMapObj + * @typedef {import('../../types/mcdev.d.js').SoapRequestParams} SoapRequestParams + * @typedef {import('../../types/mcdev.d.js').TemplateMap} TemplateMap + */ + +/** + * MobileKeyword MetadataType + * + * @augments MetadataType + */ +class MobileKeyword extends MetadataType { + /** + * Retrieves Metadata of Mobile Keywords + * Endpoint /legacy/v1/beta/mobile/keyword/ return all Mobile Keywords with all details. + * + * @param {string} retrieveDir Directory where retrieved metadata directory will be saved + * @param {void | string[]} [_] unused parameter + * @param {void | string[]} [__] unused parameter + * @param {string} [key] customer key of single item to retrieve + * @returns {Promise.<MetadataTypeMapObj>} Promise of metadata + */ + static retrieve(retrieveDir, _, __, key) { + try { + let queryParams; + [key, queryParams] = this.#getRetrieveKeyAndUrl(key); + + return super.retrieveREST( + retrieveDir, + '/legacy/v1/beta/mobile/keyword/' + queryParams, + null, + key + ); + } catch (ex) { + // if the mobileMessage does not exist, the API returns the error "Request failed with status code 400 (ERR_BAD_REQUEST)" which would otherwise bring execution to a hold + if (key && ex.code === 'ERR_BAD_REQUEST') { + Util.logger.info( + `Downloaded: ${this.definition.type} (0)${Util.getKeysString(key)}` + ); + this.postDeleteTasks(key); + } else { + throw ex; + } + } + return; + } + + /** + * helper for {@link parseResponseBody} that creates a custom key field for this type based on mobileCode and keyword + * + * @param {MetadataTypeItem} metadata single item + */ + static createCustomKeyField(metadata) { + metadata.c__codeKeyword = metadata.code.code + '.' + metadata.keyword; + } + + /** + * helper for {@link MobileKeyword.preDeployTasks} and {@link MobileKeyword.createOrUpdate} to ensure we have code & keyword properly set + * + * @param {MetadataTypeItem} metadata single item + */ + static #setCodeAndKeyword(metadata) { + const [code, keyword] = metadata.c__codeKeyword.split('.'); + + if (!code || !metadata.r__mobileCode_key || code !== metadata.r__mobileCode_key) { + throw new Error( + `r__mobileCode_key (${metadata.r__mobileCode_key}) does not match code (${code}) in c__codeKeyword (${metadata.c__codeKeyword}).` + ); + } + + // mobileCode + metadata.code = { + id: cache.searchForField('mobileCode', code, 'code', 'id'), + }; + + // keyword + metadata.keyword = keyword; + } + + /** + * helper for {@link MetadataType.upsert} + * + * @param {MetadataTypeMap} metadataMap list of metadata + * @param {string} metadataKey key of item we are looking at + * @param {boolean} hasError error flag from previous code + * @param {MetadataTypeItemDiff[]} metadataToUpdate list of items to update + * @param {MetadataTypeItem[]} metadataToCreate list of items to create + * @returns {Promise.<'create'|'update'|'skip'>} action to take + */ + static async createOrUpdate( + metadataMap, + metadataKey, + hasError, + metadataToUpdate, + metadataToCreate + ) { + const createOrUpdateAction = await super.createOrUpdate( + metadataMap, + metadataKey, + hasError, + metadataToUpdate, + metadataToCreate + ); + if (createOrUpdateAction === 'update') { + // in case --changeKeyField or --changeKeyValue was used, let's ensure we set code & keyword here again + this.#setCodeAndKeyword(metadataMap[metadataKey]); + } + return createOrUpdateAction; + } + + /** + * Retrieves event definition metadata for caching + * + * @param {void | string[]} [_] parameter not used + * @param {void | string[]} [__] parameter not used + * @param {string} [key] customer key of single item to retrieve + * @returns {Promise.<MetadataTypeMapObj>} Promise of metadata + */ + static retrieveForCache(_, __, key) { + return this.retrieve(null, null, null, key); + } + + /** + * retrieve an item and create a template from it + * + * @deprecated Use `retrieve` followed by `build` instead. `retrieveAsTemplate` will be removed in a future version. + * @param {string} templateDir Directory where retrieved metadata directory will be saved + * @param {string} key name of the metadata file + * @param {TemplateMap} templateVariables variables to be replaced in the metadata + * @returns {Promise.<MetadataTypeItemObj>} Promise of metadata + */ + static async retrieveAsTemplate(templateDir, key, templateVariables) { + Util.logDeprecated('retrieveAsTemplate', `'retrieve' followed by 'build'`); + try { + let queryParams; + [key, queryParams] = this.#getRetrieveKeyAndUrl(key); + + return super.retrieveTemplateREST( + templateDir, + `/legacy/v1/beta/mobile/keyword/` + queryParams, + templateVariables, + key + ); + } catch (ex) { + // if the mobileMessage does not exist, the API returns the error "Request failed with status code 400 (ERR_BAD_REQUEST)" which would otherwise bring execution to a hold + if (key && ex.code === 'ERR_BAD_REQUEST') { + Util.logger.info( + `Downloaded: ${this.definition.type} (0)${Util.getKeysString(key)}` + ); + } else { + throw ex; + } + } + } + + /** + * helper for {@link MobileKeyword.retrieve} and {@link MobileKeyword.retrieveAsTemplate} + * + * @param {string} key customer key of single item to retrieve / name of the metadata file + * @returns {Array} key, queryParams + */ + static #getRetrieveKeyAndUrl(key) { + let queryParams; + if (key) { + if (key.startsWith('id:')) { + // overwrite queryParams + queryParams = key.slice(3); + } else if (key.includes('.')) { + // keywords are always uppercased + key = key.toUpperCase(); + // format: code.keyword + const [code, keyword] = key.split('.'); + queryParams = `?view=simple&$where=keyword%20eq%20%27${keyword}%27%20and%code%20eq%20%27${code}%27%20`; + } else { + throw new Error( + `key ${key} has unexpected format. Expected 'code.keyword' or 'id:yourId'` + ); + } + } else { + queryParams = '?view=simple'; + } + return [key, queryParams]; + } + + /** + * Creates a single item + * + * @param {MetadataTypeItem} metadata a single item + * @returns {Promise} Promise + */ + static create(metadata) { + return super.createREST(metadata, '/legacy/v1/beta/mobile/keyword/'); + } + + /** + * Updates a single item + * + * @param {MetadataTypeItem} metadata a single item + * @returns {Promise} Promise + */ + static update(metadata) { + return super.updateREST( + metadata, + '/legacy/v1/beta/mobile/keyword/' + metadata[this.definition.idField], + 'post' // upsert API, post for insert and update! + ); + } + + /** + * manages post retrieve steps + * + * @param {MetadataTypeItem} metadata a single item + * @returns {CodeExtractItem | MetadataTypeItem | void} Array with one metadata object and one ssjs string; or single metadata object; nothing if filtered + */ + static postRetrieveTasks(metadata) { + try { + metadata.r__mobileCode_key = cache.searchForField( + 'mobileCode', + metadata.code.code, + 'code', + 'code' + ); + } catch { + // in case the the mobileCode cannot be found, do not save this keyword as its no longer accessible in the UI either + Util.logger.debug( + ` - skipping ${this.definition.type} ${ + metadata[this.definition.keyField] + }. Could not find parent mobileCode ${metadata.code.code}` + ); + return; + } + + if (metadata.responseMessage) { + // extract message body + const codeArr = []; + // keep between tags + const { fileExt, code } = this.prepExtractedCode(metadata.responseMessage); + delete metadata.responseMessage; + codeArr.push({ + subFolder: null, + fileName: metadata[this.definition.keyField], + fileExt: fileExt, + content: code, + }); + return { json: metadata, codeArr: codeArr, subFolder: null }; + } else { + return metadata; + } + } + + /** + * helper for {@link MobileKeyword.postRetrieveTasks} and {@link MobileKeyword._buildForNested} + * + * @param {string} metadataScript the code of the file + * @returns {{fileExt:string,code:string}} returns found extension and file content + */ + static prepExtractedCode(metadataScript) { + const code = metadataScript; + const fileExt = 'amp'; + + return { fileExt, code }; + } + + /** + * helper for {@link MetadataType.buildDefinition} + * handles extracted code if any are found for complex types + * + * @param {string} templateDir Directory where metadata templates are stored + * @param {string|string[]} targetDir (List of) Directory where built definitions will be saved + * @param {MetadataTypeItem} metadata main JSON file that was read from file system + * @param {TemplateMap} templateVariables variables to be replaced in the metadata + * @param {string} templateName name of the template to be built + * @returns {Promise.<string[][]>} list of extracted files with path-parts provided as an array + */ + static buildDefinitionForNested( + templateDir, + targetDir, + metadata, + templateVariables, + templateName + ) { + return this._buildForNested( + templateDir, + targetDir, + metadata, + templateVariables, + templateName, + 'definition' + ); + } + + /** + * helper for {@link MetadataType.buildTemplate} + * handles extracted code if any are found for complex types + * + * @example scripts are saved as 1 json and 1 ssjs file. both files need to be run through templating + * @param {string} templateDir Directory where metadata templates are stored + * @param {string|string[]} targetDir (List of) Directory where built definitions will be saved + * @param {MetadataTypeItem} metadata main JSON file that was read from file system + * @param {TemplateMap} templateVariables variables to be replaced in the metadata + * @param {string} templateName name of the template to be built + * @returns {Promise.<string[][]>} list of extracted files with path-parts provided as an array + */ + static buildTemplateForNested( + templateDir, + targetDir, + metadata, + templateVariables, + templateName + ) { + return this._buildForNested( + templateDir, + targetDir, + metadata, + templateVariables, + templateName, + 'template' + ); + } + + /** + * helper for {@link MobileKeyword.buildTemplateForNested} / {@link MobileKeyword.buildDefinitionForNested} + * handles extracted code if any are found for complex types + * + * @param {string} templateDir Directory where metadata templates are stored + * @param {string|string[]} targetDir (List of) Directory where built definitions will be saved + * @param {MetadataTypeItem} metadata main JSON file that was read from file system + * @param {TemplateMap} templateVariables variables to be replaced in the metadata + * @param {string} templateName name of the template to be built + * @param {'definition'|'template'} mode defines what we use this helper for + * @returns {Promise.<string[][]>} list of extracted files with path-parts provided as an array + */ + static async _buildForNested( + templateDir, + targetDir, + metadata, + templateVariables, + templateName, + mode + ) { + // get code from filesystem + let code = await this._mergeCode(metadata, templateDir, templateName); + if (!code) { + return null; + } + const file = this.prepExtractedCode(code); + const fileExt = file.fileExt; + code = file.code; + // apply templating + try { + if (mode === 'definition') { + // replace template variables with their values + code = this.applyTemplateValues(code, templateVariables); + } else if (mode === 'template') { + // replace template values with corresponding variable names + code = this.applyTemplateNames(code, templateVariables); + } + } catch { + throw new Error( + `${this.definition.type}:: Error applying template variables on ${ + templateName + '.' + this.definition.type + }-meta.${fileExt}.` + ); + } + + // write to file + const targetDirArr = Array.isArray(targetDir) ? targetDir : [targetDir]; + const nestedFilePaths = []; + + // keep old name if creating templates, otherwise use new name + const fileName = mode === 'definition' ? metadata[this.definition.keyField] : templateName; + + for (const targetDir of targetDirArr) { + File.writeToFile( + [targetDir, this.definition.type], + fileName + '.' + this.definition.type + '-meta', + fileExt, + code + ); + nestedFilePaths.push([ + targetDir, + this.definition.type, + fileName + '.' + this.definition.type + '-meta.' + fileExt, + ]); + } + return nestedFilePaths; + } + + /** + * prepares an event definition for deployment + * + * @param {MetadataTypeItem} metadata a single MobileKeyword + * @param {string} deployDir directory of deploy files + * @returns {Promise.<MetadataTypeItem>} Promise + */ + static async preDeployTasks(metadata, deployDir) { + // code + metadata.responseMessage = await this._mergeCode(metadata, deployDir); + + if (metadata.responseMessage && metadata.keywordType === 'NORMAL') { + throw new Error( + `Custom Response Text is not supported for keywords of type 'NORMAL'. Please remove the .amp file or change the keywordType to 'STOP' or 'INFO'.` + ); + } + if (!metadata.companyName && metadata.keywordType !== 'NORMAL') { + metadata.companyName = 'IGNORED'; + Util.logger.debug( + ` - No companyName found for keyword ${ + metadata[this.definition.keyField] + }. Setting to IGNORED.` + ); + } + + this.#setCodeAndKeyword(metadata); + return metadata; + } + + /** + * helper for {@link MetadataType.createREST} + * + * @param {MetadataTypeItem} metadataEntry a single metadata Entry + * @param {object} apiResponse varies depending on the API call + * @returns {Promise.<object>} apiResponse + */ + static async postCreateTasks(metadataEntry, apiResponse) { + await super.postDeployTasks_legacyApi(metadataEntry, apiResponse); + + return apiResponse; + } + + /** + * helper for {@link MetadataType.updateREST} + * + * @param {MetadataTypeItem} metadataEntry a single metadata Entry + * @param {object} apiResponse varies depending on the API call + * @returns {Promise.<object>} apiResponse, potentially modified + */ + static async postUpdateTasks(metadataEntry, apiResponse) { + await super.postDeployTasks_legacyApi(metadataEntry, apiResponse); + return apiResponse; + } + + /** + * helper for {@link MobileKeyword.preDeployTasks} that loads extracted code content back into JSON + * + * @param {MetadataTypeItem} metadata a single definition + * @param {string} deployDir directory of deploy files + * @param {string} [templateName] name of the template used to built defintion (prior applying templating) + * @returns {Promise.<string>} content for metadata.script + */ + static async _mergeCode(metadata, deployDir, templateName) { + templateName ||= metadata[this.definition.keyField]; + const codePath = File.normalizePath([ + deployDir, + this.definition.type, + templateName + '.' + this.definition.type + '-meta', + ]); + + if (await File.pathExists(codePath + '.amp')) { + return await File.readFilteredFilename( + [deployDir, this.definition.type], + templateName + '.' + this.definition.type + '-meta', + 'amp' + ); + } else { + // keeep this as a debug message, as it is optional and hence not an error + Util.logger.debug(`Could not find ${codePath}.amp`); + return null; + } + } + + /** + * Delete a metadata item from the specified business unit + * + * @param {string} key Identifier of item + * @returns {Promise.<boolean>} deletion success status + */ + static async deleteByKey(key) { + // get id from cache + const { metadata } = await this.retrieveForCache(undefined, undefined, key); + if (!metadata[key]) { + await this.deleteNotFound(key); + return false; + } + const id = metadata[key][this.definition.idField]; + // execute delete + Util.logger.info( + ' - Note: As long as the provided API key once existed, you will not see an error even if the mobileKeyword is already deleted.' + ); + return super.deleteByKeyREST('/legacy/v1/beta/mobile/keyword/' + id, key); + } + + /** + * clean up after deleting a metadata item + * + * @param {string} customerKey Identifier of metadata item + * @returns {Promise.<void>} - + */ + static async postDeleteTasks(customerKey) { + // delete local copy: retrieve/cred/bu/type/...-meta.json + // delete local copy: retrieve/cred/bu/type/...-meta.amp + super.postDeleteTasks(customerKey, [`${this.definition.type}-meta.amp`]); + } + + /** + * should return only the json for all but asset, query and script that are saved as multiple files + * additionally, the documentation for dataExtension and automation should be returned + * + * @param {string[]} keyArr customerkey of the metadata + * @returns {Promise.<string[]>} list of all files that need to be committed in a flat array ['path/file1.ext', 'path/file2.ext'] + */ + static async getFilesToCommit(keyArr) { + const path = File.normalizePath([ + this.properties.directories.retrieve, + this.buObject.credential, + this.buObject.businessUnit, + this.definition.type, + ]); + + const fileList = keyArr.flatMap((key) => [ + File.normalizePath([path, `${key}.${this.definition.type}-meta.json`]), + File.normalizePath([path, `${key}.${this.definition.type}-meta.amp`]), + ]); + return fileList; + } +} + +// Assign definition to static attributes +import MetadataTypeDefinitions from '../MetadataTypeDefinitions.js'; +MobileKeyword.definition = MetadataTypeDefinitions.mobileKeyword; + +export default MobileKeyword; diff --git a/lib/metadataTypes/MobileMessage.js b/lib/metadataTypes/MobileMessage.js new file mode 100644 index 000000000..25a361c0c --- /dev/null +++ b/lib/metadataTypes/MobileMessage.js @@ -0,0 +1,506 @@ +'use strict'; + +import MetadataType from './MetadataType.js'; +import { Util } from '../util/util.js'; +import File from '../util/file.js'; +import cache from '../util/cache.js'; + +/** + * @typedef {import('../../types/mcdev.d.js').BuObject} BuObject + * @typedef {import('../../types/mcdev.d.js').CodeExtract} CodeExtract + * @typedef {import('../../types/mcdev.d.js').CodeExtractItem} CodeExtractItem + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItem} MetadataTypeItem + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItemDiff} MetadataTypeItemDiff + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItemObj} MetadataTypeItemObj + * @typedef {import('../../types/mcdev.d.js').MetadataTypeMap} MetadataTypeMap + * @typedef {import('../../types/mcdev.d.js').MetadataTypeMapObj} MetadataTypeMapObj + * @typedef {import('../../types/mcdev.d.js').SoapRequestParams} SoapRequestParams + * @typedef {import('../../types/mcdev.d.js').TemplateMap} TemplateMap + */ + +/** + * MobileMessage MetadataType + * + * @augments MetadataType + */ +class MobileMessage extends MetadataType { + /** + * Retrieves Metadata of Mobile Keywords + * + * @param {string} retrieveDir Directory where retrieved metadata directory will be saved + * @param {void | string[]} [_] unused parameter + * @param {void | string[]} [__] unused parameter + * @param {string} [key] customer key of single item to retrieve + * @returns {Promise.<MetadataTypeMapObj>} Promise of metadata + */ + static retrieve(retrieveDir, _, __, key) { + if (key && key.startsWith('id:')) { + // if key starts with id: remove it to be compatible with other legacy API types (MetadataType.postCreateTasks_legacyApi) + key = key.slice(3); + } + try { + return super.retrieveREST( + retrieveDir, + '/legacy/v1/beta/mobile/message/' + + (key || + '?view=details&version=3&$sort=lastUpdated%20DESC&$where=isTest%20eq%200%20and%20status%20neq%20%27Archive%27'), + null, + key + ); + } catch (ex) { + // if the mobileMessage does not exist, the API returns the error "Request failed with status code 400 (ERR_BAD_REQUEST)" which would otherwise bring execution to a hold + if (key && ex.code === 'ERR_BAD_REQUEST') { + Util.logger.info( + `Downloaded: ${this.definition.type} (0)${Util.getKeysString(key)}` + ); + this.postDeleteTasks(key); + } else { + throw ex; + } + } + return; + } + + /** + * Retrieves event definition metadata for caching + * + * @param {void | string[]} [_] parameter not used + * @param {void | string[]} [__] parameter not used + * @param {string} [key] customer key of single item to retrieve + * @returns {Promise.<MetadataTypeMapObj>} Promise of metadata + */ + static retrieveForCache(_, __, key) { + return this.retrieve(null, null, null, key); + } + + /** + * Updates a single item + * + * @param {MetadataTypeItem} metadata a single item + * @returns {Promise} Promise + */ + static update(metadata) { + return super.updateREST( + metadata, + '/legacy/v1/beta/mobile/message/' + metadata[this.definition.idField], + 'post' // upsert API, post for insert and update! + ); + } + + /** + * Creates a single item + * + * @param {MetadataTypeItem} metadata a single item + * @returns {Promise} Promise + */ + static create(metadata) { + return super.createREST(metadata, '/legacy/v1/beta/mobile/message/'); + } + + /** + * helper for {@link MobileMessage.preDeployTasks} that loads extracted code content back into JSON + * + * @param {MetadataTypeItem} metadata a single definition + * @param {string} deployDir directory of deploy files + * @param {string} [templateName] name of the template used to built defintion (prior applying templating) + * @returns {Promise.<string>} code + */ + static async _mergeCode(metadata, deployDir, templateName) { + const fileExtension = 'amp'; + templateName ||= metadata[this.definition.keyField]; + const codePath = File.normalizePath([ + deployDir, + this.definition.type, + templateName + '.' + this.definition.type + '-meta', + ]); + + if (await File.pathExists(codePath + '.' + fileExtension)) { + return await File.readFilteredFilename( + [deployDir, this.definition.type], + templateName + '.' + this.definition.type + '-meta', + fileExtension + ); + } else { + throw new Error(`Could not find ${codePath}.${fileExtension}`); + } + } + + /** + * helper for {@link MobileMessage.postRetrieveTasks} and {@link MobileMessage._buildForNested} + * + * @param {string} code the code of the file + * @returns {{fileExt:string,code:string}} returns found extension and file content + */ + static prepExtractedCode(code) { + const fileExt = 'amp'; + + return { fileExt, code }; + } + + /** + * should return only the json for all but asset, query and script that are saved as multiple files + * additionally, the documentation for dataExtension and automation should be returned + * + * @param {string[]} keyArr customerkey of the metadata + * @returns {Promise.<string[]>} list of all files that need to be committed in a flat array ['path/file1.ext', 'path/file2.ext'] + */ + static async getFilesToCommit(keyArr) { + const path = File.normalizePath([ + this.properties.directories.retrieve, + this.buObject.credential, + this.buObject.businessUnit, + this.definition.type, + ]); + + const fileList = keyArr.flatMap((key) => [ + File.normalizePath([path, `${key}.${this.definition.type}-meta.json`]), + File.normalizePath([path, `${key}.${this.definition.type}-meta.amp`]), + ]); + return fileList; + } + + /** + * manages post retrieve steps + * + * @param {MetadataTypeItem} metadata a single query + * @returns {CodeExtractItem} Array with one metadata object and one query string + */ + static postRetrieveTasks(metadata) { + // mobileCode + try { + metadata.r__mobileCode_key = cache.searchForField( + 'mobileCode', + metadata.code.code, + 'code', + 'code' + ); + delete metadata.code; + } catch (ex) { + Util.logger.warn( + ` - ${this.definition.type} ${metadata[this.definition.nameField]} (${ + metadata[this.definition.keyField] + }): ${ex.message}.` + ); + } + + // mobileKeyword + + try { + for (const attr of ['keyword', 'subscriptionKeyword', 'nextKeyword']) { + if (metadata[attr]?.id) { + metadata[attr] = { + r__mobileKeyword_key: cache.searchForField( + 'mobileKeyword', + metadata[attr].id, + 'id', + 'c__codeKeyword' + ), + }; + } + } + } catch (ex) { + Util.logger.warn( + ` - ${this.definition.type} ${metadata[this.definition.nameField]} (${ + metadata[this.definition.keyField] + }): ${ex.message}.` + ); + } + // campaign + try { + if (Array.isArray(metadata.campaigns)) { + metadata.r__campaign_key = []; + + for (const campaign of metadata.campaigns) { + try { + // test if exists + const test = cache.getByKey('campaign', campaign.name); + if (!test) { + throw new Error(`campaign ${campaign.name} not found in cache`); + } + + metadata.r__campaign_key.push(campaign.name); + } catch (ex) { + Util.logger.warn( + ` - ${this.definition.type} ${metadata[this.definition.nameField]}: ${ + ex.message + }` + ); + } + } + delete metadata.campaigns; + } + } catch (ex) { + Util.logger.warn( + ` - ${this.definition.type} ${metadata[this.definition.nameField]} (${ + metadata[this.definition.keyField] + }): ${ex.message}.` + ); + } + + if (metadata.smsTriggeredSendDefinitionId !== '00000000-0000-0000-0000-000000000000') { + // TODO unknown type + } + + if (metadata.triggeredSendName) { + // TODO unknown type + } + + if (metadata.messageObjectId) { + // TODO unknown type + } + + if (metadata.template?.id) { + // TODO unknown type + } + + // extract text/code + const codeArr = []; + // keep between tags + const { fileExt, code } = this.prepExtractedCode(metadata.text); + delete metadata.text; + codeArr.push({ + subFolder: null, + fileName: metadata[this.definition.keyField], + fileExt: fileExt, + content: code, + }); + + return { json: metadata, codeArr: codeArr, subFolder: null }; + } + + /** + * prepares an event definition for deployment + * + * @param {MetadataTypeItem} metadata a single MobileMessage + * @param {string} deployDir directory of deploy files + * @returns {Promise.<MetadataTypeItem>} Promise + */ + static async preDeployTasks(metadata, deployDir) { + // mobileCode + if (metadata.r__mobileCode_key) { + metadata.code ||= {}; + const code = cache.getByKey('mobileCode', metadata.r__mobileCode_key); + if (!code) { + throw new Error(`mobileCode ${metadata.r__mobileCode_key} not found in cache`); + } + metadata.code = code; + delete metadata.r__mobileCode_key; + } + + // mobileKeyword + for (const attr of ['keyword', 'subscriptionKeyword', 'nextKeyword']) { + if (metadata[attr]?.r__mobileKeyword_key) { + const keywordObj = cache.getByKey( + 'mobileKeyword', + metadata[attr].r__mobileKeyword_key + ); + if (!keywordObj) { + throw new Error( + `mobileKeyword ${metadata[attr].r__mobileKeyword_key} not found in cache` + ); + } + metadata[attr] = keywordObj; + } + } + + // campaign + if (Array.isArray(metadata.r__campaign_key)) { + metadata.campaigns = []; + + for (const campaignName of metadata.r__campaign_key) { + const campaign = cache.getByKey('campaign', campaignName); + if (!campaign) { + throw new Error(`campaign ${campaignName} not found in cache`); + } + metadata.campaigns.push({ + id: campaign.id, + name: campaignName, + display: { + name: 'color', + value: campaign.color, + }, + }); + } + delete metadata.r__campaign_key; + } + + if (metadata.smsTriggeredSendDefinitionId !== '00000000-0000-0000-0000-000000000000') { + // TODO unknown type + } + + // code + metadata.text = await this._mergeCode(metadata, deployDir); + + return metadata; + } + + /** + * helper for {@link MetadataType.createREST} + * + * @param {MetadataTypeItem} metadataEntry a single metadata Entry + * @param {object} apiResponse varies depending on the API call + * @returns {Promise.<object>} apiResponse + */ + static async postCreateTasks(metadataEntry, apiResponse) { + await super.postDeployTasks_legacyApi(metadataEntry, apiResponse); + + return apiResponse; + } + + /** + * helper for {@link MetadataType.updateREST} + * + * @param {MetadataTypeItem} metadataEntry a single metadata Entry + * @param {object} apiResponse varies depending on the API call + * @returns {Promise.<object>} apiResponse, potentially modified + */ + static async postUpdateTasks(metadataEntry, apiResponse) { + await super.postDeployTasks_legacyApi(metadataEntry, apiResponse); + return apiResponse; + } + + /** + * helper for {@link MetadataType.buildDefinition} + * handles extracted code if any are found for complex types + * + * @param {string} templateDir Directory where metadata templates are stored + * @param {string|string[]} targetDir (List of) Directory where built definitions will be saved + * @param {MetadataTypeItem} metadata main JSON file that was read from file system + * @param {TemplateMap} templateVariables variables to be replaced in the metadata + * @param {string} templateName name of the template to be built + * @returns {Promise.<string[][]>} list of extracted files with path-parts provided as an array + */ + static buildDefinitionForNested( + templateDir, + targetDir, + metadata, + templateVariables, + templateName + ) { + return this._buildForNested( + templateDir, + targetDir, + metadata, + templateVariables, + templateName, + 'definition' + ); + } + + /** + * helper for {@link MetadataType.buildTemplate} + * handles extracted code if any are found for complex types + * + * @example scripts are saved as 1 json and 1 ssjs file. both files need to be run through templating + * @param {string} templateDir Directory where metadata templates are stored + * @param {string|string[]} targetDir (List of) Directory where built definitions will be saved + * @param {MetadataTypeItem} metadata main JSON file that was read from file system + * @param {TemplateMap} templateVariables variables to be replaced in the metadata + * @param {string} templateName name of the template to be built + * @returns {Promise.<string[][]>} list of extracted files with path-parts provided as an array + */ + static buildTemplateForNested( + templateDir, + targetDir, + metadata, + templateVariables, + templateName + ) { + return this._buildForNested( + templateDir, + targetDir, + metadata, + templateVariables, + templateName, + 'template' + ); + } + + /** + * helper for {@link MobileMessage.buildTemplateForNested} / {@link MobileMessage.buildDefinitionForNested} + * handles extracted code if any are found for complex types + * + * @param {string} templateDir Directory where metadata templates are stored + * @param {string|string[]} targetDir (List of) Directory where built definitions will be saved + * @param {MetadataTypeItem} metadata main JSON file that was read from file system + * @param {TemplateMap} templateVariables variables to be replaced in the metadata + * @param {string} templateName name of the template to be built + * @param {'definition'|'template'} mode defines what we use this helper for + * @returns {Promise.<string[][]>} list of extracted files with path-parts provided as an array + */ + static async _buildForNested( + templateDir, + targetDir, + metadata, + templateVariables, + templateName, + mode + ) { + // get code from filesystem + let code = await this._mergeCode(metadata, templateDir, templateName); + // try to remove script tags and decide on file extension (html/ssjs) + const file = this.prepExtractedCode(code); + const fileExt = file.fileExt; + code = file.code; + // apply templating + try { + if (mode === 'definition') { + // replace template variables with their values + code = this.applyTemplateValues(code, templateVariables); + } else if (mode === 'template') { + // replace template values with corresponding variable names + code = this.applyTemplateNames(code, templateVariables); + } + } catch { + throw new Error( + `${this.definition.type}:: Error applying template variables on ${ + templateName + '.' + this.definition.type + }-meta.amp.` + ); + } + + // write to file + const targetDirArr = Array.isArray(targetDir) ? targetDir : [targetDir]; + const nestedFilePaths = []; + + // keep old name if creating templates, otherwise use new name + const fileName = mode === 'definition' ? metadata[this.definition.keyField] : templateName; + + for (const targetDir of targetDirArr) { + File.writeToFile( + [targetDir, this.definition.type], + fileName + '.' + this.definition.type + '-meta', + fileExt, + code + ); + nestedFilePaths.push([ + targetDir, + this.definition.type, + fileName + '.' + this.definition.type + '-meta.' + fileExt, + ]); + } + return nestedFilePaths; + } + + /** + * Delete a metadata item from the specified business unit + * ! the endpoint expects the ID and not a key but for mcdev in this case key==id + * + * @param {string} id Identifier of item + * @returns {Promise.<boolean>} deletion success status + */ + static deleteByKey(id) { + Util.logger.info( + Util.getGrayMsg( + ' - Note: As long as the provided API key once existed, you will not see an error even if the mobileMessage is already deleted.' + ) + ); + return super.deleteByKeyREST('/legacy/v1/beta/mobile/message/' + id, id, 400); + } +} + +// Assign definition to static attributes +import MetadataTypeDefinitions from '../MetadataTypeDefinitions.js'; +MobileMessage.definition = MetadataTypeDefinitions.mobileMessage; + +export default MobileMessage; diff --git a/lib/metadataTypes/Query.js b/lib/metadataTypes/Query.js index 41ea7751c..bd76ef88f 100644 --- a/lib/metadataTypes/Query.js +++ b/lib/metadataTypes/Query.js @@ -1,96 +1,213 @@ 'use strict'; -const MetadataType = require('./MetadataType'); -const Util = require('../util/util'); -const File = require('../util/file'); -const Mustache = require('mustache'); +import { Util } from '../util/util.js'; +import MetadataType from './MetadataType.js'; +import File from '../util/file.js'; +import cache from '../util/cache.js'; /** - * @typedef {Object} QueryItem - * @property {string} name name - * @property {string} key key - * @property {string} description - - * @property {string} targetKey key of target data extension - * @property {string} createdDate e.g. "2020-09-14T01:42:03.017" - * @property {string} modifiedDate e.g. "2020-09-14T01:42:03.017" - * @property {'Overwrite'|'Update'|'Append'} targetUpdateTypeName defines how the query writes into the target data extension - * @property {0|1|2} [targetUpdateTypeId] mapped to targetUpdateTypeName via this.definition.targetUpdateTypeMapping - * @property {string} [targetId] Object ID of DE (removed before save) - * @property {string} [targetDescription] Description DE (removed before save) - * @property {boolean} isFrozen looks like this is always set to false - * @property {string} [queryText] contains SQL query with line breaks converted to '\n'. The content is extracted during retrieval and written into a separate *.sql file - * @property {string} [categoryId] holds folder ID, replaced with r__folder_Path during retrieve - * @property {string} r__folder_Path folder path in which this DE is saved - * - * @typedef {Object.<string, QueryItem>} QueryMap - * - * @typedef {Object} CodeExtractItem - * @property {QueryItem} json metadata of one item w/o code - * @property {MetadataType.CodeExtract[]} codeArr list of code snippets in this item - * @property {string[]} subFolder mostly set to null, otherwise list of subfolders + * @typedef {import('../../types/mcdev.d.js').BuObject} BuObject + * @typedef {import('../../types/mcdev.d.js').CodeExtract} CodeExtract + * @typedef {import('../../types/mcdev.d.js').CodeExtractItem} CodeExtractItem + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItem} MetadataTypeItem + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItemDiff} MetadataTypeItemDiff + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItemObj} MetadataTypeItemObj + * @typedef {import('../../types/mcdev.d.js').MetadataTypeMap} MetadataTypeMap + * @typedef {import('../../types/mcdev.d.js').MetadataTypeMapObj} MetadataTypeMapObj + * @typedef {import('../../types/mcdev.d.js').SoapRequestParams} SoapRequestParams + * @typedef {import('../../types/mcdev.d.js').TemplateMap} TemplateMap + */ + +/** + * @typedef {import('../../types/mcdev.d.js').QueryItem} QueryItem + * @typedef {import('../../types/mcdev.d.js').QueryMap} QueryMap */ /** * Query MetadataType + * * @augments MetadataType */ class Query extends MetadataType { /** * Retrieves Metadata of queries + * * @param {string} retrieveDir Directory where retrieved metadata directory will be saved - * @returns {Promise<{metadata:QueryMap,type:string}>} Promise of metadata + * @param {void | string[]} [_] unused parameter + * @param {void | string[]} [__] unused parameter + * @param {string} [key] customer key of single item to retrieve + * @returns {Promise.<{metadata: QueryMap, type: string}>} Promise of metadata */ - static async retrieve(retrieveDir) { - return super.retrieveREST(retrieveDir, '/automation/v1/queries/', null); + static async retrieve(retrieveDir, _, __, key) { + await File.initPrettier('sql'); + let objectId = null; + if (key) { + objectId = await this._getObjectIdForSingleRetrieve(key); + if (!objectId) { + // avoid running the rest request below by returning early + Util.logger.info( + `Downloaded: ${this.definition.type} (0)${Util.getKeysString(key)}` + ); + return { metadata: {}, type: this.definition.type }; + } + } + + return super.retrieveREST( + retrieveDir, + '/automation/v1/queries/' + (objectId || ''), + null, + key + ); + } + + /** + * a function to start query execution via API + * + * @param {string[]} keyArr customerkey of the metadata + * @returns {Promise.<string[]>} Returns list of keys that were executed successfully + */ + static async execute(keyArr) { + const results = []; + // works only with objectId + let objectId; + for (const key of keyArr) { + if (key) { + objectId = await this._getObjectIdForSingleRetrieve(key); + if (!objectId) { + Util.logger.info(`Skipping ${key} - did not find an item with such key`); + continue; + } + } + results.push( + super.executeREST(`/automation/v1/queries/${objectId}/actions/start/`, key) + ); + } + const executedKeyArr = (await Promise.all(results)) + .filter((r) => r.response === 'OK') + .map((r) => r.key); + Util.logger.info(`Executed ${executedKeyArr.length} of ${keyArr.length} items`); + return executedKeyArr; + } + + /** + * helper to allow us to select single metadata entries via REST + * + * @private + * @param {string} key customer key + * @returns {Promise.<string>} objectId or enpty string + */ + static async _getObjectIdForSingleRetrieve(key) { + const response = await this.client.soap.retrieve('QueryDefinition', ['ObjectID'], { + filter: { + leftOperand: { + leftOperand: 'CustomerKey', + operator: 'equals', + rightOperand: key, + }, + operator: 'AND', + rightOperand: { + leftOperand: 'Status', + operator: 'equals', + rightOperand: 'Active', + }, + }, + }); + return response?.Results?.length ? response.Results[0].ObjectID : null; } /** * Retrieves query metadata for caching - * @returns {Promise<{metadata:QueryMap,type:string}>} Promise of metadata + * + * @returns {Promise.<{metadata: QueryMap, type: string}>} Promise of metadata */ static async retrieveForCache() { - return super.retrieveREST(null, '/automation/v1/queries/', null); + return super.retrieveREST(null, '/automation/v1/queries/'); } /** * Retrieve a specific Query by Name + * + * @deprecated Use `retrieve` followed by `build` instead. `retrieveAsTemplate` will be removed in a future version. * @param {string} templateDir Directory where retrieved metadata directory will be saved * @param {string} name name of the metadata file - * @param {Util.TemplateMap} templateVariables variables to be replaced in the metadata - * @returns {Promise<{metadata:QueryMap,type:string}>} Promise of metadata + * @param {TemplateMap} templateVariables variables to be replaced in the metadata + * @returns {Promise.<{metadata: Query, type: string}>} Promise of metadata */ static async retrieveAsTemplate(templateDir, name, templateVariables) { - const response = await super.retrieveREST( + Util.logDeprecated('retrieveAsTemplate', `'retrieve' followed by 'build'`); + await File.initPrettier('sql'); + return super.retrieveREST( templateDir, - '/automation/v1/queries/?$filter=Name%20eq%20' + name.split(' ').join('%20'), - null, + '/automation/v1/queries/?$filter=Name%20eq%20' + encodeURIComponent(name), templateVariables ); - if (response && response.metadata && !Object.keys(response.metadata).length) { - Util.logger.error(`${this.definition.type} '${name}' not found on server.`); - } - return response; } /** * manages post retrieve steps + * * @param {QueryItem} metadata a single query - * @param {string} _ unused - * @param {boolean} isTemplating signals that we are retrieving templates * @returns {CodeExtractItem} Array with one metadata object and one query string */ - static postRetrieveTasks(metadata, _, isTemplating) { - // if retrieving template, replace the name with customer key if that wasn't already the case - if (isTemplating) { - const warningMsg = - 'Ensure that Automations using this query are updated with the new query-key before deployment.'; - this.overrideKeyWithName(metadata, warningMsg); + static postRetrieveTasks(metadata) { + // folder + super.setFolderPath(metadata); + + // extract SQL + const codeArr = [ + { + subFolder: null, + fileName: metadata[this.definition.keyField], + fileExt: 'sql', + content: metadata.queryText, + }, + ]; + delete metadata.queryText; + + try { + if (metadata.targetId) { + // overwrite targetKey via targetId (it's not updated on name/key change of the DE) + const targetKey = cache.searchForField( + 'dataExtension', + metadata.targetId, + 'ObjectID', + 'CustomerKey' + ); + if (targetKey !== metadata.targetKey) { + Util.logger.debug( + ` - ${this.definition.type} ${metadata[this.definition.nameField]} (${ + metadata[this.definition.keyField] + }): Replacing targetKey value in saved JSON '${ + metadata.targetKey + }' --> '${targetKey}'. Acquired new value from looking up the DE's ObjectID in targetId.` + ); + } + metadata.r__dataExtension_key = targetKey; + } else { + // if no targetId is set, at least check if the targetKey points to an existing DE (no override needed) + metadata.r__dataExtension_key = cache.searchForField( + 'dataExtension', + metadata.targetKey, + 'CustomerKey', + 'CustomerKey' + ); + } + delete metadata.targetKey; + } catch (ex) { + Util.logger.warn( + ` - ${this.definition.type} ${metadata[this.definition.nameField]} (${ + metadata[this.definition.keyField] + }): ${ex.message}.` + ); } - return this.parseMetadata(metadata); + delete metadata.targetId; + + return { json: metadata, codeArr: codeArr, subFolder: null }; } /** * Creates a single query + * * @param {QueryItem} query a single query * @returns {Promise} Promise */ @@ -101,6 +218,7 @@ class Query extends MetadataType { /** * Updates a single query + * * @param {QueryItem} query a single query * @returns {Promise} Promise */ @@ -111,140 +229,285 @@ class Query extends MetadataType { /** * prepares a Query for deployment + * * @param {QueryItem} metadata a single query activity * @param {string} deployDir directory of deploy files - * @returns {Promise<QueryItem>} Promise + * @returns {Promise.<QueryItem>} Promise */ static async preDeployTasks(metadata, deployDir) { - metadata.queryText = await File.readFile( + // folder + super.setFolderId(metadata); + + // reinject queryText + metadata.queryText = await File.readFilteredFilename( deployDir + '/' + this.definition.type, - metadata.key + '.' + this.definition.type + '-meta', + metadata[this.definition.keyField] + '.' + this.definition.type + '-meta', 'sql' ); - try { - metadata.targetKey = Util.getFromCache( - this.cache, - 'dataExtension', - metadata.targetKey, - 'CustomerKey', - 'CustomerKey' - ); - } catch (ex) { - throw new Error(`Query '${metadata.key}': ${ex.message}`); - } - try { - metadata.categoryId = Util.getFromCache( - this.cache, - 'folder', - metadata.r__folder_Path, - 'Path', - 'ID' - ); - delete metadata.r__folder_Path; - } catch (ex) { - throw new Error(`Query '${metadata.key}': ${ex.message}`); - } + + // dataExtension + metadata.targetKey = cache.searchForField( + 'dataExtension', + metadata.r__dataExtension_key, + 'CustomerKey', + 'CustomerKey' + ); + // we've seen queries without this ID set - crucial in case the DE ever gets renamed to ensure the query keeps working + metadata.targetId = cache.searchForField( + 'dataExtension', + metadata.r__dataExtension_key, + 'CustomerKey', + 'ObjectID' + ); + + // set ID for Append / Overwrite/ Update action metadata.targetUpdateTypeId = this.definition.targetUpdateTypeMapping[metadata.targetUpdateTypeName]; + + if (!Util.OPTIONS.matchName) { + // make sure the name is unique + const thisCache = cache.getCache()[this.definition.type]; + const relevantNames = Object.keys(thisCache).map((key) => ({ + type: null, + key: key, + name: thisCache[key][this.definition.nameField], + })); + // if the name is already in the folder for a different key, add a number to the end + metadata[this.definition.nameField] = this.findUniqueName( + metadata[this.definition.keyField], + metadata[this.definition.nameField], + relevantNames + ); + } + return metadata; } /** - * helper for buildDefinition + * helper for {@link Query.buildDefinitionForNested} + * searches extracted SQL file for template variables and applies the market values + * + * @param {string} code code from extracted code + * @param {TemplateMap} templateVariables variables to be replaced in the metadata + * @returns {string} code with markets applied + */ + static applyTemplateValues(code, templateVariables) { + // fix bad formatting applied by SQL Formatter Plus + code = code + .split(' { { { ') + .join('{{{') + .split('{ { { ') + .join('{{{') + .split(' } } } ') + .join('}}}') + .split(' } } }') + .join('}}}'); + + // replace template variables with their values + return super.applyTemplateValues(code, templateVariables); + } + + /** + * helper for {@link MetadataType.buildDefinition} * handles extracted code if any are found for complex types + * * @param {string} templateDir Directory where metadata templates are stored * @param {string|string[]} targetDir (List of) Directory where built definitions will be saved - * @param {Object} metadata main JSON file that was read from file system - * @param {Object} variables variables to be replaced in the metadata + * @param {QueryItem} metadata main JSON file that was read from file system + * @param {TemplateMap} templateVariables variables to be replaced in the metadata * @param {string} templateName name of the template to be built - * @returns {Promise} Promise + * @returns {Promise.<string[][]>} list of extracted files with path-parts provided as an array */ - static async buildDefinitionForExtracts( + static buildDefinitionForNested( templateDir, targetDir, metadata, - variables, + templateVariables, templateName + ) { + return this._buildForNested( + templateDir, + targetDir, + metadata, + templateVariables, + templateName, + 'definition' + ); + } + + /** + * helper for {@link MetadataType.buildTemplate} + * handles extracted code if any are found for complex types + * + * @example queries are saved as 1 json and 1 sql file. both files need to be run through templating + * @param {string} templateDir Directory where metadata templates are stored + * @param {string|string[]} targetDir (List of) Directory where built definitions will be saved + * @param {QueryItem} metadata main JSON file that was read from file system + * @param {TemplateMap} templateVariables variables to be replaced in the metadata + * @param {string} templateName name of the template to be built + * @returns {Promise.<string[][]>} list of extracted files with path-parts provided as an array + */ + static buildTemplateForNested( + templateDir, + targetDir, + metadata, + templateVariables, + templateName + ) { + return this._buildForNested( + templateDir, + targetDir, + metadata, + templateVariables, + templateName, + 'template' + ); + } + + /** + * helper for {@link Query.buildTemplateForNested} / {@link Query.buildDefinitionForNested} + * handles extracted code if any are found for complex types + * + * @private + * @param {string} templateDir Directory where metadata templates are stored + * @param {string|string[]} targetDir (List of) Directory where built definitions will be saved + * @param {QueryItem} metadata main JSON file that was read from file system + * @param {TemplateMap} templateVariables variables to be replaced in the metadata + * @param {string} templateName name of the template to be built + * @param {'definition'|'template'} mode defines what we use this helper for + * @returns {Promise.<string[][]>} list of extracted files with path-parts provided as an array + */ + static async _buildForNested( + templateDir, + targetDir, + metadata, + templateVariables, + templateName, + mode ) { // get SQL from filesystem - let code = await File.readFile( + let code = await File.readFilteredFilename( [templateDir, this.definition.type], templateName + '.' + this.definition.type + '-meta', 'sql' ); - // fix bad formatting applied by SQL Formatter Plus - code = code - .split(' { { { ') - .join('{{{') - .split('{ { { ') - .join('{{{') - .split(' } } } ') - .join('}}}') - .split(' } } }') - .join('}}}'); - // replace template variables with their values try { - code = Mustache.render(code, variables); - } catch (ex) { + if (mode === 'definition') { + code = this.applyTemplateValues(code, templateVariables); + } else if (mode === 'template') { + code = this.applyTemplateNames(code, templateVariables); + } + } catch { throw new Error( `${this.definition.type}:: Error applying template variables on ${ - metadata[this.definition.keyField] + '.' + this.definition.type + templateName + '.' + this.definition.type }-meta.sql.` ); } // write to file const targetDirArr = Array.isArray(targetDir) ? targetDir : [targetDir]; + const nestedFilePaths = []; + + // keep old name if creating templates, otherwise use new name + const fileName = mode === 'definition' ? metadata[this.definition.keyField] : templateName; for (const targetDir of targetDirArr) { File.writeToFile( [targetDir, this.definition.type], - metadata[this.definition.keyField] + '.' + this.definition.type + '-meta', + fileName + '.' + this.definition.type + '-meta', 'sql', code ); + nestedFilePaths.push([ + targetDir, + this.definition.type, + fileName + '.' + this.definition.type + '-meta.sql', + ]); } + return nestedFilePaths; } /** - * parses retrieved Metadata before saving - * @param {QueryItem} metadata a single query activity definition - * @returns {CodeExtractItem} a single item with code parts extracted + * should return only the json for all but asset, query and script that are saved as multiple files + * additionally, the documentation for dataExtension and automation should be returned + * + * @param {string[]} keyArr customerkey of the metadata + * @returns {Promise.<string[]>} list of all files that need to be committed in a flat array ['path/file1.ext', 'path/file2.ext'] */ - static parseMetadata(metadata) { - // folder - try { - metadata.r__folder_Path = Util.getFromCache( - this.cache, - 'folder', - metadata.categoryId, - 'ID', - 'Path' - ); - delete metadata.categoryId; - } catch (ex) { - Util.logger.warn(`Query '${metadata.key}': ${ex.message}`); + static async getFilesToCommit(keyArr) { + const path = File.normalizePath([ + this.properties.directories.retrieve, + this.buObject.credential, + this.buObject.businessUnit, + this.definition.type, + ]); + + const fileList = keyArr.flatMap((key) => [ + File.normalizePath([path, `${key}.${this.definition.type}-meta.json`]), + File.normalizePath([path, `${key}.${this.definition.type}-meta.sql`]), + ]); + return fileList; + } + + /** + * Standardizes a check for multiple messages but adds query specific filters to error texts + * + * @param {object} ex response payload from REST API + * @returns {string[]} formatted Error Message + */ + static getErrorsREST(ex) { + const errors = super.getErrorsREST(ex); + if (errors?.length > 0) { + return errors.map((msg) => msg.split('Error saving the Query field.').join('')); } + return errors; + } - // extract SQL - const codeArr = [ - { - subFolder: null, - fileName: metadata.key, - fileExt: 'sql', - content: metadata.queryText, - }, - ]; - delete metadata.queryText; + /** + * Delete a metadata item from the specified business unit + * + * @param {string} key Identifier of data extension + * @returns {Promise.<boolean>} deletion success flag + */ + static async deleteByKey(key) { + // delete only works with the query's object id + const objectId = key ? await this._getObjectIdForSingleRetrieve(key) : null; + if (!objectId) { + await this.deleteNotFound(key); + return false; + } + return super.deleteByKeyREST('/automation/v1/queries/' + objectId, key); + } - return { json: metadata, codeArr: codeArr, subFolder: null }; + /** + * clean up after deleting a metadata item + * + * @param {string} customerKey Identifier of metadata item + * @returns {Promise.<void>} - + */ + static async postDeleteTasks(customerKey) { + // delete local copy: retrieve/cred/bu/.../...-meta.json + // delete local copy: retrieve/cred/bu/.../...-meta.sql + await super.postDeleteTasks(customerKey, [`${this.definition.type}-meta.sql`]); + } + + /** + * Gets executed after deployment of metadata type + * + * @param {MetadataTypeMap} upsertResults metadata mapped by their keyField as returned by update/create + */ + static async postDeployTasks(upsertResults) { + if (Util.OPTIONS.execute) { + Util.logger.info(`Executing: ${this.definition.type}`); + await this.execute(Object.keys(upsertResults)); + } } } // Assign definition & cache to static attributes -Query.definition = require('../MetadataTypeDefinitions').query; -Query.cache = {}; -Query.client = undefined; +import MetadataTypeDefinitions from '../MetadataTypeDefinitions.js'; +Query.definition = MetadataTypeDefinitions.query; -module.exports = Query; +export default Query; diff --git a/lib/metadataTypes/Role.js b/lib/metadataTypes/Role.js index d56d9dbd5..eae687288 100644 --- a/lib/metadataTypes/Role.js +++ b/lib/metadataTypes/Role.js @@ -1,38 +1,51 @@ 'use strict'; -const MetadataType = require('./MetadataType'); -const Util = require('../util/util'); -const File = require('../util/file'); +import MetadataType from './MetadataType.js'; +import { Util } from '../util/util.js'; +import File from '../util/file.js'; +import cache from '../util/cache.js'; + +/** + * @typedef {import('../../types/mcdev.d.js').BuObject} BuObject + * @typedef {import('../../types/mcdev.d.js').CodeExtract} CodeExtract + * @typedef {import('../../types/mcdev.d.js').CodeExtractItem} CodeExtractItem + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItem} MetadataTypeItem + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItemDiff} MetadataTypeItemDiff + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItemObj} MetadataTypeItemObj + * @typedef {import('../../types/mcdev.d.js').MetadataTypeMap} MetadataTypeMap + * @typedef {import('../../types/mcdev.d.js').MetadataTypeMapObj} MetadataTypeMapObj + * @typedef {import('../../types/mcdev.d.js').SoapRequestParams} SoapRequestParams + * @typedef {import('../../types/mcdev.d.js').SoapSDKFilterSimple} SoapSDKFilterSimple + * @typedef {import('../../types/mcdev.d.js').TemplateMap} TemplateMap + */ /** * ImportFile MetadataType + * * @augments MetadataType */ class Role extends MetadataType { /** * Gets metadata from Marketing Cloud - * @param {String} retrieveDir Directory where retrieved metadata directory will be saved - * @param {String[]} _ Returns specified fields even if their retrieve definition is not set to true - * @param {Object} buObject properties for auth - * @returns {Promise<Object>} Metadata store object + * + * @param {string} retrieveDir Directory where retrieved metadata directory will be saved + * @param {void | string[]} [_] Returns specified fields even if their retrieve definition is not set to true + * @param {void | string[]} [___] unused parameter + * @param {string} [key] customer key of single item to retrieve + * @returns {Promise.<MetadataTypeMapObj>} Metadata store object */ - static async retrieve(retrieveDir, _, buObject) { - if (retrieveDir) { + static async retrieve(retrieveDir, _, ___, key) { + if (retrieveDir && this.buObject.eid !== this.buObject.mid) { // don't run for BUs other than Parent BU // this check does not work during caching - if (buObject.eid !== buObject.mid) { - Util.logger.info('Skipping Role retrieval on non-parent BU'); - return; - } + Util.logger.info(' - Skipping Role retrieval on non-parent BU'); + return; } - const fields = Object.keys(this.definition.fields).reduce((accumulator, currentValue) => { - if (this.definition.fields[currentValue].retrieving) { - accumulator.push(currentValue); - } - return accumulator; - }, []); - const options = { + const fields = super.getFieldNamesToRetrieve(null, !retrieveDir); + + /** @type {SoapRequestParams} */ + let requestParams = { // filter individual roles filter: { leftOperand: 'IsPrivate', @@ -40,33 +53,92 @@ class Role extends MetadataType { rightOperand: false, }, }; - const results = await new Promise((resolve) => { - this.client.SoapClient.retrieve('Role', fields, options, (error, response) => { - if (error) { - throw new Error(error); - } else { - resolve(response.body); - } - }); - }); + if (key) { + // move original filter down one level into rightOperand and add key filter into leftOperand + /** @type {SoapSDKFilterSimple} */ + const keyFilter = { + leftOperand: 'CustomerKey', + operator: 'equals', + rightOperand: key, + }; + requestParams = { + filter: { + leftOperand: keyFilter, + operator: 'AND', + rightOperand: requestParams.filter, + }, + }; + } + + const results = await this.client.soap.retrieve('Role', fields, requestParams); + const parsed = this.parseResponseBody(results); if (retrieveDir) { - const savedMetadata = await this.saveResults(parsed, retrieveDir, null); + const savedMetadata = await super.saveResults(parsed, retrieveDir, null); Util.logger.info( - `Downloaded: ${this.definition.type} (${Object.keys(savedMetadata).length})` + `Downloaded: ${this.definition.type} (${Object.keys(savedMetadata).length})` + + Util.getKeysString(key) ); - if (this.properties.metaDataTypes.documentOnRetrieve.includes(this.definition.type)) { - await this.document(buObject, savedMetadata); - } + + await this.runDocumentOnRetrieve(key, savedMetadata); } + + await this.cacheDefaultRolesAndTimezones(parsed); + return { metadata: parsed, type: this.definition.type }; } + + /** + * adds default roles to the list of retrieved roles for proper caching (but not storing) + * also caches available timezones for retrieve-user + * + * @param {MetadataTypeMap} parsed list or previously retrieved items as reference + */ + static async cacheDefaultRolesAndTimezones(parsed) { + // retrieve "Marketing Cloud%" roles not returned by SOAP API for cache (required by retrieve-user) + // also cache available timezones for retrieve-user + Util.logger.info(Util.getGrayMsg(' - Caching default roles and timezones')); + const { roles, timeZones } = await this.client.rest.get( + '/platform/v1/setup/quickflow/data' + ); + // this endpoint does not provide keys + const roleNameKeyMap = { + 'Marketing Cloud Administrator': 'SYS_DEF_IMHADMIN', + 'Marketing Cloud Channel Manager': 'SYS_DEF_CHANNELMANAGER', + 'Marketing Cloud Content Editor/Publisher': 'SYS_DEF_CONTENTEDIT', + 'Marketing Cloud Security Administrator': 'SYS_DEF_SECURITYADMIN', + 'Marketing Cloud Viewer': 'SYS_DEF_VIEWER', + }; + for (const role of roles) { + if (roleNameKeyMap[role.roleName]) { + parsed[roleNameKeyMap[role.roleName]] = { + CustomerKey: roleNameKeyMap[role.roleName], + Name: role.roleName, + ObjectID: role.roleID, + Desscription: role.description, + CreatedDate: '2012-02-21T02:09:19.983', + IsSystemDefined: true, + c__notAssignable: true, + }; + } + } + // the languages object is incomplete. the actual list is much longer --> ignoring it here + // convert timeZones to object + const timeZonesObj = {}; + for (const timeZone of timeZones) { + timeZonesObj[timeZone.id] = timeZone; + } + // cache timeZones to share it with other type-classes + cache.setMetadata('_timezone', timeZonesObj); + } + /** * Gets executed before deploying metadata - * @param {Object} metadata a single metadata item - * @returns {Promise<Object>} Promise of a single metadata item + * + * @param {MetadataTypeItem} metadata a single metadata item + * @returns {MetadataTypeItem} Promise of a single metadata item */ - static async preDeployTasks(metadata) { + static preDeployTasks(metadata) { if (this.definition.deployBlacklist.includes(metadata.CustomerKey)) { throw new Error( `Skipped ${metadata.Name} (${metadata.CustomerKey}) because its CustomerKey is reserved for a default system role.` @@ -77,7 +149,8 @@ class Role extends MetadataType { /** * Create a single Role. - * @param {Object} metadata single metadata entry + * + * @param {MetadataTypeItem} metadata single metadata entry * @returns {Promise} Promise */ static create(metadata) { @@ -86,7 +159,8 @@ class Role extends MetadataType { /** * Updates a single Role. - * @param {Object} metadata single metadata entry + * + * @param {MetadataTypeItem} metadata single metadata entry * @returns {Promise} Promise */ static update(metadata) { @@ -95,12 +169,12 @@ class Role extends MetadataType { /** * Creates markdown documentation of all roles - * @param {Object} buObject properties for auth - * @param {Object} [metadata] role definitions - * @returns {Promise<void>} - + * + * @param {MetadataTypeMap} [metadata] role definitions + * @returns {Promise.<void>} - */ - static async document(buObject, metadata) { - if (buObject.eid !== buObject.mid) { + static async document(metadata) { + if (this.buObject.eid !== this.buObject.mid) { Util.logger.error( `Roles can only be retrieved & documented for the ${Util.parentBuName}` ); @@ -108,31 +182,42 @@ class Role extends MetadataType { } if (!metadata) { try { - metadata = this.readBUMetadataForType( - File.normalizePath([ - this.properties.directories.retrieve, - buObject.credential, - Util.parentBuName, - ]), - true + metadata = ( + await this.readBUMetadataForType( + File.normalizePath([ + this.properties.directories.retrieve, + this.buObject.credential, + Util.parentBuName, + ]), + true + ) ).role; } catch (ex) { Util.logger.error(ex.message); return; } } - const directory = this.properties.directories.roles; + const directory = File.normalizePath([this.properties.directories.docs, 'role']); // initialize permission object this.allPermissions = {}; // traverse all permissions recursively and write them into allPermissions object once it has reached the end for (const role in metadata) { - metadata[role].PermissionSets.PermissionSet.forEach((element) => { - this._traverseRoles(role, element); - }); + // filter standard rules + if ( + this.properties.options?.documentStandardRoles === false && + 'string' === typeof metadata[role]?.CustomerKey && // key could be numeric + metadata[role].CustomerKey.startsWith('SYS_DEF') + ) { + delete metadata[role]; + } else { + for (const element of metadata[role].PermissionSets.PermissionSet) { + this._traverseRoles(role, element); + } + } } // Create output markdown - let output = `# Permission Overview - ${buObject.credential}\n\n`; + let output = `# Permission Overview - ${this.buObject.credential}\n\n`; output += `> **Legend** > > <hr> @@ -143,7 +228,7 @@ class Role extends MetadataType { > > **+** = _Allow_: User has access to the application or functionality > -> **•** = _Not Set_: User permission for this app or functionality is not explicitely granted nor denied, but defaults to Deny +> ** •** = _Not Set_: User permission for this app or functionality is not explicitely granted nor denied, but defaults to Deny > > **-** = _Deny_: User does not have access to the app or functionality > @@ -156,7 +241,7 @@ class Role extends MetadataType { let separator = '| --- |'; for (const role in metadata) { output += - metadata[role].IsSystemDefined === 'true' + metadata[role].IsSystemDefined === true ? ` [${metadata[role].Name}] |` : ` ${metadata[role].Name} |`; separator += ' --- |'; @@ -167,14 +252,14 @@ class Role extends MetadataType { for (const permission in this.allPermissions[permGroup]) { output += '| ' + permission + ' |'; for (const role in this.allPermissions[permGroup][permission]) { - if (this.allPermissions[permGroup][permission][role] === 'true') { + if (this.allPermissions[permGroup][permission][role] === true) { output += ' + |'; - } else if (this.allPermissions[permGroup][permission][role] === 'false') { + } else if (this.allPermissions[permGroup][permission][role] === false) { output += ' - |'; } else if ( 'undefined' === typeof this.allPermissions[permGroup][permission][role] ) { - output += ' • |'; + output += ' • |'; } else { output += ' ' + this.allPermissions[permGroup][permission][role] + ' |'; } @@ -184,16 +269,12 @@ class Role extends MetadataType { output += '\n'; } try { - const filename = buObject.credential; - // ensure docs/roles folder is existing (depends on setup in .mcdevrc.json) - if (!File.existsSync(directory)) { - File.mkdirpSync(directory); - } + const filename = this.buObject.credential; // write to disk await File.writeToFile(directory, filename + '.roles', 'md', output); - Util.logger.info(`Created ${directory}${filename}.roles.md`); + Util.logger.info(`Created ${File.normalizePath([directory, filename])}.roles.md`); if (['html', 'both'].includes(this.properties.options.documentType)) { - Util.logger.warn('HTML-based documentation of roles currently not supported.'); + Util.logger.warn(' - HTML-based documentation of roles currently not supported.'); } } catch (ex) { Util.logger.error(`Roles.document():: error | `, ex.message); @@ -207,63 +288,62 @@ class Role extends MetadataType { * @param {string} role name of the user role * @param {object} element data of the permission * @param {string} [permission] name of the permission - * @param {string} [isAllowed] "true" / "false" from the + * @param {string} [isAllowed] "true" / "false" from the parent * @memberof Role * @returns {void} */ static _traverseRoles(role, element, permission, isAllowed) { - let _permission; - if (permission) { - _permission = permission + ' > ' + element.Name; - } else { - _permission = element.Name; - } + const _permission = permission ? permission + ' > ' + element.Name : element.Name; // Reached end: write permission into this.allPermissions if (element.Operation) { const permSplit = _permission.split(' > '); - const basePermission = permSplit.shift(); - const permissionName = permSplit.join(' > '); + const permOperation = permSplit.pop(); + let basePermission = permSplit.shift(); + if (basePermission === 'Interactive Marketing Hub') { + basePermission = 'Salesforce Marketing Cloud'; + } + const permissionName = `<nobr><b>${permSplit.join( + ' > ' + )}</b> > ${permOperation}</nobr>`; if (!this.allPermissions[basePermission]) { this.allPermissions[basePermission] = {}; } if (!this.allPermissions[basePermission][permissionName]) { this.allPermissions[basePermission][permissionName] = {}; } - this.allPermissions[basePermission][permissionName][role] = element.IsAllowed - ? element.IsAllowed - : isAllowed; + this.allPermissions[basePermission][permissionName][role] = + element.IsAllowed || isAllowed; // Not at end: Traverse more } else if (element.PermissionSets) { if (Array.isArray(element.PermissionSets.PermissionSet)) { - element.PermissionSets.PermissionSet.forEach((nextElement) => { + for (const nextElement of element.PermissionSets.PermissionSet) { this._traverseRoles(role, nextElement, _permission); - }); + } } else { this._traverseRoles( role, element.PermissionSets.PermissionSet, _permission, - element.IsAllowed, - isAllowed + element.IsAllowed || isAllowed ); } // Not at end: Traverse more } else if (element.Permissions) { if (Array.isArray(element.Permissions.Permission)) { - element.Permissions.Permission.forEach((nextElement) => { + for (const nextElement of element.Permissions.Permission) { this._traverseRoles( role, nextElement, _permission, - element.IsAllowed ? element.IsAllowed : isAllowed + element.IsAllowed || isAllowed ); - }); + } } else { this._traverseRoles( role, element.Permissions.Permission, _permission, - element.IsAllowed ? element.IsAllowed : isAllowed + element.IsAllowed || isAllowed ); } } @@ -271,8 +351,7 @@ class Role extends MetadataType { } // Assign definition to static attributes -Role.definition = require('../MetadataTypeDefinitions').role; -Role.cache = {}; -Role.client = undefined; +import MetadataTypeDefinitions from '../MetadataTypeDefinitions.js'; +Role.definition = MetadataTypeDefinitions.role; -module.exports = Role; +export default Role; diff --git a/lib/metadataTypes/Script.js b/lib/metadataTypes/Script.js index 664bb76f2..eaec397c3 100644 --- a/lib/metadataTypes/Script.js +++ b/lib/metadataTypes/Script.js @@ -1,98 +1,108 @@ 'use strict'; -const MetadataType = require('./MetadataType'); -const Util = require('../util/util'); -const File = require('../util/file'); -const Mustache = require('mustache'); +import MetadataType from './MetadataType.js'; +import { Util } from '../util/util.js'; +import File from '../util/file.js'; +import ReplaceCbReference from '../util/replaceContentBlockReference.js'; /** - * @typedef {Object} ScriptItem - * @property {string} name name - * @property {string} key key - * @property {string} description - - * @property {string} createdDate e.g. "2020-09-14T01:42:03.017" - * @property {string} modifiedDate e.g. "2020-09-14T01:42:03.017" - * @property {string} [script] contains script with line breaks converted to '\n'. The content is extracted during retrieval and written into a separate *.ssjs file - * @property {string} [categoryId] holds folder ID, replaced with r__folder_Path during retrieve - * @property {string} r__folder_Path folder path in which this DE is saved - * - * @typedef {Object.<string, ScriptItem>} ScriptMap - * - * @typedef {Object} CodeExtractItem - * @property {ScriptItem} json metadata of one item w/o code - * @property {MetadataType.CodeExtract[]} codeArr list of code snippets in this item - * @property {string[]} subFolder mostly set to null, otherwise list of subfolders + * @typedef {import('../../types/mcdev.d.js').BuObject} BuObject + * @typedef {import('../../types/mcdev.d.js').CodeExtract} CodeExtract + * @typedef {import('../../types/mcdev.d.js').CodeExtractItem} CodeExtractItem + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItem} MetadataTypeItem + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItemDiff} MetadataTypeItemDiff + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItemObj} MetadataTypeItemObj + * @typedef {import('../../types/mcdev.d.js').MetadataTypeMap} MetadataTypeMap + * @typedef {import('../../types/mcdev.d.js').MetadataTypeMapObj} MetadataTypeMapObj + * @typedef {import('../../types/mcdev.d.js').SoapRequestParams} SoapRequestParams + * @typedef {import('../../types/mcdev.d.js').TemplateMap} TemplateMap + * @typedef {import('../../types/mcdev.d.js').ContentBlockConversionTypes} ContentBlockConversionTypes + */ + +/** + * @typedef {import('../../types/mcdev.d.js').ScriptItem} ScriptItem + * @typedef {import('../../types/mcdev.d.js').ScriptMap} ScriptMap */ /** * Script MetadataType + * * @augments MetadataType */ class Script extends MetadataType { /** * Retrieves Metadata of Script * Endpoint /automation/v1/scripts/ return all Scripts with all details. - * @param {string} retrieveDir Directory where retrieved metadata directory will be saved - * @returns {Promise<{metadata:ScriptMap,type:string}>} Promise + * + * @param {string} [retrieveDir] Directory where retrieved metadata directory will be saved + * @param {void | string[]} [_] unused parameter + * @param {void | string[]} [__] unused parameter + * @param {string} [key] customer key of single item to retrieve + * @returns {Promise.<{metadata: ScriptMap, type: string}>} Promise */ - static async retrieve(retrieveDir) { + static async retrieve(retrieveDir, _, __, key) { await File.initPrettier('ssjs'); - return super.retrieveREST(retrieveDir, '/automation/v1/scripts/', null); + return super.retrieveREST(retrieveDir, '/automation/v1/scripts/', null, key); } + /** * Retrieves script metadata for caching - * @returns {Promise<{metadata:ScriptMap,type:string}>} Promise + * + * @returns {Promise.<{metadata: ScriptMap, type: string}>} Promise */ static async retrieveForCache() { - return super.retrieveREST(null, '/automation/v1/scripts/', null); + return super.retrieveREST(null, '/automation/v1/scripts/'); } /** * Retrieve a specific Script by Name + * + * @deprecated Use `retrieve` followed by `build` instead. `retrieveAsTemplate` will be removed in a future version. * @param {string} templateDir Directory where retrieved metadata directory will be saved * @param {string} name name of the metadata file - * @param {Util.TemplateMap} templateVariables variables to be replaced in the metadata - * @returns {Promise<{metadata:ScriptMap,type:string}>} Promise + * @param {TemplateMap} templateVariables variables to be replaced in the metadata + * @returns {Promise.<{metadata: ScriptItem, type: string}>} Promise */ static async retrieveAsTemplate(templateDir, name, templateVariables) { + Util.logDeprecated('retrieveAsTemplate', `'retrieve' followed by 'build'`); await File.initPrettier('ssjs'); return super.retrieveREST( templateDir, - '/automation/v1/scripts/?$filter=name%20eq%20' + name.split(' ').join('%20'), - null, + '/automation/v1/scripts/?$filter=name%20eq%20' + encodeURIComponent(name), templateVariables ); } - /** - * manages post retrieve steps - * @param {ScriptItem} metadata a single script - * @param {string} [_] unused - * @param {boolean} [isTemplating] signals that we are retrieving templates - * @returns {CodeExtractItem} Array with one metadata object and one ssjs string - */ - static postRetrieveTasks(metadata, _, isTemplating) { - // if retrieving template, replace the name with customer key if that wasn't already the case - if (isTemplating) { - const warningMsg = - 'Ensure that Automations using this script are updated with the new script-key before deployment.'; - this.overrideKeyWithName(metadata, warningMsg); - } - return this.parseMetadata(metadata); - } - /** * Updates a single Script - * @param {Object} script a single Script + * + * @param {MetadataTypeItem} script a single Script * @returns {Promise} Promise */ static update(script) { return super.updateREST(script, '/automation/v1/scripts/' + script.ssjsActivityId); } + /** + * helper for {@link MetadataType.updateREST} and {@link MetadataType.updateSOAP} + * + * @param {MetadataTypeItem} metadataEntry a single metadata Entry + * @param {object} apiResponse varies depending on the API call + * @returns {Promise.<object>} apiResponse, potentially modified + */ + static async postUpdateTasks(metadataEntry, apiResponse) { + // script update endpoint returns wrong values for createdDate and modifiedDate - need to re-retrieve to get correct values + const ssjsActivityId = apiResponse?.ssjsActivityId; + if (ssjsActivityId) { + apiResponse = await this.client.rest.get('/automation/v1/scripts/' + ssjsActivityId); + } + return apiResponse; + } + /** * Creates a single Script - * @param {Object} script a single Script + * + * @param {MetadataTypeItem} script a single Script * @returns {Promise} Promise */ static create(script) { @@ -100,14 +110,15 @@ class Script extends MetadataType { } /** - * helper for this.preDeployTasks() that loads extracted code content back into JSON + * helper for {@link Script.preDeployTasks} that loads extracted code content back into JSON + * * @param {ScriptItem} metadata a single asset definition * @param {string} deployDir directory of deploy files * @param {string} [templateName] name of the template used to built defintion (prior applying templating) - * @returns {Promise<String>} content for metadata.script + * @returns {Promise.<string>} content for metadata.script */ static async _mergeCode(metadata, deployDir, templateName) { - templateName = templateName || metadata.key; + templateName ||= metadata[this.definition.keyField]; let code; const codePath = File.normalizePath([ deployDir, @@ -115,15 +126,15 @@ class Script extends MetadataType { templateName + '.' + this.definition.type + '-meta', ]); - if (File.existsSync(codePath + '.ssjs')) { - code = await File.readFile( + if (await File.pathExists(codePath + '.ssjs')) { + code = await File.readFilteredFilename( [deployDir, this.definition.type], templateName + '.' + this.definition.type + '-meta', 'ssjs' ); - code = `<script runat="server">\n${code}</script>`; - } else if (File.existsSync(codePath + '.html')) { - code = await File.readFile( + code = `<script runat="server">\n${code.trim()}\n</script>`; + } else if (await File.pathExists(codePath + '.html')) { + code = await File.readFilteredFilename( [deployDir, this.definition.type], templateName + '.' + this.definition.type + '-meta', 'html' @@ -133,26 +144,17 @@ class Script extends MetadataType { } return code; } + /** * prepares a Script for deployment + * * @param {ScriptItem} metadata a single script activity definition * @param {string} dir directory of deploy files - * @returns {ScriptItem} Promise + * @returns {Promise.<ScriptItem>} Promise */ static async preDeployTasks(metadata, dir) { // folder - try { - metadata.categoryId = Util.getFromCache( - this.cache, - 'folder', - metadata.r__folder_Path, - 'Path', - 'ID' - ); - delete metadata.r__folder_Path; - } catch (ex) { - Util.logger.error(`Script '${metadata.key}': ${ex.message}`); - } + super.setFolderId(metadata); // code metadata.script = await this._mergeCode(metadata, dir); @@ -161,102 +163,285 @@ class Script extends MetadataType { } /** - * helper for buildDefinition + * helper for {@link MetadataType.buildDefinition} * handles extracted code if any are found for complex types + * * @param {string} templateDir Directory where metadata templates are stored * @param {string|string[]} targetDir (List of) Directory where built definitions will be saved * @param {ScriptItem} metadata main JSON file that was read from file system - * @param {Util.TemplateMap} variables variables to be replaced in the metadata + * @param {TemplateMap} templateVariables variables to be replaced in the metadata * @param {string} templateName name of the template to be built - * @returns {Promise} Promise + * @returns {Promise.<string[][]>} list of extracted files with path-parts provided as an array */ - static async buildDefinitionForExtracts( + static buildDefinitionForNested( templateDir, targetDir, metadata, - variables, + templateVariables, templateName + ) { + return this._buildForNested( + templateDir, + targetDir, + metadata, + templateVariables, + templateName, + 'definition' + ); + } + + /** + * helper for {@link MetadataType.buildTemplate} + * handles extracted code if any are found for complex types + * + * @example scripts are saved as 1 json and 1 ssjs file. both files need to be run through templating + * @param {string} templateDir Directory where metadata templates are stored + * @param {string|string[]} targetDir (List of) Directory where built definitions will be saved + * @param {ScriptItem} metadata main JSON file that was read from file system + * @param {TemplateMap} templateVariables variables to be replaced in the metadata + * @param {string} templateName name of the template to be built + * @returns {Promise.<string[][]>} list of extracted files with path-parts provided as an array + */ + static buildTemplateForNested( + templateDir, + targetDir, + metadata, + templateVariables, + templateName + ) { + return this._buildForNested( + templateDir, + targetDir, + metadata, + templateVariables, + templateName, + 'template' + ); + } + + /** + * helper for {@link Script.buildTemplateForNested} / {@link Script.buildDefinitionForNested} + * handles extracted code if any are found for complex types + * + * @param {string} templateDir Directory where metadata templates are stored + * @param {string|string[]} targetDir (List of) Directory where built definitions will be saved + * @param {ScriptItem} metadata main JSON file that was read from file system + * @param {TemplateMap} templateVariables variables to be replaced in the metadata + * @param {string} templateName name of the template to be built + * @param {'definition'|'template'} mode defines what we use this helper for + * @returns {Promise.<string[][]>} list of extracted files with path-parts provided as an array + */ + static async _buildForNested( + templateDir, + targetDir, + metadata, + templateVariables, + templateName, + mode ) { // get SSJS from filesystem let code = await this._mergeCode(metadata, templateDir, templateName); - // replace template variables with their values + // try to remove script tags and decide on file extension (html/ssjs) + const file = this.prepExtractedCode(code, metadata.name); + const fileExt = file.fileExt; + code = fileExt === 'ssjs' ? file.code.replace(/^\n/, '') : file.code; + // apply templating try { - code = Mustache.render(code, variables); - } catch (ex) { - Util.logger.debug('script.buildDefinitionForExtracts: ' + ex.message); + if (mode === 'definition') { + // replace template variables with their values + code = this.applyTemplateValues(code, templateVariables); + } else if (mode === 'template') { + // replace template values with corresponding variable names + code = this.applyTemplateNames(code, templateVariables); + } + } catch { throw new Error( `${this.definition.type}:: Error applying template variables on ${ - metadata[this.definition.keyField] + '.' + this.definition.type + templateName + '.' + this.definition.type }-meta.ssjs.` ); } // write to file const targetDirArr = Array.isArray(targetDir) ? targetDir : [targetDir]; + const nestedFilePaths = []; + + // keep old name if creating templates, otherwise use new name + const fileName = mode === 'definition' ? metadata[this.definition.keyField] : templateName; for (const targetDir of targetDirArr) { File.writeToFile( [targetDir, this.definition.type], - metadata[this.definition.keyField] + '.' + this.definition.type + '-meta', - 'ssjs', + fileName + '.' + this.definition.type + '-meta', + fileExt, code ); + nestedFilePaths.push([ + targetDir, + this.definition.type, + fileName + '.' + this.definition.type + '-meta.' + fileExt, + ]); } + return nestedFilePaths; } /** - * Splits the script metadata into two parts and parses in a standard manner - * @param {ScriptItem} metadata a single script activity definition + * manages post retrieve steps + * + * @param {ScriptItem} metadata a single item * @returns {CodeExtractItem} a single item with code parts extracted */ - static parseMetadata(metadata) { + static postRetrieveTasks(metadata) { // folder - try { - metadata.r__folder_Path = Util.getFromCache( - this.cache, - 'folder', - metadata.categoryId, - 'ID', - 'Path' - ); - delete metadata.categoryId; - } catch (ex) { - Util.logger.warn(`Script '${metadata.key}': ${ex.message}`); - } + super.setFolderPath(metadata); + return this.getCodeExtractItem(metadata); + } + + /** + * manages post retrieve steps + * + * @param {ScriptItem} metadata a single item + * @returns {CodeExtractItem} a single item with code parts extracted + */ + static getCodeExtractItem(metadata) { // extract SSJS const codeArr = []; // keep between tags - const regex = /<\s*script .*?>(.+?)<\s*\/script>/gms; - let ssjs; - let fileExt; - const regexMatches = regex.exec(metadata.script); - if (regexMatches && regexMatches.length > 1) { - ssjs = regexMatches[1]; - fileExt = 'ssjs'; - } else { - ssjs = metadata.script; - fileExt = 'html'; - Util.logger.warn( - 'Script.parseMetadata:: Could not find script tags, saving whole text in SSJS: ' + - metadata.name - ); - } + const { fileExt, code } = this.prepExtractedCode(metadata.script, metadata.name); delete metadata.script; codeArr.push({ subFolder: null, - fileName: metadata.key, + fileName: metadata[this.definition.keyField], fileExt: fileExt, - content: ssjs, + content: code, }); return { json: metadata, codeArr: codeArr, subFolder: null }; } + + /** + * helper for {@link Script.postRetrieveTasks} and {@link Script._buildForNested} + * + * @param {string} metadataScript the code of the file + * @param {string} metadataName the name of the metadata + * @returns {{fileExt:string,code:string}} returns found extension and file content + */ + static prepExtractedCode(metadataScript, metadataName) { + let code; + let fileExt; + const ssjs = Util.getSsjs(metadataScript); + if (ssjs) { + code = ssjs; + fileExt = 'ssjs'; + } else { + code = metadataScript; + fileExt = 'html'; + Util.logger.verbose( + ` - Could not find script tags, saving code in ${metadataName}.script-meta.html instead of as SSJS file.` + ); + } + return { fileExt, code }; + } + + /** + * should return only the json for all but asset, query and script that are saved as multiple files + * additionally, the documentation for dataExtension and automation should be returned + * + * @param {string[]} keyArr customerkey of the metadata + * @returns {Promise.<string[]>} list of all files that need to be committed in a flat array ['path/file1.ext', 'path/file2.ext'] + */ + static async getFilesToCommit(keyArr) { + const path = File.normalizePath([ + this.properties.directories.retrieve, + this.buObject.credential, + this.buObject.businessUnit, + this.definition.type, + ]); + + const fileList = keyArr.flatMap((key) => [ + File.normalizePath([path, `${key}.${this.definition.type}-meta.json`]), + File.normalizePath([path, `${key}.${this.definition.type}-meta.ssjs`]), + File.normalizePath([path, `${key}.${this.definition.type}-meta.html`]), + ]); + return fileList; + } + + /** + * helper to allow us to select single metadata entries via REST + * + * @private + * @param {string} key customer key + * @returns {Promise.<string>} objectId or enpty string + */ + static async _getObjectIdForSingleRetrieve(key) { + const name = key.startsWith('name:') ? key.slice(5) : null; + const filter = name + ? '?$filter=name%20eq%20' + encodeURIComponent(name) + : '?$filter=key%20eq%20' + encodeURIComponent(key); + const results = await this.client.rest.get('/automation/v1/scripts/' + filter); + const items = results?.items || []; + const found = items.find((item) => + name ? item[this.definition.nameField] === name : item[this.definition.keyField] === key + ); + return found?.ssjsActivityId || null; + } + + /** + * Delete a metadata item from the specified business unit + * + * @param {string} key Identifier of data extension + * @returns {Promise.<boolean>} deletion success flag + */ + static async deleteByKey(key) { + // delete only works with the query's object id + const objectId = key ? await this._getObjectIdForSingleRetrieve(key) : null; + if (!objectId) { + await this.deleteNotFound(key); + return false; + } + return super.deleteByKeyREST('/automation/v1/scripts/' + objectId, key); + } + + /** + * clean up after deleting a metadata item + * + * @param {string} customerKey Identifier of metadata item + * @returns {Promise.<void>} - + */ + static async postDeleteTasks(customerKey) { + // delete local copy: retrieve/cred/bu/.../...-meta.json + // delete local copy: retrieve/cred/bu/.../...-meta.ssjs + // delete local copy: retrieve/cred/bu/.../...-meta.html + await super.postDeleteTasks(customerKey, [ + `${this.definition.type}-meta.ssjs`, + `${this.definition.type}-meta.html`, + ]); + } + + /** + * + * @param {MetadataTypeItem} item single metadata item + * @param {string} retrieveDir directory where metadata is saved + * @param {Set.<string>} [findAssetKeys] list of keys that were found referenced via ContentBlockByX; if set, method only gets keys and runs no updates + * @returns {Promise.<CodeExtractItem>} key of the item that was updated + */ + static async replaceCbReference(item, retrieveDir, findAssetKeys) { + const parentName = `${this.definition.type} ${item[this.definition.keyField]}`; + + const code = await this._mergeCode(item, retrieveDir); + + item.script = ReplaceCbReference.replaceReference(code, parentName, findAssetKeys); + + // *** finish *** + // replaceReference will throw an error if nothing was updated which will end execution here + // no error means we have a new item to deploy and need to update the item in our retrieve folder + return this.getCodeExtractItem(item); + } } // Assign definition & cache to static attributes -Script.definition = require('../MetadataTypeDefinitions').script; -Script.cache = {}; -Script.client = undefined; +import MetadataTypeDefinitions from '../MetadataTypeDefinitions.js'; +Script.definition = MetadataTypeDefinitions.script; -module.exports = Script; +export default Script; diff --git a/lib/metadataTypes/SendClassification.js b/lib/metadataTypes/SendClassification.js new file mode 100644 index 000000000..66dc0b113 --- /dev/null +++ b/lib/metadataTypes/SendClassification.js @@ -0,0 +1,223 @@ +'use strict'; + +import MetadataType from './MetadataType.js'; +import SenderProfile from './SenderProfile.js'; +import { Util } from '../util/util.js'; +import cache from '../util/cache.js'; + +/** + * @typedef {import('../../types/mcdev.d.js').BuObject} BuObject + * @typedef {import('../../types/mcdev.d.js').CodeExtract} CodeExtract + * @typedef {import('../../types/mcdev.d.js').CodeExtractItem} CodeExtractItem + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItem} MetadataTypeItem + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItemDiff} MetadataTypeItemDiff + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItemObj} MetadataTypeItemObj + * @typedef {import('../../types/mcdev.d.js').MetadataTypeMap} MetadataTypeMap + * @typedef {import('../../types/mcdev.d.js').MetadataTypeMapObj} MetadataTypeMapObj + * @typedef {import('../../types/mcdev.d.js').SoapRequestParams} SoapRequestParams + * @typedef {import('../../types/mcdev.d.js').TemplateMap} TemplateMap + */ + +/** + * SendClassification MetadataType + * + * @augments MetadataType + */ +class SendClassification extends MetadataType { + /** + * Retrieves SOAP based metadata of metadata type into local filesystem. executes callback with retrieved metadata + * + * @param {string} retrieveDir Directory where retrieved metadata directory will be saved + * @param {void | string[]} [_] unused parameter + * @param {void | string[]} [__] unused parameter + * @param {string} [key] customer key of single item to retrieve + * @returns {Promise.<MetadataTypeMapObj>} Promise of metadata + */ + static retrieve(retrieveDir, _, __, key) { + /** @type {SoapRequestParams} */ + let requestParams = null; + if (key) { + requestParams = { + filter: { + leftOperand: 'CustomerKey', + operator: 'equals', + rightOperand: key, + }, + }; + } + return super.retrieveSOAP(retrieveDir, requestParams, key); + } + + /** + * Retrieves event definition metadata for caching + * + * @returns {Promise.<MetadataTypeMapObj>} Promise of metadata + */ + static async retrieveForCache() { + const typeMap = await this.retrieve(null); + if (cache.getCache().deliveryProfile) { + for (const item of Object.values(typeMap.metadata)) { + // run postRetrieveTasks to cross-update deliveryProfile cache + this.updateDeliveryProfileIdInCache(item); + } + } + return typeMap; + } + + /** + * Updates a single item + * + * @param {MetadataTypeItem} metadataItem a single item + * @returns {Promise} Promise + */ + static update(metadataItem) { + return super.updateSOAP(metadataItem); + } + + /** + * Creates a single item + * + * @param {MetadataTypeItem} metadataItem a single item + * @returns {Promise} Promise + */ + static create(metadataItem) { + return super.createSOAP(metadataItem); + } + + /** + * Delete a metadata item from the specified business unit + * + * @param {string} key Identifier of data extension + * @returns {Promise.<boolean>} deletion success status + */ + static deleteByKey(key) { + return super.deleteByKeySOAP(key, undefined, 24100); + } + + /** + * prepares a import definition for deployment + * + * @param {MetadataTypeItem} metadata a single importDef + * @returns {Promise.<MetadataTypeItem>} Promise + */ + static async preDeployTasks(metadata) { + metadata.SendClassificationType = + this.definition.sendClassificationTypeMapping[metadata.c__classification]; + delete metadata.c__classification; + + const spId = cache.searchForField( + 'senderProfile', + metadata.r__senderProfile_key, + 'CustomerKey', + 'ObjectID' + ); + const sp = cache.getByKey('senderProfile', metadata.r__senderProfile_key); + SenderProfile.verifySenderEmailAddresses(sp, metadata, this.definition); + metadata.SenderProfile = { + ObjectID: spId, + CustomerKey: metadata.r__senderProfile_key, + }; + delete metadata.r__senderProfile_key; + + const dpId = cache.searchForField( + 'deliveryProfile', + metadata.r__deliveryProfile_key, + 'key', + 'ObjectID' + ); + metadata.DeliveryProfile = { + ObjectID: dpId, + CustomerKey: metadata.r__deliveryProfile_key, + }; + delete metadata.r__deliveryProfile_key; + + return metadata; + } + + /** + * Gets executed after deployment of metadata type + * + * @param {MetadataTypeMap} upsertResults metadata mapped by their keyField as returned by update/create + * @returns {Promise.<void>} - + */ + static async postDeployTasks(upsertResults) { + // re-retrieve all upserted items to ensure we have all fields (createdDate and modifiedDate are otherwise not present) + Util.logger.debug( + `Caching all ${this.definition.type} post-deploy to ensure we have all fields` + ); + const typeCache = await this.retrieveForCache(); + // update values in upsertResults with retrieved values before saving to disk + for (const key of Object.keys(upsertResults)) { + if (typeCache.metadata[key]) { + upsertResults[key] = typeCache.metadata[key]; + } + } + } + + /** + * manages post retrieve steps + * + * @param {MetadataTypeItem} metadata a single item + * @returns {MetadataTypeItem} parsed metadata + */ + static postRetrieveTasks(metadata) { + metadata.c__classification = Util.inverseGet( + this.definition.sendClassificationTypeMapping, + metadata.SendClassificationType + ); + delete metadata.SendClassificationType; + + // when sendClassification was only cached it can happen that we don't have the senderProfile cache yet + try { + metadata.r__senderProfile_key = cache.searchForField( + 'senderProfile', + metadata.SenderProfile.ObjectID, + 'ObjectID', + 'CustomerKey' + ); + delete metadata.SenderProfile; + const sp = cache.getByKey('senderProfile', metadata.r__senderProfile_key); + SenderProfile.verifySenderEmailAddresses(sp, metadata, this.definition); + } catch (ex) { + Util.logger.warn(` - ${this.definition.type} ${metadata.CustomerKey}: ${ex.message}`); + } + try { + metadata.r__deliveryProfile_key = cache.searchForField( + 'deliveryProfile', + metadata.DeliveryProfile.CustomerKey, + 'key', + 'key' + ); + // add ObjectID to deliveryProfile cache because it cannot be retrieved any other way and this way we can resolve it in journeys + this.updateDeliveryProfileIdInCache(metadata); + + delete metadata.DeliveryProfile; + } catch (ex) { + Util.logger.warn(` - ${this.definition.type} ${metadata.CustomerKey}: ${ex.message}`); + } + + return metadata; + } + + /** + * this is the only known way to get the object ID for a deliveryProfile + * + * @param {MetadataTypeItem} metadata a single sendClassification item + */ + static updateDeliveryProfileIdInCache(metadata) { + const dp = cache.getByKey('deliveryProfile', metadata.DeliveryProfile.CustomerKey); + if (dp) { + dp.ObjectID = metadata.DeliveryProfile.ObjectID; + } else { + Util.logger.debug( + ` - ${this.definition.type} ${metadata.CustomerKey}: Could not find deliveryProfile ${metadata.DeliveryProfile.CustomerKey} in cache` + ); + } + } +} + +// Assign definition to static attributes +import MetadataTypeDefinitions from '../MetadataTypeDefinitions.js'; +SendClassification.definition = MetadataTypeDefinitions.sendClassification; + +export default SendClassification; diff --git a/lib/metadataTypes/SenderProfile.js b/lib/metadataTypes/SenderProfile.js new file mode 100644 index 000000000..af43452b5 --- /dev/null +++ b/lib/metadataTypes/SenderProfile.js @@ -0,0 +1,367 @@ +'use strict'; + +import MetadataType from './MetadataType.js'; +import File from '../util/file.js'; +import DomainVerification from './DomainVerification.js'; +import cache from '../util/cache.js'; +import { Util } from '../util/util.js'; +import ReplaceCbReference from '../util/replaceContentBlockReference.js'; + +/** + * @typedef {import('../../types/mcdev.d.js').BuObject} BuObject + * @typedef {import('../../types/mcdev.d.js').CodeExtract} CodeExtract + * @typedef {import('../../types/mcdev.d.js').CodeExtractItem} CodeExtractItem + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItem} MetadataTypeItem + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItemDiff} MetadataTypeItemDiff + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItemObj} MetadataTypeItemObj + * @typedef {import('../../types/mcdev.d.js').MetadataTypeMap} MetadataTypeMap + * @typedef {import('../../types/mcdev.d.js').MetadataTypeMapObj} MetadataTypeMapObj + * @typedef {import('../../types/mcdev.d.js').SoapRequestParams} SoapRequestParams + * @typedef {import('../../types/mcdev.d.js').TemplateMap} TemplateMap + */ + +/** + * SenderProfile MetadataType + * + * @augments MetadataType + */ +class SenderProfile extends MetadataType { + /** + * Retrieves SOAP based metadata of metadata type into local filesystem. executes callback with retrieved metadata + * + * @param {string} [retrieveDir] Directory where retrieved metadata directory will be saved + * @param {void | string[]} [_] unused parameter + * @param {void | string[]} [__] unused parameter + * @param {string} [key] customer key of single item to retrieve + * @returns {Promise.<MetadataTypeMapObj>} Promise of metadata + */ + static async retrieve(retrieveDir, _, __, key) { + /** @type {SoapRequestParams} */ + let requestParams; + if (key) { + requestParams = { + filter: { + leftOperand: 'CustomerKey', + operator: 'equals', + rightOperand: key, + }, + }; + } + return super.retrieveSOAP(retrieveDir, requestParams, key); + } + + /** + * Updates a single item + * + * @param {MetadataTypeItem} metadataItem a single item + * @returns {Promise} Promise + */ + static update(metadataItem) { + return super.updateSOAP(metadataItem); + } + + /** + * Creates a single item + * + * @param {MetadataTypeItem} metadataItem a single item + * @returns {Promise} Promise + */ + static create(metadataItem) { + return super.createSOAP(metadataItem); + } + + /** + * Delete a metadata item from the specified business unit + * + * @param {string} key Identifier of data extension + * @returns {Promise.<boolean>} deletion success status + */ + static deleteByKey(key) { + return super.deleteByKeySOAP(key, undefined, 40100); + } + + /** + * manages post retrieve steps + * + * @param {MetadataTypeItem} metadata a single item + * @returns {MetadataTypeItem} a single item + */ + static postRetrieveTasks(metadata) { + // makes or easier reading + if (metadata.Client) { + try { + metadata.createdBy = cache.searchForField( + 'user', + metadata.Client.CreatedBy, + 'AccountUserID', + 'Name' + ); + } catch (ex) { + Util.logger.verbose( + ` - ${this.definition.type} ${metadata[this.definition.nameField]} (${ + metadata[this.definition.keyField] + }): ${ex.message}.` + ); + } + + try { + metadata.modifiedBy = cache.searchForField( + 'user', + metadata.Client.ModifiedBy, + 'AccountUserID', + 'Name' + ); + } catch (ex) { + Util.logger.verbose( + ` - ${this.definition.type} ${metadata[this.definition.nameField]} (${ + metadata[this.definition.keyField] + }): ${ex.message}.` + ); + } + + delete metadata.Client; + } + + // check if email address is verified. Otherwise this SenderProfile (and Send Classifications using it) will not be usable in Journey Builder + this.verifySenderEmailAddresses(metadata); + + return metadata; + } + + /** + * + * @param {MetadataTypeItem} metadata a single item + * @param {MetadataTypeItem} [metadataCaller] if called from SendClassification this can be used to adjust logs + * @param {any} [definition] type defintiion from SendClassification + */ + static verifySenderEmailAddresses(metadata, metadataCaller, definition) { + if (!metadataCaller) { + metadataCaller = metadata; + } + if (!definition) { + definition = this.definition; + } + const emailsToCheck = { + FromAddress: metadata.FromAddress.trim() + '', + FallbackFromAddress: metadata.FallbackFromAddress.trim() + '', + }; + for (const [field, email] of Object.entries(emailsToCheck)) { + if (email && !email.startsWith('%%') && email.includes('@')) { + const domainVerification = cache.getByKey('domainVerification', email); + if (domainVerification) { + if (domainVerification.status !== 'Verified') { + Util.logger.warn( + Util.getMsgPrefix(definition, metadataCaller) + + `: ${field} ${email} is currently in status ${domainVerification.status}. This ${definition.typeName} will not be usable in Journey Builder. To fix, please go to Setup > Feature Settings > Email Studio > From Address Management to verify the email.` + ); + } + if (domainVerification.isSendable === false) { + Util.logger.warn( + Util.getMsgPrefix(definition, metadataCaller) + + `: ${field} ${email} is currently not sendable. This ${definition.typeName} will not be usable in Journey Builder. To auto-fix run any update on senderProfile:"${metadata[this.definition.keyField]}" via mcdev.` + ); + } + } else { + Util.logger.warn( + Util.getMsgPrefix(definition, metadataCaller) + + `: ${field} ${email} is not verified. This ${definition.typeName} will not be usable in Journey Builder. To auto-fix run any update on senderProfile:"${metadata[this.definition.keyField]}" via mcdev. Alternatively, please go to Setup > Feature Settings > Email Studio > From Address Management.` + ); + } + } + } + } + + /** + * prepares a single item for deployment + * + * @param {MetadataTypeItem} metadata a single query activity + * @returns {Promise.<MetadataTypeItem>} Promise + */ + static async preDeployTasks(metadata) { + // cleanup + delete metadata.createdBy; + delete metadata.modifiedBy; + + if ( + metadata.UseDefaultRMMRules && + (metadata.AutoForwardToEmailAddress !== '' || metadata.AutoForwardToName !== '') + ) { + Util.logger.warn( + Util.getMsgPrefix(this.definition, metadata) + + `AutoForwardToEmailAddress and AutoForwardToName will be ignored because UseDefaultRMMRules is set to true; setting UseDefaultRMMRules to false` + ); + metadata.UseDefaultRMMRules = false; + } + if (!Util.OPTIONS.matchName) { + // #4 make sure the name is unique + const thisCache = cache.getCache()[this.definition.type]; + const relevantNames = Object.keys(thisCache).map((key) => ({ + type: null, + key: key, + name: thisCache[key][this.definition.nameField], + })); + // if the name is already in the folder for a different key, add a number to the end + metadata[this.definition.nameField] = this.findUniqueName( + metadata[this.definition.keyField], + metadata[this.definition.nameField], + relevantNames + ); + } + return metadata; + } + + /** + * Gets executed after deployment of metadata type + * + * @param {MetadataTypeMap} upsertResults metadata mapped by their keyField as returned by update/create + * @returns {Promise.<void>} - + */ + static async postDeployTasks(upsertResults) { + // re-retrieve all upserted items to ensure we have all fields (createdDate and modifiedDate are otherwise not present) + Util.logger.debug( + `Caching all ${this.definition.type} post-deploy to ensure we have all fields` + ); + const domainVerificationEmails = new Set(); + + const typeCache = await this.retrieveForCache(); + // update values in upsertResults with retrieved values before saving to disk + for (const key of Object.keys(upsertResults)) { + if (typeCache.metadata[key]) { + upsertResults[key] = typeCache.metadata[key]; + } + + // ensure the FromAddress is verified or else attempt to create it + const emailsToCheck = [ + upsertResults[key].FromAddress.trim() + '', + upsertResults[key].FallbackFromAddress.trim() + '', + ]; + + for (const email of emailsToCheck) { + if (email && !email.startsWith('%%') && email.includes('@')) { + const domainVerification = cache.getByKey('domainVerification', email); + if (!domainVerification) { + domainVerificationEmails.add(email); + } + } + } + } + + if (domainVerificationEmails.size) { + Util.logger.info( + Util.getGrayMsg(`Setting up required E-Mail Addresses for Sender Profiles:`) + ); + + const domainVerificationCreateMap = {}; + for (const email of domainVerificationEmails) { + domainVerificationCreateMap[email] = { + domain: email, + isSendable: true, + }; + } + + const deployDir = File.normalizePath([ + this.properties.directories.deploy, + this.buObject.credential, + this.buObject.businessUnit, + ]); + const retrieveDir = File.normalizePath([ + this.properties.directories.retrieve, + this.buObject.credential, + this.buObject.businessUnit, + ]); + DomainVerification.buObject = this.buObject; + DomainVerification.client = this.client; + DomainVerification.properties = this.properties; + const domainVerificationCreateResult = await DomainVerification.deploy( + domainVerificationCreateMap, + deployDir, + retrieveDir + ); + cache.mergeMetadata('domainVerification', domainVerificationCreateResult); + } + } + + /** + * + * @param {MetadataTypeItem} item single metadata item + * @param {string} [_] parameter not used + * @param {Set.<string>} [findAssetKeys] list of keys that were found referenced via ContentBlockByX; if set, method only gets keys and runs no updates + * @returns {Promise.<MetadataTypeItem>} key of the item that was updated + */ + static async replaceCbReference(item, _, findAssetKeys) { + const parentName = `${this.definition.type} ${item[this.definition.keyField]}`; + let changes = false; + let error; + + // *** type specific logic *** + try { + item.FromName = ReplaceCbReference.replaceReference( + item.FromName, + parentName, + findAssetKeys + ); + changes = true; + } catch (ex) { + if (ex.code !== 200) { + error = ex; + } + } + try { + item.FromAddress = ReplaceCbReference.replaceReference( + item.FromAddress, + parentName, + findAssetKeys + ); + changes = true; + } catch (ex) { + if (ex.code !== 200) { + error = ex; + } + } + try { + item.AutoForwardToEmailAddress = ReplaceCbReference.replaceReference( + item.AutoForwardToEmailAddress, + parentName, + findAssetKeys + ); + changes = true; + } catch (ex) { + if (ex.code !== 200) { + error = ex; + } + } + try { + item.AutoForwardToName = ReplaceCbReference.replaceReference( + item.AutoForwardToName, + parentName, + findAssetKeys + ); + changes = true; + } catch (ex) { + if (ex.code !== 200) { + error = ex; + } + } + if (error) { + throw error; + } + + if (!changes) { + const ex = new Error('No changes made to the code.'); + // @ts-expect-error custom error object + ex.code = 200; + throw ex; + } + + // *** finish *** + // replaceReference will throw an error if nothing was updated which will end execution here + // no error means we have a new item to deploy and need to update the item in our retrieve folder + return item; + } +} + +// Assign definition & cache to static attributes +import MetadataTypeDefinitions from '../MetadataTypeDefinitions.js'; +SenderProfile.definition = MetadataTypeDefinitions.senderProfile; + +export default SenderProfile; diff --git a/lib/metadataTypes/SetDefinition.js b/lib/metadataTypes/SetDefinition.js deleted file mode 100644 index 9b96022f9..000000000 --- a/lib/metadataTypes/SetDefinition.js +++ /dev/null @@ -1,32 +0,0 @@ -'use strict'; - -const MetadataType = require('./MetadataType'); - -/** - * SetDefinition MetadataType - * @augments MetadataType - */ -class SetDefinition extends MetadataType { - /** - * Retrieves Metadata of schema set Definitions. - * @param {String} retrieveDir Directory where retrieved metadata directory will be saved - * @returns {Promise} Promise - */ - static retrieve(retrieveDir) { - return super.retrieveREST(retrieveDir, '/hub/v1/contacts/schema/setDefinitions', null); - } - /** - * Retrieves Metadata of schema set definitions for caching. - * @returns {Promise} Promise - */ - static retrieveForCache() { - return super.retrieveREST(null, '/hub/v1/contacts/schema/setDefinitions', null); - } -} - -// Assign definition to static attributes -SetDefinition.definition = require('../MetadataTypeDefinitions').setDefinition; -SetDefinition.cache = {}; -SetDefinition.client = undefined; - -module.exports = SetDefinition; diff --git a/lib/metadataTypes/TransactionalEmail.js b/lib/metadataTypes/TransactionalEmail.js new file mode 100644 index 000000000..989397ebe --- /dev/null +++ b/lib/metadataTypes/TransactionalEmail.js @@ -0,0 +1,307 @@ +'use strict'; + +import TransactionalMessage from './TransactionalMessage.js'; +import Journey from './Journey.js'; +import { Util } from '../util/util.js'; +import cache from '../util/cache.js'; + +/** + * @typedef {import('../../types/mcdev.d.js').BuObject} BuObject + * @typedef {import('../../types/mcdev.d.js').CodeExtract} CodeExtract + * @typedef {import('../../types/mcdev.d.js').CodeExtractItem} CodeExtractItem + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItem} MetadataTypeItem + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItemDiff} MetadataTypeItemDiff + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItemObj} MetadataTypeItemObj + * @typedef {import('../../types/mcdev.d.js').MetadataTypeMap} MetadataTypeMap + * @typedef {import('../../types/mcdev.d.js').MetadataTypeMapObj} MetadataTypeMapObj + * @typedef {import('../../types/mcdev.d.js').SoapRequestParams} SoapRequestParams + * @typedef {import('../../types/mcdev.d.js').TemplateMap} TemplateMap + */ + +/** + * TransactionalEmail MetadataType + * + * @augments TransactionalMessage + */ +class TransactionalEmail extends TransactionalMessage { + static subType = 'email'; + /** @type {Array} */ + static _createdJourneyKeys; + + /** + * Updates a single item + * + * @param {MetadataTypeItem} metadata how the item shall look after the update + * @returns {Promise} Promise + */ + static update(metadata) { + if (metadata.options?.createJourney) { + // only send this during create or else we might end up with an unexpected outcome + Util.logger.warn( + ` - ${this.definition.type} ${metadata[this.definition.nameField]} (${ + metadata[this.definition.keyField] + }): Cannot update journey link during update. If you need to relink this item to a new journey please delete and recreate it.` + ); + delete metadata.options.createJourney; + } + return super.update(metadata); + } + + /** + * Updates a single item + * + * @param {MetadataTypeItem} metadata how the item shall look after the update + * @returns {Promise} Promise + */ + static create(metadata) { + if (metadata.definitionType === 'Transactional' && metadata.channel === 'email') { + // only send this during create or else we might end up with an unexpected outcome + Util.logger.warn( + ` - ${this.definition.type} ${metadata[this.definition.nameField]} (${ + metadata[this.definition.keyField] + }): While possible, it is not recommended to create transactional journeys via transactionalEmail. Instead, create the journey and then publish it (mcdev deploy cred/bu journey --publish)` + ); + } + return super.create(metadata); + } + + /** + * prepares for deployment + * + * @param {MetadataTypeItem} metadata a single item + * @returns {Promise.<MetadataTypeItem>} - + */ + static async preDeployTasks(metadata) { + // asset + if (metadata.r__asset_key) { + // we merely want to be able to show an error if it does not exist + metadata.content = { + customerKey: cache.searchForField( + 'asset', + metadata.r__asset_key, + 'customerKey', + 'customerKey' + ), + }; + delete metadata.r__asset_key; + } + // subscriptions: dataExtension + if (metadata.subscriptions?.r__dataExtension_key) { + // we merely want to be able to show an error if it does not exist + metadata.subscriptions.dataExtension = cache.searchForField( + 'dataExtension', + metadata.subscriptions.r__dataExtension_key, + 'CustomerKey', + 'CustomerKey' + ); + } + // subscriptions: list + if (metadata.subscriptions?.r__list_PathName) { + metadata.subscriptions.list = cache.getListObjectId( + metadata.subscriptions.r__list_PathName, + 'CustomerKey' + ); + delete metadata.subscriptions.r__list_PathName; + } + + // journey + // ! update & create enpoints dont accept journey.interactionKey. They only allow to create a new journey + metadata.options ||= {}; + metadata.options.createJourney = true; // only send this during create or else we might end up with an unexpected outcome + + // subscriptions: sendClassification + if (metadata.r__sendClassification_key) { + // we merely want to be able to show an error if it does not exist + metadata.classification = cache.searchForField( + 'sendClassification', + metadata.r__sendClassification_key, + 'CustomerKey', + 'CustomerKey' + ); + delete metadata.r__sendClassification_key; + } + + return metadata; + } + + /** + * helper for {@link TransactionalEmail.createREST} + * + * @param {MetadataTypeItem} _ not used + * @param {object} apiResponse varies depending on the API call + * @returns {Promise.<object>} apiResponse + */ + static async postCreateTasks(_, apiResponse) { + if (apiResponse.journey?.interactionKey) { + Util.logger.warn( + ` - created journey: ${apiResponse.journey.interactionKey} (auto-created when ${this.definition.type} ${apiResponse.definitionKey} was created)` + ); + // when we create new transactionalEmails, we should also download the new journey that was created with it + this._createdJourneyKeys ||= []; + this._createdJourneyKeys.push(apiResponse.journey?.interactionKey); + + // do what postRetrieveTasks won't be able to do without spending lots of time on caching + apiResponse.r__journey_key = apiResponse.journey.interactionKey; + delete apiResponse.journey; + } + + return apiResponse; + } + + /** + * Gets executed after deployment of metadata type + * + * @returns {Promise.<void>} - + */ + static async postDeployTasks() { + if (this._createdJourneyKeys?.length) { + Util.logger.warn( + `Please download related journeys via: mcdev retrieve ${this.buObject.credential}/${this.buObject.businessUnit} -m + ${this._createdJourneyKeys.map((el) => `"journey:${el}"`).join(' ')}` + ); + } + delete this._createdJourneyKeys; + } + + /** + * manages post retrieve steps + * + * @param {MetadataTypeItem} metadata a single item + * @returns {MetadataTypeItem} a single item + */ + static postRetrieveTasks(metadata) { + // asset + if (metadata.content?.customerKey) { + metadata.r__asset_key = metadata.content.customerKey; + try { + // we merely want to be able to show an error if it does not exist + cache.searchForField( + 'asset', + metadata.content.customerKey, + 'customerKey', + 'customerKey' + ); + } catch (ex) { + Util.logger.warn( + ` - ${this.definition.type} ${metadata[this.definition.nameField]} (${ + metadata[this.definition.keyField] + }): ${ex.message}.` + ); + } + delete metadata.content; + } + + // subscriptions: dataExtension + if (metadata.subscriptions?.dataExtension) { + metadata.subscriptions.r__dataExtension_key = metadata.subscriptions.dataExtension; + try { + // we merely want to be able to show a warning if it does not exist + cache.searchForField( + 'dataExtension', + metadata.subscriptions.dataExtension, + 'CustomerKey', + 'CustomerKey' + ); + } catch (ex) { + Util.logger.warn( + ` - ${this.definition.type} ${metadata[this.definition.nameField]} (${ + metadata[this.definition.keyField] + }): ${ex.message}.` + ); + } + delete metadata.subscriptions.dataExtension; + } + // subscriptions: list + if (metadata.subscriptions?.list) { + try { + // List + metadata.subscriptions.r__list_PathName = cache.getListPathName( + metadata.subscriptions.list, + 'CustomerKey' + ); + delete metadata.subscriptions.list; + } catch (ex) { + Util.logger.warn( + ` - ${this.definition.type} ${metadata[this.definition.nameField]} (${ + metadata[this.definition.keyField] + }): ${ex.message}.` + ); + } + } + // journey + if (metadata.journey?.interactionKey) { + metadata.r__journey_key = metadata.journey.interactionKey; + try { + // we merely want to be able to show a warning if it does not exist + metadata.r__journey_key = cache.searchForField( + 'journey', + metadata.journey.interactionKey, + 'key', + 'key' + ); + } catch (ex) { + Util.logger.warn( + ` - ${this.definition.type} ${metadata[this.definition.nameField]} (${ + metadata[this.definition.keyField] + }): ${ex.message}.` + ); + } + delete metadata.journey; + } + // sendClassification + if (metadata.classification) { + metadata.r__sendClassification_key = metadata.classification; + try { + // we merely want to be able to show a warning if it does not exist + metadata.r__sendClassification_key = cache.searchForField( + 'sendClassification', + metadata.classification, + 'CustomerKey', + 'CustomerKey' + ); + } catch (ex) { + Util.logger.warn( + ` - ${this.definition.type} ${metadata[this.definition.nameField]} (${ + metadata[this.definition.keyField] + }): ${ex.message}.` + ); + } + delete metadata.classification; + } + + return metadata; + } + + /** + * Delete a metadata item from the specified business unit + * + * @param {string} key Identifier of item + * @returns {Promise.<boolean>} deletion success status + */ + static async deleteByKey(key) { + const metadataMapObj = await this.retrieveForCache(null, null, key); + const journeyKey = metadataMapObj?.metadata?.[key]?.journey?.interactionKey; + + const isDeleted = await super.deleteByKeyREST( + '/messaging/v1/' + this.subType + '/definitions/' + key, + key, + 30003 + ); + if (isDeleted && journeyKey) { + Util.logger.info( + ` - deleted ${Journey.definition.type}: ${journeyKey} (SFMC auto-deletes the related journey of ${this.definition.type} ${key})` + ); + Journey.buObject = this.buObject; + Journey.properties = this.properties; + Journey.client = this.client; + Journey.postDeleteTasks(journeyKey); + } + return isDeleted; + } +} + +// Assign definition to static attributes +import MetadataTypeDefinitions from '../MetadataTypeDefinitions.js'; +TransactionalEmail.definition = MetadataTypeDefinitions.transactionalEmail; + +export default TransactionalEmail; diff --git a/lib/metadataTypes/TransactionalMessage.js b/lib/metadataTypes/TransactionalMessage.js new file mode 100644 index 000000000..80fc90472 --- /dev/null +++ b/lib/metadataTypes/TransactionalMessage.js @@ -0,0 +1,141 @@ +'use strict'; + +import MetadataType from './MetadataType.js'; +import { Util } from '../util/util.js'; + +/** + * @typedef {import('../../types/mcdev.d.js').BuObject} BuObject + * @typedef {import('../../types/mcdev.d.js').CodeExtract} CodeExtract + * @typedef {import('../../types/mcdev.d.js').CodeExtractItem} CodeExtractItem + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItem} MetadataTypeItem + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItemDiff} MetadataTypeItemDiff + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItemObj} MetadataTypeItemObj + * @typedef {import('../../types/mcdev.d.js').MetadataTypeMap} MetadataTypeMap + * @typedef {import('../../types/mcdev.d.js').MetadataTypeMapObj} MetadataTypeMapObj + * @typedef {import('../../types/mcdev.d.js').SoapRequestParams} SoapRequestParams + * @typedef {import('../../types/mcdev.d.js').TemplateMap} TemplateMap + */ + +/** + * TransactionalMessage MetadataType + * + * @augments MetadataType + */ +class TransactionalMessage extends MetadataType { + // define this.subType as string here for intellisense; requires to be redefined in child class + static subType; + + /** + * Retrieves Metadata + * + * @param {string} [retrieveDir] Directory where retrieved metadata directory will be saved + * @param {void | string[]} [_] unused parameter + * @param {void | string[]} [__] unused parameter + * @param {string} [key] customer key of single item to retrieve + * @returns {Promise.<MetadataTypeMapObj>} Promise of metadata + */ + static async retrieve(retrieveDir, _, __, key) { + let keyList; + const baseUri = '/messaging/v1/' + this.subType + '/definitions/'; + if (key) { + // Retrieve single + keyList = [key]; + } else { + // Retrieve all + // * keep deleted items for caching (and to decide on update vs create) + const parsed = ( + await this.retrieveREST( + null, + baseUri + (retrieveDir ? '?$filter=status%20neq%20deleted' : '') + ) + ).metadata; + keyList = Object.keys(parsed); + } + // get all transactionalX items with additional details not given by the list endpoint + const details = ( + await Promise.all( + keyList.map(async (key) => { + try { + return await this.client.rest.get(baseUri + (key || '')); + } catch { + return null; + } + }) + ) + ).filter(Boolean); + const parsed = this.parseResponseBody({ definitions: details }); + let savedMetadata; + if (retrieveDir) { + // * retrieveDir is mandatory in this method as it is not used for caching (there is a seperate method for that) + savedMetadata = await this.saveResults(parsed, retrieveDir, null, null); + Util.logger.info( + `Downloaded: ${this.definition.type} (${Object.keys(savedMetadata).length})` + + Util.getKeysString(key) + ); + if (!Object.keys(savedMetadata).length && key) { + this.postDeleteTasks(key); + } + } + + return { metadata: savedMetadata || parsed, type: this.definition.type }; + } + + /** + * Retrieves event definition metadata for caching + * + * @param {void | string[]} [_] parameter not used + * @param {void | string[]} [__] parameter not used + * @param {string} [key] customer key of single item to cache + * @returns {Promise.<MetadataTypeMapObj>} Promise of metadata + */ + static retrieveForCache(_, __, key) { + // the call to /messaging/v1/email/definitions/ does not return definitionId + // definitionId is required for resolving dependencies on interactions. + // we should therefore use the already defined retrieve method + return this.retrieve(undefined, undefined, undefined, key); + } + + /** + * Updates a single item + * + * @param {MetadataTypeItem} metadata a single item + * @returns {Promise} Promise + */ + static update(metadata) { + return super.updateREST( + metadata, + '/messaging/v1/' + this.subType + '/definitions/' + metadata[this.definition.keyField] + ); + } + + /** + * Creates a single item + * + * @param {MetadataTypeItem} metadata a single item + * @returns {Promise} Promise + */ + static create(metadata) { + return super.createREST(metadata, '/messaging/v1/' + this.subType + '/definitions'); + } + + /** + * Delete a metadata item from the specified business unit + * + * @param {string} key Identifier of item + * @returns {Promise.<boolean>} deletion success status + */ + static deleteByKey(key) { + return super.deleteByKeyREST( + '/messaging/v1/' + this.subType + '/definitions/' + key, + key, + 30003 + ); + } +} + +// Assign definition to static attributes +// ! using SMS definitions here as placeholder to have auto completion +import MetadataTypeDefinitions from '../MetadataTypeDefinitions.js'; +TransactionalMessage.definition = MetadataTypeDefinitions.transactionalMessage; +TransactionalMessage.definition; +export default TransactionalMessage; diff --git a/lib/metadataTypes/TransactionalPush.js b/lib/metadataTypes/TransactionalPush.js new file mode 100644 index 000000000..c7ab2b75f --- /dev/null +++ b/lib/metadataTypes/TransactionalPush.js @@ -0,0 +1,94 @@ +'use strict'; + +import TransactionalMessage from './TransactionalMessage.js'; +import { Util } from '../util/util.js'; +import cache from '../util/cache.js'; + +/** + * @typedef {import('../../types/mcdev.d.js').BuObject} BuObject + * @typedef {import('../../types/mcdev.d.js').CodeExtract} CodeExtract + * @typedef {import('../../types/mcdev.d.js').CodeExtractItem} CodeExtractItem + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItem} MetadataTypeItem + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItemDiff} MetadataTypeItemDiff + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItemObj} MetadataTypeItemObj + * @typedef {import('../../types/mcdev.d.js').MetadataTypeMap} MetadataTypeMap + * @typedef {import('../../types/mcdev.d.js').MetadataTypeMapObj} MetadataTypeMapObj + * @typedef {import('../../types/mcdev.d.js').SoapRequestParams} SoapRequestParams + * @typedef {import('../../types/mcdev.d.js').TemplateMap} TemplateMap + */ + +/** + * TransactionalPush TransactionalMessage + * + * @augments TransactionalMessage + */ +class TransactionalPush extends TransactionalMessage { + static subType = 'push'; + + /** + * prepares for deployment + * + * @param {MetadataTypeItem} metadata a single item + * @returns {Promise.<MetadataTypeItem>} - + */ + static async preDeployTasks(metadata) { + // asset + if (metadata.r__asset_key) { + // we merely want to be able to show an error if it does not exist + metadata.content ||= {}; + metadata.content.customerKey = cache.searchForField( + 'asset', + metadata.r__asset_key, + 'customerKey', + 'customerKey' + ); + delete metadata.r__asset_key; + } + if (metadata.options?.badge && typeof metadata.options?.badge !== 'string') { + // ensure it's a string, or else the API will return an error. Our SDK turns numbers in strings into actual numbers + metadata.options.badge += ''; + } + + return metadata; + } + + /** + * manages post retrieve steps + * + * @param {MetadataTypeItem} metadata a single item + * @returns {MetadataTypeItem} a single item + */ + static postRetrieveTasks(metadata) { + // asset + if (metadata.content?.customerKey) { + try { + // we merely want to be able to show an error if it does not exist + metadata.r__asset_key = cache.searchForField( + 'asset', + metadata.content.customerKey, + 'customerKey', + 'customerKey' + ); + delete metadata.content; + } catch (ex) { + Util.logger.warn( + ` - ${this.definition.type} ${metadata[this.definition.nameField]} (${ + metadata[this.definition.keyField] + }): ${ex.message}.` + ); + } + } + if (metadata.options?.badge && typeof metadata.options?.badge !== 'string') { + // ensure it's a string, or else the API will return an error. Our SDK turns numbers in strings into actual numbers + metadata.options.badge += ''; + } + + return metadata; + } +} + +// Assign definition to static attributes +import MetadataTypeDefinitions from '../MetadataTypeDefinitions.js'; +TransactionalPush.definition = MetadataTypeDefinitions.transactionalPush; + +export default TransactionalPush; diff --git a/lib/metadataTypes/TransactionalSMS.js b/lib/metadataTypes/TransactionalSMS.js new file mode 100644 index 000000000..4030228f5 --- /dev/null +++ b/lib/metadataTypes/TransactionalSMS.js @@ -0,0 +1,367 @@ +'use strict'; + +import TransactionalMessage from './TransactionalMessage.js'; +import { Util } from '../util/util.js'; +import File from '../util/file.js'; +import cache from '../util/cache.js'; + +/** + * @typedef {import('../../types/mcdev.d.js').BuObject} BuObject + * @typedef {import('../../types/mcdev.d.js').CodeExtract} CodeExtract + * @typedef {import('../../types/mcdev.d.js').CodeExtractItem} CodeExtractItem + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItem} MetadataTypeItem + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItemDiff} MetadataTypeItemDiff + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItemObj} MetadataTypeItemObj + * @typedef {import('../../types/mcdev.d.js').MetadataTypeMap} MetadataTypeMap + * @typedef {import('../../types/mcdev.d.js').MetadataTypeMapObj} MetadataTypeMapObj + * @typedef {import('../../types/mcdev.d.js').SoapRequestParams} SoapRequestParams + * @typedef {import('../../types/mcdev.d.js').TemplateMap} TemplateMap + */ + +/** + * TransactionalSMS MetadataType + * + * @augments TransactionalMessage + */ +class TransactionalSMS extends TransactionalMessage { + static subType = 'sms'; + + /** + * clean up after deleting a metadata item + * + * @param {string} customerKey Identifier of metadata item + * @returns {Promise.<void>} - + */ + static async postDeleteTasks(customerKey) { + // delete local copy: retrieve/cred/bu/type/...-meta.json + // delete local copy: retrieve/cred/bu/type/...-meta.amp + return super.postDeleteTasks(customerKey, [`${this.definition.type}-meta.amp`]); + } + + /** + * prepares for deployment + * + * @param {MetadataTypeItem} metadata a single item + * @param {string} deployDir directory of deploy files + * @returns {Promise.<MetadataTypeItem>} Promise + */ + static async preDeployTasks(metadata, deployDir) { + // code + metadata.content = { + message: await this._mergeCode(metadata, deployDir), + }; + + if (this._isHTML(metadata.content?.message)) { + // keep this as a non-blocking warning because the test not 100% accurate + Util.logger.warn( + ` - ${this.definition.type} ${metadata[this.definition.nameField]} (${ + metadata[this.definition.keyField] + }): HTML detected` + ); + } + + // subscriptions: mobileKeyword + if (metadata.subscriptions?.r__mobileKeyword_key) { + // we merely want to be able to show an error if it does not exist + cache.searchForField( + 'mobileKeyword', + metadata.subscriptions.r__mobileKeyword_key, + 'c__codeKeyword', + 'c__codeKeyword' + ); + const codeKeywordArr = metadata.subscriptions.r__mobileKeyword_key.split('.'); + metadata.subscriptions.shortCode = codeKeywordArr[0]; + metadata.subscriptions.keyword = codeKeywordArr[1]; + // make sure the code actually exists + cache.searchForField('mobileCode', metadata.subscriptions.shortCode, 'code', 'code'); + } else if (metadata.subscriptions?.r__mobileCode_key) { + // subscriptions: mobileCode + // in case we dont have r__mobileKeyword_key set + metadata.subscriptions.shortCode = cache.searchForField( + 'mobileCode', + metadata.subscriptions.r__mobileCode_key, + 'code', + 'code' + ); + } + delete metadata.subscriptions.r__mobileKeyword_key; + delete metadata.subscriptions.r__mobileCode_key; + + return metadata; + } + + /** + * helper for {@link TransactionalSMS.preDeployTasks} that loads extracted code content back into JSON + * + * @param {MetadataTypeItem} metadata a single definition + * @param {string} deployDir directory of deploy files + * @param {string} [templateName] name of the template used to built defintion (prior applying templating) + * @returns {Promise.<string>} content for metadata.script + */ + static async _mergeCode(metadata, deployDir, templateName) { + templateName ||= metadata[this.definition.keyField]; + const codePath = File.normalizePath([ + deployDir, + this.definition.type, + templateName + '.' + this.definition.type + '-meta', + ]); + + if (await File.pathExists(codePath + '.amp')) { + return await File.readFilteredFilename( + [deployDir, this.definition.type], + templateName + '.' + this.definition.type + '-meta', + 'amp' + ); + } else { + throw new Error(`Could not find ${codePath}.amp`); + } + } + + /** + * manages post retrieve steps + * + * @param {MetadataTypeItem} metadata a single item + * @returns {Promise.<CodeExtractItem>} Array with one metadata object and one ssjs string + */ + static async postRetrieveTasks(metadata) { + // extract message body + const codeArr = []; + // keep between tags + const { fileExt, code } = await this.prepExtractedCode(metadata.content?.message); + delete metadata.content; + codeArr.push({ + subFolder: null, + fileName: metadata[this.definition.keyField], + fileExt: fileExt, + content: code, + }); + + if (this._isHTML(code)) { + Util.logger.warn( + ` - ${this.definition.type} ${metadata[this.definition.nameField]} (${ + metadata[this.definition.keyField] + }): HTML detected` + ); + } + + // subscriptions: mobileCode + if (metadata.subscriptions?.shortCode) { + try { + // we merely want to be able to show a warning if it does not exist + cache.searchForField( + 'mobileCode', + metadata.subscriptions.shortCode, + 'code', + 'code' + ); + metadata.subscriptions.r__mobileCode_key = metadata.subscriptions.shortCode; + delete metadata.subscriptions.shortCode; + } catch { + Util.logger.warn( + ` - ${this.definition.type} ${metadata[this.definition.nameField]} (${ + metadata[this.definition.keyField] + }): Could not find mobileCode ${metadata.subscriptions.shortCode}.` + ); + } + // subscriptions: mobileKeyword + if (metadata.subscriptions?.keyword) { + try { + // we merely want to be able to show a warning if it does not exist + metadata.subscriptions.r__mobileKeyword_key = cache.searchForField( + 'mobileKeyword', + (metadata.subscriptions.shortCode || + metadata.subscriptions.r__mobileCode_key) + + '.' + + metadata.subscriptions.keyword, + 'c__codeKeyword', + 'c__codeKeyword' + ); + delete metadata.subscriptions.r__mobileCode_key; + delete metadata.subscriptions.shortCode; + delete metadata.subscriptions.keyword; + } catch { + Util.logger.warn( + ` - ${this.definition.type} ${metadata[this.definition.nameField]} (${ + metadata[this.definition.keyField] + }): Could not find mobileKeyword ${metadata.subscriptions.keyword}.` + ); + } + } + } + + return { json: metadata, codeArr: codeArr, subFolder: null }; + } + + /** + * helper for {@link TransactionalSMS.postRetrieveTasks} and {@link TransactionalSMS._buildForNested} + * + * @param {string} metadataScript the code of the file + * @returns {Promise.<{fileExt:string,code:string}>} returns found extension and file content + */ + static async prepExtractedCode(metadataScript) { + const code = await File.beautify_beautyAmp(metadataScript, false); + const fileExt = 'amp'; + + return { fileExt, code }; + } + + /** + * helper for {@link TransactionalMessage.buildDefinition} + * handles extracted code if any are found for complex types + * + * @param {string} templateDir Directory where metadata templates are stored + * @param {string|string[]} targetDir (List of) Directory where built definitions will be saved + * @param {MetadataTypeItem} metadata main JSON file that was read from file system + * @param {TemplateMap} templateVariables variables to be replaced in the metadata + * @param {string} templateName name of the template to be built + * @returns {Promise.<string[][]>} list of extracted files with path-parts provided as an array + */ + static buildDefinitionForNested( + templateDir, + targetDir, + metadata, + templateVariables, + templateName + ) { + return this._buildForNested( + templateDir, + targetDir, + metadata, + templateVariables, + templateName, + 'definition' + ); + } + + /** + * helper for {@link TransactionalMessage.buildTemplate} + * handles extracted code if any are found for complex types + * + * @example scripts are saved as 1 json and 1 ssjs file. both files need to be run through templating + * @param {string} templateDir Directory where metadata templates are stored + * @param {string|string[]} targetDir (List of) Directory where built definitions will be saved + * @param {MetadataTypeItem} metadata main JSON file that was read from file system + * @param {TemplateMap} templateVariables variables to be replaced in the metadata + * @param {string} templateName name of the template to be built + * @returns {Promise.<string[][]>} list of extracted files with path-parts provided as an array + */ + static buildTemplateForNested( + templateDir, + targetDir, + metadata, + templateVariables, + templateName + ) { + return this._buildForNested( + templateDir, + targetDir, + metadata, + templateVariables, + templateName, + 'template' + ); + } + + /** + * helper for {@link TransactionalSMS.buildTemplateForNested} / {@link TransactionalSMS.buildDefinitionForNested} + * handles extracted code if any are found for complex types + * + * @param {string} templateDir Directory where metadata templates are stored + * @param {string|string[]} targetDir (List of) Directory where built definitions will be saved + * @param {MetadataTypeItem} metadata main JSON file that was read from file system + * @param {TemplateMap} templateVariables variables to be replaced in the metadata + * @param {string} templateName name of the template to be built + * @param {'definition'|'template'} mode defines what we use this helper for + * @returns {Promise.<string[][]>} list of extracted files with path-parts provided as an array + */ + static async _buildForNested( + templateDir, + targetDir, + metadata, + templateVariables, + templateName, + mode + ) { + // get code from filesystem + let code = await this._mergeCode(metadata, templateDir, templateName); + const file = await this.prepExtractedCode(code); + const fileExt = file.fileExt; + code = file.code; + // apply templating + try { + if (mode === 'definition') { + // replace template variables with their values + code = this.applyTemplateValues(code, templateVariables); + } else if (mode === 'template') { + // replace template values with corresponding variable names + code = this.applyTemplateNames(code, templateVariables); + } + } catch { + throw new Error( + `${this.definition.type}:: Error applying template variables on ${ + templateName + '.' + this.definition.type + }-meta.${fileExt}.` + ); + } + + // write to file + const targetDirArr = Array.isArray(targetDir) ? targetDir : [targetDir]; + const nestedFilePaths = []; + + // keep old name if creating templates, otherwise use new name + const fileName = mode === 'definition' ? metadata[this.definition.keyField] : templateName; + + for (const targetDir of targetDirArr) { + File.writeToFile( + [targetDir, this.definition.type], + fileName + '.' + this.definition.type + '-meta', + fileExt, + code + ); + nestedFilePaths.push([ + targetDir, + this.definition.type, + fileName + '.' + this.definition.type + '-meta.' + fileExt, + ]); + } + return nestedFilePaths; + } + + /** + * very simplified test for HTML code in our SMS + * + * @param {string} code sms source code + * @returns {boolean} true if HTML is found + */ + static _isHTML(code) { + return /(<([^>]+)>)/gi.test(code); + } + + /** + * should return only the json for all but asset, query and script that are saved as multiple files + * additionally, the documentation for dataExtension and automation should be returned + * + * @param {string[]} keyArr customerkey of the metadata + * @returns {Promise.<string[]>} list of all files that need to be committed in a flat array ['path/file1.ext', 'path/file2.ext'] + */ + static async getFilesToCommit(keyArr) { + const path = File.normalizePath([ + this.properties.directories.retrieve, + this.buObject.credential, + this.buObject.businessUnit, + this.definition.type, + ]); + + const fileList = keyArr.flatMap((key) => [ + File.normalizePath([path, `${key}.${this.definition.type}-meta.json`]), + File.normalizePath([path, `${key}.${this.definition.type}-meta.amp`]), + ]); + return fileList; + } +} + +// Assign definition to static attributes +import MetadataTypeDefinitions from '../MetadataTypeDefinitions.js'; +TransactionalSMS.definition = MetadataTypeDefinitions.transactionalSMS; + +export default TransactionalSMS; diff --git a/lib/metadataTypes/TriggeredSend.js b/lib/metadataTypes/TriggeredSend.js new file mode 100644 index 000000000..d649292be --- /dev/null +++ b/lib/metadataTypes/TriggeredSend.js @@ -0,0 +1,615 @@ +'use strict'; + +import MetadataType from './MetadataType.js'; +import { Util } from '../util/util.js'; +import cache from '../util/cache.js'; +import asset from './Asset.js'; +import folder from './Folder.js'; +import list from './List.js'; +import sendClassification from './SendClassification.js'; +import senderProfile from './SenderProfile.js'; +import ReplaceCbReference from '../util/replaceContentBlockReference.js'; +import pLimit from 'p-limit'; + +/** + * @typedef {import('../../types/mcdev.d.js').BuObject} BuObject + * @typedef {import('../../types/mcdev.d.js').CodeExtract} CodeExtract + * @typedef {import('../../types/mcdev.d.js').CodeExtractItem} CodeExtractItem + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItem} MetadataTypeItem + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItemDiff} MetadataTypeItemDiff + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItemObj} MetadataTypeItemObj + * @typedef {import('../../types/mcdev.d.js').MetadataTypeMap} MetadataTypeMap + * @typedef {import('../../types/mcdev.d.js').MetadataTypeMapObj} MetadataTypeMapObj + * @typedef {import('../../types/mcdev.d.js').SoapRequestParams} SoapRequestParams + * @typedef {import('../../types/mcdev.d.js').TemplateMap} TemplateMap + */ + +/** + * MessageSendActivity MetadataType + * + * @augments MetadataType + */ +class TriggeredSend extends MetadataType { + /** + * Retrieves SOAP based metadata of metadata type into local filesystem. executes callback with retrieved metadata + * + * @param {string} retrieveDir Directory where retrieved metadata directory will be saved + * @param {void | string[]} [_] unused parameter + * @param {void | string[]} [__] unused parameter + * @param {string} [key] customer key of single item to retrieve + * @returns {Promise.<MetadataTypeMapObj>} Promise of metadata + */ + static retrieve(retrieveDir, _, __, key) { + /** @type {SoapRequestParams} */ + let requestParams = { + filter: { + leftOperand: 'TriggeredSendStatus', + operator: 'IN', + rightOperand: ['New', 'Active', 'Inactive', 'Moved', 'Canceled'], // New, Active=Running, Inactive=Paused, (Deleted) + }, + }; + if (key) { + // move original filter down one level into rightOperand and add key filter into leftOperand + requestParams = { + filter: { + leftOperand: { + leftOperand: 'CustomerKey', + operator: 'equals', + rightOperand: key, + }, + operator: 'AND', + rightOperand: requestParams.filter, + }, + }; + } + + return super.retrieveSOAP(retrieveDir, requestParams, key); + } + + /** + * Create a single TSD. + * + * @param {MetadataTypeItem} metadata single metadata entry + * @returns {Promise} Promise + */ + static create(metadata) { + return super.createSOAP(metadata); + } + + /** + * Updates a single TSD. + * + * @param {MetadataTypeItem} metadata single metadata entry + * @returns {Promise} Promise + */ + static update(metadata) { + // * in case of update and active definition, we need to pause first. + // * this should be done manually to not accidentally pause production queues without restarting them + return super.updateSOAP(metadata); + } + + /** + * Delete a metadata item from the specified business unit + * + * @param {string} key Identifier of data extension + * @returns {Promise.<boolean>} deletion success status + */ + static deleteByKey(key) { + return super.deleteByKeySOAP(key, undefined, 17015); + } + + /** + * parses retrieved Metadata before saving + * + * @param {MetadataTypeItem} metadata a single item + * @returns {MetadataTypeItem | void} Array with one metadata object and one sql string + */ + static postRetrieveTasks(metadata) { + // remove IsPlatformObject, always has to be 'false' + delete metadata.IsPlatformObject; + + // folder + this.setFolderPath(metadata); + if (!metadata.r__folder_Path) { + Util.logger.verbose( + ` ☇ skipping ${this.definition.typeName} '${metadata.Name}'/'${metadata.CustomerKey}': Could not find folder.` + ); + // do not save this TSD because it would not be visible in the user interface + return; + } + // email + try { + // content builder + const contentBuilderEmailName = cache.searchForField( + 'asset', + metadata.Email.ID, + 'legacyData.legacyId', + 'name' + ); + metadata.r__asset_name_readOnly = contentBuilderEmailName; + const contentBuilderEmailKey = cache.searchForField( + 'asset', + metadata.Email.ID, + 'legacyData.legacyId', + 'customerKey' + ); + metadata.r__asset_key = contentBuilderEmailKey; + delete metadata.Email; + } catch { + try { + // classic + const classicEmail = cache.searchForField('email', metadata.Email.ID, 'ID', 'Name'); + metadata.r__email_name = classicEmail; + delete metadata.Email; + } catch { + Util.logger.verbose( + ` - ${this.definition.typeName} '${metadata.Name}'/'${metadata.CustomerKey}': Could not find email with ID ${metadata.Email.ID} in Classic nor in Content Builder. This TSD cannot be republished but potentially restarted with its cached version of the email.` + ); + // save this TSD because it could be fixed by the user or potentially restarted without a fix; also, it might be used by a journey + } + } + // message priority + if (metadata.Priority) { + metadata.c__priority = Util.inverseGet( + this.definition.priorityMapping, + metadata.Priority + ); + delete metadata.Priority; + } + + // List (optional) + if (metadata.List) { + try { + metadata.r__list_PathName = cache.getListPathName(metadata.List.ID, 'ID'); + delete metadata.List; + } catch (ex) { + Util.logger.verbose( + ` - ${this.definition.typeName} '${metadata.Name}'/'${metadata.CustomerKey}': ${ex.message}` + ); + // save this TSD because it could be fixed by the user + } + } + + // sender profile + if (metadata.SenderProfile?.ObjectID) { + try { + const spKey = cache.searchForField( + 'senderProfile', + metadata.SenderProfile.ObjectID, + 'ObjectID', + 'CustomerKey' + ); + metadata.r__senderProfile_key = spKey; + delete metadata.SenderProfile; + } catch (ex) { + Util.logger.warn( + ` - ${this.definition.type} ${metadata.CustomerKey}: ${ex.message} (senderProfile key ${metadata.SenderProfile.CustomerKey})` + ); + } + } + // send classification + if (metadata.SendClassification?.ObjectID) { + try { + const scKey = cache.searchForField( + 'sendClassification', + metadata.SendClassification.ObjectID, + 'ObjectID', + 'CustomerKey' + ); + metadata.r__sendClassification_key = scKey; + delete metadata.SendClassification; + } catch (ex) { + Util.logger.warn( + ` - ${this.definition.type} ${metadata.CustomerKey}: ${ex.message} (sendClassification key ${metadata.SendClassification.CustomerKey})` + ); + } + } + + return metadata; + } + + /** + * prepares a TSD for deployment + * + * @param {MetadataTypeItem} metadata of a single TSD + * @returns {Promise.<MetadataTypeItem>} metadata object + */ + static async preDeployTasks(metadata) { + const cachedVersion = cache.getByKey(this.definition.type, metadata.CustomerKey); + if ( + cachedVersion?.TriggeredSendStatus === 'Active' && + cachedVersion?.TriggeredSendStatus === metadata.TriggeredSendStatus + ) { + throw new Error( + `Please pause the Triggered Send '${metadata.Name}' before updating it. You may do so via GUI; or via Accenture SFMC DevTools by setting TriggeredSendStatus to 'Inactive'.` + ); + } + // re-add IsPlatformObject, required for visibility + metadata.IsPlatformObject = false; + // folder + super.setFolderId(metadata); + // email + if (metadata.r__email_name) { + // classic + metadata.Email = { + ID: cache.searchForField('email', metadata.r__email_name, 'Name', 'ID'), + }; + delete metadata.r__email_name; + } else if (metadata.r__asset_key) { + // content builder + // * this ignores r__asset_name_readOnly on purpose as that is only unique per parent folder but useful during PR reviews + metadata.Email = { + ID: cache.searchForField( + 'asset', + metadata.r__asset_key, + 'customerKey', + 'legacyData.legacyId' + ), + }; + delete metadata.r__asset_key; + delete metadata.r__asset_name_readOnly; + } else if (metadata?.Email?.ID) { + throw new Error( + `r__asset_key / r__email_name not defined but instead found Email.ID. Please try re-retrieving this TSD from your BU.` + ); + } + // message priority + if (metadata.c__priority) { + metadata.Priority = this.definition.priorityMapping[metadata.c__priority]; + delete metadata.c__priority; + } + // get List (optional) + if (metadata.r__list_PathName) { + metadata.List = { + ID: cache.getListObjectId(metadata.r__list_PathName, 'ID'), + }; + delete metadata.r__list_PathName; + } else if (metadata?.List?.ID) { + throw new Error( + `r__list_PathName not defined but instead found List.ID. Please try re-retrieving this TSD from your BU.` + ); + } + // sender profile + if (metadata.r__senderProfile_key) { + const spId = cache.searchForField( + 'senderProfile', + metadata.r__senderProfile_key, + 'CustomerKey', + 'ObjectID' + ); + metadata.SenderProfile = { + ObjectID: spId, + CustomerKey: metadata.r__senderProfile_key, + }; + delete metadata.r__senderProfile_key; + } + // send classification + if (metadata.r__sendClassification_key) { + const scId = cache.searchForField( + 'sendClassification', + metadata.r__sendClassification_key, + 'CustomerKey', + 'ObjectID' + ); + metadata.SendClassification = { + ObjectID: scId, + CustomerKey: metadata.r__sendClassification_key, + }; + delete metadata.r__sendClassification_key; + } + + return metadata; + } + + /** + * TSD-specific refresh method that finds active TSDs and refreshes them + * + * @param {string[]} [keyArr] metadata keys + * @param {boolean} [checkKey] whether to check if the key is valid + * @returns {Promise.<string[]>} Returns list of keys that were refreshed + */ + static async refresh(keyArr, checkKey = true) { + if (!keyArr) { + keyArr = await this.getKeysForValidTSDs((await this.findRefreshableItems()).metadata); + checkKey = false; + } + // then executes pause, publish, start on them. + Util.logger.info(`Refreshing ${keyArr.length} ${this.definition.typeName}...`); + Util.logger.debug(`Refreshing keys: ${keyArr.join(', ')}`); + const refreshedKeyArr = []; + const rateLimit = pLimit(10); + await Promise.all( + keyArr.map((key) => + rateLimit(async () => { + const result = await this._refreshItem(key, checkKey); + if (result) { + refreshedKeyArr.push(key); + } + }) + ) + ); + Util.logger.info( + `Refreshed ${refreshedKeyArr.length} of ${keyArr.length} ${this.definition.type}` + ); + return refreshedKeyArr; + } + + /** + * helper for {@link TriggeredSend.refresh} that extracts the keys from the TSD item map and eli + * + * @param {MetadataTypeMap} metadata TSD item map + * @returns {Promise.<string[]>} keyArr + */ + static async getKeysForValidTSDs(metadata) { + const keyArr = Object.keys(metadata).filter((key) => { + const test = this.postRetrieveTasks(metadata[key]); + return test?.CustomerKey || false; + }); + Util.logger.info(`Found ${keyArr.length} refreshable items.`); + return keyArr; + } + + /** + * helper for {@link TriggeredSend.refresh} that finds active TSDs on the server and filters it by the same rules that {@link TriggeredSend.retrieve} is using to avoid refreshing TSDs with broken dependencies + * + * @param {boolean} [assetLoaded] if run after Asset.deploy via --refresh option this will skip caching assets + * @returns {Promise.<MetadataTypeMapObj>} Promise of TSD item map + */ + static async findRefreshableItems(assetLoaded = false) { + Util.logger.info('Finding refreshable items...'); + // cache dependencies to test for broken links + const requiredCache = { + folder: [ + 'hidden', + 'list', + 'mysubs', + 'suppression_list', + 'publication', + 'contextual_suppression_list', + 'triggered_send', + 'triggered_send_journeybuilder', + ], + }; + for (const dep of this.definition.dependencies) { + if (dep === 'email') { + // skip deprecated classic emails here, assuming they cannot be updated and hence are not relevant for {@link refresh} + continue; + } + const [type, subtype] = dep.split('-'); + if (requiredCache[type]) { + requiredCache[type].push(subtype); + } else { + requiredCache[type] = subtype ? [subtype] : null; + } + } + for (const [type, subTypeArr] of Object.entries(requiredCache)) { + if (Array.isArray(subTypeArr)) { + // make sure entries are unique + requiredCache[type] = [...new Set(subTypeArr)]; + } + } + const cacheTypes = { + asset, + folder, + list, + sendClassification, + senderProfile, + }; + for (const [type, subTypeArr] of Object.entries(requiredCache)) { + if (type === 'asset' && assetLoaded) { + continue; + } + Util.logger.info(` - Caching dependent Metadata: ${type}`); + Util.logSubtypes(subTypeArr); + if (!cacheTypes[type]) { + throw new Error(`Cache type ${type} not implemented.`); + } + cacheTypes[type].client = this.client; + cacheTypes[type].buObject = this.buObject; + cacheTypes[type].properties = this.properties; + + const result = await cacheTypes[type].retrieveForCache(null, subTypeArr); + if (cache.getCache()?.[type]) { + // re-run caching to merge with existing cache, assuming we might have missed subtypes + cache.mergeMetadata(type, result.metadata); + } else { + cache.setMetadata(type, result.metadata); + } + } + // cache ACTIVE triggeredSends from the server + /** @type {SoapRequestParams} */ + const requestParams = { + filter: { + leftOperand: 'TriggeredSendStatus', + operator: 'IN', + rightOperand: ['dummy', 'Active'], // using equals does not work for this field for an unknown reason and IN requires at least 2 values, hence the 'dummy' entry + }, + }; + return super.retrieveSOAP(null, requestParams); + } + + /** + * helper for {@link TriggeredSend.refresh} that pauses, publishes and starts a triggered send + * + * @param {string} key external key of triggered send item + * @param {boolean} checkKey whether to check if key exists on the server + * @returns {Promise.<boolean>} true if refresh was successful + */ + static async _refreshItem(key, checkKey) { + const item = {}; + let test; + item[this.definition.keyField] = key; + // check triggeredSend-key exists on the server AND its status==ACTIVE + if (checkKey) { + /** @type {SoapRequestParams} */ + const requestParams = { + filter: { + leftOperand: 'CustomerKey', + operator: 'equals', + rightOperand: key, + }, + }; + try { + test = ( + await super.retrieveSOAP(null, requestParams, key, [ + 'CustomerKey', + 'TriggeredSendStatus', + ]) + )?.metadata; + } catch (ex) { + const errorMsg = super.getSOAPErrorMsg(ex); + Util.logger.error(` ☇ skipping ${this.definition.typeName}: ${key} - ${errorMsg}}`); + return false; + } + if (!test[key]) { + Util.logger.error( + ` ☇ skipping ${this.definition.typeName}: ${key} - not found on server` + ); + return false; + } + if (test[key].TriggeredSendStatus !== 'Active') { + Util.logger.error( + ` ☇ skipping ${this.definition.typeName}: ${key} - refresh only needed for running entries (TriggeredSendStatus=Active)` + ); + return false; + } + } + + // pause + try { + item.TriggeredSendStatus = 'Inactive'; + test = await super.updateSOAP(item, true); + if (test.OverallStatus !== 'OK') { + throw new Error(test.Results[0].StatusMessage); + } + delete item.TriggeredSendStatus; + Util.logger.info(` - 🛑 paused ${this.definition.typeName}: ${key}`); + } catch (ex) { + const errorMsg = super.getSOAPErrorMsg(ex); + + Util.logger.error( + ` - failed to pause ${this.definition.typeName}: ${key} - ${errorMsg}` + ); + return false; + } + + // publish + try { + item.RefreshContent = 'true'; + test = await super.updateSOAP(item, true); + if (test.OverallStatus !== 'OK') { + throw new Error(test.Results[0].StatusMessage); + } + delete item.RefreshContent; + Util.logger.info(` - 🔃 published ${this.definition.typeName}: ${key}`); + } catch (ex) { + const errorMsg = super.getSOAPErrorMsg(ex); + Util.logger.error( + ` - failed to publish ${this.definition.typeName}: ${key} - ${errorMsg}` + ); + return false; + } + + // start + try { + item.TriggeredSendStatus = 'Active'; + test = await super.updateSOAP(item, true); + if (test.OverallStatus !== 'OK') { + throw new Error(test.Results[0].StatusMessage); + } + delete item.RefreshContent; + Util.logger.info(` - ✅ started ${this.definition.typeName}: ${key}`); + } catch (ex) { + const errorMsg = super.getSOAPErrorMsg(ex); + Util.logger.error( + ` - failed to publish ${this.definition.typeName}: ${key} - ${errorMsg}` + ); + return false; + } + return true; + } + + /** + * + * @param {MetadataTypeItem} item single metadata item + * @param {string} [_] parameter not used + * @param {Set.<string>} [findAssetKeys] list of keys that were found referenced via ContentBlockByX; if set, method only gets keys and runs no updates + * @returns {Promise.<MetadataTypeItem>} key of the item that was updated + */ + static async replaceCbReference(item, _, findAssetKeys) { + const parentName = `${this.definition.type} ${item[this.definition.keyField]}`; + let changes = false; + let error; + + // *** type specific logic *** + try { + item.FromName = ReplaceCbReference.replaceReference( + item.FromName, + parentName, + findAssetKeys + ); + changes = true; + } catch (ex) { + if (ex.code !== 200) { + error = ex; + } + } + try { + item.FromAddress = ReplaceCbReference.replaceReference( + item.FromAddress, + parentName, + findAssetKeys + ); + changes = true; + } catch (ex) { + if (ex.code !== 200) { + error = ex; + } + } + try { + item.EmailSubject = ReplaceCbReference.replaceReference( + item.EmailSubject, + parentName, + findAssetKeys + ); + changes = true; + } catch (ex) { + if (ex.code !== 200) { + error = ex; + } + } + try { + item.DynamicEmailSubject = ReplaceCbReference.replaceReference( + item.DynamicEmailSubject, + parentName, + findAssetKeys + ); + changes = true; + } catch (ex) { + if (ex.code !== 200) { + error = ex; + } + } + if (error) { + throw error; + } + + if (!changes) { + const ex = new Error('No changes made to the code.'); + // @ts-expect-error custom error object + ex.code = 200; + throw ex; + } + + // *** finish *** + // replaceReference will throw an error if nothing was updated which will end execution here + // no error means we have a new item to deploy and need to update the item in our retrieve folder + return item; + } +} + +// Assign definition to static attributes +import MetadataTypeDefinitions from '../MetadataTypeDefinitions.js'; +TriggeredSend.definition = MetadataTypeDefinitions.triggeredSend; + +export default TriggeredSend; diff --git a/lib/metadataTypes/TriggeredSendDefinition.js b/lib/metadataTypes/TriggeredSendDefinition.js deleted file mode 100644 index bbd3fb995..000000000 --- a/lib/metadataTypes/TriggeredSendDefinition.js +++ /dev/null @@ -1,240 +0,0 @@ -'use strict'; - -const MetadataType = require('./MetadataType'); -const Util = require('../util/util'); - -/** - * MessageSendActivity MetadataType - * @augments MetadataType - */ -class TriggeredSendDefinition extends MetadataType { - /** - * Retrieves SOAP based metadata of metadata type into local filesystem. executes callback with retrieved metadata - * @param {String} retrieveDir Directory where retrieved metadata directory will be saved - * @returns {Promise<Object>} Promise of metadata - */ - static retrieve(retrieveDir) { - const options = { - filter: { - leftOperand: { - // somehow that parameter controls visible (non deleted?) email send activities - leftOperand: 'IsPlatformObject', - operator: 'equals', - rightOperand: false, - }, - operator: 'AND', - rightOperand: { - leftOperand: 'TriggeredSendStatus', - operator: 'IN', - rightOperand: ['New', 'Active', 'Inactive'], // New, Active=Running, Inactive=Paused, (Deleted) - }, - }, - }; - return super.retrieveSOAPgeneric(retrieveDir, null, options); - } - - /** - * Create a single TSD. - * @param {Object} metadata single metadata entry - * @returns {Promise} Promise - */ - static create(metadata) { - return super.createSOAP(metadata); - } - - /** - * Updates a single TSD. - * @param {Object} metadata single metadata entry - * @returns {Promise} Promise - */ - static update(metadata) { - // * in case of update and active definition, we need to pause first. - // * this should be done manually to not accidentally purge production queues - return super.updateSOAP(metadata); - } - /** - * checks if the current metadata entry should be saved on retrieve or not - * @static - * @param {Object} metadataEntry metadata entry - * @returns {boolean} if false, do not save - * @memberof MetadataType - */ - static isFiltered(metadataEntry) { - try { - // get folder path to be able to filter journey-created TSDs - const folderPath = Util.getFromCache( - this.cache, - 'folder', - metadataEntry.CategoryID, - 'ID', - 'Path' - ); - - if (folderPath && folderPath.startsWith('Journey Builder Sends/')) { - // filter out any triggered sends that were auto-created by journeys - return true; - } - } catch (ex) { - // handle it in parseMetadata() - } - return false; - } - - /** - * manages post retrieve steps - * @param {Object} metadata a single query - * @returns {Object[]} Array with one metadata object and one query string - */ - static postRetrieveTasks(metadata) { - return this.parseMetadata(metadata); - } - /** - * parses retrieved Metadata before saving - * @param {Object} metadata a single query activity definition - * @returns {Array} Array with one metadata object and one sql string - */ - static parseMetadata(metadata) { - // remove IsPlatformObject, always has to be 'false' - delete metadata.IsPlatformObject; - // folder - try { - metadata.r__folder_Path = Util.getFromCache( - this.cache, - 'folder', - metadata.CategoryID, - 'ID', - 'Path' - ); - delete metadata.CategoryID; - } catch (ex) { - Util.logger.warn( - `Triggered Send '${metadata.Name}'/'${metadata.CustomerKey}': ${ex.message}` - ); - } - // email - try { - // classic - const classicEmail = Util.getFromCache( - this.cache, - 'email', - metadata.Email.ID, - 'ID', - 'Name' - ); - metadata.r__email_Name = classicEmail; - delete metadata.Email; - } catch (ex) { - try { - // content builder - const contentBuilderEmailName = Util.getFromCache( - this.cache, - 'asset', - metadata.Email.ID, - 'legacyData.legacyId', - 'name' - ); - metadata.r__assetMessage_Name = contentBuilderEmailName; - const contentBuilderEmailKey = Util.getFromCache( - this.cache, - 'asset', - metadata.Email.ID, - 'legacyData.legacyId', - 'customerKey' - ); - metadata.r__assetMessage_Key = contentBuilderEmailKey; - delete metadata.Email; - } catch (ex) { - Util.logger.warn( - `${this.definition.typeName} '${metadata.Name}'/'${metadata.CustomerKey}': Could not find email with ID ${metadata.Email.ID} in Classic nor in Content Builder.` - ); - } - } - // List - try { - metadata.r__list_PathName = Util.getListPathNameFromCache( - this.cache, - metadata.List.ID, - 'ID' - ); - delete metadata.List; - } catch (ex) { - Util.logger.warn( - `${this.definition.typeName} '${metadata.Name}'/'${metadata.CustomerKey}': ${ex.message}` - ); - } - - return metadata; - } - /** - * prepares a TSD for deployment - * @param {Object} metadata of a single TSD - * @returns {Object} metadata object - */ - static async preDeployTasks(metadata) { - const cachedVersion = this.cache[this.definition.type][metadata.CustomerKey]; - if ( - cachedVersion && - cachedVersion.TriggeredSendStatus === 'Active' && - cachedVersion.TriggeredSendStatus === metadata.TriggeredSendStatus - ) { - throw new Error( - `Please pause the Triggered Send '${metadata.Name}' before updating it. You may do so via GUI; or via Accenture SFMC DevTools by setting TriggeredSendStatus to 'Inactive'.` - ); - } - // re-add IsPlatformObject, required for visibility - metadata.IsPlatformObject = false; - // folder - metadata.CategoryID = Util.getFromCache( - this.cache, - 'folder', - metadata.r__folder_Path, - 'Path', - 'ID' - ); - delete metadata.r__folder_Path; - // email - if (metadata.r__email_Name) { - // classic - metadata.Email = { - ID: Util.getFromCache(this.cache, 'email', metadata.r__email_Name, 'Name', 'ID'), - }; - delete metadata.r__email_Name; - } else if (metadata.r__assetMessage_Key) { - // content builder - // * this ignores r__assetMessage_Name on purpose as that is only unique per parent folder but useful during PR reviews - metadata.Email = { - ID: Util.getFromCache( - this.cache, - 'asset', - metadata.r__assetMessage_Key, - 'customerKey', - 'legacyData.legacyId' - ), - }; - delete metadata.r__assetMessage_Key; - delete metadata.r__assetMessage_Name; - } else if (metadata.Email && metadata.Email.ID) { - throw new Error( - `r__assetMessage_Key / r__email_Name not defined but instead found Email.ID. Please try re-retrieving this TSD from your BU.` - ); - } - // get List - if (metadata.r__list_PathName) { - metadata.List = { - ID: Util.getListObjectIdFromCache(this.cache, metadata.r__list_PathName, 'ID'), - }; - delete metadata.r__list_PathName; - } else if (metadata.List && metadata.List.ID) { - throw new Error( - `r__list_PathName not defined but instead found List.ID. Please try re-retrieving this TSD from your BU.` - ); - } - - return metadata; - } -} - -// Assign definition to static attributes -TriggeredSendDefinition.definition = require('../MetadataTypeDefinitions').triggeredSendDefinition; - -module.exports = TriggeredSendDefinition; diff --git a/lib/metadataTypes/TriggeredSendSummary.js b/lib/metadataTypes/TriggeredSendSummary.js new file mode 100644 index 000000000..91307de3d --- /dev/null +++ b/lib/metadataTypes/TriggeredSendSummary.js @@ -0,0 +1,102 @@ +'use strict'; + +import MetadataType from './MetadataType.js'; +import cache from '../util/cache.js'; +import { Util } from '../util/util.js'; + +/** + * @typedef {import('../../types/mcdev.d.js').BuObject} BuObject + * @typedef {import('../../types/mcdev.d.js').CodeExtract} CodeExtract + * @typedef {import('../../types/mcdev.d.js').CodeExtractItem} CodeExtractItem + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItem} MetadataTypeItem + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItemDiff} MetadataTypeItemDiff + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItemObj} MetadataTypeItemObj + * @typedef {import('../../types/mcdev.d.js').MetadataTypeMap} MetadataTypeMap + * @typedef {import('../../types/mcdev.d.js').MetadataTypeMapObj} MetadataTypeMapObj + * @typedef {import('../../types/mcdev.d.js').SoapRequestParams} SoapRequestParams + * @typedef {import('../../types/mcdev.d.js').TemplateMap} TemplateMap + */ + +/** + * TriggeredSendSummary MetadataType + * + * @augments MetadataType + */ +class TriggeredSendSummary extends MetadataType { + /** + * Retrieves SOAP based metadata of metadata type into local filesystem. executes callback with retrieved metadata + * + * @param {string} retrieveDir Directory where retrieved metadata directory will be saved + * @param {void | string[]} [_] unused parameter + * @param {void | string[]} [__] unused parameter + * @param {string} [key] customer key of single item to retrieve + * @returns {Promise.<MetadataTypeMapObj>} Promise of metadata + */ + static retrieve(retrieveDir, _, __, key) { + /** @type {SoapRequestParams} */ + let requestParams = {}; + if (key) { + // filter by CustomerKey when a specific key is requested + requestParams = { + filter: { + leftOperand: 'CustomerKey', + operator: 'equals', + rightOperand: key, + }, + }; + } + + return super.retrieveSOAP(retrieveDir, requestParams, key); + } + /** + * parses retrieved Metadata before saving + * + * @param {MetadataTypeItem} metadata a single item + * @returns {MetadataTypeItem | void} Array with one metadata object and one sql string + */ + static postRetrieveTasks(metadata) { + // CustomerKey for this type is the same as the CustomerKey of the TriggeredSend it relates to + const triggeredSend = cache.getByKey('triggeredSend', metadata.CustomerKey); + if (!triggeredSend) { + Util.logger.verbose( + `Could not find related TriggeredSend with CustomerKey '${metadata.CustomerKey}' for the TriggeredSendSummary.` + ); + return null; + } + metadata['TriggeredSend.CategoryID'] = triggeredSend.CategoryID; + // folder path for a TriggeredSendSummary is the same as for the related TriggeredSend. CategoryID is not retrievable for this type, so use the TriggeredSend's field + this.setFolderPath(metadata); + delete metadata['TriggeredSend.CategoryID']; + metadata.r__triggeredSend_name = triggeredSend.Name; + metadata.r__triggeredSend_key = triggeredSend.CustomerKey; + return metadata; + } + /** + * retrieves the folder path from cache and updates the TriggeredSendSummary metadata with it after retrieve + * + * @param {MetadataTypeItem} metadata a single item + */ + static setFolderPath(metadata) { + try { + metadata.r__folder_Path = cache.searchForField( + 'folder', + metadata[this.definition.folderIdField], + 'ID', + 'Path' + ); + delete metadata[this.definition.folderIdField]; + } catch { + Util.logger.verbose( + ` ☇ skipping ${this.definition.typeName} '${metadata.Name}'/'${metadata.CustomerKey}': Could not find folder.` + ); + // do not save this Triggered Send Summary because it would not be visible in the user interface + return; + } + } +} + +// Assign definition to static attributes +import MetadataTypeDefinitions from '../MetadataTypeDefinitions.js'; +TriggeredSendSummary.definition = MetadataTypeDefinitions.triggeredSendSummary; + +export default TriggeredSendSummary; diff --git a/lib/metadataTypes/User.js b/lib/metadataTypes/User.js new file mode 100644 index 000000000..f363556de --- /dev/null +++ b/lib/metadataTypes/User.js @@ -0,0 +1,1251 @@ +'use strict'; + +import MetadataType from './MetadataType.js'; +import { Util } from '../util/util.js'; +import File from '../util/file.js'; +import cache from '../util/cache.js'; + +/** + * @typedef {import('../../types/mcdev.d.js').BuObject} BuObject + * @typedef {import('../../types/mcdev.d.js').CodeExtract} CodeExtract + * @typedef {import('../../types/mcdev.d.js').CodeExtractItem} CodeExtractItem + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItem} MetadataTypeItem + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItemDiff} MetadataTypeItemDiff + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItemObj} MetadataTypeItemObj + * @typedef {import('../../types/mcdev.d.js').MetadataTypeMap} MetadataTypeMap + * @typedef {import('../../types/mcdev.d.js').MetadataTypeMapObj} MetadataTypeMapObj + * @typedef {import('../../types/mcdev.d.js').SoapRequestParams} SoapRequestParams + * @typedef {import('../../types/mcdev.d.js').TemplateMap} TemplateMap + */ + +/** + * @typedef {import('../../types/mcdev.d.js').UserDocument} UserDocument + * @typedef {import('../../types/mcdev.d.js').UserDocumentDocument} UserDocumentDocument + * @typedef {import('../../types/mcdev.d.js').UserDocumentDiff} UserDocumentDiff + * @typedef {import('../../types/mcdev.d.js').UserDocumentMap} UserDocumentMap + * @typedef {import('../../types/mcdev.d.js').AccountUserConfiguration} AccountUserConfiguration + */ + +/** + * MetadataType + * + * @augments MetadataType + */ +class User extends MetadataType { + static userBUassignments; + static userIdBuMap; + + /** + * Retrieves SOAP based metadata of metadata type into local filesystem. executes callback with retrieved metadata + * + * @param {string} retrieveDir Directory where retrieved metadata directory will be saved + * @param {void | string[]} _ unused parameter + * @param {void | string[]} [__] unused parameter + * @param {string} [key] customer key of single item to retrieve + * @returns {Promise.<MetadataTypeMapObj>} Promise of metadata + */ + static async retrieve(retrieveDir, _, __, key) { + if (retrieveDir && this.buObject.eid !== this.buObject.mid) { + // only skip if this was not for caching + Util.logger.info(' - Skipping User retrieval on non-parent BU'); + return; + } + return this._retrieve(retrieveDir, key); + } + + /** + * Retrieves import definition metadata for caching + * + * @returns {Promise.<MetadataTypeMapObj>} Promise + */ + static async retrieveForCache() { + return this.retrieve(null); + } + + /** + * Create a single item. + * + * @param {MetadataTypeItem} metadata single metadata entry + * @returns {Promise} Promise + */ + static async create(metadata) { + if (this.buObject.eid !== this.buObject.mid) { + Util.logger.info(' - Skipping User creation on non-parent BU'); + return; + } + return super.createSOAP(metadata); + } + + /** + * Updates a single item. + * + * @param {MetadataTypeItem} metadata single metadata entry + * @returns {Promise} Promise + */ + static async update(metadata) { + if (this.buObject.eid !== this.buObject.mid) { + Util.logger.info(' - Skipping User update on non-parent BU'); + return; + } + return super.updateSOAP(metadata); + } + + /** + * prepares a item for deployment + * + * @param {UserDocument} metadata of a single item + * @returns {Promise.<UserDocument>} metadata object + */ + static async preDeployTasks(metadata) { + metadata.Client = { + ID: this.buObject.mid, + }; + + // convert roles into API compliant format + if (metadata.c__RoleNamesGlobal?.length) { + metadata.Roles = { + Role: metadata.c__RoleNamesGlobal + .filter( + // individual role (which are not manageable nor visible in the GUI) + (roleName) => !roleName.startsWith('Individual role for ') + ) + .map((roleName) => { + let roleCache; + try { + const roleKey = cache.searchForField( + 'role', + roleName, + 'Name', + 'CustomerKey' + ); + roleCache = cache.getByKey('role', roleKey + ''); + } catch { + // skip this role in case of errors + return; + } + if (roleCache?.c__notAssignable) { + throw new Error( + `Default roles starting on 'Marketing Cloud' are not assignable via API and get removed upon update. Please create/update the user manually in the GUI or remove that role.` + ); + } + return { + ObjectID: roleCache.ObjectID, + Name: roleName, + }; + }) + .filter(Boolean), + }; + } + delete metadata.c__RoleNamesGlobal; + + // check if DefaultBusinessUnit is listed in AssociatedBUs + if (!metadata.c__AssociatedBusinessUnits.includes(metadata.DefaultBusinessUnit)) { + metadata.c__AssociatedBusinessUnits.push(metadata.DefaultBusinessUnit); + Util.logger.info( + Util.getGrayMsg( + ` - adding DefaultBusinessUnit to list of associated Business Units (${metadata.CustomerKey} / ${metadata.Name}): ${metadata.DefaultBusinessUnit}` + ) + ); + } + if (metadata.c__AssociatedBusinessUnits.length) { + // ensure we do not have duplicates in the list - could happen due to user error or due to templating + metadata.c__AssociatedBusinessUnits = [...new Set(metadata.c__AssociatedBusinessUnits)]; + } + + // Timezone + if (metadata.c__TimeZoneName) { + // find the ID of the timezone + metadata.TimeZone = { Name: metadata.c__TimeZoneName }; + metadata.TimeZone.ID = + '' + + cache.searchForField('_timezone', metadata.c__TimeZoneName, 'description', 'id'); + delete metadata.c__TimeZoneName; + } + + // Locale + if (metadata.c__LocaleCode) { + // we cannot easily confirm if hte code is valid but SFMC's API will likely throw an error if not + metadata.Locale = { LocaleCode: metadata.c__LocaleCode }; + delete metadata.c__LocaleCode; + } + + // convert SSO / Federation Token into API compliant format + if (metadata.SsoIdentity || metadata.SsoIdentities) { + const ssoIdentity = {}; + let error = false; + if (metadata.SsoIdentity) { + // assume metadata.SsoIdentity is an object + ssoIdentity.IsActive = metadata.SsoIdentity.IsActive; + ssoIdentity.FederatedID = metadata.SsoIdentity.FederatedID; + delete metadata.SsoIdentity; + } else if (Array.isArray(metadata.SsoIdentities)) { + // be nice and allow SsoIdentities as an alternative if its an array of objects + ssoIdentity.IsActive = metadata.SsoIdentities[0].IsActive; + ssoIdentity.FederatedID = metadata.SsoIdentities[0].FederatedID; + } else if ( + Array.isArray(metadata.SsoIdentities?.SsoIdentity) && + metadata.SsoIdentities?.SsoIdentity.length + ) { + // API-compliant format already provided; just use it + ssoIdentity.IsActive = metadata.SsoIdentities.SsoIdentity[0]?.IsActive; + ssoIdentity.FederatedID = metadata.SsoIdentities.SsoIdentity[0]?.FederatedID; + } else { + error = true; + } + if ( + (ssoIdentity.IsActive !== true && ssoIdentity.IsActive !== false) || + !ssoIdentity.FederatedID || + error + ) { + throw new TypeError( + 'SsoIdentity should be an object with IsActive and FederatedID properties.' + ); + } + // if SsoIdentity is set, assume this was on purpose and bring it + metadata.SsoIdentities = { + SsoIdentity: [ + { + IsActive: ssoIdentity.IsActive, + FederatedID: ssoIdentity.FederatedID, + }, + ], + }; + } + + delete metadata.c__type; + delete metadata.c__AccountUserID; + delete metadata.c__IsLocked_readOnly; + + return metadata; + } + + /** + * MetadataType upsert, after retrieving from target and comparing to check if create or update operation is needed. + * + * @param {MetadataTypeMap} metadataMap metadata mapped by their keyField + * @param {string} deployDir directory where deploy metadata are saved + * @param {boolean} [runUpsertSequentially] when a type has self-dependencies creates need to run one at a time and created/changed keys need to be cached to ensure following creates/updates have thoses keys available + * @returns {Promise.<MetadataTypeMap>} keyField => metadata map + */ + static async upsert(metadataMap, deployDir, runUpsertSequentially = false) { + if (typeof this.userIdBuMap !== 'object' || Object.keys(this.userIdBuMap).length === 0) { + this.cacheBusinessUnitAssignments(); + } + + return super.upsert(metadataMap, deployDir, runUpsertSequentially); + } + + /** + * helper for {@link MetadataType.upsert} + * + * @param {MetadataTypeMap} metadata list of metadata + * @param {string} metadataKey key of item we are looking at + * @param {boolean} hasError error flag from previous code + * @param {UserDocumentDiff[]} metadataToUpdate list of items to update + * @param {UserDocument[]} metadataToCreate list of items to create + * @returns {Promise.<'create'|'update'|'skip'>} action to take + */ + static async createOrUpdate( + metadata, + metadataKey, + hasError, + metadataToUpdate, + metadataToCreate + ) { + const action = await super.createOrUpdate( + metadata, + metadataKey, + hasError, + metadataToUpdate, + metadataToCreate + ); + + if (action === 'create') { + const createItem = metadataToCreate.at(-1); + User._setPasswordForNewUser(createItem); + User._prepareRoleAssignments({ before: null, after: createItem }); + User._prepareBuAssignments(metadata[metadataKey], null, createItem); + } else if (action === 'update') { + const updateItem = metadataToUpdate.at(-1); + User._prepareRoleAssignments(updateItem); + User._prepareBuAssignments(metadata[metadataKey], updateItem, null); + } + return action; + } + + /** + * helper for {@link createOrUpdate} + * + * @private + * @param {MetadataTypeItem} metadata single metadata itme + * @param {UserDocumentDiff} [updateItem] item to update + * @param {UserDocument} [createItem] item to create + */ + static _prepareBuAssignments(metadata, updateItem, createItem) { + this.userBUassignments ||= { add: {}, delete: {} }; + if (updateItem) { + // remove business units that were unassigned + const deletedBUs = []; + updateItem.before.c__AssociatedBusinessUnits = + this.userIdBuMap[updateItem.before.ID] || []; + for (const oldBuAssignment of updateItem.before.c__AssociatedBusinessUnits) { + // check if oldRole is missing in list of new roles + if (!updateItem.after.c__AssociatedBusinessUnits.includes(oldBuAssignment)) { + deletedBUs.push(oldBuAssignment); + } + } + if (deletedBUs.length > 0) { + this.userBUassignments['delete'][updateItem.before.AccountUserID] = deletedBUs; + } + // add business units that were newly assigned + const addedBUs = []; + for (const newBuAssignment of updateItem.after.c__AssociatedBusinessUnits) { + // check if oldRole is missing in list of new roles + if (!updateItem.before.c__AssociatedBusinessUnits.includes(newBuAssignment)) { + addedBUs.push(newBuAssignment); + } + } + if (addedBUs.length > 0) { + this.userBUassignments['add'][updateItem.before.AccountUserID] = addedBUs; + } + } + // add BUs for new users + if (createItem) { + const addedBUs = createItem.c__AssociatedBusinessUnits || []; + if (addedBUs.length > 0) { + this.userBUassignments['add']['key:' + createItem.CustomerKey] = addedBUs; + } + } + delete metadata.c__AssociatedBusinessUnits; + } + + /** + * Gets executed after deployment of metadata type + * + * @param {UserDocumentMap} upsertResults metadata mapped by their keyField + * @returns {Promise.<void>} promise + */ + static async postDeployTasks(upsertResults) { + if (Object.keys(upsertResults).length) { + await this._handleBuAssignments(upsertResults); + } + } + + /** + * create/update business unit assignments. helper for {@link postDeployTasks} + * + * @private + * @param {UserDocumentMap} upsertResults metadata mapped by their keyField + * @returns {Promise.<void>} - + */ + static async _handleBuAssignments(upsertResults) { + /** @type {AccountUserConfiguration[]} */ + const configs = []; + for (const action in this.userBUassignments) { + for (const data of Object.entries(this.userBUassignments[action])) { + const buIds = data[1]; + let userId = data[0]; + if (!userId) { + continue; + } + userId = userId.startsWith('key:') ? upsertResults[userId.slice(4)].ID : userId; + configs.push( + /** @type {AccountUserConfiguration} */ { + Client: { ID: this.buObject.eid }, + ID: userId, + BusinessUnitAssignmentConfiguration: { + BusinessUnitIds: { BusinessUnitId: buIds }, + IsDelete: action === 'delete', + }, + } + ); + } + } + if (configs.length > 0) { + Util.logger.info('Deploying: BU assignment changes'); + // run update + const buResponse = await this.client.soap.configure('AccountUser', configs); + // process response + if (buResponse.OverallStatus === 'OK') { + // get userIdNameMap + const userIdNameMap = {}; + for (const user of Object.values(upsertResults)) { + userIdNameMap[user.ID] = `${user.CustomerKey} / ${user.Name}`; + } + // log what was added / removed + let configureResults = buResponse.Results?.[0]?.Result; + if (!configureResults) { + Util.logger.debug( + 'buResponse.Results?.[0]?.Result not defined: ' + JSON.stringify(buResponse) + ); + return; + } + if (!Array.isArray(configureResults)) { + configureResults = [configureResults]; + } + const userBUresults = {}; + for (const result of configureResults) { + if (result.StatusCode === 'OK') { + /** @type {AccountUserConfiguration} */ + const config = result.Object; + const buArr = + config.BusinessUnitAssignmentConfiguration.BusinessUnitIds + .BusinessUnitId; + userBUresults[config.ID] ||= { + add: [], + delete: [], + }; + userBUresults[config.ID][ + config.BusinessUnitAssignmentConfiguration.IsDelete ? 'delete' : 'add' + ] = Array.isArray(buArr) ? buArr : [buArr]; + } else { + Util.logger.debug( + `Unknown error occured during processing of BU assignment reponse: ${JSON.stringify( + result + )}` + ); + } + } + for (const [userId, buResult] of Object.entries(userBUresults)) { + // show CLI log + const msgs = []; + if (buResult['add']?.length) { + msgs.push(`MID ${buResult['add'].join(', ')} access granted`); + } else { + msgs.push('no new access granted'); + } + if (buResult['delete']?.length) { + msgs.push(`MID ${buResult['delete'].join(', ')} access removed`); + } else { + msgs.push('no access removed'); + } + Util.logger.info(` - user ${userIdNameMap[userId]}: ${msgs.join(' / ')}`); + // update BU map in local variable + if (buResult['add']?.length) { + this.userIdBuMap[userId] ||= []; + this.userIdBuMap[userId].push( + ...buResult['add'].filter( + (item) => !this.userIdBuMap[userId].includes(item) + ) + ); + } + if (buResult['delete']?.length) { + this.userIdBuMap[userId] ||= []; + this.userIdBuMap[userId] = this.userIdBuMap[userId].filter( + (item) => !buResult['delete'].includes(item) + ); + } + } + } + } + } + + /** + * helper for {@link User.createOrUpdate} + * + * @private + * @param {UserDocument} metadata single created user + * @returns {void} + */ + static _setPasswordForNewUser(metadata) { + // if Password is not set during CREATE, generate one + // avoids error "Name, Email, UserID, and Password are required fields when creating a new user. (Code 11003)" + if (!metadata.Password) { + metadata.Password = this._generatePassword(); + Util.logger.info( + ` - Password for ${metadata.UserID} was not given. Generated password:` + ); + // use console.log here to print the generated password to bypass the logfile + // eslint-disable-next-line no-console + console.log(metadata.Password); + } + } + + /** + * helper for {@link User.createOrUpdate} + * It searches for roles that were removed from the user and unassigns them; it also prints a summary of added/removed roles + * Adding roles works automatically for roles listed on the user + * + * @private + * @param {UserDocumentDiff} item updated user with before and after state + * @returns {void} + */ + static _prepareRoleAssignments(item) { + // delete global roles from user that were not in the c__RoleNamesGlobal array / Roles.Role + const deletedRoles = []; + const deletedRoleNames = []; + if (item.after?.Roles?.Role && !Array.isArray(item.after.Roles.Role)) { + item.after.Roles.Role = [item.after.Roles.Role]; + } + if (item.before?.Roles?.Role) { + if (!Array.isArray(item.before.Roles.Role)) { + item.before.Roles.Role = [item.before.Roles.Role]; + } + for (const oldRole of item.before.Roles.Role) { + // check if oldRole is missing in list of new roles --> removing role + let oldRoleFound = false; + if (item.after.Roles?.Role) { + for (const newRole of item.after.Roles.Role) { + if (newRole.ObjectID == oldRole.ObjectID) { + oldRoleFound = true; + break; + } + } + } + if (!oldRoleFound && !oldRole.Name.startsWith('Individual role for ')) { + // delete role unless it is an individual role (which are not manageable nor visible in the GUI) + deletedRoles.push({ ObjectID: oldRole.ObjectID, Name: oldRole.Name }); + deletedRoleNames.push(oldRole.Name); + } + } + } + const addedRoleNames = []; + if (item.after?.Roles?.Role) { + for (const newRole of item.after.Roles.Role) { + // check if newRole is missing in list of old roles --> adding role + let roleAlreadyExisting = false; + if (item.before?.Roles?.Role) { + for (const oldRole of item.before.Roles.Role) { + if (newRole.ObjectID == oldRole.ObjectID) { + roleAlreadyExisting = true; + break; + } + } + } + if (!roleAlreadyExisting) { + addedRoleNames.push(newRole.Name); + // Note: no AssignmentConfigurations property is needed to ADD global roles + } + } + if (addedRoleNames.length) { + Util.logger.info( + Util.getGrayMsg( + ` - adding role-assignment (${item.after.CustomerKey} / ${ + item.after.Name + }): ${addedRoleNames.join(', ')}` + ) + ); + } + } + if (deletedRoles.length) { + Util.logger.info( + Util.getGrayMsg( + ` - removing role-assignment (${item.after.CustomerKey} / ${ + item.after.Name + }): ${deletedRoleNames.join(', ')}` + ) + ); + // add deleted roles to payload with IsDelete=true + if (!item.after.Roles) { + item.after.Roles = { Role: [] }; + } else if (!item.after.Roles.Role) { + item.after.Roles.Role = []; + } + item.after.Roles.Role.push( + ...deletedRoles.map((role) => + this._getRoleObjectForDeploy( + role.ObjectID, + role.Name, + item.after.AccountUserID, + false, + true + ) + ) + ); + } + } + + /** + * helper for {@link User._prepareRoleAssignments} + * + * @param {string} roleId role.ObjectID + * @param {string} roleName role.Name + * @param {number} userId user.AccountUserID + * @param {boolean} assignmentOnly if true, only assignment configuration will be returned + * @param {boolean} [isRoleRemovale] if true, role will be removed from user; otherwise added + * @returns {object} format needed by API + */ + static _getRoleObjectForDeploy( + roleId, + roleName, + userId, + assignmentOnly, + isRoleRemovale = false + ) { + const assignmentConfigurations = { + AssignmentConfiguration: [ + { + AccountUserId: userId, + AssignmentConfigureType: 'RoleUser', + IsDelete: isRoleRemovale, + }, + ], + }; + return assignmentOnly + ? assignmentConfigurations + : { + ObjectID: roleId, + Name: roleName, + AssignmentConfigurations: assignmentConfigurations, + }; + } + + /** + * Retrieves SOAP based metadata of metadata type into local filesystem. executes callback with retrieved metadata + * + * @returns {Promise.<MetadataTypeMapObj>} Promise of metadata + */ + static async retrieveChangelog() { + return this._retrieve(); + } + + /** + * Retrieves SOAP based metadata of metadata type into local filesystem. executes callback with retrieved metadata + * + * @private + * @param {string} [retrieveDir] Directory where retrieved metadata directory will be saved + * @param {string} [key] customer key of single item to retrieve + * @returns {Promise.<MetadataTypeMapObj>} Promise of metadata + */ + static async _retrieve(retrieveDir, key) { + /** @type {SoapRequestParams} */ + const requestParams = { + QueryAllAccounts: true, + + filter: { + // normal users + leftOperand: 'Email', + operator: 'like', + rightOperand: '@', + }, + }; + if (key) { + // move original filter down one level into rightOperand and add key filter into leftOperand + requestParams.filter = { + leftOperand: { + leftOperand: 'CustomerKey', + operator: 'equals', + rightOperand: key, + }, + operator: 'AND', + rightOperand: requestParams.filter, + }; + } else { + // if we are not filtering by key the following requests will take long. Warn the user + Util.logger.info(` - Loading ${this.definition.type}s. This might take a while...`); + } + + // get actual user details + return this.retrieveSOAP(retrieveDir, requestParams, key); + } + + /** + * Retrieves SOAP via generic fuel-soap wrapper based metadata of metadata type into local filesystem. executes callback with retrieved metadata + * + * @param {string} retrieveDir Directory where retrieved metadata directory will be saved + * @param {SoapRequestParams} [requestParams] required for the specific request (filter for example) + * @param {string} [singleRetrieve] key of single item to filter by + * @param {string[]} [additionalFields] Returns specified fields even if their retrieve definition is not set to true + * @returns {Promise.<MetadataTypeMapObj>} Promise of item map + */ + static async retrieveSOAP(retrieveDir, requestParams, singleRetrieve, additionalFields) { + // to avoid not retrieving roles and userPermissions for users above the 2500 records limit we need to retrieve users twice, once with ActiveFlag=true and once with ActiveFlag=false + const requestParamsUser = { + QueryAllAccounts: true, + filter: { + leftOperand: { + leftOperand: 'ActiveFlag', + operator: 'equals', + rightOperand: null, + }, + operator: 'AND', + rightOperand: requestParams.filter, + }, + }; + const fields = this.getFieldNamesToRetrieve(additionalFields, !retrieveDir); + const soapType = this.definition.soapType || this.definition.type; + let resultsBulk; + let foundSingle = false; + for (const active of [true, false]) { + requestParamsUser.filter.leftOperand.rightOperand = active; + try { + const resultsBatch = await this.client.soap.retrieveBulk( + soapType, + fields, + requestParamsUser + ); + if (Array.isArray(resultsBatch?.Results)) { + Util.logger.debug( + Util.getGrayMsg( + ` - found ${resultsBatch?.Results.length} ${ + active ? 'active' : 'inactive' + } ${this.definition.type}s` + ) + ); + if (resultsBulk) { + // once first batch is done, the follow just add to result payload + resultsBulk.Results.push(...resultsBatch.Results); + } else { + resultsBulk = resultsBatch; + } + if (singleRetrieve && resultsBatch?.Results.length) { + foundSingle = true; + break; + } + } + } catch (ex) { + this._handleSOAPErrors(ex, 'retrieving'); + return; + } + } + if ( + !foundSingle && + !(await this._retrieveSOAP_installedPackage( + requestParams, + soapType, + fields, + resultsBulk + )) + ) { + return; + } + + const metadata = this.parseResponseBody(resultsBulk); + if (retrieveDir) { + if (!singleRetrieve) { + Util.logger.info( + Util.getGrayMsg(` - found ${resultsBulk?.Results.length} users`) + ); + } + if (resultsBulk?.Results?.length > 0) { + // get BUs that each users have access to + // split array resultsBulk?.Results into chunks to avoid not getting all roles + await this.cacheBusinessUnitAssignments(resultsBulk.Results); + } + + const savedMetadata = await this.saveResults(metadata, retrieveDir, null); + Util.logger.info( + `Downloaded: ${this.definition.type} (${Object.keys(savedMetadata).length})` + + Util.getKeysString(singleRetrieve) + ); + if (!singleRetrieve) { + // print summary to cli + const counter = { + userActive: 0, + userInactive: 0, + installedPackage: 0, + }; + for (const id in savedMetadata) { + /** @typedef {UserDocument} */ + const item = savedMetadata[id]; + if (item.c__type === 'Installed Package') { + counter.installedPackage++; + } else if (item.ActiveFlag) { + counter.userActive++; + } else { + counter.userInactive++; + } + } + Util.logger.info( + Util.getGrayMsg( + `Found ${counter.userActive} active users / ${counter.userInactive} inactive users / ${counter.installedPackage} installed packages` + ) + ); + } + await this.runDocumentOnRetrieve(singleRetrieve, savedMetadata); + } + return { metadata: metadata, type: this.definition.type }; + } + + /** + * helper for {@link retrieveSOAP} and {@link upsert}; populates userIdBuMap + * + * @param {MetadataTypeItem[]} [metadataList] - + * @returns {Promise.<void>} - + */ + static async cacheBusinessUnitAssignments(metadataList) { + if (!metadataList) { + // if run via upsert() then we won't have the metadataList with AccountUserID anywhere but in cache + const cacheUsers = cache.getCache().user; + metadataList = cacheUsers ? Object.values(cacheUsers) : []; + } + const chunkSize = 100; + this.userIdBuMap = {}; + Util.logger.info(` - Caching dependent Metadata: Business Unit assignments`); + for (let i = 0; i < metadataList?.length; i += chunkSize) { + if (i > 0) { + Util.logger.info( + Util.getGrayMsg(` - Requesting next batch (retrieved BUs for ${i} users)`) + ); + } + const accountUserIDList = metadataList + .map((item) => item.AccountUserID) + .filter(Boolean); + const chunk = accountUserIDList?.slice(i, i + chunkSize); + const resultsBatch = ( + await this.client.soap.retrieveBulk( + 'AccountUserAccount', + ['AccountUser.AccountUserID', 'Account.ID'], + { + filter: { + leftOperand: 'AccountUser.AccountUserID', + operator: chunk.length > 1 ? 'IN' : 'equals', // API does not allow IN for single item + rightOperand: chunk, + }, + } + ) + ).Results; + for (const item of resultsBatch) { + this.userIdBuMap[item.AccountUser.AccountUserID] ||= []; + // push to array if not already in array + if (!this.userIdBuMap[item.AccountUser.AccountUserID].includes(item.Account.ID)) { + this.userIdBuMap[item.AccountUser.AccountUserID].push(item.Account.ID); + } + } + } + } + + /** + * helper for {@link User.retrieveSOAP} + * + * @private + * @param {SoapRequestParams} requestParams required for the specific request (filter for example) + * @param {string} soapType e.g. AccountUser + * @param {string[]} fields list of fields to retrieve + * @param {object} resultsBulk actual return value of this method + * @returns {Promise.<boolean>} success flag + */ + static async _retrieveSOAP_installedPackage(requestParams, soapType, fields, resultsBulk) { + /** @type {SoapRequestParams} */ + const requestParamsInstalledPackage = { + QueryAllAccounts: true, + + filter: { + leftOperand: { + leftOperand: 'ActiveFlag', + operator: 'equals', + rightOperand: true, // inactive installed packages are not visible in UI and hence cannot be reactivated there. Let's not retrieve them + }, + operator: 'AND', + rightOperand: { + leftOperand: { + // filter out normal users + leftOperand: 'Email', + operator: 'isNull', + }, + operator: 'OR', + rightOperand: { + // installed packages + leftOperand: { + leftOperand: 'Name', + operator: 'like', + rightOperand: ' app user', // ! will not work if the name was too long as "app user" might be cut off + }, + operator: 'AND', + rightOperand: { + // this is used to filter out system generated installed packages. in our testing, at least those installed packages created in the last few years have hat set this to false while additional (hidden) installed packages have it set to true. + leftOperand: 'MustChangePassword', + operator: 'equals', + rightOperand: 'false', + }, + }, + }, + }, + }; + if ( + 'object' === typeof requestParams?.filter?.leftOperand && + requestParams?.filter?.leftOperand?.leftOperand === 'CustomerKey' + ) { + requestParamsInstalledPackage.filter = { + leftOperand: requestParams?.filter?.leftOperand, + operator: 'AND', + rightOperand: requestParamsInstalledPackage.filter, + }; + } + try { + const resultsBatch = await this.client.soap.retrieveBulk( + soapType, + fields, + requestParamsInstalledPackage + ); + if (Array.isArray(resultsBatch?.Results)) { + Util.logger.debug( + Util.getGrayMsg(` - found ${resultsBatch?.Results.length} installed packages`) + ); + if (resultsBulk) { + // once first batch is done, the follow just add to result payload + resultsBulk.Results.push(...resultsBatch.Results); + } else { + resultsBulk = resultsBatch; + } + } + } catch (ex) { + this._handleSOAPErrors(ex, 'retrieving'); + return false; + } + return true; + } + + /** + * + * @param {string} dateStr first date + * @param {string} interval defaults to 'days' + * @returns {string} time difference + */ + static #timeSinceDate(dateStr, interval = 'days') { + const second = 1000, + minute = second * 60, + hour = minute * 60, + day = hour * 24, + week = day * 7; + const date = new Date(dateStr); + const now = new Date(); + // get difference in miliseconds + const timediff = now.valueOf() - date.valueOf(); + if (Number.isNaN(timediff)) { + return ''; + } + let result; + switch (interval) { + case 'years': { + result = now.getFullYear() - date.getFullYear(); + break; + } + case 'months': { + result = + now.getFullYear() * 12 + + now.getMonth() - + (date.getFullYear() * 12 + date.getMonth()); + break; + } + case 'weeks': { + result = Math.floor(timediff / week); + break; + } + case 'days': { + result = Math.floor(timediff / day); + break; + } + case 'hours': { + result = Math.floor(timediff / hour); + break; + } + case 'minutes': { + result = Math.floor(timediff / minute); + break; + } + case 'seconds': { + result = Math.floor(timediff / second); + break; + } + default: { + return; + } + } + return result + ' ' + interval; + } + + /** + * helper to print bu names + * + * @private + * @param {number} id bu id + * @returns {string} "bu name (bu id)"" + */ + static _getBuName(id) { + const name = this.buObject.eid == id ? '_ParentBU_' : this.buIdName[id]; + return `<nobr>${name} (${id})</nobr>`; + } + + /** + * helper that gets BU names from config + * + * @private + */ + static _getBuNames() { + this.buIdName = {}; + for (const cred in this.properties.credentials) { + for (const buName in this.properties.credentials[cred].businessUnits) { + this.buIdName[this.properties.credentials[cred].businessUnits[buName]] = buName; + } + } + } + + /** + * helper for {@link User.createOrUpdate} to generate a random initial password for new users + * note: possible minimum length values in SFMC are 6, 8, 10, 15 chars. Therefore we should default here to 15 chars. + * + * @private + * @param {number} [length] length of password; defaults to 15 + * @returns {string} random password + */ + static _generatePassword(length = 15) { + const alpha = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'; + const special = '!@#$%&'; + const numeric = '0123456789'; + const charset = alpha + special + numeric; + let retVal; + do { + retVal = ''; + for (let i = 0, n = charset.length; i < length; ++i) { + retVal += charset.charAt(Math.floor(Math.random() * n)); + } + // check if password contains at least one of each character type or else generate a new one + } while ( + !/[a-z]/.test(retVal) || + !/[A-Z]/.test(retVal) || + !/[0-9]/.test(retVal) || + !/[!@#$%&]/.test(retVal) + ); + return retVal; + } + + /** + * Creates markdown documentation of all roles + * + * @param {UserDocumentMap} [metadata] user list + * @returns {Promise.<void>} - + */ + static async document(metadata) { + if (this.buObject.eid !== this.buObject.mid) { + Util.logger.error( + `Users can only be retrieved & documented for the ${Util.parentBuName}` + ); + return; + } + + if (!metadata) { + // load users from disk if document was called directly and not part of a retrieve + try { + metadata = ( + await this.readBUMetadataForType( + File.normalizePath([ + this.properties.directories.retrieve, + this.buObject.credential, + Util.parentBuName, + ]), + true + ) + ).user; + } catch (ex) { + Util.logger.error(ex.message); + return; + } + } + + // init map of BU Ids > BU Name + this._getBuNames(); + + /** @type {UserDocumentDocument[]} */ + const users = []; + + for (const id in metadata) { + const user = metadata[id]; + // TODO resolve user permissions to something readable + // user roles + let roles = ''; + if (user.c__RoleNamesGlobal) { + roles = '<nobr>' + user.c__RoleNamesGlobal.join(',</nobr><br> <nobr>') + '</nobr>'; + } + let associatedBus = ''; + if (user.c__AssociatedBusinessUnits) { + // ensure Parent BU is first in list + user.c__AssociatedBusinessUnits.push(user.DefaultBusinessUnit); + // ensure associatedBus have no duplicates + associatedBus = [ + ...new Set(user.c__AssociatedBusinessUnits.map((mid) => this._getBuName(mid))), + ] + .toSorted((a, b) => (a < b ? -1 : a > b ? 1 : 0)) + .join(',<br> '); + } + const defaultBUName = this._getBuName(user.DefaultBusinessUnit); + const LastSuccessfulLogin = user.LastSuccessfulLogin.split('.')[0]; + + users.push({ + ...user, // keep that here to satisfy the type + TYPE: user.c__type, + UserID: user.UserID, + AccountUserID: user.c__AccountUserID, + CustomerKey: user.CustomerKey, + Name: user.Name, + Email: user.Email, + NotificationEmailAddress: user.NotificationEmailAddress, + ActiveFlagDocs: user.ActiveFlag === true ? '✓' : '-', + IsLockedDocs: user.IsLocked === true ? '✓' : '-', + IsAPIUserDocs: user.IsAPIUser === true ? '✓' : '-', + MustChangePasswordDocs: user.MustChangePassword === true ? '✓' : '-', + DefaultBusinessUnitDocs: defaultBUName, + AssociatedBusDocs: associatedBus, + RolesDocs: roles, + LastSuccessfulLogin: user.LastSuccessfulLogin + ? // on create & update, LastSuccessfulLogin often gets overwritten with the current date + LastSuccessfulLogin === user.CreatedDate.split('.')[0] || + LastSuccessfulLogin === user.ModifiedDate.split('.')[0] + ? 'unknown' + : this.#timeSinceDate(user.LastSuccessfulLogin) + : 'never', + CreatedDate: user.CreatedDate ? user.CreatedDate.split('T').join(' ') : 'n/a', + ModifiedDate: user.ModifiedDate ? user.ModifiedDate.split('T').join(' ') : 'n/a', + ModifiedBy: user.Client.ModifiedBy || 'n/a', + TimeZoneName: user.c__TimeZoneName.slice(1, 10), + c__LocaleCode: user.c__LocaleCode, + }); + } + users.sort((a, b) => (a.Name < b.Name ? -1 : a.Name > b.Name ? 1 : 0)); + const columnsToPrint = [ + ['Name', 'Name'], + ['Last successful Login', 'LastSuccessfulLogin'], + ['Active', 'ActiveFlagDocs'], + ['Access Locked out', 'IsLockedDocs'], + ['API User', 'IsAPIUserDocs'], + ['Must change PW', 'MustChangePasswordDocs'], + ['Default BU', 'DefaultBusinessUnitDocs'], + ['BU Access', 'AssociatedBusDocs'], + ['Roles', 'RolesDocs'], + ['Login', 'UserID'], + ['ID', 'AccountUserID'], + ['Key', 'CustomerKey'], + ['E-Mail', 'Email'], + ['Notification E-Mail', 'NotificationEmailAddress'], + ['Timezone', 'TimeZoneName'], + ['SFMC Locale', 'c__LocaleCode'], + ['Modified Date', 'ModifiedDate'], + ['Modified By', 'ModifiedBy'], + ['Created Date', 'CreatedDate'], + ]; + let output = `# User Overview - ${this.buObject.credential}`; + output += this._generateDocMd( + users.filter((user) => user.TYPE === 'User' && user.ActiveFlagDocs === '✓'), + 'User', + columnsToPrint + ); + output += this._generateDocMd( + users.filter((user) => user.TYPE === 'User' && user.ActiveFlagDocs === '-'), + 'Inactivated User', + columnsToPrint + ); + output += this._generateDocMd( + users.filter((user) => user.TYPE === 'Installed Package'), + 'Installed Package', + columnsToPrint + ); + const docPath = File.normalizePath([this.properties.directories.docs, 'user']); + + try { + const filename = this.buObject.credential; + // write to disk + await File.writeToFile(docPath, filename + '.users', 'md', output); + Util.logger.info(`Created ${File.normalizePath([docPath, filename])}.users.md`); + if (['html', 'both'].includes(this.properties.options.documentType)) { + Util.logger.warn(' - HTML-based documentation of user currently not supported.'); + } + } catch (ex) { + Util.logger.error(`user.document():: error | `, ex.message); + } + } + + /** + * + * @private + * @param {object[]} users list of users and installed package + * @param {'Installed Package'|'User'|'Inactivated User'} type choose what sub type to print + * @param {Array[]} columnsToPrint helper array + * @returns {string} markdown + */ + static _generateDocMd(users, type, columnsToPrint) { + let output = `\n\n## ${type}s (${users.length})\n\n`; + let tableSeparator = ''; + for (const column of columnsToPrint) { + output += `| ${column[0]} `; + tableSeparator += '| --- '; + } + output += `|\n${tableSeparator}|\n`; + for (const user of users) { + for (const column of columnsToPrint) { + output += `| ${user[column[1]]} `; + } + output += `|\n`; + } + return output; + } + + /** + * manages post retrieve steps + * + * @param {UserDocument} metadata a single item + * @returns {MetadataTypeItem | void} a single item + */ + static postRetrieveTasks(metadata) { + metadata.c__type = 'Installed Package'; + if (metadata.Email.includes('@') && !metadata.Name.endsWith('app user')) { + metadata.c__type = 'User'; + } + if (metadata.c__type === 'Installed Package' && !metadata.ActiveFlag) { + // deleted installed package - we do try to filter them in the API call but sometimes they slip through in the other calls + return; + } + + // rewrite AccountUserID to avoid accidental overwrites by create attempts but still allow users to search for this ID + metadata.c__AccountUserID = metadata.AccountUserID; + delete metadata.AccountUserID; + + // the actual field cannot be updated. to avoid confusion, we rename it + metadata.c__IsLocked_readOnly = metadata.IsLocked; + delete metadata.IsLocked; + if (metadata.c__IsLocked_readOnly) { + // add this field in case the user is locked to offer the opportunity to unlock it via api + metadata.Unlock = false; + } + + metadata.c__AssociatedBusinessUnits = this.userIdBuMap[metadata.ID] || []; + metadata.c__AssociatedBusinessUnits.sort(); + + // make roles easily accessible + let roles; + if (metadata.Roles?.Role) { + // normalize to always use array + if (!metadata.Roles.Role.length) { + metadata.Roles.Role = [metadata.Roles.Role]; + } + // convert complex object into basic set of info + // turns out, Role Names are unique and hence we can turn this into a simple array of names + roles = metadata.Roles.Role.map((item) => item.Name) + .filter(Boolean) + .filter( + // individual role (which are not manageable nor visible in the GUI) + (roleName) => !roleName.startsWith('Individual role for ') + ) + .toSorted((a, b) => (a < b ? -1 : a > b ? 1 : 0)); + } else { + // set to empty array + roles = []; + } + metadata.c__RoleNamesGlobal = roles; + delete metadata.Roles; + + // Timezone + if (metadata.TimeZone?.ID) { + metadata.c__TimeZoneName = cache.searchForField( + '_timezone', + metadata.TimeZone.ID, + 'id', + 'description' + ); + delete metadata.TimeZone; + } + + // Locale + if (metadata.Locale?.LocaleCode) { + metadata.c__LocaleCode = metadata.Locale.LocaleCode; + delete metadata.Locale; + } + + return metadata; + } +} + +// Assign definition to static attributes +import MetadataTypeDefinitions from '../MetadataTypeDefinitions.js'; +User.definition = MetadataTypeDefinitions.user; + +export default User; diff --git a/lib/metadataTypes/Verification.js b/lib/metadataTypes/Verification.js new file mode 100644 index 000000000..1e8218a70 --- /dev/null +++ b/lib/metadataTypes/Verification.js @@ -0,0 +1,304 @@ +'use strict'; + +import Automation from './Automation.js'; +import MetadataType from './MetadataType.js'; +import { Util } from '../util/util.js'; +import cache from '../util/cache.js'; + +/** + * @typedef {import('../../types/mcdev.d.js').BuObject} BuObject + * @typedef {import('../../types/mcdev.d.js').CodeExtract} CodeExtract + * @typedef {import('../../types/mcdev.d.js').CodeExtractItem} CodeExtractItem + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItem} MetadataTypeItem + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItemDiff} MetadataTypeItemDiff + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItemObj} MetadataTypeItemObj + * @typedef {import('../../types/mcdev.d.js').MetadataTypeMap} MetadataTypeMap + * @typedef {import('../../types/mcdev.d.js').MetadataTypeMapObj} MetadataTypeMapObj + * @typedef {import('../../types/mcdev.d.js').SoapRequestParams} SoapRequestParams + * @typedef {import('../../types/mcdev.d.js').TemplateMap} TemplateMap + * @typedef {import('../../types/mcdev.d.js').RestError} RestError + */ + +/** + * @typedef {import('../../types/mcdev.d.js').VerificationItem} VerificationItem + */ + +/** + * Verification MetadataType + * + * @augments MetadataType + */ +class Verification extends MetadataType { + static verificationIdKeyMap; + /** + * Retrieves Metadata of Data Verification Activity. + * + * @param {string} [retrieveDir] Directory where retrieved metadata directory will be saved + * @param {void | string[]} [_] unused parameter + * @param {void | string[]} [__] unused parameter + * @param {string} [key] customer key of single item to retrieve + * @returns {Promise.<MetadataTypeMapObj>} Promise of metadata + */ + static async retrieve(retrieveDir, _, __, key) { + const paramArr = []; + let automationKey; + if (key) { + const regex = /^(.*?)__s\d{1,3}\.\d{1,3}$/; + const match = key.match(regex); + if (match) { + // automation key found + automationKey = match[1]; + } else { + // invalid key, unset it + Util.logger.error(`Invalid key: ${key}`); + return; + } + } + const results = {}; + // there is no API endpoint to retrieve all dataVerification items, so we need to retrieve all automations and iterate over their activities + Util.logger.info(` - Caching dependent Metadata: automation`); + Automation.client = this.client; + Automation.buObject = this.buObject; + Automation.properties = this.properties; + Automation._skipNotificationRetrieve = true; + delete Automation._cachedMetadataMap; + const automationsMapObj = automationKey + ? await Automation.retrieve(undefined, undefined, undefined, automationKey) + : await Automation.retrieve(); + delete Automation._skipNotificationRetrieve; + if (automationsMapObj?.metadata && Object.keys(automationsMapObj?.metadata).length) { + if (!key) { + // if we are not retrieving a single item, cache the automations for later use during retrieval of automations + Automation._cachedMetadataMap = automationsMapObj?.metadata; + } + // automations found, lets iterate over their activities to find the dataVerification items + this.verificationIdKeyMap = {}; + for (const automation of Object.values(automationsMapObj.metadata)) { + if (automation.steps) { + for (const step of automation.steps) { + // ideally one would use activity.displayOrder here but that doesnt always start at 1 nor is it always sequential. To avoid cross-BU issues, we use a custom order + let order = 1; + for (const activity of step.activities) { + if ( + activity.objectTypeId === 1000 && + activity.activityObjectId && + activity.activityObjectId !== '00000000-0000-0000-0000-000000000000' + ) { + // log the verification id + this.verificationIdKeyMap[activity.activityObjectId] = + `${automation.key}__s${step.step}.${order}`; + } + order++; + } + } + } + } + if (Object.keys(this.verificationIdKeyMap).length) { + paramArr.push(...Object.keys(this.verificationIdKeyMap)); + } + } + if (paramArr.length) { + const response = await this.retrieveRESTcollection( + paramArr.map((id) => ({ id, uri: '/automation/v1/dataverifications/' + id })), + undefined, + !key + ); + if (response?.metadata) { + Object.assign(results, response.metadata); + } + } + if (retrieveDir) { + const savedMetadata = await this.saveResults(results, retrieveDir, null, null); + Util.logger.info( + `Downloaded: ${this.definition.type} (${Object.keys(savedMetadata).length})` + + Util.getKeysString(key) + ); + } + + return { + metadata: results, + type: this.definition.type, + }; + } + + /** + * helper for {@link this.retrieveRESTcollection} + * + * @param {RestError} ex exception + * @param {string} id id or key of item + * @returns {null} - + */ + static handleRESTErrors(ex, id) { + if (ex.message === 'Not Found' || ex.message === 'Request failed with status code 400') { + // if the ID is too short, the system will throw the 400 error + Util.logger.debug( + ` ☇ skipping ${this.definition.type} ${id}: ${ex.message} ${ex.code}` + ); + } else { + // if we do get here, we should log the error and continue instead of failing to download all automations + Util.logger.error( + ` ☇ skipping ${this.definition.type} ${id}: ${ex.message} ${ex.code}` + ); + } + return null; + } + + /** + * Retrieves Metadata of item for caching + * + * @returns {Promise.<MetadataTypeMapObj>} Promise of metadata + */ + static async retrieveForCache() { + return this.retrieve(); + } + + /** + * Creates a single item + * + * @param {VerificationItem} metadata a single item + * @returns {Promise} Promise + */ + static create(metadata) { + return super.createREST(metadata, '/automation/v1/dataverifications/'); + } + + /** + * helper for {@link MetadataType.createREST} + * + * @param {MetadataTypeItem} metadataEntry a single metadata Entry + * @param {object} apiResponse varies depending on the API call + * @param {MetadataTypeItem} metadataEntryWithAllFields like metadataEntry but before non-creatable fields were stripped + * @returns {Promise.<object>} apiResponse + */ + static async postCreateTasks(metadataEntry, apiResponse, metadataEntryWithAllFields) { + if (!apiResponse?.[this.definition.idField]) { + return; + } + // update apiResponse to ensure the new metadata is saved correctly on disk + apiResponse[this.definition.keyField] = + metadataEntryWithAllFields?.[this.definition.keyField]; + + // update info on metadataEntry to allow for proper logs + metadataEntry[this.definition.keyField] = + metadataEntryWithAllFields?.[this.definition.keyField]; + metadataEntry[this.definition.idField] = apiResponse?.[this.definition.idField]; + + return apiResponse; + } + /** + * helper for {@link MetadataType.updateREST} and {@link MetadataType.updateSOAP} + * + * @param {MetadataTypeItem} metadataEntry a single metadata Entry + * @param {object} apiResponse varies depending on the API call + * @param {MetadataTypeItem} metadataEntryWithAllFields like metadataEntry but before non-creatable fields were stripped + * @returns {Promise.<object>} apiResponse, potentially modified + */ + static postUpdateTasks(metadataEntry, apiResponse, metadataEntryWithAllFields) { + // update apiResponse to ensure the new metadata is saved correctly on disk + apiResponse[this.definition.keyField] = + metadataEntryWithAllFields?.[this.definition.keyField]; + + // update info on metadataEntry to allow for proper logs + metadataEntry[this.definition.keyField] = + metadataEntryWithAllFields?.[this.definition.keyField]; + metadataEntry[this.definition.idField] = apiResponse?.[this.definition.idField]; + return apiResponse; + } + + /** + * Updates a single item + * + * @param {VerificationItem} metadata a single item + * @returns {Promise} Promise + */ + static update(metadata) { + return super.updateREST( + metadata, + '/automation/v1/dataverifications/' + metadata.dataVerificationDefinitionId + ); + } + + /** + * prepares a verification for deployment + * + * @param {VerificationItem} metadata a single verification activity definition + * @returns {Promise.<VerificationItem>} metadata object + */ + static async preDeployTasks(metadata) { + metadata.targetObjectId = cache.searchForField( + 'dataExtension', + metadata.r__dataExtension_key, + 'CustomerKey', + 'ObjectID' + ); + delete metadata.r__dataExtension_key; + + return metadata; + } + + /** + * helper for {@link parseResponseBody} that creates a custom key field for this type based on mobileCode and keyword + * + * @param {MetadataTypeItem} metadata single item + */ + static createCustomKeyField(metadata) { + if (this.verificationIdKeyMap[metadata[this.definition.idField]]) { + metadata[this.definition.keyField] = + this.verificationIdKeyMap[metadata[this.definition.idField]]; + } + } + + /** + * parses retrieved Metadata before saving + * + * @param {VerificationItem} metadata a single verification activity definition + * @returns {VerificationItem} Array with one metadata object and one sql string + */ + static postRetrieveTasks(metadata) { + try { + // @ts-expect-error + metadata.createdBy = cache.searchForField( + 'user', + metadata.createdBy, + 'AccountUserID', + 'Name' + ); + } catch (ex) { + Util.logger.verbose( + ` - ${this.definition.type} ${metadata[this.definition.nameField]} (${ + metadata[this.definition.keyField] + }): ${ex.message}.` + ); + } + try { + metadata.r__dataExtension_key = cache.searchForField( + 'dataExtension', + metadata.targetObjectId, + 'ObjectID', + 'CustomerKey' + ); + delete metadata.targetObjectId; + } catch (ex) { + Util.logger.warn( + ` - ${this.definition.type} ${metadata[this.definition.keyField]}: ${ex.message}` + ); + } + return metadata; + } + + /** + * Delete a metadata item from the specified business unit + * + * @param {string} key Identifier of item + * @returns {Promise.<boolean>} deletion success status + */ + static deleteByKey(key) { + return super.deleteByKeyREST('/automation/v1/dataverifications/' + key, key, 400); + } +} + +// Assign definition to static attributes +import MetadataTypeDefinitions from '../MetadataTypeDefinitions.js'; +Verification.definition = MetadataTypeDefinitions.verification; + +export default Verification; diff --git a/lib/metadataTypes/definitions/AccountUser.definition.js b/lib/metadataTypes/definitions/AccountUser.definition.js deleted file mode 100644 index c24814c6f..000000000 --- a/lib/metadataTypes/definitions/AccountUser.definition.js +++ /dev/null @@ -1,227 +0,0 @@ -module.exports = { - bodyIteratorField: 'Results', - dependencies: [], - folderType: null, - hasExtended: false, - idField: 'ID', - keyField: 'CustomerKey', - nameField: 'Name', - type: 'accountUser', - typeDescription: 'Marketing Cloud users', - typeName: 'User', - typeRetrieveByDefault: false, - fields: { - AccountUserID: { - isCreateable: null, - isUpdateable: null, - retrieving: true, - template: false, - }, - ActiveFlag: { isCreateable: null, isUpdateable: null, retrieving: true, template: false }, - AssociatedBusinessUnits: { - isCreateable: null, - isUpdateable: null, - retrieving: false, - template: null, - }, - BusinessUnit: { - isCreateable: null, - isUpdateable: null, - retrieving: false, - template: null, - }, - ChallengeAnswer: { - isCreateable: null, - isUpdateable: null, - retrieving: true, - template: false, - }, - ChallengePhrase: { - isCreateable: null, - isUpdateable: null, - retrieving: true, - template: false, - }, - Client: { isCreateable: null, isUpdateable: null, retrieving: false, template: null }, - CorrelationID: { - isCreateable: null, - isUpdateable: null, - retrieving: false, - template: null, - }, - CreatedDate: { isCreateable: null, isUpdateable: null, retrieving: true, template: false }, - CustomerKey: { isCreateable: null, isUpdateable: null, retrieving: true, template: false }, - DefaultApplication: { - isCreateable: null, - isUpdateable: null, - retrieving: false, - template: null, - }, - DefaultBusinessUnit: { - isCreateable: null, - isUpdateable: null, - retrieving: true, - template: false, - }, - DefaultBusinessUnitObject: { - isCreateable: null, - isUpdateable: null, - retrieving: false, - template: null, - }, - Delete: { isCreateable: null, isUpdateable: null, retrieving: false, template: null }, - Email: { isCreateable: null, isUpdateable: null, retrieving: true, template: false }, - ID: { isCreateable: null, isUpdateable: null, retrieving: true, template: false }, - IsAPIUser: { isCreateable: null, isUpdateable: null, retrieving: true, template: false }, - IsLocked: { isCreateable: null, isUpdateable: null, retrieving: true, template: false }, - LanguageLocale: { - isCreateable: null, - isUpdateable: null, - retrieving: false, - template: null, - }, - LastSuccessfulLogin: { - isCreateable: null, - isUpdateable: null, - retrieving: true, - template: false, - }, - Locale: { isCreateable: null, isUpdateable: null, retrieving: false, template: null }, - ModifiedDate: { - isCreateable: null, - isUpdateable: null, - retrieving: true, - template: false, - }, - MustChangePassword: { - isCreateable: null, - isUpdateable: null, - retrieving: true, - template: false, - }, - Name: { isCreateable: null, isUpdateable: null, retrieving: true, template: false }, - NotificationEmailAddress: { - isCreateable: null, - isUpdateable: null, - retrieving: true, - template: false, - }, - ObjectID: { isCreateable: null, isUpdateable: null, retrieving: false, template: null }, - ObjectState: { isCreateable: null, isUpdateable: null, retrieving: false, template: null }, - Owner: { isCreateable: null, isUpdateable: null, retrieving: false, template: null }, - PartnerKey: { isCreateable: null, isUpdateable: null, retrieving: false, template: null }, - PartnerProperties: { - isCreateable: null, - isUpdateable: null, - retrieving: false, - template: null, - }, - Password: { isCreateable: null, isUpdateable: null, retrieving: false, template: false }, - Roles: { isCreateable: null, isUpdateable: null, retrieving: true, template: false }, - 'Roles.Role': { - skipValidation: false, - }, - 'Roles.Role[].Client': { - skipValidation: false, - }, - SsoIdentities: { - isCreateable: null, - isUpdateable: null, - retrieving: false, - template: null, - }, - TimeZone: { isCreateable: null, isUpdateable: null, retrieving: false, template: null }, - Unlock: { isCreateable: null, isUpdateable: null, retrieving: false, template: null }, - UserID: { isCreateable: null, isUpdateable: null, retrieving: true, template: false }, - UserPermissions: { - isCreateable: null, - isUpdateable: null, - retrieving: true, - template: false, - }, - 'UserPermissions.PartnerKey': { - isCreateable: null, - isUpdateable: null, - retrieving: false, - template: false, - }, - 'UserPermissions.ID': { - skipValidation: true, - }, - 'UserPermissions.ObjectID': { - isCreateable: null, - isUpdateable: null, - retrieving: false, - template: false, - }, - 'UserPermissions.Name': { - isCreateable: null, - isUpdateable: null, - retrieving: false, - template: false, - }, - 'UserPermissions.Value': { - isCreateable: null, - isUpdateable: null, - retrieving: false, - template: false, - }, - 'UserPermissions.Description': { - isCreateable: null, - isUpdateable: null, - retrieving: false, - template: false, - }, - 'UserPermissions.Delete': { - isCreateable: null, - isUpdateable: null, - retrieving: false, - template: false, - }, - 'UserPermissions[].PartnerKey': { - isCreateable: null, - isUpdateable: null, - retrieving: false, - template: false, - }, - 'UserPermissions[].ID': { - skipValidation: true, - }, - 'UserPermissions[].ObjectID': { - isCreateable: null, - isUpdateable: null, - retrieving: false, - template: false, - }, - 'UserPermissions[].Name': { - isCreateable: null, - isUpdateable: null, - retrieving: false, - template: false, - }, - 'UserPermissions[].Value': { - isCreateable: null, - isUpdateable: null, - retrieving: false, - template: false, - }, - 'UserPermissions[].Description': { - isCreateable: null, - isUpdateable: null, - retrieving: false, - template: false, - }, - 'UserPermissions[].Delete': { - isCreateable: null, - isUpdateable: null, - retrieving: false, - template: false, - }, - type__c: { - skipValidation: true, - }, - AssociatedBusinessUnits__c: { - skipValidation: true, - }, - }, -}; diff --git a/lib/metadataTypes/definitions/Asset.definition.js b/lib/metadataTypes/definitions/Asset.definition.js index eef2d5d40..8eaf291b2 100644 --- a/lib/metadataTypes/definitions/Asset.definition.js +++ b/lib/metadataTypes/definitions/Asset.definition.js @@ -1,17 +1,37 @@ // asset types https://developer.salesforce.com/docs/atlas.en-us.noversion.mc-apis.meta/mc-apis/base-asset-types.htm -module.exports = { +export default { bodyIteratorField: 'items', - dependencies: ['folder'], + dependencies: ['folder-asset', 'folder-asset-shared', 'folder-cloudpages'], + dependencyGraph: { asset: ['views.html.template.r__asset_key'] }, folderType: 'asset', hasExtended: false, idField: 'id', + keyIsFixed: false, keyField: 'customerKey', nameField: 'name', + folderIdField: 'category.id', + createdDateField: 'createdDate', + createdNameField: 'createdBy.name', + lastmodDateField: 'modifiedDate', + lastmodNameField: 'modifiedBy.name', restPagination: true, + maxKeyLength: 36, // confirmed max length type: 'asset', typeDescription: 'Assets from Content Builder grouped into subtypes.', - typeRetrieveByDefault: ['asset', 'code', 'textfile', 'block', 'message', 'template', 'other'], + typeRetrieveByDefault: [ + 'asset', + 'code', + 'coderesource', + 'textfile', + 'block', + 'message', + 'template', + 'other', + ], + typeCdpByDefault: true, typeName: 'Asset-[Subtype]', + stringifyFieldsBeforeTemplate: ['memberId', 'enterpriseId'], + allowMatchingByName: true, fields: { activeDate: { isCreateable: false, @@ -50,10 +70,10 @@ module.exports = { template: true, }, availableViews: { - isCreateable: false, - isUpdateable: false, + isCreateable: true, + isUpdateable: true, retrieving: true, - template: false, + template: true, }, modelVersion: { isCreateable: true, @@ -68,7 +88,46 @@ module.exports = { template: true, }, businessUnitAvailability: { - skipValidation: true, + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: false, + }, + 'businessUnitAvailability.%': { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: false, + }, + 'businessUnitAvailability.%.view': { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: false, + }, + 'businessUnitAvailability.%.update': { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: false, + }, + 'businessUnitAvailability.%.delete': { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: false, + }, + 'businessUnitAvailability.%.memberId': { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: false, + }, + 'businessUnitAvailability.%.transferOwnership': { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: false, }, category: { isCreateable: true, @@ -106,6 +165,12 @@ module.exports = { retrieving: true, template: true, }, + 'content.url': { + isCreateable: false, + isUpdateable: true, + retrieving: true, + template: true, + }, contentType: { isCreateable: true, isUpdateable: true, @@ -160,7 +225,13 @@ module.exports = { 'data.approvals': { skipValidation: true, }, - 'data.email.options': { + 'data.email': { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + 'data.email.attributes': { skipValidation: true, }, 'data.email.legacy': { @@ -169,13 +240,33 @@ module.exports = { retrieving: false, template: false, }, + 'data.email.options': { + skipValidation: true, + }, 'data.portfolio': { isCreateable: false, isUpdateable: false, retrieving: false, template: false, }, - + 'data.site': { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + 'data.site.content': { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + 'data.site.content.url': { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, description: { isCreateable: true, isUpdateable: true, @@ -278,8 +369,8 @@ module.exports = { memberId: { isCreateable: false, isUpdateable: false, - retrieving: false, - template: false, + retrieving: true, + template: true, }, meta: { skipValidation: true, @@ -363,25 +454,37 @@ module.exports = { template: false, }, sharingProperties: { - isCreateable: true, - isUpdateable: true, + isCreateable: false, + isUpdateable: false, retrieving: true, - template: true, + template: false, }, 'sharingProperties.localAssets': { skipValidation: true, }, 'sharingProperties.sharedWith': { - isCreateable: true, - isUpdateable: true, + isCreateable: false, + isUpdateable: false, retrieving: true, - template: true, + template: false, + }, + 'sharingProperties.sharedFrom': { + isCreateable: false, + isUpdateable: false, + retrieving: true, + template: false, + }, + 'sharingProperties.sharedFromMID': { + isCreateable: false, + isUpdateable: false, + retrieving: true, + template: false, }, 'sharingProperties.sharingType': { - isCreateable: true, - isUpdateable: true, + isCreateable: false, + isUpdateable: false, retrieving: true, - template: true, + template: false, }, slots: { skipValidation: true, @@ -438,7 +541,9 @@ module.exports = { 'asset', 'audio', 'block', + 'cloudpage', 'code', + 'coderesource', 'document', 'image', 'message', @@ -448,8 +553,141 @@ module.exports = { 'textfile', 'video', ], + crosslinkedSubTypes: ['asset', 'code', 'textfile', 'block', 'other'], + selflinkedSubTypes: ['asset', 'code', 'textfile', 'block', 'other', 'template'], + + binarySubtypes: ['archive', 'audio', 'document', 'image', 'rawimage', 'video'], extendedSubTypes: { - asset: ['webpage', 'webtemplate', 'jsonmessage', 'icemailformblock'], + archive: [ + '7z', + 'arj', + 'bz2', + 'cab', + 'gz', + 'gzip', + 'iso', + 'lha', + 'sit', + 'tgz', + 'jar', + 'rar', + 'tar', + 'zip', + 'gpg', + 'archive', + ], + asset: ['webpage', 'webtemplate', 'jsonmessage', 'icemailformblock', 'asset'], + audio: [ + 'aac', + 'm4a', + 'au', + 'aif', + 'aiff', + 'aifc', + 'mp3', + 'wav', + 'wma', + 'midi', + 'oga', + 'ogg', + 'ra', + 'vox', + 'voc', + 'audio', + ], + block: [ + 'freeformblock', + 'textblock', + 'htmlblock', + 'textplusimageblock', + 'imageblock', + 'abtestblock', + 'dynamicblock', + 'stylingblock', + 'einsteincontentblock', + 'socialshareblock', + 'socialfollowblock', + 'buttonblock', + 'layoutblock', + 'block', + ], + cloudpage: ['cloudpages', 'landingpage', 'microsite', 'interactivecontent'], + code: [ + 'htm', + 'html', + 'xhtml', + 'xht', + 'css', + 'less', + 'sass', + 'js', + 'json', + 'atom', + 'rss', + 'xml', + 'xsl', + 'xslt', + 'md', + 'markdown', + 'as', + 'fla', + 'eml', + 'code', + ], + coderesource: [ + 'jscoderesource', + 'csscoderesource', + 'jsoncoderesource', + 'rsscoderesource', + 'textcoderesource', + 'xmlcoderesource', + ], + document: [ + 'indd', + 'indt', + 'incx', + 'wwcx', + 'doc', + 'docx', + 'dot', + 'dotx', + 'mdb', + 'mpp', + 'ics', + 'xls', + 'xlsx', + 'xlk', + 'xlsm', + 'xlt', + 'xltm', + 'csv', + 'tsv', + 'tab', + 'pps', + 'ppsx', + 'ppt', + 'pptx', + 'pot', + 'thmx', + 'pdf', + 'ps', + 'qxd', + 'rtf', + 'sxc', + 'sxi', + 'sxw', + 'odt', + 'ods', + 'ots', + 'odp', + 'otp', + 'epub', + 'dvi', + 'key', + 'keynote', + 'pez', + 'document', + ], image: [ 'ai', 'psd', @@ -475,6 +713,24 @@ module.exports = { 'pbm', 'ppm', 'svg', + 'image', + ], + message: ['templatebasedemail', 'htmlemail', 'textonlyemail', 'message'], + other: [ + 'smartcaptureblock', + 'smartcaptureformfieldblock', + 'smartcapturesubmitoptionsblock', + 'slotpropertiesblock', + 'externalcontentblock', + 'codesnippetblock', + 'rssfeedblock', + 'formstylingblock', + 'referenceblock', + 'imagecarouselblock', + 'customblock', + 'liveimageblock', + 'livesettingblock', + 'contentmap', ], rawimage: [ '3fr', @@ -512,7 +768,10 @@ module.exports = { 'sr2', 'srw', 'x3f', + 'rawimage', ], + template: ['defaulttemplate', 'template'], + textfile: ['text', 'txt', 'textfile'], video: [ '3gp', '3gpp', @@ -540,143 +799,25 @@ module.exports = { 'wmv', 'rm', 'ogv', - ], - document: [ - 'indd', - 'indt', - 'incx', - 'wwcx', - 'doc', - 'docx', - 'dot', - 'dotx', - 'mdb', - 'mpp', - 'ics', - 'xls', - 'xlsx', - 'xlk', - 'xlsm', - 'xlt', - 'xltm', - 'csv', - 'tsv', - 'tab', - 'pps', - 'ppsx', - 'ppt', - 'pptx', - 'pot', - 'thmx', - 'pdf', - 'ps', - 'qxd', - 'rtf', - 'sxc', - 'sxi', - 'sxw', - 'odt', - 'ods', - 'ots', - 'odp', - 'otp', - 'epub', - 'dvi', - 'key', - 'keynote', - 'pez', - ], - audio: [ - 'aac', - 'm4a', - 'au', - 'aif', - 'aiff', - 'aifc', - 'mp3', - 'wav', - 'wma', - 'midi', - 'oga', - 'ogg', - 'ra', - 'vox', - 'voc', - ], - archive: [ - '7z', - 'arj', - 'bz2', - 'cab', - 'gz', - 'gzip', - 'iso', - 'lha', - 'sit', - 'tgz', - 'jar', - 'rar', - 'tar', - 'zip', - 'gpg', - ], - code: [ - 'htm', - 'html', - 'xhtml', - 'xht', - 'css', - 'less', - 'sass', - 'js', - 'json', - 'atom', - 'rss', - 'xml', - 'xsl', - 'xslt', - 'md', - 'markdown', - 'as', - 'fla', - 'eml', - ], - textfile: ['text', 'txt'], - block: [ - 'freeformblock', - 'textblock', - 'htmlblock', - 'textplusimageblock', - 'imageblock', - 'abtestblock', - 'dynamicblock', - 'stylingblock', - 'einsteincontentblock', - 'socialshareblock', - 'socialfollowblock', - 'buttonblock', - 'layoutblock', - ], - message: ['templatebasedemail', 'htmlemail', 'textonlyemail'], - template: ['defaulttemplate'], - other: [ - 'smartcaptureblock', - 'smartcaptureformfieldblock', - 'smartcapturesubmitoptionsblock', - 'slotpropertiesblock', - 'externalcontentblock', - 'codesnippetblock', - 'rssfeedblock', - 'formstylingblock', - 'referenceblock', - 'imagecarouselblock', - 'customblock', - 'liveimageblock', - 'livesettingblock', - 'contentmap', + 'video', ], }, typeMapping: { + asset: 1, + file: 2, // not inherited on Asset Types + block: 3, + template: 4, + message: 5, + custom: 6, // not inherited on Asset Types + default: 7, // not inherited on Asset Types + image: 8, + rawimage: 9, + video: 10, + document: 11, + audio: 12, + archive: 13, + code: 14, + textfile: 15, ai: 16, psd: 17, pdd: 18, @@ -891,5 +1032,16 @@ module.exports = { contentmap: 228, jsonmessage: 230, icemailformblock: 232, + coderesource: 239, + jscoderesource: 240, + csscoderesource: 241, + jsoncoderesource: 242, + rsscoderesource: 243, + textcoderesource: 244, + xmlcoderesource: 245, + cloudpages: 246, + landingpage: 247, + microsite: 248, + interactivecontent: 249, }, }; diff --git a/lib/metadataTypes/definitions/AttributeGroup.definition.js b/lib/metadataTypes/definitions/AttributeGroup.definition.js index 5cfb2df6a..ad57e34b7 100644 --- a/lib/metadataTypes/definitions/AttributeGroup.definition.js +++ b/lib/metadataTypes/definitions/AttributeGroup.definition.js @@ -1,225 +1,257 @@ -module.exports = { +export default { bodyIteratorField: 'attributeGroupDefinitions', - dependencies: [], // future may have dependency on Data Extensions + dependencies: ['attributeSet'], // future may have dependency on Data Extensions + dependencyGraph: { attributeSet: ['r__attributeSet_key'] }, hasExtended: false, idField: 'definitionID', + keyIsFixed: true, keyField: 'definitionKey', nameField: 'definitionName.value', - restPagination: false, + restPagination: false, // Hub API does not support pagination and returns everything instead type: 'attributeGroup', - typeDescription: 'BETA: Groupings of Set Definitions (Data Extensions) in Data Designer.', - typeRetrieveByDefault: false, + typeDescription: 'Groupings of Attribute Sets (Data Extensions) in Data Designer.', + typeRetrieveByDefault: true, + typeCdpByDefault: false, typeName: 'Data Designer Attribute Groups', fields: { applicationID: { - isCreateable: null, - isUpdateable: null, - retrieving: true, - template: null, + // used by system generated attribute groups only; contains UUID + isCreateable: false, + isUpdateable: false, + retrieving: false, + template: false, }, applicationKey: { - isCreateable: null, - isUpdateable: null, + // used by system generated attribute groups only + isCreateable: false, + isUpdateable: false, retrieving: true, - template: null, + template: false, }, attributeCount: { - isCreateable: null, - isUpdateable: null, + // auto-populated + isCreateable: false, + isUpdateable: false, retrieving: true, - template: null, + template: false, }, attributeGroupIconKey: { - isCreateable: null, - isUpdateable: null, + isCreateable: true, + isUpdateable: true, retrieving: true, - template: null, + template: true, }, attributeGroupType: { - isCreateable: null, - isUpdateable: null, + isCreateable: true, + isUpdateable: true, retrieving: true, - template: null, + template: true, }, attributeSetIdentifiers: { - isCreateable: null, - isUpdateable: null, + isCreateable: true, + isUpdateable: true, retrieving: true, - template: null, + template: true, }, 'attributeSetIdentifiers[].connectingID.identifierType': { isCreateable: null, isUpdateable: null, - retrieving: false, - template: null, + retrieving: true, + template: false, }, 'attributeSetIdentifiers[].definitionID': { isCreateable: null, isUpdateable: null, retrieving: true, - template: null, + template: false, }, 'attributeSetIdentifiers[].definitionKey': { isCreateable: null, isUpdateable: null, retrieving: true, - template: null, + template: true, }, - 'attributeSetIdentifiers[].definitionName.Contact': { + 'attributeSetIdentifiers[].definitionName.value': { isCreateable: null, isUpdateable: null, retrieving: true, - template: null, + template: false, }, 'attributeSetIdentifiers[].namespace': { isCreateable: null, isUpdateable: null, retrieving: false, - template: null, + template: false, }, canAddProperties: { - isCreateable: null, - isUpdateable: null, + isCreateable: true, + isUpdateable: true, retrieving: true, - template: null, + template: true, }, canAddRelationships: { - isCreateable: null, - isUpdateable: null, + isCreateable: true, + isUpdateable: true, retrieving: true, - template: null, + template: true, }, canChangeProperties: { - isCreateable: null, - isUpdateable: null, + isCreateable: true, + isUpdateable: true, retrieving: true, - template: null, + template: true, }, canModify: { - isCreateable: null, - isUpdateable: null, + isCreateable: true, + isUpdateable: true, retrieving: true, - template: null, + template: true, }, canRemove: { - isCreateable: null, - isUpdateable: null, + isCreateable: true, + isUpdateable: true, retrieving: true, - template: null, + template: true, }, connectingID: { - isCreateable: null, - isUpdateable: null, - retrieving: false, - template: null, + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, }, 'connectingID.identifierType': { - isCreateable: null, - isUpdateable: null, - retrieving: false, - template: null, + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, }, containsSchemaAttributes: { - isCreateable: null, - isUpdateable: null, + isCreateable: true, + isUpdateable: true, retrieving: true, - template: null, + template: true, }, definitionID: { - isCreateable: null, - isUpdateable: null, + isCreateable: true, + isUpdateable: true, retrieving: true, - template: null, + template: false, }, definitionKey: { - isCreateable: null, - isUpdateable: null, + isCreateable: true, + isUpdateable: true, retrieving: true, - template: null, + template: true, }, 'definitionName.value': { - isCreateable: null, - isUpdateable: null, + isCreateable: true, + isUpdateable: true, retrieving: true, - template: null, + template: true, }, description: { - isCreateable: null, - isUpdateable: null, + // optional field. not returned by API if empty + isCreateable: true, + isUpdateable: true, retrieving: true, - template: null, + template: true, }, displayOrder: { - isCreateable: null, - isUpdateable: null, + // auto-set to i+1 + isCreateable: false, + isUpdateable: false, retrieving: true, - template: null, + template: false, }, fullyQualifiedName: { - isCreateable: null, - isUpdateable: null, - retrieving: true, - template: null, + // equal to defitionName.value; auto-populated by preDeployTasks + isCreateable: true, + isUpdateable: true, + retrieving: false, + template: false, }, isHidden: { - isCreateable: null, - isUpdateable: null, + isCreateable: true, + isUpdateable: true, retrieving: true, - template: null, + template: true, }, isOwner: { - isCreateable: null, - isUpdateable: null, + isCreateable: true, + isUpdateable: true, retrieving: true, - template: null, + template: true, }, isPrimary: { - isCreateable: null, - isUpdateable: null, - retrieving: true, - template: null, + // always false, purpose unknown + isCreateable: false, + isUpdateable: false, + retrieving: false, + template: false, }, isSystemDefined: { + isCreateable: false, + isUpdateable: false, + retrieving: true, + template: false, + }, + localizedDescription: { + // always an empty object + isCreateable: false, + isUpdateable: false, + retrieving: false, + template: false, + }, + 'localizedDescription.resourceSetKey': { isCreateable: null, isUpdateable: null, retrieving: true, - template: null, + template: true, }, - localizedDescription: { + 'localizedDescription.resourceValueKey': { isCreateable: null, isUpdateable: null, retrieving: true, - template: null, + template: true, }, 'localizedDescription.value': { isCreateable: null, isUpdateable: null, retrieving: true, - template: null, + template: true, }, mID: { - isCreateable: null, - isUpdateable: null, + // auto-populated in preDeployTask + isCreateable: true, + isUpdateable: true, retrieving: true, - template: null, + template: true, }, namespace: { - isCreateable: null, - isUpdateable: null, + // always an empty string + isCreateable: false, + isUpdateable: false, retrieving: false, - template: null, + template: false, }, objectState: { - isCreateable: null, - isUpdateable: null, - retrieving: true, - template: null, + // seems to always contain "Created" + isCreateable: false, + isUpdateable: false, + retrieving: false, + template: false, }, requiredRelationships: { - isCreateable: null, - isUpdateable: null, + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + r__attributeSet_key: { + isCreateable: false, + isUpdateable: false, retrieving: true, - template: null, + template: true, }, }, }; diff --git a/lib/metadataTypes/definitions/SetDefinition.definition.js b/lib/metadataTypes/definitions/AttributeSet.definition.js similarity index 75% rename from lib/metadataTypes/definitions/SetDefinition.definition.js rename to lib/metadataTypes/definitions/AttributeSet.definition.js index 7acc1efde..3d70db985 100644 --- a/lib/metadataTypes/definitions/SetDefinition.definition.js +++ b/lib/metadataTypes/definitions/AttributeSet.definition.js @@ -1,15 +1,42 @@ -module.exports = { +export default { bodyIteratorField: 'setDefinition', - dependencies: [], // future may have dependency on Data Extensions + dependencies: [ + 'folder-hidden', + 'folder-dataextension', + 'folder-salesforcedataextension', + 'folder-shared_data', + 'folder-shared_dataextension', + 'folder-shared_salesforcedataextension', + 'folder-synchronizeddataextension', + 'dataExtension', + ], + dependencyGraph: { + dataExtension: ['r__dataExtension_key'], + attributeSet: [ + 'relationships.leftItem.identifier.r__attributeSet_key', + 'relationships.rightItem.identifier.r__attributeSet_key', + ], + attributeGroup: [ + 'relationships.leftItem.identifier.r__attributeGroup_key', + 'relationships.rightItem.identifier.r__attributeGroup_key', + ], + }, hasExtended: false, idField: 'definitionID', + keyIsFixed: true, keyField: 'definitionKey', nameField: 'name', - restPagination: false, - type: 'setDefinition', - typeDescription: 'BETA: Data Extensions linked to Attribute Groups in Data Designer.', - typeRetrieveByDefault: false, - typeName: 'Data Designer Set Definitions', + folderIdField: 'categoryID', + createdDateField: 'createDate', + createdNameField: 'createdBy', + lastmodDateField: null, + lastmodNameField: null, + restPagination: false, // Hub API does not support pagination and returns everything instead + type: 'attributeSet', + typeDescription: 'Data Extensions linked together in Attribute Groups in Data Designer.', + typeRetrieveByDefault: true, + typeCdpByDefault: false, + typeName: 'Data Designer Attribute Sets', fields: { applicationID: { isCreateable: null, @@ -60,10 +87,10 @@ module.exports = { template: null, }, 'connectingID.identifierType': { - isCreateable: null, - isUpdateable: null, - retrieving: true, - template: null, + isCreateable: true, + isUpdateable: true, + retrieving: false, + template: false, }, createDate: { isCreateable: null, @@ -113,29 +140,43 @@ module.exports = { retrieving: true, template: null, }, - definitionID: { + 'dataRetentionProperties.periodLength': { isCreateable: null, isUpdateable: null, retrieving: true, template: null, }, - definitionKey: { + definitionID: { isCreateable: null, isUpdateable: null, retrieving: true, template: null, }, - 'definitionName.value': { + definitionKey: { isCreateable: null, isUpdateable: null, retrieving: true, template: null, }, + definitionName: { + isCreateable: true, + isUpdateable: true, + retrieving: false, + template: false, + }, + 'definitionName.value': { + // equal to 'name' + isCreateable: true, + isUpdateable: true, + retrieving: false, + template: false, + }, fullyQualifiedName: { - isCreateable: null, - isUpdateable: null, - retrieving: true, - template: null, + // equal to 'name' + isCreateable: true, + isUpdateable: true, + retrieving: false, + template: false, }, isCustomObjectBacked: { isCreateable: null, @@ -228,30 +269,54 @@ module.exports = { template: null, }, localizedDescription: { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + 'localizedDescription.resourceSetKey': { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + 'localizedDescription.resourceValueKey': { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + 'localizedDescription.value': { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + name: { isCreateable: null, isUpdateable: null, retrieving: true, template: null, }, - 'localizedDescription.resourceSetKey': { + nonStandardAttributeGroupReferences: { isCreateable: null, isUpdateable: null, retrieving: true, template: null, }, - 'localizedDescription.resourceValueKey': { + 'nonStandardAttributeGroupReferences[].attributeGroupType': { isCreateable: null, isUpdateable: null, retrieving: true, template: null, }, - 'localizedDescription.value': { + 'nonStandardAttributeGroupReferences[].attributeGroupID': { isCreateable: null, isUpdateable: null, retrieving: true, template: null, }, - name: { + 'nonStandardAttributeGroupReferences[].definitionKey': { isCreateable: null, isUpdateable: null, retrieving: true, @@ -371,6 +436,54 @@ module.exports = { retrieving: true, template: null, }, + 'relationships[].leftItem.cardinality': { + isCreateable: null, + isUpdateable: null, + retrieving: true, + template: null, + }, + 'relationships[].leftItem.relationshipType': { + isCreateable: null, + isUpdateable: null, + retrieving: true, + template: null, + }, + 'relationships[].leftItem.r__attributeSet_key': { + isCreateable: null, + isUpdateable: null, + retrieving: true, + template: null, + }, + 'relationships[].leftItem.r__attributeGroup_key': { + isCreateable: null, + isUpdateable: null, + retrieving: true, + template: null, + }, + 'relationships[].rightItem.cardinality': { + isCreateable: null, + isUpdateable: null, + retrieving: true, + template: null, + }, + 'relationships[].rightItem.relationshipType': { + isCreateable: null, + isUpdateable: null, + retrieving: true, + template: null, + }, + 'relationships[].rightItem.r__attributeSet_key': { + isCreateable: null, + isUpdateable: null, + retrieving: true, + template: null, + }, + 'relationships[].rightItem.r__attributeGroup_key': { + isCreateable: null, + isUpdateable: null, + retrieving: true, + template: null, + }, 'relationships[].leftRelationshipIDs[].type': { isCreateable: null, isUpdateable: null, @@ -407,6 +520,18 @@ module.exports = { retrieving: true, template: null, }, + 'relationships[].relationshipAttributes[].c__leftFullyQualifiedName': { + isCreateable: null, + isUpdateable: null, + retrieving: true, + template: null, + }, + 'relationships[].relationshipAttributes[].c__rightFullyQualifiedName': { + isCreateable: null, + isUpdateable: null, + retrieving: true, + template: null, + }, 'relationships[].relationshipID': { isCreateable: null, isUpdateable: null, @@ -552,9 +677,10 @@ module.exports = { template: null, }, 'valueDefinitions[].baseType': { + // "Numeric", "Text", ... valueDefinitions[].dataType is more relevant isCreateable: null, isUpdateable: null, - retrieving: true, + retrieving: false, template: null, }, 'valueDefinitions[].customerDataID': { @@ -563,6 +689,12 @@ module.exports = { retrieving: true, template: null, }, + 'valueDefinitions[].connectingID': { + isCreateable: null, + isUpdateable: null, + retrieving: false, + template: null, + }, 'valueDefinitions[].dataSourceID': { isCreateable: null, isUpdateable: null, @@ -572,7 +704,7 @@ module.exports = { 'valueDefinitions[].dataSourceName': { isCreateable: null, isUpdateable: null, - retrieving: true, + retrieving: false, template: null, }, 'valueDefinitions[].dataType': { @@ -588,9 +720,10 @@ module.exports = { template: null, }, 'valueDefinitions[].definitionID': { + // likely the main ID of the value definition. No use for simple checks on git though as long as we cannot update it isCreateable: null, isUpdateable: null, - retrieving: true, + retrieving: false, template: null, }, 'valueDefinitions[].definitionKey': { @@ -599,10 +732,11 @@ module.exports = { retrieving: true, template: null, }, - 'valueDefinitions[].definitionName.value': { + 'valueDefinitions[].definitionName': { + // equal to valueDefinitions[].name isCreateable: null, isUpdateable: null, - retrieving: true, + retrieving: false, template: null, }, 'valueDefinitions[].description': { @@ -612,15 +746,17 @@ module.exports = { template: null, }, 'valueDefinitions[].displayOrder': { + // merely a numeric counter; equal to valueDefinitions[].ordinal; not given for isHidden:true entries isCreateable: null, isUpdateable: null, - retrieving: true, + retrieving: false, template: null, }, 'valueDefinitions[].fullyQualifiedName': { + // dataExtension name + field name isCreateable: null, isUpdateable: null, - retrieving: true, + retrieving: false, template: null, }, 'valueDefinitions[].identifierType': { @@ -677,10 +813,11 @@ module.exports = { retrieving: true, template: null, }, - 'valueDefinitions[].localizedDescription.value': { + 'valueDefinitions[].localizedDescription': { + // always equal to { value: "" } isCreateable: null, isUpdateable: null, - retrieving: true, + retrieving: false, template: null, }, 'valueDefinitions[].name': { @@ -689,6 +826,13 @@ module.exports = { retrieving: true, template: null, }, + 'valueDefinitions[].obfuscationProperties': { + // might become relevant when fields are encrypted but for most cases we should simply skip it + isCreateable: null, + isUpdateable: null, + retrieving: false, + template: null, + }, 'valueDefinitions[].obfuscationProperties.maskType': { isCreateable: null, isUpdateable: null, @@ -720,9 +864,10 @@ module.exports = { template: null, }, 'valueDefinitions[].ordinal': { + // merely a numeric counter; equal to valueDefinitions[].displayOrder; not given for isHidden:true entries isCreateable: null, isUpdateable: null, - retrieving: true, + retrieving: false, template: null, }, 'valueDefinitions[].parentDefinition': { @@ -738,9 +883,10 @@ module.exports = { template: null, }, 'valueDefinitions[].parentType': { + // always "Set" isCreateable: null, isUpdateable: null, - retrieving: true, + retrieving: false, template: null, }, 'valueDefinitions[].restrictionLookupListID': { @@ -767,37 +913,87 @@ module.exports = { retrieving: false, template: null, }, - 'valueDefinitions[].setDefinitionName.value': { + 'valueDefinitions[].setDefinitionName': { + isCreateable: null, + isUpdateable: null, + retrieving: false, + template: null, + }, + 'valueDefinitions[].storageFieldReferenceID': { isCreateable: null, isUpdateable: null, retrieving: false, template: null, }, 'valueDefinitions[].storageFieldReferenceID.type': { + // always "guid" isCreateable: null, isUpdateable: null, retrieving: true, template: null, }, 'valueDefinitions[].storageFieldReferenceID.value': { + // unknown GUID isCreateable: null, isUpdateable: null, retrieving: true, template: null, }, - 'valueDefinitions[].storageName': { + 'valueDefinitions[].storageFieldValueID.type': { isCreateable: null, isUpdateable: null, retrieving: true, template: null, }, - 'valueDefinitions[].valueDefinitionID': { + 'valueDefinitions[].storageFieldValueID.value': { isCreateable: null, isUpdateable: null, retrieving: true, template: null, }, + 'valueDefinitions[].storageName': { + // always equal valueDefinitions[].definitionKey, except for when that is CustomObjectKey - then this will be _CustomObjectKey (with an underscore) + isCreateable: null, + isUpdateable: null, + retrieving: false, + template: null, + }, + 'valueDefinitions[].storageObjectFieldInformation': { + skipValidation: true, + }, + 'valueDefinitions[].storageObjectFieldInformation.externalObjectFieldAPIName': { + skipValidation: true, + }, + 'valueDefinitions[].storageObjectFieldInformation.externalObjectFieldDataTypeName': { + skipValidation: true, + }, + 'valueDefinitions[].storageObjectFieldInformation.externalObjectFieldLength': { + skipValidation: true, + }, + 'valueDefinitions[].storageObjectFieldInformation.externalIsRowIdentifier': { + skipValidation: true, + }, + 'valueDefinitions[].valueDefinitionID': { + // equal to valueDefinitions[].definitionID + isCreateable: null, + isUpdateable: null, + retrieving: false, + template: null, + }, 'valueDefinitions[].valueDefinitionKey': { + // equal to valueDefinitions[].definitionKey + isCreateable: null, + isUpdateable: null, + retrieving: false, + template: null, + }, + r__folder_Path: { + isCreateable: null, + isUpdateable: null, + retrieving: true, + template: null, + }, + r__dataExtension_key: { isCreateable: null, isUpdateable: null, retrieving: true, diff --git a/lib/metadataTypes/definitions/Automation.definition.js b/lib/metadataTypes/definitions/Automation.definition.js index bf51600b5..cc605d531 100644 --- a/lib/metadataTypes/definitions/Automation.definition.js +++ b/lib/metadataTypes/definitions/Automation.definition.js @@ -1,8 +1,8 @@ -module.exports = { +export default { activityTypeMapping: { dataExtract: 73, dataFactoryUtility: 425, - emailSendDefinition: 42, + emailSend: 42, fileTransfer: 53, filter: 303, fireEvent: 749, @@ -25,21 +25,48 @@ module.exports = { bodyIteratorField: 'items', dependencies: [ 'dataExtract', - 'emailSendDefinition', + 'emailSend', 'fileTransfer', - 'folder', + 'fileLocation', + 'filter', + 'folder-automations', 'importFile', 'query', 'script', + 'verification', ], + dependencyGraph: { + dataExtract: ['steps.activities.r__type'], + emailSend: ['steps.activities.r__type'], + fileTransfer: ['steps.activities.r__type'], + importFile: ['steps.activities.r__type'], + query: ['steps.activities.r__type'], + script: ['steps.activities.r__type'], + verification: ['steps.activities.r__type'], + }, + folderType: 'automations', hasExtended: false, filter: { description: ['Event Definition Automation'], }, idField: 'id', + keyIsFixed: false, keyField: 'key', nameField: 'name', - restPagination: false, + folderIdField: 'categoryId', + createdDateField: 'createdDate', // only returned by upsert & legacy + createdNameField: 'createdName', // only returned by upsert & legacy + lastmodDateField: 'modifiedDate', // only returned by upsert & legacy + lastmodNameField: 'modifiedName', // only returned by upsert & legacy + restPagination: true, + maxKeyLength: 200, // confirmed max length + scheduleTypeMapping: { + MINUTELY: 1, + HOURLY: 2, + DAILY: 3, + WEEKLY: 4, + MONTHLY: 5, + }, statusMapping: { AwaitingTrigger: 7, Building: 1, @@ -52,6 +79,12 @@ module.exports = { Scheduled: 6, Stopped: 5, }, + fileNameOperatorMapping: { + Equals: 4, + Contains: 1, + 'Begins with': 2, + 'Ends with': 3, + }, timeZoneMapping: { // bugs in SFMC timezones: // * Yerevan GMT+4 always is changing to 'Caucasus Standard Time' GMT+4, so no id 29 @@ -244,8 +277,10 @@ module.exports = { typeDescription: 'Used via Automation Studio directly - or indirectly via Journey Builder & MC Connect.', typeRetrieveByDefault: true, + typeCdpByDefault: true, typeName: 'Automation', - manualDeployTypes: ['wait'], + customDeployTypes: ['wait'], + manualDeployTypes: [], fields: { categoryId: { isCreateable: true, @@ -303,7 +338,7 @@ module.exports = { }, key: { isCreateable: true, - isUpdateable: false, + isUpdateable: true, retrieving: true, template: true, }, @@ -322,37 +357,67 @@ module.exports = { legacyId: { isCreateable: false, isUpdateable: false, - retrieving: true, + retrieving: false, template: false, }, lastSavedDate: { isCreateable: false, isUpdateable: false, - retrieving: true, + retrieving: false, // only returned by upsert template: false, }, lastSavedByName: { isCreateable: false, isUpdateable: false, - retrieving: true, + retrieving: false, // only returned by upsert + template: false, + }, + createdByName: { + isCreateable: false, + isUpdateable: false, + retrieving: false, // only returned by upsert template: false, }, createdDate: { isCreateable: false, isUpdateable: false, - retrieving: true, + retrieving: true, // only returned by upsert + legacy template: false, }, - createdByName: { + createdName: { isCreateable: false, isUpdateable: false, - retrieving: true, + retrieving: true, // only returned by legacy + template: false, + }, + modifiedDate: { + isCreateable: false, + isUpdateable: false, + retrieving: true, // only returned by legacy + template: false, + }, + modifiedName: { + isCreateable: false, + isUpdateable: false, + retrieving: true, // only returned by legacy + template: false, + }, + pausedDate: { + isCreateable: false, + isUpdateable: false, + retrieving: true, // only returned by legacy + template: false, + }, + pausedName: { + isCreateable: false, + isUpdateable: false, + retrieving: true, // only returned by legacy template: false, }, updateInProgress: { isCreateable: false, isUpdateable: false, - retrieving: true, + retrieving: false, template: false, }, name: { @@ -361,6 +426,45 @@ module.exports = { retrieving: true, template: true, }, + notifications: { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + 'notifications[].email': { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + 'notifications[].message': { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + 'notifications[].channelType': { + // always 'Account' + isCreateable: true, + isUpdateable: true, + retrieving: false, + template: false, + }, + 'notifications[].type': { + // custom shorthand for channelType + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + 'notifications[].notificationType': { + // Error, Complete + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, startSource: { skipValidation: true, }, @@ -404,7 +508,7 @@ module.exports = { isCreateable: true, isUpdateable: true, retrieving: false, - template: true, + template: false, }, 'schedule.scheduleStatus': { isCreateable: false, @@ -418,11 +522,17 @@ module.exports = { retrieving: true, template: true, }, + 'schedule.statusId': { + isCreateable: false, + isUpdateable: false, + retrieving: false, + template: false, + }, 'schedule.timezoneId': { isCreateable: true, isUpdateable: true, - retrieving: true, - template: true, + retrieving: false, + template: false, }, 'schedule.timezoneName': { isCreateable: true, @@ -431,10 +541,22 @@ module.exports = { template: true, }, 'schedule.typeId': { - isCreateable: true, - isUpdateable: true, - retrieving: true, - template: true, + isCreateable: false, + isUpdateable: false, + retrieving: false, + template: false, + }, + 'schedule.scheduleTypeId': { + isCreateable: false, + isUpdateable: false, + retrieving: false, + template: false, + }, + 'schedule.description': { + isCreateable: false, + isUpdateable: false, + retrieving: false, + template: false, }, status: { isCreateable: true, @@ -467,10 +589,11 @@ module.exports = { template: false, }, 'steps[].activities[].displayOrder': { + // we remove it during post-processing but need to ensure the array order equals the displayOrder isCreateable: true, isUpdateable: true, - retrieving: true, - template: true, + retrieving: false, + template: false, }, 'steps[].activities[].id': { isCreateable: true, @@ -503,14 +626,24 @@ module.exports = { template: false, }, 'steps[].activities[].serializedObject': { - isCreateable: false, - isUpdateable: false, + isCreateable: true, + isUpdateable: true, retrieving: false, template: false, }, 'steps[].activities[].r__type': { skipValidation: true, }, + 'steps[].activities[].r__key': { + skipValidation: true, + }, + 'steps[].activities[].timeZone': { + // used for wait actitivity + isCreateable: false, + isUpdateable: false, + retrieving: true, + template: true, + }, 'steps[].description': { isCreateable: true, isUpdateable: true, @@ -520,8 +653,8 @@ module.exports = { 'steps[].annotation': { isCreateable: true, isUpdateable: true, - retrieving: true, - template: true, + retrieving: false, + template: false, }, 'steps[].id': { isCreateable: true, @@ -536,8 +669,8 @@ module.exports = { template: true, }, 'steps[].step': { - isCreateable: true, - isUpdateable: true, + isCreateable: false, + isUpdateable: false, retrieving: true, template: true, }, @@ -557,7 +690,7 @@ module.exports = { isCreateable: true, isUpdateable: true, retrieving: false, - template: true, + template: false, }, r__folder_Path: { skipValidation: true }, }, diff --git a/lib/metadataTypes/definitions/Campaign.definition.js b/lib/metadataTypes/definitions/Campaign.definition.js index 07df3fdb8..84ac9275d 100644 --- a/lib/metadataTypes/definitions/Campaign.definition.js +++ b/lib/metadataTypes/definitions/Campaign.definition.js @@ -1,14 +1,134 @@ -module.exports = { - bodyIteratorField: 'items', +export default { + bodyIteratorField: 'entry', dependencies: [], + dependencyGraph: null, hasExtended: false, idField: 'id', + keepId: true, + keyIsFixed: true, keyField: 'name', nameField: 'name', + createdDateField: 'createdDate', + createdNameField: null, + lastmodDateField: 'lastUpdated', + lastmodNameField: null, restPagination: true, + restPageSize: 50, type: 'campaign', typeDescription: 'Way of tagging/categorizing emails, journeys and alike.', typeRetrieveByDefault: false, + typeCdpByDefault: false, typeName: 'Campaign Tag', - fields: {}, + fields: { + id: { + // alphanumeric string + isCreateable: false, + isUpdateable: false, + retrieving: true, + templating: false, + }, + campaignId: { + // numeric + isCreateable: false, + isUpdateable: false, + retrieving: false, + templating: false, + }, + type: { + // always set to "Campaign" + isCreateable: false, + isUpdateable: false, + retrieving: false, + templating: false, + }, + createdDate: { + isCreateable: false, + isUpdateable: false, + retrieving: true, + templating: false, + }, + createdBy: { + // returns https://mc....rest.marketingcloudapis.com/legacy/v1/beta/organization/user/Nzc1MTU2ODo0OjA + isCreateable: false, + isUpdateable: false, + retrieving: false, + templating: false, + }, + ownerId: { + // returns https://mc....rest.marketingcloudapis.com/legacy/v1/beta/organization/user/Nzc1MTU2ODo0OjA + isCreateable: false, + isUpdateable: false, + retrieving: false, + templating: false, + }, + lastUpdated: { + isCreateable: false, + isUpdateable: false, + retrieving: true, + templating: false, + }, + name: { + isCreateable: false, + isUpdateable: false, + retrieving: true, + templating: false, + }, + description: { + isCreateable: false, + isUpdateable: false, + retrieving: true, + templating: false, + }, + externalKey: { + // can be empty - should use "name" instead as key + isCreateable: false, + isUpdateable: false, + retrieving: true, + templating: false, + }, + campaignCode: { + // always empty string; real value is in field "externalKey" + isCreateable: false, + isUpdateable: false, + retrieving: false, + templating: false, + }, + 'display.name': { + isCreateable: false, + isUpdateable: false, + retrieving: true, + templating: false, + }, + 'display.value': { + isCreateable: false, + isUpdateable: false, + retrieving: true, + templating: false, + }, + isFavorite: { + isCreateable: false, + isUpdateable: false, + retrieving: true, + templating: false, + }, + campaignOwnerName: { + isCreateable: false, + isUpdateable: false, + retrieving: true, + templating: false, + }, + campaignOwner: { + // value like "MDo0OjE" + isCreateable: false, + isUpdateable: false, + retrieving: false, + templating: false, + }, + campaignStatus: { + isCreateable: false, + isUpdateable: false, + retrieving: true, + templating: false, + }, + }, }; diff --git a/lib/metadataTypes/definitions/ContentArea.definition.js b/lib/metadataTypes/definitions/ContentArea.definition.js index 2c5fdbff5..8c953717a 100644 --- a/lib/metadataTypes/definitions/ContentArea.definition.js +++ b/lib/metadataTypes/definitions/ContentArea.definition.js @@ -1,16 +1,20 @@ -module.exports = { +export default { bodyIteratorField: 'Results', dependencies: ['folder'], + dependencyGraph: null, hasExtended: false, idField: 'ID', keepId: true, + keyIsFixed: true, keyField: 'CustomerKey', nameField: 'Name', + folderIdField: 'CategoryID', restPagination: null, type: 'contentArea', typeDescription: 'DEPRECATED: Old way of saving Content Blocks; please migrate these to new Content Blocks (`Asset: ...`).', typeRetrieveByDefault: false, + typeCdpByDefault: false, typeName: 'Content Area (Classic)', fields: { // https://developer.salesforce.com/docs/atlas.en-us.noversion.mc-apis.meta/mc-apis/contentarea.htm diff --git a/lib/metadataTypes/definitions/DataExtension.definition.js b/lib/metadataTypes/definitions/DataExtension.definition.js index 01bd4ae10..a41283d7b 100644 --- a/lib/metadataTypes/definitions/DataExtension.definition.js +++ b/lib/metadataTypes/definitions/DataExtension.definition.js @@ -1,6 +1,16 @@ -module.exports = { +export default { bodyIteratorField: 'Results', - dependencies: ['folder', 'dataExtensionTemplate'], + dependencies: [ + 'folder-hidden', + 'folder-dataextension', + 'folder-salesforcedataextension', + 'folder-shared_data', + 'folder-shared_dataextension', + 'folder-shared_salesforcedataextension', + 'folder-synchronizeddataextension', + 'dataExtensionTemplate', + ], + dependencyGraph: null, // dataExtensionTemplate cannot be deployed folderType: 'dataextension', filter: { CustomerKey: [ @@ -27,6 +37,7 @@ module.exports = { '_ChatMessagingSubscription', '_EnterpriseAttribute', '_MobileAddress', + '_MobileAddressApplication', '_MobileLineAddress', '_MobileLineAddressContact', '_MobileLineProfile', @@ -76,14 +87,28 @@ module.exports = { SMSSubscriptionLog: null, // CustomerKey cannot be retrieved TriggeredSendDataExtension: ['SubscriberKey', 'EmailAddress'], }, + dataRetentionPeriodUnitOfMeasureMapping: { + Days: 3, + Weeks: 4, + Months: 5, + Years: 6, + }, hasExtended: false, idField: 'ObjectID', + keyIsFixed: false, keyField: 'CustomerKey', nameField: 'Name', + folderIdField: 'CategoryID', + createdDateField: 'CreatedDate', + createdNameField: null, + lastmodDateField: 'ModifiedDate', + lastmodNameField: null, restPagination: false, + maxKeyLength: 200, // confirmed max length type: 'dataExtension', typeDescription: 'Database table schemas.', typeRetrieveByDefault: true, + typeCdpByDefault: true, typeName: 'Data Extension', fields: { CategoryID: { @@ -99,8 +124,8 @@ module.exports = { template: false, }, CreatedDate: { - isCreateable: false, - isUpdateable: false, + isCreateable: true, + isUpdateable: true, retrieving: true, template: false, }, @@ -111,6 +136,7 @@ module.exports = { template: true, }, DataRetentionPeriod: { + // not used isCreateable: false, isUpdateable: false, retrieving: false, @@ -118,19 +144,19 @@ module.exports = { }, DataRetentionPeriodLength: { isCreateable: true, - isUpdateable: false, + isUpdateable: true, retrieving: true, template: true, }, DataRetentionPeriodUnitOfMeasure: { isCreateable: true, - isUpdateable: false, + isUpdateable: true, retrieving: true, template: true, }, DeleteAtEndOfRetentionPeriod: { isCreateable: true, - isUpdateable: false, + isUpdateable: true, retrieving: true, template: true, }, @@ -165,8 +191,8 @@ module.exports = { template: true, }, ModifiedDate: { - isCreateable: false, - isUpdateable: false, + isCreateable: true, + isUpdateable: true, retrieving: true, template: false, }, @@ -178,7 +204,7 @@ module.exports = { }, ObjectID: { isCreateable: false, - isUpdateable: false, + isUpdateable: true, retrieving: true, template: false, }, @@ -190,19 +216,19 @@ module.exports = { }, ResetRetentionPeriodOnImport: { isCreateable: true, - isUpdateable: false, + isUpdateable: true, retrieving: true, template: true, }, RetainUntil: { isCreateable: true, - isUpdateable: false, + isUpdateable: true, retrieving: true, template: true, }, RowBasedRetention: { isCreateable: true, - isUpdateable: false, + isUpdateable: true, retrieving: true, template: true, }, @@ -264,7 +290,16 @@ module.exports = { r__folder_Path: { skipValidation: true, }, - r__dataExtensionTemplate_Name: { + r__dataExtensionTemplate_name: { + skipValidation: true, + }, + c__retentionPolicy: { + skipValidation: true, + }, + c__retainUntil: { + skipValidation: true, + }, + c__dataRetentionPeriodUnitOfMeasure: { skipValidation: true, }, }, diff --git a/lib/metadataTypes/definitions/DataExtensionField.definition.js b/lib/metadataTypes/definitions/DataExtensionField.definition.js index 196a1162a..515d94bac 100644 --- a/lib/metadataTypes/definitions/DataExtensionField.definition.js +++ b/lib/metadataTypes/definitions/DataExtensionField.definition.js @@ -1,16 +1,20 @@ -module.exports = { +export default { bodyIteratorField: 'Results', - dependencies: [], + dependencies: ['dataExtension'], + dependencyGraph: null, filter: {}, hasExtended: false, idField: 'ObjectID', + keyIsFixed: true, // renamed via name_new on dataExtension update keyField: 'CustomerKey', nameField: 'Name', restPagination: false, type: 'dataExtensionField', typeDescription: 'Internal Type: Fields for type dataExtension.', typeRetrieveByDefault: false, + typeCdpByDefault: false, typeName: 'Data Extension Field', + deleteSynchronously: true, // should be run one at a time to allow asking for permission to mass-delete if *.fieldname is used fields: { 'Client.ID': { isCreateable: false, diff --git a/lib/metadataTypes/definitions/DataExtensionTemplate.definition.js b/lib/metadataTypes/definitions/DataExtensionTemplate.definition.js index 711f8454f..60a9daf1c 100644 --- a/lib/metadataTypes/definitions/DataExtensionTemplate.definition.js +++ b/lib/metadataTypes/definitions/DataExtensionTemplate.definition.js @@ -1,15 +1,18 @@ -module.exports = { +export default { bodyIteratorField: 'Results', dependencies: [], + dependencyGraph: null, filter: {}, hasExtended: false, idField: 'ObjectID', + keyIsFixed: true, keyField: 'CustomerKey', nameField: 'Name', restPagination: false, type: 'dataExtensionTemplate', typeDescription: 'Templates used for special DE use cases like Triggered Send.', typeRetrieveByDefault: false, + typeCdpByDefault: false, typeName: 'Data Extension Template', fields: { 'Client.ID': { @@ -60,6 +63,12 @@ module.exports = { retrieving: false, template: false, }, + PartnerProperties: { + isCreateable: false, + isUpdateable: false, + retrieving: false, + template: false, + }, IsSendable: { isCreateable: false, isUpdateable: false, retrieving: true, template: false }, IsTestable: { isCreateable: false, isUpdateable: false, retrieving: true, template: false }, SendableCustomObjectField: { diff --git a/lib/metadataTypes/definitions/DataExtract.definition.js b/lib/metadataTypes/definitions/DataExtract.definition.js index b0493de98..faa2566b5 100644 --- a/lib/metadataTypes/definitions/DataExtract.definition.js +++ b/lib/metadataTypes/definitions/DataExtract.definition.js @@ -1,14 +1,24 @@ -module.exports = { +export default { bodyIteratorField: 'items', - dependencies: ['dataExtension', 'dataExtractType'], + dependencies: ['dataExtension', 'dataExtractType', 'user'], + dependencyGraph: { + dataExtension: ['r__dataExtension_key'], + }, hasExtended: true, idField: 'dataExtractDefinitionId', + keyIsFixed: false, keyField: 'key', + createdDateField: 'createdDate', + createdNameField: 'createdBy', + lastmodDateField: 'modifiedDate', + lastmodNameField: 'modifiedBy', nameField: 'name', restPagination: true, + maxKeyLength: 36, // confirmed max length type: 'dataExtract', typeDescription: 'Creates zipped files in your FTP directory or convert XML into CSV.', typeRetrieveByDefault: true, + typeCdpByDefault: true, typeName: 'Automation: Data Extract Activity', fields: { createdBy: { @@ -30,8 +40,8 @@ module.exports = { template: false, }, dataExtractTypeId: { - isCreateable: null, - isUpdateable: null, + isCreateable: true, + isUpdateable: true, retrieving: true, template: true, }, @@ -39,20 +49,20 @@ module.exports = { skipValidation: true, }, description: { - isCreateable: null, - isUpdateable: null, + isCreateable: true, + isUpdateable: true, retrieving: true, template: true, }, endDate: { - isCreateable: null, - isUpdateable: null, + isCreateable: true, + isUpdateable: true, retrieving: true, template: true, }, fileSpec: { - isCreateable: null, - isUpdateable: null, + isCreateable: true, + isUpdateable: true, retrieving: true, template: true, }, @@ -63,8 +73,8 @@ module.exports = { template: true, }, key: { - isCreateable: null, - isUpdateable: false, + isCreateable: true, + isUpdateable: true, retrieving: true, template: true, }, @@ -81,17 +91,28 @@ module.exports = { template: false, }, name: { - isCreateable: null, - isUpdateable: false, + isCreateable: true, + isUpdateable: true, retrieving: true, template: true, }, startDate: { - isCreateable: null, - isUpdateable: null, + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + r__dataExtractType_name: { + isCreateable: false, + isUpdateable: false, + retrieving: true, + template: true, + }, + r__dataExtension_key: { + isCreateable: false, + isUpdateable: false, retrieving: true, template: true, }, - r__dataExtractType_name: { skipValidation: true }, }, }; diff --git a/lib/metadataTypes/definitions/DataExtractType.definition.js b/lib/metadataTypes/definitions/DataExtractType.definition.js index 86fae7628..9cdd6e019 100644 --- a/lib/metadataTypes/definitions/DataExtractType.definition.js +++ b/lib/metadataTypes/definitions/DataExtractType.definition.js @@ -1,8 +1,10 @@ -module.exports = { - bodyIteratorField: [], +export default { + bodyIteratorField: '', dependencies: [], + dependencyGraph: null, hasExtended: false, idField: 'extractId', + keyIsFixed: true, keyField: 'name', nameField: 'name', restPagination: false, @@ -10,6 +12,7 @@ module.exports = { typeDescription: 'Types of Data Extracts enabled for a specific business unit. This normally should not be stored.', typeRetrieveByDefault: false, + typeCdpByDefault: false, typeName: 'Data Extract Type', fields: { name: { diff --git a/lib/metadataTypes/definitions/DataFilter.definition.js b/lib/metadataTypes/definitions/DataFilter.definition.js new file mode 100644 index 000000000..68a1a7b78 --- /dev/null +++ b/lib/metadataTypes/definitions/DataFilter.definition.js @@ -0,0 +1,169 @@ +export default { + bodyIteratorField: 'items', + dependencies: ['folder-filterdefinition', 'folder-hidden', 'dataExtension'], + dependencyGraph: { + dataExtension: ['r__source_dataExtension_key'], + }, + filter: {}, + hasExtended: false, + idField: 'id', + keyIsFixed: false, + keyField: 'key', + nameField: 'name', + folderType: 'filterdefinition', + folderIdField: 'categoryId', + createdDateField: 'createdDate', + createdNameField: 'createdBy', + lastmodDateField: 'lastUpdated', + lastmodNameField: 'lastUpdatedBy', + restPagination: true, + restPageSize: 100, + maxKeyLength: 36, // confirmed max length + type: 'dataFilter', + soapType: 'FilterDefinition', + typeDescription: 'Defines an audience based on specified rules. Used by Filter Activities.', + typeRetrieveByDefault: true, + typeCdpByDefault: true, + typeName: 'Data Filter', + fields: { + // the GUI seems to ONLY send fields during update that are actually changed. It has yet to be tested if that also works with sending other fiedls as well + id: { + isCreateable: false, + isUpdateable: false, // included in URL + retrieving: false, + template: false, + }, + key: { + isCreateable: true, + isUpdateable: true, // can be updated + retrieving: true, + template: true, + }, + createdDate: { + isCreateable: false, + isUpdateable: false, + retrieving: true, + template: false, + }, + createdBy: { + isCreateable: false, + isUpdateable: false, + retrieving: false, + template: false, + }, + owner: { + // equal to createdBy + isCreateable: false, + isUpdateable: false, + retrieving: false, + template: false, + }, + createdByName: { + // actual name of user indicated by id in createdBy + isCreateable: false, + isUpdateable: false, + retrieving: true, + template: false, + }, + lastUpdated: { + isCreateable: false, + isUpdateable: false, + retrieving: true, + template: false, + }, + lastUpdatedBy: { + isCreateable: false, + isUpdateable: false, + retrieving: false, + template: false, + }, + lastUpdatedByName: { + // actual name of user indicated by id in lastUpdatedBy + isCreateable: false, + isUpdateable: false, + retrieving: true, + template: false, + }, + name: { + isCreateable: true, + isUpdateable: true, // can be updated + retrieving: true, + template: true, + }, + categoryId: { + // returned by GET / CREATE / UPDATE; used in CREATE payload + isCreateable: true, + isUpdateable: true, // can be updated + retrieving: true, + template: true, + }, + description: { + isCreateable: true, + isUpdateable: true, // can be updated + retrieving: true, + template: true, + }, + filterDefinitionXml: { + isCreateable: true, + isUpdateable: true, // this is the only field that can be updated + retrieving: true, + template: true, + }, + // DerivedFromType: { + // // this upper-cased spelling is used by GUI when creating a dataExtension based filterDefintion + // isCreateable: true, + // isUpdateable: false, // cannot be updated + // retrieving: false, + // template: false, + // }, + derivedFromType: { + // 1: SubscriberAttributes, 2: DataExtension, 6: EntryCriteria; + isCreateable: true, + isUpdateable: false, // cannot be updated + retrieving: true, + template: true, + }, + derivedFromObjectId: { + // dataExtension ID or '00000000-0000-0000-0000-000000000000' for lists + isCreateable: true, + isUpdateable: false, // cannot be updated + retrieving: true, + template: true, + }, + derivedFromObjectTypeName: { + // "SubscriberAttributes" | "DataExtension" | "EntryCriteria" ...; only returned by GET API + isCreateable: false, + isUpdateable: false, // cannot be updated + retrieving: true, + template: true, + }, + derivedFromObjectName: { + // dataExtension name; field only returned by GET-API + isCreateable: false, + isUpdateable: false, // cannot be updated + retrieving: true, + template: true, + }, + isSendable: { + isCreateable: false, // automatically set during create + isUpdateable: false, // cannot be updated + retrieving: true, + template: true, + }, + r__source_dataExtension_key: { + isCreateable: false, + isUpdateable: false, + retrieving: true, + template: true, + }, + c__filterDefinition: { + skipValidation: true, + }, + r__folder_Path: { + isCreateable: false, + isUpdateable: false, + retrieving: true, + template: true, + }, + }, +}; diff --git a/lib/metadataTypes/definitions/DataFilterHidden.definition.js b/lib/metadataTypes/definitions/DataFilterHidden.definition.js new file mode 100644 index 000000000..6fed2787c --- /dev/null +++ b/lib/metadataTypes/definitions/DataFilterHidden.definition.js @@ -0,0 +1,170 @@ +export default { + bodyIteratorField: 'items', + dependencies: ['folder-filterdefinition', 'folder-hidden', 'dataExtension'], + dependencyGraph: { + dataExtension: ['r__source_dataExtension_key'], + }, + filter: {}, + hasExtended: false, + idField: 'id', + keyIsFixed: false, + keyField: 'key', + nameField: 'name', + folderType: 'filterdefinition', + folderIdField: 'categoryId', + createdDateField: 'createdDate', + createdNameField: 'createdBy', + lastmodDateField: 'lastUpdated', + lastmodNameField: 'lastUpdatedBy', + restPagination: true, + restPageSize: 100, + maxKeyLength: 36, // confirmed max length + type: 'dataFilterHidden', + soapType: 'FilterDefinition', + typeDescription: + 'Defines an audience based on specified rules. Auto-generated by filtered DEs and filtered Lists.', + typeRetrieveByDefault: false, + typeCdpByDefault: false, + typeName: 'Data Filter (auto-generated)', + fields: { + // the GUI seems to ONLY send fields during update that are actually changed. It has yet to be tested if that also works with sending other fiedls as well + id: { + isCreateable: false, + isUpdateable: false, // included in URL + retrieving: false, + template: false, + }, + key: { + isCreateable: true, + isUpdateable: true, // can be updated + retrieving: true, + template: true, + }, + createdDate: { + isCreateable: false, + isUpdateable: false, + retrieving: true, + template: false, + }, + createdBy: { + isCreateable: false, + isUpdateable: false, + retrieving: false, + template: false, + }, + owner: { + // equal to createdBy + isCreateable: false, + isUpdateable: false, + retrieving: false, + template: false, + }, + createdByName: { + // actual name of user indicated by id in createdBy + isCreateable: false, + isUpdateable: false, + retrieving: true, + template: false, + }, + lastUpdated: { + isCreateable: false, + isUpdateable: false, + retrieving: true, + template: false, + }, + lastUpdatedBy: { + isCreateable: false, + isUpdateable: false, + retrieving: false, + template: false, + }, + lastUpdatedByName: { + // actual name of user indicated by id in lastUpdatedBy + isCreateable: false, + isUpdateable: false, + retrieving: true, + template: false, + }, + name: { + isCreateable: true, + isUpdateable: true, // can be updated + retrieving: true, + template: true, + }, + categoryId: { + // returned by GET / CREATE / UPDATE; used in CREATE payload + isCreateable: true, + isUpdateable: true, // can be updated + retrieving: true, + template: true, + }, + description: { + isCreateable: true, + isUpdateable: true, // can be updated + retrieving: true, + template: true, + }, + filterDefinitionXml: { + isCreateable: true, + isUpdateable: true, // this is the only field that can be updated + retrieving: true, + template: true, + }, + // DerivedFromType: { + // // this upper-cased spelling is used by GUI when creating a dataExtension based filterDefintion + // isCreateable: true, + // isUpdateable: false, // cannot be updated + // retrieving: false, + // template: false, + // }, + derivedFromType: { + // 1: SubscriberAttributes, 2: DataExtension, 6: EntryCriteria; + isCreateable: true, + isUpdateable: false, // cannot be updated + retrieving: true, + template: true, + }, + derivedFromObjectId: { + // dataExtension ID or '00000000-0000-0000-0000-000000000000' for lists + isCreateable: true, + isUpdateable: false, // cannot be updated + retrieving: true, + template: true, + }, + derivedFromObjectTypeName: { + // "SubscriberAttributes" | "DataExtension" | "EntryCriteria" ...; only returned by GET API + isCreateable: false, + isUpdateable: false, // cannot be updated + retrieving: true, + template: true, + }, + derivedFromObjectName: { + // dataExtension name; field only returned by GET-API + isCreateable: false, + isUpdateable: false, // cannot be updated + retrieving: true, + template: true, + }, + isSendable: { + isCreateable: false, // automatically set during create + isUpdateable: false, // cannot be updated + retrieving: true, + template: true, + }, + r__source_dataExtension_key: { + isCreateable: false, + isUpdateable: false, + retrieving: true, + template: true, + }, + c__filterDefinition: { + skipValidation: true, + }, + r__folder_Path: { + isCreateable: false, + isUpdateable: false, + retrieving: true, + template: true, + }, + }, +}; diff --git a/lib/metadataTypes/definitions/DeliveryProfile.definition.js b/lib/metadataTypes/definitions/DeliveryProfile.definition.js new file mode 100644 index 000000000..e182f046d --- /dev/null +++ b/lib/metadataTypes/definitions/DeliveryProfile.definition.js @@ -0,0 +1,61 @@ +export default { + bodyIteratorField: 'entry', + dependencies: [], + dependencyGraph: null, + filter: {}, + hasExtended: false, + idField: 'id', + keyField: 'key', + keyIsFixed: false, + maxKeyLength: 36, // confirmed max length + nameField: 'name', + createdDateField: 'createdDate', + createdNameField: null, + lastmodDateField: 'lastUpdated', + lastmodNameField: null, + restPagination: false, + type: 'deliveryProfile', + typeDescription: + 'Delivery profiles specify details such as IP address, domain, header inclusion, and footer; Via API we can only check for their existence but not see any details.', + typeRetrieveByDefault: false, + typeCdpByDefault: false, + typeName: 'Delivery Profile', + fields: { + id: { + isCreateable: false, + isUpdateable: false, + retrieving: true, + template: false, + }, + key: { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + name: { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + description: { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + createdDate: { + isCreateable: false, + isUpdateable: false, + retrieving: true, + template: false, + }, + lastUpdated: { + isCreateable: false, + isUpdateable: false, + retrieving: true, + template: false, + }, + }, +}; diff --git a/lib/metadataTypes/definitions/Discovery.definition.js b/lib/metadataTypes/definitions/Discovery.definition.js index 1e25682f4..2823a51a2 100644 --- a/lib/metadataTypes/definitions/Discovery.definition.js +++ b/lib/metadataTypes/definitions/Discovery.definition.js @@ -1,6 +1,7 @@ -module.exports = { +export default { bodyIteratorField: null, dependencies: [], + dependencyGraph: null, endPointMapping: { Address: '/address/v1/rest', Asset: '/asset/v1/rest', @@ -26,6 +27,7 @@ module.exports = { }, hasExtended: false, idField: '', + keyIsFixed: true, keyField: 'key', nameField: 'name', restPagination: false, @@ -33,6 +35,7 @@ module.exports = { typeDescription: 'Description of all API endpoints accessible via REST API; only relevant for developers of Accenture SFMC DevTools.', typeRetrieveByDefault: false, + typeCdpByDefault: false, typeName: 'API Discovery', fields: { basePath: { @@ -86,6 +89,18 @@ module.exports = { methods: { skipValidation: true, }, + metadata: { + isCreateable: false, + isUpdateable: false, + retrieving: true, + template: false, + }, + 'metadata.supportsResponseEncoding': { + isCreateable: false, + isUpdateable: false, + retrieving: true, + template: false, + }, name: { isCreateable: false, isUpdateable: false, diff --git a/lib/metadataTypes/definitions/DomainVerification.definition.js b/lib/metadataTypes/definitions/DomainVerification.definition.js new file mode 100644 index 000000000..a466cb81f --- /dev/null +++ b/lib/metadataTypes/definitions/DomainVerification.definition.js @@ -0,0 +1,72 @@ +export default { + bodyIteratorField: 'items', + dependencies: [], + dependencyGraph: null, + hasExtended: false, + idField: 'domain', + keyIsFixed: true, // you can only change the "isSendable" property + keyField: 'domain', + createdDateField: null, + createdNameField: null, + lastmodDateField: null, + lastmodNameField: null, + nameField: 'domain', + restPagination: true, + maxKeyLength: 254, // assumed max length + type: 'domainVerification', + typeDescription: 'Domains emails that are verified for sending', + typeRetrieveByDefault: true, + typeCdpByDefault: true, + typeName: 'Domain Verification', + fields: { + domain: { + isCreateable: true, + isUpdateable: false, + retrieving: true, + template: true, + }, + emailAddress: { + // this is the same as domain, but the update API uses this field name instead + isCreateable: false, + isUpdateable: true, + retrieving: false, + template: false, + }, + enterpriseId: { + isCreateable: false, + isUpdateable: false, + retrieving: false, + template: false, + }, + memberId: { + isCreateable: false, + isUpdateable: false, + retrieving: false, + template: false, + }, + domainType: { + isCreateable: false, + isUpdateable: false, + retrieving: true, + template: true, + }, + isSendable: { + isCreateable: false, + isUpdateable: true, + retrieving: true, + template: true, + }, + status: { + isCreateable: false, + isUpdateable: false, + retrieving: true, + template: false, + }, + emailSendTime: { + isCreateable: false, + isUpdateable: false, + retrieving: false, + template: false, + }, + }, +}; diff --git a/lib/metadataTypes/definitions/Email.definition.js b/lib/metadataTypes/definitions/Email.definition.js index eda5da370..ba66324a7 100644 --- a/lib/metadataTypes/definitions/Email.definition.js +++ b/lib/metadataTypes/definitions/Email.definition.js @@ -1,16 +1,20 @@ -module.exports = { +export default { bodyIteratorField: 'Results', - dependencies: ['folder'], + dependencies: ['folder-hidden', 'folder-email', 'folder-shared_email_default'], + dependencyGraph: null, hasExtended: false, idField: 'ID', keepId: true, + keyIsFixed: true, keyField: 'CustomerKey', nameField: 'Name', + folderIdField: 'CategoryID', restPagination: null, type: 'email', typeDescription: 'DEPRECATED: Old way of saving E-Mails; please migrate these to new E-Mail (`Asset: message`).', typeRetrieveByDefault: false, + typeCdpByDefault: false, typeName: 'E-Mail (Classic)', fields: { CategoryID: { diff --git a/lib/metadataTypes/definitions/EmailSendDefinition.definition.js b/lib/metadataTypes/definitions/EmailSend.definition.js similarity index 83% rename from lib/metadataTypes/definitions/EmailSendDefinition.definition.js rename to lib/metadataTypes/definitions/EmailSend.definition.js index ea6bb2b9b..11e05863a 100644 --- a/lib/metadataTypes/definitions/EmailSendDefinition.definition.js +++ b/lib/metadataTypes/definitions/EmailSend.definition.js @@ -1,47 +1,73 @@ -module.exports = { +export default { bodyIteratorField: 'Results', - dependencies: ['folder', 'email', 'asset-message', 'dataExtension', 'list'], // filter, SendClassification, SenderProfile, DeliveryProfile + dependencies: [ + 'folder-userinitiatedsends', + 'email', + 'asset-message', + 'dataExtension', + 'list', + 'sendClassification', + 'senderProfile', + 'deliveryProfile', + ], // filter(+) + dependencyGraph: { + asset: ['r__asset_key'], + dataExtension: ['SendDefinitionList.r__dataExtension_key'], + deliveryProfile: ['r__deliveryProfile_key'], + list: ['SendDefinitionList.r__list_PathName'], + sendClassification: ['r__sendClassification_key'], + senderProfile: ['r__senderProfile_key'], + }, folderType: 'userinitiatedsends', hasExtended: false, idField: 'ObjectID', keepId: true, + keyIsFixed: false, keyField: 'CustomerKey', nameField: 'Name', + folderIdField: 'CategoryID', + createdDateField: 'CreatedDate', + createdNameField: null, + lastmodDateField: 'ModifiedDate', + lastmodNameField: null, restPagination: null, - type: 'emailSendDefinition', + maxKeyLength: 36, // confirmed max length + type: 'emailSend', + soapType: 'emailSendDefinition', typeDescription: 'Mainly used in Automations as "Send Email Activity".', typeRetrieveByDefault: true, + typeCdpByDefault: true, typeName: 'E-Mail Send Definition', fields: { Additional: { isCreateable: true, isUpdateable: true, retrieving: true, - templating: false, + templating: true, }, AutoBccEmail: { isCreateable: true, isUpdateable: true, retrieving: true, - templating: false, + templating: true, }, BccEmail: { isCreateable: true, isUpdateable: true, retrieving: true, - templating: false, + templating: true, }, CategoryID: { isCreateable: true, isUpdateable: true, retrieving: true, - templating: false, + templating: true, }, CCEmail: { isCreateable: true, isUpdateable: true, retrieving: true, - templating: false, + templating: true, }, 'Client.ID': { isCreateable: false, @@ -65,19 +91,19 @@ module.exports = { isCreateable: true, isUpdateable: true, retrieving: true, - templating: false, + templating: true, }, DeduplicateByEmail: { isCreateable: true, isUpdateable: true, retrieving: true, - templating: false, + templating: true, }, 'DeliveryProfile.CustomerKey': { isCreateable: true, isUpdateable: true, retrieving: true, - templating: false, + templating: true, }, 'DeliveryProfile.DomainType': { isCreateable: false, @@ -125,13 +151,13 @@ module.exports = { isCreateable: true, isUpdateable: true, retrieving: true, - templating: false, + templating: true, }, 'DeliveryProfile.PrivateIP': { isCreateable: true, isUpdateable: true, retrieving: true, - templating: false, + templating: true, }, 'DeliveryProfile.SourceAddressType': { isCreateable: false, @@ -149,7 +175,7 @@ module.exports = { isCreateable: true, isUpdateable: true, retrieving: true, - templating: false, + templating: true, }, DomainType: { isCreateable: false, @@ -161,13 +187,13 @@ module.exports = { isCreateable: true, isUpdateable: true, retrieving: true, - templating: false, + templating: true, }, 'Email.ID': { isCreateable: true, isUpdateable: true, retrieving: true, - templating: false, + templating: true, }, 'Email.ObjectID': { isCreateable: false, @@ -181,17 +207,35 @@ module.exports = { retrieving: false, templating: false, }, + 'Email.Name': { + isCreateable: true, + isUpdateable: true, + retrieving: false, + templating: false, + }, + 'Email.Subject': { + isCreateable: true, + isUpdateable: true, + retrieving: false, + templating: false, + }, + 'Email.Status': { + isCreateable: true, + isUpdateable: true, + retrieving: false, + templating: false, + }, EmailSubject: { isCreateable: true, isUpdateable: true, retrieving: true, - templating: false, + templating: true, }, ExclusionFilter: { isCreateable: true, isUpdateable: true, retrieving: true, - templating: false, + templating: true, }, FooterContentArea: { isCreateable: false, @@ -251,7 +295,7 @@ module.exports = { isCreateable: true, isUpdateable: true, retrieving: true, - templating: false, + templating: true, }, IsPlatformObject: { isCreateable: true, @@ -275,7 +319,7 @@ module.exports = { isCreateable: true, isUpdateable: true, retrieving: true, - templating: false, + templating: true, }, Keyword: { isCreateable: false, @@ -299,11 +343,11 @@ module.exports = { isCreateable: true, isUpdateable: true, retrieving: true, - templating: false, + templating: true, }, ObjectID: { isCreateable: false, - isUpdateable: false, + isUpdateable: true, retrieving: false, templating: false, }, @@ -371,7 +415,7 @@ module.exports = { isCreateable: true, isUpdateable: true, retrieving: true, - templating: false, + templating: true, }, 'SendClassification.ObjectID': { isCreateable: false, @@ -395,7 +439,7 @@ module.exports = { isCreateable: true, isUpdateable: true, retrieving: true, - templating: false, + templating: true, }, 'SendDefinitionList[].ObjectID': { isCreateable: false, @@ -409,6 +453,9 @@ module.exports = { retrieving: false, templating: false, }, + 'SendDefinitionList[].CustomObjectID': { + skipValidation: true, // cannot be asked for but will be retrieved + }, 'SendDefinitionList[].SendDefinitionListType': { skipValidation: true, // cannot be asked for but will be retrieved }, @@ -424,7 +471,7 @@ module.exports = { 'SendDefinitionList[].Name': { skipValidation: true, // cannot be asked for but will be retrieved }, - 'SendDefinitionList[].r__dataExtension_Key': { + 'SendDefinitionList[].r__dataExtension_key': { skipValidation: true, }, 'SendDefinitionList[].List.ObjectID': { @@ -439,11 +486,14 @@ module.exports = { retrieving: false, templating: false, }, + 'SendDefinitionList[].r__list_PathName': { + skipValidation: true, + }, 'SenderProfile.CustomerKey': { isCreateable: true, isUpdateable: true, retrieving: true, - templating: false, + templating: true, }, 'SenderProfile.FromAddress': { isCreateable: false, @@ -473,13 +523,13 @@ module.exports = { isCreateable: true, isUpdateable: true, retrieving: true, - templating: false, + templating: true, }, SendWindowClose: { isCreateable: true, isUpdateable: true, retrieving: true, - templating: false, + templating: true, }, SendWindowDelete: { isCreateable: false, @@ -491,7 +541,7 @@ module.exports = { isCreateable: true, isUpdateable: true, retrieving: true, - templating: false, + templating: true, }, SourceAddressType: { isCreateable: false, @@ -503,13 +553,13 @@ module.exports = { isCreateable: true, isUpdateable: true, retrieving: true, - templating: false, + templating: true, }, TestEmailAddr: { isCreateable: true, isUpdateable: true, retrieving: true, - templating: false, + templating: true, }, TimeZone: { isCreateable: false, @@ -523,9 +573,12 @@ module.exports = { retrieving: false, templating: false, }, - r__assetMessage_Name: { skipValidation: true }, - r__assetMessage_Key: { skipValidation: true }, - r__email_Name: { skipValidation: true }, + r__asset_name_readOnly: { skipValidation: true }, + r__asset_key: { skipValidation: true }, + r__email_name: { skipValidation: true }, r__folder_Path: { skipValidation: true }, + r__senderProfile_key: { skipValidation: true }, + r__sendClassification_key: { skipValidation: true }, + r__deliveryProfile_key: { skipValidation: true }, }, }; diff --git a/lib/metadataTypes/definitions/EventDefinition.definition.js b/lib/metadataTypes/definitions/Event.definition.js similarity index 73% rename from lib/metadataTypes/definitions/EventDefinition.definition.js rename to lib/metadataTypes/definitions/Event.definition.js index 1068d5c81..7c9c08cce 100644 --- a/lib/metadataTypes/definitions/EventDefinition.definition.js +++ b/lib/metadataTypes/definitions/Event.definition.js @@ -1,22 +1,69 @@ -module.exports = { +export default { bodyIteratorField: 'items', - dependencies: ['dataExtension'], + dependencies: ['automation', 'dataExtension', 'dataExtensionField', 'user'], + dependencyGraph: { automation: ['r__automation_key'], dataExtension: ['r__dataExtension_key'] }, hasExtended: false, idField: 'id', + keyIsFixed: false, keyField: 'eventDefinitionKey', nameField: 'name', + createdDateField: 'createdDate', + createdNameField: 'createdBy', + lastmodDateField: 'modifiedDate', + lastmodNameField: 'modifiedBy', restPagination: true, - type: 'eventDefinition', + maxKeyLength: 200, // confirmed max length + type: 'event', typeDescription: 'Used in Journeys (Interactions) to define Entry Events.', - typeRetrieveByDefault: false, + typeRetrieveByDefault: true, + typeCdpByDefault: true, typeName: 'Journey: Entry Event Definition', + validTypes: [ + 'EmailAudience', // category: Audience; DEAudience-... + 'AutomationAudience', // category: Audience; DEAudience-... + 'APIEvent', // category: Event; APIEvent-... + 'SalesforceObjectTriggerV2', // category: Event; SalesforceObj... + ], fields: { + 'arguments.audienceCount': { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + 'arguments.audienceDefinitionID': { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + 'arguments.audienceDescription': { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + 'arguments.audienceSource': { + skipValidation: true, + }, + 'arguments.audienceName': { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, 'arguments.automationId': { isCreateable: true, isUpdateable: true, retrieving: true, template: true, }, + 'arguments.buildAudienceDefinitionID': { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, 'arguments.contactAttributeGroup': { isCreateable: true, isUpdateable: true, @@ -44,8 +91,8 @@ module.exports = { 'arguments.dataExtensionId': { isCreateable: true, isUpdateable: true, - retrieving: true, - template: true, + retrieving: false, + template: false, }, 'arguments.dataTargetName': { isCreateable: true, @@ -93,8 +140,8 @@ module.exports = { 'arguments.eventDefinitionKey': { isCreateable: true, isUpdateable: true, - retrieving: true, - template: true, + retrieving: false, + template: false, }, 'arguments.mid': { isCreateable: true, @@ -145,28 +192,52 @@ module.exports = { template: true, }, configurationArguments: { - isCreateable: false, - isUpdateable: false, - retrieving: false, - template: false, + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, }, 'configurationArguments.applicationExtensionKey': { - isCreateable: false, - isUpdateable: false, - retrieving: false, - template: false, + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, }, 'configurationArguments.contactKey': { - isCreateable: false, - isUpdateable: false, - retrieving: false, - template: false, + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + 'configurationArguments.contactKey.relationshipIdName': { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + 'configurationArguments.contactKey.relationshipName': { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + 'configurationArguments.contactKey.isPolymorphic': { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + 'configurationArguments.contactKey.referenceObjectName': { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, }, 'configurationArguments.contactPersonType': { - isCreateable: false, - isUpdateable: false, - retrieving: false, - template: false, + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, }, 'configurationArguments.dataExtensionId': { isCreateable: false, @@ -175,64 +246,82 @@ module.exports = { template: false, }, 'configurationArguments.evaluationCriteriaSummary': { - isCreateable: false, - isUpdateable: false, - retrieving: false, - template: false, + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, }, 'configurationArguments.eventDataConfig': { - isCreateable: false, - isUpdateable: false, - retrieving: false, - template: false, + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + 'configurationArguments.eventDataConfig.objects': { + skipValidation: true, }, 'configurationArguments.eventDataSummary': { - isCreateable: false, - isUpdateable: false, - retrieving: false, - template: false, + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, }, 'configurationArguments.objectAPIName': { - isCreateable: false, - isUpdateable: false, - retrieving: false, - template: false, + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, }, 'configurationArguments.passThroughArgument': { - isCreateable: false, - isUpdateable: false, - retrieving: false, - template: false, + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + 'configurationArguments.passThroughArgument.fields': { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + 'configurationArguments.passThroughArgument.fields.ContactKey': { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + 'configurationArguments.passThroughArgument.fields.Email': { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, }, 'configurationArguments.primaryObjectFilterCriteria': { - isCreateable: false, - isUpdateable: false, - retrieving: false, - template: false, + skipValidation: true, }, 'configurationArguments.primaryObjectFilterSummary': { - isCreateable: false, - isUpdateable: false, - retrieving: false, - template: false, + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, }, 'configurationArguments.relatedObjectFilterCriteria': { - isCreateable: false, - isUpdateable: false, - retrieving: false, - template: false, + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, }, 'configurationArguments.relatedObjectFilterSummary': { - isCreateable: false, - isUpdateable: false, - retrieving: false, - template: false, + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, }, 'configurationArguments.salesforceTriggerCriteria': { - isCreateable: false, - isUpdateable: false, - retrieving: false, - template: false, + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, }, 'configurationArguments.unconfigured': { isCreateable: false, @@ -241,16 +330,16 @@ module.exports = { template: false, }, 'configurationArguments.version': { - isCreateable: false, - isUpdateable: false, - retrieving: false, - template: false, + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, }, 'configurationArguments.whoToInject': { - isCreateable: false, - isUpdateable: false, - retrieving: false, - template: false, + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, }, createdBy: { isCreateable: false, @@ -271,12 +360,18 @@ module.exports = { template: false, }, dataExtensionName: { + isCreateable: false, + isUpdateable: false, + retrieving: false, + template: false, + }, + description: { isCreateable: true, isUpdateable: true, retrieving: true, template: true, }, - description: { + disableDEDataLogging: { isCreateable: true, isUpdateable: true, retrieving: true, @@ -291,7 +386,7 @@ module.exports = { filterDefinitionId: { isCreateable: true, isUpdateable: true, - retrieving: false, + retrieving: true, template: false, }, filterDefinitionTemplate: { @@ -319,7 +414,7 @@ module.exports = { template: false, }, isPlatformObject: { - isCreateable: true, + isCreateable: false, isUpdateable: true, retrieving: true, template: true, @@ -337,33 +432,33 @@ module.exports = { template: true, }, 'metaData.automationData.automationType': { - isCreateable: false, - isUpdateable: false, + isCreateable: true, + isUpdateable: true, retrieving: true, - template: false, + template: true, }, 'metaData.automationData.categoryId': { - isCreateable: false, - isUpdateable: false, + isCreateable: true, + isUpdateable: true, retrieving: true, - template: false, + template: true, }, 'metaData.automationData.createdBy.email': { isCreateable: false, isUpdateable: false, - retrieving: true, + retrieving: false, template: false, }, 'metaData.automationData.createdBy.id': { isCreateable: false, isUpdateable: false, - retrieving: true, + retrieving: false, template: false, }, 'metaData.automationData.createdBy.name': { isCreateable: false, isUpdateable: false, - retrieving: true, + retrieving: false, template: false, }, 'metaData.automationData.createdDate': { @@ -373,34 +468,34 @@ module.exports = { template: false, }, 'metaData.automationData.description': { - isCreateable: false, - isUpdateable: false, + isCreateable: true, + isUpdateable: true, retrieving: true, - template: false, + template: true, }, 'metaData.automationData.folderPath': { - isCreateable: false, - isUpdateable: false, + isCreateable: true, + isUpdateable: true, retrieving: true, - template: false, + template: true, }, 'metaData.automationData.guidId': { - isCreateable: false, - isUpdateable: false, + isCreateable: true, + isUpdateable: true, retrieving: true, - template: false, + template: true, }, 'metaData.automationData.id': { isCreateable: true, isUpdateable: true, - retrieving: false, + retrieving: true, template: true, }, 'metaData.automationData.isPlatformObject': { - isCreateable: false, - isUpdateable: false, + isCreateable: true, + isUpdateable: true, retrieving: true, - template: false, + template: true, }, 'metaData.automationData.key': { isCreateable: true, @@ -429,13 +524,13 @@ module.exports = { 'metaData.automationData.lastSavedBy.email': { isCreateable: false, isUpdateable: false, - retrieving: true, + retrieving: false, template: false, }, 'metaData.automationData.lastSavedBy.id': { isCreateable: false, isUpdateable: false, - retrieving: true, + retrieving: false, template: false, }, 'metaData.automationData.lastSavedBy.name': { @@ -445,8 +540,8 @@ module.exports = { template: false, }, 'metaData.automationData.memberId': { - isCreateable: false, - isUpdateable: false, + isCreateable: true, + isUpdateable: true, retrieving: true, template: false, }, @@ -457,28 +552,28 @@ module.exports = { template: false, }, 'metaData.automationData.name': { - isCreateable: false, - isUpdateable: false, + isCreateable: true, + isUpdateable: true, retrieving: true, - template: false, + template: true, }, 'metaData.automationData.notifications': { - isCreateable: false, - isUpdateable: false, + isCreateable: true, + isUpdateable: true, retrieving: true, - template: false, + template: true, }, 'metaData.automationData.processes': { - isCreateable: false, - isUpdateable: false, - retrieving: false, - template: false, + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, }, 'metaData.automationData.schedule': { - isCreateable: false, - isUpdateable: false, + isCreateable: true, + isUpdateable: true, retrieving: true, - template: false, + template: true, }, 'metaData.automationData.scheduleObject.createdBy': { isCreateable: false, @@ -493,16 +588,16 @@ module.exports = { template: false, }, 'metaData.automationData.scheduleObject.description': { - isCreateable: false, - isUpdateable: false, + isCreateable: true, + isUpdateable: true, retrieving: true, - template: false, + template: true, }, 'metaData.automationData.scheduleObject.iCalRecur': { - isCreateable: false, - isUpdateable: false, + isCreateable: true, + isUpdateable: true, retrieving: true, - template: false, + template: true, }, 'metaData.automationData.scheduleObject.id': { isCreateable: false, @@ -529,46 +624,46 @@ module.exports = { template: false, }, 'metaData.automationData.scheduleObject.name': { - isCreateable: false, - isUpdateable: false, + isCreateable: true, + isUpdateable: true, retrieving: true, - template: false, + template: true, }, 'metaData.automationData.scheduleObject.scheduleState': { - isCreateable: false, - isUpdateable: false, + isCreateable: true, + isUpdateable: true, retrieving: true, - template: false, + template: true, }, 'metaData.automationData.scheduleObject.scheduleStatus': { - isCreateable: false, - isUpdateable: false, + isCreateable: true, + isUpdateable: true, retrieving: true, - template: false, + template: true, }, 'metaData.automationData.scheduleObject.startDate': { - isCreateable: false, - isUpdateable: false, + isCreateable: true, + isUpdateable: true, retrieving: true, - template: false, + template: true, }, 'metaData.automationData.scheduleObject.timeZone': { - isCreateable: false, - isUpdateable: false, + isCreateable: true, + isUpdateable: true, retrieving: true, - template: false, + template: true, }, 'metaData.automationData.scheduleObject.timeZoneId': { - isCreateable: false, - isUpdateable: false, + isCreateable: true, + isUpdateable: true, retrieving: true, - template: false, + template: true, }, 'metaData.automationData.scheduledTime': { - isCreateable: false, - isUpdateable: false, + isCreateable: true, + isUpdateable: true, retrieving: true, - template: false, + template: true, }, 'metaData.automationData.selectedCategoryId': { isCreateable: false, @@ -583,10 +678,10 @@ module.exports = { template: false, }, 'metaData.automationData.status': { - isCreateable: false, - isUpdateable: false, + isCreateable: true, + isUpdateable: true, retrieving: true, - template: false, + template: true, }, 'metaData.automationData.updateInProgress': { isCreateable: false, @@ -687,8 +782,8 @@ module.exports = { mode: { isCreateable: true, isUpdateable: true, - retrieving: true, - template: true, + retrieving: false, + template: false, }, modifiedBy: { isCreateable: false, @@ -714,6 +809,18 @@ module.exports = { retrieving: true, template: false, }, + 'schedule.scheduledDayOfWeek': { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + 'schedule.scheduledWeek': { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, 'schedule.endDateTime': { isCreateable: true, isUpdateable: true, @@ -769,46 +876,46 @@ module.exports = { template: true, }, 'schedule.monday': { - isCreateable: false, - isUpdateable: false, + isCreateable: true, + isUpdateable: true, retrieving: true, - template: false, + template: true, }, 'schedule.tuesday': { - isCreateable: false, - isUpdateable: false, + isCreateable: true, + isUpdateable: true, retrieving: true, - template: false, + template: true, }, 'schedule.wednesday': { - isCreateable: false, - isUpdateable: false, + isCreateable: true, + isUpdateable: true, retrieving: true, - template: false, + template: true, }, 'schedule.thursday': { - isCreateable: false, - isUpdateable: false, + isCreateable: true, + isUpdateable: true, retrieving: true, - template: false, + template: true, }, 'schedule.friday': { - isCreateable: false, - isUpdateable: false, + isCreateable: true, + isUpdateable: true, retrieving: true, - template: false, + template: true, }, 'schedule.saturday': { - isCreateable: false, - isUpdateable: false, + isCreateable: true, + isUpdateable: true, retrieving: true, - template: false, + template: true, }, 'schedule.sunday': { - isCreateable: false, - isUpdateable: false, + isCreateable: true, + isUpdateable: true, retrieving: true, - template: false, + template: true, }, 'schema.fields': { isCreateable: true, @@ -861,14 +968,14 @@ module.exports = { 'schema.id': { isCreateable: false, isUpdateable: true, - retrieving: true, + retrieving: false, template: false, }, 'schema.name': { isCreateable: true, isUpdateable: true, - retrieving: true, - template: true, + retrieving: false, + template: false, }, 'schema.sendableCustomObjectField': { isCreateable: true, @@ -882,17 +989,41 @@ module.exports = { retrieving: true, template: true, }, + 'schema.isPlatformObject': { + isCreateable: false, + isUpdateable: true, + retrieving: false, + template: false, + }, sourceApplicationExtensionId: { isCreateable: true, isUpdateable: true, retrieving: true, template: true, }, + entrySourceGroupConfigUrl: { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, type: { isCreateable: true, isUpdateable: true, retrieving: true, template: true, }, + r__dataExtension_key: { + isCreateable: false, + isUpdateable: false, + retrieving: true, + template: true, + }, + r__automation_key: { + isCreateable: false, + isUpdateable: false, + retrieving: true, + template: true, + }, }, }; diff --git a/lib/metadataTypes/definitions/FileLocation.definition.js b/lib/metadataTypes/definitions/FileLocation.definition.js new file mode 100644 index 000000000..656eb2a29 --- /dev/null +++ b/lib/metadataTypes/definitions/FileLocation.definition.js @@ -0,0 +1,118 @@ +export default { + bodyIteratorField: 'items', + dependencies: [], + dependencyGraph: null, + hasExtended: false, + idField: 'id', + keyIsFixed: true, + keyField: 'customerKey', + nameField: 'name', + createdDateField: null, + createdNameField: null, + lastmodDateField: null, + lastmodNameField: null, + restPagination: false, + maxKeyLength: 36, // confirmed max length + type: 'fileLocation', + typeDescription: + 'Used for export or import of files to/from Marketing Cloud. Previously this was labeled ftpLocation.', + typeRetrieveByDefault: true, + typeCdpByDefault: false, + typeName: 'File Location', + locationTypeMapping: { + 'Enhanced FTP Site Import Directory': 0, + 'External FTP Site': 1, + 'External SFTP Site': 2, + 'External FTPS Site': 3, + 'Salesforce Objects and Reports': 4, + Safehouse: 5, + 'Enhanced FTP Site Export Directory': 6, + 'Legacy Import Directory': 8, + 'Relative location under FTP Site': 9, + 'Amazon Simple Storage Service': 13, + 'Azure Blob Storage': 15, + 'Google Cloud Storage': 16, + }, + locationTypeMappingDeployable: { + 'External SFTP Site': 'ExternalSftp', + 'Amazon Simple Storage Service': 'AmazonSimpleStorage', + 'Azure Blob Storage': 'AzureBlobStorage', + 'Google Cloud Storage': 'GcpBlobStorage', + }, + locationTypeIdMappingDeployable: { + 2: 'ExternalSftp', + 13: 'AmazonSimpleStorage', + 15: 'AzureBlobStorage', + 16: 'GcpBlobStorage', + }, + fields: { + id: { + isCreateable: false, + isUpdateable: false, + retrieving: false, + template: false, + }, + locationTypeId: { + // automation endpoint + isCreateable: false, + isUpdateable: false, + retrieving: false, + template: false, + }, + locationType: { + // data endpoint + isCreateable: true, + isUpdateable: true, + retrieving: false, + template: false, + }, + locationUrl: { + isCreateable: false, + isUpdateable: false, + retrieving: false, + template: false, + }, + name: { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + customerKey: { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + description: { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + relPath: { + isCreateable: false, + isUpdateable: false, + retrieving: false, + template: false, + }, + awsFileTransferLocation: { + skipValidation: true, + }, + azureFileTransferLocation: { + skipValidation: true, + }, + gcpFileTransferLocation: { + skipValidation: true, + }, + sFtpFileTransferLocation: { + skipValidation: true, + }, + c__locationType: { + isCreateable: false, + isUpdateable: false, + retrieving: true, + template: true, + }, + }, +}; diff --git a/lib/metadataTypes/definitions/FileTransfer.definition.js b/lib/metadataTypes/definitions/FileTransfer.definition.js index 39f2d13d9..40065630c 100644 --- a/lib/metadataTypes/definitions/FileTransfer.definition.js +++ b/lib/metadataTypes/definitions/FileTransfer.definition.js @@ -1,15 +1,25 @@ -module.exports = { +export default { bodyIteratorField: 'items', - dependencies: ['ftpLocation'], + dependencies: ['fileLocation'], + dependencyGraph: { + // fileLocation cannot be deployed + // fileLocation: ['metadata.source.r__fileLocation_name'], + }, hasExtended: true, idField: 'id', + keyIsFixed: false, keyField: 'customerKey', nameField: 'name', + createdDateField: 'createdDate', + createdNameField: null, + lastmodDateField: 'modifiedDate', + lastmodNameField: null, restPagination: true, type: 'fileTransfer', typeDescription: 'Unzip, decrypt a file or move a file from secure location into FTP directory.', typeRetrieveByDefault: true, + typeCdpByDefault: true, typeName: 'Automation: File Transfer Activity', fields: { createdDate: { @@ -114,6 +124,6 @@ module.exports = { retrieving: true, template: true, }, - r__ftpLocation_name: { skipValidation: true }, + r__fileLocation_name: { skipValidation: true }, }, }; diff --git a/lib/metadataTypes/definitions/Filter.definition.js b/lib/metadataTypes/definitions/Filter.definition.js index b9503571f..76ae6c136 100644 --- a/lib/metadataTypes/definitions/Filter.definition.js +++ b/lib/metadataTypes/definitions/Filter.definition.js @@ -1,62 +1,118 @@ -module.exports = { +export default { bodyIteratorField: 'items', - dependencies: [], + dependencies: [ + 'dataFilter', + 'dataFilterHidden', + 'list', + 'dataExtension', + 'folder-filteractivity', + 'folder-hidden', + ], + dependencyGraph: { + filterDefinition: ['r__dataFilter_key'], + dataExtension: ['r__source_dataExtension_key', 'r__destination_dataExtension_key'], + }, hasExtended: false, - idField: 'id', + idField: 'filterActivityId', + keyIsFixed: true, keyField: 'customerKey', nameField: 'name', + folderType: 'filteractivity', + folderIdField: 'categoryId', + filter: { + statusId: 0, // exclude deleted filters + }, + createdDateField: 'createdDate', + createdNameField: null, + lastmodDateField: 'modifiedDate', + lastmodNameField: null, restPagination: true, + maxKeyLength: 36, // confirmed max length type: 'filter', + soapType: 'FilterActivity', typeDescription: - 'BETA: Part of how filtered Data Extensions are created. Depends on type "FilterDefinitions".', - typeRetrieveByDefault: false, + 'Used in automations to filter lists and DEs. Depends on type "FilterDefinitions".', + typeRetrieveByDefault: true, + typeCdpByDefault: true, typeName: 'Automation: Filter Activity', fields: { + // https://developer.salesforce.com/docs/atlas.en-us.noversion.mc-apis.meta/mc-apis/filteractivity.htm categoryId: { isCreateable: false, - isUpdateable: false, + isUpdateable: true, retrieving: true, - template: false, + template: true, }, createdDate: { isCreateable: false, isUpdateable: false, - retrieving: true, + retrieving: false, template: false, }, customerKey: { - isCreateable: null, - isUpdateable: false, + isCreateable: false, + isUpdateable: true, retrieving: true, + template: true, + }, + CustomerKey: { + isCreateable: true, + isUpdateable: false, + retrieving: false, template: false, }, description: { isCreateable: false, - isUpdateable: false, + isUpdateable: true, retrieving: true, + template: true, + }, + Description: { + isCreateable: true, + isUpdateable: false, + retrieving: false, template: false, }, destinationObjectId: { isCreateable: false, - isUpdateable: false, + isUpdateable: true, retrieving: true, + template: true, + }, + DestinationObjectID: { + isCreateable: true, + isUpdateable: false, + retrieving: false, template: false, }, destinationTypeId: { isCreateable: false, - isUpdateable: false, + isUpdateable: true, retrieving: true, + template: true, + }, + DestinationTypeID: { + isCreateable: true, + isUpdateable: false, + retrieving: false, template: false, }, filterActivityId: { - isCreateable: null, - isUpdateable: null, - retrieving: true, + isCreateable: false, + isUpdateable: true, + retrieving: false, + template: false, }, filterDefinitionId: { isCreateable: false, - isUpdateable: false, + isUpdateable: true, retrieving: true, + template: true, + }, + FilterDefinitionID: { + isCreateable: true, + isUpdateable: false, + retrieving: false, template: false, }, modifiedDate: { @@ -66,28 +122,94 @@ module.exports = { template: false, }, name: { - isCreateable: null, - isUpdateable: false, + isCreateable: false, + isUpdateable: true, retrieving: true, + template: true, + }, + Name: { + isCreateable: true, + isUpdateable: false, + retrieving: false, template: false, }, sourceObjectId: { isCreateable: false, - isUpdateable: false, + isUpdateable: true, retrieving: true, + template: true, + }, + SourceObjectID: { + isCreateable: true, + isUpdateable: false, + retrieving: false, template: false, }, sourceTypeId: { isCreateable: false, isUpdateable: false, retrieving: true, + template: true, + }, + SourceTypeID: { + isCreateable: true, + isUpdateable: false, + retrieving: false, + template: false, + }, + filterDefinitionSourceTypeId: { + isCreateable: false, + isUpdateable: true, + retrieving: false, template: false, }, statusId: { isCreateable: false, - isUpdateable: false, + isUpdateable: true, retrieving: true, + template: true, + }, + resultDEName: { + isCreateable: false, + isUpdateable: true, + retrieving: false, template: false, }, + resultDEKey: { + isCreateable: false, + isUpdateable: true, + retrieving: false, + template: false, + }, + resultDEDescription: { + isCreateable: false, + isUpdateable: true, + retrieving: false, + template: false, + }, + r__folder_Path: { + isCreateable: false, + isUpdateable: false, + retrieving: true, + template: true, + }, + r__dataFilter_key: { + isCreateable: false, + isUpdateable: false, + retrieving: true, + template: true, + }, + r__source_dataExtension_key: { + isCreateable: false, + isUpdateable: false, + retrieving: true, + template: true, + }, + r__destination_dataExtension_key: { + isCreateable: false, + isUpdateable: false, + retrieving: true, + template: true, + }, }, }; diff --git a/lib/metadataTypes/definitions/Folder.definition.js b/lib/metadataTypes/definitions/Folder.definition.js index b2a487cc7..8f89257e4 100644 --- a/lib/metadataTypes/definitions/Folder.definition.js +++ b/lib/metadataTypes/definitions/Folder.definition.js @@ -1,12 +1,48 @@ -module.exports = { +export default { bodyIteratorField: 'Results', dependencies: [], + dependencyGraph: null, + subTypes: [ + 'asset-shared', + 'asset', + 'automations', + 'contextual_suppression_list', + 'cloudpages', + 'dataextension', + 'filteractivity', + 'filterdefinition', + 'hidden', + 'journey', + 'list', + 'mysubs', + 'publication', + 'queryactivity', + 'salesforcedataextension', + 'shared_content', + 'shared_data', + 'shared_dataextension', + 'shared_email', + 'shared_item', + 'shared_portfolio', + 'shared_publication', + 'shared_salesforcedataextension', + 'shared_suppression_list', + 'shared_template', + 'ssjsactivity', + 'suppression_list', + 'synchronizeddataextension', + 'triggered_send_journeybuilder', + 'triggered_send', + ], deployFolderTypes: [ // lower-case values! 'asset', + 'automations', + 'cloudpages', 'dataextension', 'filteractivity', 'filterdefinition', + 'journey', 'list', 'mysubs', 'publication', @@ -17,36 +53,43 @@ module.exports = { 'ssjsactivity', 'suppression_list', 'synchronizeddataextension', - 'triggered_send', 'triggered_send_journeybuilder', + 'triggered_send', ], + deployFolderTypesEmailRest: ['automations', 'journey', 'triggered_send_journeybuilder'], + deployFolderTypesAssetRest: ['cloudpages', 'asset', 'asset-shared'], deployFolderBlacklist: [ // lower-case values! 'shared data extensions', 'shared salesforce data extensions', ], folderTypesFromParent: [ + 'asset-shared', + 'asset', + 'shared_content', 'shared_data', 'shared_dataextension', - 'shared_salesforcedataextension', - 'synchronizeddataextension', + 'shared_email', 'shared_item', 'shared_portfolio', - 'shared_template', - 'shared_email', - 'shared_content', - 'shared_suppression_list', 'shared_publication', - 'asset-shared', + 'shared_salesforcedataextension', + 'shared_suppression_list', + 'shared_template', + 'synchronizeddataextension', ], hasExtended: false, idField: 'ID', + keepId: true, + keyIsFixed: true, keyField: 'CustomerKey', nameField: 'Name', restPagination: false, type: 'folder', + soapType: 'DataFolder', typeDescription: 'Used to structure all kinds of other metadata.', typeRetrieveByDefault: false, + typeCdpByDefault: false, typeName: 'Folder', fields: { $: { @@ -55,6 +98,12 @@ module.exports = { retrieving: false, template: false, }, + '@_xsi:type': { + isCreateable: false, + isUpdateable: false, + retrieving: false, + template: false, + }, ID: { isCreateable: true, isUpdateable: true, @@ -75,10 +124,17 @@ module.exports = { }, Description: { isCreateable: true, - isUpdateable: true, + isUpdateable: false, // dont update this to prevent accidental overrides by auto-created folders retrieving: true, template: false, }, + description: { + // used for cloudpages folders only + isCreateable: true, + isUpdateable: true, + retrieving: false, + template: false, + }, CreatedDate: { isCreateable: false, isUpdateable: false, @@ -97,6 +153,20 @@ module.exports = { retrieving: true, template: true, }, + categoryType: { + // REST only, used for cloudpages folders only + isCreateable: true, + isUpdateable: true, + retrieving: false, + template: false, + }, + catType: { + // REST only, equal to SOAP's ContentType + isCreateable: true, + isUpdateable: false, + retrieving: false, + template: false, + }, IsActive: { isCreateable: true, isUpdateable: true, @@ -109,24 +179,54 @@ module.exports = { retrieving: true, template: true, }, + editable: { + // used for cloudpages folders only + isCreateable: true, + isUpdateable: true, + retrieving: false, + template: false, + }, AllowChildren: { isCreateable: true, isUpdateable: true, retrieving: true, template: true, }, + extendable: { + // used for cloudpages folders only + isCreateable: true, + isUpdateable: true, + retrieving: false, + template: false, + }, ObjectID: { isCreateable: false, isUpdateable: false, retrieving: false, template: false, }, + objectId: { + // REST only, equal to SOAP's ObjectID + // automation/journey folders only + isCreateable: false, + isUpdateable: false, + retrieving: false, + template: false, + }, Name: { isCreateable: true, isUpdateable: true, retrieving: true, template: true, }, + name: { + // REST only, equal to SOAP's Name + // cloudpages and automation/journey folders only + isCreateable: true, + isUpdateable: true, + retrieving: false, + template: false, + }, 'ParentFolder.CustomerKey': { isCreateable: false, isUpdateable: false, @@ -139,6 +239,20 @@ module.exports = { retrieving: true, template: false, }, + parentCatId: { + // REST only, used for journey/automation folders, equal to SOAP's ParentFolder.ID + isCreateable: true, + isUpdateable: true, + retrieving: false, + template: false, + }, + parentId: { + // REST only, used for cloudpages folders, equal to SOAP's ParentFolder.ID + isCreateable: true, + isUpdateable: true, + retrieving: false, + template: false, + }, 'ParentFolder.PartnerKey': { isCreateable: false, isUpdateable: false, @@ -169,5 +283,11 @@ module.exports = { retrieving: false, template: false, }, + _generated: { + isCreateable: false, + isUpdateable: false, + retrieving: false, + template: false, + }, }, }; diff --git a/lib/metadataTypes/definitions/FtpLocation.definition.js b/lib/metadataTypes/definitions/FtpLocation.definition.js deleted file mode 100644 index 7c1d3962b..000000000 --- a/lib/metadataTypes/definitions/FtpLocation.definition.js +++ /dev/null @@ -1,46 +0,0 @@ -module.exports = { - bodyIteratorField: 'items', - dependencies: [], - hasExtended: false, - idField: 'id', - keyField: 'name', - nameField: 'name', - restPagination: false, - type: 'ftpLocation', - typeDescription: - 'A File Location which can be used for export or import of files to/from Marketing Cloud.', - typeRetrieveByDefault: true, - typeName: 'FTP Location', - fields: { - id: { - isCreateable: false, - isUpdateable: false, - retrieving: true, - template: false, - }, - locationTypeId: { - isCreateable: false, - isUpdateable: false, - retrieving: true, - template: false, - }, - locationUrl: { - isCreateable: false, - isUpdateable: false, - retrieving: true, - template: false, - }, - name: { - isCreateable: false, - isUpdateable: false, - retrieving: true, - template: false, - }, - relPath: { - isCreateable: true, - isUpdateable: true, - retrieving: true, - template: true, - }, - }, -}; diff --git a/lib/metadataTypes/definitions/ImportFile.definition.js b/lib/metadataTypes/definitions/ImportFile.definition.js index 6101e05e1..79397306e 100644 --- a/lib/metadataTypes/definitions/ImportFile.definition.js +++ b/lib/metadataTypes/definitions/ImportFile.definition.js @@ -1,25 +1,42 @@ -module.exports = { +export default { bodyIteratorField: 'items', - dependencies: ['folder', 'ftpLocation', 'dataExtension', 'list'], // folder has to be kept in here to resolve lists correctly + dependencies: ['fileLocation', 'dataExtension', 'list', 'mobileKeyword'], + dependencyGraph: { + // fileLocation cannot be deployed + // fileLocation: ['source.r__fileLocation_name'], + dataExtension: ['destination.r__dataExtension_key', 'source.r__dataExtension_key'], + list: ['destination.r__list_PathName'], + mobileKeyword: ['destination.r__mobileKeyword_key'], + }, destinationObjectTypeMapping: { unknown: 783, DataExtension: 310, List: 13, SMS: 584, Push: 613, + WhatsApp: 2600, }, - hasExtended: false, + hasExtended: true, idField: 'importDefinitionId', + keyIsFixed: false, keyField: 'customerKey', nameField: 'name', - restPagination: false, + createdDateField: 'createdDate', + createdNameField: null, + lastmodDateField: 'modifiedDate', + lastmodNameField: null, + restPagination: true, + restPageSize: 100, + restConcurrentLimit: 2, subscriberImportTypeMapping: { DataExtension: 255, Email: 0, }, + maxKeyLength: 36, // confirmed max length type: 'importFile', typeDescription: 'Reads files in FTP directory for further processing.', typeRetrieveByDefault: true, + typeCdpByDefault: true, typeName: 'Automation: Import File Activity', updateTypeMapping: { Add: 1, @@ -27,12 +44,24 @@ module.exports = { Overwrite: 4, Update: 2, }, + blankFileProcessingTypeMapping: { + Fail: 0, + Process: 1, + Skip: 2, + }, fields: { allowErrors: { isCreateable: true, isUpdateable: true, retrieving: true, - template: false, + template: true, + }, + blankFileProcessingType: { + // only visible if retrieved with ID + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, }, createdDate: { isCreateable: false, @@ -65,6 +94,13 @@ module.exports = { template: true, }, destinationId: { + isCreateable: true, + isUpdateable: true, + retrieving: false, + template: false, + }, + destinationName: { + // only visible if retrieved with ID isCreateable: false, isUpdateable: false, retrieving: false, @@ -83,6 +119,7 @@ module.exports = { template: true, }, encodingName: { + // only visible if retrieved with ID isCreateable: true, isUpdateable: true, retrieving: true, @@ -98,23 +135,38 @@ module.exports = { skipValidation: true, }, fileNamingPattern: { + // for FTP-import: pattern to look for; for DE-import: "_CustomObject" isCreateable: true, isUpdateable: true, retrieving: true, template: true, }, - fileTransferLocationId: { + fileSpec: { + // same as fileNamingPattern isCreateable: true, isUpdateable: true, retrieving: true, template: true, }, - fileTransferLocationTypeId: { + fileTransferLocationId: { isCreateable: true, isUpdateable: true, retrieving: true, template: true, }, + fileTransferLocationName: { + // only visible if retrieved with ID + isCreateable: false, + isUpdateable: false, + retrieving: false, + template: false, + }, + fileTransferLocationTypeId: { + isCreateable: true, + isUpdateable: true, + retrieving: false, + template: false, + }, fileType: { isCreateable: true, isUpdateable: true, @@ -136,8 +188,8 @@ module.exports = { importDefinitionId: { isCreateable: false, isUpdateable: true, - retrieving: true, - template: true, + retrieving: false, + template: false, }, isOrderedImport: { isCreateable: true, @@ -216,10 +268,79 @@ module.exports = { retrieving: true, template: true, }, - c__dataAction: { skipValidation: true }, - c__destinationType: { skipValidation: true }, - c__subscriberImportType: { skipValidation: true }, - r__dataExtension_CustomerKey: { skipValidation: true }, - r__ftpLocation_name: { skipValidation: true }, + sourceCustomObjectId: { + // for FTP-import: empty string; for DE-import: dataExtension id + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + sourceDataExtensionName: { + // for FTP-import: empty string; for DE-import: dataExtension name + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + c__dataAction: { + isCreateable: false, + isUpdateable: false, + retrieving: true, + template: true, + }, + 'destination.r__mobileKeyword_key': { + isCreateable: false, + isUpdateable: false, + retrieving: true, + template: true, + }, + 'source.r__dataExtension_key': { + isCreateable: false, + isUpdateable: false, + retrieving: true, + template: true, + }, + 'destination.r__dataExtension_key': { + isCreateable: false, + isUpdateable: false, + retrieving: true, + template: true, + }, + 'source.c__type': { + isCreateable: false, + isUpdateable: false, + retrieving: true, + template: true, + }, + 'destination.c__type': { + isCreateable: false, + isUpdateable: false, + retrieving: true, + template: true, + }, + 'destination.r__list_PathName': { + isCreateable: false, + isUpdateable: false, + retrieving: true, + template: true, + }, + 'source.r__fileLocation_name': { + isCreateable: false, + isUpdateable: false, + retrieving: true, + template: true, + }, + c__subscriberImportType: { + isCreateable: false, + isUpdateable: false, + retrieving: true, + template: true, + }, + c__blankFileProcessing: { + isCreateable: false, + isUpdateable: false, + retrieving: true, + template: true, + }, }, }; diff --git a/lib/metadataTypes/definitions/Interaction.definition.js b/lib/metadataTypes/definitions/Interaction.definition.js deleted file mode 100644 index 8ffed3100..000000000 --- a/lib/metadataTypes/definitions/Interaction.definition.js +++ /dev/null @@ -1,398 +0,0 @@ -module.exports = { - bodyIteratorField: 'items', - dependencies: [], - hasExtended: false, - idField: 'id', - keyField: 'key', - nameField: 'name', - restPagination: false, - type: 'interaction', - typeDescription: 'Journey from Builder (internally called "Interaction").', - typeRetrieveByDefault: false, - typeName: 'Journey', - fields: { - activities: { - skipValidation: true, - }, - categoryId: { - isCreateable: true, - isUpdateable: true, - retrieving: true, - template: true, - }, - channel: { - isCreateable: true, - isUpdateable: true, - retrieving: true, - template: true, - }, - createdDate: { - isCreateable: false, - isUpdateable: false, - retrieving: true, - template: false, - }, - 'defaults.email': { - skipValidation: true, - }, - 'defaults.mobileNumber': { - skipValidation: true, - }, - 'defaults.properties.analyticsTracking.enabled': { - isCreateable: null, - isUpdateable: null, - retrieving: null, - template: null, - }, - 'defaults.properties.analyticsTracking.analyticsType': { - isCreateable: null, - isUpdateable: null, - retrieving: null, - template: null, - }, - 'defaults.properties.analyticsTracking.urlDomainsToTrack': { - isCreateable: null, - isUpdateable: null, - retrieving: null, - template: null, - }, - definitionId: { - isCreateable: true, - isUpdateable: true, - retrieving: true, - template: true, - }, - definitionType: { - isCreateable: true, - isUpdateable: true, - retrieving: true, - template: true, - }, - description: { - isCreateable: true, - isUpdateable: true, - retrieving: true, - template: true, - }, - entryMode: { - isCreateable: true, - isUpdateable: true, - retrieving: true, - template: true, - }, - executionMode: { - isCreateable: true, - isUpdateable: true, - retrieving: true, - template: true, - }, - exits: { - skipValidation: true, - }, - goals: { - skipValidation: true, - }, - healthStats: { - isCreateable: false, - isUpdateable: false, - retrieving: false, - template: false, - }, - id: { - isCreateable: false, - isUpdateable: true, - retrieving: false, - template: false, - }, - key: { - isCreateable: true, - isUpdateable: true, - retrieving: true, - template: true, - }, - lastPublishedDate: { - isCreateable: false, - isUpdateable: false, - retrieving: false, - template: false, - }, - 'metaData.templateId': { - isCreateable: false, - isUpdateable: false, - retrieving: true, - template: false, - }, - modifiedDate: { - isCreateable: false, - isUpdateable: false, - retrieving: true, - template: false, - }, - name: { - isCreateable: true, - isUpdateable: true, - retrieving: true, - template: true, - }, - scheduledStatus: { - isCreateable: null, - isUpdateable: null, - retrieving: null, - template: null, - }, - stats: { - isCreateable: false, - isUpdateable: false, - retrieving: false, - template: false, - }, - status: { - isCreateable: true, - isUpdateable: true, - retrieving: true, - template: true, - }, - triggers: { - isCreateable: true, - isUpdateable: true, - retrieving: true, - template: true, - }, - 'triggers[].id': { - isCreateable: false, - isUpdateable: false, - retrieving: false, - template: false, - }, - 'triggers[].key': { - isCreateable: false, - isUpdateable: false, - retrieving: false, - template: false, - }, - 'triggers[].name': { - isCreateable: false, - isUpdateable: false, - retrieving: false, - template: false, - }, - 'triggers[].description': { - isCreateable: true, - isUpdateable: true, - retrieving: true, - template: true, - }, - 'triggers[].type': { - isCreateable: true, - isUpdateable: true, - retrieving: true, - template: true, - }, - 'triggers[].outcomes': { - isCreateable: true, - isUpdateable: true, - retrieving: true, - template: true, - }, - 'triggers[].arguments': { - isCreateable: true, - isUpdateable: true, - retrieving: true, - template: true, - }, - 'triggers[].arguments.startActivityKey': { - isCreateable: true, - isUpdateable: true, - retrieving: true, - template: true, - }, - - 'triggers[].arguments.dequeueReason': { - isCreateable: true, - isUpdateable: true, - retrieving: true, - template: true, - }, - 'triggers[].arguments.lastExecutedActivityKey': { - isCreateable: true, - isUpdateable: true, - retrieving: true, - template: true, - }, - 'triggers[].arguments.filterResult': { - isCreateable: true, - isUpdateable: true, - retrieving: true, - template: true, - }, - 'triggers[].configurationArguments': { - isCreateable: true, - isUpdateable: true, - retrieving: true, - template: true, - }, - 'triggers[].configurationArguments.eventDataConfig': { - isCreateable: true, - isUpdateable: true, - retrieving: true, - template: true, - }, - 'triggers[].configurationArguments.primaryObjectFilterCriteria': { - isCreateable: true, - isUpdateable: true, - retrieving: true, - template: true, - }, - 'triggers[].configurationArguments.relatedObjectFilterCriteria': { - isCreateable: true, - isUpdateable: true, - retrieving: true, - template: true, - }, - 'triggers[].configurationArguments.salesforceTriggerCriteria': { - isCreateable: true, - isUpdateable: true, - retrieving: true, - template: true, - }, - 'triggers[].configurationArguments.objectAPIName': { - isCreateable: true, - isUpdateable: true, - retrieving: true, - template: true, - }, - 'triggers[].configurationArguments.version': { - isCreateable: true, - isUpdateable: true, - retrieving: true, - template: true, - }, - 'triggers[].configurationArguments.contactKey': { - isCreateable: true, - isUpdateable: true, - retrieving: true, - template: true, - }, - 'triggers[].configurationArguments.contactPersonType': { - isCreateable: true, - isUpdateable: true, - retrieving: true, - template: true, - }, - 'triggers[].configurationArguments.primaryObjectFilterSummary': { - isCreateable: true, - isUpdateable: true, - retrieving: true, - template: true, - }, - 'triggers[].configurationArguments.relatedObjectFilterSummary': { - isCreateable: true, - isUpdateable: true, - retrieving: true, - template: true, - }, - - 'triggers[].configurationArguments.eventDataSummary': { - isCreateable: true, - isUpdateable: true, - retrieving: true, - template: true, - }, - 'triggers[].configurationArguments.evaluationCriteriaSummary': { - isCreateable: true, - isUpdateable: true, - retrieving: true, - template: true, - }, - 'triggers[].configurationArguments.applicationExtensionKey': { - isCreateable: true, - isUpdateable: true, - retrieving: true, - template: true, - }, - 'triggers[].configurationArguments.passThroughArgument': { - isCreateable: true, - isUpdateable: true, - retrieving: true, - template: true, - }, - 'triggers[].configurationArguments.filterDefinitionId': { - isCreateable: false, - isUpdateable: false, - retrieving: false, - template: false, - }, - 'triggers[].configurationArguments.criteria': { - isCreateable: true, - isUpdateable: true, - retrieving: true, - template: true, - }, - 'triggers[].configurationArguments.schemaVersionId': { - isCreateable: true, - isUpdateable: true, - retrieving: true, - template: true, - }, - 'triggers[].metaData': { - isCreateable: true, - isUpdateable: true, - retrieving: true, - template: true, - }, - 'triggers[].metaData.sourceInteractionId': { - isCreateable: false, - isUpdateable: false, - retrieving: false, - template: false, - }, - 'triggers[].metaData.eventDefinitionId': { - isCreateable: false, - isUpdateable: false, - retrieving: false, - template: false, - }, - 'triggers[].metaData.eventDefinitionKey': { - isCreateable: true, - isUpdateable: true, - retrieving: true, - template: true, - }, - 'triggers[].metaData.chainType': { - isCreateable: true, - isUpdateable: true, - retrieving: true, - template: true, - }, - 'triggers[].metaData.configurationRequired': { - isCreateable: true, - isUpdateable: true, - retrieving: true, - template: true, - }, - 'triggers[].metaData.iconUrl': { - isCreateable: true, - isUpdateable: true, - retrieving: true, - template: true, - }, - 'triggers[].metaData.title': { - isCreateable: true, - isUpdateable: true, - retrieving: true, - template: true, - }, - version: { - isCreateable: false, - isUpdateable: false, - retrieving: true, - template: false, - }, - workflowApiVersion: { - isCreateable: false, - isUpdateable: false, - retrieving: true, - template: false, - }, - }, -}; diff --git a/lib/metadataTypes/definitions/Journey.definition.js b/lib/metadataTypes/definitions/Journey.definition.js new file mode 100644 index 000000000..3a12c0301 --- /dev/null +++ b/lib/metadataTypes/definitions/Journey.definition.js @@ -0,0 +1,1213 @@ +// overview: https://developer.salesforce.com/docs/marketing/marketing-cloud/guide/jb-api-specification.html +// obj definition: https://developer.salesforce.com/docs/marketing/marketing-cloud/guide/getting-started-spec.html +// insert: https://developer.salesforce.com/docs/marketing/marketing-cloud/guide/postCreateInteraction.html +// update: https://developer.salesforce.com/docs/marketing/marketing-cloud/guide/putUpdateInteraction.html +export default { + folderType: 'journey', + bodyIteratorField: 'items', + dependencies: [ + 'folder-journey', + 'triggeredSend', // for EMAILV2-activity + 'dataExtension', // for transactionalEmails: EMAILV2-activity and for UPDATECONTACTDATA activity + 'deliveryProfile', + 'event', // for Multistep and Quicksend journeys + 'mobileMessage', // for SMSSYNC-activity + 'mobileCode', // for SMSSYNC-activity + 'mobileKeyword', // for SMSSYNC-activity + 'asset-asset', // for SMSSYNC-activity (sub-subtype jsonmessage) + 'list', // for EMAILV2-activity + 'email', // for EMAILV2-activity + 'asset-message', // for EMAILV2-activity + 'sendClassification', // for EMAILV2-activity + 'senderProfile', // for EMAILV2-activity + ], // ! interaction and transactionalEmail both link to each other. caching transactionalEmail here "manually" instead of via dependencies array, assuming that it is quicker than the other way round + dependencyGraph: { + // classic email cannot be deployed anymore + event: ['triggers.metaData.r__event_key'], + dataExtension: [ + 'activities.metaData.highThroughput.r__dataExtension_key', + 'activities.configurationArguments.triggeredSend.r__dataExtension_key.domainExclusions', + 'activities.arguments.activityData.updateContactFields.r__dataExtension_key', + ], + deliveryProfile: ['activities.configurationArguments.triggeredSend.r__deliveryProfile_key'], + list: [ + 'activities.configurationArguments.triggeredSend.r__list_PathName.publicationList', + 'activities.configurationArguments.triggeredSend.r__list_PathName.suppressionLists', + ], + senderProfile: ['activities.configurationArguments.triggeredSend.r__senderProfile_key'], + sendClassification: [ + 'activities.configurationArguments.triggeredSend.r__sendClassification_key', + ], + asset: [ + 'activities.configurationArguments.triggeredSend.r__asset_key', + 'activities.configurationArguments.r__asset_key', + ], + mobileMessage: ['activities.configurationArguments.r__mobileMessage_key'], + mobileKeyword: [ + 'activities.configurationArguments.r__mobileKeyword_key.current', + 'activities.configurationArguments.r__mobileKeyword_key.next', + ], + mobileCode: ['activities.configurationArguments.r__mobileCode_key'], + }, + folderIdField: 'categoryId', + hasExtended: false, + idField: 'id', + keyIsFixed: true, + keyField: 'key', + nameField: 'name', + createdDateField: 'createdDate', + createdNameField: null, + lastmodDateField: 'modifiedDate', + lastmodNameField: null, + restPagination: true, + restPageSize: 500, + maxKeyLength: 200, // confirmed max length + type: 'journey', + typeDescription: 'Journey (internally called "Interaction").', + typeRetrieveByDefault: true, + typeCdpByDefault: true, + typeName: 'Journey', + priorityMapping: { + High: 3, + Medium: 4, // not inherited on Asset Types + Low: 5, + }, + fields: { + activities: { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + 'activities[].id': { + isCreateable: false, + isUpdateable: false, + retrieving: false, + template: false, + }, + 'activities[].key': { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + 'activities[].name': { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + 'activities[].description': { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + 'activities[].type': { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + 'activities[].outcomes': { + skipValidation: true, + }, + 'activities[].arguments': { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + 'activities[].arguments.waitEndDateAttributeDataBound': { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + 'activities[].arguments.waitDefinitionId': { + isCreateable: false, + isUpdateable: false, + retrieving: false, + template: false, + }, + 'activities[].arguments.waitForEventId': { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + 'activities[].arguments.executionMode': { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + 'activities[].arguments.startActivityKey': { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + 'activities[].arguments.waitQueueId': { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + 'activities[].arguments.activityId': { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + 'activities[].arguments.definitionId': { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + 'activities[].arguments.emailSubjectDataBound': { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + 'activities[].arguments.contactId': { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + 'activities[].arguments.contactKey': { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + 'activities[].arguments.emailAddress': { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + 'activities[].arguments.sourceCustomObjectId': { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + 'activities[].arguments.sourceCustomObjectKey': { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + 'activities[].arguments.fieldType': { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + 'activities[].arguments.eventData': { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + 'activities[].arguments.obfuscationProperties': { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + 'activities[].arguments.customObjectKey': { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + 'activities[].arguments.definitionInstanceId': { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + 'activities[].arguments.filterResult': { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + 'activities[].arguments.version': { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + 'activities[].arguments.requestObjectId': { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + 'activities[].arguments.activityData': { + skipValidation: true, + }, + 'activities[].arguments.objectMap': { + skipValidation: true, + }, + 'activities[].configurationArguments': { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + 'activities[].configurationArguments.isReconcilable': { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + 'activities[].configurationArguments.isActivityBatchValidated': { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + 'activities[].configurationArguments.triggeredSendKey': { + // if used during create then we are stuck with old data + isCreateable: false, + isUpdateable: true, + retrieving: true, + template: false, + }, + 'activities[].configurationArguments.triggeredSendId': { + // if used during create then we are stuck with old data + isCreateable: false, + isUpdateable: true, + retrieving: true, + template: false, + }, + 'activities[].configurationArguments.triggeredSend': { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + 'activities[].configurationArguments.triggeredSend.id': { + // if used during create then we are stuck with old data + isCreateable: false, + isUpdateable: true, + retrieving: true, + template: false, + }, + 'activities[].configurationArguments.triggeredSend.key': { + // if used during create then we are stuck with old data + isCreateable: false, + isUpdateable: true, + retrieving: true, + template: false, + }, + 'activities[].configurationArguments.triggeredSend.campaigns': { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + 'activities[].configurationArguments.triggeredSend.suppressionLists': { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + 'activities[].configurationArguments.triggeredSend.autoAddSubscribers': { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + 'activities[].configurationArguments.triggeredSend.autoUpdateSubscribers': { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + 'activities[].configurationArguments.triggeredSend.bccEmail': { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + 'activities[].configurationArguments.triggeredSend.categoryId': { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + 'activities[].configurationArguments.triggeredSend.ccEmail': { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + 'activities[].configurationArguments.triggeredSend.created': { + skipValidation: true, + }, + 'activities[].configurationArguments.triggeredSend.description': { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + 'activities[].configurationArguments.triggeredSend.domainExclusions': { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + 'activities[].configurationArguments.triggeredSend.dynamicEmailSubject': { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + 'activities[].configurationArguments.triggeredSend.emailSubject': { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + 'activities[].configurationArguments.triggeredSend.exclusionFilter': { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + 'activities[].configurationArguments.triggeredSend.isSalesforceTracking': { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + 'activities[].configurationArguments.triggeredSend.isMultipart': { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + 'activities[].configurationArguments.triggeredSend.isSendLogging': { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + 'activities[].configurationArguments.triggeredSend.isStoppedOnJobError': { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + 'activities[].configurationArguments.triggeredSend.keyword': { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + 'activities[].configurationArguments.triggeredSend.modified': { + skipValidation: true, + }, + 'activities[].configurationArguments.triggeredSend.name': { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: false, + }, + 'activities[].configurationArguments.triggeredSend.preHeader': { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + 'activities[].configurationArguments.triggeredSend.replyToAddress': { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + 'activities[].configurationArguments.triggeredSend.replyToDisplayName': { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + 'activities[].configurationArguments.triggeredSend.suppressTracking': { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + 'activities[].configurationArguments.triggeredSend.triggeredSendStatus': { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + 'activities[].configurationArguments.triggeredSend.version': { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + 'activities[].configurationArguments.triggeredSend.throttleOpens': { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + 'activities[].configurationArguments.triggeredSend.throttleCloses': { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + 'activities[].configurationArguments.triggeredSend.throttleLimit': { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + 'activities[].configurationArguments.triggeredSend.isTrackingClicks': { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + 'activities[].configurationArguments.triggeredSend.emailId': { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + 'activities[].configurationArguments.triggeredSend.r__triggeredSend_key': { + isCreateable: false, + isUpdateable: false, + retrieving: true, + /* dont include in templates, we rather want this to be re-created from the journey */ + template: false, + }, + 'activities[].configurationArguments.triggeredSend.senderProfileId': { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + 'activities[].configurationArguments.triggeredSend.deliveryProfileId': { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + 'activities[].configurationArguments.triggeredSend.r__senderProfile_key': { + isCreateable: false, + isUpdateable: false, + retrieving: true, + template: true, + }, + 'activities[].configurationArguments.triggeredSend.sendClassificationId': { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + 'activities[].configurationArguments.triggeredSend.r__deliveryProfile_key': { + isCreateable: false, + isUpdateable: false, + retrieving: true, + template: true, + }, + 'activities[].configurationArguments.triggeredSend.r__sendClassification_key': { + isCreateable: false, + isUpdateable: false, + retrieving: true, + template: true, + }, + 'activities[].configurationArguments.triggeredSend.r__list_PathName': { + isCreateable: false, + isUpdateable: false, + retrieving: true, + template: true, + }, + 'activities[].configurationArguments.triggeredSend.publicationListId': { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + 'activities[].configurationArguments.triggeredSend.r__list_PathName.publicationList': { + isCreateable: false, + isUpdateable: false, + retrieving: true, + template: true, + }, + 'activities[].configurationArguments.triggeredSend.r__list_PathName.suppressionLists': { + isCreateable: false, + isUpdateable: false, + retrieving: true, + template: true, + }, + 'activities[].configurationArguments.triggeredSend.r__dataExtension_key': { + isCreateable: false, + isUpdateable: false, + retrieving: true, + template: true, + }, + 'activities[].configurationArguments.triggeredSend.r__dataExtension_key.domainExclusions': { + isCreateable: false, + isUpdateable: false, + retrieving: true, + template: true, + }, + 'activities[].configurationArguments.triggeredSend.priority': { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + 'activities[].configurationArguments.triggeredSend.c__priority': { + isCreateable: false, + isUpdateable: false, + retrieving: true, + template: true, + }, + 'activities[].configurationArguments.triggeredSend.r__asset_name_readOnly': { + isCreateable: false, + isUpdateable: false, + retrieving: true, + template: false, + }, + 'activities[].configurationArguments.triggeredSend.r__asset_key': { + isCreateable: false, + isUpdateable: false, + retrieving: true, + template: true, + }, + 'activities[].configurationArguments.triggeredSend.updateSubscriber': { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + 'activities[].configurationArguments.applicationExtensionKey': { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + 'activities[].configurationArguments.r__transactionalEmail_key': { + isCreateable: false, + isUpdateable: false, + retrieving: true, + template: true, + }, + 'activities[].configurationArguments.applicationExtensionId': { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + 'activities[].configurationArguments.isModified': { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + 'activities[].configurationArguments.isSimulation': { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + 'activities[].configurationArguments.googleAnalyticsCampaignName': { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + 'activities[].configurationArguments.useLLTS': { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + 'activities[].configurationArguments.fuelAgentRequested': { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + 'activities[].configurationArguments.r__triggeredSend_key': { + isCreateable: false, + isUpdateable: false, + retrieving: true, + template: false, + }, + 'activities[].configurationArguments.waitDuration': { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + 'activities[].configurationArguments.waitUnit': { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + 'activities[].configurationArguments.specifiedTime': { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + 'activities[].configurationArguments.timeZone': { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + 'activities[].configurationArguments.description': { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + 'activities[].configurationArguments.waitEndDateAttributeExpression': { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + 'activities[].configurationArguments.specificDate': { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + 'activities[].configurationArguments.waitForEventKey': { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + 'activities[].configurationArguments.schemaVersionId': { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + 'activities[].configurationArguments.criteria': { + skipValidation: true, + }, + 'activities[].configurationArguments.eventDataConfig': { + skipValidation: true, + }, + 'activities[].metaData': { + skipValidation: true, + }, + 'activities[].schema': { + skipValidation: true, + }, + 'activities[].arguments.activityData.updateContactFields[].r__dataExtension_key': { + isCreateable: false, + isUpdateable: false, + retrieving: true, + template: true, + }, + 'activities[].arguments.activityData.updateContactFields[].r__dataExtensionField_name': { + isCreateable: false, + isUpdateable: false, + retrieving: true, + template: true, + }, + 'activities[].arguments.activityData.updateContactFields[].field': { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + categoryId: { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + channel: { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + createdDate: { + isCreateable: false, + isUpdateable: false, + retrieving: true, + template: false, + }, + 'defaults.email': { + skipValidation: true, + }, + 'defaults.mobileNumber': { + skipValidation: true, + }, + 'defaults.properties.analyticsTracking.enabled': { + isCreateable: null, + isUpdateable: null, + retrieving: null, + template: null, + }, + 'defaults.properties': { + skipValidation: true, + }, + 'defaults.properties.analyticsTracking.analyticsType': { + isCreateable: null, + isUpdateable: null, + retrieving: null, + template: null, + }, + 'defaults.properties.analyticsTracking.urlDomainsToTrack': { + isCreateable: null, + isUpdateable: null, + retrieving: null, + template: null, + }, + definitionId: { + isCreateable: false, + isUpdateable: false, + retrieving: false, + template: false, + }, + definitionType: { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + description: { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + entryMode: { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + executionMode: { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + exits: { + skipValidation: true, + }, + goals: { + skipValidation: true, + }, + healthStats: { + isCreateable: false, + isUpdateable: false, + retrieving: false, + template: false, + }, + id: { + isCreateable: false, + isUpdateable: false, + retrieving: true, + template: true, + }, + key: { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + lastPublishedDate: { + isCreateable: false, + isUpdateable: false, + retrieving: true, + template: false, + }, + 'metaData.templateId': { + isCreateable: false, + isUpdateable: false, + retrieving: true, + template: true, + }, + modifiedDate: { + isCreateable: false, + isUpdateable: true, + retrieving: true, + template: true, + }, + name: { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + scheduledStatus: { + isCreateable: null, + isUpdateable: null, + retrieving: null, + template: null, + }, + stats: { + isCreateable: false, + isUpdateable: false, + retrieving: false, + template: false, + }, + status: { + isCreateable: false, + isUpdateable: true, + retrieving: true, + template: false, + }, + triggers: { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + 'triggers[].id': { + isCreateable: false, + isUpdateable: false, + retrieving: false, + template: false, + }, + 'triggers[].key': { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + 'triggers[].name': { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + 'triggers[].description': { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + 'triggers[].type': { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + 'triggers[].outcomes': { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + 'triggers[].arguments': { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + 'triggers[].arguments.startActivityKey': { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + 'triggers[].arguments.dequeueReason': { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + 'triggers[].arguments.lastExecutedActivityKey': { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + 'triggers[].arguments.filterResult': { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + 'triggers[].arguments.serializedObjectType': { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + 'triggers[].arguments.eventDefinitionId': { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + 'triggers[].arguments.eventDefinitionKey': { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + 'triggers[].arguments.dataExtensionId': { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + 'triggers[].arguments.automationId': { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + 'triggers[].arguments.r__event_key': { + isCreateable: false, + isUpdateable: false, + retrieving: true, + template: true, + }, + 'triggers[].arguments.r__dataExtension_key': { + isCreateable: false, + isUpdateable: false, + retrieving: true, + template: true, + }, + 'triggers[].configurationArguments': { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + 'triggers[].configurationArguments.eventDataConfig': { + skipValidation: true, + }, + 'triggers[].configurationArguments.primaryObjectFilterCriteria': { + skipValidation: true, + }, + 'triggers[].configurationArguments.relatedObjectFilterCriteria': { + skipValidation: true, + }, + 'triggers[].configurationArguments.salesforceTriggerCriteria': { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + 'triggers[].configurationArguments.objectApiName': { + // journey capitalization; rewritten to event way of writing it by mcdev + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + 'triggers[].configurationArguments.objectAPIName': { + // capitalization like on event, customly created by mcdev in journey + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + 'triggers[].configurationArguments.version': { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + 'triggers[].configurationArguments.contactKey': { + skipValidation: true, + }, + 'triggers[].configurationArguments.contactPersonType': { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + 'triggers[].configurationArguments.primaryObjectFilterSummary': { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + 'triggers[].configurationArguments.relatedObjectFilterSummary': { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + + 'triggers[].configurationArguments.eventDataSummary': { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + 'triggers[].configurationArguments.evaluationCriteriaSummary': { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + 'triggers[].configurationArguments.applicationExtensionKey': { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + 'triggers[].configurationArguments.passThroughArgument': { + skipValidation: true, + }, + 'triggers[].configurationArguments.filterDefinitionId': { + isCreateable: false, + isUpdateable: false, + retrieving: false, + template: false, + }, + 'triggers[].configurationArguments.criteria': { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + 'triggers[].configurationArguments.schemaVersionId': { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + 'triggers[].configurationArguments.whoToInject': { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + 'triggers[].configurationArguments.additionalObjectFilterCriteria': { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + 'triggers[].metaData': { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + 'triggers[].metaData.sourceInteractionId': { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + 'triggers[].metaData.entrySourceGroupConfigUrl': { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + 'triggers[].metaData.r__event_key': { + isCreateable: false, + isUpdateable: false, + retrieving: true, + template: true, + }, + 'triggers[].metaData.category': { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + 'triggers[].metaData.eventDefinitionId': { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + 'triggers[].metaData.eventDefinitionKey': { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + 'triggers[].metaData.chainType': { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + 'triggers[].metaData.configurationRequired': { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + 'triggers[].metaData.iconUrl': { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + 'triggers[].metaData.title': { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + 'triggers[].metaData.scheduleState': { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + version: { + isCreateable: false, + isUpdateable: true, + retrieving: true, + template: false, + }, + workflowApiVersion: { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + campaigns: { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + metaData: { + skipValidation: true, + }, + notifiers: { + skipValidation: true, + }, + tags: { + skipValidation: true, + }, + r__folder_Path: { + isCreateable: false, + isUpdateable: false, + retrieving: true, + template: true, + }, + }, +}; diff --git a/lib/metadataTypes/definitions/List.definition.js b/lib/metadataTypes/definitions/List.definition.js index d2126fb96..af5d87ec6 100644 --- a/lib/metadataTypes/definitions/List.definition.js +++ b/lib/metadataTypes/definitions/List.definition.js @@ -1,15 +1,18 @@ -module.exports = { +export default { bodyIteratorField: 'Results', - dependencies: ['folder'], + dependencies: ['folder-mysubs', 'folder-list', 'folder-publication'], + dependencyGraph: null, folderType: 'list', hasExtended: false, idField: 'ObjectID', + keyIsFixed: true, keyField: 'CustomerKey', nameField: 'ListName', restPagination: null, type: 'list', typeDescription: 'Old way of storing data. Still used for central Email Subscriber DB.', typeRetrieveByDefault: true, + typeCdpByDefault: false, typeName: 'List', fields: { 'AutomatedEmail.ID': { diff --git a/lib/metadataTypes/definitions/MobileCode.definition.js b/lib/metadataTypes/definitions/MobileCode.definition.js new file mode 100644 index 000000000..c62cf840f --- /dev/null +++ b/lib/metadataTypes/definitions/MobileCode.definition.js @@ -0,0 +1,167 @@ +export default { + bodyIteratorField: 'entry', + dependencies: [], + dependencyGraph: null, + hasExtended: false, + idField: 'id', + keyIsFixed: true, + keyField: 'code', + nameField: 'code', + createdDateField: 'createdDate', + createdNameField: null, + lastmodDateField: 'lastUpdated', + lastmodNameField: null, + restPagination: true, + restPageSize: 50, + type: 'mobileCode', + typeDescription: 'Used to send SMS Messages', + typeRetrieveByDefault: true, + typeCdpByDefault: true, + typeName: 'Mobile Code', + fields: { + id: { + isCreateable: false, + isUpdateable: false, + retrieving: false, + template: false, + }, + createdDate: { + isCreateable: false, + isUpdateable: false, + retrieving: false, + template: false, + }, + lastUpdated: { + isCreateable: false, + isUpdateable: false, + retrieving: false, + template: false, + }, + startDate: { + isCreateable: false, + isUpdateable: false, + retrieving: false, + template: false, + }, + endDate: { + isCreateable: false, + isUpdateable: false, + retrieving: false, + template: false, + }, + keywordLimit: { + isCreateable: false, + isUpdateable: false, + retrieving: false, + template: false, + }, + keywordsUsed: { + isCreateable: false, + isUpdateable: false, + retrieving: false, + template: false, + }, + code: { + isCreateable: false, + isUpdateable: false, + retrieving: true, + template: true, + }, + codeType: { + isCreateable: false, + isUpdateable: false, + retrieving: true, + template: true, + }, + isShortCode: { + isCreateable: false, + isUpdateable: false, + retrieving: false, + template: false, + }, + keywordsUsedOther: { + isCreateable: false, + isUpdateable: false, + retrieving: false, + template: false, + }, + isGsmCharacterSetOnly: { + isCreateable: false, + isUpdateable: false, + retrieving: true, + template: false, + }, + isMms: { + isCreateable: false, + isUpdateable: false, + retrieving: true, + template: false, + }, + isStackIndependant: { + isCreateable: false, + isUpdateable: false, + retrieving: false, + template: false, + }, + supportsConcatenation: { + isCreateable: false, + isUpdateable: false, + retrieving: true, + template: false, + }, + isClientOwned: { + isCreateable: false, + isUpdateable: false, + retrieving: false, + template: false, + }, + isOwner: { + isCreateable: false, + isUpdateable: false, + retrieving: false, + template: false, + }, + dipSwitches: { + isCreateable: false, + isUpdateable: false, + retrieving: false, + template: false, + }, + sendableCountries: { + isCreateable: false, + isUpdateable: false, + retrieving: true, + template: false, + }, + 'sendableCountries[].countryCode': { + isCreateable: false, + isUpdateable: false, + retrieving: true, + template: false, + }, + 'sendableCountries[].vendor': { + isCreateable: false, + isUpdateable: false, + retrieving: true, + template: false, + }, + 'sendableCountries[].fromNameSupported': { + isCreateable: false, + isUpdateable: false, + retrieving: true, + template: false, + }, + countryCode: { + isCreateable: false, + isUpdateable: false, + retrieving: true, + template: false, + }, + moEngineVersion: { + isCreateable: false, + isUpdateable: false, + retrieving: false, + template: false, + }, + }, +}; diff --git a/lib/metadataTypes/definitions/MobileKeyword.definition.js b/lib/metadataTypes/definitions/MobileKeyword.definition.js new file mode 100644 index 000000000..4bd69839e --- /dev/null +++ b/lib/metadataTypes/definitions/MobileKeyword.definition.js @@ -0,0 +1,284 @@ +export default { + bodyIteratorField: 'entry', + dependencies: ['mobileCode'], + dependencyGraph: { mobileCode: ['r__mobileCode_key'] }, + hasExtended: false, + idField: 'id', + keyIsFixed: false, // custom field but mapped to normal fields + keyField: 'c__codeKeyword', + nameField: 'c__codeKeyword', + createdDateField: 'createdDate', + createdNameField: 'createdBy.name', + lastmodDateField: 'lastUpdated', + lastmodNameField: null, + restPagination: true, + restPageSize: 50, + maxKeyLength: 50, // assumed max length + type: 'mobileKeyword', + typeDescription: 'Used for managing subscriptions for Mobile numbers in Mobile Connect', + typeRetrieveByDefault: true, + typeCdpByDefault: true, + typeName: 'Mobile Keyword', + fields: { + id: { + // irregular format: NXV4ZFMwTEFwRVczd3RaLUF5X3p5dzo4Njow + isCreateable: false, + isUpdateable: true, + retrieving: false, + template: false, + }, + c__codeKeyword: { + isCreateable: false, + isUpdateable: false, + retrieving: true, + template: true, + }, + r__mobileCode_key: { + isCreateable: false, + isUpdateable: false, + retrieving: true, + template: true, + }, + keyword: { + isCreateable: true, + isUpdateable: true, + retrieving: false, + template: false, + }, + createdDate: { + isCreateable: false, + isUpdateable: false, + retrieving: true, + template: false, + }, + lastUpdated: { + isCreateable: false, + isUpdateable: false, + retrieving: true, + template: false, + }, + startDate: { + isCreateable: false, + isUpdateable: false, + retrieving: true, + template: false, + }, + endDate: { + isCreateable: false, + isUpdateable: false, + retrieving: true, + template: false, + }, + createdBy: { + isCreateable: false, + isUpdateable: false, + retrieving: true, + template: false, + }, + 'createdBy.id': { + isCreateable: false, + isUpdateable: false, + retrieving: false, + template: false, + }, + 'createdBy.name': { + isCreateable: false, + isUpdateable: false, + retrieving: true, + template: false, + }, + 'createdBy.lastUpdated': { + isCreateable: false, + isUpdateable: false, + retrieving: false, + template: false, + }, + dipSwitches: { + isCreateable: false, + isUpdateable: false, + retrieving: false, + template: false, + }, + isInherited: { + isCreateable: false, + isUpdateable: true, + retrieving: true, + template: true, + }, + decodedId: { + // GUID format (4b5dece6-c042-45a4-b7c2-d67e032ff3cb). unsure what this is used for + isCreateable: false, + isUpdateable: false, + retrieving: false, + template: false, + }, + restriction: { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + keywordType: { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + companyName: { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + responseMessage: { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + status: { + isCreateable: false, + isUpdateable: false, + retrieving: true, + template: false, + }, + messages: { + isCreateable: false, + isUpdateable: false, + retrieving: true, + template: false, + }, + code: { + isCreateable: true, + isUpdateable: true, + retrieving: false, + template: false, + }, + 'code.code': { + isCreateable: false, + isUpdateable: false, + retrieving: false, + template: false, + }, + 'code.id': { + isCreateable: true, + isUpdateable: true, + retrieving: false, + template: false, + }, + 'code.createdDate': { + isCreateable: false, + isUpdateable: false, + retrieving: false, + template: false, + }, + 'code.lastUpdated': { + isCreateable: false, + isUpdateable: false, + retrieving: false, + template: false, + }, + 'code.startDate': { + isCreateable: false, + isUpdateable: false, + retrieving: false, + template: false, + }, + 'code.endDate': { + isCreateable: false, + isUpdateable: false, + retrieving: false, + template: false, + }, + 'code.keywordLimit': { + isCreateable: false, + isUpdateable: false, + retrieving: false, + template: false, + }, + 'code.keywordsUsed': { + isCreateable: false, + isUpdateable: false, + retrieving: false, + template: false, + }, + 'code.codeType': { + isCreateable: false, + isUpdateable: false, + retrieving: false, + template: false, + }, + 'code.isShortCode': { + isCreateable: false, + isUpdateable: false, + retrieving: false, + template: false, + }, + 'code.keywordsUsedOther': { + isCreateable: false, + isUpdateable: false, + retrieving: false, + template: false, + }, + 'code.isGsmCharacterSetOnly': { + isCreateable: false, + isUpdateable: false, + retrieving: false, + template: false, + }, + 'code.isMms': { + isCreateable: false, + isUpdateable: false, + retrieving: false, + template: false, + }, + 'code.isStackIndependant': { + isCreateable: false, + isUpdateable: false, + retrieving: false, + template: false, + }, + 'code.supportsConcatenation': { + isCreateable: false, + isUpdateable: false, + retrieving: false, + template: false, + }, + 'code.isClientOwned': { + isCreateable: false, + isUpdateable: false, + retrieving: false, + template: false, + }, + 'code.isOwner': { + isCreateable: false, + isUpdateable: false, + retrieving: false, + template: false, + }, + 'code.dipSwitches': { + isCreateable: false, + isUpdateable: false, + retrieving: false, + template: false, + }, + 'code.sendableCountries': { + isCreateable: false, + isUpdateable: false, + retrieving: false, + template: false, + }, + 'code.countryCode': { + isCreateable: false, + isUpdateable: false, + retrieving: false, + template: false, + }, + 'code.moEngineVersion': { + isCreateable: false, + isUpdateable: false, + retrieving: false, + template: false, + }, + }, +}; diff --git a/lib/metadataTypes/definitions/MobileMessage.definition.js b/lib/metadataTypes/definitions/MobileMessage.definition.js new file mode 100644 index 000000000..1243e80e5 --- /dev/null +++ b/lib/metadataTypes/definitions/MobileMessage.definition.js @@ -0,0 +1,801 @@ +export default { + bodyIteratorField: 'entry', + dependencies: ['mobileCode', 'mobileKeyword', 'campaign'], + dependencyGraph: { + mobileCode: ['r__mobileCode_key'], + mobileKeyword: [ + 'keyword.r__mobileKeyword_key', + 'subscriptionKeyword.r__mobileKeyword_key', + 'nextKeyword.r__mobileKeyword_key', + ], + // campaign: ['r__campaign_key'], // campaign cannot be deployed + }, + hasExtended: false, + idField: 'id', + keepId: true, + keyIsFixed: true, // key == id + keyField: 'id', + nameField: 'name', + createdDateField: null, + createdNameField: null, + lastmodDateField: 'lastUpdated', + lastmodNameField: null, + restPagination: true, + restPageSize: 50, + type: 'mobileMessage', + typeDescription: + 'Used by Journey Builder and to send SMS from MobileConnect triggered by API or manually on-the-fly', + typeRetrieveByDefault: true, + typeCdpByDefault: true, + typeName: 'MobileConnect SMS', + fields: { + allowSingleOptin: { + isCreatable: true, + isUpdatable: true, + retrieving: true, + template: true, + }, + audience: { + skipValidation: true, + }, + 'audience[]': { + skipValidation: true, + }, + campaigns: { + skipValidation: true, + }, + 'campaigns[]': { + skipValidation: true, + }, + r__mobileCode_key: { + isCreateable: false, + isUpdateable: false, + retrieving: true, + template: true, + }, + 'code.code': { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + 'code.codeType': { + isCreateable: true, + isUpdateable: true, + retrieving: false, + template: false, + }, + 'code.countryCode': { + isCreateable: true, + isUpdateable: true, + retrieving: false, + template: false, + }, + 'code.createdDate': { + isCreateable: true, + isUpdateable: true, + retrieving: false, + template: false, + }, + 'code.dipSwitches': { + isCreateable: true, + isUpdateable: true, + retrieving: false, + template: false, + }, + 'code.endDate': { + isCreateable: true, + isUpdateable: true, + retrieving: false, + template: false, + }, + 'code.id': { + isCreateable: true, + isUpdateable: true, + retrieving: false, + template: false, + }, + 'code.isClientOwned': { + isCreateable: true, + isUpdateable: true, + retrieving: false, + template: false, + }, + 'code.isGsmCharacterSetOnly': { + isCreateable: true, + isUpdateable: true, + retrieving: false, + template: false, + }, + 'code.isMms': { + isCreateable: true, + isUpdateable: true, + retrieving: false, + template: false, + }, + 'code.isOwner': { + isCreateable: true, + isUpdateable: true, + retrieving: false, + template: false, + }, + 'code.isShortCode': { + isCreateable: true, + isUpdateable: true, + retrieving: false, + template: false, + }, + 'code.isStackIndependant': { + isCreateable: true, + isUpdateable: true, + retrieving: false, + template: false, + }, + 'code.keywordLimit': { + isCreateable: true, + isUpdateable: true, + retrieving: false, + template: false, + }, + 'code.keywordsUsed': { + isCreateable: true, + isUpdateable: true, + retrieving: false, + template: false, + }, + 'code.keywordsUsedOther': { + isCreateable: true, + isUpdateable: true, + retrieving: false, + template: false, + }, + 'code.lastUpdated': { + isCreateable: true, + isUpdateable: true, + retrieving: false, + template: false, + }, + 'code.moEngineVersion': { + isCreateable: true, + isUpdateable: true, + retrieving: false, + template: false, + }, + 'code.sendableCountries': { + isCreateable: true, + isUpdateable: true, + retrieving: false, + template: false, + }, + 'code.sendableCountries[]': { + isCreateable: true, + isUpdateable: true, + retrieving: false, + template: false, + }, + 'code.sendableCountries[].countryCode': { + isCreateable: true, + isUpdateable: true, + retrieving: false, + template: false, + }, + 'code.sendableCountries[].vendor': { + isCreateable: true, + isUpdateable: true, + retrieving: false, + template: false, + }, + 'code.sendableCountries[].fromNameSupported': { + isCreateable: true, + isUpdateable: true, + retrieving: false, + template: false, + }, + 'code.startDate': { + isCreateable: true, + isUpdateable: true, + retrieving: false, + template: false, + }, + 'code.supportsConcatenation': { + isCreateable: true, + isUpdateable: true, + retrieving: false, + template: false, + }, + concatenateMessage: { + isCreatable: true, + isUpdatable: true, + retrieving: true, + template: true, + }, + currentEditStep: { + isCreatable: false, + isUpdatable: false, + retrieving: false, + template: false, + }, + doubleOptinConfirmMessage: { + isCreatable: true, + isUpdatable: true, + retrieving: true, + template: true, + }, + doubleOptinInitialMessage: { + isCreatable: true, + isUpdatable: true, + retrieving: true, + template: true, + }, + doubleOptinValidResponses: { + isCreatable: true, + isUpdatable: true, + retrieving: true, + template: true, + }, + duplicateOptInResponseMessage: { + isCreatable: true, + isUpdatable: true, + retrieving: true, + template: true, + }, + expireHours: { + isCreatable: true, + isUpdatable: true, + retrieving: true, + template: true, + }, + fromName: { + isCreatable: true, + isUpdatable: true, + retrieving: true, + template: true, + }, + id: { + isCreateable: false, + isUpdateable: true, + retrieving: true, + template: true, + }, + invalidMessage: { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + isCertified: { + isCreatable: true, + isUpdatable: true, + retrieving: true, + template: true, + }, + isDuplicationAllowed: { + isCreatable: true, + isUpdatable: true, + retrieving: true, + template: true, + }, + isExpireSet: { + isCreatable: true, + isUpdatable: true, + retrieving: true, + template: true, + }, + isFromNameCertificationAccepted: { + isCreatable: true, + isUpdatable: true, + retrieving: true, + template: true, + }, + isSentImmediately: { + isCreatable: true, + isUpdatable: true, + retrieving: true, + template: true, + }, + isSubscriberResponseToAnySubscriptionForShortCode: { + isCreatable: true, + isUpdatable: true, + retrieving: true, + template: true, + }, + isSuppressMt: { + isCreatable: true, + isUpdatable: true, + retrieving: true, + template: true, + }, + isTest: { + isCreatable: true, + isUpdatable: true, + retrieving: true, + template: true, + }, + isTimeZoneBased: { + isCreatable: true, + isUpdatable: true, + retrieving: true, + template: true, + }, + 'keyword.id': { + isCreateable: true, + isUpdateable: true, + retrieving: false, + template: false, + }, + 'keyword.isInherited': { + isCreateable: true, + isUpdateable: true, + retrieving: false, + template: false, + }, + 'keyword.keyword': { + isCreateable: true, + isUpdateable: true, + retrieving: false, + template: false, + }, + 'keyword.r__mobileKeyword_key': { + isCreateable: false, + isUpdateable: false, + retrieving: true, + template: true, + }, + 'keyword.keywordType': { + isCreateable: true, + isUpdateable: true, + retrieving: false, + template: false, + }, + 'keyword.restriction': { + isCreateable: true, + isUpdateable: true, + retrieving: false, + template: false, + }, + lastUpdated: { + isCreateable: false, + isUpdateable: true, + retrieving: true, + template: false, + }, + messageObjectId: { + isCreatable: true, + isUpdatable: true, + retrieving: true, + template: true, + }, + messagesPerPeriod: { + isCreatable: true, + isUpdatable: true, + retrieving: true, + template: true, + }, + minutesPerPeriod: { + isCreatable: true, + isUpdatable: true, + retrieving: true, + template: true, + }, + moStartDate: { + isCreatable: true, + isUpdatable: true, + retrieving: true, + template: true, + }, + moEndDate: { + isCreatable: true, + isUpdatable: true, + retrieving: true, + template: true, + }, + 'moTimezone.name': { + isCreatable: true, + isUpdatable: true, + retrieving: true, + template: true, + }, + 'moTimezone.offset': { + isCreatable: true, + isUpdatable: true, + retrieving: true, + template: true, + }, + 'mtRecurrence.id': { + isCreatable: true, + isUpdatable: true, + retrieving: true, + template: true, + }, + 'mtRecurrence.key': { + isCreatable: true, + isUpdatable: true, + retrieving: true, + template: true, + }, + 'mtRecurrence.createdDate': { + isCreatable: false, + isUpdatable: false, + retrieving: true, + template: false, + }, + 'mtRecurrence.createdBy': { + isCreatable: false, + isUpdatable: false, + retrieving: false, + template: false, + }, + 'mtRecurrence.lastUpdated': { + isCreatable: false, + isUpdatable: false, + retrieving: true, + template: false, + }, + 'mtRecurrence.lastUpdatedBy': { + isCreatable: false, + isUpdatable: false, + retrieving: false, + template: false, + }, + 'mtRecurrence.name': { + isCreatable: true, + isUpdatable: true, + retrieving: true, + template: true, + }, + 'mtRecurrence.description': { + isCreatable: true, + isUpdatable: true, + retrieving: true, + template: true, + }, + 'mtRecurrence.startDate': { + isCreatable: true, + isUpdatable: true, + retrieving: true, + template: true, + }, + 'mtRecurrence.iCalRecur': { + isCreatable: true, + isUpdatable: true, + retrieving: true, + template: true, + }, + 'mtRecurrence.timeZone': { + isCreatable: true, + isUpdatable: true, + retrieving: true, + template: true, + }, + 'mtRecurrence.timeZoneId': { + isCreatable: true, + isUpdatable: true, + retrieving: true, + template: true, + }, + mtSendDate: { + isCreatable: true, + isUpdatable: true, + retrieving: true, + template: true, + }, + name: { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + nextJob: { + // contains lots of info but deemed not needed for retrieving or deploying + isCreateable: false, + isUpdateable: false, + retrieving: false, + template: false, + }, + nextKeyword: { + // contains lots of info but deemed not needed for retrieving or deploying + isCreateable: false, + isUpdateable: false, + retrieving: false, + template: false, + }, + numberMessagesPerPeriod: { + isCreatable: true, + isUpdatable: true, + retrieving: true, + template: true, + }, + optinErrorMessage: { + isCreatable: true, + isUpdatable: true, + retrieving: true, + template: true, + }, + optinInvalidAgeMessage: { + isCreatable: true, + isUpdatable: true, + retrieving: true, + template: true, + }, + optinMinimumAge: { + isCreatable: true, + isUpdatable: true, + retrieving: true, + template: true, + }, + optinType: { + isCreatable: true, + isUpdatable: true, + retrieving: true, + template: true, + }, + origin: { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + outboundSendBehaviorFlag: { + isCreatable: true, + isUpdatable: true, + retrieving: true, + template: true, + }, + outboundSendTypeFlag: { + isCreatable: true, + isUpdatable: true, + retrieving: true, + template: true, + }, + periodType: { + isCreatable: true, + isUpdatable: true, + retrieving: true, + template: true, + }, + programId: { + // always "00000000-0000-0000-0000-000000000000" + isCreatable: false, + isUpdatable: false, + retrieving: false, + template: false, + }, + publishedMessage: { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + responseMessage: { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + sendMethod: { + isCreatable: true, + isUpdatable: true, + retrieving: true, + template: true, + }, + smsTriggeredSendDefinitionId: { + // if no value then it's set to "00000000-0000-0000-0000-000000000000" + isCreatable: true, + isUpdatable: true, + retrieving: true, + template: true, + }, + statistics: { + // not relevant for deployment or configuration + isCreateable: false, + isUpdateable: false, + retrieving: false, + template: false, + }, + 'statistics.outbound': { + // not relevant for deployment or configuration + isCreateable: false, + isUpdateable: false, + retrieving: false, + template: false, + }, + 'statistics.outbound.sent': { + // not relevant for deployment or configuration + isCreateable: false, + isUpdateable: false, + retrieving: false, + template: false, + }, + 'statistics.outbound.delivered': { + // not relevant for deployment or configuration + isCreateable: false, + isUpdateable: false, + retrieving: false, + template: false, + }, + 'statistics.outbound.undelivered': { + // not relevant for deployment or configuration + isCreateable: false, + isUpdateable: false, + retrieving: false, + template: false, + }, + 'statistics.outbound.unknown': { + // not relevant for deployment or configuration + isCreateable: false, + isUpdateable: false, + retrieving: false, + template: false, + }, + status: { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + statusId: { + isCreatable: true, + isUpdatable: true, + retrieving: true, + template: true, + }, + 'subscriptionKeyword.id': { + isCreatable: true, + isUpdatable: true, + retrieving: false, + template: false, + }, + 'subscriptionKeyword.keyword': { + isCreatable: false, + isUpdatable: false, + retrieving: false, + template: false, + }, + 'subscriptionKeyword.r__mobileKeyword_key': { + isCreateable: false, + isUpdateable: false, + retrieving: true, + template: true, + }, + 'subscriptionKeyword.restriction': { + isCreatable: false, + isUpdatable: false, + retrieving: false, + template: false, + }, + 'subscriptionKeyword.isInherited': { + isCreatable: false, + isUpdatable: false, + retrieving: false, + template: false, + }, + 'nextKeyword.id': { + isCreatable: true, + isUpdatable: true, + retrieving: false, + template: false, + }, + 'nextKeyword.keyword': { + isCreatable: false, + isUpdatable: false, + retrieving: false, + template: false, + }, + 'nextKeyword.r__mobileKeyword_key': { + isCreateable: false, + isUpdateable: false, + retrieving: true, + template: true, + }, + 'nextKeyword.restriction': { + isCreatable: false, + isUpdatable: false, + retrieving: false, + template: false, + }, + 'nextKeyword.isInherited': { + isCreatable: false, + isUpdatable: false, + retrieving: false, + template: false, + }, + subscriberResponseMessage: { + isCreatable: true, + isUpdatable: true, + retrieving: true, + template: true, + }, + surveyCorrectResponseMessage: { + isCreatable: true, + isUpdatable: true, + retrieving: true, + template: true, + }, + surveyIncorrectResponseMessage: { + isCreatable: true, + isUpdatable: true, + retrieving: true, + template: true, + }, + surveyResponsesAllowed: { + isCreatable: true, + isUpdatable: true, + retrieving: true, + template: true, + }, + surveyTooManyEntriesMessage: { + isCreatable: true, + isUpdatable: true, + retrieving: true, + template: true, + }, + surveyType: { + isCreatable: true, + isUpdatable: true, + retrieving: true, + template: true, + }, + 'template.description': { + isCreatable: true, + isUpdatable: true, + retrieving: true, + template: true, + }, + 'template.icon': { + isCreatable: true, + isUpdatable: true, + retrieving: true, + template: true, + }, + 'template.id': { + isCreatable: true, + isUpdatable: true, + retrieving: true, + template: true, + }, + 'template.lastUpdated': { + isCreatable: true, + isUpdatable: true, + retrieving: true, + template: true, + }, + 'template.name': { + isCreatable: true, + isUpdatable: true, + retrieving: true, + template: true, + }, + text: { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + triggeredSendId: { + // always "00000000-0000-0000-0000-000000000000" + isCreatable: false, + isUpdatable: false, + retrieving: false, + template: false, + }, + triggeredSendName: { + isCreatable: true, + isUpdatable: true, + retrieving: true, + template: true, + }, + type: { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + r__campaign_key: { + isCreateable: false, + isUpdateable: false, + retrieving: true, + template: true, + }, + 'r__campaign_key[]': { skipValidation: true }, + }, +}; diff --git a/lib/metadataTypes/definitions/Query.definition.js b/lib/metadataTypes/definitions/Query.definition.js index a08f35e1c..2408bc56f 100644 --- a/lib/metadataTypes/definitions/Query.definition.js +++ b/lib/metadataTypes/definitions/Query.definition.js @@ -1,23 +1,34 @@ -module.exports = { +export default { bodyIteratorField: 'items', - dependencies: ['folder', 'dataExtension'], + dependencies: ['folder-queryactivity', 'dataExtension'], + dependencyGraph: { + dataExtension: ['r__dataExtension_key'], + }, folderType: 'queryactivity', filter: { description: ['Query created by Query Studio'], }, hasExtended: false, idField: 'queryDefinitionId', + keyIsFixed: false, keyField: 'key', nameField: 'name', + folderIdField: 'categoryId', + createdDateField: 'createdDate', + createdNameField: null, + lastmodDateField: 'modifiedDate', + lastmodNameField: null, restPagination: true, targetUpdateTypeMapping: { Append: 2, Overwrite: 0, Update: 1, }, + maxKeyLength: 36, // confirmed max length type: 'query', typeDescription: 'Select & transform data using SQL.', typeRetrieveByDefault: true, + typeCdpByDefault: true, typeName: 'Automation: SQL Query Activity', fields: { categoryId: { @@ -81,8 +92,8 @@ module.exports = { template: false, }, targetId: { - isCreateable: false, - isUpdateable: false, + isCreateable: true, + isUpdateable: true, retrieving: false, template: false, }, @@ -116,6 +127,12 @@ module.exports = { retrieving: false, template: false, }, + r__dataExtension_key: { + isCreateable: false, + isUpdateable: false, + retrieving: true, + template: true, + }, r__folder_Path: { skipValidation: true }, }, }; diff --git a/lib/metadataTypes/definitions/Role.definition.js b/lib/metadataTypes/definitions/Role.definition.js index 1f1c0828e..bdde11039 100644 --- a/lib/metadataTypes/definitions/Role.definition.js +++ b/lib/metadataTypes/definitions/Role.definition.js @@ -1,6 +1,7 @@ -module.exports = { +export default { bodyIteratorField: 'Results', dependencies: [], + dependencyGraph: null, deployBlacklist: [ 'SYS_DEF_ADMIN', 'SYS_DEF_ANALYST', @@ -13,19 +14,27 @@ module.exports = { 'SYS_DEF_SECURITYADMIN', 'SYS_DEF_VIEWER', ], + documentInOneFile: true, hasExtended: true, idField: 'ObjectID', + keyIsFixed: false, keyField: 'CustomerKey', nameField: 'Name', + createdDateField: 'CreatedDate', + createdNameField: null, + lastmodDateField: 'ModifiedDate', + lastmodNameField: null, + maxKeyLength: 36, // confirmed max length type: 'role', typeDescription: 'User Roles define groups that are used to grant users access to SFMC systems.', typeRetrieveByDefault: true, + typeCdpByDefault: false, typeName: 'Role', fields: { CreatedDate: { - isCreateable: false, - isUpdateable: false, + isCreateable: true, + isUpdateable: true, retrieving: true, template: false, }, @@ -42,8 +51,8 @@ module.exports = { template: false, }, ModifiedDate: { - isCreateable: false, - isUpdateable: false, + isCreateable: true, + isUpdateable: true, retrieving: true, template: false, }, @@ -72,6 +81,10 @@ module.exports = { }, PermissionSets: { retrieving: true, + skipCache: true, + skipValidation: true, + }, + c__notAssignable: { skipValidation: true, }, }, diff --git a/lib/metadataTypes/definitions/Script.definition.js b/lib/metadataTypes/definitions/Script.definition.js index 709b0c749..1d57b3782 100644 --- a/lib/metadataTypes/definitions/Script.definition.js +++ b/lib/metadataTypes/definitions/Script.definition.js @@ -1,24 +1,33 @@ -module.exports = { +export default { bodyIteratorField: 'items', - dependencies: ['folder'], + dependencies: ['folder-ssjsactivity'], + dependencyGraph: null, folderType: 'ssjsactivity', hasExtended: false, idField: 'ssjsActivityId', + keyIsFixed: false, keyField: 'key', nameField: 'name', + folderIdField: 'categoryId', + createdDateField: 'createdDate', + createdNameField: null, + lastmodDateField: 'modifiedDate', + lastmodNameField: null, restPagination: true, type: 'script', typeDescription: 'Execute more complex tasks via SSJS or AMPScript.', typeRetrieveByDefault: true, + typeCdpByDefault: true, typeName: 'Automation: Script Activity', fields: { categoryId: { - isCreateable: null, - isUpdateable: null, + isCreateable: true, + isUpdateable: true, retrieving: true, template: true, }, createdBy: { + // not existing in rest api isCreateable: false, isUpdateable: false, retrieving: false, @@ -31,8 +40,8 @@ module.exports = { template: false, }, description: { - isCreateable: null, - isUpdateable: null, + isCreateable: true, + isUpdateable: true, retrieving: true, template: true, }, @@ -43,12 +52,13 @@ module.exports = { template: false, }, key: { - isCreateable: null, - isUpdateable: null, + isCreateable: true, + isUpdateable: true, retrieving: true, template: true, }, modifiedBy: { + // not existing in rest api isCreateable: false, isUpdateable: false, retrieving: false, @@ -61,20 +71,20 @@ module.exports = { template: false, }, name: { - isCreateable: null, - isUpdateable: null, + isCreateable: true, + isUpdateable: true, retrieving: true, template: true, }, script: { - isCreateable: null, - isUpdateable: null, + isCreateable: true, + isUpdateable: true, retrieving: true, template: true, }, ssjsActivityId: { - isCreateable: null, - isUpdateable: null, + isCreateable: true, + isUpdateable: true, retrieving: true, template: false, }, @@ -85,8 +95,14 @@ module.exports = { template: false, }, statusId: { - isCreateable: null, - isUpdateable: null, + isCreateable: false, + isUpdateable: false, + retrieving: false, + template: false, + }, + parentCategoryId: { + isCreateable: false, + isUpdateable: false, retrieving: false, template: false, }, diff --git a/lib/metadataTypes/definitions/SendClassification.definition.js b/lib/metadataTypes/definitions/SendClassification.definition.js new file mode 100644 index 000000000..2d7fd0616 --- /dev/null +++ b/lib/metadataTypes/definitions/SendClassification.definition.js @@ -0,0 +1,159 @@ +// https://developer.salesforce.com/docs/marketing/marketing-cloud/guide/sendclassification.html +export default { + bodyIteratorField: 'Results', + dependencies: ['senderProfile', 'deliveryProfile', 'domainVerification'], + dependencyGraph: { + senderProfile: ['r__senderProfile_key'], + // deliveryProfile: ['r__deliveryProfile_key'], // deliveryProfile cannot be deployed + }, + filter: {}, + hasExtended: false, + idField: 'ObjectID', + keyField: 'CustomerKey', + keyIsFixed: false, + maxKeyLength: 36, // confirmed max length + nameField: 'Name', + createdDateField: 'CreatedDate', + createdNameField: null, + lastmodDateField: 'ModifiedDate', + lastmodNameField: null, + restPagination: false, + type: 'sendClassification', + typeDescription: + 'Lets admins define Delivery Profile, Sender Profile and CAN-SPAM for an email job in a central location.', + typeRetrieveByDefault: true, + typeCdpByDefault: true, + typeName: 'Send Classification', + sendClassificationTypeMapping: { + Commercial: 'Marketing', + Transactional: 'Operational', + }, + fields: { + 'Client.ID': { + isCreateable: false, + isUpdateable: false, + retrieving: false, + template: false, + }, + CreatedDate: { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: false, + }, + ModifiedDate: { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: false, + }, + CustomerKey: { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + ObjectID: { + isCreateable: false, + isUpdateable: true, + retrieving: true, + template: false, + }, + Name: { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + Description: { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + PartnerKey: { + isCreateable: false, + isUpdateable: false, + retrieving: false, + template: false, + }, + PartnerProperties: { + isCreateable: false, + isUpdateable: false, + retrieving: false, + template: false, + }, + + ArchiveEmail: { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + 'DeliveryProfile.CustomerKey': { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + 'DeliveryProfile.PartnerKey': { + isCreateable: false, + isUpdateable: false, + retrieving: false, + template: false, + }, + 'DeliveryProfile.ObjectID': { + isCreateable: false, + isUpdateable: false, + retrieving: true, + template: false, + }, + HonorPublicationListOptOutsForTransactionalSends: { + /* not supported */ + isCreateable: false, + isUpdateable: false, + retrieving: false, + template: false, + }, + SendClassificationType: { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + 'SenderProfile.CustomerKey': { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + 'SenderProfile.PartnerKey': { + isCreateable: false, + isUpdateable: false, + retrieving: false, + template: false, + }, + 'SenderProfile.ObjectID': { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: false, + }, + SendPriority: { + /* not supported */ + isCreateable: false, + isUpdateable: false, + retrieving: false, + template: false, + }, + c__classification: { + skipValidation: true, + }, + r__deliveryProfile_key: { + skipValidation: true, + }, + r__senderProfile_key: { + skipValidation: true, + }, + }, +}; diff --git a/lib/metadataTypes/definitions/SenderProfile.definition.js b/lib/metadataTypes/definitions/SenderProfile.definition.js new file mode 100644 index 000000000..d7a6b7de8 --- /dev/null +++ b/lib/metadataTypes/definitions/SenderProfile.definition.js @@ -0,0 +1,222 @@ +export default { + bodyIteratorField: 'Results', + dependencies: ['user', 'domainVerification'], + dependencyGraph: { + domainVerification: ['FallbackFromAddress', 'FromAddress'], + }, + filter: {}, + hasExtended: false, + idField: 'ObjectID', + keyField: 'CustomerKey', + keyIsFixed: false, + maxKeyLength: 36, // confirmed max length + nameField: 'Name', + createdDateField: 'CreatedDate', + createdNameField: 'Client.CreatedBy', + lastmodDateField: 'ModifiedDate', + lastmodNameField: 'Client.ModifiedBy', + restPagination: false, + type: 'senderProfile', + typeDescription: 'Specifies the From information for a send in a central location', + typeRetrieveByDefault: true, + typeCdpByDefault: true, + typeName: 'Sender Profile', + fields: { + 'Client.ID': { + isCreateable: false, + isUpdateable: false, + retrieving: false, + template: false, + }, + 'Client.CreatedBy': { + isCreateable: false, + isUpdateable: false, + retrieving: true, + template: false, + }, + 'Client.ModifiedBy': { + isCreateable: false, + isUpdateable: false, + retrieving: true, + template: false, + }, + createdBy: { + isCreateable: false, + isUpdateable: false, + retrieving: null, + template: false, + }, + modifiedBy: { + isCreateable: false, + isUpdateable: false, + retrieving: null, + template: false, + }, + CreatedDate: { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: false, + }, + ModifiedDate: { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: false, + }, + CustomerKey: { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + ObjectID: { + isCreateable: false, + isUpdateable: true, + retrieving: true, + template: false, + }, + Name: { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + Description: { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + PartnerKey: { + isCreateable: false, + isUpdateable: false, + retrieving: false, + template: false, + }, + PartnerProperties: { + isCreateable: false, + isUpdateable: false, + retrieving: false, + template: false, + }, + + AutoForwardToEmailAddress: { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + AutoForwardToName: { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + 'AutoForwardTriggeredSend.ObjectID': { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + AutoReply: { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + 'AutoReplyTriggeredSend.ObjectID': { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + DataRetentionPeriodLength: { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + DataRetentionPeriodUnitOfMeasure: { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + DirectForward: { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + FallbackFromAddress: { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + FromAddress: { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + FromName: { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + ID: { + // not supported + isCreateable: false, + isUpdateable: false, + retrieving: false, + template: false, + }, + 'ReplyManagementRuleSet.ObjectID': { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + 'RMMRuleCollection.ObjectID': { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + ReplyToAddress: { + // not supported + isCreateable: false, + isUpdateable: false, + retrieving: false, + template: false, + }, + ReplyToDisplayName: { + // not supported + isCreateable: false, + isUpdateable: false, + retrieving: false, + template: false, + }, + SenderHeaderEmailAddress: { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + SenderHeaderName: { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + UseDefaultRMMRules: { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + }, +}; diff --git a/lib/metadataTypes/definitions/TransactionalEmail.definition.js b/lib/metadataTypes/definitions/TransactionalEmail.definition.js new file mode 100644 index 000000000..d0a3b9449 --- /dev/null +++ b/lib/metadataTypes/definitions/TransactionalEmail.definition.js @@ -0,0 +1,181 @@ +export default { + bodyIteratorField: 'definitions', + dependencies: ['asset-message', 'dataExtension', 'list', 'journey', 'sendClassification'], + dependencyGraph: { + // classic email cannot be deployed anymore + asset: ['r__asset_key'], + dataExtension: ['subscriptions.r__dataExtension_key'], + list: ['subscriptions.r__list_PathName'], + journey: ['r__journey_key'], + sendClassification: ['r__sendClassification_key'], + }, + hasExtended: false, + idField: 'definitionId', + keyIsFixed: true, // sending definitionKey in update call not allowed by API + keyField: 'definitionKey', + nameField: 'name', + createdDateField: 'createdDate', + createdNameField: null, + lastmodDateField: 'modifiedDate', + lastmodNameField: null, + restPagination: true, + restPageSize: 100, + maxKeyLength: 36, // confirmed max length + type: 'transactionalEmail', + typeDescription: 'Lets you send immediate Email messages via API events', + typeRetrieveByDefault: true, + typeCdpByDefault: false, + typeName: 'Transactional Email', + fields: { + name: { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + definitionKey: { + isCreateable: true, + isUpdateable: false, + retrieving: true, + template: true, + }, + description: { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + requestId: { + isCreateable: false, + isUpdateable: false, + retrieving: false, + template: false, + }, + definitionId: { + isCreateable: false, + isUpdateable: false, + retrieving: false, + template: false, + }, + status: { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + createdDate: { + isCreateable: false, + isUpdateable: false, + retrieving: true, + template: false, + }, + modifiedDate: { + isCreateable: false, + isUpdateable: false, + retrieving: true, + template: false, + }, + classification: { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + 'content.customerKey': { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + 'subscriptions.dataExtension': { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + 'subscriptions.r__dataExtension_key': { + isCreateable: false, + isUpdateable: false, + retrieving: true, + template: true, + }, + 'subscriptions.list': { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + 'subscriptions.r__list_PathName': { + isCreateable: false, + isUpdateable: false, + retrieving: true, + template: true, + }, + 'subscriptions.autoAddSubscriber': { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + 'subscriptions.updateSubscriber': { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + 'options.trackLinks': { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + 'options.cc': { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + 'options.bcc': { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + 'options.createJourney': { + isCreateable: true, + isUpdateable: false, + retrieving: false, + template: false, + }, + journey: { + isCreateable: false, + isUpdateable: false, + retrieving: true, + template: true, + }, + 'journey.interactionKey': { + isCreateable: false, + isUpdateable: false, + retrieving: true, + template: true, + }, + r__asset_key: { + isCreateable: false, + isUpdateable: false, + retrieving: true, + template: true, + }, + r__journey_key: { + isCreateable: false, + isUpdateable: false, + retrieving: true, + template: true, + }, + r__sendClassification_key: { + isCreateable: false, + isUpdateable: false, + retrieving: true, + template: true, + }, + }, +}; diff --git a/lib/metadataTypes/definitions/TransactionalMessage.definition.js b/lib/metadataTypes/definitions/TransactionalMessage.definition.js new file mode 100644 index 000000000..e02036761 --- /dev/null +++ b/lib/metadataTypes/definitions/TransactionalMessage.definition.js @@ -0,0 +1,71 @@ +export default { + bodyIteratorField: 'definitions', + dependencies: [], + dependencyGraph: null, + hasExtended: false, + idField: 'definitionId', + keyIsFixed: true, // sending definitionKey in update call not allowed by API + keyField: 'definitionKey', + nameField: 'name', + createdDateField: 'createdDate', + createdNameField: null, + lastmodDateField: 'modifiedDate', + lastmodNameField: null, + restPagination: true, + restPageSize: 100, + type: '', + typeDescription: 'here as a placeholder to have auto completion', + typeRetrieveByDefault: false, + typeCdpByDefault: true, + typeName: '', + fields: { + name: { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + definitionKey: { + isCreateable: true, + isUpdateable: false, + retrieving: true, + template: true, + }, + description: { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + requestId: { + isCreateable: false, + isUpdateable: false, + retrieving: false, + template: false, + }, + definitionId: { + isCreateable: false, + isUpdateable: false, + retrieving: false, + template: false, + }, + status: { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + createdDate: { + isCreateable: false, + isUpdateable: false, + retrieving: true, + template: false, + }, + modifiedDate: { + isCreateable: false, + isUpdateable: false, + retrieving: true, + template: false, + }, + }, +}; diff --git a/lib/metadataTypes/definitions/TransactionalPush.definition.js b/lib/metadataTypes/definitions/TransactionalPush.definition.js new file mode 100644 index 000000000..7caac2b4c --- /dev/null +++ b/lib/metadataTypes/definitions/TransactionalPush.definition.js @@ -0,0 +1,121 @@ +export default { + bodyIteratorField: 'definitions', + dependencies: ['asset-asset'], + dependencyGraph: { + asset: ['r__asset_key'], + }, + hasExtended: false, + idField: 'definitionId', + keyIsFixed: true, // sending definitionKey in update call not allowed by API + keyField: 'definitionKey', + nameField: 'name', + createdDateField: 'createdDate', + createdNameField: null, + lastmodDateField: 'modifiedDate', + lastmodNameField: null, + restPagination: true, + restPageSize: 100, + type: 'transactionalPush', + typeDescription: 'Lets you send immediate Push messages via API events', + typeRetrieveByDefault: true, + typeCdpByDefault: true, + typeName: 'Transactional Push', + fields: { + name: { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + definitionKey: { + isCreateable: true, + isUpdateable: false, + retrieving: true, + template: true, + }, + description: { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + requestId: { + isCreateable: false, + isUpdateable: false, + retrieving: false, + template: false, + }, + definitionId: { + isCreateable: false, + isUpdateable: false, + retrieving: false, + template: false, + }, + status: { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: false, + }, + createdDate: { + isCreateable: false, + isUpdateable: false, + retrieving: true, + template: false, + }, + modifiedDate: { + isCreateable: false, + isUpdateable: false, + retrieving: true, + template: false, + }, + 'content.customerKey': { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + r__asset_key: { + isCreateable: false, + isUpdateable: false, + retrieving: true, + template: true, + }, + 'options.badge': { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + 'options.sound': { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + 'options.customKeys': { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + 'options.customKeys[].value': { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + 'options.customKeys[].key': { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + applicationId: { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + }, +}; diff --git a/lib/metadataTypes/definitions/TransactionalSMS.definition.js b/lib/metadataTypes/definitions/TransactionalSMS.definition.js new file mode 100644 index 000000000..8d7ff95cf --- /dev/null +++ b/lib/metadataTypes/definitions/TransactionalSMS.definition.js @@ -0,0 +1,116 @@ +export default { + bodyIteratorField: 'definitions', + dependencies: ['mobileCode', 'mobileKeyword'], + dependencyGraph: { + mobileKeyword: ['subscriptions.r__mobileKeyword_key'], + mobileCode: ['subscriptions.r__mobileCode_key'], + }, + hasExtended: false, + idField: 'definitionId', + keyIsFixed: true, // sending definitionKey in update call not allowed by API + keyField: 'definitionKey', + nameField: 'name', + createdDateField: 'createdDate', + createdNameField: null, + lastmodDateField: 'modifiedDate', + lastmodNameField: null, + restPagination: true, + restPageSize: 100, + type: 'transactionalSMS', + typeDescription: 'Lets you send immediate SMS messages via API events', + typeRetrieveByDefault: true, + typeCdpByDefault: true, + typeName: 'Transactional SMS', + fields: { + name: { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + definitionKey: { + isCreateable: true, + isUpdateable: false, + retrieving: true, + template: true, + }, + description: { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + requestId: { + isCreateable: false, + isUpdateable: false, + retrieving: false, + template: false, + }, + definitionId: { + isCreateable: false, + isUpdateable: false, + retrieving: false, + template: false, + }, + status: { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + createdDate: { + isCreateable: false, + isUpdateable: false, + retrieving: true, + template: false, + }, + modifiedDate: { + isCreateable: false, + isUpdateable: false, + retrieving: true, + template: false, + }, + 'content.message': { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + 'subscriptions.shortCode': { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + 'subscriptions.countryCode': { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + 'subscriptions.autoAddSubscriber': { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + 'subscriptions.updateSubscriber': { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + 'subscriptions.keyword': { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + 'subscriptions.r__mobileKeyword_key': { + isCreateable: false, + isUpdateable: false, + retrieving: true, + template: true, + }, + }, +}; diff --git a/lib/metadataTypes/definitions/TriggeredSendDefinition.definition.js b/lib/metadataTypes/definitions/TriggeredSend.definition.js similarity index 79% rename from lib/metadataTypes/definitions/TriggeredSendDefinition.definition.js rename to lib/metadataTypes/definitions/TriggeredSend.definition.js index de24f253e..ee7e4a4ef 100644 --- a/lib/metadataTypes/definitions/TriggeredSendDefinition.definition.js +++ b/lib/metadataTypes/definitions/TriggeredSend.definition.js @@ -1,55 +1,93 @@ -module.exports = { +export default { bodyIteratorField: 'Results', - dependencies: ['folder', 'email', 'asset-message', 'list'], // SendClassification, SenderProfile, DeliveryProfile + dependencies: [ + 'folder-hidden', + 'folder-triggered_send', + 'folder-triggered_send_journeybuilder', + 'email', + 'asset-message', + 'list', + 'sendClassification', + 'senderProfile', + ], + dependencyGraph: { + // classic email cannot be deployed anymore + asset: ['r__asset_key'], + list: ['r__list_PathName'], + sendClassification: ['r__sendClassification_key'], + senderProfile: ['r__senderProfile_key'], + }, + filter: { + r__folder_Path: [ + 'Journey Builder Sends/', + 'HiddenCategory/HiddenJourneyBuilderTriggeredSends/', + ], + }, folderType: 'triggered_send', hasExtended: false, idField: 'ObjectID', keepId: true, + keyIsFixed: false, keyField: 'CustomerKey', nameField: 'Name', + folderIdField: 'CategoryID', + createdDateField: 'CreatedDate', + createdNameField: null, + lastmodDateField: 'ModifiedDate', + lastmodNameField: null, restPagination: null, - type: 'triggeredSendDefinition', - typeDescription: 'DEPRECATED: Sends emails via API or DataExtension Event.', - typeRetrieveByDefault: true, + maxKeyLength: 36, // confirmed max length + type: 'triggeredSend', + soapType: 'triggeredSendDefinition', + typeDescription: 'Used by Journey Builder to send triggered emails', + typeRetrieveByDefault: false, + typeCdpByDefault: false, typeName: 'Triggered Send', + priorityMapping: { + High: 3, + Medium: 4, + Low: 5, + }, fields: { AllowedSlots: { isCreateable: true, isUpdateable: true, retrieving: true, - templating: false, + templating: true, }, AutoAddSubscribers: { isCreateable: true, isUpdateable: true, retrieving: true, - templating: false, + templating: true, }, AutoUpdateSubscribers: { isCreateable: true, isUpdateable: true, retrieving: true, - templating: false, + templating: true, }, BatchInterval: { isCreateable: true, isUpdateable: true, retrieving: true, - templating: false, + templating: true, }, BccEmail: { + // while this can be retrieved, it seems to be always returned empty isCreateable: true, isUpdateable: true, - retrieving: true, + retrieving: false, templating: false, }, CategoryID: { isCreateable: true, isUpdateable: true, retrieving: true, - templating: false, + templating: true, }, CCEmail: { + // this field is updatable but not retrievable for some reason isCreateable: true, isUpdateable: true, retrieving: false, @@ -74,8 +112,8 @@ module.exports = { templating: false, }, CreatedDate: { - isCreateable: false, - isUpdateable: false, + isCreateable: true, + isUpdateable: true, retrieving: true, templating: false, }, @@ -83,7 +121,7 @@ module.exports = { isCreateable: true, isUpdateable: true, retrieving: true, - templating: false, + templating: true, }, DataSchemas: { isCreateable: false, @@ -95,19 +133,19 @@ module.exports = { isCreateable: true, isUpdateable: true, retrieving: true, - templating: false, + templating: true, }, 'DeliveryProfile.ObjectID': { isCreateable: true, isUpdateable: true, - retrieving: false, + retrieving: true, templating: false, }, Description: { isCreateable: true, isUpdateable: true, retrieving: true, - templating: false, + templating: true, }, DisableOnEmailBuildError: { isCreateable: false, @@ -125,13 +163,13 @@ module.exports = { isCreateable: true, isUpdateable: true, retrieving: true, - templating: false, + templating: true, }, 'Email.ID': { isCreateable: true, isUpdateable: true, retrieving: true, - templating: false, + templating: true, }, 'Email.PartnerKey': { isCreateable: false, @@ -149,7 +187,7 @@ module.exports = { isCreateable: true, isUpdateable: true, retrieving: true, - templating: false, + templating: true, }, ExclusionFilter: { isCreateable: false, @@ -167,7 +205,7 @@ module.exports = { isCreateable: true, isUpdateable: true, retrieving: true, - templating: false, + templating: true, }, FooterSalutationSource: { isCreateable: false, @@ -179,19 +217,19 @@ module.exports = { isCreateable: true, isUpdateable: true, retrieving: true, - templating: false, + templating: true, }, FromName: { isCreateable: true, isUpdateable: true, retrieving: true, - templating: false, + templating: true, }, 'HeaderContentArea.ID': { isCreateable: true, isUpdateable: true, retrieving: true, - templating: false, + templating: true, }, HeaderSalutationSource: { isCreateable: false, @@ -221,7 +259,7 @@ module.exports = { isCreateable: true, isUpdateable: true, retrieving: true, - templating: false, + templating: true, }, IsPlatformObject: { isCreateable: true, @@ -239,7 +277,7 @@ module.exports = { isCreateable: true, isUpdateable: true, retrieving: true, - templating: false, + templating: true, }, KeepExistingEmailSubject: { isCreateable: false, @@ -251,13 +289,13 @@ module.exports = { isCreateable: true, isUpdateable: true, retrieving: true, - templating: false, + templating: true, }, 'List.ID': { isCreateable: true, isUpdateable: true, retrieving: true, - templating: false, + templating: true, }, 'List.PartnerKey': { isCreateable: false, @@ -272,8 +310,8 @@ module.exports = { templating: false, }, ModifiedDate: { - isCreateable: false, - isUpdateable: false, + isCreateable: true, + isUpdateable: true, retrieving: true, templating: false, }, @@ -281,17 +319,17 @@ module.exports = { isCreateable: true, isUpdateable: true, retrieving: true, - templating: false, + templating: true, }, NewSlotTrigger: { isCreateable: true, isUpdateable: true, retrieving: true, - templating: false, + templating: true, }, ObjectID: { isCreateable: false, - isUpdateable: false, + isUpdateable: true, retrieving: false, templating: false, }, @@ -338,8 +376,9 @@ module.exports = { templating: false, }, PreHeader: { - isCreateable: false, - isUpdateable: false, + // retrieve not supported by API + isCreateable: true, + isUpdateable: true, retrieving: false, templating: false, }, @@ -347,13 +386,13 @@ module.exports = { isCreateable: true, isUpdateable: true, retrieving: true, - templating: false, + templating: true, }, 'PrivateDomain.ObjectID': { isCreateable: true, isUpdateable: true, retrieving: true, - templating: false, + templating: true, }, 'PrivateDomain.PartnerKey': { isCreateable: false, @@ -365,7 +404,7 @@ module.exports = { isCreateable: true, isUpdateable: true, retrieving: true, - templating: false, + templating: true, }, 'PrivateIP.PartnerKey': { isCreateable: false, @@ -375,7 +414,7 @@ module.exports = { }, RefreshContent: { isCreateable: false, - isUpdateable: false, + isUpdateable: true, retrieving: false, templating: false, }, @@ -401,12 +440,12 @@ module.exports = { isCreateable: true, isUpdateable: true, retrieving: true, - templating: false, + templating: true, }, 'SendClassification.ObjectID': { - isCreateable: false, - isUpdateable: false, - retrieving: false, + isCreateable: true, + isUpdateable: true, + retrieving: true, templating: false, }, 'SendClassification.PartnerKey': { @@ -419,12 +458,12 @@ module.exports = { isCreateable: true, isUpdateable: true, retrieving: true, - templating: false, + templating: true, }, 'SenderProfile.ObjectID': { - isCreateable: false, - isUpdateable: false, - retrieving: false, + isCreateable: true, + isUpdateable: true, + retrieving: true, templating: false, }, 'SenderProfile.PartnerKey': { @@ -437,7 +476,7 @@ module.exports = { isCreateable: true, isUpdateable: true, retrieving: true, - templating: false, + templating: true, }, SendSourceCustomerKey: { isCreateable: false, @@ -455,7 +494,7 @@ module.exports = { isCreateable: true, isUpdateable: true, retrieving: true, - templating: false, + templating: true, }, SendWindowDelete: { isCreateable: false, @@ -467,7 +506,7 @@ module.exports = { isCreateable: true, isUpdateable: true, retrieving: true, - templating: false, + templating: true, }, SourceAddressType: { isCreateable: false, @@ -479,13 +518,13 @@ module.exports = { isCreateable: true, isUpdateable: true, retrieving: true, - templating: false, + templating: true, }, TestEmailAddr: { isCreateable: true, isUpdateable: true, retrieving: true, - templating: false, + templating: true, }, TriggeredSendClass: { isCreateable: false, @@ -497,7 +536,7 @@ module.exports = { isCreateable: true, isUpdateable: true, retrieving: true, - templating: false, + templating: true, }, TriggeredSendSubClass: { isCreateable: false, @@ -509,7 +548,7 @@ module.exports = { isCreateable: true, isUpdateable: true, retrieving: true, - templating: false, + templating: true, }, TriggeredSendVersionID: { isCreateable: false, @@ -517,8 +556,13 @@ module.exports = { retrieving: false, templating: false, }, + r__asset_name_readOnly: { skipValidation: true }, + r__asset_key: { skipValidation: true }, + r__email_name: { skipValidation: true }, r__folder_Path: { skipValidation: true }, - r__assetMessage_Name: { skipValidation: true }, - r__assetMessage_Key: { skipValidation: true }, + r__list_PathName: { skipValidation: true }, + c__priority: { skipValidation: true }, + r__sendClassification_key: { skipValidation: true }, + r__senderProfile_key: { skipValidation: true }, }, }; diff --git a/lib/metadataTypes/definitions/TriggeredSendSummary.definition.js b/lib/metadataTypes/definitions/TriggeredSendSummary.definition.js new file mode 100644 index 000000000..0d70a3309 --- /dev/null +++ b/lib/metadataTypes/definitions/TriggeredSendSummary.definition.js @@ -0,0 +1,211 @@ +export default { + bodyIteratorField: 'Results', + dependencies: [ + 'triggeredSend', + 'folder-hidden', + 'folder-triggered_send', + 'folder-triggered_send_journeybuilder', + ], + dependencyGraph: { + triggeredSend: ['r__triggeredSend_key'], + }, + filter: {}, + hasExtended: false, + idField: 'ObjectID', + keepId: false, + keyIsFixed: true, + keyField: 'CustomerKey', + nameField: 'r__triggeredSend_name', + folderIdField: 'TriggeredSend.CategoryID', + createdDateField: null, + createdNameField: null, + lastmodDateField: null, + lastmodNameField: null, + restPagination: null, + maxKeyLength: 36, + type: 'triggeredSendSummary', + soapType: 'triggeredSendSummary', + typeDescription: 'Summary data for a Triggered Send', + typeRetrieveByDefault: false, + typeCdpByDefault: false, + typeName: 'Triggered Send Summary', + fields: { + Bounces: { + isCreateable: true, + isUpdateable: false, + retrieving: true, + templating: true, + }, + Clicks: { + isCreateable: true, + isUpdateable: false, + retrieving: true, + templating: true, + }, + 'Client.ID': { + isCreateable: false, + isUpdateable: false, + retrieving: false, + templating: false, + }, + Conversions: { + isCreateable: true, + isUpdateable: false, + retrieving: true, + templating: true, + }, + CustomerKey: { + isCreateable: true, + isUpdateable: true, + retrieving: true, + templating: true, + }, + FTAFEmailsSent: { + isCreateable: true, + isUpdateable: false, + retrieving: true, + templating: true, + }, + FTAFOptIns: { + isCreateable: true, + isUpdateable: false, + retrieving: true, + templating: true, + }, + FTAFRequests: { + isCreateable: true, + isUpdateable: false, + retrieving: true, + templating: true, + }, + ID: { + isCreateable: false, + isUpdateable: false, + retrieving: false, + templating: false, + }, + InProcess: { + isCreateable: true, + isUpdateable: false, + retrieving: true, + templating: true, + }, + NotSentDueToError: { + isCreateable: true, + isUpdateable: false, + retrieving: true, + templating: true, + }, + NotSentDueToOptOut: { + isCreateable: true, + isUpdateable: false, + retrieving: true, + templating: true, + }, + NotSentDueToUndeliverable: { + isCreateable: true, + isUpdateable: false, + retrieving: true, + templating: true, + }, + ObjectID: { + isCreateable: false, + isUpdateable: false, + retrieving: false, + templating: false, + }, + /* ObjectState: { + isCreateable: false, + isUpdateable: false, + retrieving: false, + templating: false, + }, */ // according to the documentation"Reserved for future use" + Opens: { + isCreateable: true, + isUpdateable: false, + retrieving: true, + templating: true, + }, + OptOuts: { + isCreateable: true, + isUpdateable: false, + retrieving: true, + templating: true, + }, + Owner: { + isCreateable: false, + isUpdateable: false, + retrieving: false, + templating: false, + }, + PartnerKey: { + isCreateable: false, + isUpdateable: false, + retrieving: false, + templating: false, + }, + PartnerProperties: { + isCreateable: false, + isUpdateable: false, + retrieving: false, + templating: false, + }, + Queued: { + isCreateable: true, + isUpdateable: false, + retrieving: true, + templating: true, + }, + Sent: { + isCreateable: true, + isUpdateable: false, + retrieving: true, + templating: true, + }, + SurveyResponses: { + isCreateable: true, + isUpdateable: false, + retrieving: true, + templating: true, + }, + UniqueClicks: { + isCreateable: true, + isUpdateable: false, + retrieving: true, + templating: true, + }, + UniqueConversions: { + isCreateable: true, + isUpdateable: false, + retrieving: true, + templating: true, + }, + UniqueOpens: { + isCreateable: true, + isUpdateable: false, + retrieving: true, + templating: true, + }, + CorrelationID: { + isCreateable: false, + isUpdateable: false, + retrieving: false, + templating: false, + }, + CreatedDate: { + isCreateable: false, + isUpdateable: false, + retrieving: false /** Listed in the type documentation but not retrievable */, + templating: false, + }, + ModifiedDate: { + isCreateable: false, + isUpdateable: false, + retrieving: false /** Listed in the type documentation but not retrievable */, + templating: false, + }, + r__triggeredSend_name: { skipValidation: true }, + r__triggeredSend_key: { skipValidation: true }, + r__folder_Path: { skipValidation: true }, + }, +}; diff --git a/lib/metadataTypes/definitions/User.definition.js b/lib/metadataTypes/definitions/User.definition.js new file mode 100644 index 000000000..0ff83164c --- /dev/null +++ b/lib/metadataTypes/definitions/User.definition.js @@ -0,0 +1,371 @@ +export default { + bodyIteratorField: 'Results', + dependencies: ['role'], + dependencyGraph: { + // role: ['c__RoleNamesGlobal'] // roles should rarely ever be deployed and hence this is not needed here + }, + folderType: null, + hasExtended: false, + idField: 'AccountUserID', // ID contains the same value as AccountUserID but is not required by API + keepId: true, + keyIsFixed: false, + keyField: 'CustomerKey', + nameField: 'Name', + createdDateField: 'CreatedDate', + createdNameField: null, + lastmodDateField: 'ModifiedDate', + lastmodNameField: 'Client.ModifiedBy', + maxKeyLength: 50, // confirmed max length + type: 'user', + soapType: 'AccountUser', + typeDescription: 'Marketing Cloud users', + typeName: 'User', + typeRetrieveByDefault: false, + typeCdpByDefault: false, + documentInOneFile: true, + stringifyFieldsBeforeTemplate: ['DefaultBusinessUnit', 'c__AssociatedBusinessUnits'], + fields: { + AccountUserID: { + // numeric id, cannot be changed but identifies the useruniquely + isCreateable: false, + isUpdateable: true, + retrieving: true, + template: false, + }, + ActiveFlag: { isCreateable: true, isUpdateable: true, retrieving: true, template: true }, + AssociatedBusinessUnits: { + // not supported by API + isCreateable: false, + isUpdateable: false, + retrieving: false, + template: false, + }, + BusinessUnit: { + // not supported by API + isCreateable: false, + isUpdateable: false, + retrieving: false, + template: false, + }, + ChallengeAnswer: { + // alwasy empty + isCreateable: false, + isUpdateable: false, + retrieving: false, + template: false, + }, + ChallengePhrase: { + // alwasy empty + isCreateable: false, + isUpdateable: false, + retrieving: false, + template: false, + }, + 'Client.ID': { isCreateable: true, isUpdateable: true, retrieving: false, template: false }, + 'Client.ModifiedBy': { + isCreateable: false, + isUpdateable: false, + retrieving: true, + template: false, + }, + 'Client.PartnerClientKey': { + isCreateable: false, + isUpdateable: false, + retrieving: false, + template: false, + }, + CorrelationID: { + isCreateable: false, + isUpdateable: false, + retrieving: false, + template: false, + }, + CreatedDate: { + isCreateable: false, + isUpdateable: false, + retrieving: true, + template: false, + }, + CustomerKey: { isCreateable: true, isUpdateable: true, retrieving: true, template: true }, + DefaultApplication: { + // not supported by API + isCreateable: false, + isUpdateable: false, + retrieving: false, + template: false, + }, + DefaultBusinessUnit: { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + DefaultBusinessUnitObject: { + // more complex version of DefaultBusinessUnit thats not needed for deployment + isCreateable: false, + isUpdateable: false, + retrieving: false, + template: false, + }, + Delete: { isCreateable: false, isUpdateable: false, retrieving: false, template: false }, + Email: { isCreateable: true, isUpdateable: true, retrieving: true, template: true }, + ID: { isCreateable: false, isUpdateable: false, retrieving: false, template: false }, + IsAPIUser: { isCreateable: true, isUpdateable: true, retrieving: true, template: true }, + IsLocked: { + // Indicates if account user can or cannot log into their account + isCreateable: false, + isUpdateable: false, + retrieving: true, + template: false, + }, + 'LanguageLocale.LocaleCode': { + // seems to always return en-US + isCreateable: false, + isUpdateable: false, + retrieving: false, + template: false, + }, + LastSuccessfulLogin: { + isCreateable: false, + isUpdateable: false, + retrieving: true, + template: false, + }, + 'Locale.LocaleCode': { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + 'Locale.ObjectID': { + isCreateable: false, + isUpdateable: false, + retrieving: false, + template: false, + }, + 'Locale.PartnerKey': { + isCreateable: false, + isUpdateable: false, + retrieving: false, + template: false, + }, + ModifiedDate: { + isCreateable: false, + isUpdateable: false, + retrieving: true, + template: false, + }, + MustChangePassword: { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + Name: { isCreateable: true, isUpdateable: true, retrieving: true, template: true }, + NotificationEmailAddress: { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + ObjectID: { isCreateable: null, isUpdateable: null, retrieving: false, template: null }, + ObjectState: { + isCreateable: false, + isUpdateable: false, + retrieving: false, + template: false, + }, + Owner: { isCreateable: false, isUpdateable: false, retrieving: false, template: false }, + PartnerKey: { + isCreateable: false, + isUpdateable: false, + retrieving: false, + template: false, + }, + PartnerProperties: { + isCreateable: false, + isUpdateable: false, + retrieving: false, + template: false, + }, + Password: { isCreateable: true, isUpdateable: true, retrieving: false, template: false }, + Roles: { isCreateable: true, isUpdateable: true, retrieving: true, template: true }, + 'Roles.Role': { + skipValidation: true, + }, + 'Roles.Role[].Client': { + skipValidation: false, + }, + SsoIdentities: { + isCreateable: true, + isUpdateable: true, + retrieving: false, // retrieve not supported by API + template: false, + }, + 'SsoIdentities.SsoIdentity': { + isCreateable: true, + isUpdateable: true, + retrieving: false, // retrieve not supported by API + template: false, + }, + 'SsoIdentities.SsoIdentity[].IsActive': { + isCreateable: true, + isUpdateable: true, + retrieving: false, + template: false, + }, + 'SsoIdentities.SsoIdentity[].FederatedID': { + isCreateable: true, + isUpdateable: true, + retrieving: false, + template: false, + }, + 'TimeZone.ID': { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: false, + }, + 'TimeZone.Name': { + isCreateable: false, + isUpdateable: false, + retrieving: true, + template: true, + }, + 'TimeZone.ObjectID': { + isCreateable: false, + isUpdateable: false, + retrieving: false, + template: false, + }, + 'TimeZone.PartnerKey': { + isCreateable: false, + isUpdateable: false, + retrieving: false, + template: false, + }, + Unlock: { + // do not retrieve it but also do not remove it from retrieve as we are adding it manually + skipValidation: true, + isCreateable: false, + isUpdateable: true, + template: true, + }, + UserID: { isCreateable: true, isUpdateable: true, retrieving: true, template: true }, + UserPermissions: { + // not sure what to do with the reponse yet. might become interesting for the future + isCreateable: false, + isUpdateable: false, + retrieving: false, + template: false, + }, + 'UserPermissions.PartnerKey': { + isCreateable: null, + isUpdateable: null, + retrieving: false, + template: false, + }, + 'UserPermissions.ID': { + skipValidation: true, + }, + 'UserPermissions.ObjectID': { + isCreateable: null, + isUpdateable: null, + retrieving: false, + template: false, + }, + 'UserPermissions.Name': { + isCreateable: null, + isUpdateable: null, + retrieving: false, + template: false, + }, + 'UserPermissions.Value': { + isCreateable: null, + isUpdateable: null, + retrieving: false, + template: false, + }, + 'UserPermissions.Description': { + isCreateable: null, + isUpdateable: null, + retrieving: false, + template: false, + }, + 'UserPermissions.Delete': { + isCreateable: null, + isUpdateable: null, + retrieving: false, + template: false, + }, + 'UserPermissions[].PartnerKey': { + isCreateable: null, + isUpdateable: null, + retrieving: false, + template: false, + }, + 'UserPermissions[].ID': { + skipValidation: true, + }, + 'UserPermissions[].ObjectID': { + isCreateable: null, + isUpdateable: null, + retrieving: false, + template: false, + }, + 'UserPermissions[].Name': { + isCreateable: null, + isUpdateable: null, + retrieving: false, + template: false, + }, + 'UserPermissions[].Value': { + isCreateable: null, + isUpdateable: null, + retrieving: false, + template: false, + }, + 'UserPermissions[].Description': { + isCreateable: null, + isUpdateable: null, + retrieving: false, + template: false, + }, + 'UserPermissions[].Delete': { + isCreateable: null, + isUpdateable: null, + retrieving: false, + template: false, + }, + c__type: { + isCreateable: false, + isUpdateable: false, + retrieve: null, // handled via script + template: false, + }, + c__AssociatedBusinessUnits: { + skipValidation: true, + }, + c__RoleNamesGlobal: { + skipValidation: true, + }, + c__LocaleCode: { + skipValidation: true, + }, + c__TimeZoneName: { + skipValidation: true, + }, + c__AccountUserID: { + isCreateable: false, + isUpdateable: false, + retrieve: null, // handled via script + template: false, + }, + c__IsLocked_readOnly: { + isCreateable: false, + isUpdateable: false, + retrieve: null, // handled via script + template: false, + }, + }, +}; diff --git a/lib/metadataTypes/definitions/Verification.definition.js b/lib/metadataTypes/definitions/Verification.definition.js new file mode 100644 index 000000000..9270ef7f0 --- /dev/null +++ b/lib/metadataTypes/definitions/Verification.definition.js @@ -0,0 +1,96 @@ +export default { + bodyIteratorField: 'items', + dependencies: ['dataExtension', 'user'], + dependencyGraph: { dataExtension: ['r__dataExtension_key'] }, + hasExtended: false, + idField: 'dataVerificationDefinitionId', + keyIsFixed: true, + keyField: 'c__automation_step', + createdDateField: null, + createdNameField: 'createdBy', + lastmodDateField: null, + lastmodNameField: null, + nameField: 'c__automation_step', + restPagination: false, + maxKeyLength: 36, // confirmed max length + type: 'verification', + typeDescription: 'Check DataExtension for a row count', + typeRetrieveByDefault: true, + typeCdpByDefault: true, + typeName: 'Automation: Verification Activity', + fields: { + createdBy: { + // User ID + isCreateable: false, + isUpdateable: false, + retrieving: true, + template: false, + }, + dataVerificationDefinitionId: { + isCreateable: false, // auto-assigned during creation by SFMC + isUpdateable: true, + retrieving: true, + template: true, + }, + notificationEmailAddress: { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + notificationEmailMessage: { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + shouldEmailOnFailure: { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + shouldStopOnFailure: { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + targetObjectId: { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + value1: { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + value2: { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + verificationType: { + isCreateable: true, + isUpdateable: true, + retrieving: true, + template: true, + }, + r__dataExtension_key: { + isCreateable: false, + isUpdateable: false, + retrieving: true, + template: true, + }, + c__automation_step: { + isCreateable: false, + isUpdateable: false, + retrieving: true, + template: true, + }, + }, +}; diff --git a/lib/retrieveChangelog.js b/lib/retrieveChangelog.js index d297d243f..1d8675670 100644 --- a/lib/retrieveChangelog.js +++ b/lib/retrieveChangelog.js @@ -1,8 +1,10 @@ #!/usr/bin/env node 'use strict'; +/* eslint-disable unicorn/prefer-top-level-await */ /** * sample file on how to retrieve a simple changelog to use in GUIs or automated processing of any kind + * * @example [{ name: 'deName', @@ -15,9 +17,10 @@ }] */ -const mcdev = require('./index'); -const Definition = require('./MetadataTypeDefinitions'); -const MetadataType = require('./MetadataTypeInfo'); +import mcdev from './index.js'; + +import Definition from './MetadataTypeDefinitions.js'; +import MetadataType from './MetadataTypeInfo.js'; // disable cli logs // mcdev._setLoggingLevel({ silent: true }); @@ -42,16 +45,20 @@ const customDefinition = { }; (async function () { // get userid>name mapping - const userList = (await mcdev.retrieve('ACN-Learning/_ParentBU_', 'accountUser', true)) - .accountUser; + const userList = (await mcdev.retrieve('ACN-Learning/_ParentBU_', ['user'], null, true)).user; // reduce userList to simple id-name map - Object.keys(userList).forEach((key) => { + for (const key of Object.keys(userList)) { userList[userList[key].ID] = userList[key].Name; delete userList[key]; - }); + } // get changed metadata - const changelogList = await mcdev.retrieve('ACN-Learning/MCDEV_Training_Source', null, true); + const changelogList = await mcdev.retrieve( + 'ACN-Learning/MCDEV_Training_Source', + null, + null, + true + ); const allMetadata = []; Object.keys(changelogList).map((type) => { if (changelogList[type]) { @@ -81,13 +88,13 @@ const customDefinition = { } }); const finalResult = allMetadata.filter((item) => undefined !== item); - console.log('finalResult', finalResult); + console.log('finalResult', finalResult); // eslint-disable-line no-console })(); /** * - * @param {object<string,string>} userList user-id > user-name map - * @param {object<string,string>} item single metadata item + * @param {Object.<string, string>} userList user-id > user-name map + * @param {Object.<string, string>} item single metadata item * @param {string} fieldname name of field containing the info * @returns {string} username or user id or 'n/a' */ diff --git a/lib/util/auth.js b/lib/util/auth.js new file mode 100644 index 000000000..dd201778a --- /dev/null +++ b/lib/util/auth.js @@ -0,0 +1,198 @@ +import { Util } from './util.js'; +import File from './file.js'; +import SDK from 'sfmc-sdk'; +import Conf from 'conf'; + +/** + * @typedef {import('../../types/mcdev.d.js').AuthObject} AuthObject + * @typedef {import('../../types/mcdev.d.js').BuObject} BuObject + * @typedef {import('../../types/mcdev.d.js').CodeExtract} CodeExtract + * @typedef {import('../../types/mcdev.d.js').CodeExtractItem} CodeExtractItem + * @typedef {import('../../types/mcdev.d.js').DeltaPkgItem} DeltaPkgItem + * @typedef {import('../../types/mcdev.d.js').Mcdevrc} Mcdevrc + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItem} MetadataTypeItem + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItemDiff} MetadataTypeItemDiff + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItemObj} MetadataTypeItemObj + * @typedef {import('../../types/mcdev.d.js').MetadataTypeMap} MetadataTypeMap + * @typedef {import('../../types/mcdev.d.js').MetadataTypeMapObj} MetadataTypeMapObj + * @typedef {import('../../types/mcdev.d.js').MultiMetadataTypeList} MultiMetadataTypeList + * @typedef {import('../../types/mcdev.d.js').MultiMetadataTypeMap} MultiMetadataTypeMap + * @typedef {import('../../types/mcdev.d.js').SoapRequestParams} SoapRequestParams + * @typedef {import('../../types/mcdev.d.js').TemplateMap} TemplateMap + * @typedef {import('../../types/mcdev.d.js').TypeKeyCombo} TypeKeyCombo + */ + +const credentialStore = new Conf({ + projectName: 'mcdev', + configName: 'sessions', + clearInvalidConfig: true, +}); +const initializedSDKs = {}; +let authfile; + +const Auth = { + /** + * For each business unit, set up base credentials to be used. + * + * @param {AuthObject} authObject details for + * @param {string} credential of the instance + * @returns {Promise.<void>} - + */ + async saveCredential(authObject, credential) { + const sdk = setupSDK(credential, authObject); + // check credentials to allow clear log output and stop execution + const test = await sdk.auth.getAccessToken(); + if (test.error) { + throw new Error(test.error_description); + } else if (test.scope) { + // find missing rights + const missingAccess = sdk.auth + .getSupportedScopes() + .filter((element) => !test.scope.includes(element)); + + if (missingAccess.length) { + Util.logger.warn( + 'Installed package has insufficient access. You might encounter malfunctions!' + ); + Util.logger.warn('Missing scope: ' + missingAccess.join(', ')); + } + const existingAuth = (await File.pathExists(Util.authFileName)) + ? await File.readJSON(Util.authFileName) + : {}; + existingAuth[credential] = authObject; + await File.writeJSONToFile('./', Util.authFileName.split('.json')[0], existingAuth); + authfile = existingAuth; + } + }, + + /** + * Returns an SDK instance to be used for API calls + * + * @param {BuObject} buObject information about current context + * @returns {SDK} auth object + */ + getSDK(buObject) { + const credentialKey = `${buObject.credential}/${buObject.businessUnit}`; + if (initializedSDKs[credentialKey]) { + // return initialied SDK if available + return initializedSDKs[credentialKey]; + } else { + // check existing credentials cached + authfile ||= File.readJsonSync(Util.authFileName); + const newAuthObj = authfile[buObject.credential]; + // use client_id + MID to ensure a unique combination across instances + const sessionKey = newAuthObj.client_id + '|' + buObject.mid; + const existingAuthObj = credentialStore.get(sessionKey); + if (!existingAuthObj) { + newAuthObj.account_id = buObject.mid; + } + initializedSDKs[credentialKey] = setupSDK(credentialKey, existingAuthObj || newAuthObj); + return initializedSDKs[credentialKey]; + } + }, + + /** + * helper to clear all auth sessions + * + * @returns {void} + */ + clearSessions() { + credentialStore.clear(); + Util.logger.info(`Auth sessions cleared`); + }, +}; + +/** + * Returns an SDK instance to be used for API calls + * + * @param {string} sessionKey key for specific BU + * @param {AuthObject} authObject credentials for specific BU + * @returns {SDK} auth object + */ +function setupSDK(sessionKey, authObject) { + return new SDK(authObject, { + eventHandlers: { + onLoop: (type, accumulator) => { + Util.logger.info( + Util.getGrayMsg( + ` - Requesting next batch (currently ${accumulator?.length} records)` + ) + ); + }, + onRefresh: (authObject) => { + authObject.scope = authObject.scope.split(' '); // Scope is usually not an array, but we enforce conversion here for simplicity + credentialStore.set(sessionKey, authObject); + }, + onConnectionError: (ex, remainingAttempts) => { + Util.logger.info( + ` - Connection problem (Code: ${ex.code}). Retrying ${remainingAttempts} time${ + remainingAttempts > 1 ? 's' : '' + }${ + ex.endpoint + ? Util.getGrayMsg( + ' - ' + ex.endpoint.split('rest.marketingcloudapis.com')[1] + ) + : '' + }` + ); + Util.logger.errorStack(ex); + }, + logRequest: (req) => { + const msg = structuredClone(req); + if (msg.url === '/Service.asmx') { + msg.data = msg.data.replaceAll( + /<fueloauth(.*)<\/fueloauth>/gim, + '<fueloauth>*** TOKEN REMOVED ***</fueloauth>' + ); + } else if (msg.headers?.Authorization) { + msg.headers.Authorization = 'Bearer *** TOKEN REMOVED ***'; + } + switch (Util.OPTIONS.api) { + case 'cli': { + /* eslint-disable no-console */ + console.log( + `${Util.color.fgMagenta}API REQUEST >>${Util.color.reset}`, + msg + ); + /* eslint-enable no-console */ + + break; + } + case 'log': { + let data; + if (msg.data) { + data = msg.data; + delete msg.data; + } + Util.logger.debug('API REQUEST >> ' + JSON.stringify(msg, null, 2)); + if (data) { + // printing it separately leads to better formatting + Util.logger.debug( + 'API REQUEST body >> \n ' + + (typeof data === 'string' + ? data + : JSON.stringify(data, null, 2)) + ); + } + + break; + } + // No default + } + }, + logResponse: (res) => { + const msg = + typeof res.data == 'string' ? res.data : JSON.stringify(res.data, null, 2); + if (Util.OPTIONS.api === 'cli') { + console.log(`${Util.color.fgMagenta}API RESPONSE <<${Util.color.reset}`, msg); // eslint-disable-line no-console + } else if (Util.OPTIONS.api === 'log') { + Util.logger.debug('API RESPONSE body << \n ' + msg); + } + }, + }, + requestAttempts: 4, + retryOnConnectionError: true, + }); +} + +export default Auth; diff --git a/lib/util/businessUnit.js b/lib/util/businessUnit.js index 9b845071e..1f534b05e 100644 --- a/lib/util/businessUnit.js +++ b/lib/util/businessUnit.js @@ -1,8 +1,27 @@ 'use strict'; -const Util = require('./util'); -const File = require('./file'); -const Retriever = require('../Retriever'); +import { Util } from './util.js'; +import File from './file.js'; +import auth from './auth.js'; + +/** + * @typedef {import('../../types/mcdev.d.js').AuthObject} AuthObject + * @typedef {import('../../types/mcdev.d.js').BuObject} BuObject + * @typedef {import('../../types/mcdev.d.js').CodeExtract} CodeExtract + * @typedef {import('../../types/mcdev.d.js').CodeExtractItem} CodeExtractItem + * @typedef {import('../../types/mcdev.d.js').DeltaPkgItem} DeltaPkgItem + * @typedef {import('../../types/mcdev.d.js').Mcdevrc} Mcdevrc + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItem} MetadataTypeItem + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItemDiff} MetadataTypeItemDiff + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItemObj} MetadataTypeItemObj + * @typedef {import('../../types/mcdev.d.js').MetadataTypeMap} MetadataTypeMap + * @typedef {import('../../types/mcdev.d.js').MetadataTypeMapObj} MetadataTypeMapObj + * @typedef {import('../../types/mcdev.d.js').MultiMetadataTypeList} MultiMetadataTypeList + * @typedef {import('../../types/mcdev.d.js').MultiMetadataTypeMap} MultiMetadataTypeMap + * @typedef {import('../../types/mcdev.d.js').SoapRequestParams} SoapRequestParams + * @typedef {import('../../types/mcdev.d.js').TemplateMap} TemplateMap + * @typedef {import('../../types/mcdev.d.js').TypeKeyCombo} TypeKeyCombo + */ /** * Helper that handles retrieval of BU info @@ -10,57 +29,42 @@ const Retriever = require('../Retriever'); const BusinessUnit = { /** * Refreshes BU names and ID's from MC instance - * @param {object} properties current properties that have to be refreshed + * + * @param {Mcdevrc} properties current properties that have to be refreshed * @param {string} credentialsName identifying name of the installed package / project - * @returns {Promise<boolean>} success of refresh + * @returns {Promise.<boolean>} success of refresh */ refreshBUProperties: async function (properties, credentialsName) { const currentCredentials = properties.credentials[credentialsName]; - const buObject = { - clientId: currentCredentials.clientId, - clientSecret: currentCredentials.clientSecret, - tenant: currentCredentials.tenant, - }; - let client; - Util.logger.info(`Testing credentials`); - try { - client = await Util.getETClient(buObject); - } catch (ex) { - Util.logger.error(ex.message); - return false; - } - const retriever = new Retriever(properties, buObject, client); Util.logger.info(`Loading BUs`); - - const buResult = await new Promise((resolve) => { - retriever.client.SoapClient.retrieve( + try { + const client = auth.getSDK({ + mid: currentCredentials.eid, + eid: currentCredentials.eid, + credential: credentialsName, + businessUnit: '_ParentBU_', + }); + const buResult = await client.soap.retrieve( 'BusinessUnit', ['Name', 'ID', 'ParentName', 'ParentID', 'IsActive'], - { queryAllAccounts: true }, - (error, response) => { - if (error) { - Util.logger.error(`Credentials failure. ${error}`); - resolve(null); - // throw new Error(error); - } else { - resolve(response.body.Results); - } - } + { QueryAllAccounts: true } ); - }); - if (buResult !== null && !buResult.length) { - Util.logger.error(`Credentials worked but no BUs found. Check access rights!`); - } else if (buResult !== null) { - Util.logger.info(`Found ${buResult.length} BUs:`); - // create shortcut and reset BU list at the same time. we don't want old entries clutter the new list - const myBuList = (currentCredentials.businessUnits = {}); - // sort array by name for better display (wont affect object in settings) - buResult - .sort((a, b) => { - if (a.ParentID === '0') { + if (buResult !== null && !buResult.Results) { + Util.logger.error(`Credentials worked but no BUs found. Check access rights!`); + } else if (buResult !== null) { + Util.logger.info(`Found ${buResult.Results.length} BUs:`); + // create shortcut and reset BU list at the same time. we don't want old entries clutter the new list + const myBuList = (currentCredentials.businessUnits = {}); + // sort array by name for better display (wont affect object in settings) + for (const element of buResult.Results.map((element) => { + element.ID = Number.parseInt(element.ID); + element.ParentID = Number.parseInt(element.ParentID); + return element; + }).toSorted((a, b) => { + if (a.ParentID === 0) { return -1; } - if (b.ParentID === '0') { + if (b.ParentID === 0) { return 1; } if (a.Name.toLowerCase() < b.Name.toLowerCase()) { @@ -70,49 +74,52 @@ const BusinessUnit = { return 1; } return 0; - }) - .forEach((element) => { - if (element.ParentID === '0') { + })) { + if (element.ParentID === 0) { myBuList[Util.parentBuName] = element.ID; currentCredentials.eid = element.ID; Util.logger.info(` - ${Util.parentBuName} (${element.Name})`); } else { - const equalizedName = element.Name.replace(/[^\w\s]/gi, '') // remove special chars - .replace(/ +/g, '_') // convert spaces to underscore - .replace(/__+/g, '_'); // make sure we never have more than one underscore in a row + const equalizedName = element.Name.replaceAll(/[^\w\s]/gi, '') // remove special chars + .replaceAll(/ +/g, '_') // convert spaces to underscore + .replaceAll(/__+/g, '_'); // make sure we never have more than one underscore in a row myBuList[equalizedName] = element.ID; Util.logger.info( ` - ${element.Name} ${ - element.Name !== equalizedName ? `(${equalizedName})` : '' + element.Name === equalizedName ? '' : `(${equalizedName})` }` ); } - }); - Util.logger.debug(`EID: ${currentCredentials.eid}`); - if (currentCredentials.eid === null) { - Util.logger.warn( - `It seems your 'installed package' was not created on the Parent BU of your instance.` - ); - Util.logger.warn( - `While basic functionality will work, it is strongly recommended that you create a new 'installed package' there to enable support for shared Data Extensions and automatic retrieval of the BU list.` - ); - Util.logger.warn( - `If you cannot create a package on the Parent BU, please open your ./.mcdevrc.json and update the list of BUs and their MIDs manually.` + } + Util.logger.debug(`EID: ${currentCredentials.eid}`); + if (currentCredentials.eid === null) { + Util.logger.warn( + `It seems your 'installed package' was not created on the Parent BU of your instance.` + ); + Util.logger.warn( + `While basic functionality will work, it is strongly recommended that you create a new 'installed package' there to enable support for shared Data Extensions and automatic retrieval of the BU list.` + ); + Util.logger.warn( + `If you cannot create a package on the Parent BU, please open your ./.mcdevrc.json and update the list of BUs and their MIDs manually.` + ); + // allow user to work by setting this to an obviously false value which nonetheless doesn't block execution + currentCredentials.eid = -1; + } + // store BU list for repo + await File.writeJSONToFile( + properties.directories.businessUnits, + File.filterIllegalFilenames(credentialsName + '.businessUnits'), + buResult.Results ); - // allow user to work by setting this to an obviously false value which nonetheless doesn't block execution - currentCredentials.eid = -1; + // update config + await File.saveConfigFile(properties); } - // store BU list for repo - await File.writeJSONToFile( - properties.directories.businessUnits, - File.filterIllegalFilenames(credentialsName + '.businessUnits'), - buResult - ); - // update config - await File.saveConfigFile(properties); + } catch (ex) { + Util.logger.error(`Credentials failure. ${ex}`); + return null; } return true; }, }; -module.exports = BusinessUnit; +export default BusinessUnit; diff --git a/lib/util/cache.js b/lib/util/cache.js new file mode 100644 index 000000000..e69e32317 --- /dev/null +++ b/lib/util/cache.js @@ -0,0 +1,305 @@ +import { Util } from './util.js'; + +/** + * @typedef {import('../../types/mcdev.d.js').AuthObject} AuthObject + * @typedef {import('../../types/mcdev.d.js').BuObject} BuObject + * @typedef {import('../../types/mcdev.d.js').Cache} Cache + * @typedef {import('../../types/mcdev.d.js').CodeExtract} CodeExtract + * @typedef {import('../../types/mcdev.d.js').CodeExtractItem} CodeExtractItem + * @typedef {import('../../types/mcdev.d.js').DeltaPkgItem} DeltaPkgItem + * @typedef {import('../../types/mcdev.d.js').Mcdevrc} Mcdevrc + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItem} MetadataTypeItem + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItemDiff} MetadataTypeItemDiff + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItemObj} MetadataTypeItemObj + * @typedef {import('../../types/mcdev.d.js').MetadataTypeMap} MetadataTypeMap + * @typedef {import('../../types/mcdev.d.js').MetadataTypeMapObj} MetadataTypeMapObj + * @typedef {import('../../types/mcdev.d.js').MultiMetadataTypeList} MultiMetadataTypeList + * @typedef {import('../../types/mcdev.d.js').MultiMetadataTypeMap} MultiMetadataTypeMap + * @typedef {import('../../types/mcdev.d.js').SoapRequestParams} SoapRequestParams + * @typedef {import('../../types/mcdev.d.js').TemplateMap} TemplateMap + * @typedef {import('../../types/mcdev.d.js').TypeKeyCombo} TypeKeyCombo + * + * @typedef {import('../../types/mcdev.d.js').ListItem} ListItem + * @typedef {import('../../types/mcdev.d.js').ListMap} ListMap + */ + +/** @type {Cache} */ +const dataStore = {}; +let currentMID = null; + +export default { + /** + * Method to setup buObject + * NOTE: in future this may need to restore, rather than wipe the cache + * + * @param {BuObject} buObject for current Business unit + * @returns {void} + */ + initCache: (buObject) => { + if (buObject?.mid) { + currentMID = buObject.mid; + dataStore[currentMID] = {}; + // If the EID is not setup, also do this for required types (ie. Folders) + if (!dataStore[buObject.eid]) { + dataStore[buObject.eid] = {}; + } + } else { + throw new Error('Business Unit (buObject) used when initialzing cache was missing MID'); + } + }, + + /** + * return entire cache for current MID + * + * @returns {MultiMetadataTypeMap} cache for one Business Unit + */ + getCache: () => dataStore[currentMID], + + /* eslint-disable unicorn/no-array-for-each */ + + /** + * clean cache for one BU if mid provided, otherwise whole cache + * + * @param {number} [mid] limit clearing to provided business unit MID + * @param {string} [type] optionally limit clearing to specific metadata type; only used if mid is provided + * @returns {void} + */ + clearCache: (mid, type) => + mid + ? Object.keys(dataStore[mid]).forEach((key) => { + if (!type || type === key) { + delete dataStore[mid][key]; + } + }) + : Object.keys(dataStore).forEach((key) => delete dataStore[key]), + /* eslint-enable unicorn/no-array-for-each */ + + /** + * return a specific item from cache + * + * @param {string} type of Metadata to retrieve from cache + * @param {string} key of the specific metadata + * @returns {MetadataTypeItem} cached metadata item + */ + getByKey: (type, key) => dataStore[currentMID]?.[type]?.[key], + + /** + * override cache for given metadata type with new data + * + * @param {string} type of Metadata to retrieve from cache + * @param {MetadataTypeMap} metadataMap map to be set + * @returns {void} + */ + setMetadata: (type, metadataMap) => { + dataStore[currentMID][type] = metadataMap; + }, + + /** + * merges entire metadata type with existing cache + * + * @param {string} type of Metadata to retrieve from cache + * @param {MetadataTypeMap} metadataMap map to be merged + * @param {number} [overrideMID] which should be used for merging + * @returns {void} + */ + mergeMetadata: (type, metadataMap, overrideMID) => { + // ensure cache exists for type + dataStore[currentMID][type] ||= {}; + // if overrideMID is provided, create a copy of current MID cache + if (overrideMID) { + // ! needs to be verified if this is actually needed. When discovering an issue with this method actually overriting metadataMap, this copy-logic was present and i did not want to break things + dataStore[overrideMID][type] = Object.assign({}, dataStore[currentMID][type]); + } + // merge metadataMap into existing cache + Object.assign(dataStore[overrideMID || currentMID][type] || {}, metadataMap); + }, + + /** + * standardized method for getting data from cache. + * + * @param {string} metadataType metadata type ie. query + * @param {string|number|boolean} searchValue unique identifier of metadata being looked for + * @param {string} searchField field name (key in object) which contains the unique identifer + * @param {string} returnField field which should be returned + * @param {number} [overrideMID] ignore currentMID and use alternative (for example parent MID) + * @param {boolean} caseInsensitive optional; if true, search is case insensitive + * @returns {string} value of specified field. Error is thrown if not found + */ + searchForField( + metadataType, + searchValue, + searchField, + returnField, + overrideMID, + caseInsensitive = false + ) { + if (caseInsensitive) { + searchValue = (searchValue + '').toLowerCase(); + } + for (const key in dataStore[overrideMID || currentMID]?.[metadataType]) { + if ( + (caseInsensitive && + ( + Util.resolveObjPath( + searchField, + dataStore[overrideMID || currentMID][metadataType][key] + ) + '' + ).toLowerCase() == searchValue) || + (!caseInsensitive && + Util.resolveObjPath( + searchField, + dataStore[overrideMID || currentMID][metadataType][key] + ) == searchValue) + ) { + try { + if ( + Util.resolveObjPath( + returnField, + dataStore[overrideMID || currentMID][metadataType][key] + ) + ) { + return Util.resolveObjPath( + returnField, + dataStore[overrideMID || currentMID][metadataType][key] + ); + } else { + throw new Error(); // eslint-disable-line unicorn/error-message + } + } catch { + throw new Error( + `${metadataType} with ${searchField} '${searchValue}' does not have field '${returnField}'` + ); + } + } + } + throw new Error( + `Dependent ${metadataType} with ${searchField}='${searchValue}' was not found on your BU` + ); + }, + + /** + * helper for setFolderId + * + * @param {string} r__folder_Path folder path value + * @param {number} [overrideMID] ignore currentMID and use alternative (for example parent MID) + * @param {boolean} allowOtherBu getting folder from other BU; FALSE for folder parent search + * @returns {number} folder ID + */ + getFolderId(r__folder_Path, overrideMID, allowOtherBu = true) { + const folder = this.getFolderByPath(r__folder_Path, overrideMID, allowOtherBu); + return folder?.ID; + }, + + /** + * helper for setFolderId + * + * @param {string} r__folder_Path folder path value + * @param {number} [overrideMID] ignore currentMID and use alternative (for example parent MID) + * @param {boolean} allowOtherBu getting folder from other BU; FALSE for folder parent search + * @returns {object} folder item + */ + getFolderByPath(r__folder_Path, overrideMID, allowOtherBu = true) { + if (!r__folder_Path) { + throw new Error('r__folder_Path not set'); + } + + /** @type {ListMap} */ + const folderMap = dataStore[overrideMID || currentMID]?.['folder']; + if (!folderMap) { + throw new Error('No folders found in cache'); + } + const folderPath_lower = r__folder_Path.toLowerCase(); + const potentialFolders = []; + for (const folder of Object.values(folderMap)) { + if (!folder?.Path) { + continue; // skip folders without Path + } + if (folder.Path.toLowerCase() === folderPath_lower) { + if (folder?.Client?.ID === (overrideMID || currentMID)) { + return folder; + } else if (allowOtherBu) { + potentialFolders.push(folder); + } + } + } + + if (potentialFolders.length >= 1) { + return potentialFolders[0]; + } else { + throw new Error(`No folders found with path ${r__folder_Path}`); + } + }, + + /** + * standardized method for getting data from cache - adapted for special case of lists + * ! keeping this in util/cache.js rather than in metadataTypes/List.js to avoid potential circular dependencies + * + * @param {string} searchValue unique identifier of metadata being looked for + * @param {'ObjectID'|'ID'|'CustomerKey'} searchField ObjectID:string(uuid), ID:numeric, CustomerKey:string(name + folder ID) + * @returns {string} unique folderPath/ListName combo of list + */ + getListPathName(searchValue, searchField) { + const returnField1 = 'r__folder_Path'; + const returnField2 = 'ListName'; + for (const key in dataStore[currentMID]['list']) { + if (dataStore[currentMID]['list'][key][searchField] === searchValue) { + try { + if ( + dataStore[currentMID]['list'][key][returnField1] && + dataStore[currentMID]['list'][key][returnField2] + ) { + return ( + dataStore[currentMID]['list'][key][returnField1] + + '/' + + dataStore[currentMID]['list'][key][returnField2] + ); + } else { + throw new Error(); // eslint-disable-line unicorn/error-message + } + } catch { + throw new Error( + `${'list'} with ${searchField}='${searchValue}' does not have the fields ${returnField1} and ${returnField2}` + ); + } + } + } + throw new Error( + `Dependent list with ${searchField}='${searchValue}' was not found on your BU` + ); + }, + + /** + * standardized method for getting data from cache - adapted for special case of lists + * ! keeping this in util/cache.js rather than in metadataTypes/List.js to avoid potential circular dependencies + * + * @param {string} listPathName folderPath/ListName combo of list + * @param {'ObjectID'|'ID'|'CustomerKey'|'ListName'} returnField ObjectID:string(uuid), ID:numeric, CustomerKey:string(name + folder ID) + * @returns {string} unique ObjectId of list + */ + getListObjectId(listPathName, returnField) { + const folderPathArr = listPathName.split('/'); + const listName = folderPathArr.pop(); + const folderPath = folderPathArr.join('/'); + for (const key in dataStore[currentMID]['list']) { + if ( + dataStore[currentMID]['list'][key].ListName === listName && + dataStore[currentMID]['list'][key].r__folder_Path === folderPath + ) { + try { + if (dataStore[currentMID]['list'][key][returnField]) { + return dataStore[currentMID]['list'][key][returnField]; + } else { + throw new Error(); // eslint-disable-line unicorn/error-message + } + } catch { + throw new Error( + `${'list'} with ListName='${listName}' and r__folder_Path='${folderPath}' does not have field '${returnField}'` + ); + } + } + } + throw new Error( + `Dependent list with ListName='${listName}' and r__folder_Path='${folderPath}' was not found on your BU` + ); + }, +}; diff --git a/lib/util/cli.js b/lib/util/cli.js index 5ed6e4d02..d75a1ad15 100644 --- a/lib/util/cli.js +++ b/lib/util/cli.js @@ -1,10 +1,36 @@ 'use strict'; -const BuHelper = require('./businessUnit'); -const File = require('./file'); -const inquirer = require('inquirer'); -const MetadataDefinitions = require('./../MetadataTypeDefinitions'); -const Util = require('./util'); +import BuHelper from './businessUnit.js'; +import File from './file.js'; +import config from './config.js'; +import { select, checkbox, input, number, confirm, Separator } from '@inquirer/prompts'; +import MetadataDefinitions from './../MetadataTypeDefinitions.js'; +import { Util } from './util.js'; +import auth from './auth.js'; +import 'console.table'; +import MetadataTypeInfo from './../MetadataTypeInfo.js'; +import TransactionalMessage from './../metadataTypes/TransactionalMessage.js'; + +/** + * @typedef {import('../../types/mcdev.d.js').AuthObject} AuthObject + * @typedef {import('../../types/mcdev.d.js').BuObject} BuObject + * @typedef {import('../../types/mcdev.d.js').Cache} Cache + * @typedef {import('../../types/mcdev.d.js').CodeExtract} CodeExtract + * @typedef {import('../../types/mcdev.d.js').CodeExtractItem} CodeExtractItem + * @typedef {import('../../types/mcdev.d.js').DeltaPkgItem} DeltaPkgItem + * @typedef {import('../../types/mcdev.d.js').Mcdevrc} Mcdevrc + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItem} MetadataTypeItem + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItemDiff} MetadataTypeItemDiff + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItemObj} MetadataTypeItemObj + * @typedef {import('../../types/mcdev.d.js').MetadataTypeMap} MetadataTypeMap + * @typedef {import('../../types/mcdev.d.js').MetadataTypeMapObj} MetadataTypeMapObj + * @typedef {import('../../types/mcdev.d.js').MultiMetadataTypeList} MultiMetadataTypeList + * @typedef {import('../../types/mcdev.d.js').MultiMetadataTypeMap} MultiMetadataTypeMap + * @typedef {import('../../types/mcdev.d.js').SoapRequestParams} SoapRequestParams + * @typedef {import('../../types/mcdev.d.js').TemplateMap} TemplateMap + * @typedef {import('../../types/mcdev.d.js').TypeKeyCombo} TypeKeyCombo + * @typedef {import('../../types/mcdev.d.js').ExplainType} ExplainType + */ /** * CLI helper class @@ -14,84 +40,120 @@ const Cli = { /** * used when initially setting up a project. * loads default config and adds first credential - * @param {Object} [skipInteraction] signals what to insert automatically for things usually asked via wizard - * @param {String} skipInteraction.clientId client id of installed package - * @param {String} skipInteraction.clientSecret client id of installed package - * @param {String} skipInteraction.tenant client id of installed package - * @param {String} skipInteraction.credentialsName how you would like the credential to be named - * @returns {Promise<boolean>} success of init + * + * @returns {Promise.<string | boolean>} success of init */ - async initMcdevConfig(skipInteraction) { + async initMcdevConfig() { Util.logger.info('-- Initialising server connection --'); Util.logger.info('Please enter a name for your "Installed Package" credentials:'); - const propertiesTemplate = Util.getDefaultProperties(); + const propertiesTemplate = await config.getDefaultProperties(); delete propertiesTemplate.credentials.default; // wait for the interaction to finish or else an outer await will run before this is done - return this._setCredential(propertiesTemplate, null, skipInteraction); + return this._setCredential(propertiesTemplate, null); }, + /** * Extends template file for properties.json - * @param {Object} properties config file's json - * @param {Object} properties.credentials list of existing credentials - * @param {Object} [skipInteraction] signals what to insert automatically for things usually asked via wizard - * @param {String} skipInteraction.clientId client id of installed package - * @param {String} skipInteraction.clientSecret client id of installed package - * @param {String} skipInteraction.tenant client id of installed package - * @param {String} skipInteraction.credentialsName how you would like the credential to be named - * @returns {Promise<void>} - + * + * @param {Mcdevrc} properties config file's json + * @returns {Promise.<boolean | string>} status */ - async addExtraCredential(properties, skipInteraction) { - if (!Util.checkProperties(properties)) { + async addExtraCredential(properties) { + const skipInteraction = Util.skipInteraction; + if (await config.checkProperties(properties)) { + this.logExistingCredentials(properties); + Util.logger.info('\nPlease enter your new credentials'); + if (skipInteraction && properties.credentials[skipInteraction.credentialName]) { + Util.logger.error( + `Credential '${skipInteraction.credentialName}' already existing. If you tried updating please provide run 'mcdev init ${skipInteraction.credentialName}'` + ); + return null; + } + return this._setCredential(properties, null); + } else { // return null here to avoid seeing 2 error messages for the same issue return null; + } + }, + + /** + * + * @param {string[]} dependentTypes types that depent on type + * @returns {Promise.<boolean>} true if user wants to continue with retrieve + */ + async postFixKeysReretrieve(dependentTypes) { + if (Util.isTrue(Util.skipInteraction?.fixKeysReretrieve)) { + return true; + } else if (Util.isFalse(Util.skipInteraction?.fixKeysReretrieve)) { + return false; } else { - Util.logger.info('Found the following credentials in your config file:'); - for (const cred in properties.credentials) { - if (Object.prototype.hasOwnProperty.call(properties.credentials, cred)) { - Util.logger.info(` - ${cred}`); + const fixKeysReretrieve = await confirm({ + message: `Do you want to re-retrieve dependent types (${dependentTypes.join( + ', ' + )}) now?`, + default: true, + }); + if (Util.OPTIONS._multiBuExecution) { + const rememberFixKeysReretrieve = await confirm({ + message: `Remember answer for other BUs?`, + default: true, + }); + if (rememberFixKeysReretrieve) { + Util.skipInteraction ||= {}; + Util.skipInteraction.fixKeysReretrieve = fixKeysReretrieve; } } - Util.logger.info('\nPlease enter your new credentials'); - if (skipInteraction && properties.credentials[skipInteraction.credentialsName]) { - Util.logger.error( - `Credential '${skipInteraction.credentialsName}' already existing. If you tried updating please provide run 'mcdev init ${skipInteraction.credentialsName}'` - ); + return fixKeysReretrieve; + } + }, + + /** + * helper that logs to cli which credentials are already existing in our config file + * + * @param {Mcdevrc} properties config file's json + * @returns {void} + */ + logExistingCredentials(properties) { + Util.logger.info('Found the following credentials in your config file:'); + for (const cred in properties.credentials) { + if (Object.prototype.hasOwnProperty.call(properties.credentials, cred)) { + Util.logger.info(` - ${cred}`); } - return this._setCredential(properties, null, skipInteraction); } }, + /** * Extends template file for properties.json * update credentials - * @param {object} properties config file's json + * + * @param {Mcdevrc} properties config file's json * @param {string} credName name of credential that needs updating - * @param {Object} [skipInteraction] signals what to insert automatically for things usually asked via wizard - * @param {String} skipInteraction.clientId client id of installed package - * @param {String} skipInteraction.clientSecret client id of installed package - * @param {String} skipInteraction.tenant client id of installed package - * @param {String} skipInteraction.credentialsName how you would like the credential to be named - * @returns {Promise<Boolean>} success of update + * @param {boolean} [refreshBUs] if this was triggered by mcdev join, do not refresh BUs + * @returns {Promise.<string | boolean>} success of update */ - async updateCredential(properties, credName, skipInteraction) { + async updateCredential(properties, credName, refreshBUs = true) { + const skipInteraction = Util.skipInteraction; if (credName) { if (!skipInteraction) { Util.logger.info(`Please enter the details for '${credName}'`); } - return await this._setCredential(properties, credName, skipInteraction); + return await this._setCredential(properties, credName, refreshBUs); } }, + /** * Returns Object with parameters required for accessing API - * @param {Object} properties object of all configuration including credentials - * @param {String} target code of BU to use - * @param {boolean|string} [isCredentialOnly] true:don't ask for BU | string: name of BU + * + * @param {Mcdevrc} properties object of all configuration including credentials + * @param {string} target code of BU to use + * @param {boolean | string} [isCredentialOnly] true:don't ask for BU | string: name of BU * @param {boolean} [allowAll] Offer ALL as option in BU selection - * @returns {Promise<Util.BuObject>} credential to be used for Business Unit + * @returns {Promise.<BuObject>} credential to be used for Business Unit */ async getCredentialObject(properties, target, isCredentialOnly, allowAll) { try { - if (!Util.checkProperties(properties)) { + if (!(await config.checkProperties(properties))) { // return null here to avoid seeing 2 error messages for the same issue return null; } @@ -107,9 +169,18 @@ const Cli = { } else if (!credential || !properties.credentials[credential]) { // no or unknown credential provided; BU either to be selected or pre-selected if (credential !== null) { - Util.logger.warn(`Credential '${credential}' not found`); + const msg = `Credential '${credential}' not found`; + if (Util.skipInteraction) { + throw new Error(msg); + } + Util.logger.warn(msg); } - const response = await this._selectBU(properties, null, isCredentialOnly, allowAll); + const response = await this._selectBU( + properties, + null, + !!isCredentialOnly, + allowAll + ); credential = response.credential; businessUnit = response.businessUnit; if (!isCredentialOnly) { @@ -126,10 +197,13 @@ const Cli = { ) { // correct credential provided but BU still needed if (businessUnit && businessUnit !== 'undefined') { - Util.logger.warn( - `Business Unit '${businessUnit}' not found for credential '${credential}'` - ); + const msg = `Business Unit '${businessUnit}' not found for credential '${credential}'`; + if (Util.skipInteraction) { + throw new Error(msg); + } + Util.logger.warn(msg); } + const response = await this._selectBU(properties, credential, null, allowAll); businessUnit = response.businessUnit; Util.logger.info( @@ -137,9 +211,6 @@ const Cli = { ); } return { - clientId: properties.credentials[credential].clientId, - clientSecret: properties.credentials[credential].clientSecret, - tenant: properties.credentials[credential].tenant, eid: properties.credentials[credential].eid, mid: properties.credentials[credential].businessUnits[businessUnit], businessUnit: businessUnit, @@ -150,53 +221,57 @@ const Cli = { return null; } }, + /** * helps select the right credential in case of bad initial input * - * @param {object} properties config file's json + * @param {Mcdevrc} properties config file's json * @param {string} [credential] name of valid credential * @param {boolean} [isCredentialOnly] don't ask for BU if true * @param {boolean} [allowAll] Offer ALL as option in BU selection - * @returns {Promise<Array>} selected credential/BU combo + * @returns {Promise.<{businessUnit:string, credential:string}>} selected credential/BU combo */ async _selectBU(properties, credential, isCredentialOnly, allowAll) { const credList = []; const buList = []; - const questions = []; - const allBUsAnswer = '* (All BUs)'; + const allBUsAnswer = { value: '*', name: '* (All BUs)' }; + const answer = {}; + // no proper credential nor BU was given. ask for credential first if (!credential) { for (const cred in properties.credentials) { if (Object.keys(properties.credentials[cred].businessUnits).length) { // only add credentials that have BUs - credList.push(cred); + const credential = { value: cred, name: cred }; + if ( + !isCredentialOnly && + (!properties.credentials[cred]?.businessUnits || + !Object.keys(properties.credentials[cred].businessUnits).length) + ) { + credential.disabled = 'No Business Units defined'; + } + credList.push(credential); } } - questions.push({ - type: 'list', - name: 'credential', + answer.credential = await select({ message: 'Please select the credential you were looking for:', choices: credList, - // eslint-disable-next-line require-jsdoc - filter: function (answer) { - if (!isCredentialOnly) { - for (const bu in properties.credentials[answer].businessUnits) { - buList.push(bu); - } - if (!buList.length) { - // unlikely error as we are filtering for this already while creating credList - throw new Error('No Business Unit defined for this credential'); - } else if (allowAll) { - // add ALL option to beginning of list - buList.unshift(allBUsAnswer); - } - } - return answer; - }, }); + if (!isCredentialOnly) { + for (const bu in properties.credentials[answer.credential].businessUnits) { + buList.push({ value: bu, name: bu }); + } + if (!buList.length) { + // unlikely error as we are filtering for this already while creating credList + throw new Error('No Business Unit defined for this credential'); + } else if (allowAll) { + // add ALL option to beginning of list + buList.unshift(allBUsAnswer); + } + } } else if (credential) { for (const bu in properties.credentials[credential].businessUnits) { - buList.push(bu); + buList.push({ value: bu, name: bu }); } if (!buList.length) { // that could only happen if config is faulty @@ -207,91 +282,72 @@ const Cli = { } } if ((credential && buList.length) || (!credential && !isCredentialOnly)) { - questions.push({ - type: 'list', - name: 'businessUnit', + answer.businessUnit = await select({ message: 'Please select the right BU:', choices: buList, }); } - let responses = null; - if (questions.length) { - try { - responses = await new Promise((resolve) => { - inquirer - .prompt(questions) - .then((answers) => { - resolve(answers); - }) - .catch((err) => { - Util.logger.error(err); - }); - }); - } catch (e) { - Util.logger.info(e); - } - if (responses.businessUnit && responses.businessUnit === allBUsAnswer) { - // remove textual explanation of * - responses.businessUnit = '*'; - } - } else { + if (!answer || !Object.keys(answer).length) { throw new Error('credentials / BUs not configured'); } - return responses; + return answer; }, + /** * helper around _askCredentials * - * @param {object} properties from config file + * @param {Mcdevrc} properties from config file * @param {string} [credName] name of credential that needs updating - * @param {Object} [skipInteraction] signals what to insert automatically for things usually asked via wizard - * @param {String} skipInteraction.clientId client id of installed package - * @param {String} skipInteraction.clientSecret client id of installed package - * @param {String} skipInteraction.tenant client id of installed package - * @param {String} skipInteraction.credentialsName how you would like the credential to be named - * - * @returns {Promise<boolean|String>} success of refresh or credential name + * @param {boolean} [refreshBUs] if this was triggered by mcdev join, do not refresh BUs + * @returns {Promise.<boolean | string>} success of refresh or credential name */ - async _setCredential(properties, credName, skipInteraction) { + async _setCredential(properties, credName, refreshBUs = true) { + const skipInteraction = Util.skipInteraction; // Get user input - let credentialsGood = null; + /** @type {boolean} */ + let credentialsGood; let inputData; do { if (skipInteraction) { if ( - skipInteraction.clientId && - skipInteraction.clientSecret && - skipInteraction.tenant && - skipInteraction.credentialsName + skipInteraction.client_id && + skipInteraction.client_secret && + skipInteraction.auth_url && + skipInteraction.account_id && + skipInteraction.credentialName ) { - // assume skipInteraction=={clientId,clientSecret,tenant,credentialsName} + // assume skipInteraction=={client_id,client_secret,auth_url,credentialName} inputData = skipInteraction; } else { throw new Error( - '--skipInteraction flag found but missing required input for clientId,clientSecret,tenant,credentialsName' + '--skipInteraction flag found but not defined for all required inputs: client_id,client_secret,auth_url,account_id,credentialName' ); } } else { inputData = await this._askCredentials(properties, credName); } - // Replace defaults with user input - const buObject = { - clientId: inputData.clientId, - clientSecret: inputData.clientSecret, - tenant: inputData.tenant, - eid: null, - businessUnits: null, - }; // test if credentials are valid try { - await Util.getETClient(buObject); + await auth.saveCredential( + { + client_id: inputData.client_id, + client_secret: inputData.client_secret, + auth_url: inputData.auth_url, + account_id: Number.parseInt(inputData.account_id), + }, + inputData.credentialName + ); credentialsGood = true; - // update central config now that the credentials are verified - properties.credentials[inputData.credentialsName] = buObject; + properties.credentials[inputData.credentialName] = { + eid: Number.parseInt(inputData.account_id), + businessUnits: {}, + }; } catch (ex) { - Util.logger.error(ex.message); + Util.logger.error( + `We could not verify your credential due to a problem (${ex.message}). Please try again.` + ); credentialsGood = false; if (skipInteraction) { // break the otherwise infinite loop @@ -299,26 +355,28 @@ const Cli = { } } } while (!credentialsGood); - // Get all business units and add them to the properties - const status = await BuHelper.refreshBUProperties(properties, inputData.credentialsName); - return status ? inputData.credentialsName : status; + if (refreshBUs) { + // Get all business units and add them to the properties + const status = await BuHelper.refreshBUProperties(properties, inputData.credentialName); + return status ? inputData.credentialName : status; + } else { + return credentialsGood; + } }, /** - * helper for addExtraCredential() + * helper for {@link Cli.addExtraCredential} * - * @param {Object} properties from config file + * @param {Mcdevrc} properties from config file * @param {string} [credName] name of credential that needs updating - * @returns {Promise<Object>} credential info + * @returns {Promise.<object>} credential info */ async _askCredentials(properties, credName) { - const questions = []; + const responses = {}; if (!credName) { - questions.push({ - type: 'input', - name: 'credentialsName', + responses.credentialName = await input({ message: 'Credential name (your choice)', - // eslint-disable-next-line require-jsdoc + // eslint-disable-next-line jsdoc/require-jsdoc validate: function (value) { if (!value || value.trim().length < 2) { return 'Please enter at least 2 characters'; @@ -326,7 +384,7 @@ const Cli = { if (properties && properties.credentials[value]) { return `There already is an account with the name '${value}' in your config.`; } - const converted = encodeURIComponent(value).replace(/[*]/g, '_STAR_'); + const converted = encodeURIComponent(value).replaceAll(/[*]/g, '_STAR_'); if (value != converted) { return 'Please do not use any special chars'; } @@ -334,92 +392,89 @@ const Cli = { }, }); } - const tenantRegex = /^https:\/\/([\w-]*).(auth|soap|rest).marketingcloudapis.com[/]?$/iu; - questions.push( - { - type: 'input', - name: 'clientId', - message: 'Client Id', - // eslint-disable-next-line require-jsdoc - validate: function (value) { - if (!value || value.trim().length < 10) { - return 'Please enter valid client id'; - } - return true; - }, + const tenantRegex = + /^https:\/\/([\w-]{28})\.(auth|soap|rest)\.marketingcloudapis\.com[/]?$/iu; + responses.client_id = await input({ + message: 'Client Id', + // eslint-disable-next-line jsdoc/require-jsdoc + validate: function (value) { + if (!value || value.trim().length < 10) { + return 'Please enter valid client id'; + } + return true; }, - { - type: 'input', - name: 'clientSecret', - message: 'Client Secret', - // eslint-disable-next-line require-jsdoc - validate: function (value) { - if (!value || value.trim().length < 10) { - return 'Please enter valid client secret'; - } + }); + responses.client_secret = await input({ + message: 'Client Secret', + // eslint-disable-next-line jsdoc/require-jsdoc + validate: function (value) { + if (!value || value.trim().length < 10) { + return 'Please enter valid client secret'; + } + return true; + }, + }); + responses.auth_url = await input({ + message: 'Authentication Base URI', + validate: (value) => { + if (!value || value.trim().length < 10) { + return 'Please enter a valid tenant identifier'; + } else if (tenantRegex.test(value.trim())) { + // all good return true; - }, + } else { + return `Please copy the URI directly from the installed package's "API Integration" section. It looks like this: https://a1b2b3xy56z.auth.marketingcloudapis.com/`; + } }, - { - type: 'input', - name: 'tenant', - message: 'Authentication Base URI', - validate: (value) => { - if (!value || value.trim().length < 10) { - return 'Please enter a valid tenant identifier'; - } else if (!tenantRegex.test(value.trim())) { - return `Please copy the URI directly from the installed package's "API Integration" section. It looks like this: https://a1b2b3xy56z.auth.marketingcloudapis.com/`; - } else { - // all good - return true; - } - }, - } - ); - const responses = await new Promise((resolve) => { - inquirer.prompt(questions).then((answers) => { - resolve(answers); - }); + }); + responses.account_id = await number({ + message: 'MID of Parent Business Unit', }); // remove extra white space - responses.clientId = responses.clientId.trim(); - responses.clientSecret = responses.clientSecret.trim(); - responses.tenant = responses.tenant.trim(); - - // extract the tenant sub-domain from the URI; the format was already validated above - responses.tenant = responses.tenant.match(tenantRegex)[1]; + responses.client_id = responses.client_id.trim(); + responses.client_secret = responses.client_secret.trim(); + responses.auth_url = responses.auth_url.trim(); if (credName) { // if credential name was provided as parameter, we didn't ask the user for it - responses.credentialsName = credName; + responses.credentialName = credName; } return responses; }, + /** * allows updating the metadata types that shall be retrieved - * @param {object} properties config file's json - * @param {object} properties.metaDataTypes - - * @param {String[]} properties.metaDataTypes.retrieve list of currently retrieved types - * @param {String[]} [setTypesArr] skip user prompt and overwrite with this list if given - * @returns {Promise<void>} - + * + * @param {Mcdevrc} properties config file's json + * @param {string[]} [setTypesArr] skip user prompt and overwrite with this list if given + * @returns {Promise.<void>} - */ async selectTypes(properties, setTypesArr) { - let responses; - if (!setTypesArr) { - if (Util.logger.level !== 'debug') { - Util.logger.info( - 'Run mcdev selectTypes --debug if you need to use "disabled" types.' - ); - } else { + let selectedTypes; + if (setTypesArr) { + selectedTypes = setTypesArr; + } else { + if (Util.logger.level === 'debug') { Util.logger.warn( 'Debug mode enabled. Allowing selection of "disabled" types. Please be aware that these might be unstable.' ); + } else { + Util.logger.info( + 'Run mcdev selectTypes --debug if you need to use "disabled" types.' + ); } const flattenedDefinitions = []; for (const el in MetadataDefinitions) { + if (MetadataDefinitions[el].type === '') { + // dont offer wrapper types like TransactionalMessage which don't have a value in "type" + continue; + } // if subtypes on metadata (eg. Assets) then add each nested subtype - if (MetadataDefinitions[el].subTypes) { + if ( + MetadataDefinitions[el].subTypes && + Array.isArray(MetadataDefinitions[el].typeRetrieveByDefault) + ) { for (const subtype of MetadataDefinitions[el].subTypes) { flattenedDefinitions.push({ typeName: @@ -446,12 +501,11 @@ const Cli = { name: def.typeName + (Util.logger.level === 'debug' && !def.typeRetrieveByDefault - ? ' \x1b[1;30;40m(non-default)\u001b[0m' + ? ' \x1B[1;30;40m(non-default)\u001B[0m' : ''), value: def.type, - disabled: !(Util.logger.level === 'debug' || def.typeRetrieveByDefault) - ? 'disabled' - : false, + disabled: + Util.logger.level === 'debug' || def.typeRetrieveByDefault ? false : 'disabled', // subtypes can be activated through their main type checked: properties.metaDataTypes.retrieve.includes(def.type) || @@ -477,79 +531,82 @@ const Cli = { } return 0; }); - // add end-of-list marker - typeChoices.push(new inquirer.Separator(' ==== ')); - - const questions = [ - { - type: 'checkbox', - message: 'Select Metadata types for retrieval', - name: 'selectedTypes', - pageSize: 10, - choices: typeChoices, - }, - ]; - responses = await new Promise((resolve) => { - inquirer.prompt(questions).then((answers) => { - resolve(answers); - }); + selectedTypes = await checkbox({ + message: 'Select Metadata types for retrieval', + pageSize: 10, + choices: [...typeChoices, new Separator(' ==== ')], }); - } else { - responses = { - selectedTypes: setTypesArr, - }; } - if (responses.selectedTypes) { - this._summarizeSubtypes(responses, 'asset'); + if (selectedTypes) { + selectedTypes = Util.summarizeSubtypes('typeRetrieveByDefault', selectedTypes); // update config - properties.metaDataTypes.retrieve = responses.selectedTypes; + properties.metaDataTypes.retrieve = selectedTypes; await File.saveConfigFile(properties); } }, - /** - * helper for this.selectTypes() that converts subtypes back to main type if all and only defaults were selected - * this keeps the config automatically upgradable when we add new subtypes or change what is selected by default - * @param {Object} responses wrapper object for respones - * @param {String[]} responses.selectedTypes what types the user selected - * @param {String} type metadata type - * @returns {void} - */ - _summarizeSubtypes(responses, type) { - const selectedAssetSubtypes = responses.selectedTypes.filter((str) => - str.includes(type + '-') - ); - if ( - selectedAssetSubtypes.length === MetadataDefinitions[type].typeRetrieveByDefault.length - ) { - const nonDefaultSelectedAssetSubtypes = selectedAssetSubtypes - .map((subtype) => subtype.replace(type + '-', '')) - .filter( - (subtype) => !MetadataDefinitions[type].typeRetrieveByDefault.includes(subtype) - ); - if (!nonDefaultSelectedAssetSubtypes.length) { - // found all defaults and nothing else. replace with main type - responses.selectedTypes = responses.selectedTypes.filter( - (str) => !str.includes(type + '-') - ); - - responses.selectedTypes.push(type); - responses.selectedTypes.sort(); - } - } - }, /** * shows metadata type descriptions - * @returns {void} - + * + * @returns {ExplainType[]} list of supported types with their apiNames */ explainTypes() { - // overwrites default layout of console.table - require('console.table'); + /** @type {ExplainType[]} */ + const json = []; + const apiNameArr = Object.keys(MetadataDefinitions); + + for (const apiName of apiNameArr) { + const details = MetadataDefinitions[apiName]; + if (details.type === '') { + // skip wrapper types like TransactionalMessage which don't have a value in "type" + continue; + } + const supportCheckClass = apiName.startsWith('transactional') + ? TransactionalMessage + : MetadataTypeInfo[apiName]; + json.push({ + name: details.typeName, + apiName: details.type, + retrieveByDefault: details.typeRetrieveByDefault, + supports: { + retrieve: Object.prototype.hasOwnProperty.call(supportCheckClass, 'retrieve'), + create: Object.prototype.hasOwnProperty.call(supportCheckClass, 'create'), + update: Object.prototype.hasOwnProperty.call(supportCheckClass, 'update'), + delete: Object.prototype.hasOwnProperty.call(supportCheckClass, 'deleteByKey'), + changeKey: + supportCheckClass.definition.keyIsFixed === false && + supportCheckClass.definition.keyField !== + supportCheckClass.definition.idField && + supportCheckClass.definition.fields[supportCheckClass.definition.keyField] + .isUpdateable && + Object.prototype.hasOwnProperty.call(supportCheckClass, 'update'), + buildTemplate: Object.prototype.hasOwnProperty.call( + supportCheckClass, + 'create' + ), // supported for all types that can be created + retrieveAsTemplate: Object.prototype.hasOwnProperty.call( + supportCheckClass, + 'retrieveAsTemplate' + ), + }, + description: details.typeDescription, + }); + } + if (Util.OPTIONS.json) { + if (Util.OPTIONS.loggerLevel !== 'error') { + console.log(JSON.stringify(json, null, 2)); // eslint-disable-line no-console + } + return json; + } const typeChoices = []; for (const el in MetadataDefinitions) { - if (MetadataDefinitions[el].subTypes) { + if (MetadataDefinitions[el].type === '') { + // skip wrapper types like TransactionalMessage which don't have a value in "type" + continue; + } + if (MetadataDefinitions[el].subTypes && MetadataDefinitions[el].extendedSubTypes) { // used for assets to show whats available by default typeChoices.push({ Name: MetadataDefinitions[el].typeName, @@ -560,9 +617,11 @@ const Cli = { for (const subtype of MetadataDefinitions[el].subTypes) { lastCountdown--; const subTypeRetrieveByDefault = + Array.isArray(MetadataDefinitions[el].typeRetrieveByDefault) && MetadataDefinitions[el].typeRetrieveByDefault.includes(subtype); + const definition = - ' ' + MetadataDefinitions[el].extendedSubTypes[subtype].join(', '); + ' ' + MetadataDefinitions[el].extendedSubTypes?.[subtype]?.join(', '); typeChoices.push({ Name: MetadataDefinitions[el].typeName.replace('-[Subtype]', ': ') + subtype, @@ -570,7 +629,7 @@ const Cli = { (lastCountdown > 0 ? '├ ' : '└ ') + (subTypeRetrieveByDefault ? 'yes' : '-'), Description: - definition.length > 90 ? definition.substr(0, 90) + '...' : definition, + definition.length > 90 ? definition.slice(0, 90) + '...' : definition, }); } // change leading symbol of last subtype to close the tree visually @@ -592,8 +651,11 @@ const Cli = { } return 0; }); - console.table(typeChoices); + if (Util.OPTIONS.loggerLevel !== 'error') { + console.table(typeChoices); // eslint-disable-line no-console + } + return json; }, }; -module.exports = Cli; +export default Cli; diff --git a/lib/util/config.js b/lib/util/config.js new file mode 100644 index 000000000..b1423ac5b --- /dev/null +++ b/lib/util/config.js @@ -0,0 +1,332 @@ +import { Util } from './util.js'; +import File from './file.js'; +import { confirm } from '@inquirer/prompts'; +import semver from 'semver'; +import path from 'node:path'; +import { fileURLToPath } from 'node:url'; +const __dirname = path.dirname(fileURLToPath(import.meta.url)); + +/** + * @typedef {import('../../types/mcdev.d.js').AuthObject} AuthObject + * @typedef {import('../../types/mcdev.d.js').BuObject} BuObject + * @typedef {import('../../types/mcdev.d.js').Cache} Cache + * @typedef {import('../../types/mcdev.d.js').CodeExtract} CodeExtract + * @typedef {import('../../types/mcdev.d.js').CodeExtractItem} CodeExtractItem + * @typedef {import('../../types/mcdev.d.js').DeltaPkgItem} DeltaPkgItem + * @typedef {import('../../types/mcdev.d.js').Mcdevrc} Mcdevrc + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItem} MetadataTypeItem + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItemDiff} MetadataTypeItemDiff + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItemObj} MetadataTypeItemObj + * @typedef {import('../../types/mcdev.d.js').MetadataTypeMap} MetadataTypeMap + * @typedef {import('../../types/mcdev.d.js').MetadataTypeMapObj} MetadataTypeMapObj + * @typedef {import('../../types/mcdev.d.js').MultiMetadataTypeList} MultiMetadataTypeList + * @typedef {import('../../types/mcdev.d.js').MultiMetadataTypeMap} MultiMetadataTypeMap + * @typedef {import('../../types/mcdev.d.js').SoapRequestParams} SoapRequestParams + * @typedef {import('../../types/mcdev.d.js').TemplateMap} TemplateMap + * @typedef {import('../../types/mcdev.d.js').TypeKeyCombo} TypeKeyCombo + */ + +/** + * Central class for loading and validating properties from config and auth + */ +const config = { + properties: null, + + /** + * loads central properties from config file + * + * @param {boolean} [silent] omit throwing errors and print messages; assuming not silent if not set + * @param {boolean} [isInit] don't tell the user to run init + * @returns {Promise.<Mcdevrc>} central properties object + */ + async getProperties(silent, isInit) { + if (config.properties) { + return config.properties; + } + if (await File.pathExists(Util.configFileName)) { + try { + config.properties = await File.readJSON(Util.configFileName); + if (!isInit && !(await this.checkProperties(config.properties, silent))) { + return; + } + } catch (ex) { + Util.logger.error(`${ex.code}: ${ex.message}`); + return; + } + if (await File.pathExists(Util.authFileName)) { + let auth; + try { + auth = await File.readJSON(Util.authFileName); + } catch (ex) { + Util.logger.error(`${ex.code}: ${ex.message}`); + return; + } + + if (!auth) { + const err = `${Util.authFileName} is not set up correctly.`; + Util.logger.error(err); + throw new Error(err); + } + for (const cred in config.properties.credentials) { + if (auth[cred]) { + if ( + config.properties.credentials[cred].eid != auth[cred].account_id && + !silent + ) { + Util.logger.error( + `'${cred}' found in ${Util.configFileName} (${typeof config + .properties.credentials[cred].eid} ${ + config.properties.credentials[cred].eid + }) and ${Util.authFileName} (${typeof auth[cred].account_id} ${ + auth[cred].account_id + }) have a Enterprise ID mismatch. Please check.` + ); + return; + } + // TODO add auth checks #294 + } else if (!silent) { + Util.logger.error( + `'${cred}' found in ${Util.configFileName} but not in ${Util.authFileName}. Please run 'mcdev init' to provide the missing credential details.` + ); + return; + } + } + } else if (!silent && !isInit) { + Util.logger.error( + `${Util.authFileName} not found. Please run 'mcdev init' to provide the missing credential details.` + ); + return; + } + } else if (!silent && !isInit) { + Util.logger.error(`Could not find ${Util.configFileName} in ${process.cwd()}.`); + Util.logger.error(`Run 'mcdev init' to initialize your project.\n`); + } + return config.properties; + }, + + /** + * check if the config file is correctly formatted and has values + * + * @param {Mcdevrc} properties javascript object in .mcdevrc.json + * @param {boolean} [silent] set to true for internal use w/o cli output + * @returns {Promise.<boolean | string[]>} file structure ok OR list of fields to be fixed + */ + async checkProperties(properties, silent) { + if (!(await File.pathExists(Util.configFileName))) { + Util.logger.error(`Could not find ${Util.configFileName} in ${process.cwd()}.`); + Util.logger.error(`Run 'mcdev init' to initialize your project.\n`); + return false; + } + if (!(await File.pathExists(Util.authFileName))) { + Util.logger.error(`Could not find ${Util.authFileName} in ${process.cwd()}.`); + Util.logger.error(`Run 'mcdev init' to initialize your project.\n`); + return false; + } + if (!properties) { + // assume there was an error loading the config failed + return false; + } + + // check if user is running older (ignores patches) mcdev version than whats saved to the config + if (properties.version && semver.gt(properties.version, Util.packageJsonMcdev.version)) { + Util.logger.error( + `Your Accenture SFMC DevTools version ${Util.packageJsonMcdev.version} is lower than your project's config version ${properties.version}` + ); + if (Util.skipInteraction) { + // print guidance for extension users + Util.logger.error( + `Run 'npm install -g mcdev@${properties.version}' now to fix this.` + ); + return false; + } + + const runUpgradeNow = await confirm({ + message: `Do you want to run 'npm install -g mcdev@${properties.version}' now? This may take a few minutes.`, + default: true, + }); + if (runUpgradeNow) { + // use _execSync here to avoid a circular dependency + Util.execSync('npm', ['install', '-g', `mcdev@${properties.version}`]); + } + return false; + } + + // check config properties + const defaultProps = await this.getDefaultProperties(); + const errorMsgs = []; + const solutionSet = new Set(); + const missingFields = []; + for (const key in defaultProps) { + if (Object.prototype.hasOwnProperty.call(defaultProps, key)) { + if (Object.prototype.hasOwnProperty.call(properties, key)) { + if (!silent && key === 'credentials') { + if (Object.keys(properties.credentials)) { + for (const cred in properties.credentials) { + if (cred.includes('/') || cred.includes('\\')) { + errorMsgs.push( + `Credential names may not includes slashes: ${cred}` + ); + solutionSet.add('Apply manual fix in your config.'); + } + if ( + !properties.credentials[cred].eid || + properties.credentials[cred].eid === 0 + ) { + errorMsgs.push(`invalid account_id (EID) on ${cred}`); + solutionSet.add(`Run 'mcdev init ${cred}'`); + } + let i = 0; + for (const buName in properties.credentials[cred].businessUnits) { + if (buName.includes('/') || buName.includes('\\')) { + errorMsgs.push( + `Business Unit names may not includes slashes: ${cred}: ${buName}` + ); + solutionSet.add(`Run 'mcdev reloadBUs ${cred}'`); + } + if ( + Object.prototype.hasOwnProperty.call( + properties.credentials[cred].businessUnits, + buName + ) && + properties.credentials[cred].businessUnits[buName] !== 0 + ) { + i++; + } + } + if (!i) { + errorMsgs.push(`no Business Units defined`); + solutionSet.add(`Run 'mcdev reloadBUs ${cred}'`); + } + } + } else { + errorMsgs.push(`no Credential defined`); + } + } else if (['directories', 'metaDataTypes', 'options'].includes(key)) { + for (const subkey in defaultProps[key]) { + if ( + Object.prototype.hasOwnProperty.call(defaultProps[key], subkey) && + !Object.prototype.hasOwnProperty.call(properties[key], subkey) + ) { + errorMsgs.push( + `${key}.${subkey} missing. Default value (${ + Array.isArray(defaultProps[key][subkey]) + ? 'Array' + : typeof defaultProps[key][subkey] + }): ${typeof defaultProps[key][subkey] === 'object' ? JSON.stringify(defaultProps[key][subkey]) : defaultProps[key][subkey]}` + ); + solutionSet.add( + `Run 'mcdev upgrade' to fix missing or changed configuration options` + ); + missingFields.push(`${key}.${subkey}`); + } else if (subkey === 'deployment') { + for (const dkey in defaultProps[key][subkey]) { + if ( + Object.prototype.hasOwnProperty.call( + defaultProps[key][subkey], + dkey + ) && + !Object.prototype.hasOwnProperty.call( + properties[key][subkey], + dkey + ) + ) { + errorMsgs.push( + `${key}.${subkey} missing. Default value (${ + Array.isArray(defaultProps[key][subkey][dkey]) + ? 'Array' + : typeof defaultProps[key][subkey][dkey] + }): ${defaultProps[key][subkey][dkey]}` + ); + solutionSet.add( + `Run 'mcdev upgrade' to fix missing or changed configuration options` + ); + missingFields.push(`${key}.${subkey}.${dkey}`); + } + } + } + } + } + } else { + errorMsgs.push(`${key}{} missing`); + solutionSet.add( + `Run 'mcdev upgrade' to fix missing or changed configuration options` + ); + missingFields.push(key); + } + } + } + // check if project config version is outdated compared to user's mcdev version + if ( + !properties.version || + (![null, 'patch'].includes( + semver.diff(Util.packageJsonMcdev.version, properties.version) + ) && + semver.gt(Util.packageJsonMcdev.version, properties.version)) + ) { + errorMsgs.push( + `Your project's config version ${properties.version} is lower than your Accenture SFMC DevTools version ${Util.packageJsonMcdev.version}` + ); + solutionSet.add(`Run 'mcdev upgrade' to ensure optimal performance`); + missingFields.push('version'); + } + if (silent) { + return missingFields; + } else { + if (errorMsgs.length) { + const errorMsgOutput = [ + `Found problems in your ./${Util.configFileName} that you need to fix first:`, + ]; + for (const msg of errorMsgs) { + errorMsgOutput.push(' - ' + msg); + } + Util.logger.error(errorMsgOutput.join('\n')); + Util.logger.info( + [ + 'Here is what you can do to fix these issues:', + ...Array.from(solutionSet), + ].join('\n- ') + ); + if (Util.skipInteraction) { + // print guidance for extension users + Util.logger.error(`Run 'mcdev upgrade' now to fix this.`); + return false; + } + const runUpgradeNow = await confirm({ + message: `Do you want to run 'mcdev upgrade' now?`, + default: true, + }); + if (runUpgradeNow) { + // use _execSync here to avoid a circular dependency + Util.execSync('mcdev', ['upgrade']); + } + return false; + } else { + return true; + } + } + }, + + /** + * defines how the properties.json should look like + * used for creating a template and for checking if variables are set + * + * @returns {Promise.<Mcdevrc>} default properties + */ + async getDefaultProperties() { + const configFileName = path.resolve(__dirname, Util.boilerplateDirectory, 'config.json'); + if (!(await File.pathExists(configFileName))) { + Util.logger.debug(`Default config file not found in ${configFileName}`); + return; + } + const defaultProperties = await File.readJSON(configFileName); + // set default name for parent BU + defaultProperties.credentials.default.businessUnits[Util.parentBuName] = 0; + // set default retrieve values + defaultProperties.metaDataTypes.retrieve = Util.getTypeChoices('typeRetrieveByDefault'); + // set default retrieve values + defaultProperties.metaDataTypes.createDeltaPkg = Util.getTypeChoices('typeCdpByDefault'); + + return defaultProperties; + }, +}; +export default config; diff --git a/lib/util/devops.js b/lib/util/devops.js index f05bc95a8..6cc8b6784 100644 --- a/lib/util/devops.js +++ b/lib/util/devops.js @@ -1,37 +1,64 @@ -const File = require('./file'); -const path = require('path'); -const inquirer = require('inquirer'); -const Util = require('./util'); -const git = require('simple-git/promise')(); -const MetadataType = require('../MetadataTypeInfo'); -const jsonToTable = require('json-to-table'); +import File from './file.js'; +import path from 'node:path'; +import { select, confirm, Separator } from '@inquirer/prompts'; +import { Util } from './util.js'; +import Cli from './cli.js'; +import { simpleGit } from 'simple-git'; +const git = simpleGit(); +import mcdev from '../index.js'; +import Builder from '../Builder.js'; +import MetadataType from '../MetadataTypeInfo.js'; +import jsonToTable from 'json-to-table'; +import pLimit from 'p-limit'; +import cliProgress from 'cli-progress'; + /** - * DevOps helper class + * @typedef {import('../../types/mcdev.d.js').AuthObject} AuthObject + * @typedef {import('../../types/mcdev.d.js').BuObject} BuObject + * @typedef {import('../../types/mcdev.d.js').Cache} Cache + * @typedef {import('../../types/mcdev.d.js').CodeExtract} CodeExtract + * @typedef {import('../../types/mcdev.d.js').CodeExtractItem} CodeExtractItem + * @typedef {import('../../types/mcdev.d.js').DeltaPkgItem} DeltaPkgItem + * @typedef {import('../../types/mcdev.d.js').Mcdevrc} Mcdevrc + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItem} MetadataTypeItem + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItemDiff} MetadataTypeItemDiff + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItemObj} MetadataTypeItemObj + * @typedef {import('../../types/mcdev.d.js').MetadataTypeMap} MetadataTypeMap + * @typedef {import('../../types/mcdev.d.js').MetadataTypeMapObj} MetadataTypeMapObj + * @typedef {import('../../types/mcdev.d.js').MultiMetadataTypeList} MultiMetadataTypeList + * @typedef {import('../../types/mcdev.d.js').MultiMetadataTypeMap} MultiMetadataTypeMap + * @typedef {import('../../types/mcdev.d.js').SoapRequestParams} SoapRequestParams + * @typedef {import('../../types/mcdev.d.js').TemplateMap} TemplateMap + * @typedef {import('../../types/mcdev.d.js').TypeKeyCombo} TypeKeyCombo + * @typedef {import('../../types/mcdev.d.js').BuildFilter} BuildFilter */ +/** + * DevOps helper class + */ const DevOps = { /** * Extracts the delta between a commit and the current state for deployment. * Interactive commit selection if no commits are passed. - * @param {Object} properties central properties object - * @param {String} [range] git commit range + * + * @param {Mcdevrc} properties central properties object + * @param {string} [range] git commit range * @param {boolean} [saveToDeployDir] if true, copy metadata changes into deploy directory - * @param {String} [filterPaths] filter file paths that start with any specified path (comma separated) - * @returns {Promise<Object>} - + * @param {string} [filterPathsCSV] filter file paths that start with any specified path (comma separated) + * @param {number} [commitHistory] cli option to override default commit history value in config + * @returns {Promise.<DeltaPkgItem[]>} - */ - async createDeltaPkg(properties, range, saveToDeployDir, filterPaths) { + async getDeltaList(properties, range, saveToDeployDir, filterPathsCSV, commitHistory) { const rangeUserInput = range; - Util.logger.info('Create Delta Package ::'); - if (filterPaths) { - filterPaths = filterPaths.split(',').map((filePath) => - path - .normalize(properties.directories.retrieve + filePath) - .split('\\') - .join('/') - ); - } else { - filterPaths = [properties.directories.retrieve]; - } + const filterPaths = filterPathsCSV + ? filterPathsCSV.split(',').map( + (filePath) => + path + .normalize(properties.directories.retrieve + filePath) + .split('\\') + .join('/') + '/' + ) + : [properties.directories.retrieve]; if (range) { if (!range.includes('..')) { // we limit the user here somewhat by always comparing to current branch if no range was given @@ -46,29 +73,26 @@ const DevOps = { // Current commit is skipped due to no changes const commits = await git.log([ '--skip=1', - `-${properties.options.deployment.commitHistory || 10}`, + `-${commitHistory || properties.options.deployment.commitHistory || 10}`, ]); - const display = commits.all.map((commit) => ({ - name: commit.date + ' / ' + commit.message + ' / ' + commit.author_name, + /** @type {({value: string, name?: string, description?: string, disabled?: boolean | string} | Separator)[]} */ + const choices = commits.all.map((commit) => ({ + name: + commit.date.split('T').join(' ').split('+')[0] + + ' / ' + + commit.message + + ' / ' + + commit.author_name, value: commit.hash, })); - display.push(new inquirer.Separator(' ==== ')); + choices.push(new Separator(' ==== ')); - const questions = [ - { - type: 'list', - message: 'Select base commit for comparison with current commit', - name: 'commit', - pageSize: 10, - choices: display, - }, - ]; - const responses = await new Promise((resolve) => { - inquirer.prompt(questions).then((answers) => { - resolve(answers); - }); + const baseCommit = await select({ + message: 'Select base commit for comparison with current commit', + pageSize: 10, + choices: choices, }); - range = `${responses.commit}..HEAD`; + range = `${baseCommit}..HEAD`; } const metadata = {}; @@ -78,18 +102,35 @@ const DevOps = { 'add/update': 0, move: 0, }; - const delta = (await git.diffSummary([range])).files + let diffSummary; + try { + diffSummary = await git.diffSummary([range]); + } catch (ex) { + const error = ex.message.startsWith('fatal: ambiguous argument') + ? new Error( + `Make sure you checked out the branches mentioned in your git range (${rangeUserInput})` + ) + : ex; + throw error; + } + Util.logger.info(`Found ${diffSummary.files.length} changed files in the commit range`); + /** + * @type {DeltaPkgItem[]} + */ + // first, process everything that can be done synchronously here + const deltaSync = diffSummary.files // populate additional info for all changed files - .map((file) => { + .map((/** @type {DeltaPkgItem} */ file) => { // If file was moved it's path needs to be parsed file.moved = file.file.includes('=>'); if (file.moved) { const p = file.file; + // TODO: rewrite remaining substring() to slice() const paths = { - base: p.substring(0, p.indexOf('{')), - before: p.substring(p.indexOf('{') + 1, p.indexOf('=>') - 1), - after: p.substring(p.indexOf('=>') + 3, p.indexOf('}')), - end: p.substring(p.indexOf('}') + 1), + base: p.slice(0, Math.max(0, p.indexOf('{'))), + before: p.substring(p.indexOf('{') + 1, p.indexOf('=>') - 1), // eslint-disable-line unicorn/prefer-string-slice + after: p.substring(p.indexOf('=>') + 3, p.indexOf('}')), // eslint-disable-line unicorn/prefer-string-slice + end: p.slice(Math.max(0, p.indexOf('}') + 1)), }; file.fromPath = path .normalize(`${paths.base}${paths.before}${paths.end}`) @@ -105,77 +146,120 @@ const DevOps = { } // get metadata type from file name - file.type = path.basename(file.file).split('.')[1].split('-').shift(); + file.type = file.file.split('/')[3]; return file; }) // Filter to only handle files that start with at least one of the passed filterPaths. // ! Filter happens after initial parse, because if file was moved its new path has to be calculated .filter((file) => filterPaths.some((path) => file.file.startsWith(path))) + .filter((file) => !file.file.endsWith('.error.log')) + .filter((file) => !file.file.endsWith('.md')) // ensure badly named files on unsupported metadata types are not in our subset - .filter((file) => { - if (!MetadataType[file.type]) { + .filter((/** @type {DeltaPkgItem} */ file) => { + if (MetadataType[file.type]) { + return true; + } else { Util.logger.debug( `Unknown metadata-type found for (${file.file}): ` + file.type ); return false; - } else { - return true; - } - }) - .map((file) => { - // Gets external key based on file name und the assumption that filename = externalKey - if (file.type === 'folder') { - file.externalKey = null; - file.name = path.basename(file.file).split('.').shift(); - } else { - file.externalKey = path.basename(file.file).split('.').shift(); - file.name = null; } + }); - // Check if file doesn't exist in reported path, that means it was a git deletion - // TODO: improve git action detection by switching from diffSummary to diff with --summary result parsing - if (!File.existsSync(file.file)) { - file.gitAction = 'delete'; - } else if (file.moved) { - file.gitAction = 'move'; - } else { - file.gitAction = 'add/update'; - } - gitActionsCounter[file.gitAction]++; - file._credential = file.file.split('/')[1]; - file._businessUnit = file.file.split('/')[2]; + Util.logger.info( + `Identified ${deltaSync.length} relevant file changes after filtering file types and folders. Processing related metadata now.` + ); + // second, we need to do asynchronous file operations + + const extendedBar = new cliProgress.SingleBar( + { + format: ' Processing changes [{bar}] {percentage}% | {value}/{total}', + }, + cliProgress.Presets.shades_classic + ); + extendedBar.start(deltaSync.length, 0); + const rateLimit = pLimit(10); - // Parse retrieve directory to also populate the name field (not possible for deleted files) - if (file.gitAction !== 'delete' && file.type !== 'folder') { - // folders are saved with their name as file-name, not with their key, hence this section can be skipped for folders - const buPath = `${properties.directories.retrieve}/${file._credential}/${file._businessUnit}/`; - if (!metadata[file._credential]) { - metadata[file._credential] = {}; + /** + * @type {DeltaPkgItem[]} + */ + const delta = await Promise.all( + deltaSync.map((/** @type {DeltaPkgItem} */ file) => + rateLimit(async () => { + // Gets external key based on file name und the assumption that filename = externalKey + if (file.type === 'folder') { + file.externalKey = null; + file.name = path.basename(file.file).split('.').shift(); + } else { + // find the key in paths like: + // - retrieve/cred/bu/asset/block/016aecc7-7063-4b78-93f4-aa119ea933c7.asset-block-meta.html + // - retrieve/cred/bu/query/03efd5f1-ba1f-487a-9c9a-36aeb2ae5192.query-meta.sql + // assets have an additional folder level for their subtype + // keys could contain dots themselves + file.externalKey = file.file + .split('/') + [file.type === 'asset' ? 5 : 4].split('.') + .slice(0, -2) + .join('.'); + if (file.type === 'asset' && !file.externalKey) { + // retrieve/cred/bu/asset/message/emailkey/blocks/views.html.slots.[8maw2k7jnlb-5llcajmxaqa].asset-message-meta.html + file.externalKey = file.file.split('/')[5]; + } + file.name = null; } - if (!metadata[file._credential][file._businessUnit]) { - metadata[file._credential][file._businessUnit] = {}; + + // Check if file doesn't exist in reported path, that means it was a git deletion + // TODO: improve git action detection by switching from diffSummary to diff with --summary result parsing + if (!(await File.pathExists(file.file))) { + file.gitAction = 'delete'; + } else if (file.moved) { + file.gitAction = 'move'; + } else { + file.gitAction = 'add/update'; } - if (!metadata[file._credential][file._businessUnit][file.type]) { - try { - MetadataType[file.type].readBUMetadataForType( - buPath, - false, - metadata[file._credential][file._businessUnit] - ); - } catch (ex) { - // silently catch directory-not-found errors here - Util.logger.debug(ex.message); + gitActionsCounter[file.gitAction]++; + file._credential = file.file.split('/')[1]; + file._businessUnit = file.file.split('/')[2]; + + // Parse retrieve directory to also populate the name field (not possible for deleted files) + if (file.gitAction !== 'delete' && file.type !== 'folder') { + // folders are saved with their name as file-name, not with their key, hence this section can be skipped for folders + const buPath = `${properties.directories.retrieve}/${file._credential}/${file._businessUnit}/`; + if (!metadata[file._credential]) { + metadata[file._credential] = {}; + } + if (!metadata[file._credential][file._businessUnit]) { + metadata[file._credential][file._businessUnit] = {}; + } + if (!metadata[file._credential][file._businessUnit][file.type]) { + try { + await MetadataType[file.type].readBUMetadataForType( + buPath, + false, + metadata[file._credential][file._businessUnit] + ); + } catch (ex) { + // silently catch directory-not-found errors here + Util.logger.debug(ex.message); + } + } + const fileContent = + metadata[file._credential][file._businessUnit][file.type][ + file.externalKey + ]; + if (fileContent) { + file.name = fileContent[MetadataType[file.type].definition.nameField]; } } - const fileContent = - metadata[file._credential][file._businessUnit][file.type][file.externalKey]; - if (fileContent) { - file.name = fileContent[MetadataType[file.type].definition.nameField]; - } - } - return file; - }); + extendedBar.increment(); + return file; + }) + ) + ); + // stop the progress bar + extendedBar.stop(); + if ( !gitActionsCounter['add/update'] && !gitActionsCounter.move && @@ -183,37 +267,133 @@ const DevOps = { ) { Util.logger.warn( `- ❌ No changes found. Check what branch you are currently on and if the target branch name (${rangeUserInput}${ - range !== rangeUserInput ? ' converted to ' + range : '' + range === rangeUserInput ? '' : ' converted to ' + range }) was correct` ); return []; } // Write into delta.json to serve as documentation - File.writeJSONToFile(properties.directories.deltaPackage, 'delta_package', delta); - this.document(properties.directories.deltaPackage, delta); + const directoryDeltaPkg = 'logs/'; + await File.writeJSONToFile( + directoryDeltaPkg, + Util.logFileName + + '-delta_package-' + + filterPathsCSV.replaceAll(',', '-').replaceAll('/', '-'), + delta + ); + this.document(directoryDeltaPkg, filterPathsCSV, delta); Util.logger.info( `- ✔️ Identified changes: Add/Update=${gitActionsCounter['add/update']}, Move=${gitActionsCounter['move']}, Delete=${gitActionsCounter['delete']}` ); - if (gitActionsCounter.delete > 0) { + if (gitActionsCounter.move > 0 || gitActionsCounter.delete > 0) { Util.logger.warn( - 'Please note that deletions have to be done manually on the SFMC website.' + 'Deleted/Changed keys detected! Please note that re-keyed components should have their key changed as a pre-deployment step.' ); } Util.logger.info( - `Saved report in ${path.join(properties.directories.deltaPackage, 'delta_package.md')}` + `Saved report in ./${directoryDeltaPkg}${Util.logFileName}-delta_package.md` ); + // const deletedTypeKeys = {}; + // for (const file of delta.filter((file) => file.gitAction === 'delete')) { + // if (deletedTypeKeys[file.type]) { + // deletedTypeKeys[file.type].add(file.externalKey); + // } else { + // deletedTypeKeys[file.type] = new Set([file.externalKey]); + // } + // } + // for (const deletedType in deletedTypeKeys) { + // const keyArr = [...deletedTypeKeys[deletedType]]; + // Util.logger.warn(`Found deleted ${deletedType} keys: ${keyArr.join(', ')}`); + // } + // Copy filtered list of files into deploy directory + // only do that if we do not use templating if (saveToDeployDir) { - const copied = delta.map((file) => - File.copyFile( - file.file, - file.file.replace( - path.normalize(properties.directories.retrieve), - path.normalize(properties.directories.deploy) + // if templating is not used, we need to add related files to the delta package + const typeKeysMap = {}; + /** @type {Object.<string, BuObject>} */ + const buObjects = {}; + for (const file of delta) { + if (file.gitAction === 'delete' || file.type === 'folder') { + continue; + } + if (typeKeysMap[file.type]) { + typeKeysMap[file.type].push(file.externalKey); + } else { + typeKeysMap[file.type] = [file.externalKey]; + } + if (!buObjects[`${file._credential}/${file._businessUnit}`]) { + buObjects[`${file._credential}/${file._businessUnit}`] = + await Cli.getCredentialObject( + properties, + `${file._credential}/${file._businessUnit}` + ); + } + } + // a bit crude but works for now + for (const buObject of Object.values(buObjects)) { + for (const type in typeKeysMap) { + MetadataType[type].buObject = buObject; + MetadataType[type].properties = properties; + const additionalFiles = await MetadataType[type].getFilesToCommit( + typeKeysMap[type] + ); + if (additionalFiles?.length) { + delta.push( + ...additionalFiles + .map((filePath) => ({ + file: path.normalize(filePath).split('\\').join('/'), + type, + gitAction: 'add/update', + })) + .filter( + // avoid adding files that we already have in the list + (addFile) => + !delta.find((existFile) => existFile.file === addFile.file) + ) + ); + } + } + } + + let isPurgeDeployFolder; + if (!Util.skipInteraction) { + // deploy folder is in targets for definition creation + // recommend to purge their content first + isPurgeDeployFolder = await confirm({ + message: + 'Do you want to empty the deploy folder (ensures no files from previous deployments remain)?', + default: true, + }); + } + if (Util.skipInteraction || isPurgeDeployFolder) { + // Clear output folder structure for selected sub-type + for (const buObject of Object.values(buObjects)) { + await File.remove( + File.normalizePath([ + properties.directories.deploy, + buObject.credential, + buObject.businessUnit, + ]) + ); + } + } + + /** @type {Promise.<{status:'ok'|'skipped'|'failed', statusMessage:string, file:string}>[]} */ + const copied = delta + .filter((file) => !file.file.endsWith('.md')) // filter documentation files + .map((file) => + File.copyFileSimple( + file.file, + path + .normalize(file.file) + .replace( + path.normalize(properties.directories.retrieve), + path.normalize(properties.directories.deploy) + ) ) - ) - ); + ); const results = await Promise.all(copied); const failed = results.filter((result) => result.status === 'failed'); const skipped = results.filter((result) => result.status === 'skipped'); @@ -229,51 +409,348 @@ const DevOps = { } copied, ${skipped.length} skipped, ${failed.length} failed)` ); if (skipped.length > 0) { - skipped.forEach((file) => - Util.logger.debug(`Skipped - ${file.statusMessage} - ${file.file}`) - ); + for (const file of skipped) { + Util.logger.debug(`Skipped - ${file.statusMessage} - ${file.file}`); + } } if (failed.length > 0) { - failed.forEach((file) => - Util.logger.error(`Failed - ${file.statusMessage} - ${file.file}`) - ); + for (const file of failed) { + Util.logger.error(`Failed - ${file.statusMessage} - ${file.file}`); + } } } return delta; }, + + /** + * wrapper around DevOps.getDeltaList, Builder.buildTemplate and M + * + * @param {Mcdevrc} properties project config file + * @param {string} range git commit range + * @param {DeltaPkgItem[]} [diffArr] instead of running git diff the method can also get a list of files to process + * @param {number} [commitHistory] cli option to override default commit history value in config + * @returns {Promise.<DeltaPkgItem[]>} - + */ + async buildDeltaDefinitions(properties, range, diffArr, commitHistory) { + // check if sourceTargetMapping is valid + let sourceTargetMapping; + if (properties.options.deployment.branchSourceTargetMapping?.[range]) { + Util.logger.info(Util.getGrayMsg('Using branch specific sourceTargetMapping')); + sourceTargetMapping = properties.options.deployment.branchSourceTargetMapping[range]; + } else if ( + properties.options.deployment.sourceTargetMapping && + Object.keys(properties.options.deployment.sourceTargetMapping).length + ) { + Util.logger.info(Util.getGrayMsg('Using generic sourceTargetMapping')); + sourceTargetMapping = properties.options.deployment.sourceTargetMapping; + } else { + Util.logger.error('Bad configuration of options.deployment.sourceTargetMapping'); + return; + } + const sourceMarketListArr = Object.keys(sourceTargetMapping); + /** @type {DeltaPkgItem[]} */ + const deltaDeployAll = []; + for (const sourceML of sourceMarketListArr) { + // check if sourceTargetMapping has valid values + // #1 check source marketlist + try { + Util.verifyMarketList(sourceML, properties); + // remove potentially existing "description"-entry + delete properties.marketList[sourceML].description; + + const sourceMarketBuArr = Object.keys(properties.marketList[sourceML]).filter( + (key) => key !== 'filter' + ); + if (sourceMarketBuArr.length !== 1) { + throw new Error('Only 1 BU is allowed per source marketList'); + } + if ('string' !== typeof properties.marketList[sourceML][sourceMarketBuArr[0]]) { + throw new TypeError('Only 1 market per BU is allowed per source marketList'); + } + } catch (ex) { + Util.logger.error('Deployment Source: ' + ex.message); + return; + } + // #2 check corresponding target marketList + let targetML; + try { + targetML = sourceTargetMapping[sourceML]; + if ('string' !== typeof targetML) { + throw new TypeError( + 'Please define one target marketList per source in deployment.sourceTargetMapping (No arrays allowed)' + ); + } + Util.verifyMarketList(targetML, properties); + // remove potentially existing "description"-entry + delete properties.marketList[targetML].description; + } catch (ex) { + Util.logger.error('Deployment Target: ' + ex.message); + } + } + if (Util.OPTIONS.purge === true && sourceMarketListArr.length > 1) { + // if --purge was defined and there is more than one source-target mapping, execute the purge up front to avoid deleting the package that was created by a prior mapping in this same run + for (const sourceMlName of sourceMarketListArr) { + /** @type {string} */ + await Builder.purgeDeployFolderList(sourceTargetMapping[sourceMlName]); + } + Util.OPTIONS.purge = false; + } + + // all good let's loop a second time for actual execution + for (const sourceMlName of sourceMarketListArr) { + /** @type {string} */ + const targetMlName = sourceTargetMapping[sourceMlName]; + const sourceMarketLists = properties.marketList[sourceMlName]; + /** @type {string} */ + const sourceBU = Object.keys(sourceMarketLists).find((key) => key !== 'filter'); + // accept ["oneMarket"] or "oneMarket" for sourceMarket, but not ["oneMarket","secondMarket"] or [] + /** @type {string} */ + const sourceMarket = + Array.isArray(sourceMarketLists[sourceBU]) && + sourceMarketLists[sourceBU].length === 1 + ? sourceMarketLists[sourceBU][0] + : sourceMarketLists[sourceBU]; + if ('string' !== typeof sourceMarket) { + Util.logger.error( + 'Deployment Source market list needs to have a 1:1 BU-Market combo. Your value: ' + + sourceMarket + ); + // skip this source-target mapping + continue; + } + let delta; + try { + delta = Array.isArray(diffArr) + ? diffArr + : await DevOps.getDeltaList(properties, range, false, sourceBU, commitHistory); + } catch (ex) { + Util.logger.error(ex.message); + return; + } + // If only chaing templating and buildDefinition if required + if (!delta || delta.length === 0) { + // skip this source-target mapping + continue; + } + Util.logger.info('============='); + + // Put files into maps. One map with BU -> type -> file (for retrieveAsTemplate) + // Other map only with type -> file (for buildDefinitionBulk) + const buTypeDelta = {}; // for bt, with BU info + const deltaDeploy = delta + // Only template/build files that were added/updated/moved. no deletions + // ! doesn't work for folder, because their name parsing doesnt work at the moment + .filter((file) => file.gitAction !== 'delete' && file.name); + deltaDeployAll.push(...deltaDeploy); + for (const file of deltaDeploy) { + const buFrom = `${file._credential}/${file._businessUnit}`; + if (!buTypeDelta[buFrom]) { + // init object + /** @type {TypeKeyCombo} */ + buTypeDelta[buFrom] = {}; + } + if (!buTypeDelta[buFrom][file.type]) { + // init array + buTypeDelta[buFrom][file.type] = []; + } + if (!buTypeDelta[buFrom][file.type].includes(file.externalKey)) { + buTypeDelta[buFrom][file.type].push(file.externalKey); + } + } + for (const buFrom in buTypeDelta) { + for (const type of Object.keys(buTypeDelta[buFrom])) { + if ( + Array.isArray(properties.metaDataTypes.createDeltaPkg) && + !properties.metaDataTypes.createDeltaPkg.includes(type) + ) { + Util.logger.warn( + `Skipping ${type} for build based on config.metaDataTypes.createDeltaPkg: ${buTypeDelta[buFrom][type].join(', ')}` + ); + delete buTypeDelta[buFrom][type]; + } + } + // Run buildTemplate for each business unit for each type + await mcdev.build( + buFrom, + undefined, + buTypeDelta[buFrom], + [sourceMarket], + [targetMlName], + true, + sourceMarketLists.filter + ); + } + this._generateDeleteInstructions(delta, sourceMarket, properties, targetMlName); + } + if (!deltaDeployAll.length) { + Util.logger.error( + '- ❌ No Templates or Deploy Definitions created. Check if you expected no changes.' + ); + } + return deltaDeployAll; + }, + /** * create markdown file for deployment listing - * @param {String} directory - - * @param {Object} jsonReport - + * + * @param {string} directory - + * @param {string} filterPathsCSV - + * @param {object} jsonReport - * @returns {void} */ - document(directory, jsonReport) { + document(directory, filterPathsCSV, jsonReport) { const tabled = jsonToTable(jsonReport); let output = `# Deployment Report\n\n`; let tableSeparator = ''; - tabled[0].forEach((column) => { + for (const column of tabled[0]) { if (column !== '') { output += `| ${column} `; tableSeparator += '| --- '; } - }); + } output += `|\n${tableSeparator}|\n`; for (let i = 1; i < tabled.length; i++) { - tabled[i].forEach((field) => { + for (let field of tabled[i]) { if (field !== '') { field = field === true ? '✓' : field === false ? '✗' : field; output += `| ${field} `; } - }); + } output += '|\n'; } try { // write to disk (asynchronously) - File.writeToFile(directory, 'delta_package', 'md', output); + File.writeToFile( + directory, + Util.logFileName + + '-delta_package-' + + filterPathsCSV.replaceAll(',', '-').replaceAll('/', '-'), + 'md', + output + ); } catch (ex) { Util.logger.error(`DevOps.document():: error | ` + ex.message); } }, + + /** + * should return only the json for all but asset, query and script that are saved as multiple files + * additionally, the documentation for dataExtension and automation should be returned + * + * @param {Mcdevrc} properties central properties object + * @param {BuObject} buObject references credentials + * @param {string} metadataType metadata type to build + * @param {string[]} keyArr customerkey of the metadata + * @returns {Promise.<string[]>} list of all files that need to be committed in a flat array ['path/file1.ext', 'path/file2.ext'] + */ + getFilesToCommit(properties, buObject, metadataType, keyArr) { + MetadataType[metadataType].properties = properties; + MetadataType[metadataType].buObject = buObject; + return MetadataType[metadataType].getFilesToCommit(keyArr); + }, + /** + * helper for {@link DevOps.buildDeltaDefinitions} + * + * @param {DeltaPkgItem[]} delta git delta + * @param {string} sourceMarket market for the source BU + * @param {Mcdevrc} properties mcdev config + * @param {string} targetMlName marketList used to build for the target BU + */ + _generateDeleteInstructions(delta, sourceMarket, properties, targetMlName) { + const deltaDelete = delta + .filter((file) => file.gitAction === 'delete') + .filter( + // in case of assets we need to be careful because extracted code files might get deleted but that doesnt mean the asset was + (file) => + file.type !== 'asset' || (file.type === 'asset' && file.file.endsWith('.json')) + ); + const buTypeDeltaDelete = {}; // for bt, with BU info + + for (const file of deltaDelete) { + const buFrom = `${file._credential}/${file._businessUnit}`; + if (!buTypeDeltaDelete[buFrom]) { + // init object + /** @type {TypeKeyCombo} */ + buTypeDeltaDelete[buFrom] = {}; + } + if (!buTypeDeltaDelete[buFrom][file.type]) { + // init array + buTypeDeltaDelete[buFrom][file.type] = []; + } + if (!buTypeDeltaDelete[buFrom][file.type].includes(file.externalKey)) { + buTypeDeltaDelete[buFrom][file.type].push(file.externalKey); + } + } + const deleteByBU = {}; + for (const buFrom in buTypeDeltaDelete) { + /** @type {TemplateMap} */ + const sourceVariables = {}; + if (Util.checkMarket(sourceMarket, properties)) { + Object.assign(sourceVariables, properties.markets[sourceMarket]); + } + const typeKeyFrom = {}; + const typeKeyDelete = {}; + for (const type of Object.keys(buTypeDeltaDelete[buFrom])) { + if ( + Array.isArray(properties.metaDataTypes.createDeltaPkg) && + !properties.metaDataTypes.createDeltaPkg.includes(type) + ) { + Util.logger.warn( + `Skipping ${type} for delete based on config.metaDataTypes.createDeltaPkg: ${buTypeDeltaDelete[buFrom][type].join(', ')}` + ); + delete buTypeDeltaDelete[buFrom][type]; + continue; + } + typeKeyFrom[type] = new Set(); + if (Object.keys(sourceVariables).length > 0) { + for (let i = 0; i < buTypeDeltaDelete[buFrom][type].length; i++) { + // add templating variables to keys + typeKeyFrom[type].add( + Util.replaceByObject( + buTypeDeltaDelete[buFrom][type][i], + sourceVariables + ) + ); + } + } + typeKeyFrom[type] = Array.from(typeKeyFrom[type]); + for (const targetBu in properties.marketList[targetMlName]) { + typeKeyDelete[targetBu] ||= {}; + typeKeyDelete[targetBu][type] ||= []; + deleteByBU[targetBu] || {}; + const market = properties.marketList[targetMlName][targetBu]; + const markets = 'string' === typeof market ? [market] : market; + for (const marketArr of markets) { + const templateVariables = {}; + for (const market of Array.isArray(marketArr) ? marketArr : [marketArr]) { + if (Util.checkMarket(market, properties)) { + Object.assign(templateVariables, properties.markets[market]); + } + } + typeKeyDelete[targetBu][type].push( + ...typeKeyFrom[type].map((key) => + MetadataType[type].applyTemplateValues(key, templateVariables) + ) + ); + } + } + } + for (const targetBu in typeKeyDelete) { + const metadataList = []; + for (const type in typeKeyDelete[targetBu]) { + for (const key of typeKeyDelete[targetBu][type]) { + metadataList.push(type + ':"' + key + '"'); + } + } + if (metadataList.length) { + Util.logger.warn( + `Run the following to delete ${metadataList.length} potentially existing old files in ${targetBu}` + ); + Util.logger.warn(`mcdev delete ${targetBu} -m ${metadataList.join(' ')}`); + } + } + } + }, }; -module.exports = DevOps; +export default DevOps; diff --git a/lib/util/file.js b/lib/util/file.js index 02e688ae3..a74217a2e 100644 --- a/lib/util/file.js +++ b/lib/util/file.js @@ -1,19 +1,37 @@ -/* eslint-disable no-control-regex */ 'use strict'; +import fs from 'fs-extra'; -const fs = require('fs-extra'); -const packageJson = require('../../package.json'); -const path = require('path'); -const prettier = require('prettier'); -const Util = require('./util'); -const sql = require('sql-formatter-plus'); -const updateNotifier = require('update-notifier-git'); +import path from 'node:path'; +import prettier from 'prettier'; +import beautyAmp from 'beauty-amp-core2'; +import { Util } from './util.js'; +import updateNotifier from 'update-notifier'; +import config from './config.js'; + +/** + * @typedef {import('../../types/mcdev.d.js').AuthObject} AuthObject + * @typedef {import('../../types/mcdev.d.js').BuObject} BuObject + * @typedef {import('../../types/mcdev.d.js').Cache} Cache + * @typedef {import('../../types/mcdev.d.js').CodeExtract} CodeExtract + * @typedef {import('../../types/mcdev.d.js').CodeExtractItem} CodeExtractItem + * @typedef {import('../../types/mcdev.d.js').DeltaPkgItem} DeltaPkgItem + * @typedef {import('../../types/mcdev.d.js').Mcdevrc} Mcdevrc + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItem} MetadataTypeItem + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItemDiff} MetadataTypeItemDiff + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItemObj} MetadataTypeItemObj + * @typedef {import('../../types/mcdev.d.js').MetadataTypeMap} MetadataTypeMap + * @typedef {import('../../types/mcdev.d.js').MetadataTypeMapObj} MetadataTypeMapObj + * @typedef {import('../../types/mcdev.d.js').MultiMetadataTypeList} MultiMetadataTypeList + * @typedef {import('../../types/mcdev.d.js').MultiMetadataTypeMap} MultiMetadataTypeMap + * @typedef {import('../../types/mcdev.d.js').SoapRequestParams} SoapRequestParams + * @typedef {import('../../types/mcdev.d.js').TemplateMap} TemplateMap + * @typedef {import('../../types/mcdev.d.js').TypeKeyCombo} TypeKeyCombo + */ // inform user when there is an update const notifier = updateNotifier({ - pkg: packageJson, + pkg: Util.packageJsonMcdev, updateCheckInterval: 1000 * 3600 * 24, // once per day - remoteUrl: packageJson.repository.url.split('git+')[1], }); // Notify using the built-in convenience method notifier.notify(); @@ -22,38 +40,42 @@ notifier.notify(); * File extends fs-extra. It adds logger and util methods for file handling */ const File = { + prettierConfig: null, + prettierConfigFileType: null, + /** * copies a file from one path to another - * @param {String} from - full filepath including name of existing file - * @param {String} to - full filepath including name where file should go - * @returns {Object} - results object + * + * @param {string} from - full filepath including name of existing file + * @param {string} to - full filepath including name where file should go + * @returns {Promise.<{status:'ok'|'skipped'|'failed', statusMessage:string, file:string}>} - results object */ - async copyFile(from, to) { + async copyFileSimple(from, to) { try { await fs.copy(from, to); - return { status: 'ok', file: from }; + return { status: 'ok', statusMessage: null, file: from }; } catch (ex) { // This can happen in some cases where referencing files deleted in Commit - if (ex.message.startsWith('ENOENT: no such file or directory')) { - return { - status: 'skipped', - statusMessage: 'deleted from repository', - file: from, - }; - } else { - return { status: 'failed', statusMessage: ex.message, file: from }; - } + return ex.message.startsWith('ENOENT: no such file or directory') + ? { + status: 'skipped', + statusMessage: 'deleted from repository', + file: from, + } + : { status: 'failed', statusMessage: ex.message, file: from }; } }, + /** * makes sure Windows accepts path names - * @param {String} path - filename or path - * @returns {String} - corrected string + * + * @param {string} path - filename or path + * @returns {string} - corrected string */ filterIllegalPathChars(path) { return ( encodeURIComponent(path) - .replace(/[*]/g, '_STAR_') + .replaceAll(/[*]/g, '_STAR_') // convert space back .split('%20') .join(' ') @@ -69,18 +91,28 @@ const File = { // convert closing-curly brackets back for templating .split('%7D') .join('}') + // convert brackets back for asset blocks + .split('%5B') + .join('[') + // convert brackets back for asset blocks + .split('%5D') + .join(']') + // convert @ back for users + .split('%40') + .join('@') ); }, /** * makes sure Windows accepts file names - * @param {String} filename - filename or path - * @returns {String} - corrected string + * + * @param {string} filename - filename or path + * @returns {string} - corrected string */ filterIllegalFilenames(filename) { return ( encodeURIComponent(filename) - .replace(/[*]/g, '_STAR_') + .replaceAll(/[*]/g, '_STAR_') // convert space back .split('%20') .join(' ') @@ -90,13 +122,23 @@ const File = { // convert closing-curly brackets back for templating .split('%7D') .join('}') + // convert brackets back for asset blocks + .split('%5B') + .join('[') + // convert brackets back for asset blocks + .split('%5D') + .join(']') + // convert @ back for users + .split('%40') + .join('@') ); }, /** * makes sure Windows accepts file names - * @param {String} filename - filename or path - * @returns {String} - corrected string + * + * @param {string} filename - filename or path + * @returns {string} - corrected string */ reverseFilterIllegalFilenames(filename) { return decodeURIComponent(filename).split('_STAR_').join('*'); @@ -104,10 +146,12 @@ const File = { /** * Takes various types of path strings and formats into a platform specific path + * * @param {string|string[]} denormalizedPath directory the file will be written to - * @returns {String} Path strings + * @returns {string} Path strings */ normalizePath: function (denormalizedPath) { + /* eslint-disable unicorn/prefer-ternary */ if (Array.isArray(denormalizedPath)) { // if the value is undefined set to empty string to allow parsing return path.join(...denormalizedPath.map((val) => val || '')); @@ -115,173 +159,230 @@ const File = { // if directory is empty put . as otherwill will write to c:// return path.join(denormalizedPath || '.'); } + /* eslint-enable unicorn/prefer-ternary */ }, + /** * Saves json content to a file in the local file system. Will create the parent directory if it does not exist + * * @param {string|string[]} directory directory the file will be written to - * @param {String} filename name of the file without '.json' ending - * @param {Object} content filecontent + * @param {string} filename name of the file without '.json' ending + * @param {object} content filecontent * @returns {Promise} Promise */ writeJSONToFile: async function (directory, filename, content) { directory = this.filterIllegalPathChars(this.normalizePath(directory)); filename = this.filterIllegalFilenames(filename); - if (!fs.existsSync(directory)) { - fs.mkdirpSync(directory); - } + await fs.ensureDir(directory); try { - await fs.writeJSON(path.join(directory, filename + '.json'), content, { spaces: 4 }); + return fs.writeJSON(path.join(directory, filename + '.json'), content, { spaces: 4 }); } catch (ex) { Util.logger.error('File.writeJSONToFile:: error | ' + ex.message); } }, + /** * Saves beautified files in the local file system. Will create the parent directory if it does not exist * ! Important: run 'await File.initPrettier()' in your MetadataType.retrieve() once before hitting this + * * @param {string|string[]} directory directory the file will be written to - * @param {String} filename name of the file without suffix - * @param {String} filetype filetype ie. JSON or SSJS - * @param {String} content filecontent - * @param {Object} [templateVariables] templating variables to be replaced in the metadata - * @returns {Promise<Boolean>} Promise + * @param {string} filename name of the file without suffix + * @param {string} filetype filetype ie. JSON or SSJS + * @param {string} content filecontent + * @param {TemplateMap} [templateVariables] templating variables to be replaced in the metadata + * @returns {Promise.<boolean>} Promise */ writePrettyToFile: async function (directory, filename, filetype, content, templateVariables) { let formatted; - if (filetype === 'sql') { - formatted = this._beautify_sql(content); + const properties = await config.getProperties(); + if ( + (properties?.options?.formatOnSave && Util.OPTIONS.format === undefined) || + Util.OPTIONS.format + ) { + formatted = + filetype === 'amp' + ? await this.beautify_beautyAmp(content, false) + : await this._beautify_prettier(directory, filename, filetype, content); } else { - // we need to ensure formatted is a String, not a Promise - formatted = await this._beautify_prettier(directory, filename, filetype, content); + // skip formatting + formatted = content; } if (templateVariables) { formatted = Util.replaceByObject(formatted, templateVariables); } - return this.writeToFile(directory, filename, filetype, formatted); }, + /** - * helper for writePrettyToFile, applying sql formatting onto given stringified content - * @param {String} content filecontent - * @returns {String} original string on error; formatted string on success + * helper that applies beautyAmp onto given stringified content; strongly typed for strings only + * + * @param {string} content code + * @param {boolean} [formatHTML] applies formatting to html and ampscript if true + * @returns {Promise.<string>} formatted code */ - _beautify_sql: function (content) { - let formatted; - try { - formatted = sql.format(content, { - language: 'sql', // Defaults to "sql" - indent: ' ', // Defaults to two spaces,W - uppercase: true, // Defaults to false - linesBetweenQueries: 1, // Defaults to 1 - }); - // if templating variables were in the code, those now have extra spaces - formatted = formatted.split('{ { { ').join('{{{').split(' } } }').join('}}}'); - } catch (ex) { - Util.logger.debug('SQL Formatter Exception: ' + ex.message); - formatted = content; + _beautify_beautyAmp_beautify: async function (content, formatHTML = true) { + const response = await beautyAmp.beautify(content, formatHTML); + if (typeof response == 'string') { + return response.trim() + '\n'; + } else { + throw new TypeError('beautyAmp failed to beautify the content'); } - return formatted; }, + /** - * helper for writePrettyToFile, applying prettier onto given stringified content - * ! Important: run 'await File.initPrettier()' in your MetadataType.retrieve() once before hitting this - * @param {string|string[]} directory directory the file will be written to - * @param {String} filename name of the file without suffix - * @param {String} filetype filetype ie. JSON or SSJS - * @param {String} content filecontent - * @returns {String} original string on error; formatted string on success + * helper for {@link File.writePrettyToFile}, applying beautyAmp onto given stringified content + * + * @param {string} content filecontent + * @param {boolean} formatHTML should we format HTML or not via prettier included in beautyAmp + * @returns {Promise.<string>} original string on error; formatted string on success */ - _beautify_prettier: function (directory, filename, filetype, content) { - if (!FileFs.prettierConfig) { - // either no prettier config in project directory or initPrettier was not run before this - return content; - } else if (content.includes('%%[') || content.includes('%%=')) { - // in case we find AMPScript we need to abort beautifying as prettier - // will throw an error falsely assuming bad syntax + beautify_beautyAmp: async function (content, formatHTML = true) { + const properties = await config.getProperties(); + if ( + (properties?.options?.formatOnSave && Util.OPTIONS.format === undefined) || + Util.OPTIONS.format + ) { + // logs trough console only for the moment. + const logs = { + loggerOn: false, // <= disable logging + }; + try { + beautyAmp.setup(null, null, logs); + // Note: we need to trim the result as beautyAmp adds a leading new line; but we also want to ensure there is a single new line at the end to comply with standard linting rules + return await this._beautify_beautyAmp_beautify(content, formatHTML); + } catch { + return content; + } + } else { + // skip formatting return content; } - let formatted = ''; + }, + + /** + * helper for {@link File.writePrettyToFile}, applying prettier onto given stringified content + * ! Important: run 'await File.initPrettier()' in your MetadataType.retrieve() once before hitting this + * + * @param {string|string[]} directory directory the file will be written to + * @param {string} filename name of the file without suffix + * @param {string} filetype filetype ie. JSON or SSJS + * @param {string} content filecontent + * @returns {Promise.<string>} original string on error; formatted string on success + */ + _beautify_prettier: async function (directory, filename, filetype, content) { + const properties = await config.getProperties(); + /** @type {string} */ + let formatted; try { - // load the right prettier config relative to our file - switch (filetype) { - case 'htm': - case 'html': - FileFs.prettierConfig.parser = 'html'; - break; - case 'ssjs': - case 'js': - FileFs.prettierConfig.parser = 'babel'; - break; - case 'json': - FileFs.prettierConfig.parser = 'json'; - break; - case 'yaml': - case 'yml': - FileFs.prettierConfig.parser = 'yaml'; - break; - case 'ts': - FileFs.prettierConfig.parser = 'babel-ts'; - break; - case 'css': - FileFs.prettierConfig.parser = 'css'; - break; - case 'less': - FileFs.prettierConfig.parser = 'less'; - break; - case 'sass': - case 'scss': - FileFs.prettierConfig.parser = 'scss'; - break; - case 'md': - FileFs.prettierConfig.parser = 'markdown'; - break; - default: - FileFs.prettierConfig.parser = 'babel'; + if (!FileFs.prettierConfig) { + // either no prettier config in project directory or initPrettier was not run before this + return content; + } else if (content.includes('%%[') || content.includes('%%=')) { + // in case we find AMPScript we need to abort beautifying as prettier + // will throw an error falsely assuming bad syntax + return await this.beautify_beautyAmp(content, true); + } + + if (!FileFs.prettierConfig.parser) { + // load the right prettier config relative to our file + switch (filetype) { + case 'htm': + case 'html': { + FileFs.prettierConfig.parser = 'html'; + break; + } + case 'ssjs': + case 'js': { + FileFs.prettierConfig.parser = 'babel'; + break; + } + case 'json': { + FileFs.prettierConfig.parser = 'json'; + break; + } + case 'yaml': + case 'yml': { + FileFs.prettierConfig.parser = 'yaml'; + break; + } + case 'ts': { + FileFs.prettierConfig.parser = 'babel-ts'; + break; + } + case 'css': { + FileFs.prettierConfig.parser = 'css'; + break; + } + case 'less': { + FileFs.prettierConfig.parser = 'less'; + break; + } + case 'sass': + case 'scss': { + FileFs.prettierConfig.parser = 'scss'; + break; + } + case 'md': { + FileFs.prettierConfig.parser = 'markdown'; + break; + } + case 'sql': { + FileFs.prettierConfig.parser = 'sql'; + FileFs.prettierConfig.plugins = ['prettier-plugin-sql']; + break; + } + default: { + FileFs.prettierConfig.parser = 'babel'; + } + } } - formatted = prettier.format(content, FileFs.prettierConfig); + + formatted = await prettier.format(content, FileFs.prettierConfig); } catch (ex) { - const warnMsg = `Potential Code issue found in ${this.normalizePath([ - ...directory, - filename + '.' + filetype, - ])}`; - Util.logger.debug(warnMsg); - - // save prettier errror into log file - // Note: we have to filter color codes from prettier's error message before saving it to file - this.writeToFile( - directory, - filename + '.error', - 'log', - `Error Log\nParser: ${FileFs.prettierConfig.parser}\n${ex.message.replace( - /[\u001b\u009b][[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-ORZcf-nqry=><]/g, - - '' - )}` - ); + if (properties?.options?.formatErrorLog) { + // save prettier errror into log file + // Note: we have to filter color codes from prettier's error message before saving it to file + /* eslint-disable no-control-regex */ + this.writeToFile( + directory, + filename + '.error', + 'log', + `Error Log\nParser: ${FileFs.prettierConfig.parser}\n${ex.message.replaceAll( + /[\u001B\u009B][[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-ORZcf-nqry=><]/g, + + '' + )}` + ); + /* eslint-enable no-control-regex */ + } formatted = content; } return formatted; }, + /** * Saves text content to a file in the local file system. Will create the parent directory if it does not exist + * * @param {string|string[]} directory directory the file will be written to - * @param {String} filename name of the file without '.json' ending - * @param {String} filetype filetype suffix - * @param {String} content filecontent - * @param {Object} [encoding] added for certain file types (like images) - * @returns {Promise<Boolean>} Promise + * @param {string} filename name of the file without '.json' ending + * @param {string} filetype filetype suffix + * @param {string} content filecontent + * @param {object} [encoding] added for certain file types (like images) + * @returns {Promise.<boolean>} Promise */ writeToFile: async function (directory, filename, filetype, content, encoding) { directory = this.filterIllegalPathChars(this.normalizePath(directory)); - if (!fs.existsSync(directory)) { - fs.mkdirpSync(directory); - } + await fs.ensureDir(directory); // filter characters that are illegal for file names in Windows filename = this.filterIllegalFilenames(filename); - + const filePath = path.join(directory, filename + '.' + filetype); try { - await fs.writeFile(path.join(directory, filename + '.' + filetype), content, encoding); + if (await fs.pathExists(filePath)) { + Util.logger.debug(`Overwriting: ${filePath}`); + } + await fs.writeFile(filePath, content, encoding); return true; } catch (ex) { Util.logger.error('File.writeToFile:: error | ' + ex.message); @@ -291,13 +392,13 @@ const File = { /** * Saves json content to a file in the local file system. Will create the parent directory if it does not exist - * @param {String|String[]} directory directory where the file is stored - * @param {String} filename name of the file without '.json' ending - * @param {Boolean} sync should execute sync (default is async) - * @param {Boolean} cleanPath should execute sync (default is true) - * @returns {Promise|Object} Promise or JSON object depending on if async or not + * + * @param {string | string[]} directory directory where the file is stored + * @param {string} filename name of the file without '.json' ending + * @param {boolean} cleanPath filters illegal chars if true + * @returns {Promise.<object | object | void>} Promise or JSON object depending on if async or not; void on error */ - readJSONFile: function (directory, filename, sync, cleanPath) { + readJSONFile: async function (directory, filename, cleanPath) { try { if (cleanPath == null || cleanPath == true) { directory = this.filterIllegalPathChars(this.normalizePath(directory)); @@ -311,45 +412,47 @@ const File = { } let json; try { - json = sync - ? fs.readJsonSync(path.join(directory, filename + '.json')) - : fs.readJson(path.join(directory, filename + '.json')); + json = await fs.readJSON(path.join(directory, filename + '.json')); } catch (ex) { - // Note: this only works for sync, not async Util.logger.debug(ex.stack); - throw new Error(`${ex.code}: ${ex.message}`); } return json; } catch (ex) { Util.logger.error('File.readJSONFile:: error | ' + ex.message); } }, + /** * reads file from local file system. - * @param {String|String[]} directory directory where the file is stored - * @param {String} filename name of the file without '.json' ending - * @param {String} filetype filetype suffix - * @param {String} [encoding='utf8'] read file with encoding (defaults to utf-8) - * @returns {Promise<String>} file contents + * + * @param {string | string[]} directory directory where the file is stored + * @param {string} filename name of the file without '.json' ending + * @param {string} filetype filetype suffix + * @param {string} [encoding] read file with encoding (defaults to utf-8) + * @returns {Promise.<string>} file contents; void on error */ - readFile: function (directory, filename, filetype, encoding) { + readFilteredFilename: async function (directory, filename, filetype, encoding) { try { directory = this.filterIllegalPathChars(this.normalizePath(directory)); filename = this.filterIllegalFilenames(filename); + // @ts-expect-error somehow, the typing for fs-extra is not correct return fs.readFile(path.join(directory, filename + '.' + filetype), encoding || 'utf8'); } catch (ex) { - Util.logger.error('File.readFile:: error | ' + ex.message); + Util.logger.debug('File.readFilteredFilename:: error | ' + ex.message); } + return; }, + /** * reads directories to a specific depth returning an array * of file paths to be iterated over + * * @example ['deploy/mcdev/bu1'] - * @param {String} directory directory to checkin - * @param {Number} depth how many levels to check (1 base) - * @param {Boolean} [includeStem] include the parent directory in the response - * @param {Number} [_stemLength] set recursively for subfolders. do not set manually! - * @returns {Promise<String[]>} array of fully defined file paths + * @param {string} directory directory to checkin + * @param {number} depth how many levels to check (1 base) + * @param {boolean} [includeStem] include the parent directory in the response + * @param {number} [_stemLength] set recursively for subfolders. do not set manually! + * @returns {Promise.<string[]>} array of fully defined file paths */ readDirectories: async function (directory, depth, includeStem, _stemLength) { try { @@ -362,8 +465,8 @@ const File = { for (const dirent of raw) { const direntPath = path.join(directory, dirent.name); if ( - fs.existsSync(direntPath) && - fs.lstatSync(direntPath).isDirectory() && + (await fs.pathExists(direntPath)) && + (await fs.lstat(direntPath)).isDirectory() && depth > 0 ) { const nestedChildren = await this.readDirectories( @@ -376,14 +479,15 @@ const File = { } } if (children.length === 0) { - if (includeStem) { - return [directory]; - } else { - // remove base directory and leading slahes and backslashes - return [ - directory.substring(_stemLength).replace(/^\\+/, '').replace(/^\/+/, ''), - ]; - } + // if not includeStem then remove base directory and leading slahes and backslashes + return includeStem + ? [directory] + : [ + directory + .slice(Math.max(0, _stemLength)) + .replace(/^\\+/, '') + .replace(/^\/+/, ''), + ]; } else { return children; } @@ -396,12 +500,14 @@ const File = { /** * reads directories to a specific depth returning an array * of file paths to be iterated over using sync api (required in constructors) + * TODO - merge with readDirectories. so far the logic is really different + * * @example ['deploy/mcdev/bu1'] - * @param {String} directory directory to checkin - * @param {Number} [depth] how many levels to check (1 base) - * @param {Boolean} [includeStem] include the parent directory in the response - * @param {Number} [_stemLength] set recursively for subfolders. do not set manually! - * @returns {String[]} array of fully defined file paths + * @param {string} directory directory to checkin + * @param {number} [depth] how many levels to check (1 base) + * @param {boolean} [includeStem] include the parent directory in the response + * @param {number} [_stemLength] set recursively for subfolders. do not set manually! + * @returns {string[] | void} array of fully defined file paths; void on error */ readDirectoriesSync: function (directory, depth, includeStem, _stemLength) { try { @@ -417,8 +523,8 @@ const File = { children.push(directory); } else { // remove base directory and leading slahes and backslashes - const currentPath = directory.substring(_stemLength).replace(path.sep, ''); - children.push(currentPath ? currentPath : '.'); + const currentPath = directory.slice(Math.max(0, _stemLength)).replace(path.sep, ''); + children.push(currentPath || '.'); } // read all directories const raw = fs.readdirSync(directory, { withFileTypes: true }); @@ -433,7 +539,9 @@ const File = { includeStem, _stemLength ); - children.push(...nestedChildren); + if (Array.isArray(nestedChildren) && nestedChildren.length > 0) { + children.push(...nestedChildren); + } } } return children; @@ -442,98 +550,40 @@ const File = { Util.logger.debug(ex.stack); } }, - /** - * loads central properties from config file - * @param {Boolean} [silent] omit throwing errors and print messages; assuming not silent if not set - * @returns {Object} central properties object - */ - loadConfigFile(silent) { - let properties; - if (fs.existsSync(Util.configFileName)) { - // properties = JSON.parse(fs.readFileSync(Util.configFileName, 'utf8')); - try { - properties = fs.readJsonSync(Util.configFileName); - } catch (ex) { - Util.logger.error(`${ex.code}: ${ex.message}`); - return; - } - if (fs.existsSync(Util.authFileName)) { - let auth; - try { - auth = fs.readJsonSync(Util.authFileName); - } catch (ex) { - Util.logger.error(`${ex.code}: ${ex.message}`); - return; - } - if (!auth.credentials) { - const err = `${Util.authFileName} is not set up correctly.`; - Util.logger.error(err); - throw new Error(err); - } - for (const cred in properties.credentials) { - const configset = properties.credentials[cred]; - const authset = auth.credentials[cred]; - if (authset) { - if (configset.eid === authset.eid) { - for (const key in authset) { - configset[key] = authset[key]; - } - } else if (!silent) { - const err = `'${cred}' found in ${Util.configFileName} and ${Util.authFileName} have a Enterprise ID mismatch. Please check.`; - Util.logger.error(err); - throw new Error(err); - } - } else if (!silent) { - Util.logger.warn( - `'${cred}' found in ${Util.configFileName} but not in ${Util.authFileName}. Please run 'mcdev init' to provide the missing credential details.` - ); - } - } - } else if (!silent) { - Util.logger.warn( - `${Util.authFileName} not found. Please run 'mcdev init' to provide the missing credential details.` - ); - } - } - return properties; - }, /** * helper that splits the config back into auth & config parts to save them separately - * @param {Object} properties central properties object - * @returns {Promise<void>} - + * + * @param {Mcdevrc} properties central properties object + * @returns {Promise.<void>} - */ async saveConfigFile(properties) { - const auth = { credentials: {} }; - const config = properties; - for (const cred in config.credentials) { - auth.credentials[cred] = {}; - // copy id+secret+tenant to auth file - auth.credentials[cred].clientId = config.credentials[cred].clientId; - auth.credentials[cred].clientSecret = config.credentials[cred].clientSecret; - auth.credentials[cred].tenant = config.credentials[cred].tenant; - // copy eid as well to make sure we can test for equality when merging the files during runtime - auth.credentials[cred].eid = config.credentials[cred].eid; - // delete id+secret from config file - delete config.credentials[cred].clientId; - delete config.credentials[cred].clientSecret; - delete config.credentials[cred].tenant; - } // we want to save to save the full version here to allow us to upgrade configs properly in the future - config.version = packageJson.version; + properties.version = Util.packageJsonMcdev.version; - await this.writeJSONToFile('', Util.configFileName.split('.json')[0], config); - await this.writeJSONToFile('', Util.authFileName.split('.json')[0], auth); + await this.writeJSONToFile('', Util.configFileName.split('.json')[0], properties); Util.logger.info(`✔️ ${Util.configFileName} and ${Util.authFileName} saved successfully`); }, + /** * Initalises Prettier formatting lib async. - * @param {String} [filetype='html'] filetype ie. JSON or SSJS - * @returns {Promise<Boolean>} success of config load + * + * @param {string} [filetype] filetype ie. JSON or SSJS + * @returns {Promise.<boolean>} success of config load */ - async initPrettier(filetype) { - if (FileFs.prettierConfig === null) { - filetype = filetype || 'html'; + async initPrettier(filetype = 'html') { + if (Util.OPTIONS.format === false) { + // auto-formatting was disabled via CLI option + return; + } + const properties = await config.getProperties(); + if (Util.OPTIONS.format !== true && properties.options.formatOnSave === false) { + // auto-formatting was disabled via config file + return; + } + if (FileFs.prettierConfig === null || FileFs.prettierConfigFileType !== filetype) { + // run this if no config was yet found or if the filetype previously used to initialize it differs (because it results in a potentially different config!) + FileFs.prettierConfigFileType = filetype; try { // pass in project dir with fake index.html to avoid "no parser" error // by using process.cwd we are limiting ourselves to a config in the project root @@ -551,7 +601,7 @@ const File = { return true; } catch (ex) { FileFs.prettierConfig = false; - Util.logger.error('Cannot apply auto-formatting to your code:' + ex.message); + Util.logger.error('Cannot apply auto-formatting to your code: ' + ex.message); return false; } } else { @@ -559,7 +609,6 @@ const File = { } }, }; -const FileFs = { ...fs, ...File }; -FileFs.prettierConfig = null; -module.exports = FileFs; +const FileFs = Object.assign(fs, File); +export default FileFs; diff --git a/lib/util/init.config.js b/lib/util/init.config.js index 5ac8be525..9c50960ed 100644 --- a/lib/util/init.config.js +++ b/lib/util/init.config.js @@ -1,10 +1,33 @@ 'use strict'; -const Cli = require('./cli'); -const File = require('./file'); -const Util = require('./util'); -const inquirer = require('inquirer'); -const path = require('path'); +import File from './file.js'; +import config from './config.js'; +import { Util } from './util.js'; +import { confirm } from '@inquirer/prompts'; +import path from 'node:path'; +import semver from 'semver'; +import { fileURLToPath } from 'node:url'; +const __dirname = path.dirname(fileURLToPath(import.meta.url)); + +/** + * @typedef {import('../../types/mcdev.d.js').AuthObject} AuthObject + * @typedef {import('../../types/mcdev.d.js').BuObject} BuObject + * @typedef {import('../../types/mcdev.d.js').Cache} Cache + * @typedef {import('../../types/mcdev.d.js').CodeExtract} CodeExtract + * @typedef {import('../../types/mcdev.d.js').CodeExtractItem} CodeExtractItem + * @typedef {import('../../types/mcdev.d.js').DeltaPkgItem} DeltaPkgItem + * @typedef {import('../../types/mcdev.d.js').Mcdevrc} Mcdevrc + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItem} MetadataTypeItem + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItemDiff} MetadataTypeItemDiff + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItemObj} MetadataTypeItemObj + * @typedef {import('../../types/mcdev.d.js').MetadataTypeMap} MetadataTypeMap + * @typedef {import('../../types/mcdev.d.js').MetadataTypeMapObj} MetadataTypeMapObj + * @typedef {import('../../types/mcdev.d.js').MultiMetadataTypeList} MultiMetadataTypeList + * @typedef {import('../../types/mcdev.d.js').MultiMetadataTypeMap} MultiMetadataTypeMap + * @typedef {import('../../types/mcdev.d.js').SoapRequestParams} SoapRequestParams + * @typedef {import('../../types/mcdev.d.js').TemplateMap} TemplateMap + * @typedef {import('../../types/mcdev.d.js').TypeKeyCombo} TypeKeyCombo + */ /** * CLI helper class @@ -13,8 +36,9 @@ const path = require('path'); const Init = { /** * helper method for this.upgradeProject that upgrades project config if needed - * @param {Object} properties config file's json - * @returns {Promise<Boolean>} returns true if worked without errors + * + * @param {Mcdevrc} properties config file's json + * @returns {Promise.<boolean>} returns true if worked without errors */ async fixMcdevConfig(properties) { if (!properties) { @@ -26,46 +50,76 @@ const Init = { const upgradeMsgs = [`Upgrading existing ${Util.configFileName}:`]; - const missingFields = Util.checkProperties(properties, true); - if (missingFields.length) { - const defaultProps = Util.getDefaultProperties(); - missingFields.forEach((fieldName) => { + const missingFields = await config.checkProperties(properties, true); + const defaultProps = await config.getDefaultProperties(); + if (Array.isArray(missingFields) && missingFields.length) { + for (const fieldName of missingFields) { switch (fieldName) { - case 'marketList': + case 'marketList': { + // @ts-expect-error - deprecated field if (properties.marketBulk) { upgradeMsgs.push(`- ✔️ converted 'marketBulk' to '${fieldName}'`); + // @ts-expect-error - deprecated field properties[fieldName] = properties.marketBulk; + // @ts-expect-error - deprecated field delete properties.marketBulk; } else { upgradeMsgs.push(`- ✔️ added '${fieldName}'`); this._updateLeaf(properties, defaultProps, fieldName); } break; - case 'directories.dataExtension': - if (properties.directories.dataextension) { - upgradeMsgs.push( - `- ✔️ converted 'directories.dataextension' to '${fieldName}'` - ); - properties.directories.dataExtension = - properties.directories.dataextension; - delete properties.directories.dataextension; - } else { - upgradeMsgs.push(`- ✔️ added '${fieldName}'`); - this._updateLeaf(properties, defaultProps, fieldName); + } + case 'directories.docs': { + // @ts-expect-error - deprecated field + if (properties.directories.badKeys) { + // @ts-expect-error - deprecated field + delete properties.directories.badKeys; + upgradeMsgs.push(`- ✋ removed 'directories.badKeys'`); } + // @ts-expect-error - deprecated field + if (properties.directories.dataExtension) { + // @ts-expect-error - deprecated field + File.removeSync(properties.directories.dataExtension); + // @ts-expect-error - deprecated field + delete properties.directories.dataExtension; + upgradeMsgs.push(`- ✋ removed 'directories.dataExtension'`); + } + // @ts-expect-error - deprecated field + if (properties.directories.deltaPackage) { + // @ts-expect-error - deprecated field + delete properties.directories.deltaPackage; + upgradeMsgs.push(`- ✋ removed 'directories.deltaPackage'`); + } + // @ts-expect-error - deprecated field + if (properties.directories.roles) { + // @ts-expect-error - deprecated field + delete properties.directories.roles; + upgradeMsgs.push(`- ✋ removed 'directories.roles'`); + } + // @ts-expect-error - deprecated field + if (properties.directories.users) { + // @ts-expect-error - deprecated field + delete properties.directories.users; + upgradeMsgs.push(`- ✋ removed 'directories.users'`); + } + + this._updateLeaf(properties, defaultProps, fieldName); + upgradeMsgs.push(`- ✔️ added '${fieldName}'`); break; - case 'metaDataTypes.documentOnRetrieve': - if (!properties.options.documentOnRetrieve) { - properties.metaDataTypes.documentOnRetrieve = []; - } else { + } + case 'metaDataTypes.documentOnRetrieve': { + if (properties.options.documentOnRetrieve) { this._updateLeaf(properties, defaultProps, fieldName); + } else { + properties.metaDataTypes.documentOnRetrieve = []; } delete properties.options.documentOnRetrieve; upgradeMsgs.push( `- ✔️ converted 'options.documentOnRetrieve' to '${fieldName}'` ); break; - case 'options.deployment.commitHistory': + } + case 'options.deployment.commitHistory': { if (properties.options.commitHistory) { upgradeMsgs.push( `- ✔️ converted 'options.commitHistory' to '${fieldName}'` @@ -78,7 +132,8 @@ const Init = { this._updateLeaf(properties, defaultProps, fieldName); } break; - case 'options.exclude': + } + case 'options.exclude': { if (properties.options.filter) { upgradeMsgs.push(`- ✔️ converted 'options.filter' to '${fieldName}'`); properties.options.exclude = properties.options.filter; @@ -88,87 +143,160 @@ const Init = { this._updateLeaf(properties, defaultProps, fieldName); } break; - case 'version': + } + case 'version': { // do nothing other than ensure we re-save the config (with the new version) - delete properties.catalystFullVersion; - delete properties.catalystVersion; - upgradeMsgs.push(`- ✔️ version updated`); break; - default: + } + default: { this._updateLeaf(properties, defaultProps, fieldName); upgradeMsgs.push(`- ✔️ added '${fieldName}'`); + } } - }); + } + updateConfigNeeded = true; + } + + // ensure we document dataExtensions and automations on retrieve as they should now be in the retrieve folder + if (this._updateLeaf(properties, defaultProps, 'metaDataTypes.documentOnRetrieve')) { + upgradeMsgs.push( + `- ✔️ updated 'metaDataTypes.documentOnRetrieve' to include all available types` + ); updateConfigNeeded = true; } // check if metaDataTypes.retrieve is set to default values and if not, launch selectTypes - const defaultRetrieveArr = Util.getRetrieveTypeChoices(); + const defaultRetrieveArr = Util.getTypeChoices('typeRetrieveByDefault'); let reselectDefaultRetrieve = false; - const toBeRemovedTypes = properties.metaDataTypes.retrieve.filter( + const toBeRemovedRetrieve = properties.metaDataTypes.retrieve.filter( (type) => !defaultRetrieveArr.includes(type) ); - const toBeAddedTypes = defaultRetrieveArr.filter( + const toBeAddedRetrieve = defaultRetrieveArr.filter( (type) => !properties.metaDataTypes.retrieve.includes(type) ); - if (toBeRemovedTypes.length || toBeAddedTypes.length) { + if (toBeRemovedRetrieve.length || toBeAddedRetrieve.length) { reselectDefaultRetrieve = true; updateConfigNeeded = true; } + // check if metaDataTypes.retrieve is set to default values and if not, launch selectTypes + const defaultCdpArr = Util.getTypeChoices('typeCdpByDefault'); + let reselectDefaultCdp = false; + const toBeRemovedCdp = properties.metaDataTypes.createDeltaPkg.filter( + (type) => !defaultCdpArr.includes(type) + ); + const toBeAddedCdp = defaultCdpArr.filter( + (type) => !properties.metaDataTypes.createDeltaPkg.includes(type) + ); + + if (toBeRemovedCdp.length || toBeAddedCdp.length) { + reselectDefaultCdp = true; + updateConfigNeeded = true; + } + + // move to version 4 uses integers for MIDs + for (const cred in properties.credentials) { + let credentialMidsUpdated = false; + if (typeof properties.credentials[cred].eid === 'string') { + properties.credentials[cred].eid = Number.parseInt( + properties.credentials[cred].eid + ); + credentialMidsUpdated = true; + } + for (const bu in properties.credentials[cred].businessUnits) { + if (typeof properties.credentials[cred].businessUnits[bu] === 'string') { + properties.credentials[cred].businessUnits[bu] = Number.parseInt( + properties.credentials[cred].businessUnits[bu] + ); + credentialMidsUpdated = true; + } + } + if (credentialMidsUpdated) { + updateConfigNeeded = true; + upgradeMsgs.push(`- ✔️ updated Business Unit format (${cred})`); + } + } + // update config if (updateConfigNeeded) { for (const msg of upgradeMsgs) { Util.logger.info(msg); } + if (reselectDefaultCdp) { + // run selectTypes here as it _also_ runs File.saveConfigFile() + Util.logger.warn( + 'Your metaDataTypes.createDeltaPkg list is not set to standard values. Resetting config.' + ); + Util.logger.warn(''); + if (toBeAddedCdp.length) { + Util.logger.warn('Adding types:'); + for (const type of toBeAddedCdp) { + Util.logger.warn(` - ${type}`); + } + Util.logger.warn(''); + } + if (toBeRemovedCdp.length) { + Util.logger.warn('Removing types:'); + for (const type of toBeRemovedCdp) { + Util.logger.warn(` - ${type}`); + } + Util.logger.warn(''); + } + properties.metaDataTypes.createDeltaPkg = Util.summarizeSubtypes( + 'typeCdpByDefault', + defaultCdpArr + ); + } if (reselectDefaultRetrieve) { // run selectTypes here as it _also_ runs File.saveConfigFile() Util.logger.warn( 'Your metaDataTypes.retrieve list is not set to standard values. Resetting config.' ); Util.logger.warn(''); - if (toBeAddedTypes.length) { + if (toBeAddedRetrieve.length) { Util.logger.warn('Adding types:'); - toBeAddedTypes.forEach((type) => { + for (const type of toBeAddedRetrieve) { Util.logger.warn(` - ${type}`); - }); + } Util.logger.warn(''); } - if (toBeRemovedTypes.length) { + if (toBeRemovedRetrieve.length) { Util.logger.warn('Removing types:'); - toBeRemovedTypes.forEach((type) => { + for (const type of toBeRemovedRetrieve) { Util.logger.warn(` - ${type}`); - }); + } Util.logger.warn(''); } - await Cli.selectTypes(properties, defaultRetrieveArr); - } else { - // update config if anything else was changed but no re-selection of retrieve-types was triggered - await File.saveConfigFile(properties); + properties.metaDataTypes.retrieve = Util.summarizeSubtypes( + 'typeRetrieveByDefault', + defaultRetrieveArr + ); } + // update config + await File.saveConfigFile(properties); } else { Util.logger.info(`✔️ No problems found in existing ${Util.configFileName}`); } return true; }, + /** * handles creation/update of all config file from the boilerplate - * @returns {Promise<Boolean>} status of config file creation + * + * @param {string} versionBeforeUpgrade 'x.y.z' + * @returns {Promise.<boolean>} status of config file creation */ - async createIdeConfigFiles() { + async createIdeConfigFiles(versionBeforeUpgrade) { Util.logger.info('Checking configuration files (existing files will not be changed):'); const creationLog = []; + await File.ensureDir('deploy/'); + await File.ensureDir('src/cloudPages'); + const relevantForced = await this._getForcedUpdateList(versionBeforeUpgrade); - if (!File.existsSync('deploy/')) { - File.mkdirpSync('deploy/'); - } - - if (!File.existsSync('src/cloudPages')) { - File.mkdirpSync('src/cloudPages'); - } + await this._removeIdeConfigFiles(relevantForced); // copy in .gitignore (cant be retrieved via npm install directly) const gitignoreFileName = path.resolve( @@ -176,33 +304,42 @@ const Init = { Util.boilerplateDirectory, 'gitignore-template' ); - if (!File.existsSync(gitignoreFileName)) { - Util.logger.debug(`Dependency file not found in ${gitignoreFileName}`); - return false; - } else { - const fileContent = File.readFileSync(gitignoreFileName, 'utf8'); + if (await File.pathExists(gitignoreFileName)) { + const fileContent = await File.readFile(gitignoreFileName, 'utf8'); creationLog.push( - await this._createIdeConfigFile(['.' + path.sep, '', '.gitignore'], fileContent) + await this._createIdeConfigFile( + ['.' + path.sep, '', '.gitignore'], + relevantForced, + fileContent + ) ); + } else { + Util.logger.debug(`Dependency file not found in ${gitignoreFileName}`); + return false; } // load file list from boilerplate dir and initiate copy process const boilerPlateFilesPath = path.resolve(__dirname, Util.boilerplateDirectory, 'files'); - const directories = File.readDirectoriesSync(boilerPlateFilesPath, 10, false); - - for (const subdir of directories) { - // walk thru the root of our boilerplate-files directory and all sub folders - const curDir = path.join(boilerPlateFilesPath, subdir); - for (const file of File.readdirSync(curDir)) { - // read all files in these directories - if (!File.lstatSync(path.join(curDir, file)).isDirectory()) { - // filter entries that are actually folders - const fileArr = file.split('.'); - const ext = '.' + fileArr.pop(); - // awaiting the result here due to interactive optional overwrite - creationLog.push( - await this._createIdeConfigFile([subdir + path.sep, fileArr.join('.'), ext]) - ); + // ! do not switch to readDirectories before merging the two custom methods. Their logic is different! + const directories = await File.readDirectoriesSync(boilerPlateFilesPath, 10, false); + if (directories) { + for (const subdir of directories) { + // walk thru the root of our boilerplate-files directory and all sub folders + const curDir = path.join(boilerPlateFilesPath, subdir); + for (const file of await File.readdir(curDir)) { + // read all files in these directories + if (!(await File.lstat(path.join(curDir, file))).isDirectory()) { + // filter entries that are actually folders + const fileArr = file.split('.'); + const ext = '.' + fileArr.pop(); + // awaiting the result here due to interactive optional overwrite + creationLog.push( + await this._createIdeConfigFile( + [subdir + path.sep, fileArr.join('.'), ext], + relevantForced + ) + ); + } } } } @@ -218,37 +355,86 @@ const Init = { return true; } }, + /** - * recursive helper for _fixMcdevConfig that adds missing settings - * @param {Object} propertiersCur current sub-object of project settings - * @param {Object} defaultPropsCur current sub-object of default settings - * @param {String} fieldName dot-concatenated object-path that needs adding - * @returns {void} + * recursive helper for {@link Init.fixMcdevConfig} that adds missing settings + * + * @param {object} propertiersCur current sub-object of project settings + * @param {object} defaultPropsCur current sub-object of default settings + * @param {string} fieldName dot-concatenated object-path that needs adding + * @returns {boolean} was something updated or not */ _updateLeaf(propertiersCur, defaultPropsCur, fieldName) { if (fieldName.includes('.')) { const fieldNameArr = fieldName.split('.'); const curKey = fieldNameArr[0]; + let updated = false; if (!propertiersCur[curKey]) { + updated = true; propertiersCur[curKey] = {}; } fieldNameArr.splice(0, 1); - this._updateLeaf( - propertiersCur[curKey], - defaultPropsCur[curKey], - fieldNameArr.join('.') + return ( + this._updateLeaf( + propertiersCur[curKey], + defaultPropsCur[curKey], + fieldNameArr.join('.') + ) || updated ); + } else if (Util.isEqual(propertiersCur[fieldName], defaultPropsCur[fieldName])) { + return false; } else { propertiersCur[fieldName] = defaultPropsCur[fieldName]; + return true; + } + }, + + /** + * returns list of files that need to be updated + * + * @param {string} projectVersion version found in config file of the current project + * @returns {Promise.<{updates:string[],deletes:string[]}>} relevant files with path that need to be updated + */ + async _getForcedUpdateList(projectVersion) { + // list of files that absolutely need to get overwritten, no questions asked, when upgrading from a version lower than the given. + let forceIdeConfigUpdate; + const updates = []; + const deletes = []; + if (await File.pathExists(Util.configFileName)) { + forceIdeConfigUpdate = await File.readJSON( + path.resolve(__dirname, Util.boilerplateDirectory, 'forcedUpdates.json') + ); + // return all if no project version was found or only changes from "newer" versions otherwise + for (const element of forceIdeConfigUpdate) { + if (!projectVersion || semver.gt(element.version, projectVersion)) { + updates.push( + // adapt it for local file systems + ...element.files.map((item) => path.normalize(item)) + ); + if (element.filesRemove) { + deletes.push( + // adapt it for local file systems + ...element.filesRemove.map((item) => path.normalize(item)) + ); + } + } else { + continue; + } + } } + + return { updates, deletes }; }, + /** * handles creation/update of one config file from the boilerplate at a time - * @param {String[]} fileNameArr 0: path, 1: filename, 2: extension with dot - * @param {String} [fileContent] in case we cannot copy files 1:1 this can be used to pass in content - * @returns {Promise<Boolean>} install successful or error occured + * + * @param {string[]} fileNameArr 0: path, 1: filename, 2: extension with dot + * @param {{updates:string[],deletes:string[]}} relevantForced if fileNameArr is in this list we require an override + * @param {string} [boilerplateFileContent] in case we cannot copy files 1:1 this can be used to pass in content + * @returns {Promise.<boolean>} install successful or error occured */ - async _createIdeConfigFile(fileNameArr, fileContent) { + async _createIdeConfigFile(fileNameArr, relevantForced, boilerplateFileContent) { const fileName = fileNameArr.join(''); const boilerplateFileName = path.resolve( __dirname, @@ -256,41 +442,135 @@ const Init = { 'files', fileName ); - if (File.existsSync(fileName)) { - Util.logger.info(`- ✋ ${fileName} already existing`); - const questions = [ - { - type: 'confirm', - name: 'overrideFile', - message: 'Would you like to override it?', - default: false, - }, - ]; - const responses = await new Promise((resolve) => { - inquirer.prompt(questions).then((answers) => { - resolve(answers); - }); - }); - if (!responses.overrideFile) { - return true; + boilerplateFileContent ||= await File.readFile(boilerplateFileName, 'utf8'); + + /** @type {string} */ + let todo; + + if (await File.pathExists(fileName)) { + if (relevantForced.deletes.includes(path.normalize(fileName))) { + Util.logger.info( + `- ✋ ${fileName} found but it is required to delete it. Commencing rename instead for your convenience:` + ); + // eslint-disable-next-line no-useless-assignment + todo = 'delete'; + } else { + const existingFileContent = await File.readFile(fileName, 'utf8'); + if (existingFileContent === boilerplateFileContent) { + Util.logger.info(`- ✔️ ${fileName} found. No update needed`); + return true; + } + } + + if (relevantForced.updates.includes(path.normalize(fileName))) { + Util.logger.info( + `- ✋ ${fileName} found but an update is required. Commencing with override:` + ); + todo = 'update'; + } else { + Util.logger.info( + `- ✋ ${fileName} found with differences to the new standard version. We recommend updating it.` + ); + if (Util.skipInteraction) { + todo = 'update'; + } else { + const overrideFile = await confirm({ + message: 'Would you like to update (override) it?', + default: true, + }); + if (overrideFile) { + todo = 'update'; + } else { + // skip override without error + return true; + } + } } + + // ensure our update is not leading to data loss in case config files were not versioned correctly by the user + await File.rename(fileName, fileName + '.BAK'); + } else if (!relevantForced.deletes.includes(path.normalize(fileName))) { + todo = 'create'; } - fileContent = fileContent || File.readFileSync(boilerplateFileName, 'utf8'); - const saveStatus = await File.writeToFile( - fileNameArr[0], - fileNameArr[1], - fileNameArr[2].substr(1), - fileContent - ); + if (todo === 'create' || todo === 'update') { + const saveStatus = await File.writeToFile( + fileNameArr[0], + fileNameArr[1], + fileNameArr[2].slice(1), + boilerplateFileContent + ); - if (saveStatus) { - Util.logger.info(`- ✔️ ${fileName} created`); + if (saveStatus) { + Util.logger.info( + `- ✔️ ${fileName} ${ + todo === 'update' + ? `updated (we created a backup of the old file under ${fileName + '.BAK'})` + : 'created' + }` + ); + return true; + } else { + Util.logger.warn( + `- ❌ ${fileName} ${todo === 'update' ? 'update' : 'creation'} failed` + ); + return false; + } + } else if (todo === 'delete') { + await File.rename(fileName, fileName + '.BAK'); + Util.logger.info(`- ✔️ ${fileName} removed (renamed to ${fileName + '.BAK'})`); return true; - } else { - Util.logger.warn(`- ❌ ${fileName} creation failed`); - return false; } }, + + /** + * handles deletion of no longer needed config files + * + * @param {{updates:string[],deletes:string[]}} relevantForced if file is in .deletes, we require deleting/renaming it + * @returns {Promise.<boolean>} deletion successful or error occured + */ + async _removeIdeConfigFiles(relevantForced) { + for (const fileName of relevantForced.deletes) { + if (await File.pathExists(fileName)) { + Util.logger.info( + `- ✋ ${fileName} found but it is required to delete it. Commencing rename instead for your convenience:` + ); + + await File.rename(fileName, fileName + '.BAK'); + Util.logger.info(`- ✔️ ${fileName} removed (renamed to ${fileName + '.BAK'})`); + } + } + return true; + }, + + /** + * helper method for this.upgradeProject that upgrades project config if needed + * + * @returns {Promise.<boolean>} returns true if worked without errors + */ + async upgradeAuthFile() { + if (await File.pathExists(Util.authFileName)) { + const existingAuth = await File.readJSON(Util.authFileName); + // if has credentials key then is old format + if (existingAuth.credentials) { + const newAuth = {}; + for (const cred in existingAuth.credentials) { + newAuth[cred] = { + client_id: existingAuth.credentials[cred].clientId, + client_secret: existingAuth.credentials[cred].clientSecret, + auth_url: `https://${existingAuth.credentials[cred].tenant}.auth.marketingcloudapis.com/`, + account_id: Number.parseInt(existingAuth.credentials[cred].eid), + }; + } + await File.writeJSONToFile( + './', + Util.authFileName.replace(/(.json)+$/, ''), + newAuth + ); + Util.logger.info(`- ✔️ upgraded credential file`); + } + } + return true; + }, }; -module.exports = Init; +export default Init; diff --git a/lib/util/init.git.js b/lib/util/init.git.js index 3e7308276..62498a92f 100644 --- a/lib/util/init.git.js +++ b/lib/util/init.git.js @@ -1,10 +1,11 @@ 'use strict'; +import File from './file.js'; -const File = require('./file'); -const inquirer = require('inquirer'); -const Util = require('./util'); -const commandExists = require('command-exists'); -const git = require('simple-git/promise')(); +import { confirm, input } from '@inquirer/prompts'; +import { Util } from './util.js'; +import commandExists from 'command-exists'; +import { simpleGit } from 'simple-git'; +const git = simpleGit(); /** * CLI helper class @@ -13,31 +14,31 @@ const git = require('simple-git/promise')(); const Init = { /** * check if git repo exists and otherwise create one - * @param {Object} [skipInteraction] signals what to insert automatically for things usually asked via wizard - * @param {String} skipInteraction.gitRemoteUrl URL of Git remote server - * @returns {Promise<{status:String, repoName:String}>} success flag + * + * @returns {Promise.<{status: string, repoName: string}>} success flag */ - async initGitRepo(skipInteraction) { + async initGitRepo() { const result = { status: null, repoName: null }; // check if git is installed (https://www.npmjs.com/package/command-exists) if (!commandExists.sync('git')) { Util.logger.error('Git installation not found.'); Util.logger.error( - 'Please follow our tutorial on installing Git: https://go.accenture.com/mcdevdocs' + 'Please follow our tutorial on installing Git: https://github.com/Accenture/sfmc-devtools#212-install-the-git-command-line' ); result.status = 'error'; return result; } // 3. test if in git repo - const gitRepoFoundInCWD = File.existsSync('.git'); - let newRepoInitialized = null; + const gitRepoFoundInCWD = await File.pathExists('.git'); + /** @type {boolean} */ + let newRepoInitialized; if (gitRepoFoundInCWD) { Util.logger.info(`✔️ Git repository found`); newRepoInitialized = false; } else { Util.logger.warn('No Git repository found. Initializing git:'); - Util.execSync('git', ['init']); - if (File.existsSync('.git')) { + Util.execSync('git', ['init', '--initial-branch=' + Util.defaultGitBranch]); + if (await File.pathExists('.git')) { newRepoInitialized = true; } else { Util.logger.error( @@ -50,7 +51,7 @@ const Init = { Util.logger.info('Ensuring long file paths are not causing issues with git:'); try { Util.execSync('git', ['config', '--local', 'core.longpaths', 'true']); - } catch (ex) { + } catch { Util.logger.warn( `Updating your git config failed. We recommend running the above command manually yourself to avoid issues.` ); @@ -58,29 +59,31 @@ const Init = { Util.logger.info('Ensuring checkout (git pull) as-is and commit Unix-style line endings:'); try { Util.execSync('git', ['config', '--local', 'core.autocrlf', 'input']); - } catch (ex) { + } catch { Util.logger.warn( `Updating your git config failed. We recommend running the above command manually yourself to avoid issues.` ); } // offer to update local user.name and user.email - await this._updateGitConfigUser(skipInteraction); + await this._updateGitConfigUser(); if (newRepoInitialized) { // offer to insert git remote url now - result.repoName = await this._addGitRemote(skipInteraction); + result.repoName = await this._addGitRemote(); } Util.logger.info('✔️ Git initialization done.'); result.status = newRepoInitialized ? 'init' : 'update'; return result; }, + /** * offer to push the new repo straight to the server - * @param {Boolean|Object} [skipInteraction] signals what to insert automatically for things usually asked via wizard - * @returns {void} + * + * @returns {Promise.<void>} - */ - async gitPush(skipInteraction) { + async gitPush() { + const skipInteraction = Util.skipInteraction; const gitRemotes = (await git.getRemotes(true)).filter((item) => item.name === 'origin'); if (gitRemotes.length && gitRemotes[0].refs.push) { // check if remote repo is still empty (otherwise to risky to blindly push) @@ -99,23 +102,14 @@ const Init = { Util.logger.info( `Your remote Git repository is still empty and ready to store your initial backup. Hint: This is the server version of the repo which you share with your team.` ); - let responses; + let gitPush; if (!skipInteraction) { - const questions = [ - { - type: 'confirm', - name: 'gitPush', - message: `Would you like to 'push' your backup to the remote Git repo?`, - default: true, - }, - ]; - responses = await new Promise((resolve) => { - inquirer.prompt(questions).then((answers) => { - resolve(answers); - }); + gitPush = await confirm({ + message: `Would you like to 'push' your backup to the remote Git repo?`, + default: true, }); } - if (skipInteraction || responses.gitPush) { + if (skipInteraction?.gitPush === 'true' || gitPush) { Util.execSync('git', ['push', '-u', 'origin', 'master']); } } else if (remoteBranchesExist === true) { @@ -125,90 +119,80 @@ const Init = { } } }, + /** * offers to add the git remote origin - * @param {Object} [skipInteraction] signals what to insert automatically for things usually asked via wizard - * @param {String} skipInteraction.gitRemoteUrl URL of Git remote server - * @returns {String} repo name (optionally) + * + * @returns {Promise.<string>} repo name (optionally) */ - async _addGitRemote(skipInteraction) { + async _addGitRemote() { + const skipInteraction = Util.skipInteraction; // #1 ask if the user wants to do it now - let responses; + let gitOriginKnown; if (!skipInteraction) { - const questions = [ - { - type: 'confirm', - name: 'gitOriginKnown', - message: `Do you know the remote/clone URL of your Git repo (starts with ssh:// or http:// and ends on '.git')?`, - default: true, - }, - ]; - responses = await new Promise((resolve) => { - inquirer.prompt(questions).then((answers) => { - resolve(answers); - }); + gitOriginKnown = await confirm({ + message: `Do you know the remote/clone URL of your Git repo (starts with ssh:// or http:// and ends on '.git')?`, + default: true, }); } - if (skipInteraction || responses.gitOriginKnown) { + if (skipInteraction || gitOriginKnown) { // #2 if yes, guide the user to input the right url + + let answers = {}; if (skipInteraction) { - responses = skipInteraction; + answers = skipInteraction; } else { - const questions = [ - { - type: 'input', - name: 'gitRemoteUrl', - message: 'Git Remote URL', - validate: (value) => { - value = value.trim(); - if (!value || value.length < 10) { - return 'Please enter a valid remote URL'; - } else if (!value.startsWith('http') && !value.startsWith('ssh')) { - return `Your Git Remote URL should start with 'http' or 'ssh'`; - } else if (!value.endsWith('.git')) { - return `Your Git Remote URL should end with '.git'`; - } else { - // all good - return true; - } - }, + answers.gitRemoteUrl = await input({ + message: 'Git Remote URL', + validate: (value) => { + value = value.trim(); + if (!value || value.length < 10) { + return 'Please enter a valid remote URL'; + } else if (!value.startsWith('http') && !value.startsWith('ssh')) { + return `Your Git Remote URL should start with 'http' or 'ssh'`; + } else if (value.endsWith('.git')) { + // all good + return true; + } else { + return `Your Git Remote URL should end with '.git'`; + } }, - ]; - responses = await new Promise((resolve) => { - inquirer.prompt(questions).then((answers) => { - resolve(answers); - }); }); } - responses.gitRemoteUrl = responses.gitRemoteUrl.trim(); - Util.execSync('git', ['remote', 'add', 'origin', responses.gitRemoteUrl]); - return responses.gitRemoteUrl.split('/').pop().split('.')[0]; + + if (typeof answers.gitRemoteUrl === 'string') { + answers.gitRemoteUrl = answers.gitRemoteUrl.trim(); + Util.execSync('git', ['remote', 'add', 'origin', answers.gitRemoteUrl]); + return answers.gitRemoteUrl.split('/').pop().split('.')[0]; + } } }, + /** * checks global config and ask to config the user info and then store it locally - * @param {Object|Boolean} [skipInteraction] signals what to insert automatically for things usually asked via wizard - * @returns {void} + * + * @returns {Promise.<void>} - */ - async _updateGitConfigUser(skipInteraction) { + async _updateGitConfigUser() { + const skipInteraction = Util.skipInteraction; const gitUser = (await this._getGitConfigUser()) || {}; Util.logger.info( `Please confirm your Git user name & email. It should be in the format 'FirstName LastName' and 'your.email@accenture.com'. The current (potentially wrong) values are provided as default. If correct, confirm with ENTER, otherwise please update:` ); let responses; + + /* eslint-disable unicorn/prefer-ternary */ if (skipInteraction) { responses = { name: gitUser['user.name'], email: gitUser['user.email'], }; } else { - const questions = [ - { - type: 'input', - name: 'name', + responses = { + name: await input({ message: 'Git user.name', default: gitUser['user.name'] || null, - // eslint-disable-next-line require-jsdoc + // eslint-disable-next-line jsdoc/require-jsdoc validate: function (value) { if ( !value || @@ -220,13 +204,11 @@ const Init = { } return true; }, - }, - { - type: 'input', - name: 'email', + }), + email: await input({ message: 'Git user.email', default: gitUser['user.email'] || null, - // eslint-disable-next-line require-jsdoc + // eslint-disable-next-line jsdoc/require-jsdoc validate: function (value) { value = value.trim(); const regex = @@ -236,45 +218,37 @@ const Init = { } return true; }, - }, - ]; - responses = await new Promise((resolve) => { - inquirer.prompt(questions).then((answers) => { - resolve(answers); - }); - }); + }), + }; } + /* eslint-enable unicorn/prefer-ternary */ + if (responses.name && responses.email) { // name can contain spaces - wrap it in quotes const name = `"${responses.name.trim()}"`; const email = responses.email.trim(); - Util.execSync('git', ['config', '--local', 'user.name', name]); - Util.execSync('git', ['config', '--local', 'user.email', email]); + try { + Util.execSync('git', ['config', '--local', 'user.name', name]); + Util.execSync('git', ['config', '--local', 'user.email', email]); + } catch (ex) { + // if project folder is not a git folder then using --local will lead to a fatal error + Util.logger.warn('- Could not update git user name and email'); + Util.logger.debug(ex.message); + } } }, + /** * retrieves the global user.name and user.email values - * @returns {Promise<{'user.name': String, 'user.email': String}>} user.name and user.email + * + * @returns {Promise.<{'user.name': string, 'user.email': string}>} user.name and user.email */ async _getGitConfigUser() { - const gitConfigs = await git.listConfig(); - // remove local config - delete gitConfigs.values['.git/config']; - const result = {}; + const names = await git.getConfig('user.name'); + const emails = await git.getConfig('user.email'); - Object.keys(gitConfigs.values).forEach((file) => { - if (gitConfigs.values[file]['user.name']) { - result['user.name'] = gitConfigs.values[file]['user.name']; - } - if (gitConfigs.values[file]['user.email']) { - result['user.email'] = gitConfigs.values[file]['user.email']; - } - }); - if (!result['user.name'] || !result['user.email']) { - return null; - } - return result; + return { 'user.name': names.value || '', 'user.email': emails.value || '' }; }, }; -module.exports = Init; +export default Init; diff --git a/lib/util/init.js b/lib/util/init.js index 4df030193..b06d79c94 100644 --- a/lib/util/init.js +++ b/lib/util/init.js @@ -1,12 +1,34 @@ 'use strict'; +import Cli from './cli.js'; +import File from './file.js'; +import config from './config.js'; +import InitGit from './init.git.js'; +import InitNpm from './init.npm.js'; +import InitConfig from './init.config.js'; +import { confirm, input, select } from '@inquirer/prompts'; +import { Util } from './util.js'; +import fs from 'node:fs'; +import path from 'node:path'; -const Cli = require('./cli'); -const File = require('./file'); -const InitGit = require('./init.git'); -const InitNpm = require('./init.npm'); -const InitConfig = require('./init.config'); -const inquirer = require('inquirer'); -const Util = require('./util'); +/** + * @typedef {import('../../types/mcdev.d.js').AuthObject} AuthObject + * @typedef {import('../../types/mcdev.d.js').BuObject} BuObject + * @typedef {import('../../types/mcdev.d.js').Cache} Cache + * @typedef {import('../../types/mcdev.d.js').CodeExtract} CodeExtract + * @typedef {import('../../types/mcdev.d.js').CodeExtractItem} CodeExtractItem + * @typedef {import('../../types/mcdev.d.js').DeltaPkgItem} DeltaPkgItem + * @typedef {import('../../types/mcdev.d.js').Mcdevrc} Mcdevrc + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItem} MetadataTypeItem + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItemDiff} MetadataTypeItemDiff + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItemObj} MetadataTypeItemObj + * @typedef {import('../../types/mcdev.d.js').MetadataTypeMap} MetadataTypeMap + * @typedef {import('../../types/mcdev.d.js').MetadataTypeMapObj} MetadataTypeMapObj + * @typedef {import('../../types/mcdev.d.js').MultiMetadataTypeList} MultiMetadataTypeList + * @typedef {import('../../types/mcdev.d.js').MultiMetadataTypeMap} MultiMetadataTypeMap + * @typedef {import('../../types/mcdev.d.js').SoapRequestParams} SoapRequestParams + * @typedef {import('../../types/mcdev.d.js').TemplateMap} TemplateMap + * @typedef {import('../../types/mcdev.d.js').TypeKeyCombo} TypeKeyCombo + */ /** * CLI helper class @@ -15,48 +37,62 @@ const Util = require('./util'); const Init = { /** * Creates template file for properties.json - * @param {Object} properties config file's json - * @param {string} credentialsName identifying name of the installed package / project - * @param {Object} [skipInteraction] signals what to insert automatically for things usually asked via wizard - * @param {String} skipInteraction.clientId client id of installed package - * @param {String} skipInteraction.clientSecret client id of installed package - * @param {String} skipInteraction.tenant client id of installed package - * @param {String} skipInteraction.credentialsName how you would like the credential to be named - * @param {String} skipInteraction.gitRemoteUrl URL of Git remote server - * @returns {Promise<void>} - + * + * @param {Mcdevrc} properties config file's json + * @param {string} [credentialName] identifying name of the installed package / project; if set, will update this credential + * @param {boolean} [refreshBUs] if this was triggered by mcdev join, do not refresh BUs + * @returns {Promise.<void>} - */ - async initProject(properties, credentialsName, skipInteraction) { + async initProject(properties, credentialName, refreshBUs = true) { + if (!(await Init._checkPathForCloud())) { + return; + } + + const skipInteraction = Util.skipInteraction; + if (!properties) { + // try to get cached properties because we return null in case of a crucial error + properties = config.properties; + } const missingCredentials = this._getMissingCredentials(properties); - if (File.existsSync(Util.configFileName) && properties) { + if ((await File.pathExists(Util.configFileName)) && properties) { // config exists - if (credentialsName) { - Util.logger.info(`Updating credential '${credentialsName}'`); + if (credentialName) { // update-credential mode - if (!properties.credentials[credentialsName]) { - Util.logger.error(`Could not find credential '${credentialsName}'`); + if (!properties.credentials[credentialName]) { + Util.logger.error( + `Could not update credential '${credentialName}' because it was not found in your config. Please check your spelling and try again.` + ); + Cli.logExistingCredentials(properties); + if (skipInteraction) { + return; + } const response = await Cli._selectBU(properties, null, true); - credentialsName = response.credential; + credentialName = response.credential; } + Util.logger.info(`Updating existing credential '${credentialName}'`); let error; do { error = false; try { - const success = await Cli.updateCredential( - properties, - credentialsName, - skipInteraction - ); + const success = await Cli.updateCredential(properties, credentialName); if (success) { - Util.logger.info(`✔️ Credential '${credentialsName}' updated.`); + Util.logger.info(`✔️ Credential '${credentialName}' updated.`); } else { error = true; } } catch (ex) { - error = true; + if (skipInteraction) { + Util.logger.error(ex.message); + return; + } else { + // retry + error = true; + } } } while (error && !skipInteraction); Util.logger.debug('reloading config'); - properties = File.loadConfigFile(true); + // eslint-disable-next-line no-useless-assignment + properties = await config.getProperties(true); } else if (missingCredentials.length) { // forced update-credential mode - user likely cloned repo and is missing mcdev-auth.json Util.logger.warn( @@ -74,19 +110,19 @@ const Init = { const success = await Cli.updateCredential( properties, badCredName, - skipInteraction + refreshBUs ); if (success) { Util.logger.info(`✔️ Credential '${badCredName}' updated.`); } else { error = true; } - } catch (ex) { + } catch { error = true; } } while (error); Util.logger.debug('reloading config'); - properties = File.loadConfigFile(true); + properties = await config.getProperties(true); } Util.logger.info('✔️ All credentials updated.'); // assume node dependencies are not installed @@ -97,44 +133,36 @@ const Init = { // add-credential mode Util.logger.warn(Util.configFileName + ' found in root'); - let responses; + let isAddCredential; if (skipInteraction) { if ( - skipInteraction.clientId && - skipInteraction.clientSecret && - skipInteraction.tenant && - skipInteraction.credentialsName + skipInteraction.client_id && + skipInteraction.client_secret && + skipInteraction.auth_url && + skipInteraction.account_id && + skipInteraction.credentialName ) { // assume automated input; only option here is to add a new credential - // requires skipInteraction=={clientId,clientSecret,tenant,credentialsName} + // requires skipInteraction=={client_id,client_secret,auth_url,account_id,credentialName} // will be checked inside of Cli.addExtraCredential() Util.logger.info('Adding another credential'); } else { throw new Error( - '--skipInteraction flag found but missing required input for clientId,clientSecret,tenant,credentialsName' + '--skipInteraction flag found but missing required input for client_id,client_secret,auth_url,account_id,credentialName' ); } } else { - const questions = [ - { - type: 'confirm', - name: 'isAddCredential', - message: 'Do you want to add another credential instead?', - default: false, - }, - ]; - responses = await new Promise((resolve) => { - inquirer.prompt(questions).then((answers) => { - resolve(answers); - }); + isAddCredential = await confirm({ + message: 'Do you want to add another credential instead?', + default: false, }); } let credentialName; - if (skipInteraction || responses.isAddCredential) { - credentialName = await Cli.addExtraCredential(properties, skipInteraction); + if (skipInteraction || isAddCredential) { + credentialName = await Cli.addExtraCredential(properties); } if (credentialName) { - await this._downloadAllBUs(`${credentialName}/*`, 'update', skipInteraction); + await this._downloadAllBUs(`${credentialName}/*`, 'update'); } } } else { @@ -142,28 +170,30 @@ const Init = { // assuming it's the first time this command is run for this project // initialize git repo - const initGit = await InitGit.initGitRepo(skipInteraction); + const initGit = await InitGit.initGitRepo(); if (initGit.status === 'error') { return; } // set up IDE files and load npm dependencies - let status = await this.upgradeProject(properties, true, initGit.repoName); - if (!status) { + + if (!(await this.upgradeProject(properties, true, initGit.repoName))) { return; } // ask for credentials and create mcdev config - status = await Cli.initMcdevConfig(skipInteraction); - if (!status) { + if (!(await Cli.initMcdevConfig())) { return; } + // set up markets and market lists initially + await Init._initMarkets(); + // create first commit to backup the project configuration if (initGit.status === 'init') { Util.logger.info(`Committing initial setup to Git:`); Util.execSync('git', ['add', '.']); - Util.execSync('git', ['commit', '-m', '"Initial commit"', '--quiet']); + Util.execSync('git', ['commit', '-n', '-m', '"Initial commit"', '--quiet']); Util.logger.info(`✔️ Configuration committed`); } @@ -171,7 +201,7 @@ const Init = { await this._downloadAllBUs('"*"', initGit.status); // backup to server - await InitGit.gitPush(skipInteraction); + await InitGit.gitPush(); // all done Util.logger.info('You are now ready to work with Accenture SFMC DevTools!'); @@ -180,37 +210,159 @@ const Init = { ); } }, + + /** + * Creates template file for properties.json + * + * @returns {Promise.<void>} - + */ + async joinProject() { + if (!(await Init._checkPathForCloud())) { + return; + } + + const isJoin = await confirm({ + message: + 'Do you want to join an existing project for which you have a Git-Repository URL?', + default: true, + }); + if (isJoin) { + const gitRepoQs = { + gitRepoUrl: await input({ + message: 'Please enter the Git-Repository URL', + }), + gitBranch: await input({ + message: + 'If you were asked to work on a specific branch, please enter it now (or leave empty for default)', + }), + }; + + const repoName = gitRepoQs.gitRepoUrl.split('/').pop().replace('.git', ''); + // clone repo into current folder + Util.logger.info( + 'Cloning initiated. You might be asked for your Git credentials in a pop-up window in a few seconds.' + ); + Util.execSync( + 'git', + [ + 'clone', + gitRepoQs.gitBranch ? `--branch ${gitRepoQs.gitBranch}` : null, + '--config core.longpaths=true', + '--config core.autocrlf=input', + gitRepoQs.gitRepoUrl, + ].filter(Boolean) + ); + + if (!fs.existsSync(repoName)) { + Util.logger.error( + 'Could not clone repository. Please check your Git-Repository URL as well as your credentials and try again.' + ); + Util.logger.info( + 'Check if you need an "API-Token" instead of your normal user password to authenticate' + ); + return; + } + // make sure we switch to the new subfolder or else the rest will fail + process.chdir(repoName); + + // check if the branch looks good + const properties = await config.getProperties(true, true); + if (!properties) { + Util.logger.error( + 'Could not find .mcdevrc.json file in project folder. Please check your Git repository and branch.' + ); + return; + } + + // get name and email that's to be used for git commits + await InitGit._updateGitConfigUser(); + + // ask the user to enter the server credentials + await this.initProject(properties, null, false); + } else { + return; + } + }, + /** - * helper for this.initProject() - * @param {String} bu cred/bu or cred/* or * - * @param {String} gitStatus signals what state the git repo is in - * @param {Boolean|Object} [skipInteraction] signals what to insert automatically for things usually asked via wizard - * @returns {Promise<void>} - + * helper for {@link Init.initProject} that optionally creates markets and market lists for all BUs */ - async _downloadAllBUs(bu, gitStatus, skipInteraction) { - let responses; + async _initMarkets() { + const skipInteraction = Util.skipInteraction; + const properties = await config.getProperties(true); + + // get list of business units + const firstCredentialName = Object.keys(properties.credentials)[0]; + const businessUnits = Object.keys( + properties.credentials[firstCredentialName].businessUnits + ); + + // set up empty markets for them + const markets = {}; + for (const bu of businessUnits) { + markets[bu] = { suffix: '_' + bu }; + } + properties.markets = markets; + + let sourceBuName; + // set up default deployment market lists + if (skipInteraction) { + // don't ask, list all BUs in deployment-target and set deployment-source to ??? + if (!businessUnits.includes(skipInteraction.developmentBu)) { + Util.logger.warn( + `Could not find developmentBu=${skipInteraction.developmentBu} in business units. Skipping.` + ); + delete skipInteraction.developmentBu; + } + sourceBuName = skipInteraction.developmentBu || '???'; + if (!skipInteraction.developmentBu) { + Util.logger.info( + 'Market List "deployment-source" will need to be set up manually. Marking all BUs as target BUs in "deployment-target".' + ); + } + } else { + sourceBuName = await select({ + message: 'Please select your development business unit:', + choices: businessUnits.map((bu) => ({ name: bu, value: bu })), + }); + } + // set source list + properties.marketList['deployment-source'][firstCredentialName + '/' + sourceBuName] = + sourceBuName; + + // set target list + for (const bu of businessUnits) { + // filter out source BU & parent BU to ensure they dont get deployed to automatically + if (bu !== sourceBuName && bu !== '_ParentBU_') { + properties.marketList['deployment-target'][firstCredentialName + '/' + bu] = bu; + } + } + await File.saveConfigFile(properties); + }, + + /** + * helper for {@link Init.initProject} + * + * @param {string} bu cred/bu or cred/* or * + * @param {string} gitStatus signals what state the git repo is in + * @returns {Promise.<void>} - + */ + async _downloadAllBUs(bu, gitStatus) { + const skipInteraction = Util.skipInteraction; + let initialRetrieveAll; if (!skipInteraction) { - const questions = [ - { - type: 'confirm', - name: 'initialRetrieveAll', - message: 'Do you want to start downloading all Business Units (recommended)?', - default: true, - }, - ]; - responses = await new Promise((resolve) => { - inquirer.prompt(questions).then((answers) => { - resolve(answers); - }); + initialRetrieveAll = await confirm({ + message: 'Do you want to start downloading all Business Units (recommended)?', + default: true, }); } - if (skipInteraction || responses.initialRetrieveAll) { + if (skipInteraction?.downloadBUs === 'true' || initialRetrieveAll) { Util.execSync('mcdev', ['retrieve', bu]); if (gitStatus === 'init') { Util.logger.info(`Committing first backup of your SFMC instance:`); Util.execSync('git', ['add', '.']); - Util.execSync('git', ['commit', '-m', '"First instance backup"', '--quiet']); + Util.execSync('git', ['commit', '-n', '-m', '"First instance backup"', '--quiet']); Util.logger.info(`✔️ SFMC instance backed up`); } else if (gitStatus === 'update') { Util.logger.warn( @@ -224,16 +376,22 @@ const Init = { } } }, + /** * wrapper around npm dependency & configuration file setup - * @param {Object} properties config file's json - * @param {Boolean} [initial] print message if not part of initial setup - * @param {String} [repoName] if git URL was provided earlier, the repo name was extracted to use it for npm init - * @returns {Promise<Boolean>} success flag + * + * @param {Mcdevrc} properties config file's json + * @param {boolean} [initial] print message if not part of initial setup + * @param {string} [repoName] if git URL was provided earlier, the repo name was extracted to use it for npm init + * @returns {Promise.<boolean>} success flag */ async upgradeProject(properties, initial, repoName) { - let status; + if (!(await Init._checkPathForCloud())) { + return; + } + let status; + const versionBeforeUpgrade = properties?.version || '0.0.0'; if (!initial) { Util.logger.info( 'Upgrading project with newest configuration, npm dependencies & other project configurations:' @@ -244,10 +402,15 @@ const Init = { if (!status) { return false; } + // version 4 release to simplify auth + status = await InitConfig.upgradeAuthFile(); + if (!status) { + return false; + } } // create files before installing dependencies to ensure .gitignore is properly set up - status = await InitConfig.createIdeConfigFiles(); + status = await InitConfig.createIdeConfigFiles(versionBeforeUpgrade); if (!status) { return false; } @@ -260,23 +423,90 @@ const Init = { return true; }, + + /** + * check if git repo is being saved on a cloud service and warn the user + * + * @private + * @returns {Promise.<boolean>} true if path is good; false if project seems to be in a cloud service folder + */ + async _checkPathForCloud() { + const absolutePath = path.resolve(''); + // popular cloud services and their respective default name for the absolute path + // * CloudDocs is the default folder name for iCloud + const cloudServices = ['Dropbox', 'OneDrive', 'Google Drive', 'iCloud', 'CloudDocs']; + let cloudServiceFound = false; + for (const variable in cloudServices) { + if (absolutePath.includes(cloudServices[variable])) { + Util.logger.warn( + `It seems your project folder will be synchronized via '${ + cloudServices[variable] === 'CloudDocs' ? 'iCloud' : cloudServices[variable] + }'. This can reduce the overall performance of your computer due to conflicts with Git.` + ); + Util.logger.warn( + `We strongly recommend moving your project folder outside of the '${ + cloudServices[variable] === 'CloudDocs' ? 'iCloud' : cloudServices[variable] + }' folder.` + ); + cloudServiceFound = true; + } + } + if (!cloudServiceFound && absolutePath.includes(process.env.USERPROFILE)) { + // warn user to not place project folder into user profile folder + Util.logger.warn( + `It seems your project folder is located in your user profile's default folder which is often synchronized to webservices like ${cloudServices.join( + ', ' + )}. This can reduce the overall performance of your computer due to conflicts between with Git.` + ); + Util.logger.warn( + `We strongly recommend moving your project folder outside of this folder.` + ); + cloudServiceFound = true; + } + if (cloudServiceFound) { + const ignoreCloudWarning = await confirm({ + message: 'Do you want to continue anyways?', + default: false, + }); + if (!ignoreCloudWarning) { + Util.logger.error('Exiting due to cloud service warning'); + return false; + } + } + return true; + }, + /** * finds credentials that are set up in config but not in auth file - * @param {object} properties javascript object in .mcdevrc.json - * @returns {String[]} list of credential names + * + * @private + * @param {Mcdevrc} properties javascript object in .mcdevrc.json + * @returns {string[]} list of credential names */ _getMissingCredentials(properties) { let missingCredentials; - if (properties && properties.credentials) { + if (properties?.credentials) { + // reload auth file because for some reason we didnt want that in our main properties object + let auth; + try { + auth = File.readJsonSync(Util.authFileName); + } catch { + // file not found + auth = []; + } + // walk through config credentials and check if the matching credential in the auth file is missing something missingCredentials = Object.keys(properties.credentials).filter( (cred) => - !properties.credentials[cred].clientId || - !properties.credentials[cred].clientSecret || - !properties.credentials[cred].tenant + !auth[cred] || + !auth[cred].account_id || + properties.credentials[cred].eid != auth[cred].account_id || + !auth[cred].client_id || + !auth[cred].client_secret || + !auth[cred].auth_url ); } return missingCredentials || []; }, }; -module.exports = Init; +export default Init; diff --git a/lib/util/init.npm.js b/lib/util/init.npm.js index 740f203cc..6ce27879e 100644 --- a/lib/util/init.npm.js +++ b/lib/util/init.npm.js @@ -1,9 +1,11 @@ 'use strict'; -const File = require('./file'); -const inquirer = require('inquirer'); -const path = require('path'); -const Util = require('./util'); +import File from './file.js'; +import path from 'node:path'; +import { Util } from './util.js'; +import semver from 'semver'; +import { fileURLToPath } from 'node:url'; +const __dirname = path.dirname(fileURLToPath(import.meta.url)); /** * CLI helper class @@ -14,15 +16,16 @@ const Init = { * initiates npm project and then * takes care of loading the pre-configured dependency list * from the boilerplate directory to them as dev-dependencies - * @param {String} [repoName] if git URL was provided earlier, the repo name was extracted to use it for npm init - * @returns {Promise<Boolean>} install successful or error occured + * + * @param {string} [repoName] if git URL was provided earlier, the repo name was extracted to use it for npm init + * @returns {Promise.<boolean>} install successful or error occured */ async installDependencies(repoName) { let fileContent; let projectPackageJson; - if (File.existsSync('package.json')) { + if (await File.pathExists('package.json')) { try { - fileContent = File.readFileSync('package.json', 'utf8'); + fileContent = await File.readFile('package.json', 'utf8'); } catch (ex) { Util.logger.error( 'Your package.json was found but seems to be corrupted: ' + ex.message @@ -42,20 +45,22 @@ const Init = { repoName || currentFolderName .toLowerCase() - .replace(/[^a-z0-9 ]/gi, '') - .replace(/ /gi, '-'); + .replaceAll(/[^a-z0-9 ]/gi, '') + .replaceAll(/ /gi, '-'); projectPackageJson = { name: standardNpmName }; this._getDefaultPackageJson(projectPackageJson); await File.writeToFile('./', 'package', 'json', JSON.stringify(projectPackageJson)); // execute "no questions asked" npm init - Util.execSync('npm', ['init', '--yes']); + Util.execSync('npm', ['init', '--yes'], true); try { - fileContent = File.readFileSync('package.json', 'utf8'); + fileContent = await File.readFile('package.json', 'utf8'); if (fileContent) { projectPackageJson = JSON.parse(fileContent); } + // type="module" is solely required for the new flat configs of ESLint >=9 + Util.execSync('npm', ['pkg', 'set', 'type="module"'], true); Util.logger.info('✔️ package.json created'); - } catch (ex) { + } catch { Util.logger.error('No package.json found. Please run "npm init" manually'); return false; } @@ -67,64 +72,75 @@ const Init = { Util.boilerplateDirectory, 'npm-dependencies.json' ); - if (!File.existsSync(dependencyFile)) { + if (!(await File.pathExists(dependencyFile))) { Util.logger.debug(`Dependency file not found in ${dependencyFile}`); return false; } - const defaultDependencies = File.readJsonSync(dependencyFile); + const defaultDependencies = await File.readJSON(dependencyFile); + const versionsDefault = {}; + for (const name of defaultDependencies) { + // check mcdev.devDependencies first + versionsDefault[name] = Object.keys(Util.packageJsonMcdev.dependencies).includes(name) + ? Util.packageJsonMcdev.dependencies[name] + : // then check mcdev.devDependencies + Object.keys(Util.packageJsonMcdev.devDependencies).includes(name) + ? Util.packageJsonMcdev.devDependencies[name] + : // fallback to using latest version if not found + 'latest'; + } + const versionsProject = {}; + if (projectPackageJson.devDependencies) { + for (const name of defaultDependencies) { + // check project.devDependencies + versionsProject[name] = Object.keys(projectPackageJson.devDependencies).includes( + name + ) + ? projectPackageJson.devDependencies[name].replace(/^[\^~]/, '') + : // fallback to invalid version if not found + '0.0.0'; + } + } const loadDependencies = defaultDependencies.filter( (name) => !projectPackageJson || !projectPackageJson.devDependencies || - !projectPackageJson.devDependencies[name] + !projectPackageJson.devDependencies[name] || + versionsDefault[name] == 'latest' || + // filters out file:.. references instead of versions that would otherwise lead to an error in semver.gt() + !semver.valid(versionsProject[name]) || + semver.gt(versionsDefault[name], versionsProject[name]) ); - if (loadDependencies.length < defaultDependencies.length) { - Util.logger.info( - `✔️ ${ - !loadDependencies.length ? 'All' : 'Some' - } default dependencies are already installed: ` + defaultDependencies.join(', ') - ); - const questions = [ - { - type: 'confirm', - name: 'runUpdate', - message: 'Would you like to attempt updating them?', - default: true, - }, - ]; - const responses = await new Promise((resolve) => { - inquirer.prompt(questions).then((answers) => { - resolve(answers); - }); - }); - if (responses.runUpdate) { - loadDependencies.length = 0; - loadDependencies.push(...defaultDependencies); - } - } if (loadDependencies.length) { - Util.logger.info('Installing Dependencies:'); - const args = ['install', '--save-dev'].concat(loadDependencies); + Util.logger.info('Installing/Updating Dependencies:'); + const args = ['install', '--save-dev'].concat( + loadDependencies.map((name) => `${name}@${versionsDefault[name]}`) + ); Util.execSync('npm', args); Util.logger.info('✔️ Dependencies installed.'); + } else { + Util.logger.info( + `✔️ All default dependencies are already installed: ` + + defaultDependencies.map((name) => `${name}@${versionsProject[name]}`).join(', ') + ); } return true; }, + /** * ensure we have certain default values in our config - * @param {Object} [currentContent] what was read from existing package.json file - * @returns {Promise<{script: Object, author: String, license: String}>} extended currentContent + * + * @param {object} [currentContent] what was read from existing package.json file + * @returns {Promise.<{script: object, author: string, license: string}>} extended currentContent */ async _getDefaultPackageJson(currentContent) { - currentContent = currentContent || {}; + currentContent ||= {}; // #1 scripts const predefinedCommandList = { build: 'sfmc-build all', 'build-cp': 'sfmc-build cloudPages', 'build-email': 'sfmc-build emails', - upgrade: 'npm-check --update', 'eslint-check': 'eslint', }; if (!currentContent.scripts) { @@ -141,8 +157,12 @@ const Init = { if (!currentContent.license || currentContent.license === 'ISC') { currentContent.license = 'UNLICENSED'; } + if (!currentContent.type || currentContent.type !== 'module') { + // type="module" is solely required for the new flat configs of ESLint >=9 + currentContent.type = 'module'; + } return currentContent; }, }; -module.exports = Init; +export default Init; diff --git a/lib/util/replaceContentBlockReference.js b/lib/util/replaceContentBlockReference.js new file mode 100644 index 000000000..2d960b0d2 --- /dev/null +++ b/lib/util/replaceContentBlockReference.js @@ -0,0 +1,350 @@ +'use strict'; + +import auth from './auth.js'; +import cache from './cache.js'; +import File from './file.js'; +import { Util } from '../util/util.js'; + +import Folder from '../metadataTypes/Folder.js'; +import Asset from '../metadataTypes/Asset.js'; + +/** + * @typedef {import('../../types/mcdev.d.js').AuthObject} AuthObject + * @typedef {import('../../types/mcdev.d.js').BuObject} BuObject + * @typedef {import('../../types/mcdev.d.js').Cache} Cache + * @typedef {import('../../types/mcdev.d.js').CodeExtract} CodeExtract + * @typedef {import('../../types/mcdev.d.js').CodeExtractItem} CodeExtractItem + * @typedef {import('../../types/mcdev.d.js').DeltaPkgItem} DeltaPkgItem + * @typedef {import('../../types/mcdev.d.js').McdevLogger} McdevLogger + * @typedef {import('../../types/mcdev.d.js').Logger} Logger + * @typedef {import('../../types/mcdev.d.js').Mcdevrc} Mcdevrc + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItem} MetadataTypeItem + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItemDiff} MetadataTypeItemDiff + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItemObj} MetadataTypeItemObj + * @typedef {import('../../types/mcdev.d.js').MetadataTypeMap} MetadataTypeMap + * @typedef {import('../../types/mcdev.d.js').MetadataTypeMapObj} MetadataTypeMapObj + * @typedef {import('../../types/mcdev.d.js').MultiMetadataTypeList} MultiMetadataTypeList + * @typedef {import('../../types/mcdev.d.js').MultiMetadataTypeMap} MultiMetadataTypeMap + * @typedef {import('../../types/mcdev.d.js').SkipInteraction} SkipInteraction + * @typedef {import('../../types/mcdev.d.js').SoapRequestParams} SoapRequestParams + * @typedef {import('../../types/mcdev.d.js').TemplateMap} TemplateMap + * @typedef {import('../../types/mcdev.d.js').TypeKeyCombo} TypeKeyCombo + * @typedef {import('../../types/mcdev.d.js').SDKError} SDKError + * + * @typedef {import('../../types/mcdev.d.js').AssetMap} AssetMap + * @typedef {import('../../types/mcdev.d.js').AssetItemSimple} AssetItemSimple + * @typedef {import('../../types/mcdev.d.js').AssetItemSimpleMap} AssetItemSimpleMap + * @typedef {import('../../types/mcdev.d.js').AssetItemIdSimpleMap} AssetItemIdSimpleMap + * @typedef {import('../../types/mcdev.d.js').ContentBlockConversionTypes} ContentBlockConversionTypes + */ + +/** + * Util that contains logger and simple util methods + */ +export default class ReplaceContentBlockReference { + /** @type {{id: AssetItemIdSimpleMap, key: AssetItemSimpleMap, name: AssetItemSimpleMap}} */ + static assetCacheMap = { + id: {}, + key: {}, + name: {}, + }; + /** @type {Object.<string, {id: RegExp[], key: RegExp[], name: RegExp[]}>} */ + static #regexBy = { + // TODO: handle cases in which variables or functions are passed into ContentBlockByX + + amp: { + id: [ + /ContentBlockById\(\s*"([0-9]+)"\s*\)/gim, + /ContentBlockById\(\s*'([0-9]+)'\s*\)/gim, + /ContentBlockById\(\s*([0-9]+)\s*\)/gim, + ], + key: [ + /ContentBlockByKey\(\s*"([a-z0-9-/._][ a-z0-9-/._]+[a-z0-9-/._])"\s*\)/gim, + /ContentBlockByKey\(\s*'([a-z0-9-/._][ a-z0-9-/._]+[a-z0-9-/._])'\s*\)/gim, + ], + name: [ + /ContentBlockByName\(\s*"([ a-z0-9-\\._)(]+)"\s*\)/gim, + /ContentBlockByName\(\s*'([ a-z0-9-\\._)(]+)'\s*\)/gim, + ], + }, + ssjs: { + id: [ + /Platform.Function.ContentBlockById\(\s*"([0-9]+)"\s*\)/gim, + /Platform.Function.ContentBlockById\(\s*'([0-9]+)'\s*\)/gim, + /Platform.Function.ContentBlockById\(\s*([0-9]+)\s*\)/gim, + ], + key: [ + /Platform.Function.ContentBlockByKey\(\s*"([a-z0-9-/._][ a-z0-9-/._]+[a-z0-9-/._])"\s*\)/gim, + /Platform.Function.ContentBlockByKey\(\s*'([a-z0-9-/._][ a-z0-9-/._]+[a-z0-9-/._])'\s*\)/gim, + ], + name: [ + /Platform.Function.ContentBlockByName\(\s*"([ a-z0-9-\\._)(]+)"\s*\)/gim, + /Platform.Function.ContentBlockByName\(\s*'([ a-z0-9-\\._)(]+)'\s*\)/gim, + ], + }, + }; + + /** + * helper for tests + */ + static resetCacheMap() { + this.assetCacheMap = { + id: {}, + key: {}, + name: {}, + }; + } + + /** + * used to equalize the reference in the code to whatever is set in the "to" field + * + * @param {string} str full code string + * @param {string} parentName name of the object that was passed in; used in error message only + * @param {Set.<string>} [findAssetKeys] list of keys that were found referenced via ContentBlockByX; if set, method only gets keys and runs no updates + * @returns {string} replaced string + */ + static replaceReference(str, parentName, findAssetKeys) { + if (!str) { + const ex = new Error('No string provided'); + // @ts-expect-error custom error object + ex.code = 200; + throw ex; + } + /** @type {ContentBlockConversionTypes[]} */ + const fromList = Util.OPTIONS.referenceFrom; + /** @type {ContentBlockConversionTypes} */ + const to = Util.OPTIONS.referenceTo; + let result = str; + let changes = 0; + const languages = [ + { name: 'ssjs', isSsjs: true }, + { name: 'amp', isSsjs: false }, + ]; + for (const from of fromList) { + for (const lang of languages) { + for (const regex of this.#regexBy[lang.name][from]) { + result = result.replaceAll(regex, (match, identifier) => { + const referencedAsset = this.#getAssetBy( + from, + identifier, + parentName, + lang.isSsjs, + !!findAssetKeys + ); + if (referencedAsset && referencedAsset[to]) { + // make sure we not only found the asset but also have a replacement for it (folder issue could block swap to ContentBlockByName) + changes++; + if (findAssetKeys) { + findAssetKeys.add(referencedAsset.key); + return; + } else { + return this.#replaceWith(referencedAsset, to, lang.isSsjs); + } + } else { + if (referencedAsset && !referencedAsset[to]) { + // this is expected to only happen if to=="name" + Util.logger.error( + ` - ${parentName}: Asset ${from} ${identifier} has no valid ${to} reference` + ); + } else if (!referencedAsset && findAssetKeys) { + const newError = new Error(`${identifier}`); + // @ts-expect-error custom error object + newError.code = 404; + throw newError; + } + return match; + } + }); + } + } + } + if (!changes) { + const ex = new Error('No changes made to the code.'); + // @ts-expect-error custom error object + ex.code = 200; + throw ex; + } + return result; + } + + /** + * + * @param {ContentBlockConversionTypes} from replace with + * @param {string|number} identifier id, key or name of asset + * @param {string} parentName name of the object that was passed in; used in error message only + * @param {boolean} [isSsjs] replaces backslashes with double backslashes in name if true + * @param {boolean} [handleOutside] don not print error message if asset not found + * @returns {AssetItemSimple} asset object + */ + static #getAssetBy(from, identifier, parentName, isSsjs = false, handleOutside = false) { + let reference; + switch (from) { + case 'id': { + reference = ReplaceContentBlockReference.assetCacheMap.id[identifier]; + break; + } + case 'key': { + reference = ReplaceContentBlockReference.assetCacheMap.key[identifier]; + break; + } + case 'name': { + if (isSsjs && typeof identifier === 'string') { + identifier = identifier.replaceAll('\\\\', '\\'); + } + reference = ReplaceContentBlockReference.assetCacheMap.name[identifier]; + break; + } + } + if (!reference && !handleOutside) { + Util.logger.error(` - ${parentName}: Asset not found for ${from} ${identifier}`); + } + return reference; + } + + /** + * + * @param {AssetItemSimple} asset asset object + * @param {ContentBlockConversionTypes} to replace with + * @param {boolean} [isSsjs] replaces backslashes with double backslashes in name if true + * @returns {string} replaced string + */ + static #replaceWith(asset, to, isSsjs = false) { + switch (to) { + case 'id': { + return `${isSsjs ? 'Platform.Function.' : ''}ContentBlockById(${asset.id})`; + } + case 'key': { + return `${isSsjs ? 'Platform.Function.' : ''}ContentBlockByKey("${asset.key}")`; + } + case 'name': { + return `${isSsjs ? 'Platform.Function.' : ''}ContentBlockByName("${isSsjs ? asset.name.replaceAll('\\', '\\\\') : asset.name}")`; + } + } + } + + /** + * ensures we cache the right things from disk and if required from server + * + * @param {Mcdevrc} properties properties for auth + * @param {BuObject} buObject properties for auth + * @param {boolean} [retrieveSharedOnly] for --dependencies only, do not have to re-retrieve local assets + * @returns {Promise.<void>} - + */ + static async createCache(properties, buObject, retrieveSharedOnly = false) { + const { localAssets, sharedAssets } = await ReplaceContentBlockReference._retrieveCache( + buObject, + properties, + retrieveSharedOnly + ); + + ReplaceContentBlockReference.createCacheForMap(localAssets); + ReplaceContentBlockReference.createCacheForMap(sharedAssets); + } + + /** + * helper for {@link ReplaceContentBlockReference.createCache} that converts AssetMap into AssetItemSimple entries in this.assetCacheMap + * + * @param {AssetMap} metadataMap list of local or shared assets + */ + static createCacheForMap(metadataMap) { + for (const element of Object.values(metadataMap)) { + // create actual cache map + /** @type {AssetItemSimple} */ + const simpleAsset = { + id: element.id, + key: element.customerKey, + // ! note that ContentBlockByName expects backslashes between folders and file name, not forward slashes + name: element.r__folder_Path + ? element.r__folder_Path.replaceAll('/', '\\') + '\\' + element.name + : null, + }; + // if this method was filled by Asset.upsert it might have been run before with more accurate (retrieved) data including the id that we do not want to override + this.assetCacheMap.key[simpleAsset.key] ||= simpleAsset; + if (simpleAsset.id) { + // if this method was filled by Asset.upsert it won't have ids + this.assetCacheMap.id[simpleAsset.id] = simpleAsset; + } + if (simpleAsset.name) { + // while asset without path could still be found via search, it would no longer referencable via ContentBlockByName + // if this method was filled by Asset.upsert it might have been run before with more accurate (retrieved) data including the id that we do not want to override + this.assetCacheMap.name[simpleAsset.name] ||= simpleAsset; + } + } + } + + /** + * helper for {@link ReplaceContentBlockReference.createCache} + * + * @param {BuObject} buObject references credentials + * @param {Mcdevrc} properties central properties object + * @param {boolean} [retrieveSharedOnly] for --dependencies only, do not have to re-retrieve local assets + * @returns {Promise.<{localAssets: AssetMap, sharedAssets: AssetMap}>} - + */ + static async _retrieveCache(buObject, properties, retrieveSharedOnly = false) { + const client = auth.getSDK(buObject); + + if (!cache.getCache()) { + cache.initCache(buObject); + } + Util.logger.info(' - Caching folders'); + Folder.buObject = buObject; + Folder.properties = properties; + Folder.client = client; + const resultFolder = await Folder.retrieveForCache(null, ['asset', 'asset-shared']); + cache.setMetadata('folder', resultFolder.metadata); + + let localAssets; + if (retrieveSharedOnly) { + Util.logger.debug(' - Caching assets locally'); + if (!Asset.getJsonFromFSCache) { + // avoid re-reading the same files in every recursive iteration + Asset.getJsonFromFSCache = await Asset.getJsonFromFS( + File.normalizePath([ + properties.directories.retrieve, + buObject.credential, + buObject.businessUnit, + Asset.definition.type, + ]) + ); + } + localAssets = Asset.getJsonFromFSCache; + cache.setMetadata('asset', Asset.getJsonFromFSCache); + } else { + Util.logger.info(' - Caching assets from server'); + Asset.buObject = buObject; + Asset.properties = properties; + Asset.client = client; + const resultAsset = await Asset.retrieveForCache( + undefined, + Asset.definition.crosslinkedSubTypes + ); + for (const element of Object.values(resultAsset.metadata)) { + // ensure we got the folder-path in our cache + Asset.setFolderPath(element); + } + localAssets = resultAsset.metadata; + cache.setMetadata('asset', resultAsset.metadata); + } + + // get shared assets + Util.logger.info(' - Caching shared assets from server (not stored on disk)'); + Asset.buObject = buObject; + Asset.properties = properties; + Asset.client = client; + const sharedAssets = ( + await Asset.retrieveForCache( + undefined, + Asset.definition.crosslinkedSubTypes, + undefined, + true + ) + )?.metadata; + // lets not put the shared assets into our cache to avoid confusing the system... + + for (const element of Object.values(sharedAssets)) { + // ensure we got the folder-path in our cache + Asset.setFolderPath(element); + } + return { localAssets, sharedAssets }; + } +} diff --git a/lib/util/util.js b/lib/util/util.js index 3675af114..1bb9849e1 100644 --- a/lib/util/util.js +++ b/lib/util/util.js @@ -1,162 +1,379 @@ 'use strict'; +import MetadataDefinitions from './../MetadataTypeDefinitions.js'; +import process from 'node:process'; +import toposort from 'toposort'; +import winston from 'winston'; +import child_process from 'node:child_process'; +import path from 'node:path'; +// import just to resolve cyclical - TO DO consider if could move to file or context +import { readJsonSync } from 'fs-extra/esm'; +import { fileURLToPath } from 'node:url'; +const __dirname = path.dirname(fileURLToPath(import.meta.url)); + /** - * @ignore @typedef {import('sfmc-fuelsdk-node')} ET_Client - * - * @typedef {Object} BuObject - * @property {String} clientId installed package client id - * @property {String} clientSecret installed package client secret - * @property {String} tenant subdomain part of Authentication Base Uri - * @property {String} [eid] Enterprise ID = MID of the parent BU - * @property {String} [mid] MID of the BU to work with - * @property {String} [businessUnit] name of the BU to interact with - * @property {String} [credential] name of the credential to interact with - */ -/** - * @typedef {Object.<string,string>} TemplateMap + * @typedef {import('../../types/mcdev.d.js').AuthObject} AuthObject + * @typedef {import('../../types/mcdev.d.js').BuObject} BuObject + * @typedef {import('../../types/mcdev.d.js').Cache} Cache + * @typedef {import('../../types/mcdev.d.js').CodeExtract} CodeExtract + * @typedef {import('../../types/mcdev.d.js').CodeExtractItem} CodeExtractItem + * @typedef {import('../../types/mcdev.d.js').DeltaPkgItem} DeltaPkgItem + * @typedef {import('../../types/mcdev.d.js').McdevLogger} McdevLogger + * @typedef {import('../../types/mcdev.d.js').Logger} Logger + * @typedef {import('../../types/mcdev.d.js').Mcdevrc} Mcdevrc + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItem} MetadataTypeItem + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItemDiff} MetadataTypeItemDiff + * @typedef {import('../../types/mcdev.d.js').MetadataTypeItemObj} MetadataTypeItemObj + * @typedef {import('../../types/mcdev.d.js').MetadataTypeMap} MetadataTypeMap + * @typedef {import('../../types/mcdev.d.js').MetadataTypeMapObj} MetadataTypeMapObj + * @typedef {import('../../types/mcdev.d.js').MultiMetadataTypeList} MultiMetadataTypeList + * @typedef {import('../../types/mcdev.d.js').MultiMetadataTypeMap} MultiMetadataTypeMap + * @typedef {import('../../types/mcdev.d.js').SkipInteraction} SkipInteraction + * @typedef {import('../../types/mcdev.d.js').SoapRequestParams} SoapRequestParams + * @typedef {import('../../types/mcdev.d.js').TemplateMap} TemplateMap + * @typedef {import('../../types/mcdev.d.js').TypeKeyCombo} TypeKeyCombo + * @typedef {import('../../types/mcdev.d.js').SDKError} SDKError */ -/** @type ET_Client */ -const ET_Client = require('sfmc-fuelsdk-node'); -const fs = require('fs-extra'); // ! do not switch to util/file.js to avoid circular dependency -const MetadataDefinitions = require('./../MetadataTypeDefinitions'); -const packageJsonMcdev = require('../../package.json'); -const path = require('path'); -const toposort = require('toposort'); -const winston = require('winston'); -const inquirer = require('inquirer'); -const child_process = require('child_process'); -const semver = require('semver'); - /** * Util that contains logger and simple util methods */ -const Util = { +export const Util = { authFileName: '.mcdev-auth.json', boilerplateDirectory: '../../boilerplate', configFileName: '.mcdevrc.json', + defaultGitBranch: 'main', parentBuName: '_ParentBU_', standardizedSplitChar: '/', - expectedAuthScope: [ - 'accounts_read', - 'accounts_write', - 'approvals_read', - 'approvals_write', - 'audiences_read', - 'audiences_write', - 'automations_execute', - 'automations_read', - 'automations_write', - 'calendar_read', - 'calendar_write', - 'campaign_read', - 'campaign_write', - 'data_extensions_read', - 'data_extensions_write', - 'documents_and_images_read', - 'documents_and_images_write', - 'email_read', - 'email_send', - 'email_write', - 'event_notification_callback_create', - 'event_notification_callback_delete', - 'event_notification_callback_read', - 'event_notification_callback_update', - 'event_notification_subscription_create', - 'event_notification_subscription_delete', - 'event_notification_subscription_read', - 'event_notification_subscription_update', - 'file_locations_read', - 'file_locations_write', - 'journeys_execute', - 'journeys_read', - 'journeys_write', - 'key_manage_revoke', - 'key_manage_rotate', - 'key_manage_view', - 'list_and_subscribers_read', - 'list_and_subscribers_write', - 'marketing_cloud_connect_read', - 'marketing_cloud_connect_send', - 'marketing_cloud_connect_write', - 'offline', - 'ott_channels_read', - 'ott_channels_write', - 'ott_chat_messaging_read', - 'ott_chat_messaging_send', - 'push_read', - 'push_send', - 'push_write', - 'saved_content_read', - 'saved_content_write', - 'sms_read', - 'sms_send', - 'sms_write', - 'social_post', - 'social_publish', - 'social_read', - 'social_write', - 'tags_read', - 'tags_write', - 'tracking_events_read', - 'tracking_events_write', - 'users_read', - 'users_write', - 'web_publish', - 'web_read', - 'web_write', - 'webhooks_read', - 'webhooks_write', - 'workflows_read', - 'workflows_write', - ], - /** - * SFMC accepts multiple true values for Boolean attributes for which we are checking here + /** used to replace '/' in folder names to avoid confusion with the path separator */ + folderNameSlashEscapeChar: '\u2215', + /** @type {SkipInteraction} */ + skipInteraction: null, + packageJsonMcdev: readJsonSync(path.join(__dirname, '../../package.json')), + OPTIONS: {}, + changedKeysMap: {}, + matchedByName: {}, + + /** + * helper that allows filtering an object by its keys + * + * @param {Object.<string,*>} originalObj object that you want to filter + * @param {string[]} [whitelistArr] positive filter. if not provided, returns originalObj without filter + * @returns {Object.<string,*>} filtered object that only contains keys you provided + */ + filterObjByKeys(originalObj, whitelistArr) { + if (!whitelistArr || !Array.isArray(whitelistArr)) { + return originalObj; + } + return Object.keys(originalObj) + .filter((key) => whitelistArr.includes(key)) + .reduce((obj, key) => { + obj[key] = originalObj[key]; + return obj; + }, {}); + }, + + /** + * extended Array.includes method that allows check if an array-element starts with a certain string + * + * @param {string[]} arr your array of strigns + * @param {string} search the string you are looking for + * @returns {boolean} found / not found + */ + includesStartsWith(arr, search) { + return this.includesStartsWithIndex(arr, search) >= 0; + }, + + /** + * extended Array.includes method that allows check if an array-element starts with a certain string + * + * @param {string[]} arr your array of strigns + * @param {string} search the string you are looking for + * @returns {number} array index 0..n or -1 of not found + */ + includesStartsWithIndex(arr, search) { + return Array.isArray(arr) ? arr.findIndex((el) => el.startsWith(search)) : -1; + }, + + /** + * check if a market name exists in current mcdev config + * + * @param {string} market market localizations + * @param {Mcdevrc} properties local mcdev config + * @returns {boolean} found market or not + */ + checkMarket(market, properties) { + if (properties.markets[market]) { + return true; + } else { + Util.logger.error(`Could not find the market '${market}' in your configuration file.`); + const marketArr = Object.keys(properties.markets); + + if (marketArr.length) { + Util.logger.info('Available markets are: ' + marketArr.join(', ')); + } + return false; + } + }, + + /** + * check if a market name exists in current mcdev config + * + * @param {string[]} marketArr market localizations + * @param {Mcdevrc} properties local mcdev config + * @returns {boolean} found market or not + */ + checkMarketList(marketArr, properties) { + if (marketArr[0] !== '__clone__') { + // if __clone__ is passed, we don't want to actually change anything but simply clone the metadata as-is + for (const market of marketArr) { + if (!Util.checkMarket(market, properties)) { + return false; + } + } + } + return true; + }, + + /** + * ensure provided MarketList exists and it's content including markets and BUs checks out + * + * @param {string} mlName name of marketList + * @param {Mcdevrc} properties General configuration to be used in retrieve + */ + verifyMarketList(mlName, properties) { + if (properties.marketList[mlName]) { + // ML exists, check if it is properly set up + + // check if BUs in marketList are valid + let buCounter = 0; + for (const businessUnit in properties.marketList[mlName]) { + if (businessUnit !== 'description' && businessUnit !== 'filter') { + buCounter++; + Util.isValidBU(properties, businessUnit, true); + if (!Util.isValidBU(properties, businessUnit, true)) { + throw new Error(`'${businessUnit}' in Market ${mlName} is not defined.`); + } + + // check if markets are valid + let marketArr = properties.marketList[mlName][businessUnit]; + if ('string' === typeof marketArr) { + marketArr = [marketArr]; + } + for (const market of marketArr) { + if (properties.markets[market]) { + // * markets can be empty or include variables. Nothing we can test here + } else { + throw new Error(`Market '${market}' is not defined.`); + } + } + } + } + if (!buCounter) { + throw new Error(`No BUs defined in marketList ${mlName}`); + } + } else { + // ML does not exist + throw new Error(`Market List ${mlName} is not defined`); + } + }, + /** + * + * @param {string | TypeKeyCombo} selectedTypes supported metadata type + * @param {string[]} [keyArr] name/key of the metadata + * @param {string} [commandName] for log output only + * @returns {TypeKeyCombo | undefined} true if everything is valid; false otherwise + */ + checkAndPrepareTypeKeyCombo(selectedTypes, keyArr, commandName) { + if ('string' === typeof selectedTypes) { + // ensure we have TypeKeyCombo here + /** @type {TypeKeyCombo} */ + selectedTypes = this.createTypeKeyCombo(selectedTypes, keyArr); + } + // check if types are valid + for (const type of Object.keys(selectedTypes)) { + if (!this._isValidType(type)) { + return; + } + if (!Array.isArray(selectedTypes[type]) || !selectedTypes[type].length) { + this.logger.error( + 'You need to define keys, not just types to run ' + (commandName || '') + ); + // we need an array of keys here + return; + } + // ensure keys are sorted to enhance log readability + selectedTypes[type].sort(); + } + return selectedTypes; + }, + + /** + * used to ensure the program tells surrounding software that an unrecoverable error occured + * + * @returns {void} + */ + signalFatalError() { + // Util.logger.debug('Util.signalFataError() sets process.exitCode = 1 unless already set'); + process.exitCode ||= 1; + }, + + /** + * SFMC accepts multiple true values for Boolean attributes for which we are checking here. + * The same problem occurs when evaluating boolean CLI flags + * * @param {*} attrValue value * @returns {boolean} attribute value == true ? true : false */ isTrue(attrValue) { - return ['true', 'TRUE', 'True', '1', 1, 'Y'].includes(attrValue); + return ['true', 'TRUE', 'True', '1', 1, 'Y', 'y', true].includes(attrValue); }, + /** - * SFMC accepts multiple false values for Boolean attributes for which we are checking here + * SFMC accepts multiple false values for Boolean attributes for which we are checking here. + * The same problem occurs when evaluating boolean CLI flags + * * @param {*} attrValue value * @returns {boolean} attribute value == false ? true : false */ isFalse(attrValue) { - return ['false', 'FALSE', 'False', '0', 0, 'N'].includes(attrValue); + return ['false', 'FALSE', 'False', '0', 0, 'N', 'n', false].includes(attrValue); + }, + /** + * helper to test if two variables are equal + * + * @param {string | number | boolean | Array | object} item1 - + * @param {string | number | boolean | Array | object} item2 - + * @returns {boolean} equal or not + */ + isEqual: function (item1, item2) { + if (item1 === item2) { + return true; + } + if (typeof item1 !== typeof item2) { + return false; + } + if (Array.isArray(item1) && Array.isArray(item2)) { + return this._isEqualArray(item1, item2); + } + if (typeof item1 === 'object') { + return this._isEqualObject(item1, item2); + } + return false; + }, + /** + * helper to test if two arrays are equal + * + * @param {Array} array1 - + * @param {Array} array2 - + * @returns {boolean} equal or not + */ + _isEqualArray: function (array1, array2) { + return ( + array1.length === array2.length && + array1.every((val) => array2.includes(val)) && + array2.every((val) => array1.includes(val)) + ); + }, + /** + * helper to test if two objects are equal + * + * @param {object} item1 - + * @param {object} item2 - + * @returns {boolean} equal or not + */ + _isEqualObject: function (item1, item2) { + if (!this._isEqualArray(Object.keys(item1), Object.keys(item2))) { + return false; + } + for (const key in item1) { + if (!this.isEqual(item1[key], item2[key])) { + return false; + } + } + return true; + }, + + /** + * helper for Mcdev.retrieve, Mcdev.retrieveAsTemplate and Mcdev.deploy + * + * @param {string} selectedType type or type-subtype + * @param {boolean} [handleOutside] if the API reponse is irregular this allows you to handle it outside of this generic method + * @returns {boolean} type ok or not + */ + _isValidType(selectedType, handleOutside) { + const { type, subType } = Util.getTypeAndSubType(selectedType); + if (type && !MetadataDefinitions[type]) { + if (!handleOutside) { + Util.logger.error(`:: '${type}' is not a valid metadata type`); + } + return false; + } else if ( + type && + subType && + (!MetadataDefinitions[type] || !MetadataDefinitions[type].subTypes.includes(subType)) + ) { + if (!handleOutside) { + Util.logger.error(`:: '${selectedType}' is not a valid metadata type`); + } + return false; + } + return true; }, /** - * defines how the properties.json should look like - * used for creating a template and for checking if variables are set + * helper for Mcdev.retrieve, Mcdev.retrieveAsTemplate and Mcdev.deploy * - * @returns {object} default properties + * @param {Mcdevrc} properties javascript object in .mcdevrc.json + * @param {string} businessUnit name of BU + * @param {boolean} [handleOutside] if the API reponse is irregular this allows you to handle it outside of this generic method + * @returns {boolean} bu found or not */ - getDefaultProperties: function () { - const configFileName = path.resolve(__dirname, this.boilerplateDirectory, 'config.json'); - if (!fs.existsSync(configFileName)) { - this.logger.debug(`Default config file file not found in ${configFileName}`); + isValidBU(properties, businessUnit, handleOutside) { + const [cred, bu] = businessUnit ? businessUnit.split('/') : [null, null]; + if (!properties.credentials[cred]) { + if (!handleOutside) { + Util.logger.error(`Credential not found`); + } + return false; + } else if (!properties.credentials[cred].businessUnits[bu]) { + if (!handleOutside) { + Util.logger.error(`BU not found in credential`); + } return false; } - const defaultProperties = fs.readJsonSync(configFileName); - // set default name for parent BU - defaultProperties.credentials.default.businessUnits[this.parentBuName] = '000000000'; - // set default retrieve values - defaultProperties.metaDataTypes.retrieve = this.getRetrieveTypeChoices(); + return true; + }, - return defaultProperties; + /** + * helper that deals with extracting type and subtype + * + * @param {string} selectedType "type" or "type-subtype" + * @returns {{type:string, subType:string}} first elem is type, second elem is subType + */ + getTypeAndSubType(selectedType) { + if (selectedType) { + const temp = selectedType.split('-'); + const type = temp.shift(); // remove first item which is the main typ + const subType = temp.join('-'); // subType can include "-" + return { type, subType }; + } else { + return { type: null, subType: null }; + } }, + /** * helper for getDefaultProperties() + * + * @param {'typeRetrieveByDefault'|'typeCdpByDefault'} field relevant field in type definition * @returns {string[]} type choices */ - getRetrieveTypeChoices() { + getTypeChoices(field) { const typeChoices = []; for (const el in MetadataDefinitions) { if ( - Array.isArray(MetadataDefinitions[el].typeRetrieveByDefault) || - MetadataDefinitions[el].typeRetrieveByDefault === true + Array.isArray(MetadataDefinitions[el][field]) || + MetadataDefinitions[el][field] === true ) { // complex types like assets are saved as array but to ease upgradability we // save the main type only unless the user deviates from our pre-selection. @@ -175,236 +392,223 @@ const Util = { return 0; }); - return typeChoices; + return typeChoices.filter(Boolean); }, /** - * check if the config file is correctly formatted and has values + * helper for cli.selectTypes and init.config.fixMcdevConfig that converts subtypes back to main type if all and only defaults were selected + * this keeps the config automatically upgradable when we add new subtypes or change what is selected by default * - * @param {object} properties javascript object in .mcdevrc.json - * @param {boolean} [silent] set to true for internal use w/o cli output - * @returns {boolean|String[]} file structure ok OR list of fields to be fixed + * @param {'typeRetrieveByDefault'|'typeCdpByDefault'} field relevant field in type definition + * @param {string[]} selectedTypes what types the user selected + * @param {'asset'} [type] metadata type + * @returns {string[]} filtered selectedTypes */ - checkProperties: function (properties, silent) { - if (!fs.existsSync(Util.configFileName) || !properties) { - Util.logger.error(`\nCould not find ${Util.configFileName} in ${process.cwd()}.`); - Util.logger.error(`Run 'mcdev init' to initialize your project.\n`); - return false; - } - if (!fs.existsSync(Util.authFileName) || !properties) { - Util.logger.error(`\nCould not find ${Util.authFileName} in ${process.cwd()}.`); - Util.logger.error(`Run 'mcdev init' to initialize your project.\n`); - return false; - } + summarizeSubtypes(field, selectedTypes, type = 'asset') { + const selectedAssetSubtypes = selectedTypes.filter((str) => str.includes(type + '-')); + /** @type {string[]|boolean} */ + const config = MetadataDefinitions[type][field]; + if (Array.isArray(config) && selectedAssetSubtypes.length === config.length) { + const nonDefaultSelectedAssetSubtypes = selectedAssetSubtypes + .map((subtype) => subtype.replace(type + '-', '')) + .filter((subtype) => !config.includes(subtype)); + if (!nonDefaultSelectedAssetSubtypes.length) { + // found all defaults and nothing else. replace with main type + selectedTypes = selectedTypes.filter((str) => !str.includes(type + '-')); - // check if user is running older mcdev version than whats saved to the config - if (properties.version && semver.gt(properties.version, packageJsonMcdev.version)) { - // dont run this for Catalyst to MC DevTools migration - Util.logger.error( - `Your Accenture SFMC DevTools version ${packageJsonMcdev.version} is lower than your project's config version ${properties.version}` - ); - const questions = [ - { - type: 'confirm', - name: 'runUpgradeNow', - message: `Do you want to run 'npm update -g mcdev' now? This may take a few minutes.`, - default: true, - }, - ]; - inquirer.prompt(questions).then((responses) => { - if (responses.runUpgradeNow) { - // use _execSync here to avoid a circular dependency - this.execSync('npm', ['update', '-g', 'mcdev']); - } - }); - return false; - } - - // check config properties - const defaultProps = this.getDefaultProperties(); - const errorMsgs = []; - const solutionSet = new Set(); - const missingFields = []; - for (const key in defaultProps) { - if (Object.prototype.hasOwnProperty.call(defaultProps, key)) { - if (!Object.prototype.hasOwnProperty.call(properties, key)) { - errorMsgs.push(`${key}{} missing`); - solutionSet.add( - `Run 'mcdev upgrade' to fix missing or changed configuration options` - ); - missingFields.push(key); - } else { - if (!silent && key === 'credentials') { - if (!Object.keys(properties.credentials)) { - errorMsgs.push(`no Credential defined`); - } else { - for (const cred in properties.credentials) { - if (cred.includes('/') || cred.includes('\\')) { - errorMsgs.push( - `Credential names may not includes slashes: ${cred}` - ); - solutionSet.add('Apply manual fix in your config.'); - } - if ( - !properties.credentials[cred].clientId || - properties.credentials[cred].clientId === '--- update me ---' - ) { - errorMsgs.push(`invalid ClientId on ${cred}`); - solutionSet.add(`Run 'mcdev init ${cred}'`); - } - if ( - !properties.credentials[cred].clientSecret || - properties.credentials[cred].clientSecret === - '--- update me ---' - ) { - errorMsgs.push(`invalid ClientSecret on ${cred}`); - solutionSet.add(`Run 'mcdev init ${cred}'`); - } - if ( - !properties.credentials[cred].tenant || - properties.credentials[cred].tenant === '--- update me ---' - ) { - errorMsgs.push(`invalid tenant on ${cred}`); - solutionSet.add(`Run 'mcdev init ${cred}'`); - } - if ( - !properties.credentials[cred].eid || - properties.credentials[cred].eid === '000000000' - ) { - errorMsgs.push(`invalid eid on ${cred}`); - solutionSet.add(`Run 'mcdev init ${cred}'`); - } - let i = 0; - for (const buName in properties.credentials[cred].businessUnits) { - if (buName.includes('/') || buName.includes('\\')) { - errorMsgs.push( - `Business Unit names may not includes slashes: ${cred}: ${buName}` - ); - solutionSet.add(`Run 'mcdev reloadBUs ${cred}'`); - } - if ( - Object.prototype.hasOwnProperty.call( - properties.credentials[cred].businessUnits, - buName - ) && - properties.credentials[cred].businessUnits[buName] !== - '000000000' - ) { - i++; - } - } - if (!i) { - errorMsgs.push(`no Business Units defined`); - solutionSet.add(`Run 'mcdev reloadBUs ${cred}'`); - } - } - } - } else if (['directories', 'metaDataTypes', 'options'].includes(key)) { - for (const subkey in defaultProps[key]) { - if ( - Object.prototype.hasOwnProperty.call(defaultProps[key], subkey) && - !Object.prototype.hasOwnProperty.call(properties[key], subkey) - ) { - errorMsgs.push( - `${key}.${subkey} missing. Default value (${ - Array.isArray(defaultProps[key][subkey]) - ? 'Array' - : typeof defaultProps[key][subkey] - }): ${defaultProps[key][subkey]}` - ); - solutionSet.add( - `Run 'mcdev upgrade' to fix missing or changed configuration options` - ); - missingFields.push(`${key}.${subkey}`); - } else if (subkey === 'deployment') { - for (const dkey in defaultProps[key][subkey]) { - if ( - Object.prototype.hasOwnProperty.call( - defaultProps[key][subkey], - dkey - ) && - !Object.prototype.hasOwnProperty.call( - properties[key][subkey], - dkey - ) - ) { - errorMsgs.push( - `${key}.${subkey} missing. Default value (${ - Array.isArray(defaultProps[key][subkey][dkey]) - ? 'Array' - : typeof defaultProps[key][subkey][dkey] - }): ${defaultProps[key][subkey][dkey]}` - ); - solutionSet.add( - `Run 'mcdev upgrade' to fix missing or changed configuration options` - ); - missingFields.push(`${key}.${subkey}.${dkey}`); - } - } - } - } - } - } + selectedTypes.push(type); } } - // check if project config version is outdated compared to user's mcdev version - if (!properties.version || semver.gt(packageJsonMcdev.version, properties.version)) { - errorMsgs.push( - `Your project's config version ${properties.version} is lower than your Accenture SFMC DevTools version ${packageJsonMcdev.version}` - ); - solutionSet.add(`Run 'mcdev upgrade' to ensure optimal performance`); - missingFields.push('version'); + selectedTypes.sort(); + return selectedTypes; + }, + + /** @type {string} last used timestamp to create log filename with */ + logFileName: null, + + /** + * wrapper around our standard winston logging to console and logfile + * + * @param {boolean} [noLogFile] optional flag to indicate if we should log to file; CLI logs are always on + * @returns {object} initiated logger for console and file + */ + _createNewLoggerTransport: function (noLogFile = false) { + // { + // error: 0, + // warn: 1, + // info: 2, + // http: 3, + // verbose: 4, + // debug: 5, + // silly: 6 + // } + + if ( + process.env.FORK_PROCESS_ID || // run via Git-Fork + process.env.PATH.toLowerCase().includes('sourcetree') // run via Atlassian SourceTree + ) { + Util.OPTIONS.noLogColors = true; } - if (silent) { - return missingFields; - } else { - if (errorMsgs.length) { - const errorMsgOutput = [ - `Found problems in your ./${Util.configFileName} that you need to fix first:`, - ]; - for (const msg of errorMsgs) { - errorMsgOutput.push(' - ' + msg); - } - Util.logger.error(errorMsgOutput.join('\n')); - Util.logger.info( - [ - 'Here is what you can do to fix these issues:', - ...Array.from(solutionSet), - ].join('\n- ') - ); - const questions = [ - { - type: 'confirm', - name: 'runUpgradeNow', - message: `Do you want to run 'mcdev upgrade' now?`, - default: true, - }, - ]; - inquirer.prompt(questions).then((responses) => { - if (responses.runUpgradeNow) { - // use _execSync here to avoid a circular dependency - this.execSync('mcdev', ['upgrade']); - } + Util.logFileName = new Date().toISOString().split(':').join('.'); + const transports = { + console: new winston.transports.Console({ + // Write logs to Console + level: Util.OPTIONS.loggerLevel || 'info', + format: winston.format.combine( + Util.OPTIONS.noLogColors + ? winston.format.uncolorize() + : winston.format.colorize(), + winston.format.timestamp({ format: 'HH:mm:ss' }), + winston.format.simple(), + winston.format.printf( + (info) => `${info.timestamp} ${info.level}: ${info.message}` + ) + ), + }), + }; + if (!noLogFile) { + transports.file = new winston.transports.File({ + // Write logs to logfile + filename: 'logs/' + Util.logFileName + '.log', + level: 'debug', // log everything + format: winston.format.combine( + winston.format.uncolorize(), + winston.format.timestamp({ format: 'HH:mm:ss.SSS' }), + winston.format.simple(), + winston.format.printf( + (info) => `${info.timestamp} ${info.level}: ${info.message}` + ) + ), + }); + if (Util.OPTIONS.errorLog) { + // used by CI/CD solutions like Copado to quickly show the error message to admins/users + transports.fileError = new winston.transports.File({ + // Write logs to additional error-logfile for better visibility of errors + filename: 'logs/' + Util.logFileName + '-errors.log', + level: 'error', // only log errors + lazy: true, // if true, log files will be created on demand, not at the initialization time. + format: winston.format.combine( + winston.format.uncolorize(), + winston.format.timestamp({ format: 'HH:mm:ss.SSS' }), + winston.format.simple(), + winston.format.printf( + (info) => `${info.timestamp} ${info.level}: ${info.message}` + ) + ), }); - - return false; - } else { - return true; } } + return transports; }, + loggerTransports: null, /** * Logger that creates timestamped log file in 'logs/' directory + * + * @type {Logger} */ logger: null, - restartLogger: startLogger, + + /** + * initiate winston logger + * + * @param {boolean} [restart] if true, logger will be restarted; otherwise, an existing logger will be used + * @param {boolean} [noLogFile] if false, logger will log to file; otherwise, only to console + * @returns {void} + */ + startLogger: function (restart = false, noLogFile = false) { + if ( + !( + Util.loggerTransports === null || + restart || + (!Util.loggerTransports?.file && !noLogFile && !Util.OPTIONS?.noLogFile) + ) + ) { + // logger already started + return; + } + Util.loggerTransports = this._createNewLoggerTransport( + noLogFile || Util.OPTIONS?.noLogFile + ); + const myWinston = winston.createLogger({ + level: Util.OPTIONS.loggerLevel, + levels: winston.config.npm.levels, + transports: Object.values(Util.loggerTransports), + }); + const winstonError = myWinston.error; + /** @type {McdevLogger} */ + const winstonExtension = { + /** + * helper that prints better stack trace for errors + * + * @param {SDKError} ex the error + * @param {string} [message] optional custom message to be printed as error together with the exception's message + * @returns {void} + */ + errorStack: function (ex, message) { + if (message) { + // ! this method only sets exitCode=1 if message-param was set + // if not, then this method purely outputs debug information and should not change the exitCode + winstonError(`${message}: ${ex.message}${ex.code ? ' (' + ex.code + ')' : ''}`); + if (ex.endpoint) { + // ex.endpoint is only available if 'ex' is of type RestError + winstonError(' endpoint: ' + ex.endpoint); + } + Util.signalFatalError(); + } else { + myWinston.debug(`${ex.message}${ex.code ? ' (' + ex.code + ')' : ''}`); + if (ex.endpoint) { + // ex.endpoint is only available if 'ex' is of type RestError + myWinston.debug(' endpoint: ' + ex.endpoint); + } + } + let stack; + /* eslint-disable unicorn/prefer-ternary */ + if ( + [ + 'ETIMEDOUT', + 'EHOSTUNREACH', + 'ENOTFOUND', + 'ECONNRESET', + 'ECONNABORTED', + ].includes(ex.code) + ) { + // the stack would just return a one-liner that does not help + stack = new Error().stack; // eslint-disable-line unicorn/error-message + } else { + stack = ex.stack; + } + /* eslint-enable unicorn/prefer-ternary */ + myWinston.debug(stack); + }, + + /** + * errors should cause surrounding applications to take notice + * hence we overwrite the default error function here + * + * @param {string} msg - the message to log + * @returns {void} + */ + error: function (msg) { + winstonError(msg); + Util.signalFatalError(); + }, + }; + Util.logger = Object.assign(myWinston, winstonExtension); + + const processArgv = process.argv.slice(2); + Util.logger.debug( + `:: mcdev ${Util.packageJsonMcdev.version} :: ⚡ mcdev ${processArgv.join(' ')}` + ); + }, + /** * Logger helper for Metadata functions - * @param {String} level of log (error, info, warn) - * @param {String} type of metadata being referenced - * @param {String} method name which log was called from + * + * @param {string} level of log (error, info, warn) + * @param {string} type of metadata being referenced + * @param {string} method name which log was called from * @param {*} payload generic object which details the error - * @param {String} [source] key/id of metadata which relates to error + * @param {string} [source] key/id of metadata which relates to error * @returns {void} */ metadataLogger: function (level, type, method, payload, source) { @@ -423,12 +627,14 @@ const Util = { Util.logger[level](`${type}.${method}: ${prependSource}${JSON.stringify(payload)}`); } }, + /** * replaces values in a JSON object string, based on a series of * key-value pairs (obj) - * @param {String|Object} str JSON object or its stringified version, which has values to be replaced + * + * @param {string | object} str JSON object or its stringified version, which has values to be replaced * @param {TemplateMap} obj key value object which contains keys to be replaced and values to be replaced with - * @returns {String|Object} replaced version of str + * @returns {string | object} replaced version of str */ replaceByObject: function (str, obj) { let convertType = false; @@ -445,11 +651,9 @@ const Util = { } } - sortable.sort(function (a, b) { - return b[1].length - a[1].length; - }); + sortable.sort((a, b) => b[1].length - a[1].length); for (const pair of sortable) { - const escVal = pair[1].replace(/[-/\\^$*+?.()|[\]{}]/g, '\\$&'); + const escVal = pair[1].toString().replaceAll(/[-/\\^$*+?.()|[\]{}]/g, String.raw`\$&`); const regString = new RegExp(escVal, 'g'); str = str.replace(regString, '{{{' + pair[0] + '}}}'); } @@ -458,11 +662,13 @@ const Util = { } return str; }, + /** * get key of an object based on the first matching value - * @param {Object} objs object of objects to be searched - * @param {String} val value to be searched for - * @returns {String} key + * + * @param {object} objs object of objects to be searched + * @param {string | number} val value to be searched for + * @returns {string} key */ inverseGet: function (objs, val) { for (const obj in objs) { @@ -473,324 +679,686 @@ const Util = { throw new Error(`${val} not found in object`); }, + /** + *helper for Mcdev.fixKeys. Retrieve dependent metadata + * + * @param {string} fixedType type of the metadata passed as a parameter to fixKeys function + * @returns {string[]} array of types that depend on the given type + */ + getDependentMetadata(fixedType) { + const dependencies = new Set(); + + for (const dependentType of Object.keys(MetadataDefinitions)) { + if (MetadataDefinitions[dependentType].dependencies.includes(fixedType)) { + // fixedType was found as a dependency of dependentType + dependencies.add(dependentType); + } else if ( + MetadataDefinitions[dependentType].dependencies.some((dependency) => + dependency.startsWith(fixedType + '-') + ) + ) { + // if MetadataTypeDefinitions[dependentType].dependencies start with type then also add dependentType to the set; use some to check if any of the dependencies start with type + dependencies.add(dependentType); + } + } + return [...dependencies]; + }, + /** * Returns Order in which metadata needs to be retrieved/deployed - * @param {String[]} metadataTypes which should be retrieved/deployed - * @returns {String[]} retrieve/deploy order as array + * + * @param {string[]} typeArr which should be retrieved/deployed + * @returns {Object.<string, string[]>} retrieve/deploy order as array */ - getMetadataHierachy(metadataTypes) { + getMetadataHierachy(typeArr) { const dependencies = []; // loop through all metadata types which are being retrieved/deployed const subTypeDeps = {}; - for (const metadataType of metadataTypes) { - const type = metadataType.split('-')[0]; + for (const typeSubType of typeArr) { + const type = typeSubType.split('-')[0]; // if they have dependencies then add a dependency pair for each type if (MetadataDefinitions[type].dependencies.length > 0) { dependencies.push( ...MetadataDefinitions[type].dependencies.map((dep) => { if (dep.includes('-')) { // log subtypes to be able to replace them if main type is also present - subTypeDeps[dep.split('-')[0]] = - subTypeDeps[dep.split('-')[0]] || new Set(); + subTypeDeps[dep.split('-')[0]] ||= new Set(); subTypeDeps[dep.split('-')[0]].add(dep); } - return [dep, metadataType]; + return [dep, typeSubType]; }) ); } // if they have no dependencies then just add them with undefined. else { - dependencies.push([undefined, metadataType]); + dependencies.push([undefined, typeSubType]); } } + const allDeps = dependencies.map((dep) => dep[0]); // remove subtypes if main type is in the list - Object.keys(subTypeDeps) - // only look at subtype deps that are also supposed to be retrieved fully - .filter((type) => metadataTypes.includes(type)) - // Rewrite the subtype dependecies to main types. - .forEach((type) => { - // convert set into array to walk its elements - [...subTypeDeps[type]].forEach((subType) => { - dependencies.forEach((item) => { - if (item[0] === subType) { - // if subtype recognized, replace with main type - item[0] = type; - } - }); - }); - }); + for (const type of Object.keys(subTypeDeps) + // only look at subtype deps that are also supposed to be retrieved or cached fully + .filter((type) => typeArr.includes(type) || allDeps.includes(type))) { + // convert set into array to walk its elements + for (const subType of subTypeDeps[type]) { + for (const item of dependencies) { + if (item[0] === subType) { + // if subtype recognized, replace with main type + item[0] = type; + } + } + } + } // sort list & remove the undefined dependencies - return toposort(dependencies).filter((a) => !!a); + const flatList = toposort(dependencies).filter((a) => !!a); + /** @type {Object.<string, null | Set.<string>>} */ + const setList = {}; + // group subtypes per type + for (const flatType of flatList) { + if (flatType.includes('-')) { + const { type, subType } = Util.getTypeAndSubType(flatType); + if (setList[type] === null) { + // if main type is already required, then don't filter by subtypes + continue; + } else if (setList[type] && subType) { + // add another subtype to the set + setList[type].add(subType); + continue; + } else { + // create a new set with the first subtype; subKey will be always set here + setList[type] = new Set([subType]); + } + if (subTypeDeps[type]) { + // check if there are depndent subtypes that need to be added + /** @type {string[]} */ + const temp = [...subTypeDeps[type]].map((a) => { + const temp = a.split('-'); + temp.shift(); // remove first item which is the main type + return temp.join('-'); // subType can include "-" + }); + for (const item of temp) { + setList[type].add(item); + } + } + } else { + setList[flatType] = null; + } + } + // convert sets into arrays + /** @type {Object.<string, string[]>} */ + const finalList = {}; + + for (const type of Object.keys(setList)) { + finalList[type] = setList[type] instanceof Set ? [...setList[type]] : null; + } + + return finalList; + }, + + /** + * let's you dynamically walk down an object and get a value + * + * @param {string} path 'fieldA.fieldB.fieldC' + * @param {object} obj some parent object + * @returns {any} value of obj.path + */ + resolveObjPath(path, obj) { + return path.split('.').reduce((prev, curr) => (prev ? prev[curr] : null), obj); }, + /** - * signs in with SFMC + * helper to run other commands as if run manually by user * - * @param {BuObject} buObject properties for auth - * @returns {Promise<ET_Client>} auth object + * @param {string} cmd to be executed command + * @param {string[]} [args] list of arguments + * @param {boolean} [hideOutput] if true, output of command will be hidden from CLI + * @returns {string|void} output of command if hideOutput is true */ - async getETClient(buObject) { - /** @type ET_Client */ - const myClient = new ET_Client(buObject.clientId, buObject.clientSecret, null, { - authOptions: { - authVersion: 2, - accountId: buObject.mid, - }, - globalReqOptions: {}, - authOrigin: 'https://' + buObject.tenant + '.auth.marketingcloudapis.com', - origin: null, - soapOrigin: null, - }); + execSync(cmd, args, hideOutput) { + args ||= []; + Util.logger.info('⚡ ' + cmd + ' ' + args.join(' ')); + try { - // check credentials to allow clear log output and stop execution - const test = await myClient.FuelAuthClient.getAccessToken(); - if (test.error) { - throw new Error(test.error_description); - } else if (test.scope) { - // find missing rights - const currentScope = test.scope.split(' '); - const missingAccess = Util.expectedAuthScope.filter( - (element) => !currentScope.includes(element) - ); - const excessAccess = currentScope.filter( - (element) => !Util.expectedAuthScope.includes(element) - ); - if (excessAccess.length) { - Util.logger.debug('Extra access found:' + excessAccess.join(', ')); - } - if (missingAccess.length) { - Util.logger.warn( - 'Installed package has insufficient access. You might encounter malfunctions!' - ); - Util.logger.warn('Missing scope: ' + missingAccess.join(', ')); - } + if (hideOutput) { + // no output displayed to user but instead returned to parsed elsewhere + return child_process + .execSync(cmd + ' ' + args.join(' ')) + .toString() + .trim(); + } else { + // the following options ensure the user sees the same output and + // interaction options as if the command was manually run + child_process.execSync(cmd + ' ' + args.join(' '), { stdio: [0, 1, 2] }); + return null; } - } catch (ex) { - throw new Error(ex.message); + } catch { + // avoid errors from execSync to bubble up + return null; } - return myClient; }, /** - * standardized method for getting data from cache. + * standardize check to ensure only one result is returned from template search * - * @param {Object} cache data retrieved from sfmc instance - * @param {String} metadataType metadata type ie. query - * @param {String} searchValue unique identifier of metadata being looked for - * @param {String} searchField field name (key in object) which contains the unique identifer - * @param {String} returnField field which should be returned - * @returns {String} unique user definable metadata key (usually external/customer key) + * @param {MetadataTypeItem[]} results array of metadata + * @param {string} keyToSearch the field which contains the searched value + * @param {string} searchValue the value which is being looked for + * @returns {MetadataTypeItem} metadata to be used in building template */ - getFromCache(cache, metadataType, searchValue, searchField, returnField) { - for (const key in cache[metadataType]) { - if (Util.resolveObjPath(searchField, cache[metadataType][key]) == searchValue) { - try { - if (Util.resolveObjPath(returnField, cache[metadataType][key])) { - return Util.resolveObjPath(returnField, cache[metadataType][key]); - } else { - throw new Error(); - } - } catch (ex) { - throw new Error( - `${metadataType} with ${searchField} '${searchValue}' does not have field '${returnField}'` - ); - } - } + templateSearchResult(results, keyToSearch, searchValue) { + const matching = results.filter((item) => item[keyToSearch] === searchValue); + + if (matching.length === 0) { + throw new Error(`No metadata found with name "${searchValue}"`); + } else if (matching.length > 1) { + throw new Error( + `Multiple metadata with name "${searchValue}" please rename to be unique to avoid issues` + ); + } else { + return matching[0]; } - throw new Error( - `Missing one or more dependent metadata. ${metadataType} with ${searchField}='${searchValue}' was not found on your BU` + }, + + /** + * configures what is displayed in the console + * + * @param {object} argv list of command line parameters given by user + * @param {boolean} [argv.silent] only errors printed to CLI + * @param {boolean} [argv.verbose] chatty user CLI output + * @param {boolean} [argv.debug] enables developer output & features + * @returns {void} + */ + setLoggingLevel(argv) { + if (argv.silent) { + // only errors printed to CLI + Util.OPTIONS.loggerLevel = 'error'; + Util.logger.debug('CLI logger set to: silent'); + } else if (argv.verbose) { + // chatty user cli logs + Util.OPTIONS.loggerLevel = 'verbose'; + Util.logger.debug('CLI logger set to: verbose'); + } else { + // default user cli logs + Util.OPTIONS.loggerLevel = 'info'; + Util.logger.debug('CLI logger set to: info / default'); + } + if (argv.debug) { + // enables developer output & features. no change to actual logs + Util.OPTIONS.loggerLevel = 'debug'; + Util.logger.debug('CLI logger set to: debug'); + } + if (Util.loggerTransports?.console) { + Util.loggerTransports.console.level = Util.OPTIONS.loggerLevel; + } + if (Util.logger) { + Util.logger.level = Util.OPTIONS.loggerLevel; + } + }, + + /** + * outputs a warning that the given type is still in beta + * + * @param {string} type api name of the type thats in beta + */ + logBeta(type) { + Util.logger.warn( + ` - 🚧 ${type} support is currently still in beta. Please report any issues here: https://github.com/Accenture/sfmc-devtools/issues/new/choose` ); }, + /** - * let's you dynamically walk down an object and get a value - * @param {String} path 'fieldA.fieldB.fieldC' - * @param {Object} obj some parent object - * @returns {any} value of obj.path + * outputs a warning that the given method is deprecated + * + * @param {string} method name of the method + * @param {string} [useInstead] optionally specify which method to use instead */ - resolveObjPath(path, obj) { - return path.split('.').reduce(function (prev, curr) { - return prev ? prev[curr] : null; - }, obj); + logDeprecated(method, useInstead = '') { + Util.logger.warn( + ` 💥 '${method}' is deprecated and will be sunset in a future version. ${useInstead ? `Please use ${useInstead} instead.` : ''}` + ); }, + /** - * standardized method for getting data from cache - adapted for special case of lists - * ! keeping this in util/util.js rather than in metadataTypes/List.js to avoid potential circular dependencies + * helper for MetadataType class to issue a similar error message for unsupported methods * - * @param {Object} cache data retrieved from sfmc instance - * @param {String} listPathName folderPath/ListName combo of list - * @param {String} returnField ObjectID or ID - * @returns {String} unique ObjectId of list + * @param {any} definition type definition object + * @param {string} method name of the method thats not supported + * @param {MetadataTypeItem} [item] metadata item */ - getListObjectIdFromCache(cache, listPathName, returnField) { - let folderPath = listPathName.split('/'); - const listName = folderPath.pop(); - folderPath = folderPath.join('/'); - for (const key in cache['list']) { - if ( - cache['list'][key].ListName === listName && - cache['list'][key].r__folder_Path === folderPath - ) { - try { - if (cache['list'][key][returnField]) { - return cache['list'][key][returnField]; - } else { - throw new Error(); - } - } catch (ex) { - throw new Error( - `${'list'} with ListName='${listName}' and r__folder_Path='${folderPath}' does not have field '${returnField}'` - ); - } - } - } - throw new Error( - `Missing one or more dependent metadata. list with ListName='${listName}' and r__folder_Path='${folderPath}' was not found on your BU` + logNotSupported: function (definition, method, item) { + Util.logger.error( + ` ☇ skipping ${item ? Util.getTypeKeyName(definition, item) : definition.type}: ${method} is not supported for ${definition.type}` ); }, + // defined colors for logging things in different colors + color: { + reset: '\x1B[0m', + dim: '\x1B[2m', + bright: '\x1B[1m', + underscore: '\x1B[4m', + blink: '\x1B[5m', + reverse: '\x1B[7m', + hidden: '\x1B[8m', + + fgBlack: '\x1B[30m', + fgRed: '\x1B[31m', + fgGreen: '\x1B[32m', + fgYellow: '\x1B[33m', + fgBlue: '\x1B[34m', + fgMagenta: '\x1B[35m', + fgCyan: '\x1B[36m', + fgWhite: '\x1B[37m', + fgGray: '\x1B[90m', + + bgBlack: '\x1B[40m', + bgRed: '\x1B[41m', + bgGreen: '\x1B[42m', + bgYellow: '\x1B[43m', + bgBlue: '\x1B[44m', + bgMagenta: '\x1B[45m', + bgCyan: '\x1B[46m', + bgWhite: '\x1B[47m', + bgGray: '\x1B[100m', + }, + /** - * standardized method for getting data from cache - adapted for special case of lists - * ! keeping this in util/util.js rather than in metadataTypes/List.js to avoid potential circular dependencies - * - * @param {Object} cache data retrieved from sfmc instance - * @param {String} searchValue unique identifier of metadata being looked for - * @param {String} searchField ObjectID or ID - * @returns {String} unique folderPath/ListName combo of list - */ - getListPathNameFromCache(cache, searchValue, searchField) { - const returnField1 = 'r__folder_Path'; - const returnField2 = 'ListName'; - for (const key in cache['list']) { - if (cache['list'][key][searchField] === searchValue) { - try { - if (cache['list'][key][returnField1] && cache['list'][key][returnField2]) { - return ( - cache['list'][key][returnField1] + - '/' + - cache['list'][key][returnField2] - ); - } else { - throw new Error(); - } - } catch (ex) { - throw new Error( - `${'list'} with ${searchField}='${searchValue}' does not have the fields ${returnField1} and ${returnField2}` - ); - } + * helper that wraps a message in the correct color codes to have them printed gray + * + * @param {string} msg log message that should be wrapped with color codes + * @returns {string} gray msg + */ + getGrayMsg(msg) { + return `${Util.color.dim}${msg}${Util.color.reset}`; + }, + + /** + * helper that returns the prefix of item specific log messages + * + * @param {any} definition metadata definition + * @param {MetadataTypeItem} metadataItem metadata item + * @returns {string} msg prefix + */ + getMsgPrefix(definition, metadataItem) { + return ` - ${Util.getTypeKeyName(definition, metadataItem)}`; + }, + + /** + * helper that returns the prefix of item specific log messages + * + * @param {any} definition metadata definition + * @param {MetadataTypeItem} metadataItem metadata item + * @returns {string} key or key/name combo + */ + getTypeKeyName(definition, metadataItem) { + return `${definition.type}: ${Util.getKeyName(definition, metadataItem)}`; + }, + + /** + * helper that returns the prefix of item specific log messages + * + * @param {any} definition metadata definition + * @param {MetadataTypeItem} metadataItem metadata item + * @returns {string} key or key/name combo + */ + getKeyName(definition, metadataItem) { + const key = metadataItem[definition.keyField] || metadataItem[definition.nameField]; + const name = metadataItem[definition.nameField]; + + return !name || name == key ? key : key + ` / ` + name; + }, + + /** + * helper to print the subtypes we filtered by + * + * @param {string[]} subTypeArr list of subtypes to be printed + * @param {string} [indent] optional prefix of spaces to be added to the log message + * @returns {void} + */ + logSubtypes(subTypeArr, indent = '') { + if (subTypeArr && subTypeArr.length > 0) { + Util.logger.info( + Util.getGrayMsg( + `${indent} - Subtype${subTypeArr.length > 1 ? 's' : ''}: ${[...subTypeArr].toSorted().join(', ')}` + ) + ); + } + }, + + /** + * helper to print the subtypes we filtered by + * + * @param {string[] | string} keyArr list of subtypes to be printed + * @param {boolean} [isId] optional flag to indicate if key is an id + * @returns {string} string to be appended to log message + */ + getKeysString(keyArr, isId) { + if (!keyArr) { + return ''; + } + if (!Array.isArray(keyArr)) { + // if only one key, make it an array + keyArr = [keyArr]; + } + if (keyArr.length > 0) { + return Util.getGrayMsg( + ` - ${isId ? 'ID' : 'Key'}${keyArr.length > 1 ? 's' : ''}: ${keyArr.join(', ')}` + ); + } + return ''; + }, + + /** + * pause execution of code; useful when multiple server calls are dependent on each other and might not be executed right away + * + * @param {number} ms time in miliseconds to wait + * @returns {Promise.<void>} - promise to wait for + */ + async sleep(ms) { + if (Util.OPTIONS._runningTest) { + Util.logger.debug('Skipping sleep in test mode'); + return; + } + return new Promise((resolve) => { + setTimeout(resolve, ms); + }); + }, + + /** + * helper for Asset.extractCode and Script.prepExtractedCode to determine if a code block is a valid SSJS block + * + * @example the following is invalid: + * <script runat="server"> + * // 1 + * </script> + * <script runat="server"> + * // 2 + * </script> + * + * the following is valid: + * <script runat="server"> + * // 3 + * </script> + * @param {string} code code block to check + * @returns {string} the SSJS code if code block is a valid SSJS block, otherwise null + */ + getSsjs(code) { + if (!code) { + return null; + } + // \s* whitespace characters, zero or more times + // [^>]*? any character that is not a >, zero or more times, un-greedily + // (.*) capture any character, zero or more times + // /s dotall flag + // ideally the code looks like <script runat="server">...</script> + + // regex that matches <script runat="server">...</script>, <script runat="server" language="javascript">...</script> or <script language="JavaScript" runat="server">...</script>, but it may not match <script language="ampscript" runat="server">...</script> and it may also not match <script runat="server" language="ampscript">...</script> + const scriptRegex = + /^<\s*script\s*(language=["']{1}javascript["']{1})?\s?[^>]*?runat\s*=\s*["']{1}server["']{1}\s*?(language=["']{1}javascript["']{1})?\s*>(.*)<\/\s*script\s*>$/is; + + code = code.trim(); + const regexMatches = scriptRegex.exec(code); + // regexMatches indexes: + // 1: first optional language block + // 2: second optional language block + // 3: the actual code + if (regexMatches?.length > 1 && regexMatches[3]) { + // script found + /* eslint-disable unicorn/prefer-ternary */ + if (regexMatches[3].includes('<script')) { + // nested script found + return null; + } else { + // no nested script found: return the assumed SSJS-code + return regexMatches[3]; } + /* eslint-enable unicorn/prefer-ternary */ } - throw new Error( - `Missing one or more dependent metadata. list with ${searchField}='${searchValue}' was not found on your BU` + // no script found + return null; + }, + + /** + * allows us to filter just like with SQL's LIKE operator + * + * @param {string} testString field value to test + * @param {string} search search string in SQL LIKE format + * @returns {boolean} true if testString matches search + */ + stringLike(testString, search) { + if (typeof search !== 'string' || this === null) { + return false; + } + // Remove special chars + search = search.replaceAll( + new RegExp(String.raw`([\.\\\+\*\?\[\^\]\$\(\)\{\}\=\!\<\>\|\:\-])`, 'g'), + String.raw`\$1` ); + // Replace % and _ with equivalent regex + // Replace % with .* + search = search.replaceAll('%', '.*'); + // Replace _ with . only if not surrounded by [ and ] + search = search.replaceAll(/(?<!\[)_+(?!\])/g, (match) => '.'.repeat(match.length)); + // replace [_] with _ + search = search.replaceAll(String.raw`\[_\]`, '_'); + // Check matches + return new RegExp('^' + search + '$', 'gi').test(testString); }, + /** - * retry on network issues - * @param {String} errorMsg what to print behind "Connection error. " - * @param {Function} callback what to try executing - * @param {Boolean} [silentError=false] prints retry messages to log only; default=false - * @param {Number} [retries=1] number of retries; default=1 - * @returns {Promise<void>} - + * returns true if no LIKE filter is defined or if all filters match + * + * @param {MetadataTypeItem} metadata a single metadata item + * @param {object} definition type definition + * @param {object} [filters] only used in recursive calls + * @returns {boolean} true if no LIKE filter is defined or if all filters match */ - async retryOnError(errorMsg, callback, silentError, retries) { - if ('undefined' === typeof retries || retries === null) { - retries = 3; + fieldsLike(metadata, definition, filters) { + if (metadata.json && metadata.codeArr) { + // Compensate for CodeExtractItem format + metadata = metadata.json; } - try { - await callback(); - } catch (ex) { - if ( - retries > 0 && - ex.code && - ['ETIMEDOUT', 'EHOSTUNREACH', 'ENOTFOUND', 'ECONNRESET'].includes(ex.code) - ) { - retries--; - Util.logger.debug(ex.stack); - const msg = `Connection problem. ${errorMsg} (${retries + 1} tries left)`; - if (silentError) { - Util.logger.debug(msg); - } else { - Util.logger.warn(msg); - } - await this.retryOnError(errorMsg, callback, silentError, retries); - } else if ( - ex.code && - ['ETIMEDOUT', 'EHOSTUNREACH', 'ENOTFOUND', 'ECONNRESET'].includes(ex.code) - ) { - Util.logger.debug(ex.stack); - Util.logger.error( - `"${errorMsg}" Failed due to a Connection Error (${ex.code}) - Please check your network connection and try again` - ); - if (Util.logger.level === 'debug') { - console.log(ex.stack); - } - throw ex; + // ensure we only convert "key" and "name" fields on the first call to this method + const checkDefaultKeyAndName = filters ? false : true; + filters ||= Util.OPTIONS.like; + if (!filters) { + return true; + } + const fields = Object.keys(filters); + return fields.every((field) => { + // to allow passing in an array via cli, e.g. --like=field1,field2, we need to convert comma separated lists into arrays + const filter = + typeof filters[field] === 'string' && filters[field].includes(',') + ? filters[field].split(',') + : filters[field]; + if (Array.isArray(metadata[field])) { + return metadata[field].some((f) => Util.fieldsLike(f, definition, filter)); } else { - Util.logger.debug(ex.stack); - if (Util.logger.level === 'debug') { - console.log(ex.stack); + let fieldName; + if (field === 'key' && checkDefaultKeyAndName) { + fieldName = definition.keyField; + } else if (field === 'name' && checkDefaultKeyAndName) { + fieldName = definition.nameField; + } + if (typeof filter === 'string') { + return Util.stringLike(metadata[fieldName || field], filter); + } else if (Array.isArray(filter)) { + return filter.some((f) => Util.stringLike(metadata[field], f)); + } else if (typeof filter === 'object') { + return Util.fieldsLike(metadata[field], definition, filter); } - Util.logger.error(ex.message); - throw ex; } + return false; + }); + }, + + /** + * helper used by SOAP methods to ensure the type always uses an upper-cased first letter + * + * @param {string} str string to capitalize + * @returns {string} str with first letter capitalized + */ + capitalizeFirstLetter(str) { + return str.charAt(0).toUpperCase() + str.slice(1); + }, + + /** + * helper for Retriever and Deployer class + * + * @param {string | string[]} typeArr - + * @param {string[]} keyArr - + * @param {boolean} [returnEmpty] returns array with null element if false/not set; Retriever needs this to be false; Deployer needs it to be true + * @returns {TypeKeyCombo} - + */ + createTypeKeyCombo(typeArr, keyArr, returnEmpty = false) { + if (!keyArr || (Array.isArray(keyArr) && !keyArr.length)) { + // no keys were provided, ensure we retrieve all + keyArr = returnEmpty ? null : [null]; + } + /** @type {TypeKeyCombo} */ + const typeKeyMap = {}; + if ('string' === typeof typeArr) { + typeArr = [typeArr]; } + // no keys or array of keys was provided (likely called via CLI or to retrieve all) + // transform into TypeKeyCombo to iterate over it + for (const type of typeArr) { + typeKeyMap[type] = keyArr; + } + return typeKeyMap; }, + /** - * helper to run other commands as if run manually by user - * @param {string} cmd to be executed command - * @param {string[]} [args] list of arguments - * @returns {undefined} + * helper that converts TypeKeyCombo objects into a string with all relevant -m parameters + * + * @param {TypeKeyCombo} [selectedTypes] selected metadata types & key + * @returns {string} object converted into --metadata parameters */ - execSync(cmd, args) { - args = args || []; - Util.logger.info('⚡ ' + cmd + ' ' + args.join(' ')); + convertTypeKeyToCli(selectedTypes) { + return selectedTypes + ? Object.keys(selectedTypes) + .reduce((previousValue, type) => { + previousValue.push( + ...selectedTypes[type].map((key) => + key === null ? `-m ${type}` : `-m "${type}:${key}"` + ) + ); + return previousValue; + }, []) + .join(' ') + : ''; + }, + + /** + * helper that converts TypeKeyCombo objects into a string with all relevant -m parameters + * + * @param {TypeKeyCombo} [selectedTypes] selected metadata types & key + * @returns {string} object converted into --metadata parameters + */ + convertTypeKeyToString(selectedTypes) { + return selectedTypes + ? Object.keys(selectedTypes) + .reduce((previousValue, type) => { + previousValue.push( + selectedTypes[type] + .map((key, index) => { + let response = ''; + if (index === 0) { + response += `${type}`; + } + if (key !== null && index === 0) { + response += ' ('; + } + response += key === null ? `` : `"${key}"`; + if (key !== null && index === selectedTypes[type].length - 1) { + response += ')'; + } + return response; + }) + .join(', ') + ); + return previousValue; + }, []) + .join(', ') + : ''; + }, + + /** + * helper that checks how many keys are defined in TypeKeyCombo object + * + * @param {TypeKeyCombo} [selectedTypes] selected metadata types & key + * @returns {number} amount of keys across all types + */ + getTypeKeyCount(selectedTypes) { + return Object.keys(selectedTypes).reduce( + (previousValue, type) => + previousValue + (selectedTypes[type] ? selectedTypes[type].length : 0), + 0 + ); + }, + + /** + * async version of Array.find() + * returns the first element in the provided array that satisfies the provided testin function + * + * @param {Array} arr your test array + * @param {Function} asyncCallback callback + * @returns {Promise.<any | undefined>} first element that passed the test + */ + async findAsync(arr, asyncCallback) { + for (const element of arr) { + if (await asyncCallback(element)) { + return element; + } + } + }, - // the following options ensure the user sees the same output and - // interaction options as if the command was manually run - const options = { stdio: [0, 1, 2] }; - return child_process.execSync(cmd + ' ' + args.join(' '), options); + /** + * + * @param {Array} array array to be chunked + * @param {number} chunk_size integer > 0 + * @returns {Array[]} array of arrays with max chunk_size members per element, last element might have less + */ + chunk(array, chunk_size) { + return array.length == 0 + ? [] + : [array.splice(0, chunk_size)].concat(this.chunk(array, chunk_size)); + }, + /** + * recursively find all values of the given key in the object + * + * @param {any} object data to search in + * @param {string} key attribute to find + * @returns {Array} all values of the given key + */ + findLeafVals(object, key) { + const values = []; + Object.keys(object).map((k) => { + if (k === key) { + values.push(object[k]); + return true; + } + if (object[k] && typeof object[k] === 'object') { + values.push(...this.findLeafVals(object[k], key)); + } + }); + return [...new Set(values.toSorted())]; + }, + /** + * helper that returns a new object with sorted attributes of the given object + * + * @param {object} obj object with unsorted attributes + * @returns {object} obj but with sorted attributes + */ + sortObjectAttributes(obj) { + return Object.keys(obj) + .toSorted() + .reduce((acc, key) => { + acc[key] = obj[key]; + return acc; + }, {}); }, }; -/** - * wrapper around our standard winston logging to console and logfile - * @returns {object} initiated logger for console and file - */ -function createNewLoggerTransport() { - return { - console: new winston.transports.Console({ - // Write logs to Console - level: 'info', - format: winston.format.combine( - winston.format.colorize(), - winston.format.timestamp({ format: 'HH:mm:ss' }), - winston.format.simple(), - winston.format.printf((info) => `${info.timestamp} ${info.level}: ${info.message}`) - ), - }), - file: new winston.transports.File({ - // Write logs to logfile - filename: 'logs/' + new Date().toISOString().split(':').join('.') + '.log', - // filename: 'logs/' + Math.floor(Date.now() / 1000) + '.log', - level: 'debug', - format: winston.format.combine( - winston.format.timestamp({ format: 'HH:mm:ss.SSS' }), - winston.format.simple(), - winston.format.printf((info) => `${info.timestamp} ${info.level}: ${info.message}`) - ), - }), - }; -} -/** - * initiate winston logger - * @returns {void} - */ -function startLogger() { - Util.loggerTransports = createNewLoggerTransport(); - Util.logger = winston.createLogger({ - levels: winston.config.npm.levels, - transports: [Util.loggerTransports.console, Util.loggerTransports.file], - }); - Util.logger.debug(`:: mcdev ${packageJsonMcdev.version} ::`); -} -startLogger(); - -module.exports = Util; + +Util.startLogger(false, true); diff --git a/lib/util/validations.js b/lib/util/validations.js new file mode 100644 index 000000000..2886d6ef3 --- /dev/null +++ b/lib/util/validations.js @@ -0,0 +1,163 @@ +'use strict'; +import path from 'node:path'; +import { Util } from './util.js'; + +/** + * @typedef {import('../../types/mcdev.d.js').validationRuleList} validationRuleList + * @typedef {import('../../types/mcdev.d.js').validationRuleFix} validationRuleFix + * @typedef {import('../../types/mcdev.d.js').validationRuleTest} validationRuleTest + * @typedef {import('../../types/mcdev.d.js').CodeExtract} CodeExtract + */ + +/** @type {validationRuleList} */ +let customRules = {}; +let customRuleImport; +/** + * helper for validation + * + * @returns {Promise.<void>} - + */ +async function loadCustomRules() { + try { + customRuleImport = await import( + 'file://' + path.join(process.cwd(), '.mcdev-validations.js') + ); + } catch (ex) { + if (ex instanceof SyntaxError) { + Util.logger.error('SyntaxError in .mcdev-validations.js: ' + ex.message); + } else if (ex.code === 'ERR_MODULE_NOT_FOUND') { + Util.logger.debug('.mcdev-validations.js not found'); + } else { + Util.logger.errorStack( + ex, + 'Could not load custom validation rules from .mcdev-validations.js' + ); + } + } +} +/** + * + * @param {any} definition type definition + * @param {any} item MetadataItem + * @param {string} targetDir folder in which the MetadataItem is deployed from (deploy/cred/bu) + * @param {CodeExtract[]} [codeExtractItemArr] array of code snippets + * @returns {Promise.<validationRuleList>} MetadataItem + */ +export default async function validation(definition, item, targetDir, codeExtractItemArr) { + try { + if (!customRuleImport) { + // we might need to re-run this for mocha tests + await loadCustomRules(); + } + customRules = customRuleImport + ? await customRuleImport.validation( + definition, + item, + targetDir, + codeExtractItemArr, + Util + ) + : {}; + } catch (ex) { + Util.logger.errorStack( + ex, + 'Could not load custom validation rules from .mcdev-validations.js' + ); + } + /** @type {validationRuleList} */ + const defaultRules = { + noGuidKeys: { + failedMsg: 'Please update the key to a readable value. Currently still in GUID format.', + /** + * @type {validationRuleFix} + */ + fix: function () { + // to fix we skip the component + return this.passed() || null; + }, + /** + * @type {validationRuleTest} + */ + passed: function () { + const key = item[definition.keyField]; + if (key) { + const regex = /^[0-9a-z]{8}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{12}$/i; + return !regex.test(String(key).toLowerCase()); + } else { + Util.logger.debug('validation-noGuidKeys: key not found'); + return true; + } + }, + }, + noRootFolder: { + failedMsg: 'Root folder not allowed. Current folder: ' + item.r__folder_Path, + /** + * @type {validationRuleFix} + */ + fix: function () { + // to fix we skip the component + return this.passed() || null; + }, + /** + * @type {validationRuleTest} + */ + passed: function () { + /** @type {string} */ + const folderPath = item.r__folder_Path; + if (!folderPath) { + // some types do not support folders + return true; + } + const doNotEvaluate = [ + 'automation', + 'attributeSet', + 'dataFilter', + 'list', + 'filter', + ]; + if ( + doNotEvaluate.includes(definition.type) || + (definition.type === 'asset' && item?.assetType?.name === 'webpage') || + (definition.type === 'dataExtension' && + item.r__folder_Path === 'Synchronized Data Extensions') + ) { + // this subtype is not visible in the interface and hence always technically sits in the root + return true; + } + + return folderPath.includes('/'); + }, + }, + noAmpscriptHtmlTag: { + failedMsg: + 'Please use %%[]%% instead of <script runat="server" language="ampscript"></script> for AMPscript', + /** + * @type {validationRuleFix} + */ + fix: function () { + // to fix we skip the component + return this.passed() || null; + }, + /** + * @type {validationRuleTest} + */ + passed: function () { + if (definition.type === 'asset' && Array.isArray(codeExtractItemArr)) { + for (const codeExtractItem of codeExtractItemArr) { + if ( + codeExtractItem.content.includes( + '<script runat="server" language="ampscript">' + ) + ) { + return false; + } + } + return true; + } else { + return true; // test case should pass since non-asset metadatatypes get a pass + } + }, + }, + }; + return Object.assign({}, defaultRules, customRules); +} diff --git a/package-lock.json b/package-lock.json index fa67cca2d..b45cef16b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,266 +1,325 @@ { "name": "mcdev", - "version": "3.1.3", - "lockfileVersion": 2, + "version": "9.0.2", + "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "mcdev", - "version": "3.1.3", + "version": "9.0.2", "license": "MIT", "dependencies": { - "bluebird": "3.7.2", - "cli-progress": "3.10.0", + "beauty-amp-core2": "0.4.9", + "cli-progress": "3.12.0", "command-exists": "1.2.9", + "conf": "15.1.0", "console.table": "0.10.0", - "fs-extra": "10.0.0", - "inquirer": "8.2.0", + "deep-equal": "2.2.3", + "fs-extra": "11.3.4", + "inquirer": "13.3.0", "json-to-table": "4.2.1", "mustache": "4.2.0", - "prettier": "2.5.1", - "semver": "7.3.5", - "sfmc-fuelsdk-node": "2.4.0", - "simple-git": "2.48.0", - "sql-formatter-plus": "1.3.6", + "p-limit": "7.3.0", + "prettier": "3.8.1", + "prettier-plugin-sql": "0.19.2", + "semver": "7.7.4", + "sfmc-sdk": "3.0.1", + "simple-git": "3.32.3", "toposort": "2.0.2", - "update-notifier-git": "5.0.3", - "winston": "3.3.4", - "yargs": "17.3.0" + "update-notifier": "7.3.1", + "winston": "3.19.0", + "yargs": "18.0.0", + "yocto-spinner": "1.1.0" }, "bin": { "mcdev": "lib/cli.js" }, "devDependencies": { - "chai": "4.3.4", - "eslint": "8.4.1", - "eslint-config-prettier": "8.3.0", - "eslint-config-ssjs": "1.1.11", - "eslint-plugin-mocha": "10.0.1", - "eslint-plugin-prettier": "4.0.0", - "husky": "7.0.4", - "jsdoc-to-markdown": "7.1.0", - "lint-staged": "12.1.2", - "mocha": "9.1.3", - "npm-check": "5.9.2", - "npm-run-all": "4.1.5" - }, - "engines": { - "node": ">=14.16" + "@eslint/js": "10.0.1", + "@types/fs-extra": "11.0.4", + "@types/inquirer": "9.0.9", + "@types/mocha": "10.0.8", + "@types/node": "25.3.5", + "@types/yargs": "17.0.35", + "assert": "2.1.0", + "axios-mock-adapter": "2.0.0", + "c8": "11.0.0", + "chai": "6.2.2", + "chai-files": "1.4.0", + "eslint": "10.0.3", + "eslint-config-ssjs": "2.0.0", + "eslint-plugin-jsdoc": "62.7.1", + "eslint-plugin-mocha": "11.2.0", + "eslint-plugin-prettier": "5.5.5", + "eslint-plugin-unicorn": "63.0.0", + "fast-xml-parser": "5.4.2", + "globals": "17.4.0", + "husky": "9.1.7", + "lint-staged": "16.3.2", + "mocha": "11.7.5", + "mock-fs": "5.3.0", + "npm-run-all": "4.1.5", + "prettier-eslint": "16.4.2", + "typescript": "5.9.3" + }, + "engines": { + "node": "^20.19.0 || ^22.13.0 || >=24" }, "funding": { "type": "corporate", "url": "https://github.com/Accenture/sfmc-devtools" + }, + "optionalDependencies": { + "fsevents": "*" } }, - "node_modules/@babel/code-frame": { - "version": "7.12.11", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.12.11.tgz", - "integrity": "sha512-Zt1yodBx1UcyiePMSkWnU4hPqhwq7hGi2nFL1LeA3EUl+q2LQx16MISgJ0+z7dnmgvP9QtIleuETGOiOH1RcIw==", + "node_modules/@aashutoshrathi/word-wrap": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz", + "integrity": "sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==", "dev": true, - "dependencies": { - "@babel/highlight": "^7.10.4" + "engines": { + "node": ">=0.10.0" } }, - "node_modules/@babel/generator": { - "version": "7.9.5", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.9.5.tgz", - "integrity": "sha512-GbNIxVB3ZJe3tLeDm1HSn2AhuD/mVcyLDpgtLXa5tplmWrJdF/elxB56XNqCuD6szyNkDi6wuoKXln3QeBmCHQ==", + "node_modules/@babel/helper-validator-identifier": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz", + "integrity": "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==", "dev": true, - "dependencies": { - "@babel/types": "^7.9.5", - "jsesc": "^2.5.1", - "lodash": "^4.17.13", - "source-map": "^0.5.0" + "license": "MIT", + "engines": { + "node": ">=6.9.0" } }, - "node_modules/@babel/generator/node_modules/source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "node_modules/@bcoe/v8-coverage": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-1.0.1.tgz", + "integrity": "sha512-W+a0/JpU28AqH4IKtwUPcEUnUyXMDLALcn5/JLczGGT9fHE2sIby/xP/oQnx3nxkForzgzPy201RAKcB4xPAFQ==", "dev": true, "engines": { - "node": ">=0.10.0" + "node": ">=18" } }, - "node_modules/@babel/helper-function-name": { - "version": "7.9.5", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.9.5.tgz", - "integrity": "sha512-JVcQZeXM59Cd1qanDUxv9fgJpt3NeKUaqBqUEvfmQ+BCOKq2xUgaWZW2hr0dkbyJgezYuplEoh5knmrnS68efw==", - "dev": true, + "node_modules/@colors/colors": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.6.0.tgz", + "integrity": "sha512-Ir+AOibqzrIsL6ajt3Rz3LskB7OiMVHqltZmspbW/TJuTVuyOMirVqAkjfY6JISiLHgyNqicAC8AyHHGzNd/dA==", + "engines": { + "node": ">=0.1.90" + } + }, + "node_modules/@dabh/diagnostics": { + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/@dabh/diagnostics/-/diagnostics-2.0.8.tgz", + "integrity": "sha512-R4MSXTVnuMzGD7bzHdW2ZhhdPC/igELENcq5IjEverBvq5hn1SXCWcsi6eSsdWP0/Ur+SItRRjAktmdoX/8R/Q==", + "license": "MIT", "dependencies": { - "@babel/helper-get-function-arity": "^7.8.3", - "@babel/template": "^7.8.3", - "@babel/types": "^7.9.5" + "@so-ric/colorspace": "^1.1.6", + "enabled": "2.0.x", + "kuler": "^2.0.0" } }, - "node_modules/@babel/helper-get-function-arity": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.8.3.tgz", - "integrity": "sha512-FVDR+Gd9iLjUMY1fzE2SR0IuaJToR4RkCDARVfsBBPSP53GEqSFjD8gNyxg246VUyc/ALRxFaAK8rVG7UT7xRA==", + "node_modules/@es-joy/jsdoccomment": { + "version": "0.84.0", + "resolved": "https://registry.npmjs.org/@es-joy/jsdoccomment/-/jsdoccomment-0.84.0.tgz", + "integrity": "sha512-0xew1CxOam0gV5OMjh2KjFQZsKL2bByX1+q4j3E73MpYIdyUxcZb/xQct9ccUb+ve5KGUYbCUxyPnYB7RbuP+w==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/types": "^7.8.3" + "@types/estree": "^1.0.8", + "@typescript-eslint/types": "^8.54.0", + "comment-parser": "1.4.5", + "esquery": "^1.7.0", + "jsdoc-type-pratt-parser": "~7.1.1" + }, + "engines": { + "node": "^20.19.0 || ^22.13.0 || >=24" } }, - "node_modules/@babel/helper-split-export-declaration": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.8.3.tgz", - "integrity": "sha512-3x3yOeyBhW851hroze7ElzdkeRXQYQbFIb7gLK1WQYsw2GWDay5gAJNw1sWJ0VFP6z5J1whqeXH/WCdCjZv6dA==", + "node_modules/@es-joy/jsdoccomment/node_modules/@typescript-eslint/types": { + "version": "8.55.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.55.0.tgz", + "integrity": "sha512-ujT0Je8GI5BJWi+/mMoR0wxwVEQaxM+pi30xuMiJETlX80OPovb2p9E8ss87gnSVtYXtJoU9U1Cowcr6w2FE0w==", "dev": true, - "dependencies": { - "@babel/types": "^7.8.3" + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/@babel/helper-validator-identifier": { - "version": "7.9.5", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.9.5.tgz", - "integrity": "sha512-/8arLKUFq882w4tWGj9JYzRpAlZgiWUJ+dtteNTDqrRBz9Iguck9Rn3ykuBDoUwh2TO4tSAJlrxDUOXWklJe4g==", - "dev": true + "node_modules/@es-joy/resolve.exports": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@es-joy/resolve.exports/-/resolve.exports-1.2.0.tgz", + "integrity": "sha512-Q9hjxWI5xBM+qW2enxfe8wDKdFWMfd0Z29k5ZJnuBqD/CasY5Zryj09aCA6owbGATWz+39p5uIdaHXpopOcG8g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + } }, - "node_modules/@babel/highlight": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.10.4.tgz", - "integrity": "sha512-i6rgnR/YgPEQzZZnbTHHuZdlE8qyoBNalD6F+q4vAFlcMEcqmkoG+mPqJYJCo63qPf74+Y1UZsl3l6f7/RIkmA==", + "node_modules/@eslint-community/eslint-utils": { + "version": "4.9.1", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.9.1.tgz", + "integrity": "sha512-phrYmNiYppR7znFEdqgfWHXR6NCkZEK7hwWDHZUjit/2/U0r6XvkDl0SYnoM51Hq7FhCGdLDT6zxCCOY1hexsQ==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-validator-identifier": "^7.10.4", - "chalk": "^2.0.0", - "js-tokens": "^4.0.0" + "eslint-visitor-keys": "^3.4.3" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" } }, - "node_modules/@babel/highlight/node_modules/@babel/helper-validator-identifier": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.10.4.tgz", - "integrity": "sha512-3U9y+43hz7ZM+rzG24Qe2mufW5KhvFg/NhnNph+i9mgCtdTCtMJuI1TMkrIUiK7Ix4PYlRF9I5dhqaLYA/ADXw==", - "dev": true - }, - "node_modules/@babel/parser": { - "version": "7.15.3", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.15.3.tgz", - "integrity": "sha512-O0L6v/HvqbdJawj0iBEfVQMc3/6WP+AeOsovsIgBFyJaG+W2w7eqvZB7puddATmWuARlm1SX7DwxJ/JJUnDpEA==", + "node_modules/@eslint-community/regexpp": { + "version": "4.12.2", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.2.tgz", + "integrity": "sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew==", "dev": true, - "bin": { - "parser": "bin/babel-parser.js" - }, + "license": "MIT", "engines": { - "node": ">=6.0.0" + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" } }, - "node_modules/@babel/polyfill": { - "version": "7.10.1", - "resolved": "https://registry.npmjs.org/@babel/polyfill/-/polyfill-7.10.1.tgz", - "integrity": "sha512-TviueJ4PBW5p48ra8IMtLXVkDucrlOZAIZ+EXqS3Ot4eukHbWiqcn7DcqpA1k5PcKtmJ4Xl9xwdv6yQvvcA+3g==", + "node_modules/@eslint/config-array": { + "version": "0.23.3", + "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.23.3.tgz", + "integrity": "sha512-j+eEWmB6YYLwcNOdlwQ6L2OsptI/LO6lNBuLIqe5R7RetD658HLoF+Mn7LzYmAWWNNzdC6cqP+L6r8ujeYXWLw==", + "dev": true, + "license": "Apache-2.0", "dependencies": { - "core-js": "^2.6.5", - "regenerator-runtime": "^0.13.4" + "@eslint/object-schema": "^3.0.3", + "debug": "^4.3.1", + "minimatch": "^10.2.4" + }, + "engines": { + "node": "^20.19.0 || ^22.13.0 || >=24" } }, - "node_modules/@babel/polyfill/node_modules/regenerator-runtime": { - "version": "0.13.5", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.5.tgz", - "integrity": "sha512-ZS5w8CpKFinUzOwW3c83oPeVXoNsrLsaCoLtJvAClH135j/R77RuymhiSErhm2lKcwSCIpmvIWSbDkIfAqKQlA==" - }, - "node_modules/@babel/template": { - "version": "7.8.6", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.8.6.tgz", - "integrity": "sha512-zbMsPMy/v0PWFZEhQJ66bqjhH+z0JgMoBWuikXybgG3Gkd/3t5oQ1Rw2WQhnSrsOmsKXnZOx15tkC4qON/+JPg==", + "node_modules/@eslint/config-array/node_modules/balanced-match": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz", + "integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==", "dev": true, - "dependencies": { - "@babel/code-frame": "^7.8.3", - "@babel/parser": "^7.8.6", - "@babel/types": "^7.8.6" + "license": "MIT", + "engines": { + "node": "18 || 20 || >=22" } }, - "node_modules/@babel/traverse": { - "version": "7.9.5", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.9.5.tgz", - "integrity": "sha512-c4gH3jsvSuGUezlP6rzSJ6jf8fYjLj3hsMZRx/nX0h+fmHN0w+ekubRrHPqnMec0meycA2nwCsJ7dC8IPem2FQ==", + "node_modules/@eslint/config-array/node_modules/brace-expansion": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.4.tgz", + "integrity": "sha512-h+DEnpVvxmfVefa4jFbCf5HdH5YMDXRsmKflpf1pILZWRFlTbJpxeU55nJl4Smt5HQaGzg1o6RHFPJaOqnmBDg==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/code-frame": "^7.8.3", - "@babel/generator": "^7.9.5", - "@babel/helper-function-name": "^7.9.5", - "@babel/helper-split-export-declaration": "^7.8.3", - "@babel/parser": "^7.9.0", - "@babel/types": "^7.9.5", - "debug": "^4.1.0", - "globals": "^11.1.0", - "lodash": "^4.17.13" + "balanced-match": "^4.0.2" + }, + "engines": { + "node": "18 || 20 || >=22" } }, - "node_modules/@babel/traverse/node_modules/globals": { - "version": "11.12.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", - "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "node_modules/@eslint/config-array/node_modules/minimatch": { + "version": "10.2.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.4.tgz", + "integrity": "sha512-oRjTw/97aTBN0RHbYCdtF1MQfvusSIBQM0IZEgzl6426+8jSC0nF1a/GmnVLpfB9yyr6g6FTqWqiZVbxrtaCIg==", "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "brace-expansion": "^5.0.2" + }, "engines": { - "node": ">=4" + "node": "18 || 20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/@babel/types": { - "version": "7.9.5", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.9.5.tgz", - "integrity": "sha512-XjnvNqenk818r5zMaba+sLQjnbda31UfUURv3ei0qPQw4u+j2jMyJ5b11y8ZHYTRSI3NnInQkkkRT4fLqqPdHg==", + "node_modules/@eslint/config-helpers": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.5.2.tgz", + "integrity": "sha512-a5MxrdDXEvqnIq+LisyCX6tQMPF/dSJpCfBgBauY+pNZ28yCtSsTvyTYrMhaI+LK26bVyCJfJkT0u8KIj2i1dQ==", "dev": true, + "license": "Apache-2.0", "dependencies": { - "@babel/helper-validator-identifier": "^7.9.5", - "lodash": "^4.17.13", - "to-fast-properties": "^2.0.0" + "@eslint/core": "^1.1.0" + }, + "engines": { + "node": "^20.19.0 || ^22.13.0 || >=24" } }, - "node_modules/@dabh/diagnostics": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@dabh/diagnostics/-/diagnostics-2.0.2.tgz", - "integrity": "sha512-+A1YivoVDNNVCdfozHSR8v/jyuuLTMXwjWuxPFlFlUapXoGc+Gj9mDlTDDfrwl7rXCl2tNZ0kE8sIBO6YOn96Q==", + "node_modules/@eslint/core": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@eslint/core/-/core-1.1.1.tgz", + "integrity": "sha512-QUPblTtE51/7/Zhfv8BDwO0qkkzQL7P/aWWbqcf4xWLEYn1oKjdO0gglQBB4GAsu7u6wjijbCmzsUTy6mnk6oQ==", + "dev": true, + "license": "Apache-2.0", "dependencies": { - "colorspace": "1.1.x", - "enabled": "2.0.x", - "kuler": "^2.0.0" + "@types/json-schema": "^7.0.15" + }, + "engines": { + "node": "^20.19.0 || ^22.13.0 || >=24" } }, "node_modules/@eslint/eslintrc": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.0.5.tgz", - "integrity": "sha512-BLxsnmK3KyPunz5wmCCpqy0YelEoxxGmH73Is+Z74oOTMtExcjkr3dDR6quwrjh1YspA8DH9gnX1o069KiS9AQ==", + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", + "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", "dev": true, + "license": "MIT", "dependencies": { "ajv": "^6.12.4", "debug": "^4.3.2", - "espree": "^9.2.0", - "globals": "^13.9.0", - "ignore": "^4.0.6", + "espree": "^9.6.0", + "globals": "^13.19.0", + "ignore": "^5.2.0", "import-fresh": "^3.2.1", "js-yaml": "^4.1.0", - "minimatch": "^3.0.4", + "minimatch": "^3.1.2", "strip-json-comments": "^3.1.1" }, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" } }, - "node_modules/@eslint/eslintrc/node_modules/argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true - }, - "node_modules/@eslint/eslintrc/node_modules/js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "node_modules/@eslint/eslintrc/node_modules/ajv": { + "version": "6.14.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.14.0.tgz", + "integrity": "sha512-IWrosm/yrn43eiKqkfkHis7QioDleaXQHdDVPKg0FSwwd/DuvyX79TZnFOnYpB7dcsFAMmtFztZuXPDvSePkFw==", "dev": true, + "license": "MIT", "dependencies": { - "argparse": "^2.0.1" + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" }, - "bin": { - "js-yaml": "bin/js-yaml.js" + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" } }, - "node_modules/@eslint/eslintrc/node_modules/strip-json-comments": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "node_modules/@eslint/eslintrc/node_modules/globals": { + "version": "13.24.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", + "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", "dev": true, + "license": "MIT", + "dependencies": { + "type-fest": "^0.20.2" + }, "engines": { "node": ">=8" }, @@ -268,1046 +327,1255 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@humanwhocodes/config-array": { - "version": "0.9.2", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.9.2.tgz", - "integrity": "sha512-UXOuFCGcwciWckOpmfKDq/GyhlTf9pN/BzG//x8p8zTOFEcGuA68ANXheFS0AGvy3qgZqLBUkMs7hqzqCKOVwA==", + "node_modules/@eslint/eslintrc/node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", "dev": true, - "dependencies": { - "@humanwhocodes/object-schema": "^1.2.1", - "debug": "^4.1.1", - "minimatch": "^3.0.4" - }, - "engines": { - "node": ">=10.10.0" - } + "license": "MIT" }, - "node_modules/@humanwhocodes/object-schema": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz", - "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", - "dev": true - }, - "node_modules/@kwsites/file-exists": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@kwsites/file-exists/-/file-exists-1.1.1.tgz", - "integrity": "sha512-m9/5YGR18lIwxSFDwfE3oA7bWuq9kdau6ugN4H2rJeyhFQZcG9AgSHkQtSD15a8WvTgfz9aikZMrKPHvbpqFiw==", - "dependencies": { - "debug": "^4.1.1" + "node_modules/@eslint/js": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-10.0.1.tgz", + "integrity": "sha512-zeR9k5pd4gxjZ0abRoIaxdc7I3nDktoXZk2qOv9gCNWx3mVwEn32VRhyLaRsDiJjTs0xq/T8mfPtyuXu7GWBcA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^20.19.0 || ^22.13.0 || >=24" + }, + "funding": { + "url": "https://eslint.org/donate" + }, + "peerDependencies": { + "eslint": "^10.0.0" + }, + "peerDependenciesMeta": { + "eslint": { + "optional": true + } } }, - "node_modules/@kwsites/promise-deferred": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@kwsites/promise-deferred/-/promise-deferred-1.1.1.tgz", - "integrity": "sha512-GaHYm+c0O9MjZRu0ongGBRbinu8gVAMd2UZjji6jVmqKtZluZnptXGWhz1E8j8D2HJ3f/yMxKAUC0b+57wncIw==" - }, - "node_modules/@sindresorhus/is": { - "version": "0.14.0", - "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-0.14.0.tgz", - "integrity": "sha512-9NET910DNaIPngYnLLPeg+Ogzqsi9uM4mSboU5y6p8S5DzMTVEsJZrawi+BoDNUVBa2DhJqQYUFvMDfgU062LQ==", + "node_modules/@eslint/object-schema": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-3.0.3.tgz", + "integrity": "sha512-iM869Pugn9Nsxbh/YHRqYiqd23AmIbxJOcpUMOuWCVNdoQJ5ZtwL6h3t0bcZzJUlC3Dq9jCFCESBZnX0GTv7iQ==", + "dev": true, + "license": "Apache-2.0", "engines": { - "node": ">=6" + "node": "^20.19.0 || ^22.13.0 || >=24" } }, - "node_modules/@szmarczak/http-timer": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-1.1.2.tgz", - "integrity": "sha512-XIB2XbzHTN6ieIjfIMV9hlVcfPU26s2vafYWQcZHWXHOxiaRZYEDKEwdl129Zyg50+foYV2jCgtrqSA6qNuNSA==", + "node_modules/@eslint/plugin-kit": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.6.1.tgz", + "integrity": "sha512-iH1B076HoAshH1mLpHMgwdGeTs0CYwL0SPMkGuSebZrwBp16v415e9NZXg2jtrqPVQjf6IANe2Vtlr5KswtcZQ==", + "dev": true, + "license": "Apache-2.0", "dependencies": { - "defer-to-connect": "^1.0.1" + "@eslint/core": "^1.1.1", + "levn": "^0.4.1" }, "engines": { - "node": ">=6" + "node": "^20.19.0 || ^22.13.0 || >=24" } }, - "node_modules/@ungap/promise-all-settled": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@ungap/promise-all-settled/-/promise-all-settled-1.1.2.tgz", - "integrity": "sha512-sL/cEvJWAnClXw0wHk85/2L0G6Sj8UB0Ctc1TEMbKSsmpRosqhwj9gWgFRZSrBr2f9tiXISwNhCPmlfqUqyb9Q==", - "dev": true + "node_modules/@humanfs/core": { + "version": "0.19.1", + "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz", + "integrity": "sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==", + "dev": true, + "engines": { + "node": ">=18.18.0" + } }, - "node_modules/acorn": { - "version": "8.6.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.6.0.tgz", - "integrity": "sha512-U1riIR+lBSNi3IbxtaHOIKdH8sLFv3NYfNv8sg7ZsNhcfl4HF2++BfqqrNAxoCLQW1iiylOj76ecnaUxz+z9yw==", + "node_modules/@humanfs/node": { + "version": "0.16.6", + "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.6.tgz", + "integrity": "sha512-YuI2ZHQL78Q5HbhDiBA1X4LmYdXCKCMQIfw0pw7piHJwyREFebJUvrQN4cMssyES6x+vfUbx1CIpaQUKYdQZOw==", "dev": true, - "bin": { - "acorn": "bin/acorn" + "dependencies": { + "@humanfs/core": "^0.19.1", + "@humanwhocodes/retry": "^0.3.0" }, "engines": { - "node": ">=0.4.0" + "node": ">=18.18.0" } }, - "node_modules/acorn-jsx": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", - "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "node_modules/@humanfs/node/node_modules/@humanwhocodes/retry": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.3.1.tgz", + "integrity": "sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA==", "dev": true, - "peerDependencies": { - "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + "engines": { + "node": ">=18.18" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" } }, - "node_modules/aggregate-error": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", - "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", + "node_modules/@humanwhocodes/config-array": { + "version": "0.13.0", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.13.0.tgz", + "integrity": "sha512-DZLEEqFWQFiyK6h5YIeynKx7JlvCYWL0cImfSRXZ9l4Sg2efkFGTuFf6vzXjK1cq6IYkU+Eg/JizXw+TD2vRNw==", + "deprecated": "Use @eslint/config-array instead", "dev": true, + "license": "Apache-2.0", "dependencies": { - "clean-stack": "^2.0.0", - "indent-string": "^4.0.0" + "@humanwhocodes/object-schema": "^2.0.3", + "debug": "^4.3.1", + "minimatch": "^3.0.5" }, "engines": { - "node": ">=8" + "node": ">=10.10.0" } }, - "node_modules/aggregate-error/node_modules/indent-string": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", - "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", "dev": true, "engines": { - "node": ">=8" - } - }, - "node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" + "node": ">=12.22" }, "funding": { "type": "github", - "url": "https://github.com/sponsors/epoberezkin" + "url": "https://github.com/sponsors/nzakas" } }, - "node_modules/ansi-align": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.1.tgz", - "integrity": "sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w==", - "dependencies": { - "string-width": "^4.1.0" - } + "node_modules/@humanwhocodes/object-schema": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz", + "integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==", + "deprecated": "Use @eslint/object-schema instead", + "dev": true, + "license": "BSD-3-Clause" }, - "node_modules/ansi-align/node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "node_modules/@humanwhocodes/retry": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.2.tgz", + "integrity": "sha512-xeO57FpIu4p1Ri3Jq/EXq4ClRm86dVF2z/+kvFnyqVYRavTZmaFaUBbWCOuuTh0o/g7DSsk6kc2vrS4Vl5oPOQ==", + "dev": true, + "license": "Apache-2.0", "engines": { - "node": ">=8" + "node": ">=18.18" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" } }, - "node_modules/ansi-align/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" - }, - "node_modules/ansi-align/node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "node_modules/@inquirer/ansi": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@inquirer/ansi/-/ansi-2.0.3.tgz", + "integrity": "sha512-g44zhR3NIKVs0zUesa4iMzExmZpLUdTLRMCStqX3GE5NT6VkPcxQGJ+uC8tDgBUC/vB1rUhUd55cOf++4NZcmw==", + "license": "MIT", "engines": { - "node": ">=8" + "node": ">=23.5.0 || ^22.13.0 || ^21.7.0 || ^20.12.0" } }, - "node_modules/ansi-align/node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "node_modules/@inquirer/checkbox": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/@inquirer/checkbox/-/checkbox-5.1.0.tgz", + "integrity": "sha512-/HjF1LN0a1h4/OFsbGKHNDtWICFU/dqXCdym719HFTyJo9IG7Otr+ziGWc9S0iQuohRZllh+WprSgd5UW5Fw0g==", + "license": "MIT", "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" + "@inquirer/ansi": "^2.0.3", + "@inquirer/core": "^11.1.5", + "@inquirer/figures": "^2.0.3", + "@inquirer/type": "^4.0.3" }, "engines": { - "node": ">=8" + "node": ">=23.5.0 || ^22.13.0 || ^21.7.0 || ^20.12.0" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } } }, - "node_modules/ansi-align/node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "node_modules/@inquirer/confirm": { + "version": "6.0.8", + "resolved": "https://registry.npmjs.org/@inquirer/confirm/-/confirm-6.0.8.tgz", + "integrity": "sha512-Di6dgmiZ9xCSUxWUReWTqDtbhXCuG2MQm2xmgSAIruzQzBqNf49b8E07/vbCYY506kDe8BiwJbegXweG8M1klw==", + "license": "MIT", "dependencies": { - "ansi-regex": "^5.0.1" + "@inquirer/core": "^11.1.5", + "@inquirer/type": "^4.0.3" }, "engines": { - "node": ">=8" + "node": ">=23.5.0 || ^22.13.0 || ^21.7.0 || ^20.12.0" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } } }, - "node_modules/ansi-colors": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", - "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", - "dev": true, + "node_modules/@inquirer/core": { + "version": "11.1.5", + "resolved": "https://registry.npmjs.org/@inquirer/core/-/core-11.1.5.tgz", + "integrity": "sha512-QQPAX+lka8GyLcZ7u7Nb1h6q72iZ/oy0blilC3IB2nSt1Qqxp7akt94Jqhi/DzARuN3Eo9QwJRvtl4tmVe4T5A==", + "license": "MIT", + "dependencies": { + "@inquirer/ansi": "^2.0.3", + "@inquirer/figures": "^2.0.3", + "@inquirer/type": "^4.0.3", + "cli-width": "^4.1.0", + "fast-wrap-ansi": "^0.2.0", + "mute-stream": "^3.0.0", + "signal-exit": "^4.1.0" + }, "engines": { - "node": ">=6" - } - }, - "node_modules/ansi-escape-sequences": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/ansi-escape-sequences/-/ansi-escape-sequences-4.1.0.tgz", - "integrity": "sha512-dzW9kHxH011uBsidTXd14JXgzye/YLb2LzeKZ4bsgl/Knwx8AtbSFkkGxagdNOoh0DlqHCmfiEjWKBaqjOanVw==", - "dev": true, + "node": ">=23.5.0 || ^22.13.0 || ^21.7.0 || ^20.12.0" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } + } + }, + "node_modules/@inquirer/editor": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/@inquirer/editor/-/editor-5.0.8.tgz", + "integrity": "sha512-sLcpbb9B3XqUEGrj1N66KwhDhEckzZ4nI/W6SvLXyBX8Wic3LDLENlWRvkOGpCPoserabe+MxQkpiMoI8irvyA==", + "license": "MIT", "dependencies": { - "array-back": "^3.0.1" + "@inquirer/core": "^11.1.5", + "@inquirer/external-editor": "^2.0.3", + "@inquirer/type": "^4.0.3" }, "engines": { - "node": ">=8.0.0" + "node": ">=23.5.0 || ^22.13.0 || ^21.7.0 || ^20.12.0" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } } }, - "node_modules/ansi-escape-sequences/node_modules/array-back": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/array-back/-/array-back-3.1.0.tgz", - "integrity": "sha512-TkuxA4UCOvxuDK6NZYXCalszEzj+TLszyASooky+i742l9TqsOdYCMJJupxRic61hwquNtppB3hgcuq9SVSH1Q==", - "dev": true, + "node_modules/@inquirer/expand": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/@inquirer/expand/-/expand-5.0.8.tgz", + "integrity": "sha512-QieW3F1prNw3j+hxO7/NKkG1pk3oz7pOB6+5Upwu3OIwADfPX0oZVppsqlL+Vl/uBHHDSOBY0BirLctLnXwGGg==", + "license": "MIT", + "dependencies": { + "@inquirer/core": "^11.1.5", + "@inquirer/type": "^4.0.3" + }, "engines": { - "node": ">=6" + "node": ">=23.5.0 || ^22.13.0 || ^21.7.0 || ^20.12.0" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } } }, - "node_modules/ansi-escapes": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.1.tgz", - "integrity": "sha512-JWF7ocqNrp8u9oqpgV+wH5ftbt+cfvv+PTjOvKLT3AdYly/LmORARfEVT1iyjwN+4MqE5UmVKoAdIBqeoCHgLA==", + "node_modules/@inquirer/external-editor": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@inquirer/external-editor/-/external-editor-2.0.3.tgz", + "integrity": "sha512-LgyI7Agbda74/cL5MvA88iDpvdXI2KuMBCGRkbCl2Dg1vzHeOgs+s0SDcXV7b+WZJrv2+ERpWSM65Fpi9VfY3w==", + "license": "MIT", "dependencies": { - "type-fest": "^0.11.0" + "chardet": "^2.1.1", + "iconv-lite": "^0.7.2" }, "engines": { - "node": ">=8" + "node": ">=23.5.0 || ^22.13.0 || ^21.7.0 || ^20.12.0" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } } }, - "node_modules/ansi-escapes/node_modules/type-fest": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.11.0.tgz", - "integrity": "sha512-OdjXJxnCN1AvyLSzeKIgXTXxV+99ZuXl3Hpo9XpJAv9MBcHrrJOQ5kV7ypXOuQie+AmWG25hLbiKdwYTifzcfQ==", + "node_modules/@inquirer/figures": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@inquirer/figures/-/figures-2.0.3.tgz", + "integrity": "sha512-y09iGt3JKoOCBQ3w4YrSJdokcD8ciSlMIWsD+auPu+OZpfxLuyz+gICAQ6GCBOmJJt4KEQGHuZSVff2jiNOy7g==", + "license": "MIT", "engines": { - "node": ">=8" + "node": ">=23.5.0 || ^22.13.0 || ^21.7.0 || ^20.12.0" } }, - "node_modules/ansi-regex": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", - "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", - "dev": true, + "node_modules/@inquirer/input": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/@inquirer/input/-/input-5.0.8.tgz", + "integrity": "sha512-p0IJslw0AmedLEkOU+yrEX3Aj2RTpQq7ZOf8nc1DIhjzaxRWrrgeuE5Kyh39fVRgtcACaMXx/9WNo8+GjgBOfw==", + "license": "MIT", + "dependencies": { + "@inquirer/core": "^11.1.5", + "@inquirer/type": "^4.0.3" + }, "engines": { - "node": ">=6" + "node": ">=23.5.0 || ^22.13.0 || ^21.7.0 || ^20.12.0" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } } }, - "node_modules/ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, + "node_modules/@inquirer/number": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/@inquirer/number/-/number-4.0.8.tgz", + "integrity": "sha512-uGLiQah9A0F9UIvJBX52m0CnqtLaym0WpT9V4YZrjZ+YRDKZdwwoEPz06N6w8ChE2lrnsdyhY9sL+Y690Kh9gQ==", + "license": "MIT", "dependencies": { - "color-convert": "^1.9.0" + "@inquirer/core": "^11.1.5", + "@inquirer/type": "^4.0.3" }, "engines": { - "node": ">=4" + "node": ">=23.5.0 || ^22.13.0 || ^21.7.0 || ^20.12.0" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } } }, - "node_modules/anymatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", - "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==", - "dev": true, + "node_modules/@inquirer/password": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/@inquirer/password/-/password-5.0.8.tgz", + "integrity": "sha512-zt1sF4lYLdvPqvmvHdmjOzuUUjuCQ897pdUCO8RbXMUDKXJTTyOQgtn23le+jwcb+MpHl3VAFvzIdxRAf6aPlA==", + "license": "MIT", "dependencies": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" + "@inquirer/ansi": "^2.0.3", + "@inquirer/core": "^11.1.5", + "@inquirer/type": "^4.0.3" }, "engines": { - "node": ">= 8" + "node": ">=23.5.0 || ^22.13.0 || ^21.7.0 || ^20.12.0" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } } }, - "node_modules/argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "dev": true, + "node_modules/@inquirer/prompts": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/@inquirer/prompts/-/prompts-8.3.0.tgz", + "integrity": "sha512-JAj66kjdH/F1+B7LCigjARbwstt3SNUOSzMdjpsvwJmzunK88gJeXmcm95L9nw1KynvFVuY4SzXh/3Y0lvtgSg==", + "license": "MIT", "dependencies": { - "sprintf-js": "~1.0.2" + "@inquirer/checkbox": "^5.1.0", + "@inquirer/confirm": "^6.0.8", + "@inquirer/editor": "^5.0.8", + "@inquirer/expand": "^5.0.8", + "@inquirer/input": "^5.0.8", + "@inquirer/number": "^4.0.8", + "@inquirer/password": "^5.0.8", + "@inquirer/rawlist": "^5.2.4", + "@inquirer/search": "^4.1.4", + "@inquirer/select": "^5.1.0" + }, + "engines": { + "node": ">=23.5.0 || ^22.13.0 || ^21.7.0 || ^20.12.0" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } } }, - "node_modules/array-back": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/array-back/-/array-back-4.0.1.tgz", - "integrity": "sha512-Z/JnaVEXv+A9xabHzN43FiiiWEE7gPCRXMrVmRm00tWbjZRul1iHm7ECzlyNq1p4a4ATXz+G9FJ3GqGOkOV3fg==", - "dev": true, + "node_modules/@inquirer/rawlist": { + "version": "5.2.4", + "resolved": "https://registry.npmjs.org/@inquirer/rawlist/-/rawlist-5.2.4.tgz", + "integrity": "sha512-fTuJ5Cq9W286isLxwj6GGyfTjx1Zdk4qppVEPexFuA6yioCCXS4V1zfKroQqw7QdbDPN73xs2DiIAlo55+kBqg==", + "license": "MIT", + "dependencies": { + "@inquirer/core": "^11.1.5", + "@inquirer/type": "^4.0.3" + }, "engines": { - "node": ">=8" + "node": ">=23.5.0 || ^22.13.0 || ^21.7.0 || ^20.12.0" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } } }, - "node_modules/array-find-index": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/array-find-index/-/array-find-index-1.0.2.tgz", - "integrity": "sha1-3wEKoSh+Fku9pvlyOwqWoexBh6E=", - "dev": true, + "node_modules/@inquirer/search": { + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/@inquirer/search/-/search-4.1.4.tgz", + "integrity": "sha512-9yPTxq7LPmYjrGn3DRuaPuPbmC6u3fiWcsE9ggfLcdgO/ICHYgxq7mEy1yJ39brVvgXhtOtvDVjDh9slJxE4LQ==", + "license": "MIT", + "dependencies": { + "@inquirer/core": "^11.1.5", + "@inquirer/figures": "^2.0.3", + "@inquirer/type": "^4.0.3" + }, "engines": { - "node": ">=0.10.0" + "node": ">=23.5.0 || ^22.13.0 || ^21.7.0 || ^20.12.0" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } } }, - "node_modules/array-union": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", - "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=", - "dev": true, + "node_modules/@inquirer/select": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/@inquirer/select/-/select-5.1.0.tgz", + "integrity": "sha512-OyYbKnchS1u+zRe14LpYrN8S0wH1vD0p2yKISvSsJdH2TpI87fh4eZdWnpdbrGauCRWDph3NwxRmM4Pcm/hx1Q==", + "license": "MIT", "dependencies": { - "array-uniq": "^1.0.1" + "@inquirer/ansi": "^2.0.3", + "@inquirer/core": "^11.1.5", + "@inquirer/figures": "^2.0.3", + "@inquirer/type": "^4.0.3" }, "engines": { - "node": ">=0.10.0" + "node": ">=23.5.0 || ^22.13.0 || ^21.7.0 || ^20.12.0" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } } }, - "node_modules/array-uniq": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", - "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=", + "node_modules/@inquirer/type": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/@inquirer/type/-/type-4.0.3.tgz", + "integrity": "sha512-cKZN7qcXOpj1h+1eTTcGDVLaBIHNMT1Rz9JqJP5MnEJ0JhgVWllx7H/tahUp5YEK1qaByH2Itb8wLG/iScD5kw==", + "license": "MIT", + "engines": { + "node": ">=23.5.0 || ^22.13.0 || ^21.7.0 || ^20.12.0" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } + } + }, + "node_modules/@isaacs/cliui": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", + "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", "dev": true, + "dependencies": { + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" + }, "engines": { - "node": ">=0.10.0" + "node": ">=12" } }, - "node_modules/arrify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", - "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=", + "node_modules/@isaacs/cliui/node_modules/ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", "dev": true, "engines": { - "node": ">=0.10.0" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/asn1": { - "version": "0.2.4", - "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz", - "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==", + "node_modules/@isaacs/cliui/node_modules/emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "dev": true + }, + "node_modules/@isaacs/cliui/node_modules/string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "dev": true, "dependencies": { - "safer-buffer": "~2.1.0" + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/assert-plus": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", + "node_modules/@isaacs/cliui/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dev": true, + "dependencies": { + "ansi-regex": "^6.0.1" + }, "engines": { - "node": ">=0.8" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" } }, - "node_modules/assertion-error": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", - "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==", + "node_modules/@isaacs/cliui/node_modules/wrap-ansi": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", "dev": true, + "dependencies": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + }, "engines": { - "node": "*" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, - "node_modules/astral-regex": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", - "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", + "node_modules/@istanbuljs/schema": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", + "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } }, - "node_modules/async": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/async/-/async-3.2.3.tgz", - "integrity": "sha512-spZRyzKL5l5BZQrr/6m/SqFdBN0q3OCI0f9rjfBzCMBIP4p75P620rR3gTmaksNOhmzgdxcaxdNfMy6anrbM0g==" - }, - "node_modules/asynckit": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" - }, - "node_modules/aws-sign2": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", - "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=", + "node_modules/@jest/schemas": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", + "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", + "dev": true, + "dependencies": { + "@sinclair/typebox": "^0.27.8" + }, "engines": { - "node": "*" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/aws4": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.8.0.tgz", - "integrity": "sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ==" - }, - "node_modules/babel-runtime": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", - "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=", + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz", + "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==", "dev": true, - "dependencies": { - "core-js": "^2.4.0", - "regenerator-runtime": "^0.11.0" + "engines": { + "node": ">=6.0.0" } }, - "node_modules/balanced-match": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", - "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.4.15", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", + "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==", "dev": true }, - "node_modules/base64-js": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", - "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/bcrypt-pbkdf": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", - "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", - "dependencies": { - "tweetnacl": "^0.14.3" - } - }, - "node_modules/binary-extensions": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", - "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.19", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.19.tgz", + "integrity": "sha512-kf37QtfW+Hwx/buWGMPcR60iF9ziHa6r/CZJIHbmcm4+0qrXiVdxegAH0F6yddEVQ7zdkjcGCgCzUu+BcbhQxw==", "dev": true, - "engines": { - "node": ">=8" + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" } }, - "node_modules/bl": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", - "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "node_modules/@kwsites/file-exists": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@kwsites/file-exists/-/file-exists-1.1.1.tgz", + "integrity": "sha512-m9/5YGR18lIwxSFDwfE3oA7bWuq9kdau6ugN4H2rJeyhFQZcG9AgSHkQtSD15a8WvTgfz9aikZMrKPHvbpqFiw==", "dependencies": { - "buffer": "^5.5.0", - "inherits": "^2.0.4", - "readable-stream": "^3.4.0" + "debug": "^4.1.1" } }, - "node_modules/bluebird": { - "version": "3.7.2", - "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", - "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==" + "node_modules/@kwsites/promise-deferred": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@kwsites/promise-deferred/-/promise-deferred-1.1.1.tgz", + "integrity": "sha512-GaHYm+c0O9MjZRu0ongGBRbinu8gVAMd2UZjji6jVmqKtZluZnptXGWhz1E8j8D2HJ3f/yMxKAUC0b+57wncIw==" }, - "node_modules/boxen": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/boxen/-/boxen-4.2.0.tgz", - "integrity": "sha512-eB4uT9RGzg2odpER62bBwSLvUeGC+WbRjjyyFhGsKnc8wp/m0+hQsMUvUe3H2V0D5vw0nBdO1hCJoZo5mKeuIQ==", + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dev": true, "dependencies": { - "ansi-align": "^3.0.0", - "camelcase": "^5.3.1", - "chalk": "^3.0.0", - "cli-boxes": "^2.2.0", - "string-width": "^4.1.0", - "term-size": "^2.1.0", - "type-fest": "^0.8.1", - "widest-line": "^3.1.0" + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" }, "engines": { - "node": ">=8" - } - }, - "node_modules/boxen/node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "engines": { - "node": ">=8" + "node": ">= 8" } }, - "node_modules/boxen/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dependencies": { - "color-convert": "^2.0.1" - }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "dev": true, "engines": { - "node": ">=8" + "node": ">= 8" } }, - "node_modules/boxen/node_modules/chalk": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", - "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dev": true, "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" }, "engines": { - "node": ">=8" + "node": ">= 8" } }, - "node_modules/boxen/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dependencies": { - "color-name": "~1.1.4" - }, + "node_modules/@pkgjs/parseargs": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", + "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", + "dev": true, + "optional": true, "engines": { - "node": ">=7.0.0" + "node": ">=14" } }, - "node_modules/boxen/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" - }, - "node_modules/boxen/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" - }, - "node_modules/boxen/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "node_modules/@pkgr/core": { + "version": "0.2.9", + "resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.2.9.tgz", + "integrity": "sha512-QNqXyfVS2wm9hweSYD2O7F0G06uurj9kZ96TRQE5Y9hU7+tgdZwIkbAKc5Ocy1HxEY2kuDQa6cQ1WRs/O5LFKA==", + "dev": true, + "license": "MIT", "engines": { - "node": ">=8" + "node": "^12.20.0 || ^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/pkgr" } }, - "node_modules/boxen/node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "node_modules/@pnpm/config.env-replace": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@pnpm/config.env-replace/-/config.env-replace-1.1.0.tgz", + "integrity": "sha512-htyl8TWnKL7K/ESFa1oW2UB5lVDxuF5DpM7tBi6Hu2LNL3mWkIzNLG6N4zoCUP1lCKNxWy/3iu8mS8MvToGd6w==", "engines": { - "node": ">=8" + "node": ">=12.22.0" } }, - "node_modules/boxen/node_modules/string-width": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz", - "integrity": "sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==", + "node_modules/@pnpm/network.ca-file": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@pnpm/network.ca-file/-/network.ca-file-1.0.2.tgz", + "integrity": "sha512-YcPQ8a0jwYU9bTdJDpXjMi7Brhkr1mXsXrUJvjqM2mQDgkRiz8jFaQGOdaLxgjtUfQgZhKy/O3cG/YwmgKaxLA==", "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.0" + "graceful-fs": "4.2.10" }, "engines": { - "node": ">=8" + "node": ">=12.22.0" } }, - "node_modules/boxen/node_modules/strip-ansi": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", - "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", - "dependencies": { - "ansi-regex": "^5.0.0" - }, - "engines": { - "node": ">=8" - } + "node_modules/@pnpm/network.ca-file/node_modules/graceful-fs": { + "version": "4.2.10", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", + "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==" }, - "node_modules/boxen/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "node_modules/@pnpm/npm-conf": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/@pnpm/npm-conf/-/npm-conf-2.3.1.tgz", + "integrity": "sha512-c83qWb22rNRuB0UaVCI0uRPNRr8Z0FWnEIvT47jiHAmOIUHbBOg5XvV7pM5x+rKn9HRpjxquDbXYSXr3fAKFcw==", "dependencies": { - "has-flag": "^4.0.0" + "@pnpm/config.env-replace": "^1.1.0", + "@pnpm/network.ca-file": "^1.0.1", + "config-chain": "^1.1.11" }, "engines": { - "node": ">=8" + "node": ">=12" } }, - "node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } + "node_modules/@sinclair/typebox": { + "version": "0.27.8", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", + "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", + "dev": true }, - "node_modules/braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "node_modules/@sindresorhus/base62": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/base62/-/base62-1.0.0.tgz", + "integrity": "sha512-TeheYy0ILzBEI/CO55CP6zJCSdSWeRtGnHy8U8dWSUH4I68iqTsy7HkMktR4xakThc9jotkPQUXT4ITdbV7cHA==", "dev": true, - "dependencies": { - "fill-range": "^7.0.1" - }, + "license": "MIT", "engines": { - "node": ">=8" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/browser-stdout": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", - "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", - "dev": true - }, - "node_modules/buffer": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", - "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], + "node_modules/@so-ric/colorspace": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/@so-ric/colorspace/-/colorspace-1.1.6.tgz", + "integrity": "sha512-/KiKkpHNOBgkFJwu9sh48LkHSMYGyuTcSFK/qMBdnOAlrRJzRSXAOFB5qwzaVQuDl8wAvHVMkaASQDReTahxuw==", + "license": "MIT", "dependencies": { - "base64-js": "^1.3.1", - "ieee754": "^1.1.13" + "color": "^5.0.2", + "text-hex": "1.0.x" } }, - "node_modules/builtin-modules": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-3.1.0.tgz", - "integrity": "sha512-k0KL0aWZuBt2lrxrcASWDfwOLMnodeQjodT/1SxEQAXsHANgo6ZC/VEaSEHCXt7aSTZ4/4H5LKa+tBXmW7Vtvw==", + "node_modules/@types/esrecurse": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/@types/esrecurse/-/esrecurse-4.3.1.tgz", + "integrity": "sha512-xJBAbDifo5hpffDBuHl0Y8ywswbiAp/Wi7Y/GtAgSlZyIABppyurxVueOPE8LUQOxdlgi6Zqce7uoEpqNTeiUw==", "dev": true, - "engines": { - "node": ">=6" - } + "license": "MIT" }, - "node_modules/cache-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/cache-point/-/cache-point-2.0.0.tgz", - "integrity": "sha512-4gkeHlFpSKgm3vm2gJN5sPqfmijYRFYCQ6tv5cLw0xVmT6r1z1vd4FNnpuOREco3cBs1G709sZ72LdgddKvL5w==", + "node_modules/@types/estree": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", + "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", "dev": true, - "dependencies": { - "array-back": "^4.0.1", - "fs-then-native": "^2.0.0", - "mkdirp2": "^1.0.4" - }, - "engines": { - "node": ">=8" - } + "license": "MIT" }, - "node_modules/cacheable-request": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-6.1.0.tgz", - "integrity": "sha512-Oj3cAGPCqOZX7Rz64Uny2GYAZNliQSqfbePrgAQ1wKAihYmCUnraBtJtKcGR4xz7wF+LoJC+ssFZvv5BgF9Igg==", + "node_modules/@types/fs-extra": { + "version": "11.0.4", + "resolved": "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-11.0.4.tgz", + "integrity": "sha512-yTbItCNreRooED33qjunPthRcSjERP1r4MqCZc7wv0u2sUkzTFp45tgUfS5+r7FrZPdmCCNflLhVSP/o+SemsQ==", + "dev": true, "dependencies": { - "clone-response": "^1.0.2", - "get-stream": "^5.1.0", - "http-cache-semantics": "^4.0.0", - "keyv": "^3.0.0", - "lowercase-keys": "^2.0.0", - "normalize-url": "^4.1.0", - "responselike": "^1.0.2" - }, - "engines": { - "node": ">=8" + "@types/jsonfile": "*", + "@types/node": "*" } }, - "node_modules/cacheable-request/node_modules/get-stream": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", - "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", + "node_modules/@types/inquirer": { + "version": "9.0.9", + "resolved": "https://registry.npmjs.org/@types/inquirer/-/inquirer-9.0.9.tgz", + "integrity": "sha512-/mWx5136gts2Z2e5izdoRCo46lPp5TMs9R15GTSsgg/XnZyxDWVqoVU3R9lWnccKpqwsJLvRoxbCjoJtZB7DSw==", + "dev": true, + "license": "MIT", "dependencies": { - "pump": "^3.0.0" - }, - "engines": { - "node": ">=8" + "@types/through": "*", + "rxjs": "^7.2.0" } }, - "node_modules/cacheable-request/node_modules/lowercase-keys": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz", - "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==", - "engines": { - "node": ">=8" - } + "node_modules/@types/istanbul-lib-coverage": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.4.tgz", + "integrity": "sha512-z/QT1XN4K4KYuslS23k62yDIDLwLFkzxOuMplDtObz0+y7VqJCaO2o+SPwHCvLFZh7xazvvoor2tA/hPz9ee7g==", + "dev": true }, - "node_modules/callsite": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/callsite/-/callsite-1.0.0.tgz", - "integrity": "sha1-KAOY5dZkvXQDi28JBRU+borxvCA=", - "dev": true, - "engines": { - "node": "*" - } + "node_modules/@types/json-schema": { + "version": "7.0.15", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", + "dev": true }, - "node_modules/callsite-record": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/callsite-record/-/callsite-record-3.2.2.tgz", - "integrity": "sha1-mgOQZC5D/ou4I5ReUUZPafQWQ94=", + "node_modules/@types/jsonfile": { + "version": "6.1.4", + "resolved": "https://registry.npmjs.org/@types/jsonfile/-/jsonfile-6.1.4.tgz", + "integrity": "sha512-D5qGUYwjvnNNextdU59/+fI+spnwtTFmyQP0h+PfIOSkNfpU6AOICUOkm4i0OnSk+NyjdPJrxCDro0sJsWlRpQ==", "dev": true, "dependencies": { - "callsite": "^1.0.0", - "chalk": "^1.1.1", - "error-stack-parser": "^1.3.3", - "highlight-es": "^1.0.0", - "lodash": "4.6.1 || ^4.16.1", - "pinkie-promise": "^2.0.0" - } - }, - "node_modules/callsite-record/node_modules/ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", - "dev": true, - "engines": { - "node": ">=0.10.0" + "@types/node": "*" } }, - "node_modules/callsite-record/node_modules/ansi-styles": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } + "node_modules/@types/mocha": { + "version": "10.0.8", + "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-10.0.8.tgz", + "integrity": "sha512-HfMcUmy9hTMJh66VNcmeC9iVErIZJli2bszuXc6julh5YGuRb/W5OnkHjwLNYdFlMis0sY3If5SEAp+PktdJjw==", + "dev": true }, - "node_modules/callsite-record/node_modules/chalk": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", - "dev": true, + "node_modules/@types/node": { + "version": "25.3.5", + "resolved": "https://registry.npmjs.org/@types/node/-/node-25.3.5.tgz", + "integrity": "sha512-oX8xrhvpiyRCQkG1MFchB09f+cXftgIXb3a7UUa4Y3wpmZPw5tyZGTLWhlESOLq1Rq6oDlc8npVU2/9xiCuXMA==", + "devOptional": true, + "license": "MIT", "dependencies": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" + "undici-types": "~7.18.0" } }, - "node_modules/callsite-record/node_modules/strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "node_modules/@types/pegjs": { + "version": "0.10.6", + "resolved": "https://registry.npmjs.org/@types/pegjs/-/pegjs-0.10.6.tgz", + "integrity": "sha512-eLYXDbZWXh2uxf+w8sXS8d6KSoXTswfps6fvCUuVAGN8eRpfe7h9eSRydxiSJvo9Bf+GzifsDOr9TMQlmJdmkw==", + "license": "MIT" + }, + "node_modules/@types/through": { + "version": "0.0.33", + "resolved": "https://registry.npmjs.org/@types/through/-/through-0.0.33.tgz", + "integrity": "sha512-HsJ+z3QuETzP3cswwtzt2vEIiHBk/dCcHGhbmG5X3ecnwFD/lPrMpliGXxSCg03L9AhrdwA4Oz/qfspkDW+xGQ==", "dev": true, "dependencies": { - "ansi-regex": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" + "@types/node": "*" } }, - "node_modules/callsite-record/node_modules/supports-color": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", - "dev": true, - "engines": { - "node": ">=0.8.0" - } + "node_modules/@types/triple-beam": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/@types/triple-beam/-/triple-beam-1.3.5.tgz", + "integrity": "sha512-6WaYesThRMCl19iryMYP7/x2OVgCtbIVflDGFpWnb9irXI3UjYE4AzmYuiUKY1AJstGijoY+MgUszMgRxIYTYw==" }, - "node_modules/callsites": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", - "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "node_modules/@types/yargs": { + "version": "17.0.35", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.35.tgz", + "integrity": "sha512-qUHkeCyQFxMXg79wQfTtfndEC+N9ZZg76HJftDJp+qH2tV7Gj4OJi7l+PiWwJ+pWtW8GwSmqsDj/oymhrTWXjg==", "dev": true, - "engines": { - "node": ">=6" + "license": "MIT", + "dependencies": { + "@types/yargs-parser": "*" } }, - "node_modules/camelcase": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", - "engines": { - "node": ">=6" - } + "node_modules/@types/yargs-parser": { + "version": "21.0.3", + "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.3.tgz", + "integrity": "sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==", + "dev": true }, - "node_modules/camelcase-keys": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-2.1.0.tgz", - "integrity": "sha1-MIvur/3ygRkFHvodkyITyRuPkuc=", + "node_modules/@typescript-eslint/scope-manager": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.21.0.tgz", + "integrity": "sha512-OwLUIWZJry80O99zvqXVEioyniJMa+d2GrqpUTqi5/v5D5rOrppJVBPa0yKCblcigC0/aYAzxxqQ1B+DS2RYsg==", "dev": true, "dependencies": { - "camelcase": "^2.0.0", - "map-obj": "^1.0.0" + "@typescript-eslint/types": "6.21.0", + "@typescript-eslint/visitor-keys": "6.21.0" }, "engines": { - "node": ">=0.10.0" + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/camelcase-keys/node_modules/camelcase": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-2.1.1.tgz", - "integrity": "sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8=", + "node_modules/@typescript-eslint/types": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.21.0.tgz", + "integrity": "sha512-1kFmZ1rOm5epu9NZEZm1kckCDGj5UJEf7P1kliH4LKu/RkwpsfqqGmY2OOcUs18lSlQBKLDYBOGxRVtrMN5lpg==", "dev": true, "engines": { - "node": ">=0.10.0" + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/capture-stack-trace": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/capture-stack-trace/-/capture-stack-trace-1.0.1.tgz", - "integrity": "sha512-mYQLZnx5Qt1JgB1WEiMCf2647plpGeQ2NMR/5L0HNZzGQo4fuSPnK+wjfPnKZV0aiJDgzmWqqkV/g7JD+DW0qw==", + "node_modules/@typescript-eslint/typescript-estree": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.21.0.tgz", + "integrity": "sha512-6npJTkZcO+y2/kr+z0hc4HwNfrrP4kNYh57ek7yCNlrBjWQ1Y0OS7jiZTkgumrvkX5HkEKXFZkkdFNkaW2wmUQ==", "dev": true, + "dependencies": { + "@typescript-eslint/types": "6.21.0", + "@typescript-eslint/visitor-keys": "6.21.0", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "minimatch": "9.0.3", + "semver": "^7.5.4", + "ts-api-utils": "^1.0.1" + }, "engines": { - "node": ">=0.10.0" + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } } }, - "node_modules/caseless": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", - "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=" - }, - "node_modules/catharsis": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/catharsis/-/catharsis-0.9.0.tgz", - "integrity": "sha512-prMTQVpcns/tzFgFVkVp6ak6RykZyWb3gu8ckUpd6YkTlacOd3DXGJjIpD4Q6zJirizvaiAjSSHlOsA+6sNh2A==", + "node_modules/@typescript-eslint/typescript-estree/node_modules/brace-expansion": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", + "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", "dev": true, + "license": "MIT", "dependencies": { - "lodash": "^4.17.15" - }, - "engines": { - "node": ">= 10" + "balanced-match": "^1.0.0" } }, - "node_modules/chai": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/chai/-/chai-4.3.4.tgz", - "integrity": "sha512-yS5H68VYOCtN1cjfwumDSuzn/9c+yza4f3reKXlE5rUg7SFcCEy90gJvydNgOYtblyf4Zi6jIWRnXOgErta0KA==", + "node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch": { + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", + "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", "dev": true, "dependencies": { - "assertion-error": "^1.1.0", - "check-error": "^1.0.2", - "deep-eql": "^3.0.1", - "get-func-name": "^2.0.0", - "pathval": "^1.1.1", - "type-detect": "^4.0.5" + "brace-expansion": "^2.0.1" }, "engines": { - "node": ">=4" + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "node_modules/@typescript-eslint/visitor-keys": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.21.0.tgz", + "integrity": "sha512-JJtkDduxLi9bivAB+cYOVMtbkqdPOhZ+ZI5LC47MIRrDV4Yn2o+ZnW10Nkmr28xRpSpdJ6Sm42Hjf2+REYXm0A==", "dev": true, "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" + "@typescript-eslint/types": "6.21.0", + "eslint-visitor-keys": "^3.4.1" }, "engines": { - "node": ">=4" + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/chardet": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz", - "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==" - }, - "node_modules/check-error": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz", - "integrity": "sha1-V00xLt2Iu13YkS6Sht1sCu1KrII=", + "node_modules/@ungap/structured-clone": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", + "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==", + "dev": true + }, + "node_modules/acorn": { + "version": "8.16.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.16.0.tgz", + "integrity": "sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==", "dev": true, + "license": "MIT", + "bin": { + "acorn": "bin/acorn" + }, "engines": { - "node": "*" + "node": ">=0.4.0" } }, - "node_modules/chokidar": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.2.tgz", - "integrity": "sha512-ekGhOnNVPgT77r4K/U3GDhu+FQ2S8TnK/s2KbIGXi0SZWuwkZ2QNyfWdZW+TVfn84DpEP7rLeCt2UI6bJ8GwbQ==", + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", "dev": true, + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/ajv": { + "version": "8.18.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.18.0.tgz", + "integrity": "sha512-PlXPeEWMXMZ7sPYOHqmDyCJzcfNrUr3fGNKtezX14ykXOEIvyK81d+qydx89KY5O71FKMPaQ2vBfBFI5NHR63A==", + "license": "MIT", "dependencies": { - "anymatch": "~3.1.2", - "braces": "~3.0.2", - "glob-parent": "~5.1.2", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.6.0" - }, - "engines": { - "node": ">= 8.10.0" + "fast-deep-equal": "^3.1.3", + "fast-uri": "^3.0.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2" }, - "optionalDependencies": { - "fsevents": "~2.3.2" + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" } }, - "node_modules/ci-info": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-1.6.0.tgz", - "integrity": "sha512-vsGdkwSCDpWmP80ncATX7iea5DWQemg1UgCW5J8tqjU3lYw4FBYuj89J0CTVomA7BEfvSZd84GmHko+MxFQU2A==", - "dev": true + "node_modules/ajv-formats": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-3.0.1.tgz", + "integrity": "sha512-8iUql50EUR+uUcdRQ3HDqa6EVyo3docL8g5WJ3FNcWmu62IbkGUue/pEyLBW8VGKKucTPgqeks4fIU1DA4yowQ==", + "dependencies": { + "ajv": "^8.0.0" + }, + "peerDependencies": { + "ajv": "^8.0.0" + }, + "peerDependenciesMeta": { + "ajv": { + "optional": true + } + } }, - "node_modules/clean-stack": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", - "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", - "dev": true, - "engines": { - "node": ">=6" + "node_modules/ansi-align": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.1.tgz", + "integrity": "sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w==", + "dependencies": { + "string-width": "^4.1.0" } }, - "node_modules/cli-boxes": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-2.2.1.tgz", - "integrity": "sha512-y4coMcylgSCdVinjiDBuR8PCC2bLjyGTwEmPb9NHR/QaNU6EUOXcTY/s6VjGMD6ENSEaeQYHCY0GNGS5jfMwPw==", + "node_modules/ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", "engines": { - "node": ">=6" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" } }, - "node_modules/cli-cursor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", - "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, "dependencies": { - "restore-cursor": "^3.1.0" + "color-convert": "^2.0.1" }, "engines": { "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/cli-progress": { - "version": "3.10.0", - "resolved": "https://registry.npmjs.org/cli-progress/-/cli-progress-3.10.0.tgz", - "integrity": "sha512-kLORQrhYCAtUPLZxqsAt2YJGOvRdt34+O6jl5cQGb7iF3dM55FQZlTR+rQyIK9JUcO9bBMwZsTlND+3dmFU2Cw==", + "node_modules/are-docs-informative": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/are-docs-informative/-/are-docs-informative-0.0.2.tgz", + "integrity": "sha512-ixiS0nLNNG5jNQzgZJNoUpBKdo9yTYZMGJ+QgT2jmjR7G7+QHRCc4v6LQ3NgE7EBJq+o0ams3waJwkrlBom8Ig==", + "dev": true, + "engines": { + "node": ">=14" + } + }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" + }, + "node_modules/array-buffer-byte-length": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.0.tgz", + "integrity": "sha512-LPuwb2P+NrQw3XhxGc36+XSvuBPopovXYTR9Ew++Du9Yb/bx5AzBfrIsBoj0EZUifjQU+sHL21sseZ3jerWO/A==", "dependencies": { - "string-width": "^4.2.0" + "call-bind": "^1.0.2", + "is-array-buffer": "^3.0.1" }, - "engines": { - "node": ">=4" + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/cli-progress/node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "node_modules/array-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", + "dev": true, "engines": { "node": ">=8" } }, - "node_modules/cli-progress/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + "node_modules/assert": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/assert/-/assert-2.1.0.tgz", + "integrity": "sha512-eLHpSK/Y4nhMJ07gDaAzoX/XAKS8PSaojml3M0DM4JpV1LAi5JOJ/p6H/XWrl8L+DzVEvVCW1z3vWAaB9oTsQw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "is-nan": "^1.3.2", + "object-is": "^1.1.5", + "object.assign": "^4.1.4", + "util": "^0.12.5" + } }, - "node_modules/cli-progress/node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "node_modules/assertion-error": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", + "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==", + "dev": true, "engines": { - "node": ">=8" + "node": "*" } }, - "node_modules/cli-progress/node_modules/string-width": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz", - "integrity": "sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==", + "node_modules/async": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.3.tgz", + "integrity": "sha512-spZRyzKL5l5BZQrr/6m/SqFdBN0q3OCI0f9rjfBzCMBIP4p75P620rR3gTmaksNOhmzgdxcaxdNfMy6anrbM0g==" + }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", + "license": "MIT" + }, + "node_modules/atomically": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/atomically/-/atomically-2.0.3.tgz", + "integrity": "sha512-kU6FmrwZ3Lx7/7y3hPS5QnbJfaohcIul5fGqf7ok+4KklIEk9tJ0C2IQPdacSbVUWv6zVHXEBWoWd6NrVMT7Cw==", "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.0" - }, + "stubborn-fs": "^1.2.5", + "when-exit": "^2.1.1" + } + }, + "node_modules/available-typed-arrays": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz", + "integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==", "engines": { - "node": ">=8" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/cli-progress/node_modules/strip-ansi": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", - "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", + "node_modules/axios": { + "version": "1.13.5", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.13.5.tgz", + "integrity": "sha512-cz4ur7Vb0xS4/KUN0tPWe44eqxrIu31me+fbang3ijiNscE129POzipJJA6zniq2C/Z6sJCjMimjS8Lc/GAs8Q==", + "license": "MIT", + "dependencies": { + "follow-redirects": "^1.15.11", + "form-data": "^4.0.5", + "proxy-from-env": "^1.1.0" + } + }, + "node_modules/axios-mock-adapter": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/axios-mock-adapter/-/axios-mock-adapter-2.0.0.tgz", + "integrity": "sha512-D/K0J5Zm6KvaMTnsWrBQZWLzKN9GxUFZEa0mx2qeEHXDeTugCoplWehy8y36dj5vuSjhe1u/Dol8cZ8lzzmDew==", + "dev": true, "dependencies": { - "ansi-regex": "^5.0.0" + "fast-deep-equal": "^3.1.3", + "is-buffer": "^2.0.5" }, - "engines": { - "node": ">=8" + "peerDependencies": { + "axios": ">= 0.17.0" } }, - "node_modules/cli-spinners": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-0.1.2.tgz", - "integrity": "sha1-u3ZNiOGF+54eaiofGXcjGPYF4xw=", + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true + }, + "node_modules/baseline-browser-mapping": { + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.10.0.tgz", + "integrity": "sha512-lIyg0szRfYbiy67j9KN8IyeD7q7hcmqnJ1ddWmNt19ItGpNN64mnllmxUNFIOdOm6by97jlL6wfpTTJrmnjWAA==", "dev": true, + "license": "Apache-2.0", + "bin": { + "baseline-browser-mapping": "dist/cli.cjs" + }, "engines": { - "node": ">=0.10.0" + "node": ">=6.0.0" } }, - "node_modules/cli-truncate": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-3.1.0.tgz", - "integrity": "sha512-wfOBkjXteqSnI59oPcJkcPl/ZmwvMMOj340qUIY1SKZCv0B9Cf4D4fAucRkIKQmsIuYK3x1rrgU7MeGRruiuiA==", - "dev": true, + "node_modules/beauty-amp-core2": { + "version": "0.4.9", + "resolved": "https://registry.npmjs.org/beauty-amp-core2/-/beauty-amp-core2-0.4.9.tgz", + "integrity": "sha512-OFZ3XHPgv1NCHwic0H7G4kfS5gkkyY5iLzM4WZF6M8KxV1JGYhKFbFke2bVp3DKa4vy6yOwlVyhOmFhuTt7X6Q==" + }, + "node_modules/big-integer": { + "version": "1.6.52", + "resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.52.tgz", + "integrity": "sha512-QxD8cf2eVqJOOz63z6JIN9BzvVs/dlySa5HGSBH5xtR8dPteIRQnBxxKqkNTiT6jbDTF6jAfrd4oMcND9RGbQg==", + "license": "Unlicense", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/boxen": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/boxen/-/boxen-8.0.1.tgz", + "integrity": "sha512-F3PH5k5juxom4xktynS7MoFY+NUWH5LC4CnH11YB8NPew+HLpmBLCybSAEyb2F+4pRXhuhWqFesoQd6DAyc2hw==", "dependencies": { - "slice-ansi": "^5.0.0", - "string-width": "^5.0.0" + "ansi-align": "^3.0.1", + "camelcase": "^8.0.0", + "chalk": "^5.3.0", + "cli-boxes": "^3.0.0", + "string-width": "^7.2.0", + "type-fest": "^4.21.0", + "widest-line": "^5.0.0", + "wrap-ansi": "^9.0.0" }, "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/cli-truncate/node_modules/ansi-regex": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", - "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", - "dev": true, + "node_modules/boxen/node_modules/camelcase": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-8.0.0.tgz", + "integrity": "sha512-8WB3Jcas3swSvjIeA2yvCJ+Miyz5l1ZmB6HFb9R1317dt9LCQoswg/BGrmAmkWVEszSrrg4RwmO46qIm2OEnSA==", "engines": { - "node": ">=12" + "node": ">=16" }, "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/cli-truncate/node_modules/emoji-regex": { - "version": "9.2.2", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", - "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", - "dev": true - }, - "node_modules/cli-truncate/node_modules/is-fullwidth-code-point": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-4.0.0.tgz", - "integrity": "sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ==", - "dev": true, + "node_modules/boxen/node_modules/chalk": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.3.0.tgz", + "integrity": "sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==", "engines": { - "node": ">=12" + "node": "^12.17.0 || ^14.13 || >=16.0.0" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/cli-truncate/node_modules/string-width": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.0.1.tgz", - "integrity": "sha512-5ohWO/M4//8lErlUUtrFy3b11GtNOuMOU0ysKCDXFcfXuuvUXu95akgj/i8ofmaGdN0hCqyl6uu9i8dS/mQp5g==", - "dev": true, + "node_modules/boxen/node_modules/emoji-regex": { + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.3.0.tgz", + "integrity": "sha512-QpLs9D9v9kArv4lfDEgg1X/gN5XLnf/A6l9cs8SPZLRZR3ZkY9+kwIQTxm+fsSej5UMYGE8fdoaZVIBlqG0XTw==" + }, + "node_modules/boxen/node_modules/string-width": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz", + "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", "dependencies": { - "emoji-regex": "^9.2.2", - "is-fullwidth-code-point": "^4.0.0", - "strip-ansi": "^7.0.1" + "emoji-regex": "^10.3.0", + "get-east-asian-width": "^1.0.0", + "strip-ansi": "^7.1.0" }, "engines": { - "node": ">=12" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/cli-truncate/node_modules/strip-ansi": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.0.1.tgz", - "integrity": "sha512-cXNxvT8dFNRVfhVME3JAe98mkXDYN2O1l7jmcwMnOslDeESg1rF/OZMtK0nRAhiari1unG5cD4jG3rapUAkLbw==", - "dev": true, + "node_modules/boxen/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", "dependencies": { "ansi-regex": "^6.0.1" }, @@ -1318,994 +1586,1183 @@ "url": "https://github.com/chalk/strip-ansi?sponsor=1" } }, - "node_modules/cli-width": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.0.tgz", - "integrity": "sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk=", - "dev": true + "node_modules/boxen/node_modules/type-fest": { + "version": "4.25.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.25.0.tgz", + "integrity": "sha512-bRkIGlXsnGBRBQRAY56UXBm//9qH4bmJfFvq83gSz41N282df+fjy8ofcEgc1sM8geNt5cl6mC2g9Fht1cs8Aw==", + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } }, - "node_modules/cliui": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", - "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", + "node_modules/brace-expansion": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", "dev": true, + "license": "MIT", "dependencies": { - "string-width": "^3.1.0", - "strip-ansi": "^5.2.0", - "wrap-ansi": "^5.1.0" + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" } }, - "node_modules/clone": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", - "integrity": "sha1-2jCcwmPfFZlMaIypAheco8fNfH4=", + "node_modules/braces": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "dev": true, + "dependencies": { + "fill-range": "^7.1.1" + }, "engines": { - "node": ">=0.8" + "node": ">=8" } }, - "node_modules/clone-response": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.2.tgz", - "integrity": "sha1-0dyXOSAxTfZ/vrlCI7TuNQI56Ws=", - "dependencies": { - "mimic-response": "^1.0.0" - } + "node_modules/browser-stdout": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", + "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", + "dev": true }, - "node_modules/co": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", - "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=", + "node_modules/browserslist": { + "version": "4.28.1", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.1.tgz", + "integrity": "sha512-ZC5Bd0LgJXgwGqUknZY/vkUQ04r8NXnJZ3yYi4vDmSiZmC/pdSN0NbNRPxZpbtO4uAfDUAFffO8IZoM3Gj8IkA==", "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "baseline-browser-mapping": "^2.9.0", + "caniuse-lite": "^1.0.30001759", + "electron-to-chromium": "^1.5.263", + "node-releases": "^2.0.27", + "update-browserslist-db": "^1.2.0" + }, + "bin": { + "browserslist": "cli.js" + }, "engines": { - "iojs": ">= 1.0.0", - "node": ">= 0.12.0" + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" } }, - "node_modules/code-point-at": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", - "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", + "node_modules/builtin-modules": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-5.0.0.tgz", + "integrity": "sha512-bkXY9WsVpY7CvMhKSR6pZilZu9Ln5WDrKVBUXf2S443etkmEO4V58heTecXcUIsNsi4Rx8JUO4NfX1IcQl4deg==", "dev": true, + "license": "MIT", "engines": { - "node": ">=0.10.0" + "node": ">=18.20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/collect-all": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/collect-all/-/collect-all-1.0.4.tgz", - "integrity": "sha512-RKZhRwJtJEP5FWul+gkSMEnaK6H3AGPTTWOiRimCcs+rc/OmQE3Yhy1Q7A7KsdkG3ZXVdZq68Y6ONSdvkeEcKA==", + "node_modules/c8": { + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/c8/-/c8-11.0.0.tgz", + "integrity": "sha512-e/uRViGHSVIJv7zsaDKM7VRn2390TgHXqUSvYwPHBQaU6L7E9L0n9JbdkwdYPvshDT0KymBmmlwSpms3yBaMNg==", "dev": true, + "license": "ISC", "dependencies": { - "stream-connect": "^1.0.2", - "stream-via": "^1.0.4" + "@bcoe/v8-coverage": "^1.0.1", + "@istanbuljs/schema": "^0.1.3", + "find-up": "^5.0.0", + "foreground-child": "^3.1.1", + "istanbul-lib-coverage": "^3.2.0", + "istanbul-lib-report": "^3.0.1", + "istanbul-reports": "^3.1.6", + "test-exclude": "^8.0.0", + "v8-to-istanbul": "^9.0.0", + "yargs": "^17.7.2", + "yargs-parser": "^21.1.1" + }, + "bin": { + "c8": "bin/c8.js" }, "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/color": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/color/-/color-3.0.0.tgz", - "integrity": "sha512-jCpd5+s0s0t7p3pHQKpnJ0TpQKKdleP71LWcA0aqiljpiuAkOSUFN/dyH8ZwF0hRmFlrIuRhufds1QyEP9EB+w==", - "dependencies": { - "color-convert": "^1.9.1", - "color-string": "^1.5.2" + "node": "20 || >=22" + }, + "peerDependencies": { + "monocart-coverage-reports": "^2" + }, + "peerDependenciesMeta": { + "monocart-coverage-reports": { + "optional": true + } } }, - "node_modules/color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "node_modules/c8/node_modules/cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "dev": true, + "license": "ISC", "dependencies": { - "color-name": "1.1.3" + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" } }, - "node_modules/color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" - }, - "node_modules/color-string": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.9.0.tgz", - "integrity": "sha512-9Mrz2AQLefkH1UvASKj6v6hj/7eWgjnT/cVsR8CumieLoT+g900exWeNogqtweI8dxloXN9BDQTYro1oWu/5CQ==", + "node_modules/c8/node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "license": "MIT", "dependencies": { - "color-name": "^1.0.0", - "simple-swizzle": "^0.2.2" - } - }, - "node_modules/colorette": { - "version": "2.0.16", - "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.16.tgz", - "integrity": "sha512-hUewv7oMjCp+wkBv5Rm0v87eJhq4woh5rSR+42YSQJKecCqgIqNkZ6lAlQms/BwHPJA5NKMRlpxPRv0n8HQW6g==", - "dev": true - }, - "node_modules/colors": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz", - "integrity": "sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==", + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, "engines": { - "node": ">=0.1.90" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, - "node_modules/colorspace": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/colorspace/-/colorspace-1.1.2.tgz", - "integrity": "sha512-vt+OoIP2d76xLhjwbBaucYlNSpPsrJWPlBTtwCpQKIu6/CSMutyzX93O/Do0qzpH3YoHEes8YEFXyZ797rEhzQ==", + "node_modules/c8/node_modules/yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "dev": true, + "license": "MIT", "dependencies": { - "color": "3.0.x", - "text-hex": "1.0.x" + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + }, + "engines": { + "node": ">=12" } }, - "node_modules/combined-stream": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", - "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "node_modules/call-bind": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.5.tgz", + "integrity": "sha512-C3nQxfFZxFRVoJoGKKI8y3MOEo129NQ+FgQ08iye+Mk4zNZZGdjfs06bVTr+DBSlA66Q2VEcMki/cUCP4SercQ==", "dependencies": { - "delayed-stream": "~1.0.0" + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.1", + "set-function-length": "^1.1.1" }, - "engines": { - "node": ">= 0.8" + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/command-exists": { - "version": "1.2.9", - "resolved": "https://registry.npmjs.org/command-exists/-/command-exists-1.2.9.tgz", - "integrity": "sha512-LTQ/SGc+s0Xc0Fu5WaKnR0YiygZkm9eKFvyS+fRsU7/ZWFF8ykFM6Pc9aCVf1+xasOOZpO3BAVgVrKvsqKHV7w==" - }, - "node_modules/command-line-args": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/command-line-args/-/command-line-args-5.1.1.tgz", - "integrity": "sha512-hL/eG8lrll1Qy1ezvkant+trihbGnaKaeEjj6Scyr3DN+RC7iQ5Rz84IeLERfAWDGo0HBSNAakczwgCilDXnWg==", - "dev": true, + "node_modules/call-bind-apply-helpers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", + "license": "MIT", "dependencies": { - "array-back": "^3.0.1", - "find-replace": "^3.0.0", - "lodash.camelcase": "^4.3.0", - "typical": "^4.0.0" + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" }, "engines": { - "node": ">=4.0.0" + "node": ">= 0.4" } }, - "node_modules/command-line-args/node_modules/array-back": { + "node_modules/callsites": { "version": "3.1.0", - "resolved": "https://registry.npmjs.org/array-back/-/array-back-3.1.0.tgz", - "integrity": "sha512-TkuxA4UCOvxuDK6NZYXCalszEzj+TLszyASooky+i742l9TqsOdYCMJJupxRic61hwquNtppB3hgcuq9SVSH1Q==", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", "dev": true, "engines": { "node": ">=6" } }, - "node_modules/command-line-args/node_modules/typical": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/typical/-/typical-4.0.0.tgz", - "integrity": "sha512-VAH4IvQ7BDFYglMd7BPRDfLgxZZX4O4TFcRDA6EN5X7erNJJq+McIEp8np9aVtxrCJ6qx4GTYVfOWNjcqwZgRw==", + "node_modules/camelcase": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", "dev": true, "engines": { - "node": ">=8" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/command-line-tool": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/command-line-tool/-/command-line-tool-0.8.0.tgz", - "integrity": "sha512-Xw18HVx/QzQV3Sc5k1vy3kgtOeGmsKIqwtFFoyjI4bbcpSgnw2CWVULvtakyw4s6fhyAdI6soQQhXc2OzJy62g==", + "node_modules/caniuse-lite": { + "version": "1.0.30001770", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001770.tgz", + "integrity": "sha512-x/2CLQ1jHENRbHg5PSId2sXq1CIO1CISvwWAj027ltMVG2UNgW+w9oH2+HzgEIRFembL8bUlXtfbBHR1fCg2xw==", "dev": true, - "dependencies": { - "ansi-escape-sequences": "^4.0.0", - "array-back": "^2.0.0", - "command-line-args": "^5.0.0", - "command-line-usage": "^4.1.0", - "typical": "^2.6.1" - }, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "CC-BY-4.0" + }, + "node_modules/chai": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/chai/-/chai-6.2.2.tgz", + "integrity": "sha512-NUPRluOfOiTKBKvWPtSD4PhFvWCqOi0BGStNWs57X9js7XGTprSmFoz5F0tWhR4WPjNeR9jXqdC7/UpSJTnlRg==", + "dev": true, + "license": "MIT", "engines": { - "node": ">=4.0.0" + "node": ">=18" } }, - "node_modules/command-line-tool/node_modules/array-back": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/array-back/-/array-back-2.0.0.tgz", - "integrity": "sha512-eJv4pLLufP3g5kcZry0j6WXpIbzYw9GUB4mVJZno9wfwiBxbizTnHCw3VJb07cBihbFX48Y7oSrW9y+gt4glyw==", + "node_modules/chai-files": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/chai-files/-/chai-files-1.4.0.tgz", + "integrity": "sha512-tPTx7H2kpR+wILWHRx8RxpXcRUdc2uH8su505C9R3p5GA+eYbZBXuxWC0RZbyElYi7X7Fp/V/S2PQjkakrT1mQ==", "dev": true, "dependencies": { - "typical": "^2.6.1" - }, - "engines": { - "node": ">=4" + "assertion-error": "^1.0.1" } }, - "node_modules/command-line-usage": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/command-line-usage/-/command-line-usage-4.1.0.tgz", - "integrity": "sha512-MxS8Ad995KpdAC0Jopo/ovGIroV/m0KHwzKfXxKag6FHOkGsH8/lv5yjgablcRxCJJC0oJeUMuO/gmaq+Wq46g==", + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, "dependencies": { - "ansi-escape-sequences": "^4.0.0", - "array-back": "^2.0.0", - "table-layout": "^0.4.2", - "typical": "^2.6.1" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" }, "engines": { - "node": ">=4.0.0" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/command-line-usage/node_modules/array-back": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/array-back/-/array-back-2.0.0.tgz", - "integrity": "sha512-eJv4pLLufP3g5kcZry0j6WXpIbzYw9GUB4mVJZno9wfwiBxbizTnHCw3VJb07cBihbFX48Y7oSrW9y+gt4glyw==", + "node_modules/change-case": { + "version": "5.4.4", + "resolved": "https://registry.npmjs.org/change-case/-/change-case-5.4.4.tgz", + "integrity": "sha512-HRQyTk2/YPEkt9TnUPbOpr64Uw3KOicFWPVBb+xiHvd6eBx/qPr9xqfBFDT8P2vWsvvz4jbEkfDe71W3VyNu2w==", + "dev": true, + "license": "MIT" + }, + "node_modules/chardet": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/chardet/-/chardet-2.1.1.tgz", + "integrity": "sha512-PsezH1rqdV9VvyNhxxOW32/d75r01NY7TQCmOqomRo15ZSOKbpTFVsfjghxo6JloQUCGnH4k1LGu0R4yCLlWQQ==", + "license": "MIT" + }, + "node_modules/chokidar": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz", + "integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==", "dev": true, + "license": "MIT", "dependencies": { - "typical": "^2.6.1" + "readdirp": "^4.0.1" }, "engines": { - "node": ">=4" + "node": ">= 14.16.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" } }, - "node_modules/commander": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz", - "integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==", + "node_modules/ci-info": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-4.4.0.tgz", + "integrity": "sha512-77PSwercCZU2Fc4sX94eF8k8Pxte6JAwL4/ICZLFjJLqegs7kCuAsqqj/70NQF6TvDpgFjkubQB2FW2ZZddvQg==", "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], + "license": "MIT", "engines": { - "node": ">= 12" + "node": ">=8" } }, - "node_modules/common-sequence": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/common-sequence/-/common-sequence-2.0.2.tgz", - "integrity": "sha512-jAg09gkdkrDO9EWTdXfv80WWH3yeZl5oT69fGfedBNS9pXUKYInVJ1bJ+/ht2+Moeei48TmSbQDYMc8EOx9G0g==", + "node_modules/clean-regexp": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/clean-regexp/-/clean-regexp-1.0.0.tgz", + "integrity": "sha512-GfisEZEJvzKrmGWkvfhgzcz/BllN1USeqD2V6tg14OAOgaCD2Z/PUEuxnAZ/nPvmaHRG7a8y77p1T/IRQ4D1Hw==", "dev": true, + "dependencies": { + "escape-string-regexp": "^1.0.5" + }, "engines": { - "node": ">=8" + "node": ">=4" } }, - "node_modules/concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", - "dev": true - }, - "node_modules/config-master": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/config-master/-/config-master-3.1.0.tgz", - "integrity": "sha1-ZnZjWQUFooO/JqSE1oSJ10xUhdo=", + "node_modules/clean-regexp/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", "dev": true, - "dependencies": { - "walk-back": "^2.0.1" + "engines": { + "node": ">=0.8.0" } }, - "node_modules/config-master/node_modules/walk-back": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/walk-back/-/walk-back-2.0.1.tgz", - "integrity": "sha1-VU4qnYdPrEeoywBr9EwvDEmYoKQ=", - "dev": true, + "node_modules/cli-boxes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-3.0.0.tgz", + "integrity": "sha512-/lzGpEWL/8PfI0BmBOPRwp0c/wFNX1RdUML3jK/RcSBA9T8mZDdQpqYBKtCFTOfQbwPqWEOpjqW+Fnayc0969g==", "engines": { - "node": ">=0.10.0" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/configstore": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/configstore/-/configstore-5.0.1.tgz", - "integrity": "sha512-aMKprgk5YhBNyH25hj8wGt2+D52Sw1DRRIzqBwLp2Ya9mFmY8KPvvtvmna8SxVR9JMZ4kzMD68N22vlaRpkeFA==", + "node_modules/cli-cursor": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-5.0.0.tgz", + "integrity": "sha512-aCj4O5wKyszjMmDT4tZj93kxyydN/K5zPWSCe6/0AV/AA1pqe5ZBIw0a2ZfPQV7lL5/yb5HsUreJ6UFAF1tEQw==", + "dev": true, + "license": "MIT", "dependencies": { - "dot-prop": "^5.2.0", - "graceful-fs": "^4.1.2", - "make-dir": "^3.0.0", - "unique-string": "^2.0.0", - "write-file-atomic": "^3.0.0", - "xdg-basedir": "^4.0.0" + "restore-cursor": "^5.0.0" }, "engines": { - "node": ">=8" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/console.table": { - "version": "0.10.0", - "resolved": "https://registry.npmjs.org/console.table/-/console.table-0.10.0.tgz", - "integrity": "sha1-CRcCVYiHW+/XDPLv9L7yxuLXXQQ=", + "node_modules/cli-progress": { + "version": "3.12.0", + "resolved": "https://registry.npmjs.org/cli-progress/-/cli-progress-3.12.0.tgz", + "integrity": "sha512-tRkV3HJ1ASwm19THiiLIXLO7Im7wlTuKnvkYaTkyoAPefqjNg7W7DHKUlGRxy9vxDvbyCYQkQozvptuMkGCg8A==", "dependencies": { - "easy-table": "1.1.0" + "string-width": "^4.2.3" }, "engines": { - "node": "> 0.10" + "node": ">=4" } }, - "node_modules/core-js": { - "version": "2.6.11", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.11.tgz", - "integrity": "sha512-5wjnpaT/3dV+XB4borEsnAYQchn00XSgTAWKDkEqv+K8KevjbzmofK6hfJ9TZIlpj2N0xQpazy7PiRQiWHqzWg==", - "hasInstallScript": true - }, - "node_modules/core-util-is": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" - }, - "node_modules/create-error-class": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/create-error-class/-/create-error-class-3.0.2.tgz", - "integrity": "sha1-Br56vvlHo/FKMP1hBnHUAbyot7Y=", + "node_modules/cli-truncate": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-5.1.1.tgz", + "integrity": "sha512-SroPvNHxUnk+vIW/dOSfNqdy1sPEFkrTk6TUtqLCnBlo3N7TNYYkzzN7uSD6+jVjrdO4+p8nH7JzH6cIvUem6A==", "dev": true, + "license": "MIT", "dependencies": { - "capture-stack-trace": "^1.0.0" + "slice-ansi": "^7.1.0", + "string-width": "^8.0.0" }, "engines": { - "node": ">=0.10.0" + "node": ">=20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/cross-spawn": { - "version": "6.0.5", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", - "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", + "node_modules/cli-truncate/node_modules/string-width": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-8.1.0.tgz", + "integrity": "sha512-Kxl3KJGb/gxkaUMOjRsQ8IrXiGW75O4E3RPjFIINOVH8AMl2SQ/yWdTzWwF3FevIX9LcMAjJW+GRwAlAbTSXdg==", "dev": true, + "license": "MIT", "dependencies": { - "nice-try": "^1.0.4", - "path-key": "^2.0.1", - "semver": "^5.5.0", - "shebang-command": "^1.2.0", - "which": "^1.2.9" + "get-east-asian-width": "^1.3.0", + "strip-ansi": "^7.1.0" }, "engines": { - "node": ">=4.8" + "node": ">=20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/cross-spawn-async": { - "version": "2.2.5", - "resolved": "https://registry.npmjs.org/cross-spawn-async/-/cross-spawn-async-2.2.5.tgz", - "integrity": "sha1-hF/wwINKPe2dFg2sptOQkGuyiMw=", + "node_modules/cli-truncate/node_modules/strip-ansi": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.2.tgz", + "integrity": "sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA==", "dev": true, + "license": "MIT", "dependencies": { - "lru-cache": "^4.0.0", - "which": "^1.2.8" - } - }, - "node_modules/cross-spawn/node_modules/semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true, - "bin": { - "semver": "bin/semver" + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" } }, - "node_modules/crypto-random-string": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-2.0.0.tgz", - "integrity": "sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA==", + "node_modules/cli-width": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-4.1.0.tgz", + "integrity": "sha512-ouuZd4/dm2Sw5Gmqy6bGyNNNe1qt9RpmxveLSO7KcgsTnU7RXfsw+/bukWGo1abgBiMAic068rclZsO4IWmmxQ==", + "license": "ISC", "engines": { - "node": ">=8" + "node": ">= 12" } }, - "node_modules/currently-unhandled": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/currently-unhandled/-/currently-unhandled-0.4.1.tgz", - "integrity": "sha1-mI3zP+qxke95mmE2nddsF635V+o=", - "dev": true, + "node_modules/cliui": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-9.0.1.tgz", + "integrity": "sha512-k7ndgKhwoQveBL+/1tqGJYNz097I7WOvwbmmU2AR5+magtbjPWQTS1C5vzGkBC8Ym8UWRzfKUzUUqFLypY4Q+w==", + "license": "ISC", "dependencies": { - "array-find-index": "^1.0.1" + "string-width": "^7.2.0", + "strip-ansi": "^7.1.0", + "wrap-ansi": "^9.0.0" }, "engines": { - "node": ">=0.10.0" + "node": ">=20" } }, - "node_modules/dashdash": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", - "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", + "node_modules/cliui/node_modules/emoji-regex": { + "version": "10.6.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.6.0.tgz", + "integrity": "sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A==", + "license": "MIT" + }, + "node_modules/cliui/node_modules/string-width": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz", + "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", + "license": "MIT", "dependencies": { - "assert-plus": "^1.0.0" + "emoji-regex": "^10.3.0", + "get-east-asian-width": "^1.0.0", + "strip-ansi": "^7.1.0" }, "engines": { - "node": ">=0.10" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/de-indent": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/de-indent/-/de-indent-1.0.2.tgz", - "integrity": "sha1-sgOOhG3DO6pXlhKNCAS0VbjB4h0=", - "dev": true - }, - "node_modules/debug": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", - "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", + "node_modules/cliui/node_modules/strip-ansi": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.2.tgz", + "integrity": "sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA==", + "license": "MIT", "dependencies": { - "ms": "2.1.2" + "ansi-regex": "^6.0.1" }, "engines": { - "node": ">=6.0" + "node": ">=12" }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" } }, - "node_modules/decamelize": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", - "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", - "dev": true, + "node_modules/clone": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", + "integrity": "sha1-2jCcwmPfFZlMaIypAheco8fNfH4=", + "optional": true, "engines": { - "node": ">=0.10.0" + "node": ">=0.8" } }, - "node_modules/decompress-response": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-3.3.0.tgz", - "integrity": "sha1-gKTdMjdIOEv6JICDYirt7Jgq3/M=", + "node_modules/color": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/color/-/color-5.0.3.tgz", + "integrity": "sha512-ezmVcLR3xAVp8kYOm4GS45ZLLgIE6SPAFoduLr6hTDajwb3KZ2F46gulK3XpcwRFb5KKGCSezCBAY4Dw4HsyXA==", + "license": "MIT", "dependencies": { - "mimic-response": "^1.0.0" + "color-convert": "^3.1.3", + "color-string": "^2.1.3" }, "engines": { - "node": ">=4" + "node": ">=18" } }, - "node_modules/deep-eql": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-3.0.1.tgz", - "integrity": "sha512-+QeIQyN5ZuO+3Uk5DYh6/1eKO0m0YmJFGNmFHGACpf1ClL1nmlV/p4gNgbl2pJGxgXb4faqo6UE+M5ACEMyVcw==", + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dev": true, "dependencies": { - "type-detect": "^4.0.0" + "color-name": "~1.1.4" }, "engines": { - "node": ">=0.12" - } - }, - "node_modules/deep-extend": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", - "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", - "engines": { - "node": ">=4.0.0" + "node": ">=7.0.0" } }, - "node_modules/deep-is": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", - "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true }, - "node_modules/defaults": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.3.tgz", - "integrity": "sha1-xlYFHpgX2f8I7YgUd/P+QBnz730=", + "node_modules/color-string": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/color-string/-/color-string-2.1.4.tgz", + "integrity": "sha512-Bb6Cq8oq0IjDOe8wJmi4JeNn763Xs9cfrBcaylK1tPypWzyoy2G3l90v9k64kjphl/ZJjPIShFztenRomi8WTg==", + "license": "MIT", "dependencies": { - "clone": "^1.0.2" + "color-name": "^2.0.0" + }, + "engines": { + "node": ">=18" } }, - "node_modules/defer-to-connect": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-1.1.3.tgz", - "integrity": "sha512-0ISdNousHvZT2EiFlZeZAHBUvSxmKswVCEf8hW7KWgG4a8MVEu/3Vb6uWYozkjylyCxe0JBIiRB1jV45S70WVQ==" + "node_modules/color-string/node_modules/color-name": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-2.1.0.tgz", + "integrity": "sha512-1bPaDNFm0axzE4MEAzKPuqKWeRaT43U/hyxKPBdqTfmPF+d6n7FSoTFxLVULUJOmiLp01KjhIPPH+HrXZJN4Rg==", + "license": "MIT", + "engines": { + "node": ">=12.20" + } }, - "node_modules/define-properties": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", - "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", + "node_modules/color/node_modules/color-convert": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-3.1.3.tgz", + "integrity": "sha512-fasDH2ont2GqF5HpyO4w0+BcewlhHEZOFn9c1ckZdHpJ56Qb7MHhH/IcJZbBGgvdtwdwNbLvxiBEdg336iA9Sg==", + "license": "MIT", "dependencies": { - "object-keys": "^1.0.12" + "color-name": "^2.0.0" }, "engines": { - "node": ">= 0.4" + "node": ">=14.6" } }, - "node_modules/delayed-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", + "node_modules/color/node_modules/color-name": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-2.1.0.tgz", + "integrity": "sha512-1bPaDNFm0axzE4MEAzKPuqKWeRaT43U/hyxKPBdqTfmPF+d6n7FSoTFxLVULUJOmiLp01KjhIPPH+HrXZJN4Rg==", + "license": "MIT", "engines": { - "node": ">=0.4.0" + "node": ">=12.20" } }, - "node_modules/depcheck": { - "version": "0.8.3", - "resolved": "https://registry.npmjs.org/depcheck/-/depcheck-0.8.3.tgz", - "integrity": "sha512-xcLTnaovCFFTts5Ge7mUUhMGHSu6eRfftvVvOjN7gXO5EFUhJfX6UQa1b08a0SIwKfzG9eKNn5mzZlXp0mZARA==", + "node_modules/colorette": { + "version": "2.0.20", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", + "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==", "dev": true, + "license": "MIT" + }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "license": "MIT", "dependencies": { - "@babel/parser": "^7.3.1", - "@babel/traverse": "^7.2.3", - "builtin-modules": "^3.0.0", - "deprecate": "^1.0.0", - "deps-regex": "^0.1.4", - "js-yaml": "^3.4.2", - "lodash": "^4.17.11", - "minimatch": "^3.0.2", - "node-sass-tilde-importer": "^1.0.2", - "please-upgrade-node": "^3.1.1", - "require-package-name": "^2.0.1", - "resolve": "^1.10.0", - "vue-template-compiler": "^2.6.10", - "walkdir": "^0.3.2", - "yargs": "^13.2.2" - }, - "bin": { - "depcheck": "bin/depcheck.js" + "delayed-stream": "~1.0.0" }, "engines": { - "node": ">=6" - } - }, - "node_modules/depcheck/node_modules/yargs": { - "version": "13.3.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.2.tgz", - "integrity": "sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw==", - "dev": true, - "dependencies": { - "cliui": "^5.0.0", - "find-up": "^3.0.0", - "get-caller-file": "^2.0.1", - "require-directory": "^2.1.1", - "require-main-filename": "^2.0.0", - "set-blocking": "^2.0.0", - "string-width": "^3.0.0", - "which-module": "^2.0.0", - "y18n": "^4.0.0", - "yargs-parser": "^13.1.2" + "node": ">= 0.8" } }, - "node_modules/deprecate": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/deprecate/-/deprecate-1.1.1.tgz", - "integrity": "sha512-ZGDXefq1xknT292LnorMY5s8UVU08/WKdzDZCUT6t9JzsiMSP4uzUhgpqugffNVcT5WC6wMBiSQ+LFjlv3v7iQ==", - "dev": true - }, - "node_modules/deps-regex": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/deps-regex/-/deps-regex-0.1.4.tgz", - "integrity": "sha1-UYZnt2kUYKXn4KNBvnbrfOgJAYQ=", - "dev": true + "node_modules/command-exists": { + "version": "1.2.9", + "resolved": "https://registry.npmjs.org/command-exists/-/command-exists-1.2.9.tgz", + "integrity": "sha512-LTQ/SGc+s0Xc0Fu5WaKnR0YiygZkm9eKFvyS+fRsU7/ZWFF8ykFM6Pc9aCVf1+xasOOZpO3BAVgVrKvsqKHV7w==" }, - "node_modules/diff": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-5.0.0.tgz", - "integrity": "sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==", + "node_modules/commander": { + "version": "14.0.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-14.0.3.tgz", + "integrity": "sha512-H+y0Jo/T1RZ9qPP4Eh1pkcQcLRglraJaSLoyOtHxu6AapkjWVCy2Sit1QQ4x3Dng8qDlSsZEet7g5Pq06MvTgw==", "dev": true, + "license": "MIT", "engines": { - "node": ">=0.3.1" + "node": ">=20" } }, - "node_modules/dmd": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/dmd/-/dmd-6.0.0.tgz", - "integrity": "sha512-PwWZlqZnJPETwqZZ70haRa+UDZcD5jeBD3ywW1Kf+jYYv0MHu/S7Ri9jsSoeTMwkcMVW9hXOMA1IZUMEufBhOg==", + "node_modules/comment-parser": { + "version": "1.4.5", + "resolved": "https://registry.npmjs.org/comment-parser/-/comment-parser-1.4.5.tgz", + "integrity": "sha512-aRDkn3uyIlCFfk5NUA+VdwMmMsh8JGhc4hapfV4yxymHGQ3BVskMQfoXGpCo5IoBuQ9tS5iiVKhCpTcB4pW4qw==", "dev": true, - "dependencies": { - "array-back": "^5.0.0", - "cache-point": "^2.0.0", - "common-sequence": "^2.0.0", - "file-set": "^4.0.1", - "handlebars": "^4.7.7", - "marked": "^2.0.0", - "object-get": "^2.1.1", - "reduce-flatten": "^3.0.0", - "reduce-unique": "^2.0.1", - "reduce-without": "^1.0.1", - "test-value": "^3.0.0", - "walk-back": "^5.0.0" - }, + "license": "MIT", "engines": { - "node": ">=14" + "node": ">= 12.0.0" } }, - "node_modules/dmd/node_modules/array-back": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/array-back/-/array-back-5.0.0.tgz", - "integrity": "sha512-kgVWwJReZWmVuWOQKEOohXKJX+nD02JAZ54D1RRWlv8L0NebauKAaFxACKzB74RTclt1+WNz5KHaLRDAPZbDEw==", + "node_modules/common-tags": { + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/common-tags/-/common-tags-1.8.2.tgz", + "integrity": "sha512-gk/Z852D2Wtb//0I+kRFNKKE9dIIVirjoqPoA1wJU+XePVXZfGeBpk45+A1rKO4Q43prqWBNY/MiIeRLbPWUaA==", "dev": true, "engines": { - "node": ">=10" + "node": ">=4.0.0" } }, - "node_modules/dmd/node_modules/reduce-flatten": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/reduce-flatten/-/reduce-flatten-3.0.0.tgz", - "integrity": "sha512-eczl8wAYBxJ6Egl6I1ECIF+8z6sHu+KE7BzaEDZTpPXKXfy9SUDQlVYwkRcNTjJLC3Iakxbhss50KuT/R6SYfg==", - "dev": true, - "engines": { - "node": ">=8" - } + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "dev": true }, - "node_modules/doctrine": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", - "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", - "dev": true, + "node_modules/conf": { + "version": "15.1.0", + "resolved": "https://registry.npmjs.org/conf/-/conf-15.1.0.tgz", + "integrity": "sha512-Uy5YN9KEu0WWDaZAVJ5FAmZoaJt9rdK6kH+utItPyGsCqCgaTKkrmZx3zoE0/3q6S3bcp3Ihkk+ZqPxWxFK5og==", + "license": "MIT", "dependencies": { - "esutils": "^2.0.2" + "ajv": "^8.17.1", + "ajv-formats": "^3.0.1", + "atomically": "^2.0.3", + "debounce-fn": "^6.0.0", + "dot-prop": "^10.0.0", + "env-paths": "^3.0.0", + "json-schema-typed": "^8.0.1", + "semver": "^7.7.2", + "uint8array-extras": "^1.5.0" }, "engines": { - "node": ">=6.0.0" + "node": ">=20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/dot-prop": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-5.3.0.tgz", - "integrity": "sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q==", + "node_modules/conf/node_modules/dot-prop": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-10.1.0.tgz", + "integrity": "sha512-MVUtAugQMOff5RnBy2d9N31iG0lNwg1qAoAOn7pOK5wf94WIaE3My2p3uwTQuvS2AcqchkcR3bHByjaM0mmi7Q==", + "license": "MIT", "dependencies": { - "is-obj": "^2.0.0" + "type-fest": "^5.0.0" }, "engines": { - "node": ">=8" + "node": ">=20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/duplexer3": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.4.tgz", - "integrity": "sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI=" - }, - "node_modules/easy-table": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/easy-table/-/easy-table-1.1.0.tgz", - "integrity": "sha1-hvmrTBAvA3G3KXuSplHVgkvIy3M=", - "optionalDependencies": { - "wcwidth": ">=1.0.1" + "node_modules/conf/node_modules/type-fest": { + "version": "5.4.4", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-5.4.4.tgz", + "integrity": "sha512-JnTrzGu+zPV3aXIUhnyWJj4z/wigMsdYajGLIYakqyOW1nPllzXEJee0QQbHj+CTIQtXGlAjuK0UY+2xTyjVAw==", + "license": "(MIT OR CC0-1.0)", + "dependencies": { + "tagged-tag": "^1.0.0" + }, + "engines": { + "node": ">=20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/ecc-jsbn": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", - "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=", + "node_modules/config-chain": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/config-chain/-/config-chain-1.1.13.tgz", + "integrity": "sha512-qj+f8APARXHrM0hraqXYb2/bOVSV4PvJQlNZ/DVj0QrmNM2q2euizkeuVckQ57J+W0mRH6Hvi+k50M4Jul2VRQ==", "dependencies": { - "jsbn": "~0.1.0", - "safer-buffer": "^2.1.0" + "ini": "^1.3.4", + "proto-list": "~1.2.1" } }, - "node_modules/emoji-regex": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", - "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", - "dev": true - }, - "node_modules/enabled": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/enabled/-/enabled-2.0.0.tgz", - "integrity": "sha512-AKrN98kuwOzMIdAizXGI86UFBoo26CL21UM763y1h/GMSJ4/OHU9k2YlsmBpyScFo/wbLzWQJBMCW4+IO3/+OQ==" + "node_modules/config-chain/node_modules/ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==" }, - "node_modules/end-of-stream": { - "version": "1.4.4", - "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", - "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "node_modules/configstore": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/configstore/-/configstore-7.0.0.tgz", + "integrity": "sha512-yk7/5PN5im4qwz0WFZW3PXnzHgPu9mX29Y8uZ3aefe2lBPC1FYttWZRcaW9fKkT0pBCJyuQ2HfbmPVaODi9jcQ==", "dependencies": { - "once": "^1.4.0" + "atomically": "^2.0.3", + "dot-prop": "^9.0.0", + "graceful-fs": "^4.2.11", + "xdg-basedir": "^5.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/yeoman/configstore?sponsor=1" } }, - "node_modules/enquirer": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz", - "integrity": "sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==", - "dev": true, + "node_modules/console.table": { + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/console.table/-/console.table-0.10.0.tgz", + "integrity": "sha1-CRcCVYiHW+/XDPLv9L7yxuLXXQQ=", "dependencies": { - "ansi-colors": "^4.1.1" + "easy-table": "1.1.0" }, "engines": { - "node": ">=8.6" + "node": "> 0.10" } }, - "node_modules/entities": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/entities/-/entities-2.0.3.tgz", - "integrity": "sha512-MyoZ0jgnLvB2X3Lg5HqpFmn1kybDiIfEQmKzTb5apr51Rb+T3KdmMiqa70T+bhGnyv7bQ6WMj2QMHpGMmlrUYQ==", + "node_modules/convert-source-map": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz", + "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==", "dev": true }, - "node_modules/error-ex": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", - "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "node_modules/core-js-compat": { + "version": "3.48.0", + "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.48.0.tgz", + "integrity": "sha512-OM4cAF3D6VtH/WkLtWvyNC56EZVXsZdU3iqaMG2B4WvYrlqU831pc4UtG5yp0sE9z8Y02wVN7PjW5Zf9Gt0f1Q==", "dev": true, + "license": "MIT", "dependencies": { - "is-arrayish": "^0.2.1" + "browserslist": "^4.28.1" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/core-js" } }, - "node_modules/error-ex/node_modules/is-arrayish": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", - "dev": true - }, - "node_modules/error-stack-parser": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/error-stack-parser/-/error-stack-parser-1.3.6.tgz", - "integrity": "sha1-4Oc7k+QXE40c18C3RrGkoUhUwpI=", + "node_modules/cross-spawn": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", "dev": true, "dependencies": { - "stackframe": "^0.3.1" + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" } }, - "node_modules/es-abstract": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.15.0.tgz", - "integrity": "sha512-bhkEqWJ2t2lMeaJDuk7okMkJWI/yqgH/EoGwpcvv0XW9RWQsRspI4wt6xuyuvMvvQE3gg/D9HXppgk21w78GyQ==", + "node_modules/debounce-fn": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/debounce-fn/-/debounce-fn-6.0.0.tgz", + "integrity": "sha512-rBMW+F2TXryBwB54Q0d8drNEI+TfoS9JpNTAoVpukbWEhjXQq4rySFYLaqXMFXwdv61Zb2OHtj5bviSoimqxRQ==", "dependencies": { - "es-to-primitive": "^1.2.0", - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.0", - "is-callable": "^1.1.4", - "is-regex": "^1.0.4", - "object-inspect": "^1.6.0", - "object-keys": "^1.1.1", - "string.prototype.trimleft": "^2.1.0", - "string.prototype.trimright": "^2.1.0" + "mimic-function": "^5.0.0" }, "engines": { - "node": ">= 0.4" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/es-to-primitive": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.0.tgz", - "integrity": "sha512-qZryBOJjV//LaxLTV6UC//WewneB3LcXOL9NP++ozKVXsIIIpm/2c13UDiD9Jp2eThsecw9m3jPqDwTyobcdbg==", + "node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "license": "MIT", "dependencies": { - "is-callable": "^1.1.4", - "is-date-object": "^1.0.1", - "is-symbol": "^1.0.2" + "ms": "^2.1.3" }, "engines": { - "node": ">= 0.4" + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } } }, - "node_modules/escalade": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", - "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "node_modules/deep-equal": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-2.2.3.tgz", + "integrity": "sha512-ZIwpnevOurS8bpT4192sqAowWM76JDKSHYzMLty3BZGSswgq6pBaH3DhCSW5xVAZICZyKdOBPjwww5wfgT/6PA==", + "dependencies": { + "array-buffer-byte-length": "^1.0.0", + "call-bind": "^1.0.5", + "es-get-iterator": "^1.1.3", + "get-intrinsic": "^1.2.2", + "is-arguments": "^1.1.1", + "is-array-buffer": "^3.0.2", + "is-date-object": "^1.0.5", + "is-regex": "^1.1.4", + "is-shared-array-buffer": "^1.0.2", + "isarray": "^2.0.5", + "object-is": "^1.1.5", + "object-keys": "^1.1.1", + "object.assign": "^4.1.4", + "regexp.prototype.flags": "^1.5.1", + "side-channel": "^1.0.4", + "which-boxed-primitive": "^1.0.2", + "which-collection": "^1.0.1", + "which-typed-array": "^1.1.13" + }, "engines": { - "node": ">=6" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/escape-goat": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/escape-goat/-/escape-goat-2.1.1.tgz", - "integrity": "sha512-8/uIhbG12Csjy2JEW7D9pHbreaVaS/OpN3ycnyvElTdwM5n6GY6W6e2IPemfvGZeUMqZ9A/3GqIZMgKnBhAw/Q==", + "node_modules/deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", "engines": { - "node": ">=8" + "node": ">=4.0.0" } }, - "node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", - "engines": { - "node": ">=0.8.0" - } + "node_modules/deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true }, - "node_modules/eslint": { - "version": "8.4.1", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.4.1.tgz", - "integrity": "sha512-TxU/p7LB1KxQ6+7aztTnO7K0i+h0tDi81YRY9VzB6Id71kNz+fFYnf5HD5UOQmxkzcoa0TlVZf9dpMtUv0GpWg==", - "dev": true, + "node_modules/defaults": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.3.tgz", + "integrity": "sha1-xlYFHpgX2f8I7YgUd/P+QBnz730=", + "optional": true, "dependencies": { - "@eslint/eslintrc": "^1.0.5", - "@humanwhocodes/config-array": "^0.9.2", - "ajv": "^6.10.0", - "chalk": "^4.0.0", - "cross-spawn": "^7.0.2", - "debug": "^4.3.2", - "doctrine": "^3.0.0", - "enquirer": "^2.3.5", - "escape-string-regexp": "^4.0.0", - "eslint-scope": "^7.1.0", - "eslint-utils": "^3.0.0", - "eslint-visitor-keys": "^3.1.0", - "espree": "^9.2.0", - "esquery": "^1.4.0", - "esutils": "^2.0.2", - "fast-deep-equal": "^3.1.3", - "file-entry-cache": "^6.0.1", - "functional-red-black-tree": "^1.0.1", - "glob-parent": "^6.0.1", - "globals": "^13.6.0", - "ignore": "^4.0.6", - "import-fresh": "^3.0.0", - "imurmurhash": "^0.1.4", - "is-glob": "^4.0.0", - "js-yaml": "^4.1.0", - "json-stable-stringify-without-jsonify": "^1.0.1", - "levn": "^0.4.1", - "lodash.merge": "^4.6.2", - "minimatch": "^3.0.4", - "natural-compare": "^1.4.0", - "optionator": "^0.9.1", - "progress": "^2.0.0", - "regexpp": "^3.2.0", - "semver": "^7.2.1", - "strip-ansi": "^6.0.1", - "strip-json-comments": "^3.1.0", - "text-table": "^0.2.0", - "v8-compile-cache": "^2.0.3" + "clone": "^1.0.2" + } + }, + "node_modules/define-data-property": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.1.tgz", + "integrity": "sha512-E7uGkTzkk1d0ByLeSc6ZsFS79Axg+m1P/VsgYsxHgiuc3tFSj+MjMIwe90FC4lOAZzNBdY7kkO2P2wKdsQ1vgQ==", + "dependencies": { + "get-intrinsic": "^1.2.1", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.0" }, - "bin": { - "eslint": "bin/eslint.js" + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/define-properties": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.0.tgz", + "integrity": "sha512-xvqAVKGfT1+UAvPwKTVw/njhdQ8ZhXK4lI0bCIuCMrp2up9nPnaDftrLtmpTazqd1o+UY4zgzU+avtMbDP+ldA==", + "dependencies": { + "has-property-descriptors": "^1.0.0", + "object-keys": "^1.1.1" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": ">= 0.4" }, "funding": { - "url": "https://opencollective.com/eslint" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/eslint-config-prettier": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-8.3.0.tgz", - "integrity": "sha512-BgZuLUSeKzvlL/VUjx/Yb787VQ26RU3gGjA3iiFvdsp/2bMfVIWUVP7tjxtjS0e+HP409cPlPvNkQloz8C91ew==", - "dev": true, - "bin": { - "eslint-config-prettier": "bin/cli.js" - }, - "peerDependencies": { - "eslint": ">=7.0.0" + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "license": "MIT", + "engines": { + "node": ">=0.4.0" } }, - "node_modules/eslint-config-ssjs": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/eslint-config-ssjs/-/eslint-config-ssjs-1.1.11.tgz", - "integrity": "sha512-8C7J0TgjkwQM4j7vra9/SuqjhZa+rq6CrPzwPnPRqcrVclfOFqI6uoo3LXMnxCI/ovOoOy0KqmD++uzIXsmr5g==", + "node_modules/diff": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-7.0.0.tgz", + "integrity": "sha512-PJWHUb1RFevKCwaFA9RlG5tCd+FO5iRh9A8HEtkmBH2Li03iJriB6m6JIN4rGz3K3JLawI7/veA1xzRKP6ISBw==", "dev": true, + "license": "BSD-3-Clause", "engines": { - "node": "^6.14.0 || ^8.10.0 || >=9.10.0" + "node": ">=0.3.1" } }, - "node_modules/eslint-plugin-mocha": { - "version": "10.0.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-mocha/-/eslint-plugin-mocha-10.0.1.tgz", - "integrity": "sha512-XSsqkSE0ViKLjYWO5Z9AcNvPBupTXDlI60TEUsJMNYQFUKZmDzO0Gh3OsSmZ2j5iYl0qT8muJzxTKRwVC6M0wA==", + "node_modules/dir-glob": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", "dev": true, "dependencies": { - "eslint-utils": "^3.0.0", - "ramda": "^0.27.1" + "path-type": "^4.0.0" }, "engines": { - "node": ">=14.0.0" - }, - "peerDependencies": { - "eslint": ">=7.0.0" + "node": ">=8" } }, - "node_modules/eslint-plugin-prettier": { + "node_modules/dir-glob/node_modules/path-type": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-4.0.0.tgz", - "integrity": "sha512-98MqmCJ7vJodoQK359bqQWaxOE0CS8paAz/GgjaZLyex4TTk3g9HugoO89EqWCrFiOqn9EVvcoo7gZzONCWVwQ==", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", "dev": true, - "dependencies": { - "prettier-linter-helpers": "^1.0.0" - }, "engines": { - "node": ">=6.0.0" - }, - "peerDependencies": { - "eslint": ">=7.28.0", - "prettier": ">=2.0.0" - }, - "peerDependenciesMeta": { - "eslint-config-prettier": { - "optional": true - } + "node": ">=8" } }, - "node_modules/eslint-scope": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.1.0.tgz", - "integrity": "sha512-aWwkhnS0qAXqNOgKOK0dJ2nvzEbhEvpy8OlJ9kZ0FeZnA6zpjv1/Vei+puGFFX7zkPCkHHXb7IDX3A+7yPrRWg==", + "node_modules/discontinuous-range": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/discontinuous-range/-/discontinuous-range-1.0.0.tgz", + "integrity": "sha512-c68LpLbO+7kP/b1Hr1qs8/BJ09F5khZGTxqxZuhzxpmwJKOgRFHJWIb9/KmqnqHhLdO55aOxFH/EGBvUQbL/RQ==", + "license": "MIT" + }, + "node_modules/dlv": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz", + "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==", + "dev": true + }, + "node_modules/doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", "dev": true, "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^5.2.0" + "esutils": "^2.0.2" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": ">=6.0.0" } }, - "node_modules/eslint-utils": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz", - "integrity": "sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==", - "dev": true, + "node_modules/dot-prop": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-9.0.0.tgz", + "integrity": "sha512-1gxPBJpI/pcjQhKgIU91II6Wkay+dLcN3M6rf2uwP8hRur3HtQXjVrdAK3sjC0piaEuxzMwjXChcETiJl47lAQ==", "dependencies": { - "eslint-visitor-keys": "^2.0.0" + "type-fest": "^4.18.2" }, "engines": { - "node": "^10.0.0 || ^12.0.0 || >= 14.0.0" + "node": ">=18" }, "funding": { - "url": "https://github.com/sponsors/mysticatea" + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/dot-prop/node_modules/type-fest": { + "version": "4.20.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.20.1.tgz", + "integrity": "sha512-R6wDsVsoS9xYOpy8vgeBlqpdOyzJ12HNfQhC/aAKWM3YoCV9TtunJzh/QpkMgeDhkoynDcw5f1y+qF9yc/HHyg==", + "engines": { + "node": ">=16" }, - "peerDependencies": { - "eslint": ">=5" + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/eslint-utils/node_modules/eslint-visitor-keys": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", - "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", - "dev": true, + "node_modules/dunder-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + }, "engines": { - "node": ">=10" + "node": ">= 0.4" } }, - "node_modules/eslint-visitor-keys": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.1.0.tgz", - "integrity": "sha512-yWJFpu4DtjsWKkt5GeNBBuZMlNcYVs6vRCLoCVEJrTjaSB6LC98gFipNK/erM2Heg/E8mIK+hXG/pJMLK+eRZA==", + "node_modules/eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", + "dev": true + }, + "node_modules/easy-table": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/easy-table/-/easy-table-1.1.0.tgz", + "integrity": "sha1-hvmrTBAvA3G3KXuSplHVgkvIy3M=", + "optionalDependencies": { + "wcwidth": ">=1.0.1" + } + }, + "node_modules/electron-to-chromium": { + "version": "1.5.302", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.302.tgz", + "integrity": "sha512-sM6HAN2LyK82IyPBpznDRqlTQAtuSaO+ShzFiWTvoMJLHyZ+Y39r8VMfHzwbU8MVBzQ4Wdn85+wlZl2TLGIlwg==", "dev": true, + "license": "ISC" + }, + "node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + }, + "node_modules/enabled": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/enabled/-/enabled-2.0.0.tgz", + "integrity": "sha512-AKrN98kuwOzMIdAizXGI86UFBoo26CL21UM763y1h/GMSJ4/OHU9k2YlsmBpyScFo/wbLzWQJBMCW4+IO3/+OQ==", + "license": "MIT" + }, + "node_modules/env-paths": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-3.0.0.tgz", + "integrity": "sha512-dtJUTepzMW3Lm/NPxRf3wP4642UWhjL2sQxc+ym2YMj1m/H2zDNQOlezafzkHwn6sMstjHTwG6iQQsctDW/b1A==", "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/eslint/node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "node_modules/environment": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/environment/-/environment-1.1.0.tgz", + "integrity": "sha512-xUtoPkMggbz0MPyPiIWr1Kp4aeWJjDZ6SMvURhimjdZgsRuDplF5/s9hcgGhyXMhs+6vpnuoiZ2kFiu3FMnS8Q==", "dev": true, + "license": "MIT", "engines": { - "node": ">=8" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/eslint/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "node_modules/error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", "dev": true, "dependencies": { - "color-convert": "^2.0.1" + "is-arrayish": "^0.2.1" + } + }, + "node_modules/es-abstract": { + "version": "1.19.5", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.19.5.tgz", + "integrity": "sha512-Aa2G2+Rd3b6kxEUKTF4TaW67czBLyAv3z7VOhYRU50YBx+bbsYZ9xQP4lMNazePuFlybXI0V4MruPos7qUo5fA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "es-to-primitive": "^1.2.1", + "function-bind": "^1.1.1", + "get-intrinsic": "^1.1.1", + "get-symbol-description": "^1.0.0", + "has": "^1.0.3", + "has-symbols": "^1.0.3", + "internal-slot": "^1.0.3", + "is-callable": "^1.2.4", + "is-negative-zero": "^2.0.2", + "is-regex": "^1.1.4", + "is-shared-array-buffer": "^1.0.2", + "is-string": "^1.0.7", + "is-weakref": "^1.0.2", + "object-inspect": "^1.12.0", + "object-keys": "^1.1.1", + "object.assign": "^4.1.2", + "string.prototype.trimend": "^1.0.4", + "string.prototype.trimstart": "^1.0.4", + "unbox-primitive": "^1.0.1" }, "engines": { - "node": ">=8" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/eslint/node_modules/argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true + "node_modules/es-define-property": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } }, - "node_modules/eslint/node_modules/chalk": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", - "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", - "dev": true, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-get-iterator": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/es-get-iterator/-/es-get-iterator-1.1.3.tgz", + "integrity": "sha512-sPZmqHBe6JIiTfN5q2pEi//TwxmAFHwj/XEuYjTuse78i8KxaqMTTzxPoFKuzRpDpTJ+0NAbpfenkmH2rePtuw==", + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.3", + "has-symbols": "^1.0.3", + "is-arguments": "^1.1.1", + "is-map": "^2.0.2", + "is-set": "^2.0.2", + "is-string": "^1.0.7", + "isarray": "^2.0.5", + "stop-iteration-iterator": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/es-object-atoms": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", + "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", + "license": "MIT", "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" + "es-errors": "^1.3.0" }, "engines": { - "node": ">=10" + "node": ">= 0.4" } }, - "node_modules/eslint/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, + "node_modules/es-set-tostringtag": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", + "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", + "license": "MIT", "dependencies": { - "color-name": "~1.1.4" + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" }, "engines": { - "node": ">=7.0.0" + "node": ">= 0.4" } }, - "node_modules/eslint/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/eslint/node_modules/cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "node_modules/es-to-primitive": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", + "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", "dev": true, "dependencies": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" }, "engines": { - "node": ">= 8" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-goat": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-goat/-/escape-goat-4.0.0.tgz", + "integrity": "sha512-2Sd4ShcWxbx6OY1IHyla/CVNwvg7XwZVoXZHcSu9w9SReNP1EzzD5T8NWKIR38fIqEns9kDWKUQTXXAmlDrdPg==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/eslint/node_modules/escape-string-regexp": { + "node_modules/escape-string-regexp": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", @@ -2317,149 +2774,446 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/eslint/node_modules/glob-parent": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", - "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "node_modules/eslint": { + "version": "10.0.3", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-10.0.3.tgz", + "integrity": "sha512-COV33RzXZkqhG9P2rZCFl9ZmJ7WL+gQSCRzE7RhkbclbQPtLAWReL7ysA0Sh4c8Im2U9ynybdR56PV0XcKvqaQ==", "dev": true, + "license": "MIT", "dependencies": { - "is-glob": "^4.0.3" + "@eslint-community/eslint-utils": "^4.8.0", + "@eslint-community/regexpp": "^4.12.2", + "@eslint/config-array": "^0.23.3", + "@eslint/config-helpers": "^0.5.2", + "@eslint/core": "^1.1.1", + "@eslint/plugin-kit": "^0.6.1", + "@humanfs/node": "^0.16.6", + "@humanwhocodes/module-importer": "^1.0.1", + "@humanwhocodes/retry": "^0.4.2", + "@types/estree": "^1.0.6", + "ajv": "^6.14.0", + "cross-spawn": "^7.0.6", + "debug": "^4.3.2", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^9.1.2", + "eslint-visitor-keys": "^5.0.1", + "espree": "^11.1.1", + "esquery": "^1.7.0", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^8.0.0", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "ignore": "^5.2.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "minimatch": "^10.2.4", + "natural-compare": "^1.4.0", + "optionator": "^0.9.3" + }, + "bin": { + "eslint": "bin/eslint.js" }, "engines": { - "node": ">=10.13.0" + "node": "^20.19.0 || ^22.13.0 || >=24" + }, + "funding": { + "url": "https://eslint.org/donate" + }, + "peerDependencies": { + "jiti": "*" + }, + "peerDependenciesMeta": { + "jiti": { + "optional": true + } } }, - "node_modules/eslint/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "node_modules/eslint-config-prettier": { + "version": "10.1.8", + "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-10.1.8.tgz", + "integrity": "sha512-82GZUjRS0p/jganf6q1rEO25VSoHH0hKPCTrgillPjdI/3bgBhAE1QzHrHTizjpRvy6pGAvKjDJtk2pF9NDq8w==", + "dev": true, + "license": "MIT", + "peer": true, + "bin": { + "eslint-config-prettier": "bin/cli.js" + }, + "funding": { + "url": "https://opencollective.com/eslint-config-prettier" + }, + "peerDependencies": { + "eslint": ">=7.0.0" + } + }, + "node_modules/eslint-config-ssjs": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/eslint-config-ssjs/-/eslint-config-ssjs-2.0.0.tgz", + "integrity": "sha512-AeJwOzxN+32mS/NNC2RnlJ8/fQUyzljNXhbDTQneE7HE8QhDrKnfVpTp4uin9vM3c/cHCeRgALu7mF+37vZjlQ==", "dev": true, "engines": { - "node": ">=8" + "node": "^6.14.0 || ^8.10.0 || >=9.10.0" + }, + "peerDependencies": { + "eslint": ">=8.56.0", + "eslint-config-prettier": ">=6.11.0", + "eslint-plugin-prettier": ">=3.1.3", + "prettier": ">=3.0.0" } }, - "node_modules/eslint/node_modules/js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "node_modules/eslint-plugin-jsdoc": { + "version": "62.7.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-62.7.1.tgz", + "integrity": "sha512-4Zvx99Q7d1uggYBUX/AIjvoyqXhluGbbKrRmG8SQTLprPFg6fa293tVJH1o1GQwNe3lUydd8ZHzn37OaSncgSQ==", "dev": true, + "license": "BSD-3-Clause", "dependencies": { - "argparse": "^2.0.1" + "@es-joy/jsdoccomment": "~0.84.0", + "@es-joy/resolve.exports": "1.2.0", + "are-docs-informative": "^0.0.2", + "comment-parser": "1.4.5", + "debug": "^4.4.3", + "escape-string-regexp": "^4.0.0", + "espree": "^11.1.0", + "esquery": "^1.7.0", + "html-entities": "^2.6.0", + "object-deep-merge": "^2.0.0", + "parse-imports-exports": "^0.2.4", + "semver": "^7.7.4", + "spdx-expression-parse": "^4.0.0", + "to-valid-identifier": "^1.0.0" }, - "bin": { - "js-yaml": "bin/js-yaml.js" + "engines": { + "node": "^20.19.0 || ^22.13.0 || >=24" + }, + "peerDependencies": { + "eslint": "^7.0.0 || ^8.0.0 || ^9.0.0 || ^10.0.0" } }, - "node_modules/eslint/node_modules/path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "node_modules/eslint-plugin-jsdoc/node_modules/eslint-visitor-keys": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-5.0.0.tgz", + "integrity": "sha512-A0XeIi7CXU7nPlfHS9loMYEKxUaONu/hTEzHTGba9Huu94Cq1hPivf+DE5erJozZOky0LfvXAyrV/tcswpLI0Q==", "dev": true, + "license": "Apache-2.0", "engines": { - "node": ">=8" + "node": "^20.19.0 || ^22.13.0 || >=24" + }, + "funding": { + "url": "https://opencollective.com/eslint" } }, - "node_modules/eslint/node_modules/shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "node_modules/eslint-plugin-jsdoc/node_modules/espree": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-11.1.0.tgz", + "integrity": "sha512-WFWYhO1fV4iYkqOOvq8FbqIhr2pYfoDY0kCotMkDeNtGpiGGkZ1iov2u8ydjtgM8yF8rzK7oaTbw2NAzbAbehw==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { - "shebang-regex": "^3.0.0" + "acorn": "^8.15.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^5.0.0" }, "engines": { - "node": ">=8" + "node": "^20.19.0 || ^22.13.0 || >=24" + }, + "funding": { + "url": "https://opencollective.com/eslint" } }, - "node_modules/eslint/node_modules/shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "node_modules/eslint-plugin-jsdoc/node_modules/spdx-expression-parse": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-4.0.0.tgz", + "integrity": "sha512-Clya5JIij/7C6bRR22+tnGXbc4VKlibKSVj2iHvVeX5iMW7s1SIQlqu699JkODJJIhh/pUu8L0/VLh8xflD+LQ==", + "dev": true, + "dependencies": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "node_modules/eslint-plugin-mocha": { + "version": "11.2.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-mocha/-/eslint-plugin-mocha-11.2.0.tgz", + "integrity": "sha512-nMdy3tEXZac8AH5Z/9hwUkSfWu8xHf4XqwB5UEQzyTQGKcNlgFeciRAjLjliIKC3dR1Ex/a2/5sqgQzvYRkkkA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.4.1", + "globals": "^15.14.0" + }, + "peerDependencies": { + "eslint": ">=9.0.0" + } + }, + "node_modules/eslint-plugin-mocha/node_modules/globals": { + "version": "15.15.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-15.15.0.tgz", + "integrity": "sha512-7ACyT3wmyp3I61S4fG682L0VA2RGD9otkqGJIwNUMF1SWUombIIk+af1unuDYgMm082aHYwD+mzJvv9Iu8dsgg==", "dev": true, + "license": "MIT", "engines": { - "node": ">=8" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/eslint/node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "node_modules/eslint-plugin-prettier": { + "version": "5.5.5", + "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.5.5.tgz", + "integrity": "sha512-hscXkbqUZ2sPithAuLm5MXL+Wph+U7wHngPBv9OMWwlP8iaflyxpjTYZkmdgB4/vPIhemRlBEoLrH7UC1n7aUw==", "dev": true, + "license": "MIT", "dependencies": { - "ansi-regex": "^5.0.1" + "prettier-linter-helpers": "^1.0.1", + "synckit": "^0.11.12" }, "engines": { - "node": ">=8" + "node": "^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint-plugin-prettier" + }, + "peerDependencies": { + "@types/eslint": ">=8.0.0", + "eslint": ">=8.0.0", + "eslint-config-prettier": ">= 7.0.0 <10.0.0 || >=10.1.0", + "prettier": ">=3.0.0" + }, + "peerDependenciesMeta": { + "@types/eslint": { + "optional": true + }, + "eslint-config-prettier": { + "optional": true + } } }, - "node_modules/eslint/node_modules/strip-json-comments": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "node_modules/eslint-plugin-unicorn": { + "version": "63.0.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-unicorn/-/eslint-plugin-unicorn-63.0.0.tgz", + "integrity": "sha512-Iqecl9118uQEXYh7adylgEmGfkn5es3/mlQTLLkd4pXkIk9CTGrAbeUux+YljSa2ohXCBmQQ0+Ej1kZaFgcfkA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-validator-identifier": "^7.28.5", + "@eslint-community/eslint-utils": "^4.9.0", + "change-case": "^5.4.4", + "ci-info": "^4.3.1", + "clean-regexp": "^1.0.0", + "core-js-compat": "^3.46.0", + "find-up-simple": "^1.0.1", + "globals": "^16.4.0", + "indent-string": "^5.0.0", + "is-builtin-module": "^5.0.0", + "jsesc": "^3.1.0", + "pluralize": "^8.0.0", + "regexp-tree": "^0.1.27", + "regjsparser": "^0.13.0", + "semver": "^7.7.3", + "strip-indent": "^4.1.1" + }, + "engines": { + "node": "^20.10.0 || >=21.0.0" + }, + "funding": { + "url": "https://github.com/sindresorhus/eslint-plugin-unicorn?sponsor=1" + }, + "peerDependencies": { + "eslint": ">=9.38.0" + } + }, + "node_modules/eslint-plugin-unicorn/node_modules/globals": { + "version": "16.5.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-16.5.0.tgz", + "integrity": "sha512-c/c15i26VrJ4IRt5Z89DnIzCGDn9EcebibhAOjw5ibqEHsE1wLUgkPn9RDmNcUKyU87GeaL633nyJ+pplFR2ZQ==", "dev": true, + "license": "MIT", "engines": { - "node": ">=8" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/eslint/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "node_modules/eslint-plugin-unicorn/node_modules/indent-string": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-5.0.0.tgz", + "integrity": "sha512-m6FAo/spmsW2Ab2fU35JTYwtOKa2yAwXSwgjSv1TJzh4Mh7mC3lzAOVLBprb72XsTrgkEIsl7YrFNAiDiRhIGg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint-scope": { + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", + "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", "dev": true, "dependencies": { - "has-flag": "^4.0.0" + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" }, "engines": { - "node": ">=8" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" } }, - "node_modules/eslint/node_modules/which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint/node_modules/ajv": { + "version": "6.14.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.14.0.tgz", + "integrity": "sha512-IWrosm/yrn43eiKqkfkHis7QioDleaXQHdDVPKg0FSwwd/DuvyX79TZnFOnYpB7dcsFAMmtFztZuXPDvSePkFw==", "dev": true, + "license": "MIT", "dependencies": { - "isexe": "^2.0.0" + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" }, - "bin": { - "node-which": "bin/node-which" + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/eslint/node_modules/balanced-match": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.3.tgz", + "integrity": "sha512-1pHv8LX9CpKut1Zp4EXey7Z8OfH11ONNH6Dhi2WDUt31VVZFXZzKwXcysBgqSumFCmR+0dqjMK5v5JiFHzi0+g==", + "dev": true, + "license": "MIT", + "engines": { + "node": "20 || >=22" + } + }, + "node_modules/eslint/node_modules/brace-expansion": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.2.tgz", + "integrity": "sha512-Pdk8c9poy+YhOgVWw1JNN22/HcivgKWwpxKq04M/jTmHyCZn12WPJebZxdjSa5TmBqISrUSgNYU3eRORljfCCw==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^4.0.2" }, "engines": { - "node": ">= 8" + "node": "20 || >=22" } }, - "node_modules/espree": { - "version": "9.2.0", - "resolved": "https://registry.npmjs.org/espree/-/espree-9.2.0.tgz", - "integrity": "sha512-oP3utRkynpZWF/F2x/HZJ+AGtnIclaR7z1pYPxy7NYM2fSO6LgK/Rkny8anRSPK/VwEA1eqm2squui0T7ZMOBg==", + "node_modules/eslint/node_modules/eslint-scope": { + "version": "9.1.2", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-9.1.2.tgz", + "integrity": "sha512-xS90H51cKw0jltxmvmHy2Iai1LIqrfbw57b79w/J7MfvDfkIkFZ+kj6zC3BjtUwh150HsSSdxXZcsuv72miDFQ==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { - "acorn": "^8.6.0", - "acorn-jsx": "^5.3.1", - "eslint-visitor-keys": "^3.1.0" + "@types/esrecurse": "^4.3.1", + "@types/estree": "^1.0.8", + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^20.19.0 || ^22.13.0 || >=24" + }, + "funding": { + "url": "https://opencollective.com/eslint" } }, - "node_modules/esprima": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "node_modules/eslint/node_modules/eslint-visitor-keys": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-5.0.1.tgz", + "integrity": "sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA==", "dev": true, - "bin": { - "esparse": "bin/esparse.js", - "esvalidate": "bin/esvalidate.js" + "license": "Apache-2.0", + "engines": { + "node": "^20.19.0 || ^22.13.0 || >=24" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint/node_modules/espree": { + "version": "11.1.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-11.1.1.tgz", + "integrity": "sha512-AVHPqQoZYc+RUM4/3Ly5udlZY/U4LS8pIG05jEjWM2lQMU/oaZ7qshzAl2YP1tfNmXfftH3ohurfwNAug+MnsQ==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "acorn": "^8.16.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^5.0.1" }, "engines": { - "node": ">=4" + "node": "^20.19.0 || ^22.13.0 || >=24" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint/node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true, + "license": "MIT" + }, + "node_modules/eslint/node_modules/minimatch": { + "version": "10.2.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.4.tgz", + "integrity": "sha512-oRjTw/97aTBN0RHbYCdtF1MQfvusSIBQM0IZEgzl6426+8jSC0nF1a/GmnVLpfB9yyr6g6FTqWqiZVbxrtaCIg==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "brace-expansion": "^5.0.2" + }, + "engines": { + "node": "18 || 20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/espree": { + "version": "9.6.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", + "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", + "dev": true, + "dependencies": { + "acorn": "^8.9.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^3.4.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" } }, "node_modules/esquery": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.4.0.tgz", - "integrity": "sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==", + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.7.0.tgz", + "integrity": "sha512-Ap6G0WQwcU/LHsvLwON1fAQX9Zp0A2Y6Y/cJBl9r/JbW90Zyg4/zbG6zzKa2OTALELarYHmKu0GhpM5EO+7T0g==", "dev": true, + "license": "BSD-3-Clause", "dependencies": { "estraverse": "^5.1.0" }, @@ -2497,199 +3251,247 @@ "node": ">=0.10.0" } }, - "node_modules/execa": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/execa/-/execa-0.2.2.tgz", - "integrity": "sha1-4urUcsLDGq1vc/GslW7vReEjIMs=", + "node_modules/eventemitter3": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz", + "integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==", "dev": true, - "dependencies": { - "cross-spawn-async": "^2.1.1", - "npm-run-path": "^1.0.0", - "object-assign": "^4.0.1", - "path-key": "^1.0.0", - "strip-eof": "^1.0.0" - }, - "engines": { - "node": ">=0.12" - } + "license": "MIT" }, - "node_modules/execa/node_modules/path-key": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-1.0.0.tgz", - "integrity": "sha1-XVPVeAGWRsDWiADbThRua9wqx68=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" }, - "node_modules/exit-hook": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/exit-hook/-/exit-hook-1.1.1.tgz", - "integrity": "sha1-8FyiM7SMBdVP/wd2XfhQfpXAL/g=", + "node_modules/fast-diff": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.3.0.tgz", + "integrity": "sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==", "dev": true, - "engines": { - "node": ">=0.10.0" - } + "license": "Apache-2.0" }, - "node_modules/expand-tilde": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-2.0.2.tgz", - "integrity": "sha1-l+gBqgUt8CRU3kawK/YhZCzchQI=", + "node_modules/fast-glob": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", + "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", "dev": true, "dependencies": { - "homedir-polyfill": "^1.0.1" + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" }, "engines": { - "node": ">=0.10.0" + "node": ">=8.6.0" } }, - "node_modules/extend": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", - "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" - }, - "node_modules/external-editor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz", - "integrity": "sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==", + "node_modules/fast-glob/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, "dependencies": { - "chardet": "^0.7.0", - "iconv-lite": "^0.4.24", - "tmp": "^0.0.33" + "is-glob": "^4.0.1" }, "engines": { - "node": ">=4" + "node": ">= 6" } }, - "node_modules/extsprintf": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", - "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=", - "engines": [ - "node >=0.6.0" - ] - }, - "node_modules/fast-deep-equal": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" - }, - "node_modules/fast-diff": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.2.0.tgz", - "integrity": "sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w==", - "dev": true - }, - "node_modules/fast-json-stable-stringify": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", - "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=" + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true }, "node_modules/fast-levenshtein": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", "dev": true }, - "node_modules/fecha": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/fecha/-/fecha-4.2.1.tgz", - "integrity": "sha512-MMMQ0ludy/nBs1/o0zVOiKTpG7qMbonKUzjJgQFEuvq6INZ1OraKPRAWkBq5vlKLOUMpmNYG1JoN3oDPUQ9m3Q==" + "node_modules/fast-string-truncated-width": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/fast-string-truncated-width/-/fast-string-truncated-width-3.0.3.tgz", + "integrity": "sha512-0jjjIEL6+0jag3l2XWWizO64/aZVtpiGE3t0Zgqxv0DPuxiMjvB3M24fCyhZUO4KomJQPj3LTSUnDP3GpdwC0g==", + "license": "MIT" }, - "node_modules/figures": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", - "integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==", + "node_modules/fast-string-width": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/fast-string-width/-/fast-string-width-3.0.2.tgz", + "integrity": "sha512-gX8LrtNEI5hq8DVUfRQMbr5lpaS4nMIWV+7XEbXk2b8kiQIizgnlr12B4dA3ZEx3308ze0O4Q1R+cHts8kyUJg==", + "license": "MIT", "dependencies": { - "escape-string-regexp": "^1.0.5" + "fast-string-truncated-width": "^3.0.2" + } + }, + "node_modules/fast-uri": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.0.3.tgz", + "integrity": "sha512-aLrHthzCjH5He4Z2H9YZ+v6Ujb9ocRuW6ZzkJQOrTxleEijANq4v1TsaPaVG1PZcuurEzrLcWRyYBYXD5cEiaw==" + }, + "node_modules/fast-wrap-ansi": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/fast-wrap-ansi/-/fast-wrap-ansi-0.2.0.tgz", + "integrity": "sha512-rLV8JHxTyhVmFYhBJuMujcrHqOT2cnO5Zxj37qROj23CP39GXubJRBUFF0z8KFK77Uc0SukZUf7JZhsVEQ6n8w==", + "license": "MIT", + "dependencies": { + "fast-string-width": "^3.0.2" + } + }, + "node_modules/fast-xml-builder": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fast-xml-builder/-/fast-xml-builder-1.0.0.tgz", + "integrity": "sha512-fpZuDogrAgnyt9oDDz+5DBz0zgPdPZz6D4IR7iESxRXElrlGTRkHJ9eEt+SACRJwT0FNFrt71DFQIUFBJfX/uQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/NaturalIntelligence" + } + ], + "license": "MIT" + }, + "node_modules/fast-xml-parser": { + "version": "5.4.2", + "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-5.4.2.tgz", + "integrity": "sha512-pw/6pIl4k0CSpElPEJhDppLzaixDEuWui2CUQQBH/ECDf7+y6YwA4Gf7Tyb0Rfe4DIMuZipYj4AEL0nACKglvQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/NaturalIntelligence" + } + ], + "license": "MIT", + "dependencies": { + "fast-xml-builder": "^1.0.0", + "strnum": "^2.1.2" }, - "engines": { - "node": ">=8" + "bin": { + "fxparser": "src/cli/cli.js" + } + }, + "node_modules/fastq": { + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.13.0.tgz", + "integrity": "sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw==", + "dev": true, + "dependencies": { + "reusify": "^1.0.4" } }, + "node_modules/fecha": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/fecha/-/fecha-4.2.3.tgz", + "integrity": "sha512-OP2IUU6HeYKJi3i0z4A19kHMQoLVs4Hc+DPqqxI2h/DPZHTm/vjsfC6P0b4jCMy14XizLBqvndQ+UilD7707Jw==" + }, "node_modules/file-entry-cache": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", - "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", + "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==", "dev": true, "dependencies": { - "flat-cache": "^3.0.4" + "flat-cache": "^4.0.0" }, "engines": { - "node": "^10.12.0 || >=12.0.0" + "node": ">=16.0.0" } }, - "node_modules/file-set": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/file-set/-/file-set-4.0.2.tgz", - "integrity": "sha512-fuxEgzk4L8waGXaAkd8cMr73Pm0FxOVkn8hztzUW7BAHhOGH90viQNXbiOsnecCWmfInqU6YmAMwxRMdKETceQ==", + "node_modules/fill-range": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", "dev": true, "dependencies": { - "array-back": "^5.0.0", - "glob": "^7.1.6" + "to-regex-range": "^5.0.1" }, "engines": { - "node": ">=10" + "node": ">=8" } }, - "node_modules/file-set/node_modules/array-back": { + "node_modules/find-up": { "version": "5.0.0", - "resolved": "https://registry.npmjs.org/array-back/-/array-back-5.0.0.tgz", - "integrity": "sha512-kgVWwJReZWmVuWOQKEOohXKJX+nD02JAZ54D1RRWlv8L0NebauKAaFxACKzB74RTclt1+WNz5KHaLRDAPZbDEw==", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", "dev": true, + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, "engines": { "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "node_modules/find-up-simple": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/find-up-simple/-/find-up-simple-1.0.1.tgz", + "integrity": "sha512-afd4O7zpqHeRyg4PfDQsXmlDe2PfdHtJt6Akt8jOWaApLOZk5JXs6VMR29lz03pRe9mpykrRCYIYxaJYcfpncQ==", "dev": true, - "dependencies": { - "to-regex-range": "^5.0.1" - }, + "license": "MIT", "engines": { - "node": ">=8" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/find-parent-dir": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/find-parent-dir/-/find-parent-dir-0.3.0.tgz", - "integrity": "sha1-M8RLQpqysvBkYpnF+fcY83b/jVQ=", - "dev": true - }, - "node_modules/find-replace": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/find-replace/-/find-replace-3.0.0.tgz", - "integrity": "sha512-6Tb2myMioCAgv5kfvP5/PkZZ/ntTpVK39fHY7WkWBgvbeE+VHd/tZuZ4mrC+bxh4cfOZeYKVPaJIZtZXV7GNCQ==", + "node_modules/find-up/node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", "dev": true, "dependencies": { - "array-back": "^3.0.1" + "p-locate": "^5.0.0" }, "engines": { - "node": ">=4.0.0" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/find-replace/node_modules/array-back": { + "node_modules/find-up/node_modules/p-limit": { "version": "3.1.0", - "resolved": "https://registry.npmjs.org/array-back/-/array-back-3.1.0.tgz", - "integrity": "sha512-TkuxA4UCOvxuDK6NZYXCalszEzj+TLszyASooky+i742l9TqsOdYCMJJupxRic61hwquNtppB3hgcuq9SVSH1Q==", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", "dev": true, + "dependencies": { + "yocto-queue": "^0.1.0" + }, "engines": { - "node": ">=6" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/find-up": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", - "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "node_modules/find-up/node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", "dev": true, "dependencies": { - "locate-path": "^3.0.0" + "p-limit": "^3.0.2" }, "engines": { - "node": ">=6" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/find-up/node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/flat": { @@ -2702,22 +3504,22 @@ } }, "node_modules/flat-cache": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", - "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz", + "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==", "dev": true, "dependencies": { - "flatted": "^3.1.0", - "rimraf": "^3.0.2" + "flatted": "^3.2.9", + "keyv": "^4.5.4" }, "engines": { - "node": "^10.12.0 || >=12.0.0" + "node": ">=16" } }, "node_modules/flatted": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.1.1.tgz", - "integrity": "sha512-zAoAQiudy+r5SvnSw3KJy5os/oRJYHzrzja/tBDqrZtNhUw8bt6y8OBzMWcjWr+8liV8Eb6yOhw8WZ7VFZ5ZzA==", + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.1.tgz", + "integrity": "sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==", "dev": true }, "node_modules/fn.name": { @@ -2725,55 +3527,78 @@ "resolved": "https://registry.npmjs.org/fn.name/-/fn.name-1.1.0.tgz", "integrity": "sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw==" }, - "node_modules/forever-agent": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", - "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=", + "node_modules/follow-redirects": { + "version": "1.15.11", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.11.tgz", + "integrity": "sha512-deG2P0JfjrTxl50XGCDyfI97ZGVCxIpfKYmfyrQ54n5FO/0gfIES8C/Psl6kWVDolizcaaxZJnTS0QSMxvnsBQ==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "license": "MIT", "engines": { - "node": "*" + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, + "node_modules/for-each": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", + "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", + "dependencies": { + "is-callable": "^1.1.3" + } + }, + "node_modules/foreground-child": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.1.1.tgz", + "integrity": "sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==", + "dev": true, + "dependencies": { + "cross-spawn": "^7.0.0", + "signal-exit": "^4.0.1" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, "node_modules/form-data": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", - "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.5.tgz", + "integrity": "sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==", + "license": "MIT", "dependencies": { "asynckit": "^0.4.0", - "combined-stream": "^1.0.6", + "combined-stream": "^1.0.8", + "es-set-tostringtag": "^2.1.0", + "hasown": "^2.0.2", "mime-types": "^2.1.12" }, "engines": { - "node": ">= 0.12" + "node": ">= 6" } }, "node_modules/fs-extra": { - "version": "10.0.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.0.0.tgz", - "integrity": "sha512-C5owb14u9eJwizKGdchcDUQeFtlSHHthBk8pbX9Vc1PFZrLombudjDnNns88aYslCyF6IY5SUw3Roz6xShcEIQ==", + "version": "11.3.4", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.3.4.tgz", + "integrity": "sha512-CTXd6rk/M3/ULNQj8FBqBWHYBVYybQ3VPBw0xGKFe3tuH7ytT6ACnvzpIQ3UZtB8yvUKC2cXn1a+x+5EVQLovA==", + "license": "MIT", "dependencies": { "graceful-fs": "^4.2.0", "jsonfile": "^6.0.1", "universalify": "^2.0.0" }, "engines": { - "node": ">=12" - } - }, - "node_modules/fs-extra/node_modules/universalify": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", - "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", - "engines": { - "node": ">= 10.0.0" - } - }, - "node_modules/fs-then-native": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/fs-then-native/-/fs-then-native-2.0.0.tgz", - "integrity": "sha1-GaEk2U2QwiyOBF8ujdbr6jbUjGc=", - "dev": true, - "engines": { - "node": ">=4.0.0" + "node": ">=14.14" } }, "node_modules/fs.realpath": { @@ -2783,10 +3608,9 @@ "dev": true }, "node_modules/fsevents": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", - "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", - "dev": true, + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", "hasInstallScript": true, "optional": true, "os": [ @@ -2796,58 +3620,22 @@ "node": "^8.16.0 || ^10.6.0 || >=11.0.0" } }, - "node_modules/fuel-auth": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/fuel-auth/-/fuel-auth-3.3.0.tgz", - "integrity": "sha512-ZJSfLmhcTHkY8h9i7Wmb8hebYjC064zLC+LxUaFj78qUQ/T/5v2rVwJ5dtpqhJ6BLwpVepKa0hDMfHak8+WaYA==", - "dependencies": { - "lodash.merge": "^4.6.1", - "request": "~2.88.0" - }, - "engines": { - "node": ">= 4" - } - }, - "node_modules/fuel-rest": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/fuel-rest/-/fuel-rest-3.2.2.tgz", - "integrity": "sha512-vqCvpOblssPQPLtn9QKCz4pMleRBneUUY0OXQc8tGyv+7qynwpkNw62OJw346RzKG4TtN9EuHb80Cm26aJCz6Q==", - "dependencies": { - "fuel-auth": "^3.3.0", - "lodash.clone": "~4.5.0", - "lodash.isplainobject": "~4.0.4", - "lodash.merge": "^4.6.1", - "request": "~2.88.0" - }, - "engines": { - "node": ">= 4" + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/fuel-soap": { - "version": "2.2.4", - "resolved": "https://registry.npmjs.org/fuel-soap/-/fuel-soap-2.2.4.tgz", - "integrity": "sha512-0+glcwMlBuF7NUpNNJ6x0gpUWOJzgT58GYnLIIuOaDrG7eS3i8JnOG+oElBCKdbymrmAqLwUBLsdBDYm/EdbQA==", - "dependencies": { - "fuel-auth": "^3.3.0", - "lodash.clone": "^4.5.0", - "lodash.isempty": "^4.4.0", - "lodash.isplainobject": "^4.0.3", - "lodash.merge": "^4.6.0", - "request": "^2.81.0", - "xml2js": "^0.4.16" + "node_modules/functions-have-names": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", + "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" - }, - "node_modules/functional-red-black-tree": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", - "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", - "dev": true - }, "node_modules/get-caller-file": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", @@ -2856,71 +3644,82 @@ "node": "6.* || 8.* || >= 10.*" } }, - "node_modules/get-func-name": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.0.tgz", - "integrity": "sha1-6td0q+5y4gQJQzoGY2YCPdaIekE=", - "dev": true, - "engines": { - "node": "*" - } - }, - "node_modules/get-stream": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", - "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=", - "dev": true, + "node_modules/get-east-asian-width": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/get-east-asian-width/-/get-east-asian-width-1.4.0.tgz", + "integrity": "sha512-QZjmEOC+IT1uk6Rx0sX22V6uHWVwbdbxf1faPqJ1QhLdGgsRGCZoyaQBm/piRdJy/D2um6hM1UP7ZEeQ4EkP+Q==", + "license": "MIT", "engines": { - "node": ">=4" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/getpass": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", - "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", + "node_modules/get-intrinsic": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", + "license": "MIT", "dependencies": { - "assert-plus": "^1.0.0" + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "function-bind": "^1.1.2", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/git-version-tag": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/git-version-tag/-/git-version-tag-1.0.2.tgz", - "integrity": "sha512-342rLtHtBdXcgngQOPhHt+IhxLbrijmd+Pa9rWDnQ9ubZYrWWSOWSQd9MTi8xo599RkrWkYh4lTYrNzPNxTmsQ==", + "node_modules/get-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "license": "MIT", "dependencies": { - "semver": "^5.6.0", - "simple-git": "^2.17.0" + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" }, "engines": { - "node": ">=8" - } - }, - "node_modules/git-version-tag/node_modules/semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "bin": { - "semver": "bin/semver" + "node": ">= 0.4" } }, - "node_modules/giturl": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/giturl/-/giturl-1.0.1.tgz", - "integrity": "sha512-wQourBdI13n8tbjcZTDl6k+ZrCRMU6p9vfp9jknZq+zfWc8xXNztpZFM4XkPHVzHcMSUZxEMYYKZjIGkPlei6Q==", + "node_modules/get-symbol-description": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.0.tgz", + "integrity": "sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==", "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.1" + }, "engines": { - "node": ">= 0.10.0" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, "node_modules/glob": { - "version": "7.1.7", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.7.tgz", - "integrity": "sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==", + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", "dev": true, "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", "inherits": "2", - "minimatch": "^3.0.4", + "minimatch": "^3.1.1", "once": "^1.3.0", "path-is-absolute": "^1.0.0" }, @@ -2932,192 +3731,86 @@ } }, "node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", "dev": true, "dependencies": { - "is-glob": "^4.0.1" + "is-glob": "^4.0.3" }, "engines": { - "node": ">= 6" + "node": ">=10.13.0" } }, - "node_modules/global-modules": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-1.0.0.tgz", - "integrity": "sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg==", - "dev": true, + "node_modules/global-directory": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/global-directory/-/global-directory-4.0.1.tgz", + "integrity": "sha512-wHTUcDUoZ1H5/0iVqEudYW4/kAlN5cZ3j/bXn0Dpbizl9iaUVeWSHqiOjsgk6OW2bkLclbBjzewBz6weQ1zA2Q==", "dependencies": { - "global-prefix": "^1.0.1", - "is-windows": "^1.0.1", - "resolve-dir": "^1.0.0" + "ini": "4.1.1" }, "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/global-prefix": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-1.0.2.tgz", - "integrity": "sha1-2/dDxsFJklk8ZVVoy2btMsASLr4=", - "dev": true, - "dependencies": { - "expand-tilde": "^2.0.2", - "homedir-polyfill": "^1.0.1", - "ini": "^1.3.4", - "is-windows": "^1.0.1", - "which": "^1.2.14" - }, - "engines": { - "node": ">=0.10.0" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/globals": { - "version": "13.12.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.12.0.tgz", - "integrity": "sha512-uS8X6lSKN2JumVoXrbUz+uG4BYG+eiawqm3qFcT7ammfbUHeCBoJMlHcec/S3krSk73/AE/f0szYFmgAA3kYZg==", - "dev": true, - "dependencies": { - "type-fest": "^0.20.2" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/globals/node_modules/type-fest": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "version": "17.4.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-17.4.0.tgz", + "integrity": "sha512-hjrNztw/VajQwOLsMNT1cbJiH2muO3OROCHnbehc8eY5JyD2gqz4AcMHPqgaOR59DjgUjYAYLeH699g/eWi2jw==", "dev": true, + "license": "MIT", "engines": { - "node": ">=10" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/globby": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-4.1.0.tgz", - "integrity": "sha1-CA9UVJ7BuCpsYOYx/ILhIR2+lfg=", + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", + "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", "dev": true, "dependencies": { - "array-union": "^1.0.1", - "arrify": "^1.0.0", - "glob": "^6.0.1", - "object-assign": "^4.0.1", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0" + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.2.9", + "ignore": "^5.2.0", + "merge2": "^1.4.1", + "slash": "^3.0.0" }, "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/globby/node_modules/glob": { - "version": "6.0.4", - "resolved": "https://registry.npmjs.org/glob/-/glob-6.0.4.tgz", - "integrity": "sha1-DwiGD2oVUSey+t1PnOJLGqtuTSI=", - "dev": true, - "dependencies": { - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "2 || 3", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" + "node": ">=10" }, - "engines": { - "node": "*" + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/globby/node_modules/pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", - "dev": true, + "node_modules/gopd": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "license": "MIT", "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/got": { - "version": "6.7.1", - "resolved": "https://registry.npmjs.org/got/-/got-6.7.1.tgz", - "integrity": "sha1-JAzQV4WpoY5WHcG0S0HHY+8ejbA=", - "dev": true, - "dependencies": { - "create-error-class": "^3.0.0", - "duplexer3": "^0.1.4", - "get-stream": "^3.0.0", - "is-redirect": "^1.0.0", - "is-retry-allowed": "^1.0.0", - "is-stream": "^1.0.0", - "lowercase-keys": "^1.0.0", - "safe-buffer": "^5.0.1", - "timed-out": "^4.0.0", - "unzip-response": "^2.0.1", - "url-parse-lax": "^1.0.0" + "node": ">= 0.4" }, - "engines": { - "node": ">=4" + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, "node_modules/graceful-fs": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.2.tgz", - "integrity": "sha512-IItsdsea19BoLC7ELy13q1iJFNmd7ofZH5+X/pJr90/nRoPEX0DJo1dHDbgtYWOhJhcCgMDTOw84RZ72q6lB+Q==" - }, - "node_modules/growl": { - "version": "1.10.5", - "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz", - "integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==", - "dev": true, - "engines": { - "node": ">=4.x" - } - }, - "node_modules/handlebars": { - "version": "4.7.7", - "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.7.tgz", - "integrity": "sha512-aAcXm5OAfE/8IXkcZvCepKU3VzW1/39Fb5ZuqMtgI/hT8X2YgoMvBY5dLhq/cpOvw7Lk1nK/UF71aLG/ZnVYRA==", - "dev": true, - "dependencies": { - "minimist": "^1.2.5", - "neo-async": "^2.6.0", - "source-map": "^0.6.1", - "wordwrap": "^1.0.0" - }, - "bin": { - "handlebars": "bin/handlebars" - }, - "engines": { - "node": ">=0.4.7" - }, - "optionalDependencies": { - "uglify-js": "^3.1.4" - } - }, - "node_modules/har-schema": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", - "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=", - "engines": { - "node": ">=4" - } + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==" }, - "node_modules/har-validator": { - "version": "5.1.3", - "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.3.tgz", - "integrity": "sha512-sNvOCzEQNr/qrvJgc3UG/kD4QtlHycrzwS+6mfTrrSq97BvaYcPZZI1ZSqGSPR73Cxn4LKTD4PttRwfU7jWq5g==", - "dependencies": { - "ajv": "^6.5.5", - "har-schema": "^2.0.0" - }, - "engines": { - "node": ">=6" - } + "node_modules/graphemer": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", + "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", + "dev": true }, "node_modules/has": { "version": "1.0.3", @@ -3151,29 +3844,71 @@ "node": ">=0.10.0" } }, + "node_modules/has-bigints": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz", + "integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true, "engines": { - "node": ">=4" + "node": ">=8" + } + }, + "node_modules/has-property-descriptors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.1.tgz", + "integrity": "sha512-VsX8eaIewvas0xnvinAe9bw4WfIeODpGYikiWYLH+dma0Jw6KHYqWiWfhQlgOVK8D6PvjubK5Uc4P0iIhIcNVg==", + "dependencies": { + "get-intrinsic": "^1.2.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, "node_modules/has-symbols": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.0.tgz", - "integrity": "sha1-uhqPGvKg/DllD1yFA2dwQSIGO0Q=", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", + "license": "MIT", "engines": { "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/has-yarn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/has-yarn/-/has-yarn-2.1.0.tgz", - "integrity": "sha512-UqBRqi4ju7T+TqGNdqAO0PaSVGsDGJUBQvk9eUWNGRY1CFGDzYhLWoM7JQEemnlvVcv/YEmc2wNW8BC24EnUsw==", + "node_modules/has-tostringtag": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", + "license": "MIT", + "dependencies": { + "has-symbols": "^1.0.3" + }, "engines": { - "node": ">=8" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" } }, "node_modules/he": { @@ -3185,127 +3920,79 @@ "he": "bin/he" } }, - "node_modules/highlight-es": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/highlight-es/-/highlight-es-1.0.3.tgz", - "integrity": "sha512-s/SIX6yp/5S1p8aC/NRDC1fwEb+myGIfp8/TzZz0rtAv8fzsdX7vGl3Q1TrXCsczFq8DI3CBFBCySPClfBSdbg==", - "dev": true, - "dependencies": { - "chalk": "^2.4.0", - "is-es2016-keyword": "^1.0.0", - "js-tokens": "^3.0.0" - } - }, - "node_modules/highlight-es/node_modules/js-tokens": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz", - "integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls=", - "dev": true - }, - "node_modules/homedir-polyfill": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz", - "integrity": "sha512-eSmmWE5bZTK2Nou4g0AI3zZ9rswp7GRKoKXS1BLUkvPviOqs4YTN1djQIqrXy9k5gEtdLPy86JjRwsNM9tnDcA==", - "dev": true, - "dependencies": { - "parse-passwd": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/hosted-git-info": { "version": "2.8.9", "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", "dev": true }, - "node_modules/http-cache-semantics": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz", - "integrity": "sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ==" - }, - "node_modules/http-signature": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", - "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", - "dependencies": { - "assert-plus": "^1.0.0", - "jsprim": "^1.2.2", - "sshpk": "^1.7.0" - }, - "engines": { - "node": ">=0.8", - "npm": ">=1.3.7" - } - }, - "node_modules/human-signals": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", - "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", + "node_modules/html-entities": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-2.6.0.tgz", + "integrity": "sha512-kig+rMn/QOVRvr7c86gQ8lWXq+Hkv6CbAH1hLu+RG338StTpE8Z0b44SDVaqVu7HGKf27frdmUYEs9hTUX/cLQ==", "dev": true, - "engines": { - "node": ">=10.17.0" - } + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/mdevils" + }, + { + "type": "patreon", + "url": "https://patreon.com/mdevils" + } + ], + "license": "MIT" + }, + "node_modules/html-escaper": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", + "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", + "dev": true }, "node_modules/husky": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/husky/-/husky-7.0.4.tgz", - "integrity": "sha512-vbaCKN2QLtP/vD4yvs6iz6hBEo6wkSzs8HpRah1Z6aGmF2KW5PdYuAd7uX5a+OyBZHBhd+TFLqgjUgytQr4RvQ==", + "version": "9.1.7", + "resolved": "https://registry.npmjs.org/husky/-/husky-9.1.7.tgz", + "integrity": "sha512-5gs5ytaNjBrh5Ow3zrvdUUY+0VxIuWVL4i9irt6friV+BqdCfmV11CQTWMiBYWHbXhco+J1kHfTOUkePhCDvMA==", "dev": true, "bin": { - "husky": "lib/bin.js" + "husky": "bin.js" }, "engines": { - "node": ">=12" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/typicode" } }, "node_modules/iconv-lite": { - "version": "0.4.24", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.7.2.tgz", + "integrity": "sha512-im9DjEDQ55s9fL4EYzOAv0yMqmMBSZp6G0VvFyTMPKWxiSBHUj9NW/qqLmXUwXrrM7AvqSlTCfvqRb0cM8yYqw==", + "license": "MIT", "dependencies": { - "safer-buffer": ">= 2.1.2 < 3" + "safer-buffer": ">= 2.1.2 < 3.0.0" }, "engines": { "node": ">=0.10.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" } }, - "node_modules/ieee754": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", - "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, "node_modules/ignore": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", - "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.0.tgz", + "integrity": "sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==", "dev": true, "engines": { "node": ">= 4" } }, "node_modules/import-fresh": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.2.2.tgz", - "integrity": "sha512-cTPNrlvJT6twpYy+YmKUKrTSjWFs3bjYjAhCwm+z4EOCubZxAuO+hHpRN64TqjEaYSHs7tJAE0w1CKMGmsG/lw==", + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", "dev": true, "dependencies": { "parent-module": "^1.0.0", @@ -3313,34 +4000,27 @@ }, "engines": { "node": ">=6" - } - }, - "node_modules/import-lazy": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/import-lazy/-/import-lazy-2.1.0.tgz", - "integrity": "sha1-BWmOPUXIjo1+nZLLBYTnfwlvPkM=", - "engines": { - "node": ">=4" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/imurmurhash": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", + "dev": true, "engines": { "node": ">=0.8.19" } }, "node_modules/indent-string": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-2.1.0.tgz", - "integrity": "sha1-ji1INIdCEhtKghi3oTfppSBJ3IA=", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", + "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", "dev": true, - "dependencies": { - "repeating": "^2.0.0" - }, "engines": { - "node": ">=0.10.0" + "node": ">=8" } }, "node_modules/inflight": { @@ -3359,235 +4039,188 @@ "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" }, "node_modules/ini": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", - "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==" - }, - "node_modules/inquirer": { - "version": "8.2.0", - "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-8.2.0.tgz", - "integrity": "sha512-0crLweprevJ02tTuA6ThpoAERAGyVILC4sS74uib58Xf/zSr1/ZWtmm7D5CI+bSQEaA04f0K7idaHpQbSWgiVQ==", - "dependencies": { - "ansi-escapes": "^4.2.1", - "chalk": "^4.1.1", - "cli-cursor": "^3.1.0", - "cli-width": "^3.0.0", - "external-editor": "^3.0.3", - "figures": "^3.0.0", - "lodash": "^4.17.21", - "mute-stream": "0.0.8", - "ora": "^5.4.1", - "run-async": "^2.4.0", - "rxjs": "^7.2.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0", - "through": "^2.3.6" - }, + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/ini/-/ini-4.1.1.tgz", + "integrity": "sha512-QQnnxNyfvmHFIsj7gkPcYymR8Jdw/o7mp5ZFihxn6h8Ci6fh3Dx4E1gPjpQEpIuPo9XVNY/ZUwh4BPMjGyL01g==", "engines": { - "node": ">=8.0.0" + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, - "node_modules/inquirer/node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "node_modules/inquirer": { + "version": "13.3.0", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-13.3.0.tgz", + "integrity": "sha512-APTrZe9IhrsshL0u2PgmEMLP3CXDBjZ99xh5dR2+sryOt5R+JGL0KNuaTTT2lW54B9eNQDMutPR05UYTL7Xb1Q==", + "license": "MIT", + "dependencies": { + "@inquirer/ansi": "^2.0.3", + "@inquirer/core": "^11.1.5", + "@inquirer/prompts": "^8.3.0", + "@inquirer/type": "^4.0.3", + "mute-stream": "^3.0.0", + "run-async": "^4.0.6", + "rxjs": "^7.8.2" + }, "engines": { - "node": ">=8" + "node": ">=23.5.0 || ^22.13.0 || ^21.7.0 || ^20.12.0" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } } }, - "node_modules/inquirer/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "node_modules/internal-slot": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.5.tgz", + "integrity": "sha512-Y+R5hJrzs52QCG2laLn4udYVnxsfny9CpOhNhUvk/SSSVyF6T27FzRbF0sroPidSu3X8oEAkOn2K804mjpt6UQ==", "dependencies": { - "color-convert": "^2.0.1" + "get-intrinsic": "^1.2.0", + "has": "^1.0.3", + "side-channel": "^1.0.4" }, "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "node": ">= 0.4" } }, - "node_modules/inquirer/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "node_modules/is-arguments": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz", + "integrity": "sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==", "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" }, "engines": { - "node": ">=10" + "node": ">= 0.4" }, "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/inquirer/node_modules/cli-spinners": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.6.1.tgz", - "integrity": "sha512-x/5fWmGMnbKQAaNwN+UZlV79qBLM9JFnJuJ03gIi5whrob0xV0ofNVHy9DhwGdsMJQc2OKv0oGmLzvaqvAVv+g==", - "engines": { - "node": ">=6" + "node_modules/is-array-buffer": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.2.tgz", + "integrity": "sha512-y+FyyR/w8vfIRq4eQcM1EYgSTnmHXPqaF+IgzgraytCFq5Xh8lllDVmAZolPJiZttZLeFSINPYMaEJ7/vWUa1w==", + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.2.0", + "is-typed-array": "^1.1.10" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/inquirer/node_modules/cli-width": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-3.0.0.tgz", - "integrity": "sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw==", - "engines": { - "node": ">= 10" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/inquirer/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/inquirer/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" - }, - "node_modules/inquirer/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" - }, - "node_modules/inquirer/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "engines": { - "node": ">=8" - } - }, - "node_modules/inquirer/node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "engines": { - "node": ">=8" - } + "node_modules/is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", + "dev": true }, - "node_modules/inquirer/node_modules/ora": { - "version": "5.4.1", - "resolved": "https://registry.npmjs.org/ora/-/ora-5.4.1.tgz", - "integrity": "sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==", + "node_modules/is-bigint": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", + "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==", "dependencies": { - "bl": "^4.1.0", - "chalk": "^4.1.0", - "cli-cursor": "^3.1.0", - "cli-spinners": "^2.5.0", - "is-interactive": "^1.0.0", - "is-unicode-supported": "^0.1.0", - "log-symbols": "^4.1.0", - "strip-ansi": "^6.0.0", - "wcwidth": "^1.0.1" - }, - "engines": { - "node": ">=10" + "has-bigints": "^1.0.1" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/inquirer/node_modules/string-width": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz", - "integrity": "sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==", + "node_modules/is-boolean-object": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", + "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==", "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.0" + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" }, "engines": { - "node": ">=8" - } - }, - "node_modules/inquirer/node_modules/strip-ansi": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", - "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", - "dependencies": { - "ansi-regex": "^5.0.0" + "node": ">= 0.4" }, - "engines": { - "node": ">=8" + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/inquirer/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dependencies": { - "has-flag": "^4.0.0" - }, + "node_modules/is-buffer": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.5.tgz", + "integrity": "sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], "engines": { - "node": ">=8" + "node": ">=4" } }, - "node_modules/is-arrayish": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz", - "integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==" - }, - "node_modules/is-binary-path": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", - "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "node_modules/is-builtin-module": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-5.0.0.tgz", + "integrity": "sha512-f4RqJKBUe5rQkJ2eJEJBXSticB3hGbN9j0yxxMQFqIW89Jp9WYFtzfTcRlstDKVUTRzSOTLKRfO9vIztenwtxA==", "dev": true, + "license": "MIT", "dependencies": { - "binary-extensions": "^2.0.0" + "builtin-modules": "^5.0.0" }, "engines": { - "node": ">=8" + "node": ">=18.20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/is-callable": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.4.tgz", - "integrity": "sha512-r5p9sxJjYnArLjObpjA4xu5EKI3CuKHkJXMhT7kwbpUyIFD1n5PMAsoPvWnvtZiNz7LjkYDRZhd7FlI0eMijEA==", + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.4.tgz", + "integrity": "sha512-nsuwtxZfMX67Oryl9LCQ+upnC0Z0BgpwntpS89m1H/TLF0zNfzfLMV/9Wa/6MZsj0acpEjAO0KF1xT6ZdLl95w==", "engines": { "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-ci": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-1.2.1.tgz", - "integrity": "sha512-s6tfsaQaQi3JNciBH6shVqEDvhGut0SUXr31ag8Pd8BBbVVlcGfWhpPmEOoM6RJ5TFhbypvf5yyRw/VXW1IiWg==", + "node_modules/is-core-module": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.9.0.tgz", + "integrity": "sha512-+5FPy5PnwmO3lvfMb0AsoPaBG+5KHUI0wYFXOtYPnVVVspTFUuMZNfNaNVRt3FZadstu2c8x23vykRW/NBoU6A==", "dev": true, "dependencies": { - "ci-info": "^1.5.0" + "has": "^1.0.3" }, - "bin": { - "is-ci": "bin.js" + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, "node_modules/is-date-object": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.1.tgz", - "integrity": "sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY=", + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", + "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", + "dependencies": { + "has-tostringtag": "^1.0.0" + }, "engines": { "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-es2016-keyword": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-es2016-keyword/-/is-es2016-keyword-1.0.0.tgz", - "integrity": "sha1-9uVOEQxeT40mXmnS7Q6vjPX0dxg=", - "dev": true - }, "node_modules/is-extglob": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", @@ -3597,22 +4230,35 @@ "node": ">=0.10.0" } }, - "node_modules/is-finite": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-finite/-/is-finite-1.1.0.tgz", - "integrity": "sha512-cdyMtqX/BOqqNBBiKlIVkytNHm49MtMlYyn1zxzvJKWmFMlGzm+ry5BBfYyeY9YmNKbRSo/o7OX9w9ale0wg3w==", + "node_modules/is-fullwidth-code-point": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-5.1.0.tgz", + "integrity": "sha512-5XHYaSyiqADb4RnZ1Bdad6cPp8Toise4TzEjcOYDHZkTCbKgiUl7WTUCpNWHuxmDt91wnsZBc9xinNzopv3JMQ==", "dev": true, + "license": "MIT", + "dependencies": { + "get-east-asian-width": "^1.3.1" + }, "engines": { - "node": ">=0.10.0" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "node_modules/is-generator-function": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.10.tgz", + "integrity": "sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==", "dev": true, + "dependencies": { + "has-tostringtag": "^1.0.0" + }, "engines": { - "node": ">=4" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, "node_modules/is-glob": { @@ -3627,20 +4273,91 @@ "node": ">=0.10.0" } }, - "node_modules/is-interactive": { + "node_modules/is-in-ci": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-1.0.0.tgz", - "integrity": "sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==", + "resolved": "https://registry.npmjs.org/is-in-ci/-/is-in-ci-1.0.0.tgz", + "integrity": "sha512-eUuAjybVTHMYWm/U+vBO1sY/JOCgoPCXRxzdju0K+K0BiGW0SChEL1MLC0PoCIR1OlPo5YAp8HuQoUlsWEICwg==", + "bin": { + "is-in-ci": "cli.js" + }, "engines": { - "node": ">=8" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/is-npm": { + "node_modules/is-installed-globally": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-installed-globally/-/is-installed-globally-1.0.0.tgz", + "integrity": "sha512-K55T22lfpQ63N4KEN57jZUAaAYqYHEe8veb/TycJRk9DdSCLLcovXz/mL6mOnhQaZsQGwPhuFopdQIlqGSEjiQ==", + "dependencies": { + "global-directory": "^4.0.1", + "is-path-inside": "^4.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-installed-globally/node_modules/is-path-inside": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/is-npm/-/is-npm-4.0.0.tgz", - "integrity": "sha512-96ECIfh9xtDDlPylNPXhzjsykHsMJZ18ASpaWzQyBr4YRTcVjUvzaHayDAES2oU/3KpljhHUjtSRNiDwi0F0ig==", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-4.0.0.tgz", + "integrity": "sha512-lJJV/5dYS+RcL8uQdBDW9c9uWFLLBNRyFhnAKXw5tVqLlKZ4RMGZKv+YQ/IA3OhD+RpbJa1LLFM1FQPGyIXvOA==", "engines": { - "node": ">=8" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-map": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.2.tgz", + "integrity": "sha512-cOZFQQozTha1f4MxLFzlgKYPTyj26picdZTx82hbc/Xf4K/tZOOXSCkMvU4pKioRXGDLJRn0GM7Upe7kR721yg==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-nan": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/is-nan/-/is-nan-1.3.2.tgz", + "integrity": "sha512-E+zBKpQ2t6MEo1VsonYmluk9NxGrbzpeeLC2xIViuO2EjU2xsXsBPwTr3Ykv9l08UYEVEdWeRZNouaZqF6RN0w==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.0", + "define-properties": "^1.1.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-negative-zero": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.2.tgz", + "integrity": "sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-npm": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/is-npm/-/is-npm-6.0.0.tgz", + "integrity": "sha512-JEjxbSmtPSt1c8XTkVrlujcXdKV1/tvuQ7GwKcAlyiVLeYFQ2VHat8xfrDJsIkhCdF/tZ7CiIR3sy141c6+gPQ==", + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/is-number": { @@ -3652,10 +4369,25 @@ "node": ">=0.12.0" } }, - "node_modules/is-obj": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz", - "integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==", + "node_modules/is-number-object": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz", + "integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==", + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-path-inside": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", + "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", + "dev": true, "engines": { "node": ">=8" } @@ -3669,285 +4401,247 @@ "node": ">=8" } }, - "node_modules/is-redirect": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-redirect/-/is-redirect-1.0.0.tgz", - "integrity": "sha1-HQPd7VO9jbDzDCbk+V02/HyH3CQ=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/is-regex": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.4.tgz", - "integrity": "sha1-VRdIm1RwkbCTDglWVM7SXul+lJE=", + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", + "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", "dependencies": { - "has": "^1.0.1" + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" }, "engines": { "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-retry-allowed": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/is-retry-allowed/-/is-retry-allowed-1.2.0.tgz", - "integrity": "sha512-RUbUeKwvm3XG2VYamhJL1xFktgjvPzL0Hq8C+6yrWIswDy3BIXGqCxhxkc30N9jqK311gVU137K8Ei55/zVJRg==", - "dev": true, - "engines": { - "node": ">=0.10.0" + "node_modules/is-set": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.2.tgz", + "integrity": "sha512-+2cnTEZeY5z/iXGbLhPrOAaK/Mau5k5eXq9j14CpRTftq0pAJu2MwVRSZhyZWBzx3o6X795Lz6Bpb6R0GKf37g==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-shared-array-buffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz", + "integrity": "sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==", + "dependencies": { + "call-bind": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, "node_modules/is-stream": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", - "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=", - "dev": true, + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", "engines": { - "node": ">=0.10.0" + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/is-symbol": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.2.tgz", - "integrity": "sha512-HS8bZ9ox60yCJLH9snBpIwv9pYUAkcuLhSA1oero1UB5y9aiQpRA8y2ex945AOtCZL1lJDeIk3G5LthswI46Lw==", + "node_modules/is-string": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", + "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", "dependencies": { - "has-symbols": "^1.0.0" + "has-tostringtag": "^1.0.0" }, "engines": { "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-typedarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", - "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=" - }, - "node_modules/is-unicode-supported": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", - "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", + "node_modules/is-symbol": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", + "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", + "dependencies": { + "has-symbols": "^1.0.2" + }, "engines": { - "node": ">=10" + "node": ">= 0.4" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-utf8": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", - "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=", - "dev": true + "node_modules/is-typed-array": { + "version": "1.1.10", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.10.tgz", + "integrity": "sha512-PJqgEHiWZvMpaFZ3uTc8kHPM4+4ADTlDniuQL7cU/UDA0Ql7F70yGfHph3cLNe+c9toaigv+DFzTJKhc2CtO6A==", + "dependencies": { + "available-typed-arrays": "^1.0.5", + "call-bind": "^1.0.2", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } }, - "node_modules/is-windows": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", - "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", + "node_modules/is-unicode-supported": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", + "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", "dev": true, "engines": { - "node": ">=0.10.0" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/is-yarn-global": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/is-yarn-global/-/is-yarn-global-0.3.0.tgz", - "integrity": "sha512-VjSeb/lHmkoyd8ryPVIKvOCn4D1koMqY+vqyjjUfc3xyKtP4dYOxM44sZrnqQSzSds3xyOrUTLTC9LVCVgLngw==" - }, - "node_modules/isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", - "dev": true - }, - "node_modules/isstream": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", - "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=" - }, - "node_modules/js-tokens": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "dev": true + "node_modules/is-weakmap": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.1.tgz", + "integrity": "sha512-NSBR4kH5oVj1Uwvv970ruUkCV7O1mzgVFO4/rev2cLRda9Tm9HrL70ZPut4rOHgY0FNrUu9BCbXA2sdQ+x0chA==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } }, - "node_modules/js-yaml": { - "version": "3.13.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz", - "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==", + "node_modules/is-weakref": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz", + "integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==", "dev": true, "dependencies": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" + "call-bind": "^1.0.2" }, - "bin": { - "js-yaml": "bin/js-yaml.js" + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/js2xmlparser": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/js2xmlparser/-/js2xmlparser-4.0.2.tgz", - "integrity": "sha512-6n4D8gLlLf1n5mNLQPRfViYzu9RATblzPEtm1SthMX1Pjao0r9YI9nw7ZIfRxQMERS87mcswrg+r/OYrPRX6jA==", - "dev": true, + "node_modules/is-weakset": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.2.tgz", + "integrity": "sha512-t2yVvttHkQktwnNNmBQ98AhENLdPUTDTE21uPqAQ0ARwQfGeQKRVS0NNurH7bTf7RrvcVn1OOge45CnBeHCSmg==", "dependencies": { - "xmlcreate": "^2.0.4" + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/jsbn": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", - "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=" + "node_modules/isarray": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==" + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", + "dev": true }, - "node_modules/jsdoc": { - "version": "3.6.7", - "resolved": "https://registry.npmjs.org/jsdoc/-/jsdoc-3.6.7.tgz", - "integrity": "sha512-sxKt7h0vzCd+3Y81Ey2qinupL6DpRSZJclS04ugHDNmRUXGzqicMJ6iwayhSA0S0DwwX30c5ozyUthr1QKF6uw==", + "node_modules/istanbul-lib-coverage": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.0.tgz", + "integrity": "sha512-eOeJ5BHCmHYvQK7xt9GkdHuzuCGS1Y6g9Gvnx3Ym33fz/HpLRYxiS0wHNr+m/MBC8B647Xt608vCDEvhl9c6Mw==", "dev": true, - "dependencies": { - "@babel/parser": "^7.9.4", - "bluebird": "^3.7.2", - "catharsis": "^0.9.0", - "escape-string-regexp": "^2.0.0", - "js2xmlparser": "^4.0.1", - "klaw": "^3.0.0", - "markdown-it": "^10.0.0", - "markdown-it-anchor": "^5.2.7", - "marked": "^2.0.3", - "mkdirp": "^1.0.4", - "requizzle": "^0.2.3", - "strip-json-comments": "^3.1.0", - "taffydb": "2.6.2", - "underscore": "~1.13.1" - }, - "bin": { - "jsdoc": "jsdoc.js" - }, "engines": { - "node": ">=8.15.0" + "node": ">=8" } }, - "node_modules/jsdoc-api": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/jsdoc-api/-/jsdoc-api-7.1.0.tgz", - "integrity": "sha512-yjIiZa6LFOgd0dyFW/R+3unnVUhhbU1CeBhisgjBPRHkar83rkgDtTMRdgQotSvt+pGlmknZqfwR5AQuMh9/6w==", + "node_modules/istanbul-lib-report": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz", + "integrity": "sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==", "dev": true, "dependencies": { - "array-back": "^6.2.0", - "cache-point": "^2.0.0", - "collect-all": "^1.0.4", - "file-set": "^4.0.2", - "fs-then-native": "^2.0.0", - "jsdoc": "^3.6.7", - "object-to-spawn-args": "^2.0.1", - "temp-path": "^1.0.0", - "walk-back": "^5.1.0" + "istanbul-lib-coverage": "^3.0.0", + "make-dir": "^4.0.0", + "supports-color": "^7.1.0" }, "engines": { - "node": ">=12.17" + "node": ">=10" } }, - "node_modules/jsdoc-api/node_modules/array-back": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/array-back/-/array-back-6.2.0.tgz", - "integrity": "sha512-mixVv03GOOn/ubHE4STQ+uevX42ETdk0JoMVEjNkSOCT7WgERh7C8/+NyhWYNpE3BN69pxFyJIBcF7CxWz/+4A==", + "node_modules/istanbul-reports": { + "version": "3.1.6", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.6.tgz", + "integrity": "sha512-TLgnMkKg3iTDsQ9PbPTdpfAK2DzjF9mqUG7RMgcQl8oFjad8ob4laGxv5XV5U9MAfx8D6tSJiUyuAwzLicaxlg==", "dev": true, + "dependencies": { + "html-escaper": "^2.0.0", + "istanbul-lib-report": "^3.0.0" + }, "engines": { - "node": ">=12.17" + "node": ">=8" } }, - "node_modules/jsdoc-parse": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/jsdoc-parse/-/jsdoc-parse-6.0.1.tgz", - "integrity": "sha512-ij3Az5y2dp+ajMxYnEJH7kjKK5v6+yZ3Cg/KtRdoT15pIm6qTk/W8q72QdNLZ9jQm/U2/ifENFXXTOe6xIxGeA==", + "node_modules/jackspeak": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.0.tgz", + "integrity": "sha512-JVYhQnN59LVPFCEcVa2C3CrEKYacvjRfqIQl+h8oi91aLYQVWRYbxjPcv1bUiUy/kLmQaANrYfNMCO3kuEDHfw==", "dev": true, "dependencies": { - "array-back": "^6.1.1", - "lodash.omit": "^4.5.0", - "lodash.pick": "^4.4.0", - "reduce-extract": "^1.0.0", - "sort-array": "^4.1.4", - "test-value": "^3.0.0" + "@isaacs/cliui": "^8.0.2" }, "engines": { "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + }, + "optionalDependencies": { + "@pkgjs/parseargs": "^0.11.0" } }, - "node_modules/jsdoc-parse/node_modules/array-back": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/array-back/-/array-back-6.2.0.tgz", - "integrity": "sha512-mixVv03GOOn/ubHE4STQ+uevX42ETdk0JoMVEjNkSOCT7WgERh7C8/+NyhWYNpE3BN69pxFyJIBcF7CxWz/+4A==", - "dev": true, - "engines": { - "node": ">=12.17" - } - }, - "node_modules/jsdoc-to-markdown": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/jsdoc-to-markdown/-/jsdoc-to-markdown-7.1.0.tgz", - "integrity": "sha512-LJAiwrUaOpPqOmllqnVVqfBZh6KI/rHHfSwL7DerTpjLQWHfpndz/JUNlF5ngYjbL4aHNf7uJ1TuXl6xGfq5rg==", + "node_modules/js-yaml": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz", + "integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==", "dev": true, + "license": "MIT", "dependencies": { - "array-back": "^6.2.0", - "command-line-tool": "^0.8.0", - "config-master": "^3.1.0", - "dmd": "^6.0.0", - "jsdoc-api": "^7.1.0", - "jsdoc-parse": "^6.0.1", - "walk-back": "^5.1.0" + "argparse": "^2.0.1" }, "bin": { - "jsdoc2md": "bin/cli.js" - }, - "engines": { - "node": ">=12.17" - } - }, - "node_modules/jsdoc-to-markdown/node_modules/array-back": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/array-back/-/array-back-6.2.0.tgz", - "integrity": "sha512-mixVv03GOOn/ubHE4STQ+uevX42ETdk0JoMVEjNkSOCT7WgERh7C8/+NyhWYNpE3BN69pxFyJIBcF7CxWz/+4A==", - "dev": true, - "engines": { - "node": ">=12.17" - } - }, - "node_modules/jsdoc/node_modules/escape-string-regexp": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", - "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", - "dev": true, - "engines": { - "node": ">=8" + "js-yaml": "bin/js-yaml.js" } }, - "node_modules/jsdoc/node_modules/strip-json-comments": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "node_modules/jsdoc-type-pratt-parser": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/jsdoc-type-pratt-parser/-/jsdoc-type-pratt-parser-7.1.1.tgz", + "integrity": "sha512-/2uqY7x6bsrpi3i9LVU6J89352C0rpMk0as8trXxCtvd4kPk1ke/Eyif6wqfSLvoNJqcDG9Vk4UsXgygzCt2xA==", "dev": true, + "license": "MIT", "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=20.0.0" } }, "node_modules/jsesc": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", - "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", + "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", "dev": true, + "license": "MIT", "bin": { "jsesc": "bin/jsesc" }, "engines": { - "node": ">=4" + "node": ">=6" } }, "node_modules/json-buffer": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.0.tgz", - "integrity": "sha1-Wx85evx11ne96Lz8Dkfh+aPZqJg=" + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "dev": true }, "node_modules/json-parse-better-errors": { "version": "1.0.2", @@ -3955,15 +4649,15 @@ "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", "dev": true }, - "node_modules/json-schema": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz", - "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==" - }, "node_modules/json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==" + }, + "node_modules/json-schema-typed": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/json-schema-typed/-/json-schema-typed-8.0.1.tgz", + "integrity": "sha512-XQmWYj2Sm4kn4WeTYvmpKEbyPsL7nBsb647c7pMe6l02/yx2+Jfc4dT6UZkEXnIUb5LhD55r2HPsJ1milQ4rDg==" }, "node_modules/json-stable-stringify-without-jsonify": { "version": "1.0.1", @@ -3971,11 +4665,6 @@ "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", "dev": true }, - "node_modules/json-stringify-safe": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", - "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=" - }, "node_modules/json-to-table": { "version": "4.2.1", "resolved": "https://registry.npmjs.org/json-to-table/-/json-to-table-4.2.1.tgz", @@ -3986,154 +4675,63 @@ } }, "node_modules/jsonfile": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.0.1.tgz", - "integrity": "sha512-jR2b5v7d2vIOust+w3wtFKZIfpC2pnRmFAhAC/BuweZFQR8qZzxH1OyrQ10HmdVYiXWkYUqPVsz91cG7EL2FBg==", - "dependencies": { - "graceful-fs": "^4.1.6", - "universalify": "^1.0.0" - } - }, - "node_modules/jsprim": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.2.tgz", - "integrity": "sha512-P2bSOMAc/ciLz6DzgjVlGJP9+BrJWu5UDGK70C2iweC5QBIeFf0ZXRvGjEj2uYgrY2MkAAhsSWHDWlFtEroZWw==", + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", "dependencies": { - "assert-plus": "1.0.0", - "extsprintf": "1.3.0", - "json-schema": "0.4.0", - "verror": "1.10.0" + "universalify": "^2.0.0" }, - "engines": { - "node": ">=0.6.0" + "optionalDependencies": { + "graceful-fs": "^4.1.6" } }, - "node_modules/keyv": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/keyv/-/keyv-3.1.0.tgz", - "integrity": "sha512-9ykJ/46SN/9KPM/sichzQ7OvXyGDYKGTaDlKMGCAlg2UK8KRy4jb0d8sFc+0Tt0YYnThq8X2RZgCg74RPxgcVA==", - "dependencies": { - "json-buffer": "3.0.0" + "node_modules/jsox": { + "version": "1.2.123", + "resolved": "https://registry.npmjs.org/jsox/-/jsox-1.2.123.tgz", + "integrity": "sha512-LYordXJ/0Q4G8pUE1Pvh4fkfGvZY7lRe4WIJKl0wr0rtFDVw9lcdNW95GH0DceJ6E9xh41zJNW0vreEz7xOxCw==", + "license": "MIT", + "bin": { + "jsox": "lib/cli.js" } }, - "node_modules/klaw": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/klaw/-/klaw-3.0.0.tgz", - "integrity": "sha512-0Fo5oir+O9jnXu5EefYbVK+mHMBeEVEy2cmctR1O1NECcCkPRreJKrS6Qt/j3KC2C148Dfo9i3pCmCMsdqGr0g==", + "node_modules/keyv": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", "dev": true, "dependencies": { - "graceful-fs": "^4.1.9" + "json-buffer": "3.0.1" } }, "node_modules/kuler": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/kuler/-/kuler-2.0.0.tgz", - "integrity": "sha512-Xq9nH7KlWZmXAtodXDDRE7vs6DU1gTU8zYDHDiWLSip45Egwq3plLHzPn27NgvzL2r1LMPC1vdqh98sQxtqj4A==" - }, - "node_modules/latest-version": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/latest-version/-/latest-version-5.1.0.tgz", - "integrity": "sha512-weT+r0kTkRQdCdYCNtkMwWXQTMEswKrFBkm4ckQOMVhhqhIMI1UT2hMj+1iigIhgSZm5gTmrRXBNoGUgaTY1xA==", - "dependencies": { - "package-json": "^6.3.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/latest-version/node_modules/get-stream": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", - "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", - "dependencies": { - "pump": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/latest-version/node_modules/got": { - "version": "9.6.0", - "resolved": "https://registry.npmjs.org/got/-/got-9.6.0.tgz", - "integrity": "sha512-R7eWptXuGYxwijs0eV+v3o6+XH1IqVK8dJOEecQfTmkncw9AV4dcw/Dhxi8MdlqPthxxpZyizMzyg8RTmEsG+Q==", - "dependencies": { - "@sindresorhus/is": "^0.14.0", - "@szmarczak/http-timer": "^1.1.2", - "cacheable-request": "^6.0.0", - "decompress-response": "^3.3.0", - "duplexer3": "^0.1.4", - "get-stream": "^4.1.0", - "lowercase-keys": "^1.0.1", - "mimic-response": "^1.0.1", - "p-cancelable": "^1.0.0", - "to-readable-stream": "^1.0.0", - "url-parse-lax": "^3.0.0" - }, - "engines": { - "node": ">=8.6" - } - }, - "node_modules/latest-version/node_modules/package-json": { - "version": "6.5.0", - "resolved": "https://registry.npmjs.org/package-json/-/package-json-6.5.0.tgz", - "integrity": "sha512-k3bdm2n25tkyxcjSKzB5x8kfVxlMdgsbPr0GkZcwHsLpba6cBjqCt1KlcChKEvxHIcTB1FVMuwoijZ26xex5MQ==", - "dependencies": { - "got": "^9.6.0", - "registry-auth-token": "^4.0.0", - "registry-url": "^5.0.0", - "semver": "^6.2.0" - }, - "engines": { - "node": ">=8" - } + "integrity": "sha512-Xq9nH7KlWZmXAtodXDDRE7vs6DU1gTU8zYDHDiWLSip45Egwq3plLHzPn27NgvzL2r1LMPC1vdqh98sQxtqj4A==", + "license": "MIT" }, - "node_modules/latest-version/node_modules/prepend-http": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-2.0.0.tgz", - "integrity": "sha1-6SQ0v6XqjBn0HN/UAddBo8gZ2Jc=", + "node_modules/ky": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/ky/-/ky-1.7.0.tgz", + "integrity": "sha512-g+S6ZMESSMuxrrbcDioBKSjBj8Xvam2WmLso+q1Ub7TTYCGS68XbSEM+eA3VSTmXJfR1uQjsTooC2tCsC3bW6g==", "engines": { - "node": ">=4" - } - }, - "node_modules/latest-version/node_modules/registry-auth-token": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-4.2.0.tgz", - "integrity": "sha512-P+lWzPrsgfN+UEpDS3U8AQKg/UjZX6mQSJueZj3EK+vNESoqBSpBUD3gmu4sF9lOsjXWjF11dQKUqemf3veq1w==", - "dependencies": { - "rc": "^1.2.8" + "node": ">=18" }, - "engines": { - "node": ">=6.0.0" + "funding": { + "url": "https://github.com/sindresorhus/ky?sponsor=1" } }, - "node_modules/latest-version/node_modules/registry-url": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/registry-url/-/registry-url-5.1.0.tgz", - "integrity": "sha512-8acYXXTI0AkQv6RAOjE3vOaIXZkT9wo4LOFbBKYQEEnnMNBpKqdUrI6S4NT0KPIo/WVvJ5tE/X5LF/TQUf0ekw==", + "node_modules/latest-version": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/latest-version/-/latest-version-9.0.0.tgz", + "integrity": "sha512-7W0vV3rqv5tokqkBAFV1LbR7HPOWzXQDpDgEuib/aJ1jsZZx6x3c2mBI+TJhJzOhkGeaLbCKEHXEXLfirtG2JA==", "dependencies": { - "rc": "^1.2.8" + "package-json": "^10.0.0" }, "engines": { - "node": ">=8" - } - }, - "node_modules/latest-version/node_modules/semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/latest-version/node_modules/url-parse-lax": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-3.0.0.tgz", - "integrity": "sha1-FrXK/Afb42dsGxmZF3gj1lA6yww=", - "dependencies": { - "prepend-http": "^2.0.0" + "node": ">=18" }, - "engines": { - "node": ">=4" + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/levn": { @@ -4149,97 +4747,93 @@ "node": ">= 0.8.0" } }, - "node_modules/lilconfig": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.0.4.tgz", - "integrity": "sha512-bfTIN7lEsiooCocSISTWXkiWJkRqtL9wYtYy+8EK3Y41qh3mpwPU0ycTOgjdY9ErwXCc8QyrQp82bdL0Xkm9yA==", - "dev": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/linkify-it": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-2.2.0.tgz", - "integrity": "sha512-GnAl/knGn+i1U/wjBz3akz2stz+HrHLsxMwHQGofCDfPvlf+gDKN58UtfmUquTY4/MXeE2x7k19KQmeoZi94Iw==", - "dev": true, - "dependencies": { - "uc.micro": "^1.0.1" - } - }, "node_modules/lint-staged": { - "version": "12.1.2", - "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-12.1.2.tgz", - "integrity": "sha512-bSMcQVqMW98HLLLR2c2tZ+vnDCnx4fd+0QJBQgN/4XkdspGRPc8DGp7UuOEBe1ApCfJ+wXXumYnJmU+wDo7j9A==", + "version": "16.3.2", + "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-16.3.2.tgz", + "integrity": "sha512-xKqhC2AeXLwiAHXguxBjuChoTTWFC6Pees0SHPwOpwlvI3BH7ZADFPddAdN3pgo3aiKgPUx/bxE78JfUnxQnlg==", "dev": true, + "license": "MIT", "dependencies": { - "cli-truncate": "^3.1.0", - "colorette": "^2.0.16", - "commander": "^8.3.0", - "debug": "^4.3.2", - "enquirer": "^2.3.6", - "execa": "^5.1.1", - "lilconfig": "2.0.4", - "listr2": "^3.13.3", - "micromatch": "^4.0.4", - "normalize-path": "^3.0.0", - "object-inspect": "^1.11.0", - "string-argv": "^0.3.1", - "supports-color": "^9.0.2", - "yaml": "^1.10.2" + "commander": "^14.0.3", + "listr2": "^9.0.5", + "micromatch": "^4.0.8", + "string-argv": "^0.3.2", + "tinyexec": "^1.0.2", + "yaml": "^2.8.2" }, "bin": { "lint-staged": "bin/lint-staged.js" }, "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + "node": ">=20.17" }, "funding": { "url": "https://opencollective.com/lint-staged" } }, - "node_modules/lint-staged/node_modules/cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "node_modules/listr2": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/listr2/-/listr2-9.0.5.tgz", + "integrity": "sha512-ME4Fb83LgEgwNw96RKNvKV4VTLuXfoKudAmm2lP8Kk87KaMK0/Xrx/aAkMWmT8mDb+3MlFDspfbCs7adjRxA2g==", "dev": true, + "license": "MIT", "dependencies": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" + "cli-truncate": "^5.0.0", + "colorette": "^2.0.20", + "eventemitter3": "^5.0.1", + "log-update": "^6.1.0", + "rfdc": "^1.4.1", + "wrap-ansi": "^9.0.0" }, "engines": { - "node": ">= 8" + "node": ">=20.0.0" } }, - "node_modules/lint-staged/node_modules/execa": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", - "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", + "node_modules/load-json-file": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz", + "integrity": "sha1-L19Fq5HjMhYjT9U62rZo607AmTs=", "dev": true, "dependencies": { - "cross-spawn": "^7.0.3", - "get-stream": "^6.0.0", - "human-signals": "^2.1.0", - "is-stream": "^2.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^4.0.1", - "onetime": "^5.1.2", - "signal-exit": "^3.0.3", - "strip-final-newline": "^2.0.0" + "graceful-fs": "^4.1.2", + "parse-json": "^4.0.0", + "pify": "^3.0.0", + "strip-bom": "^3.0.0" }, "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sindresorhus/execa?sponsor=1" + "node": ">=4" } }, - "node_modules/lint-staged/node_modules/get-stream": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", - "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "node_modules/load-json-file/node_modules/pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/lodash": { + "version": "4.17.23", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.23.tgz", + "integrity": "sha512-LgVTMpQtIopCi79SJeDiP0TfWi5CNEc/L/aRdTh3yIvmZXTnheWpKjSZhnvMl8iXbC1tFg9gdHHDMLoV7CnG+w==", + "license": "MIT" + }, + "node_modules/lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true + }, + "node_modules/log-symbols": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", + "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", "dev": true, + "dependencies": { + "chalk": "^4.1.0", + "is-unicode-supported": "^0.1.0" + }, "engines": { "node": ">=10" }, @@ -4247,232 +4841,406 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/lint-staged/node_modules/is-stream": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", - "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "node_modules/log-update": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/log-update/-/log-update-6.1.0.tgz", + "integrity": "sha512-9ie8ItPR6tjY5uYJh8K/Zrv/RMZ5VOlOWvtZdEHYSTFKZfIBPQa9tOAEeAWhd+AnIneLJ22w5fjOYtoutpWq5w==", "dev": true, + "license": "MIT", + "dependencies": { + "ansi-escapes": "^7.0.0", + "cli-cursor": "^5.0.0", + "slice-ansi": "^7.1.0", + "strip-ansi": "^7.1.0", + "wrap-ansi": "^9.0.0" + }, "engines": { - "node": ">=8" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/lint-staged/node_modules/npm-run-path": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", - "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "node_modules/log-update/node_modules/ansi-escapes": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-7.1.1.tgz", + "integrity": "sha512-Zhl0ErHcSRUaVfGUeUdDuLgpkEo8KIFjB4Y9uAc46ScOpdDiU1Dbyplh7qWJeJ/ZHpbyMSM26+X3BySgnIz40Q==", "dev": true, + "license": "MIT", "dependencies": { - "path-key": "^3.0.0" + "environment": "^1.0.0" }, "engines": { - "node": ">=8" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/lint-staged/node_modules/path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "node_modules/log-update/node_modules/strip-ansi": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.2.tgz", + "integrity": "sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA==", "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^6.0.1" + }, "engines": { - "node": ">=8" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" } }, - "node_modules/lint-staged/node_modules/shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dev": true, + "node_modules/logform": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/logform/-/logform-2.7.0.tgz", + "integrity": "sha512-TFYA4jnP7PVbmlBIfhlSe+WKxs9dklXMTEGcBCIvLhE/Tn3H6Gk1norupVW7m5Cnd4bLcr08AytbyV/xj7f/kQ==", "dependencies": { - "shebang-regex": "^3.0.0" + "@colors/colors": "1.6.0", + "@types/triple-beam": "^1.3.2", + "fecha": "^4.2.0", + "ms": "^2.1.1", + "safe-stable-stringify": "^2.3.1", + "triple-beam": "^1.3.0" }, "engines": { - "node": ">=8" + "node": ">= 12.0.0" } }, - "node_modules/lint-staged/node_modules/shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "node_modules/loglevel": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/loglevel/-/loglevel-1.8.0.tgz", + "integrity": "sha512-G6A/nJLRgWOuuwdNuA6koovfEV1YpqqAG4pRUlFaz3jj2QNZ8M4vBqnVA+HBTmU/AMNUtlOsMmSpF6NyOjztbA==", "dev": true, "engines": { - "node": ">=8" + "node": ">= 0.6.0" + }, + "funding": { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/loglevel" + } + }, + "node_modules/loglevel-colored-level-prefix": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/loglevel-colored-level-prefix/-/loglevel-colored-level-prefix-1.0.0.tgz", + "integrity": "sha1-akAhj9x64V/HbD0PPmdsRlOIYD4=", + "dev": true, + "dependencies": { + "chalk": "^1.1.3", + "loglevel": "^1.4.1" } }, - "node_modules/lint-staged/node_modules/supports-color": { - "version": "9.2.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-9.2.1.tgz", - "integrity": "sha512-Obv7ycoCTG51N7y175StI9BlAXrmgZrFhZOb0/PyjHBher/NmsdBgbbQ1Inhq+gIhz6+7Gb+jWF2Vqi7Mf1xnQ==", + "node_modules/loglevel-colored-level-prefix/node_modules/ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", "dev": true, "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/supports-color?sponsor=1" + "node": ">=0.10.0" } }, - "node_modules/lint-staged/node_modules/which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "node_modules/loglevel-colored-level-prefix/node_modules/ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/loglevel-colored-level-prefix/node_modules/chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", "dev": true, "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "node-which": "bin/node-which" + "ansi-styles": "^2.2.1", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^2.0.0", + "strip-ansi": "^3.0.0", + "supports-color": "^2.0.0" }, "engines": { - "node": ">= 8" + "node": ">=0.10.0" } }, - "node_modules/listr2": { - "version": "3.13.5", - "resolved": "https://registry.npmjs.org/listr2/-/listr2-3.13.5.tgz", - "integrity": "sha512-3n8heFQDSk+NcwBn3CgxEibZGaRzx+pC64n3YjpMD1qguV4nWus3Al+Oo3KooqFKTQEJ1v7MmnbnyyNspgx3NA==", - "dev": true, - "dependencies": { - "cli-truncate": "^2.1.0", - "colorette": "^2.0.16", - "log-update": "^4.0.0", - "p-map": "^4.0.0", - "rfdc": "^1.3.0", - "rxjs": "^7.4.0", - "through": "^2.3.8", - "wrap-ansi": "^7.0.0" - }, + "node_modules/loglevel-colored-level-prefix/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true, "engines": { - "node": ">=10.0.0" - }, - "peerDependencies": { - "enquirer": ">= 2.3.0 < 3" + "node": ">=0.8.0" + } + }, + "node_modules/loglevel-colored-level-prefix/node_modules/strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true, + "dependencies": { + "ansi-regex": "^2.0.0" }, - "peerDependenciesMeta": { - "enquirer": { - "optional": true - } + "engines": { + "node": ">=0.10.0" } }, - "node_modules/listr2/node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "node_modules/loglevel-colored-level-prefix/node_modules/supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", "dev": true, "engines": { - "node": ">=8" + "node": ">=0.8.0" } }, - "node_modules/listr2/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "node_modules/lru-cache": { + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/make-dir": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz", + "integrity": "sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==", "dev": true, "dependencies": { - "color-convert": "^2.0.1" + "semver": "^7.5.3" }, "engines": { - "node": ">=8" + "node": ">=10" }, "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/listr2/node_modules/cli-truncate": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-2.1.0.tgz", - "integrity": "sha512-n8fOixwDD6b/ObinzTrp1ZKFzbgvKZvuz/TvejnLn1aQfC6r52XEx85FmuC+3HI+JM7coBRXUvNqEU2PHVrHpg==", + "node_modules/math-intrinsics": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/memorystream": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/memorystream/-/memorystream-0.3.1.tgz", + "integrity": "sha1-htcJCzDORV1j+64S3aUaR93K+bI=", + "dev": true, + "engines": { + "node": ">= 0.10.0" + } + }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/micromatch": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", "dev": true, "dependencies": { - "slice-ansi": "^3.0.0", - "string-width": "^4.2.0" + "braces": "^3.0.3", + "picomatch": "^2.3.1" }, "engines": { - "node": ">=8" + "node": ">=8.6" + } + }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "license": "MIT", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mimic-function": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/mimic-function/-/mimic-function-5.0.1.tgz", + "integrity": "sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA==", + "engines": { + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/listr2/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "node_modules/minimatch": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", + "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", "dev": true, + "license": "ISC", "dependencies": { - "color-name": "~1.1.4" + "brace-expansion": "^1.1.7" }, "engines": { - "node": ">=7.0.0" + "node": "*" } }, - "node_modules/listr2/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } }, - "node_modules/listr2/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true + "node_modules/minipass": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.3.tgz", + "integrity": "sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A==", + "dev": true, + "license": "BlueOak-1.0.0", + "engines": { + "node": ">=16 || 14 >=14.17" + } }, - "node_modules/listr2/node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "node_modules/mocha": { + "version": "11.7.5", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-11.7.5.tgz", + "integrity": "sha512-mTT6RgopEYABzXWFx+GcJ+ZQ32kp4fMf0xvpZIIfSq9Z8lC/++MtcCnQ9t5FP2veYEP95FIYSvW+U9fV4xrlig==", "dev": true, + "license": "MIT", + "dependencies": { + "browser-stdout": "^1.3.1", + "chokidar": "^4.0.1", + "debug": "^4.3.5", + "diff": "^7.0.0", + "escape-string-regexp": "^4.0.0", + "find-up": "^5.0.0", + "glob": "^10.4.5", + "he": "^1.2.0", + "is-path-inside": "^3.0.3", + "js-yaml": "^4.1.0", + "log-symbols": "^4.1.0", + "minimatch": "^9.0.5", + "ms": "^2.1.3", + "picocolors": "^1.1.1", + "serialize-javascript": "^6.0.2", + "strip-json-comments": "^3.1.1", + "supports-color": "^8.1.1", + "workerpool": "^9.2.0", + "yargs": "^17.7.2", + "yargs-parser": "^21.1.1", + "yargs-unparser": "^2.0.0" + }, + "bin": { + "_mocha": "bin/_mocha", + "mocha": "bin/mocha.js" + }, "engines": { - "node": ">=8" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, - "node_modules/listr2/node_modules/slice-ansi": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-3.0.0.tgz", - "integrity": "sha512-pSyv7bSTC7ig9Dcgbw9AuRNUb5k5V6oDudjZoMBSr13qpLBG7tB+zgCkARjq7xIUgdz5P1Qe8u+rSGdouOOIyQ==", + "node_modules/mocha/node_modules/brace-expansion": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", + "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", "dev": true, + "license": "MIT", "dependencies": { - "ansi-styles": "^4.0.0", - "astral-regex": "^2.0.0", - "is-fullwidth-code-point": "^3.0.0" + "balanced-match": "^1.0.0" + } + }, + "node_modules/mocha/node_modules/cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" }, "engines": { - "node": ">=8" + "node": ">=12" } }, - "node_modules/listr2/node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "node_modules/mocha/node_modules/glob": { + "version": "10.5.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.5.0.tgz", + "integrity": "sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg==", "dev": true, + "license": "ISC", "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" + "foreground-child": "^3.1.0", + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^1.11.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/mocha/node_modules/minimatch": { + "version": "9.0.9", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.9.tgz", + "integrity": "sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.2" }, "engines": { - "node": ">=8" + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/listr2/node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "node_modules/mocha/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", "dev": true, "dependencies": { - "ansi-regex": "^5.0.1" + "has-flag": "^4.0.0" }, "engines": { - "node": ">=8" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" } }, - "node_modules/listr2/node_modules/wrap-ansi": { + "node_modules/mocha/node_modules/wrap-ansi": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", "dev": true, + "license": "MIT", "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", @@ -4485,2017 +5253,1996 @@ "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, - "node_modules/load-json-file": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz", - "integrity": "sha1-L19Fq5HjMhYjT9U62rZo607AmTs=", + "node_modules/mocha/node_modules/yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", "dev": true, + "license": "MIT", "dependencies": { - "graceful-fs": "^4.1.2", - "parse-json": "^4.0.0", - "pify": "^3.0.0", - "strip-bom": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/load-yaml-file": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/load-yaml-file/-/load-yaml-file-0.1.1.tgz", - "integrity": "sha512-G910TofXH7u0NfslAzqv6c9pHpvBzObNOo2hMG0/KUDpdHeFY0wE/fTBMExt0Gb12gg5bXS7Hj6pb0e+xbBXLA==", - "dev": true, - "dependencies": { - "graceful-fs": "^4.1.5", - "js-yaml": "^3.13.0", - "pify": "^2.3.0", - "strip-bom": "^3.0.0" + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" }, "engines": { - "node": ">=4" - } - }, - "node_modules/load-yaml-file/node_modules/pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", - "dev": true, - "engines": { - "node": ">=0.10.0" + "node": ">=12" } }, - "node_modules/locate-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", - "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "node_modules/mock-fs": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/mock-fs/-/mock-fs-5.3.0.tgz", + "integrity": "sha512-IMvz1X+RF7vf+ur7qUenXMR7/FSKSIqS3HqFHXcyNI7G0FbpFO8L5lfsUJhl+bhK1AiulVHWKUSxebWauPA+xQ==", "dev": true, - "dependencies": { - "p-locate": "^3.0.0", - "path-exists": "^3.0.0" - }, "engines": { - "node": ">=6" + "node": ">=12.0.0" } }, - "node_modules/lodash": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" - }, - "node_modules/lodash.camelcase": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", - "integrity": "sha1-soqmKIorn8ZRA1x3EfZathkDMaY=", - "dev": true - }, - "node_modules/lodash.clone": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.clone/-/lodash.clone-4.5.0.tgz", - "integrity": "sha1-GVhwRQ9aExkkeN9Lw9I9LeoZB7Y=" - }, - "node_modules/lodash.isempty": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/lodash.isempty/-/lodash.isempty-4.4.0.tgz", - "integrity": "sha1-b4bL7di+TsmHvpqvM8loTbGzHn4=" - }, - "node_modules/lodash.isplainobject": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", - "integrity": "sha1-fFJqUtibRcRcxpC4gWO+BJf1UMs=" - }, - "node_modules/lodash.merge": { - "version": "4.6.2", - "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", - "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==" + "node_modules/moo": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/moo/-/moo-0.5.2.tgz", + "integrity": "sha512-iSAJLHYKnX41mKcJKjqvnAN9sf0LMDTXDEvFv+ffuRR9a1MIuXLjMNL6EsnDHSkKLTWNqQQ5uo61P4EbU4NU+Q==", + "license": "BSD-3-Clause" }, - "node_modules/lodash.omit": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.omit/-/lodash.omit-4.5.0.tgz", - "integrity": "sha1-brGa5aHuHdnfC5aeZs4Lf6MLXmA=", - "dev": true + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" }, - "node_modules/lodash.padend": { - "version": "4.6.1", - "resolved": "https://registry.npmjs.org/lodash.padend/-/lodash.padend-4.6.1.tgz", - "integrity": "sha1-U8y6BH0G4VjTEfRdpiX05J5vFm4=", - "dev": true + "node_modules/mustache": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/mustache/-/mustache-4.2.0.tgz", + "integrity": "sha512-71ippSywq5Yb7/tVYyGbkBggbU8H3u5Rz56fH60jGFgr8uHwxs+aSKeqmluIVzM0m0kB7xQjKS6qPfd0b2ZoqQ==", + "bin": { + "mustache": "bin/mustache" + } }, - "node_modules/lodash.pick": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/lodash.pick/-/lodash.pick-4.4.0.tgz", - "integrity": "sha1-UvBWEP/53tQiYRRB7R/BI6AwAbM=", - "dev": true + "node_modules/mute-stream": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-3.0.0.tgz", + "integrity": "sha512-dkEJPVvun4FryqBmZ5KhDo0K9iDXAwn08tMLDinNdRBNPcYEDiWYysLcc6k3mjTMlbP9KyylvRpd4wFtwrT9rw==", + "license": "ISC", + "engines": { + "node": "^20.17.0 || >=22.9.0" + } }, - "node_modules/lodash.toarray": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/lodash.toarray/-/lodash.toarray-4.4.0.tgz", - "integrity": "sha1-JMS/zWsvuji/0FlNsRedjptlZWE=", + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", "dev": true }, - "node_modules/log-symbols": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", - "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", + "node_modules/nearley": { + "version": "2.20.1", + "resolved": "https://registry.npmjs.org/nearley/-/nearley-2.20.1.tgz", + "integrity": "sha512-+Mc8UaAebFzgV+KpI5n7DasuuQCHA89dmwm7JXw3TV43ukfNQ9DnBH3Mdb2g/I4Fdxc26pwimBWvjIw0UAILSQ==", + "license": "MIT", "dependencies": { - "chalk": "^4.1.0", - "is-unicode-supported": "^0.1.0" + "commander": "^2.19.0", + "moo": "^0.5.0", + "railroad-diagrams": "^1.0.0", + "randexp": "0.4.6" }, - "engines": { - "node": ">=10" + "bin": { + "nearley-railroad": "bin/nearley-railroad.js", + "nearley-test": "bin/nearley-test.js", + "nearley-unparse": "bin/nearley-unparse.js", + "nearleyc": "bin/nearleyc.js" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "type": "individual", + "url": "https://nearley.js.org/#give-to-nearley" } }, - "node_modules/log-symbols/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "node_modules/nearley/node_modules/commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "license": "MIT" + }, + "node_modules/nice-try": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", + "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==", + "dev": true + }, + "node_modules/node-releases": { + "version": "2.0.27", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.27.tgz", + "integrity": "sha512-nmh3lCkYZ3grZvqcCH+fjmQ7X+H0OeZgP40OierEaAptX4XofMh5kwNbWh7lBduUzCcV/8kZ+NDLCwm2iorIlA==", + "dev": true, + "license": "MIT" + }, + "node_modules/node-sql-parser": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/node-sql-parser/-/node-sql-parser-5.4.0.tgz", + "integrity": "sha512-jVe6Z61gPcPjCElPZ6j8llB3wnqGcuQzefim1ERsqIakxnEy5JlzV7XKdO1KmacRG5TKwPc4vJTgSRQ0LfkbFw==", + "license": "Apache-2.0", "dependencies": { - "color-convert": "^2.0.1" + "@types/pegjs": "^0.10.0", + "big-integer": "^1.6.48" }, "engines": { "node": ">=8" } }, - "node_modules/log-symbols/node_modules/chalk": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", - "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", + "node_modules/normalize-package-data": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", + "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", + "dev": true, "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" + "hosted-git-info": "^2.1.4", + "resolve": "^1.10.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" } }, - "node_modules/log-symbols/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" + "node_modules/normalize-package-data/node_modules/semver": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", + "dev": true, + "bin": { + "semver": "bin/semver" } }, - "node_modules/log-symbols/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" - }, - "node_modules/log-symbols/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "node_modules/npm-run-all": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/npm-run-all/-/npm-run-all-4.1.5.tgz", + "integrity": "sha512-Oo82gJDAVcaMdi3nuoKFavkIHBRVqQ1qvMb+9LHk/cF4P6B2m8aP04hGf7oL6wZ9BuGwX1onlLhpuoofSyoQDQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^3.2.1", + "chalk": "^2.4.1", + "cross-spawn": "^6.0.5", + "memorystream": "^0.3.1", + "minimatch": "^3.0.4", + "pidtree": "^0.3.0", + "read-pkg": "^3.0.0", + "shell-quote": "^1.6.1", + "string.prototype.padend": "^3.0.0" + }, + "bin": { + "npm-run-all": "bin/npm-run-all/index.js", + "run-p": "bin/run-p/index.js", + "run-s": "bin/run-s/index.js" + }, "engines": { - "node": ">=8" + "node": ">= 4" } }, - "node_modules/log-symbols/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "node_modules/npm-run-all/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, "dependencies": { - "has-flag": "^4.0.0" + "color-convert": "^1.9.0" }, "engines": { - "node": ">=8" + "node": ">=4" } }, - "node_modules/log-update": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/log-update/-/log-update-4.0.0.tgz", - "integrity": "sha512-9fkkDevMefjg0mmzWFBW8YkFP91OrizzkW3diF7CpG+S2EYdy4+TVfGwz1zeF8x7hCx1ovSPTOE9Ngib74qqUg==", + "node_modules/npm-run-all/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", "dev": true, "dependencies": { - "ansi-escapes": "^4.3.0", - "cli-cursor": "^3.1.0", - "slice-ansi": "^4.0.0", - "wrap-ansi": "^6.2.0" + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" }, "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=4" } }, - "node_modules/log-update/node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "node_modules/npm-run-all/node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", "dev": true, - "engines": { - "node": ">=8" + "dependencies": { + "color-name": "1.1.3" } }, - "node_modules/log-update/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "node_modules/npm-run-all/node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "dev": true + }, + "node_modules/npm-run-all/node_modules/cross-spawn": { + "version": "6.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.6.tgz", + "integrity": "sha512-VqCUuhcd1iB+dsv8gxPttb5iZh/D0iubSP21g36KXdEuf6I5JiioesUVjpCdHV9MZRUfVFlvwtIUyPfxo5trtw==", "dev": true, "dependencies": { - "color-convert": "^2.0.1" + "nice-try": "^1.0.4", + "path-key": "^2.0.1", + "semver": "^5.5.0", + "shebang-command": "^1.2.0", + "which": "^1.2.9" }, "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "node": ">=4.8" } }, - "node_modules/log-update/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "node_modules/npm-run-all/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, "engines": { - "node": ">=7.0.0" + "node": ">=0.8.0" } }, - "node_modules/log-update/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/log-update/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true - }, - "node_modules/log-update/node_modules/is-fullwidth-code-point": { + "node_modules/npm-run-all/node_modules/has-flag": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", "dev": true, "engines": { - "node": ">=8" + "node": ">=4" } }, - "node_modules/log-update/node_modules/slice-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz", - "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==", + "node_modules/npm-run-all/node_modules/path-key": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", + "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", "dev": true, - "dependencies": { - "ansi-styles": "^4.0.0", - "astral-regex": "^2.0.0", - "is-fullwidth-code-point": "^3.0.0" - }, "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/slice-ansi?sponsor=1" + "node": ">=4" } }, - "node_modules/log-update/node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "node_modules/npm-run-all/node_modules/pidtree": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/pidtree/-/pidtree-0.3.1.tgz", + "integrity": "sha512-qQbW94hLHEqCg7nhby4yRC7G2+jYHY4Rguc2bjw7Uug4GIJuu1tvf2uHaZv5Q8zdt+WKJ6qK1FOI6amaWUo5FA==", "dev": true, - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" + "bin": { + "pidtree": "bin/pidtree.js" }, "engines": { - "node": ">=8" + "node": ">=0.10" } }, - "node_modules/log-update/node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "node_modules/npm-run-all/node_modules/semver": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", "dev": true, - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" + "bin": { + "semver": "bin/semver" } }, - "node_modules/log-update/node_modules/wrap-ansi": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", - "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", + "node_modules/npm-run-all/node_modules/shebang-command": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", + "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", "dev": true, "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" + "shebang-regex": "^1.0.0" }, "engines": { - "node": ">=8" + "node": ">=0.10.0" } }, - "node_modules/logform": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/logform/-/logform-2.3.2.tgz", - "integrity": "sha512-V6JiPThZzTsbVRspNO6TmHkR99oqYTs8fivMBYQkjZj6rxW92KxtDCPE6IkAk1DNBnYKNkjm4jYBm6JDUcyhOA==", - "dependencies": { - "colors": "1.4.0", - "fecha": "^4.2.0", - "ms": "^2.1.1", - "safe-stable-stringify": "^1.1.0", - "triple-beam": "^1.3.0" + "node_modules/npm-run-all/node_modules/shebang-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", + "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", + "dev": true, + "engines": { + "node": ">=0.10.0" } }, - "node_modules/loud-rejection": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/loud-rejection/-/loud-rejection-1.6.0.tgz", - "integrity": "sha1-W0b4AUft7leIcPCG0Eghz5mOVR8=", + "node_modules/npm-run-all/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", "dev": true, "dependencies": { - "currently-unhandled": "^0.4.1", - "signal-exit": "^3.0.0" + "has-flag": "^3.0.0" }, "engines": { - "node": ">=0.10.0" + "node": ">=4" } }, - "node_modules/lowercase-keys": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz", - "integrity": "sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==", - "engines": { - "node": ">=0.10.0" + "node_modules/npm-run-all/node_modules/which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "dev": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "which": "bin/which" } }, - "node_modules/lru-cache": { - "version": "4.1.5", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", - "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==", + "node_modules/object-deep-merge": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/object-deep-merge/-/object-deep-merge-2.0.0.tgz", + "integrity": "sha512-3DC3UMpeffLTHiuXSy/UG4NOIYTLlY9u3V82+djSCLYClWobZiS4ivYzpIUWrRY/nfsJ8cWsKyG3QfyLePmhvg==", "dev": true, - "dependencies": { - "pseudomap": "^1.0.2", - "yallist": "^2.1.2" + "license": "MIT" + }, + "node_modules/object-inspect": { + "version": "1.12.3", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.3.tgz", + "integrity": "sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==", + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/make-dir": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", - "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", + "node_modules/object-is": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.5.tgz", + "integrity": "sha512-3cyDsyHgtmi7I7DfSSI2LDp6SK2lwvtbg0p0R1e0RvTqF5ceGx+K2dfSjm1bKDMVCFEDAQvy+o8c6a7VujOddw==", "dependencies": { - "semver": "^6.0.0" + "call-bind": "^1.0.2", + "define-properties": "^1.1.3" }, "engines": { - "node": ">=8" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/make-dir/node_modules/semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "bin": { - "semver": "bin/semver.js" + "node_modules/object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "engines": { + "node": ">= 0.4" } }, - "node_modules/map-obj": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz", - "integrity": "sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0=", - "dev": true, + "node_modules/object.assign": { + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.4.tgz", + "integrity": "sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==", + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "has-symbols": "^1.0.3", + "object-keys": "^1.1.1" + }, "engines": { - "node": ">=0.10.0" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/markdown-it": { - "version": "10.0.0", - "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-10.0.0.tgz", - "integrity": "sha512-YWOP1j7UbDNz+TumYP1kpwnP0aEa711cJjrAQrzd0UXlbJfc5aAq0F/PZHjiioqDC1NKgvIMX+o+9Bk7yuM2dg==", + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", "dev": true, "dependencies": { - "argparse": "^1.0.7", - "entities": "~2.0.0", - "linkify-it": "^2.0.0", - "mdurl": "^1.0.1", - "uc.micro": "^1.0.5" - }, - "bin": { - "markdown-it": "bin/markdown-it.js" + "wrappy": "1" } }, - "node_modules/markdown-it-anchor": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/markdown-it-anchor/-/markdown-it-anchor-5.3.0.tgz", - "integrity": "sha512-/V1MnLL/rgJ3jkMWo84UR+K+jF1cxNG1a+KwqeXqTIJ+jtA8aWSHuigx8lTzauiIjBDbwF3NcWQMotd0Dm39jA==", - "dev": true, - "peerDependencies": { - "markdown-it": "*" + "node_modules/one-time": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/one-time/-/one-time-1.0.0.tgz", + "integrity": "sha512-5DXOiRKwuSEcQ/l0kGCF6Q3jcADFv5tSmRaJck/OqkVFcOzutB134KRSfF0xDrL39MNnqxbHBbUUcjZIhTgb2g==", + "dependencies": { + "fn.name": "1.x.x" } }, - "node_modules/marked": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/marked/-/marked-2.1.3.tgz", - "integrity": "sha512-/Q+7MGzaETqifOMWYEA7HVMaZb4XbcRfaOzcSsHZEith83KGlvaSG33u0SKu89Mj5h+T8V2hM+8O45Qc5XTgwA==", + "node_modules/onetime": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-7.0.0.tgz", + "integrity": "sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ==", "dev": true, - "bin": { - "marked": "bin/marked" + "license": "MIT", + "dependencies": { + "mimic-function": "^5.0.0" }, "engines": { - "node": ">= 10" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/mdurl": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-1.0.1.tgz", - "integrity": "sha1-/oWy7HWlkDfyrf7BAP1sYBdhFS4=", - "dev": true - }, - "node_modules/memorystream": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/memorystream/-/memorystream-0.3.1.tgz", - "integrity": "sha1-htcJCzDORV1j+64S3aUaR93K+bI=", + "node_modules/optionator": { + "version": "0.9.3", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz", + "integrity": "sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==", "dev": true, + "dependencies": { + "@aashutoshrathi/word-wrap": "^1.2.3", + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0" + }, "engines": { - "node": ">= 0.10.0" + "node": ">= 0.8.0" } }, - "node_modules/meow": { - "version": "3.7.0", - "resolved": "https://registry.npmjs.org/meow/-/meow-3.7.0.tgz", - "integrity": "sha1-cstmi0JSKCkKu/qFaJJYcwioAfs=", - "dev": true, + "node_modules/p-limit": { + "version": "7.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-7.3.0.tgz", + "integrity": "sha512-7cIXg/Z0M5WZRblrsOla88S4wAK+zOQQWeBYfV3qJuJXMr+LnbYjaadrFaS0JILfEDPVqHyKnZ1Z/1d6J9VVUw==", + "license": "MIT", "dependencies": { - "camelcase-keys": "^2.0.0", - "decamelize": "^1.1.2", - "loud-rejection": "^1.0.0", - "map-obj": "^1.0.1", - "minimist": "^1.1.3", - "normalize-package-data": "^2.3.4", - "object-assign": "^4.0.1", - "read-pkg-up": "^1.0.1", - "redent": "^1.0.0", - "trim-newlines": "^1.0.0" + "yocto-queue": "^1.2.1" }, "engines": { - "node": ">=0.10.0" + "node": ">=20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/merge-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", - "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", - "dev": true - }, - "node_modules/micromatch": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.4.tgz", - "integrity": "sha512-pRmzw/XUcwXGpD9aI9q/0XOwLNygjETJ8y0ao0wdqprrzDa4YnxLcz7fQRZr8voh8V10kGhABbNcHVk5wHgWwg==", - "dev": true, + "node_modules/package-json": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/package-json/-/package-json-10.0.1.tgz", + "integrity": "sha512-ua1L4OgXSBdsu1FPb7F3tYH0F48a6kxvod4pLUlGY9COeJAJQNX/sNH2IiEmsxw7lqYiAwrdHMjz1FctOsyDQg==", "dependencies": { - "braces": "^3.0.1", - "picomatch": "^2.2.3" + "ky": "^1.2.0", + "registry-auth-token": "^5.0.2", + "registry-url": "^6.0.1", + "semver": "^7.6.0" }, "engines": { - "node": ">=8.6" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/mime-db": { - "version": "1.40.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.40.0.tgz", - "integrity": "sha512-jYdeOMPy9vnxEqFRRo6ZvTZ8d9oPb+k18PKoYNYUe2stVEBPPwsln/qWzdbmaIvnhZ9v2P+CuecK+fpUfsV2mA==", - "engines": { - "node": ">= 0.6" - } + "node_modules/package-json-from-dist": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", + "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==", + "dev": true }, - "node_modules/mime-types": { - "version": "2.1.24", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.24.tgz", - "integrity": "sha512-WaFHS3MCl5fapm3oLxU4eYDw77IQM2ACcxQ9RIxfaC3ooc6PFuBMGZZsYpvoXS5D5QTWPieo1jjLdAm3TBP3cQ==", + "node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, "dependencies": { - "mime-db": "1.40.0" + "callsites": "^3.0.0" }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/mimic-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", - "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", "engines": { "node": ">=6" } }, - "node_modules/mimic-response": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz", - "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==", - "engines": { - "node": ">=4" + "node_modules/parse-imports-exports": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/parse-imports-exports/-/parse-imports-exports-0.2.4.tgz", + "integrity": "sha512-4s6vd6dx1AotCx/RCI2m7t7GCh5bDRUtGNvRfHSP2wbBQdMi67pPe7mtzmgwcaQ8VKK/6IB7Glfyu3qdZJPybQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "parse-statements": "1.0.11" } }, - "node_modules/minimatch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "node_modules/parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=", "dev": true, "dependencies": { - "brace-expansion": "^1.1.7" + "error-ex": "^1.3.1", + "json-parse-better-errors": "^1.0.1" }, "engines": { - "node": "*" + "node": ">=4" } }, - "node_modules/minimist": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", - "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==" + "node_modules/parse-statements": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/parse-statements/-/parse-statements-1.0.11.tgz", + "integrity": "sha512-HlsyYdMBnbPQ9Jr/VgJ1YF4scnldvJpJxCVx6KgqPL4dxppsWrJHCIIxQXMJrqGnsRkNPATbeMJ8Yxu7JMsYcA==", + "dev": true, + "license": "MIT" }, - "node_modules/mkdirp": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", "dev": true, - "bin": { - "mkdirp": "bin/cmd.js" - }, "engines": { - "node": ">=10" + "node": ">=8" } }, - "node_modules/mkdirp2": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mkdirp2/-/mkdirp2-1.0.4.tgz", - "integrity": "sha512-Q2PKB4ZR4UPtjLl76JfzlgSCUZhSV1AXQgAZa1qt5RiaALFjP/CDrGvFBrOz7Ck6McPcwMAxTsJvWOUjOU8XMw==", - "dev": true - }, - "node_modules/mocha": { - "version": "9.1.3", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-9.1.3.tgz", - "integrity": "sha512-Xcpl9FqXOAYqI3j79pEtHBBnQgVXIhpULjGQa7DVb0Po+VzmSIK9kanAiWLHoRR/dbZ2qpdPshuXr8l1VaHCzw==", - "dev": true, - "dependencies": { - "@ungap/promise-all-settled": "1.1.2", - "ansi-colors": "4.1.1", - "browser-stdout": "1.3.1", - "chokidar": "3.5.2", - "debug": "4.3.2", - "diff": "5.0.0", - "escape-string-regexp": "4.0.0", - "find-up": "5.0.0", - "glob": "7.1.7", - "growl": "1.10.5", - "he": "1.2.0", - "js-yaml": "4.1.0", - "log-symbols": "4.1.0", - "minimatch": "3.0.4", - "ms": "2.1.3", - "nanoid": "3.1.25", - "serialize-javascript": "6.0.0", - "strip-json-comments": "3.1.1", - "supports-color": "8.1.1", - "which": "2.0.2", - "workerpool": "6.1.5", - "yargs": "16.2.0", - "yargs-parser": "20.2.4", - "yargs-unparser": "2.0.0" - }, - "bin": { - "_mocha": "bin/_mocha", - "mocha": "bin/mocha" - }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "dev": true, "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/mochajs" + "node": ">=0.10.0" } }, - "node_modules/mocha/node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", "dev": true, "engines": { "node": ">=8" } }, - "node_modules/mocha/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true + }, + "node_modules/path-scurry": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", + "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", "dev": true, "dependencies": { - "color-convert": "^2.0.1" + "lru-cache": "^10.2.0", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" }, "engines": { - "node": ">=8" + "node": ">=16 || 14 >=14.18" }, "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/mocha/node_modules/argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true - }, - "node_modules/mocha/node_modules/cliui": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", - "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", + "node_modules/path-type": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz", + "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==", "dev": true, "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", - "wrap-ansi": "^7.0.0" + "pify": "^3.0.0" + }, + "engines": { + "node": ">=4" } }, - "node_modules/mocha/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "node_modules/path-type/node_modules/pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, "engines": { - "node": ">=7.0.0" + "node": ">=4" } }, - "node_modules/mocha/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/mocha/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "dev": true, + "license": "ISC" }, - "node_modules/mocha/node_modules/escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", "dev": true, "engines": { - "node": ">=10" - } - }, - "node_modules/mocha/node_modules/find-up": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", - "dev": true, - "dependencies": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" + "node": ">=8.6" }, - "engines": { - "node": ">=10" + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" } }, - "node_modules/mocha/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "node_modules/pluralize": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-8.0.0.tgz", + "integrity": "sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==", "dev": true, "engines": { - "node": ">=8" + "node": ">=4" } }, - "node_modules/mocha/node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", "dev": true, "engines": { - "node": ">=8" + "node": ">= 0.8.0" } }, - "node_modules/mocha/node_modules/js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "dev": true, - "dependencies": { - "argparse": "^2.0.1" - }, + "node_modules/prettier": { + "version": "3.8.1", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.8.1.tgz", + "integrity": "sha512-UOnG6LftzbdaHZcKoPFtOcCKztrQ57WkHDeRD9t/PTQtmT0NHSeWWepj6pS0z/N7+08BHFDQVUrfmfMRcZwbMg==", + "license": "MIT", "bin": { - "js-yaml": "bin/js-yaml.js" + "prettier": "bin/prettier.cjs" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" } }, - "node_modules/mocha/node_modules/locate-path": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", - "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "node_modules/prettier-eslint": { + "version": "16.4.2", + "resolved": "https://registry.npmjs.org/prettier-eslint/-/prettier-eslint-16.4.2.tgz", + "integrity": "sha512-vtJAQEkaN8fW5QKl08t7A5KCjlZuDUNeIlr9hgolMS5s3+uzbfRHDwaRnzrdqnY2YpHDmeDS/8zY0MKQHXJtaA==", "dev": true, + "license": "MIT", "dependencies": { - "p-locate": "^5.0.0" + "@typescript-eslint/parser": "^6.21.0", + "common-tags": "^1.8.2", + "dlv": "^1.1.3", + "eslint": "^8.57.1", + "indent-string": "^4.0.0", + "lodash.merge": "^4.6.2", + "loglevel-colored-level-prefix": "^1.0.0", + "prettier": "^3.5.3", + "pretty-format": "^29.7.0", + "require-relative": "^0.8.7", + "tslib": "^2.8.1", + "vue-eslint-parser": "^9.4.3" }, "engines": { - "node": ">=10" + "node": ">=16.10.0" + }, + "funding": { + "url": "https://opencollective.com/prettier-eslint" + }, + "peerDependencies": { + "prettier-plugin-svelte": "^3.0.0", + "svelte-eslint-parser": "*" + }, + "peerDependenciesMeta": { + "prettier-plugin-svelte": { + "optional": true + }, + "svelte-eslint-parser": { + "optional": true + } } }, - "node_modules/mocha/node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true - }, - "node_modules/mocha/node_modules/p-limit": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.0.2.tgz", - "integrity": "sha512-iwqZSOoWIW+Ew4kAGUlN16J4M7OB3ysMLSZtnhmqx7njIHFPlxWBX8xo3lVTyFVq6mI/lL9qt2IsN1sHwaxJkg==", + "node_modules/prettier-eslint/node_modules/@eslint/js": { + "version": "8.57.1", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.1.tgz", + "integrity": "sha512-d9zaMRSTIKDLhctzH12MtXvJKSSUhaHcjV+2Z+GK+EEY7XKpP5yR4x+N3TAcHTcu963nIr+TMcCb4DBCYX1z6Q==", "dev": true, - "dependencies": { - "p-try": "^2.0.0" - }, + "license": "MIT", "engines": { - "node": ">=10" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" } }, - "node_modules/mocha/node_modules/p-locate": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", - "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "node_modules/prettier-eslint/node_modules/@typescript-eslint/parser": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.21.0.tgz", + "integrity": "sha512-tbsV1jPne5CkFQCgPBcDOt30ItF7aJoZL997JSF7MhGQqOeT3svWRYxiqlfA5RUdlHN6Fi+EI9bxqbdyAUZjYQ==", "dev": true, "dependencies": { - "p-limit": "^3.0.2" + "@typescript-eslint/scope-manager": "6.21.0", + "@typescript-eslint/types": "6.21.0", + "@typescript-eslint/typescript-estree": "6.21.0", + "@typescript-eslint/visitor-keys": "6.21.0", + "debug": "^4.3.4" }, "engines": { - "node": ">=10" + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } } }, - "node_modules/mocha/node_modules/path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "node_modules/prettier-eslint/node_modules/ajv": { + "version": "6.14.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.14.0.tgz", + "integrity": "sha512-IWrosm/yrn43eiKqkfkHis7QioDleaXQHdDVPKg0FSwwd/DuvyX79TZnFOnYpB7dcsFAMmtFztZuXPDvSePkFw==", "dev": true, - "engines": { - "node": ">=8" + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" } }, - "node_modules/mocha/node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "node_modules/prettier-eslint/node_modules/eslint": { + "version": "8.57.1", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.1.tgz", + "integrity": "sha512-ypowyDxpVSYpkXr9WPv2PAZCtNip1Mv5KTW0SCurXv/9iOpcrH9PaqUElksqEB6pChqHGDRCFTyrZlGhnLNGiA==", + "deprecated": "This version is no longer supported. Please see https://eslint.org/version-support for other options.", "dev": true, + "license": "MIT", "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" + "@eslint-community/eslint-utils": "^4.2.0", + "@eslint-community/regexpp": "^4.6.1", + "@eslint/eslintrc": "^2.1.4", + "@eslint/js": "8.57.1", + "@humanwhocodes/config-array": "^0.13.0", + "@humanwhocodes/module-importer": "^1.0.1", + "@nodelib/fs.walk": "^1.2.8", + "@ungap/structured-clone": "^1.2.0", + "ajv": "^6.12.4", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", + "debug": "^4.3.2", + "doctrine": "^3.0.0", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^7.2.2", + "eslint-visitor-keys": "^3.4.3", + "espree": "^9.6.1", + "esquery": "^1.4.2", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^6.0.1", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "globals": "^13.19.0", + "graphemer": "^1.4.0", + "ignore": "^5.2.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "is-path-inside": "^3.0.3", + "js-yaml": "^4.1.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.4.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.2", + "natural-compare": "^1.4.0", + "optionator": "^0.9.3", + "strip-ansi": "^6.0.1", + "text-table": "^0.2.0" + }, + "bin": { + "eslint": "bin/eslint.js" }, "engines": { - "node": ">=8" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" } }, - "node_modules/mocha/node_modules/strip-ansi": { + "node_modules/prettier-eslint/node_modules/file-entry-cache": { "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", + "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", "dev": true, "dependencies": { - "ansi-regex": "^5.0.1" + "flat-cache": "^3.0.4" }, "engines": { - "node": ">=8" + "node": "^10.12.0 || >=12.0.0" } }, - "node_modules/mocha/node_modules/strip-json-comments": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "node_modules/prettier-eslint/node_modules/flat-cache": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz", + "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==", "dev": true, + "dependencies": { + "flatted": "^3.2.9", + "keyv": "^4.5.3", + "rimraf": "^3.0.2" + }, "engines": { - "node": ">=8" + "node": "^10.12.0 || >=12.0.0" } }, - "node_modules/mocha/node_modules/supports-color": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "node_modules/prettier-eslint/node_modules/globals": { + "version": "13.24.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", + "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", "dev": true, "dependencies": { - "has-flag": "^4.0.0" + "type-fest": "^0.20.2" }, "engines": { - "node": ">=10" + "node": ">=8" }, "funding": { - "url": "https://github.com/chalk/supports-color?sponsor=1" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/mocha/node_modules/which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "node_modules/prettier-eslint/node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "node_modules/prettier-linter-helpers": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.1.tgz", + "integrity": "sha512-SxToR7P8Y2lWmv/kTzVLC1t/GDI2WGjMwNhLLE9qtH8Q13C+aEmuRlzDst4Up4s0Wc8sF2M+J57iB3cMLqftfg==", "dev": true, + "license": "MIT", "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "node-which": "bin/node-which" + "fast-diff": "^1.1.2" }, "engines": { - "node": ">= 8" + "node": ">=6.0.0" } }, - "node_modules/mocha/node_modules/wrap-ansi": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dev": true, + "node_modules/prettier-plugin-sql": { + "version": "0.19.2", + "resolved": "https://registry.npmjs.org/prettier-plugin-sql/-/prettier-plugin-sql-0.19.2.tgz", + "integrity": "sha512-DAu1Jcanpvs32OAOXsqaVXOpPs4nFLVkB3XwzRiZZVNL5/c+XdlNxWFMiMpMhYhmCG5BW3srK8mhikCOv5tPfg==", + "license": "MIT", "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" + "jsox": "^1.2.123", + "node-sql-parser": "^5.3.10", + "sql-formatter": "^15.6.5", + "tslib": "^2.8.1" }, "engines": { - "node": ">=10" + "node": "^14.18.0 || >=16.0.0" }, "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, - "node_modules/mocha/node_modules/y18n": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", - "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", - "dev": true, - "engines": { - "node": ">=10" + "url": "https://opencollective.com/unts" + }, + "peerDependencies": { + "prettier": "^3.0.3" } }, - "node_modules/mocha/node_modules/yargs": { - "version": "16.2.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", - "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", + "node_modules/pretty-format": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", + "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", "dev": true, "dependencies": { - "cliui": "^7.0.2", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.0", - "y18n": "^5.0.5", - "yargs-parser": "^20.2.2" + "@jest/schemas": "^29.6.3", + "ansi-styles": "^5.0.0", + "react-is": "^18.0.0" }, "engines": { - "node": ">=10" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/mocha/node_modules/yargs-parser": { - "version": "20.2.4", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.4.tgz", - "integrity": "sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==", + "node_modules/pretty-format/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", "dev": true, "engines": { "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" - }, - "node_modules/mustache": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/mustache/-/mustache-4.2.0.tgz", - "integrity": "sha512-71ippSywq5Yb7/tVYyGbkBggbU8H3u5Rz56fH60jGFgr8uHwxs+aSKeqmluIVzM0m0kB7xQjKS6qPfd0b2ZoqQ==", - "bin": { - "mustache": "bin/mustache" - } + "node_modules/proto-list": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/proto-list/-/proto-list-1.2.4.tgz", + "integrity": "sha512-vtK/94akxsTMhe0/cbfpR+syPuszcuwhqVjJq26CuNDgFGj682oRBXOP5MJpv2r7JtE8MsiepGIqvvOTBwn2vA==" }, - "node_modules/mute-stream": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz", - "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==" + "node_modules/proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==" }, - "node_modules/nanoid": { - "version": "3.1.25", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.1.25.tgz", - "integrity": "sha512-rdwtIXaXCLFAQbnfqDRnI6jaRHp9fTcYBjtFKE8eezcZ7LuLjhUaQGNeMXf1HmRoCH32CLz6XwX0TtxEOS/A3Q==", + "node_modules/punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", "dev": true, - "bin": { - "nanoid": "bin/nanoid.cjs" - }, "engines": { - "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + "node": ">=6" } }, - "node_modules/natural-compare": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", - "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", - "dev": true - }, - "node_modules/neo-async": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", - "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", - "dev": true - }, - "node_modules/nice-try": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", - "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==", - "dev": true - }, - "node_modules/node-emoji": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/node-emoji/-/node-emoji-1.10.0.tgz", - "integrity": "sha512-Yt3384If5H6BYGVHiHwTL+99OzJKHhgp82S8/dktEK73T26BazdgZ4JZh92xSVtGNJvz9UbXdNAc5hcrXV42vw==", - "dev": true, + "node_modules/pupa": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/pupa/-/pupa-3.1.0.tgz", + "integrity": "sha512-FLpr4flz5xZTSJxSeaheeMKN/EDzMdK7b8PTOC6a5PYFKTucWbdqjgqaEyH0shFiSJrVB1+Qqi4Tk19ccU6Aug==", "dependencies": { - "lodash.toarray": "^4.4.0" + "escape-goat": "^4.0.0" + }, + "engines": { + "node": ">=12.20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/node-sass-tilde-importer": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/node-sass-tilde-importer/-/node-sass-tilde-importer-1.0.2.tgz", - "integrity": "sha512-Swcmr38Y7uB78itQeBm3mThjxBy9/Ah/ykPIaURY/L6Nec9AyRoL/jJ7ECfMR+oZeCTVQNxVMu/aHU+TLRVbdg==", + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", "dev": true, - "dependencies": { - "find-parent-dir": "^0.3.0" - } - }, - "node_modules/normalize-package-data": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", - "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", - "dev": true, - "dependencies": { - "hosted-git-info": "^2.1.4", - "resolve": "^1.10.0", - "semver": "2 || 3 || 4 || 5", - "validate-npm-package-license": "^3.0.1" - } - }, - "node_modules/normalize-package-data/node_modules/semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true, - "bin": { - "semver": "bin/semver" - } + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] }, - "node_modules/normalize-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", - "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", - "dev": true, + "node_modules/railroad-diagrams": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/railroad-diagrams/-/railroad-diagrams-1.0.0.tgz", + "integrity": "sha512-cz93DjNeLY0idrCNOH6PviZGRN9GJhsdm9hpn1YCS879fj4W+x5IFJhhkRZcwVgMmFF7R82UA/7Oh+R8lLZg6A==", + "license": "CC0-1.0" + }, + "node_modules/randexp": { + "version": "0.4.6", + "resolved": "https://registry.npmjs.org/randexp/-/randexp-0.4.6.tgz", + "integrity": "sha512-80WNmd9DA0tmZrw9qQa62GPPWfuXJknrmVmLcxvq4uZBdYqb1wYoKTmnlGUchvVWe0XiLupYkBoXVOxz3C8DYQ==", + "license": "MIT", + "dependencies": { + "discontinuous-range": "1.0.0", + "ret": "~0.1.10" + }, "engines": { - "node": ">=0.10.0" + "node": ">=0.12" } }, - "node_modules/normalize-url": { - "version": "4.5.1", - "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-4.5.1.tgz", - "integrity": "sha512-9UZCFRHQdNrfTpGg8+1INIg93B6zE0aXMVFkw1WFwvO4SlZywU6aLg5Of0Ap/PgcbSw4LNxvMWXMeugwMCX0AA==", - "engines": { - "node": ">=8" + "node_modules/randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "dev": true, + "dependencies": { + "safe-buffer": "^5.1.0" } }, - "node_modules/npm-check": { - "version": "5.9.2", - "resolved": "https://registry.npmjs.org/npm-check/-/npm-check-5.9.2.tgz", - "integrity": "sha512-YlTZGP1A8+Rad5wldGil9STYxgZpZl18X6GZI03f4Ch6qTI1TLHIYM0ISco19qgg8M3UHfooEqMfYOpOkF3AeA==", - "dev": true, + "node_modules/rc": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", "dependencies": { - "babel-runtime": "^6.6.1", - "callsite-record": "^3.0.0", - "chalk": "^1.1.3", - "co": "^4.6.0", - "depcheck": "0.8.3", - "execa": "^0.2.2", - "giturl": "^1.0.0", - "global-modules": "^1.0.0", - "globby": "^4.0.0", - "inquirer": "^0.12.0", - "is-ci": "^1.0.8", - "lodash": "^4.17.15", - "meow": "^3.7.0", - "minimatch": "^3.0.2", - "node-emoji": "^1.0.3", - "ora": "^0.2.1", - "package-json": "^4.0.1", - "path-exists": "^2.1.0", - "pkg-dir": "^1.0.0", - "preferred-pm": "^1.0.1", - "semver": "^5.0.1", - "semver-diff": "^2.0.0", - "text-table": "^0.2.0", - "throat": "^2.0.2", - "update-notifier": "^2.1.0", - "xtend": "^4.0.1" + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" }, "bin": { - "npm-check": "bin/cli.js" - }, - "engines": { - "node": ">=0.11.0" + "rc": "cli.js" } }, - "node_modules/npm-check/node_modules/ansi-align": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-2.0.0.tgz", - "integrity": "sha1-w2rsy6VjuJzrVW82kPCx2eNUf38=", - "dev": true, - "dependencies": { - "string-width": "^2.0.0" - } + "node_modules/rc/node_modules/ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==" }, - "node_modules/npm-check/node_modules/ansi-align/node_modules/ansi-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", - "dev": true, + "node_modules/rc/node_modules/strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==", "engines": { - "node": ">=4" + "node": ">=0.10.0" } }, - "node_modules/npm-check/node_modules/ansi-align/node_modules/is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", - "dev": true, - "engines": { - "node": ">=4" - } + "node_modules/react-is": { + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", + "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", + "dev": true }, - "node_modules/npm-check/node_modules/ansi-align/node_modules/string-width": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", - "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "node_modules/read-pkg": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz", + "integrity": "sha1-nLxoaXj+5l0WwA4rGcI3/Pbjg4k=", "dev": true, "dependencies": { - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^4.0.0" + "load-json-file": "^4.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^3.0.0" }, "engines": { "node": ">=4" } }, - "node_modules/npm-check/node_modules/ansi-align/node_modules/strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", - "dev": true, + "node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", "dependencies": { - "ansi-regex": "^3.0.0" + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" }, "engines": { - "node": ">=4" - } - }, - "node_modules/npm-check/node_modules/ansi-escapes": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-1.4.0.tgz", - "integrity": "sha1-06ioOzGapneTZisT52HHkRQiMG4=", - "dev": true, - "engines": { - "node": ">=0.10.0" + "node": ">= 6" } }, - "node_modules/npm-check/node_modules/ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "node_modules/readdirp": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.1.2.tgz", + "integrity": "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==", "dev": true, + "license": "MIT", "engines": { - "node": ">=0.10.0" + "node": ">= 14.18.0" + }, + "funding": { + "type": "individual", + "url": "https://paulmillr.com/funding/" } }, - "node_modules/npm-check/node_modules/ansi-styles": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "node_modules/regexp-tree": { + "version": "0.1.27", + "resolved": "https://registry.npmjs.org/regexp-tree/-/regexp-tree-0.1.27.tgz", + "integrity": "sha512-iETxpjK6YoRWJG5o6hXLwvjYAoW+FEZn9os0PD/b6AP6xQwsa/Y7lCVgIixBbUPMfhu+i2LtdeAqVTgGlQarfA==", "dev": true, - "engines": { - "node": ">=0.10.0" + "bin": { + "regexp-tree": "bin/regexp-tree" } }, - "node_modules/npm-check/node_modules/boxen": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/boxen/-/boxen-1.3.0.tgz", - "integrity": "sha512-TNPjfTr432qx7yOjQyaXm3dSR0MH9vXp7eT1BFSl/C51g+EFnOR9hTg1IreahGBmDNCehscshe45f+C1TBZbLw==", - "dev": true, + "node_modules/regexp.prototype.flags": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.1.tgz", + "integrity": "sha512-sy6TXMN+hnP/wMy+ISxg3krXx7BAtWVO4UouuCN/ziM9UEne0euamVNafDfvC83bRNr95y0V5iijeDQFUNpvrg==", "dependencies": { - "ansi-align": "^2.0.0", - "camelcase": "^4.0.0", - "chalk": "^2.0.1", - "cli-boxes": "^1.0.0", - "string-width": "^2.0.0", - "term-size": "^1.2.0", - "widest-line": "^2.0.0" + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "set-function-name": "^2.0.0" }, "engines": { - "node": ">=4" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/npm-check/node_modules/boxen/node_modules/ansi-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", - "dev": true, + "node_modules/registry-auth-token": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-5.0.2.tgz", + "integrity": "sha512-o/3ikDxtXaA59BmZuZrJZDJv8NMDGSj+6j6XaeBmHw8eY1i1qd9+6H+LjVvQXx3HN6aRCGa1cUdJ9RaJZUugnQ==", + "dependencies": { + "@pnpm/npm-conf": "^2.1.0" + }, "engines": { - "node": ">=4" + "node": ">=14" } }, - "node_modules/npm-check/node_modules/boxen/node_modules/ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, + "node_modules/registry-url": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/registry-url/-/registry-url-6.0.1.tgz", + "integrity": "sha512-+crtS5QjFRqFCoQmvGduwYWEBng99ZvmFvF+cUJkGYF1L1BfU8C6Zp9T7f5vPAwyLkUExpvK+ANVZmGU49qi4Q==", "dependencies": { - "color-convert": "^1.9.0" + "rc": "1.2.8" }, "engines": { - "node": ">=4" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/npm-check/node_modules/boxen/node_modules/chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "node_modules/regjsparser": { + "version": "0.13.0", + "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.13.0.tgz", + "integrity": "sha512-NZQZdC5wOE/H3UT28fVGL+ikOZcEzfMGk/c3iN9UGxzWHMa1op7274oyiUVrAG4B2EuFhus8SvkaYnhvW92p9Q==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" + "jsesc": "~3.1.0" }, - "engines": { - "node": ">=4" + "bin": { + "regjsparser": "bin/parser" } }, - "node_modules/npm-check/node_modules/boxen/node_modules/is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", "dev": true, + "license": "MIT", "engines": { - "node": ">=4" + "node": ">=0.10.0" } }, - "node_modules/npm-check/node_modules/boxen/node_modules/string-width": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", - "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", - "dev": true, - "dependencies": { - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^4.0.0" - }, + "node_modules/require-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", "engines": { - "node": ">=4" + "node": ">=0.10.0" } }, - "node_modules/npm-check/node_modules/boxen/node_modules/strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "node_modules/require-relative": { + "version": "0.8.7", + "resolved": "https://registry.npmjs.org/require-relative/-/require-relative-0.8.7.tgz", + "integrity": "sha1-eZlTn8ngR6N5KPoZb44VY9q9Nt4=", + "dev": true + }, + "node_modules/reserved-identifiers": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/reserved-identifiers/-/reserved-identifiers-1.2.0.tgz", + "integrity": "sha512-yE7KUfFvaBFzGPs5H3Ops1RevfUEsDc5Iz65rOwWg4lE8HJSYtle77uul3+573457oHvBKuHYDl/xqUkKpEEdw==", "dev": true, - "dependencies": { - "ansi-regex": "^3.0.0" - }, + "license": "MIT", "engines": { - "node": ">=4" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/npm-check/node_modules/boxen/node_modules/supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "node_modules/resolve": { + "version": "1.22.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.0.tgz", + "integrity": "sha512-Hhtrw0nLeSrFQ7phPp4OOcVjLPIeMnRlr5mcnVuMe7M/7eBn98A3hmFRLoFo3DLZkivSYwhRUJTyPyWAk56WLw==", "dev": true, "dependencies": { - "has-flag": "^3.0.0" + "is-core-module": "^2.8.1", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" }, - "engines": { - "node": ">=4" + "bin": { + "resolve": "bin/resolve" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/npm-check/node_modules/camelcase": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz", - "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=", + "node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", "dev": true, "engines": { "node": ">=4" } }, - "node_modules/npm-check/node_modules/chalk": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "node_modules/restore-cursor": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-5.1.0.tgz", + "integrity": "sha512-oMA2dcrw6u0YfxJQXm342bFKX/E4sG9rbTzO9ptUcR/e8A33cHuvStiYOwH7fszkZlZ1z/ta9AAoPk2F4qIOHA==", "dev": true, + "license": "MIT", "dependencies": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" + "onetime": "^7.0.0", + "signal-exit": "^4.1.0" }, "engines": { - "node": ">=0.10.0" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/npm-check/node_modules/cli-boxes": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-1.0.0.tgz", - "integrity": "sha1-T6kXw+WclKAEzWH47lCdplFocUM=", - "dev": true, + "node_modules/ret": { + "version": "0.1.15", + "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", + "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==", + "license": "MIT", "engines": { - "node": ">=0.10.0" + "node": ">=0.12" } }, - "node_modules/npm-check/node_modules/cli-cursor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-1.0.2.tgz", - "integrity": "sha1-ZNo/fValRBLll5S9Ytw1KV6PKYc=", + "node_modules/reusify": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", "dev": true, - "dependencies": { - "restore-cursor": "^1.0.1" - }, "engines": { + "iojs": ">=1.0.0", "node": ">=0.10.0" } }, - "node_modules/npm-check/node_modules/configstore": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/configstore/-/configstore-3.1.5.tgz", - "integrity": "sha512-nlOhI4+fdzoK5xmJ+NY+1gZK56bwEaWZr8fYuXohZ9Vkc1o3a4T/R3M+yE/w7x/ZVJ1zF8c+oaOvF0dztdUgmA==", + "node_modules/rfdc": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.4.1.tgz", + "integrity": "sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==", "dev": true, - "dependencies": { - "dot-prop": "^4.2.1", - "graceful-fs": "^4.1.2", - "make-dir": "^1.0.0", - "unique-string": "^1.0.0", - "write-file-atomic": "^2.0.0", - "xdg-basedir": "^3.0.0" - }, - "engines": { - "node": ">=4" - } + "license": "MIT" }, - "node_modules/npm-check/node_modules/cross-spawn": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", - "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=", + "node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "deprecated": "Rimraf versions prior to v4 are no longer supported", "dev": true, "dependencies": { - "lru-cache": "^4.0.1", - "shebang-command": "^1.2.0", - "which": "^1.2.9" + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/npm-check/node_modules/crypto-random-string": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-1.0.0.tgz", - "integrity": "sha1-ojD2T1aDEOFJgAmUB5DsmVRbyn4=", - "dev": true, + "node_modules/run-async": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/run-async/-/run-async-4.0.6.tgz", + "integrity": "sha512-IoDlSLTs3Yq593mb3ZoKWKXMNu3UpObxhgA/Xuid5p4bbfi2jdY1Hj0m1K+0/tEuQTxIGMhQDqGjKb7RuxGpAQ==", + "license": "MIT", "engines": { - "node": ">=4" + "node": ">=0.12.0" } }, - "node_modules/npm-check/node_modules/dot-prop": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-4.2.1.tgz", - "integrity": "sha512-l0p4+mIuJIua0mhxGoh4a+iNL9bmeK5DvnSVQa6T0OhrVmaEa1XScX5Etc673FePCJOArq/4Pa2cLGODUWTPOQ==", - "dev": true, - "dependencies": { - "is-obj": "^1.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/npm-check/node_modules/figures": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/figures/-/figures-1.7.0.tgz", - "integrity": "sha1-y+Hjr/zxzUS4DK3+0o3Hk6lwHS4=", + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], "dependencies": { - "escape-string-regexp": "^1.0.5", - "object-assign": "^4.1.0" - }, - "engines": { - "node": ">=0.10.0" + "queue-microtask": "^1.2.2" } }, - "node_modules/npm-check/node_modules/global-dirs": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-0.1.1.tgz", - "integrity": "sha1-sxnA3UYH81PzvpzKTHL8FIxJ9EU=", - "dev": true, + "node_modules/rxjs": { + "version": "7.8.2", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.2.tgz", + "integrity": "sha512-dhKf903U/PQZY6boNNtAGdWbG85WAbjT/1xYoZIC7FAY0yWapOBQVsVrDl58W86//e1VpMNBtRV4MaXfdMySFA==", + "license": "Apache-2.0", "dependencies": { - "ini": "^1.3.4" + "tslib": "^2.1.0" + } + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/safe-stable-stringify": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/safe-stable-stringify/-/safe-stable-stringify-2.5.0.tgz", + "integrity": "sha512-b3rppTKm9T+PsVCBEOUR46GWI7fdOs00VKZ1+9c1EWDaDMvjQc6tUwuFyIprgGgTcWoVHSKrU8H31ZHA2e0RHA==", + "engines": { + "node": ">=10" + } + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "license": "MIT" + }, + "node_modules/semver": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz", + "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" }, "engines": { - "node": ">=4" + "node": ">=10" } }, - "node_modules/npm-check/node_modules/inquirer": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-0.12.0.tgz", - "integrity": "sha1-HvK/1jUE3wvHV4X/+MLEHfEvB34=", + "node_modules/serialize-javascript": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz", + "integrity": "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==", "dev": true, "dependencies": { - "ansi-escapes": "^1.1.0", - "ansi-regex": "^2.0.0", - "chalk": "^1.0.0", - "cli-cursor": "^1.0.1", - "cli-width": "^2.0.0", - "figures": "^1.3.5", - "lodash": "^4.3.0", - "readline2": "^1.0.1", - "run-async": "^0.1.0", - "rx-lite": "^3.1.2", - "string-width": "^1.0.1", - "strip-ansi": "^3.0.0", - "through": "^2.3.6" + "randombytes": "^2.1.0" } }, - "node_modules/npm-check/node_modules/is-fullwidth-code-point": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", - "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", - "dev": true, + "node_modules/set-function-length": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.0.tgz", + "integrity": "sha512-4DBHDoyHlM1IRPGYcoxexgh67y4ueR53FKV1yyxwFMY7aCqcN/38M1+SwZ/qJQ8iLv7+ck385ot4CcisOAPT9w==", "dependencies": { - "number-is-nan": "^1.0.0" + "define-data-property": "^1.1.1", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.2", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.1" }, "engines": { - "node": ">=0.10.0" + "node": ">= 0.4" } }, - "node_modules/npm-check/node_modules/is-installed-globally": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/is-installed-globally/-/is-installed-globally-0.1.0.tgz", - "integrity": "sha1-Df2Y9akRFxbdU13aZJL2e/PSWoA=", - "dev": true, + "node_modules/set-function-name": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.1.tgz", + "integrity": "sha512-tMNCiqYVkXIZgc2Hnoy2IvC/f8ezc5koaRFkCjrpWzGpCd3qbZXPzVy9MAZzK1ch/X0jvSkojys3oqJN0qCmdA==", "dependencies": { - "global-dirs": "^0.1.0", - "is-path-inside": "^1.0.0" + "define-data-property": "^1.0.1", + "functions-have-names": "^1.2.3", + "has-property-descriptors": "^1.0.0" }, "engines": { - "node": ">=4" + "node": ">= 0.4" } }, - "node_modules/npm-check/node_modules/is-npm": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-npm/-/is-npm-1.0.0.tgz", - "integrity": "sha1-8vtjpl5JBbQGyGBydloaTceTufQ=", - "dev": true, + "node_modules/sfmc-sdk": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/sfmc-sdk/-/sfmc-sdk-3.0.1.tgz", + "integrity": "sha512-y2NwGUm4uuPAtWEKSiI+R4dFg65bXdP4EChRYmHHxnx9e1cOXBuH9166A84MDZC/sDLQ3UBdb1l4VuQ4YLIh0A==", + "license": "BSD-3-Clause", + "dependencies": { + "axios": "^1.7.2", + "fast-xml-parser": "5.4.2", + "p-limit": "5.0.0" + }, "engines": { - "node": ">=0.10.0" + "node": "^20.19.0 || ^22.13.0 || >=24", + "npm": ">=9" } }, - "node_modules/npm-check/node_modules/is-obj": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz", - "integrity": "sha1-PkcprB9f3gJc19g6iW2rn09n2w8=", - "dev": true, + "node_modules/sfmc-sdk/node_modules/p-limit": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-5.0.0.tgz", + "integrity": "sha512-/Eaoq+QyLSiXQ4lyYV23f14mZRQcXnxfHrN0vCai+ak9G0pp9iEQukIIZq5NccEvwRB8PUnZT0KsOoDCINS1qQ==", + "dependencies": { + "yocto-queue": "^1.0.0" + }, "engines": { - "node": ">=0.10.0" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/npm-check/node_modules/is-path-inside": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-1.0.1.tgz", - "integrity": "sha1-jvW33lBDej/cprToZe96pVy0gDY=", + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", "dev": true, "dependencies": { - "path-is-inside": "^1.0.1" + "shebang-regex": "^3.0.0" }, "engines": { - "node": ">=0.10.0" + "node": ">=8" } }, - "node_modules/npm-check/node_modules/latest-version": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/latest-version/-/latest-version-3.1.0.tgz", - "integrity": "sha1-ogU4P+oyKzO1rjsYq+4NwvNW7hU=", + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", "dev": true, - "dependencies": { - "package-json": "^4.0.0" - }, "engines": { - "node": ">=4" + "node": ">=8" } }, - "node_modules/npm-check/node_modules/make-dir": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-1.3.0.tgz", - "integrity": "sha512-2w31R7SJtieJJnQtGc7RVL2StM2vGYVfqUOvUDxH6bC6aJTxPxTF0GnIgCyu7tjockiUWAYQRbxa7vKn34s5sQ==", - "dev": true, + "node_modules/shell-quote": { + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.7.3.tgz", + "integrity": "sha512-Vpfqwm4EnqGdlsBFNmHhxhElJYrdfcxPThu+ryKS5J8L/fhAwLazFZtq+S+TWZ9ANj2piSQLGj6NQg+lKPmxrw==", + "dev": true + }, + "node_modules/side-channel": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", + "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", "dependencies": { - "pify": "^3.0.0" + "call-bind": "^1.0.0", + "get-intrinsic": "^1.0.2", + "object-inspect": "^1.9.0" }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", "engines": { - "node": ">=4" + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/npm-check/node_modules/npm-run-path": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", - "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=", - "dev": true, + "node_modules/simple-git": { + "version": "3.32.3", + "resolved": "https://registry.npmjs.org/simple-git/-/simple-git-3.32.3.tgz", + "integrity": "sha512-56a5oxFdWlsGygOXHWrG+xjj5w9ZIt2uQbzqiIGdR/6i5iococ7WQ/bNPzWxCJdEUGUCmyMH0t9zMpRJTaKxmw==", + "license": "MIT", "dependencies": { - "path-key": "^2.0.0" + "@kwsites/file-exists": "^1.1.1", + "@kwsites/promise-deferred": "^1.1.1", + "debug": "^4.4.0" }, - "engines": { - "node": ">=4" + "funding": { + "type": "github", + "url": "https://github.com/steveukx/git-js?sponsor=1" } }, - "node_modules/npm-check/node_modules/onetime": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-1.1.0.tgz", - "integrity": "sha1-ofeDj4MUxRbwXs78vEzP4EtO14k=", + "node_modules/slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", "dev": true, "engines": { - "node": ">=0.10.0" + "node": ">=8" } }, - "node_modules/npm-check/node_modules/path-exists": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", - "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", + "node_modules/slice-ansi": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-7.1.2.tgz", + "integrity": "sha512-iOBWFgUX7caIZiuutICxVgX1SdxwAVFFKwt1EvMYYec/NWO5meOJ6K5uQxhrYBdQJne4KxiqZc+KptFOWFSI9w==", "dev": true, + "license": "MIT", "dependencies": { - "pinkie-promise": "^2.0.0" + "ansi-styles": "^6.2.1", + "is-fullwidth-code-point": "^5.0.0" }, "engines": { - "node": ">=0.10.0" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/chalk/slice-ansi?sponsor=1" } }, - "node_modules/npm-check/node_modules/restore-cursor": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-1.0.1.tgz", - "integrity": "sha1-NGYfRohjJ/7SmRR5FSJS35LapUE=", + "node_modules/slice-ansi/node_modules/ansi-styles": { + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz", + "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==", "dev": true, - "dependencies": { - "exit-hook": "^1.0.0", - "onetime": "^1.0.0" - }, + "license": "MIT", "engines": { - "node": ">=0.10.0" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/npm-check/node_modules/run-async": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/run-async/-/run-async-0.1.0.tgz", - "integrity": "sha1-yK1KXhEGYeQCp9IbUw4AnyX444k=", + "node_modules/spdx-correct": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.1.tgz", + "integrity": "sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==", "dev": true, "dependencies": { - "once": "^1.3.0" + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" } }, - "node_modules/npm-check/node_modules/semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "node_modules/spdx-exceptions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz", + "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==", + "dev": true + }, + "node_modules/spdx-expression-parse": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", + "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", "dev": true, - "bin": { - "semver": "bin/semver" + "dependencies": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" } }, - "node_modules/npm-check/node_modules/string-width": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", - "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", - "dev": true, + "node_modules/spdx-license-ids": { + "version": "3.0.11", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.11.tgz", + "integrity": "sha512-Ctl2BrFiM0X3MANYgj3CkygxhRmr9mi6xhejbdO960nF6EDJApTYpn0BQnDKlnNBULKiCN1n3w9EBkHK8ZWg+g==", + "dev": true + }, + "node_modules/sql-formatter": { + "version": "15.7.0", + "resolved": "https://registry.npmjs.org/sql-formatter/-/sql-formatter-15.7.0.tgz", + "integrity": "sha512-o2yiy7fYXK1HvzA8P6wwj8QSuwG3e/XcpWht/jIxkQX99c0SVPw0OXdLSV9fHASPiYB09HLA0uq8hokGydi/QA==", + "license": "MIT", "dependencies": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" + "argparse": "^2.0.1", + "nearley": "^2.20.1" }, + "bin": { + "sql-formatter": "bin/sql-formatter-cli.cjs" + } + }, + "node_modules/stack-trace": { + "version": "0.0.10", + "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz", + "integrity": "sha1-VHxws0fo0ytOEI6hoqFZ5f3eGcA=", "engines": { - "node": ">=0.10.0" + "node": "*" } }, - "node_modules/npm-check/node_modules/strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "dev": true, + "node_modules/stop-iteration-iterator": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/stop-iteration-iterator/-/stop-iteration-iterator-1.0.0.tgz", + "integrity": "sha512-iCGQj+0l0HOdZ2AEeBADlsRC+vsnDsZsbdSiH1yNSjcfKM7fdpCMfqAL/dwF5BLiw/XhRft/Wax6zQbhq2BcjQ==", "dependencies": { - "ansi-regex": "^2.0.0" + "internal-slot": "^1.0.4" }, "engines": { - "node": ">=0.10.0" + "node": ">= 0.4" } }, - "node_modules/npm-check/node_modules/supports-color": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, + "node_modules/string-argv": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/string-argv/-/string-argv-0.3.2.tgz", + "integrity": "sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q==", "dev": true, "engines": { - "node": ">=0.8.0" + "node": ">=0.6.19" } }, - "node_modules/npm-check/node_modules/term-size": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/term-size/-/term-size-1.2.0.tgz", - "integrity": "sha1-RYuDiH8oj8Vtb/+/rSYuJmOO+mk=", - "dev": true, + "node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", "dependencies": { - "execa": "^0.7.0" + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" }, "engines": { - "node": ">=4" + "node": ">=8" } }, - "node_modules/npm-check/node_modules/term-size/node_modules/execa": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/execa/-/execa-0.7.0.tgz", - "integrity": "sha1-lEvs00zEHuMqY6n68nrVpl/Fl3c=", + "node_modules/string-width-cjs": { + "name": "string-width", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", "dev": true, "dependencies": { - "cross-spawn": "^5.0.1", - "get-stream": "^3.0.0", - "is-stream": "^1.1.0", - "npm-run-path": "^2.0.0", - "p-finally": "^1.0.0", - "signal-exit": "^3.0.0", - "strip-eof": "^1.0.0" + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" }, "engines": { - "node": ">=4" + "node": ">=8" } }, - "node_modules/npm-check/node_modules/unique-string": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-1.0.0.tgz", - "integrity": "sha1-nhBXzKhRq7kzmPizOuGHuZyuwRo=", + "node_modules/string-width-cjs/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", "dev": true, - "dependencies": { - "crypto-random-string": "^1.0.0" - }, "engines": { - "node": ">=4" + "node": ">=8" } }, - "node_modules/npm-check/node_modules/update-notifier": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/update-notifier/-/update-notifier-2.5.0.tgz", - "integrity": "sha512-gwMdhgJHGuj/+wHJJs9e6PcCszpxR1b236igrOkUofGhqJuG+amlIKwApH1IW1WWl7ovZxsX49lMBWLxSdm5Dw==", - "dev": true, - "dependencies": { - "boxen": "^1.2.1", - "chalk": "^2.0.1", - "configstore": "^3.0.0", - "import-lazy": "^2.1.0", - "is-ci": "^1.0.10", - "is-installed-globally": "^0.1.0", - "is-npm": "^1.0.0", - "latest-version": "^3.0.0", - "semver-diff": "^2.0.0", - "xdg-basedir": "^3.0.0" - }, + "node_modules/string-width/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", "engines": { - "node": ">=4" + "node": ">=8" } }, - "node_modules/npm-check/node_modules/update-notifier/node_modules/ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "node_modules/string.prototype.padend": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/string.prototype.padend/-/string.prototype.padend-3.1.3.tgz", + "integrity": "sha512-jNIIeokznm8SD/TZISQsZKYu7RJyheFNt84DUPrh482GC8RVp2MKqm2O5oBRdGxbDQoXrhhWtPIWQOiy20svUg==", "dev": true, "dependencies": { - "color-convert": "^1.9.0" + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "es-abstract": "^1.19.1" }, "engines": { - "node": ">=4" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/npm-check/node_modules/update-notifier/node_modules/chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "node_modules/string.prototype.trimend": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.4.tgz", + "integrity": "sha512-y9xCjw1P23Awk8EvTpcyL2NIr1j7wJ39f+k6lvRnSMz+mz9CGz9NYPelDk42kOz6+ql8xjfK8oYzy3jAP5QU5A==", "dev": true, "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" + "call-bind": "^1.0.2", + "define-properties": "^1.1.3" }, - "engines": { - "node": ">=4" + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/npm-check/node_modules/update-notifier/node_modules/supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "node_modules/string.prototype.trimstart": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.4.tgz", + "integrity": "sha512-jh6e984OBfvxS50tdY2nRZnoC5/mLFKOREQfw8t5yytkoUsJRNxvI/E39qu1sD0OtWI3OC0XgKSmcWwziwYuZw==", "dev": true, "dependencies": { - "has-flag": "^3.0.0" + "call-bind": "^1.0.2", + "define-properties": "^1.1.3" }, - "engines": { - "node": ">=4" + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/npm-check/node_modules/widest-line": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-2.0.1.tgz", - "integrity": "sha512-Ba5m9/Fa4Xt9eb2ELXt77JxVDV8w7qQrH0zS/TWSJdLyAwQjWoOzpzj5lwVftDz6n/EOu3tNACS84v509qwnJA==", - "dev": true, + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "dependencies": { - "string-width": "^2.1.1" + "ansi-regex": "^5.0.1" }, "engines": { - "node": ">=4" - } - }, - "node_modules/npm-check/node_modules/widest-line/node_modules/ansi-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/npm-check/node_modules/widest-line/node_modules/is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", - "dev": true, - "engines": { - "node": ">=4" + "node": ">=8" } }, - "node_modules/npm-check/node_modules/widest-line/node_modules/string-width": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", - "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "node_modules/strip-ansi-cjs": { + "name": "strip-ansi", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "dev": true, "dependencies": { - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^4.0.0" + "ansi-regex": "^5.0.1" }, "engines": { - "node": ">=4" + "node": ">=8" } }, - "node_modules/npm-check/node_modules/widest-line/node_modules/strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "node_modules/strip-ansi-cjs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", "dev": true, - "dependencies": { - "ansi-regex": "^3.0.0" - }, "engines": { - "node": ">=4" + "node": ">=8" } }, - "node_modules/npm-check/node_modules/write-file-atomic": { - "version": "2.4.3", - "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-2.4.3.tgz", - "integrity": "sha512-GaETH5wwsX+GcnzhPgKcKjJ6M2Cq3/iZp1WyY/X1CSqrW+jVNM9Y7D8EC2sM4ZG/V8wZlSniJnCKWPmBYAucRQ==", - "dev": true, - "dependencies": { - "graceful-fs": "^4.1.11", - "imurmurhash": "^0.1.4", - "signal-exit": "^3.0.2" + "node_modules/strip-ansi/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "engines": { + "node": ">=8" } }, - "node_modules/npm-check/node_modules/xdg-basedir": { + "node_modules/strip-bom": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-3.0.0.tgz", - "integrity": "sha1-SWsswQnsqNus/i3HK2A8F8WHCtQ=", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", "dev": true, "engines": { "node": ">=4" } }, - "node_modules/npm-run-all": { - "version": "4.1.5", - "resolved": "https://registry.npmjs.org/npm-run-all/-/npm-run-all-4.1.5.tgz", - "integrity": "sha512-Oo82gJDAVcaMdi3nuoKFavkIHBRVqQ1qvMb+9LHk/cF4P6B2m8aP04hGf7oL6wZ9BuGwX1onlLhpuoofSyoQDQ==", + "node_modules/strip-indent": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-4.1.1.tgz", + "integrity": "sha512-SlyRoSkdh1dYP0PzclLE7r0M9sgbFKKMFXpFRUMNuKhQSbC6VQIGzq3E0qsfvGJaUFJPGv6Ws1NZ/haTAjfbMA==", "dev": true, - "dependencies": { - "ansi-styles": "^3.2.1", - "chalk": "^2.4.1", - "cross-spawn": "^6.0.5", - "memorystream": "^0.3.1", - "minimatch": "^3.0.4", - "pidtree": "^0.3.0", - "read-pkg": "^3.0.0", - "shell-quote": "^1.6.1", - "string.prototype.padend": "^3.0.0" - }, - "bin": { - "npm-run-all": "bin/npm-run-all/index.js", - "run-p": "bin/run-p/index.js", - "run-s": "bin/run-s/index.js" - }, + "license": "MIT", "engines": { - "node": ">= 4" - } - }, - "node_modules/npm-run-path": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-1.0.0.tgz", - "integrity": "sha1-9cMr9ZX+ga6Sfa7FLoL4sACsPI8=", - "dev": true, - "dependencies": { - "path-key": "^1.0.0" + "node": ">=12" }, - "engines": { - "node": ">=0.10.0" + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/npm-run-path/node_modules/path-key": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-1.0.0.tgz", - "integrity": "sha1-XVPVeAGWRsDWiADbThRua9wqx68=", + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", "dev": true, "engines": { - "node": ">=0.10.0" + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/number-is-nan": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", - "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } + "node_modules/strnum": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/strnum/-/strnum-2.1.2.tgz", + "integrity": "sha512-l63NF9y/cLROq/yqKXSLtcMeeyOfnSQlfMSlzFt/K73oIaD8DGaQWd7Z34X9GPiKqP5rbSh84Hl4bOlLcjiSrQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/NaturalIntelligence" + } + ], + "license": "MIT" }, - "node_modules/oauth-sign": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", - "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==", - "engines": { - "node": "*" - } + "node_modules/stubborn-fs": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/stubborn-fs/-/stubborn-fs-1.2.5.tgz", + "integrity": "sha512-H2N9c26eXjzL/S/K+i/RHHcFanE74dptvvjM8iwzwbVcWY/zjBbgRqF3K0DY4+OD+uTTASTBvDoxPDaPN02D7g==" }, - "node_modules/object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", + "node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/object-get": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/object-get/-/object-get-2.1.1.tgz", - "integrity": "sha512-7n4IpLMzGGcLEMiQKsNR7vCe+N5E9LORFrtNUVy4sO3dj9a3HedZCxEL2T7QuLhcHN1NBuBsMOKaOsAYI9IIvg==", - "dev": true - }, - "node_modules/object-inspect": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.11.1.tgz", - "integrity": "sha512-If7BjFlpkzzBeV1cqgT3OSWT3azyoxDGajR+iGnFBfVV2EWyDyWaZZW2ERDjUaY2QM8i5jI3Sj7mhsM4DDAqWA==", - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=8" } }, - "node_modules/object-keys": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", - "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "dev": true, "engines": { "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/object-to-spawn-args": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/object-to-spawn-args/-/object-to-spawn-args-2.0.1.tgz", - "integrity": "sha512-6FuKFQ39cOID+BMZ3QaphcC8Y4cw6LXBLyIgPU+OhIYwviJamPAn+4mITapnSBQrejB+NNp+FMskhD8Cq+Ys3w==", + "node_modules/synckit": { + "version": "0.11.12", + "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.11.12.tgz", + "integrity": "sha512-Bh7QjT8/SuKUIfObSXNHNSK6WHo6J1tHCqJsuaFDP7gP0fkzSfTxI8y85JrppZ0h8l0maIgc2tfuZQ6/t3GtnQ==", "dev": true, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/object.getownpropertydescriptors": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.0.3.tgz", - "integrity": "sha1-h1jIRvW0B62rDyNuCYbxSwUcqhY=", + "license": "MIT", "dependencies": { - "define-properties": "^1.1.2", - "es-abstract": "^1.5.1" + "@pkgr/core": "^0.2.9" }, "engines": { - "node": ">= 0.8" - } - }, - "node_modules/once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", - "dependencies": { - "wrappy": "1" + "node": "^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/synckit" } }, - "node_modules/one-time": { + "node_modules/tagged-tag": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/one-time/-/one-time-1.0.0.tgz", - "integrity": "sha512-5DXOiRKwuSEcQ/l0kGCF6Q3jcADFv5tSmRaJck/OqkVFcOzutB134KRSfF0xDrL39MNnqxbHBbUUcjZIhTgb2g==", - "dependencies": { - "fn.name": "1.x.x" + "resolved": "https://registry.npmjs.org/tagged-tag/-/tagged-tag-1.0.0.tgz", + "integrity": "sha512-yEFYrVhod+hdNyx7g5Bnkkb0G6si8HJurOoOEgC8B/O0uXLHlaey/65KRv6cuWBNhBgHKAROVpc7QyYqE5gFng==", + "license": "MIT", + "engines": { + "node": ">=20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/onetime": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", - "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "node_modules/test-exclude": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-8.0.0.tgz", + "integrity": "sha512-ZOffsNrXYggvU1mDGHk54I96r26P8SyMjO5slMKSc7+IWmtB/MQKnEC2fP51imB3/pT6YK5cT5E8f+Dd9KdyOQ==", + "dev": true, + "license": "ISC", "dependencies": { - "mimic-fn": "^2.1.0" + "@istanbuljs/schema": "^0.1.2", + "glob": "^13.0.6", + "minimatch": "^10.2.2" }, "engines": { - "node": ">=6" + "node": "20 || >=22" } }, - "node_modules/optionator": { - "version": "0.9.1", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", - "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==", + "node_modules/test-exclude/node_modules/balanced-match": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz", + "integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==", "dev": true, - "dependencies": { - "deep-is": "^0.1.3", - "fast-levenshtein": "^2.0.6", - "levn": "^0.4.1", - "prelude-ls": "^1.2.1", - "type-check": "^0.4.0", - "word-wrap": "^1.2.3" - }, + "license": "MIT", "engines": { - "node": ">= 0.8.0" + "node": "18 || 20 || >=22" } }, - "node_modules/ora": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/ora/-/ora-0.2.3.tgz", - "integrity": "sha1-N1J9Igrc1Tw5tzVx11QVbV22V6Q=", + "node_modules/test-exclude/node_modules/brace-expansion": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.4.tgz", + "integrity": "sha512-h+DEnpVvxmfVefa4jFbCf5HdH5YMDXRsmKflpf1pILZWRFlTbJpxeU55nJl4Smt5HQaGzg1o6RHFPJaOqnmBDg==", "dev": true, + "license": "MIT", "dependencies": { - "chalk": "^1.1.1", - "cli-cursor": "^1.0.2", - "cli-spinners": "^0.1.2", - "object-assign": "^4.0.1" + "balanced-match": "^4.0.2" }, "engines": { - "node": ">=0.10.0" + "node": "18 || 20 || >=22" } }, - "node_modules/ora/node_modules/ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "node_modules/test-exclude/node_modules/glob": { + "version": "13.0.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-13.0.6.tgz", + "integrity": "sha512-Wjlyrolmm8uDpm/ogGyXZXb1Z+Ca2B8NbJwqBVg0axK9GbBeoS7yGV6vjXnYdGm6X53iehEuxxbyiKp8QmN4Vw==", "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "minimatch": "^10.2.2", + "minipass": "^7.1.3", + "path-scurry": "^2.0.2" + }, "engines": { - "node": ">=0.10.0" + "node": "18 || 20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/ora/node_modules/ansi-styles": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "node_modules/test-exclude/node_modules/lru-cache": { + "version": "11.2.6", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.2.6.tgz", + "integrity": "sha512-ESL2CrkS/2wTPfuend7Zhkzo2u0daGJ/A2VucJOgQ/C48S/zB8MMeMHSGKYpXhIjbPxfuezITkaBH1wqv00DDQ==", "dev": true, + "license": "BlueOak-1.0.0", "engines": { - "node": ">=0.10.0" + "node": "20 || >=22" } }, - "node_modules/ora/node_modules/chalk": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "node_modules/test-exclude/node_modules/minimatch": { + "version": "10.2.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.4.tgz", + "integrity": "sha512-oRjTw/97aTBN0RHbYCdtF1MQfvusSIBQM0IZEgzl6426+8jSC0nF1a/GmnVLpfB9yyr6g6FTqWqiZVbxrtaCIg==", "dev": true, + "license": "BlueOak-1.0.0", "dependencies": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" + "brace-expansion": "^5.0.2" }, "engines": { - "node": ">=0.10.0" + "node": "18 || 20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/ora/node_modules/cli-cursor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-1.0.2.tgz", - "integrity": "sha1-ZNo/fValRBLll5S9Ytw1KV6PKYc=", + "node_modules/test-exclude/node_modules/path-scurry": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-2.0.2.tgz", + "integrity": "sha512-3O/iVVsJAPsOnpwWIeD+d6z/7PmqApyQePUtCndjatj/9I5LylHvt5qluFaBT3I5h3r1ejfR056c+FCv+NnNXg==", "dev": true, + "license": "BlueOak-1.0.0", "dependencies": { - "restore-cursor": "^1.0.1" + "lru-cache": "^11.0.0", + "minipass": "^7.1.2" }, "engines": { - "node": ">=0.10.0" + "node": "18 || 20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/ora/node_modules/onetime": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-1.1.0.tgz", - "integrity": "sha1-ofeDj4MUxRbwXs78vEzP4EtO14k=", + "node_modules/text-hex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/text-hex/-/text-hex-1.0.0.tgz", + "integrity": "sha512-uuVGNWzgJ4yhRaNSiubPY7OjISw4sw4E5Uv0wbjp+OzcbmVU/rsT8ujgcXJhn9ypzsgr5vlzpPqP+MBBKcGvbg==", + "license": "MIT" + }, + "node_modules/text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", + "dev": true + }, + "node_modules/tinyexec": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-1.0.2.tgz", + "integrity": "sha512-W/KYk+NFhkmsYpuHq5JykngiOCnxeVL8v8dFnqxSD8qEEdRfXk1SDM6JzNqcERbcGYj9tMrDQBYV9cjgnunFIg==", "dev": true, + "license": "MIT", "engines": { - "node": ">=0.10.0" + "node": ">=18" } }, - "node_modules/ora/node_modules/restore-cursor": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-1.0.1.tgz", - "integrity": "sha1-NGYfRohjJ/7SmRR5FSJS35LapUE=", + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", "dev": true, "dependencies": { - "exit-hook": "^1.0.0", - "onetime": "^1.0.0" + "is-number": "^7.0.0" }, "engines": { - "node": ">=0.10.0" + "node": ">=8.0" } }, - "node_modules/ora/node_modules/strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "node_modules/to-valid-identifier": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/to-valid-identifier/-/to-valid-identifier-1.0.0.tgz", + "integrity": "sha512-41wJyvKep3yT2tyPqX/4blcfybknGB4D+oETKLs7Q76UiPqRpUJK3hr1nxelyYO0PHKVzJwlu0aCeEAsGI6rpw==", "dev": true, + "license": "MIT", "dependencies": { - "ansi-regex": "^2.0.0" + "@sindresorhus/base62": "^1.0.0", + "reserved-identifiers": "^1.0.0" }, "engines": { - "node": ">=0.10.0" + "node": ">=20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/ora/node_modules/supports-color": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", - "dev": true, - "engines": { - "node": ">=0.8.0" - } + "node_modules/toposort": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/toposort/-/toposort-2.0.2.tgz", + "integrity": "sha1-riF2gXXRVZ1IvvNUILL0li8JwzA=" }, - "node_modules/os-tmpdir": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", - "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", - "engines": { - "node": ">=0.10.0" - } + "node_modules/traverse": { + "version": "0.6.6", + "resolved": "https://registry.npmjs.org/traverse/-/traverse-0.6.6.tgz", + "integrity": "sha1-y99WD9e5r2MlAv7UD5GMFX6pcTc=" }, - "node_modules/p-cancelable": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-1.1.0.tgz", - "integrity": "sha512-s73XxOZ4zpt1edZYZzvhqFa6uvQc1vwUa0K0BdtIZgQMAJj9IbebH+JkgKZc9h+B05PKHLOTl4ajG1BmNrVZlw==", + "node_modules/triple-beam": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/triple-beam/-/triple-beam-1.4.1.tgz", + "integrity": "sha512-aZbgViZrg1QNcG+LULa7nhZpJTZSLm/mXnHXnbAbjmN5aSa0y7V+wvv6+4WaBtpISJzThKy+PIPxc1Nq1EJ9mg==", "engines": { - "node": ">=6" + "node": ">= 14.0.0" } }, - "node_modules/p-finally": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", - "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=", + "node_modules/ts-api-utils": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.3.0.tgz", + "integrity": "sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ==", "dev": true, "engines": { - "node": ">=4" - } - }, - "node_modules/p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dev": true, - "dependencies": { - "p-try": "^2.0.0" + "node": ">=16" }, - "engines": { - "node": ">=6" + "peerDependencies": { + "typescript": ">=4.2.0" } }, - "node_modules/p-locate": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", - "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD" + }, + "node_modules/type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", "dev": true, "dependencies": { - "p-limit": "^2.0.0" + "prelude-ls": "^1.2.1" }, "engines": { - "node": ">=6" + "node": ">= 0.8.0" } }, - "node_modules/p-map": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", - "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", + "node_modules/type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", "dev": true, - "dependencies": { - "aggregate-error": "^3.0.0" - }, "engines": { "node": ">=10" }, @@ -6503,9173 +7250,633 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/p-try": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "node_modules/typescript": { + "version": "5.9.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", + "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", "dev": true, + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, "engines": { - "node": ">=6" + "node": ">=14.17" } }, - "node_modules/package-json": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/package-json/-/package-json-4.0.1.tgz", - "integrity": "sha1-iGmgQBJTZhxMTKPabCEh7VVfXu0=", + "node_modules/uint8array-extras": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/uint8array-extras/-/uint8array-extras-1.5.0.tgz", + "integrity": "sha512-rvKSBiC5zqCCiDZ9kAOszZcDvdAHwwIKJG33Ykj43OKcWsnmcBRL09YTU4nOeHZ8Y2a7l1MgTd08SBe9A8Qj6A==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/unbox-primitive": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", + "integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==", "dev": true, "dependencies": { - "got": "^6.7.1", - "registry-auth-token": "^3.0.1", - "registry-url": "^3.0.3", - "semver": "^5.1.0" + "call-bind": "^1.0.2", + "has-bigints": "^1.0.2", + "has-symbols": "^1.0.3", + "which-boxed-primitive": "^1.0.2" }, - "engines": { - "node": ">=4" + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/package-json/node_modules/semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true, - "bin": { - "semver": "bin/semver" + "node_modules/undici-types": { + "version": "7.18.2", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.18.2.tgz", + "integrity": "sha512-AsuCzffGHJybSaRrmr5eHr81mwJU3kjw6M+uprWvCXiNeN9SOGwQ3Jn8jb8m3Z6izVgknn1R0FTCEAP2QrLY/w==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/universalify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", + "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", + "engines": { + "node": ">= 10.0.0" } }, - "node_modules/parent-module": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", - "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "node_modules/update-browserslist-db": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.2.3.tgz", + "integrity": "sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==", "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", "dependencies": { - "callsites": "^3.0.0" + "escalade": "^3.2.0", + "picocolors": "^1.1.1" }, - "engines": { - "node": ">=6" + "bin": { + "update-browserslist-db": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" } }, - "node_modules/parse-json": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", - "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=", - "dev": true, + "node_modules/update-notifier": { + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/update-notifier/-/update-notifier-7.3.1.tgz", + "integrity": "sha512-+dwUY4L35XFYEzE+OAL3sarJdUioVovq+8f7lcIJ7wnmnYQV5UD1Y/lcwaMSyaQ6Bj3JMj1XSTjZbNLHn/19yA==", "dependencies": { - "error-ex": "^1.3.1", - "json-parse-better-errors": "^1.0.1" + "boxen": "^8.0.1", + "chalk": "^5.3.0", + "configstore": "^7.0.0", + "is-in-ci": "^1.0.0", + "is-installed-globally": "^1.0.0", + "is-npm": "^6.0.0", + "latest-version": "^9.0.0", + "pupa": "^3.1.0", + "semver": "^7.6.3", + "xdg-basedir": "^5.1.0" }, "engines": { - "node": ">=4" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/yeoman/update-notifier?sponsor=1" } }, - "node_modules/parse-passwd": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz", - "integrity": "sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY=", - "dev": true, + "node_modules/update-notifier/node_modules/chalk": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.3.0.tgz", + "integrity": "sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==", "engines": { - "node": ">=0.10.0" + "node": "^12.17.0 || ^14.13 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/path-exists": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", "dev": true, - "engines": { - "node": ">=4" + "dependencies": { + "punycode": "^2.1.0" } }, - "node_modules/path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "node_modules/util": { + "version": "0.12.5", + "resolved": "https://registry.npmjs.org/util/-/util-0.12.5.tgz", + "integrity": "sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA==", "dev": true, - "engines": { - "node": ">=0.10.0" + "dependencies": { + "inherits": "^2.0.3", + "is-arguments": "^1.0.4", + "is-generator-function": "^1.0.7", + "is-typed-array": "^1.1.3", + "which-typed-array": "^1.1.2" } }, - "node_modules/path-is-inside": { + "node_modules/util-deprecate": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz", - "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=", - "dev": true - }, - "node_modules/path-key": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", - "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/path-parse": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", - "dev": true + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" }, - "node_modules/path-type": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz", - "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==", + "node_modules/v8-to-istanbul": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.1.0.tgz", + "integrity": "sha512-6z3GW9x8G1gd+JIIgQQQxXuiJtCXeAjp6RaPEPLv62mH3iPHPxV6W3robxtCzNErRo6ZwTmzWhsbNvjyEBKzKA==", "dev": true, "dependencies": { - "pify": "^3.0.0" + "@jridgewell/trace-mapping": "^0.3.12", + "@types/istanbul-lib-coverage": "^2.0.1", + "convert-source-map": "^1.6.0" }, "engines": { - "node": ">=4" + "node": ">=10.12.0" } }, - "node_modules/pathval": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.1.tgz", - "integrity": "sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==", + "node_modules/validate-npm-package-license": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", + "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", "dev": true, - "engines": { - "node": "*" + "dependencies": { + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" } }, - "node_modules/performance-now": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", - "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=" - }, - "node_modules/picomatch": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.0.tgz", - "integrity": "sha512-lY1Q/PiJGC2zOv/z391WOTD+Z02bCgsFfvxoXXf6h7kv9o+WmsmzYqrAwY63sNgOxE4xEdq0WyUnXfKeBrSvYw==", + "node_modules/vue-eslint-parser": { + "version": "9.4.3", + "resolved": "https://registry.npmjs.org/vue-eslint-parser/-/vue-eslint-parser-9.4.3.tgz", + "integrity": "sha512-2rYRLWlIpaiN8xbPiDyXZXRgLGOtWxERV7ND5fFAv5qo1D2N9Fu9MNajBNc6o13lZ+24DAWCkQCvj4klgmcITg==", "dev": true, + "license": "MIT", + "dependencies": { + "debug": "^4.3.4", + "eslint-scope": "^7.1.1", + "eslint-visitor-keys": "^3.3.0", + "espree": "^9.3.1", + "esquery": "^1.4.0", + "lodash": "^4.17.21", + "semver": "^7.3.6" + }, "engines": { - "node": ">=8.6" + "node": "^14.17.0 || >=16.0.0" }, "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/pidtree": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/pidtree/-/pidtree-0.3.0.tgz", - "integrity": "sha512-9CT4NFlDcosssyg8KVFltgokyKZIFjoBxw8CTGy+5F38Y1eQWrt8tRayiUOXE+zVKQnYu5BR8JjCtvK3BcnBhg==", - "dev": true, - "bin": { - "pidtree": "bin/pidtree.js" + "url": "https://github.com/sponsors/mysticatea" }, - "engines": { - "node": ">=0.10" + "peerDependencies": { + "eslint": ">=6.0.0" } }, - "node_modules/pify": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", - "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", - "dev": true, - "engines": { - "node": ">=4" + "node_modules/wcwidth": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz", + "integrity": "sha1-8LDc+RW8X/FSivrbLA4XtTLaL+g=", + "optional": true, + "dependencies": { + "defaults": "^1.0.3" } }, - "node_modules/pinkie": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", - "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } + "node_modules/when-exit": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/when-exit/-/when-exit-2.1.2.tgz", + "integrity": "sha512-u9J+toaf3CCxCAzM/484qNAxQE75rFdVgiFEEV8Xps2gzYhf0tx73s1WXDQhkwV17E3MxRMz40m7Ekd2/121Lg==" }, - "node_modules/pinkie-promise": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", - "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", "dev": true, "dependencies": { - "pinkie": "^2.0.0" + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" }, "engines": { - "node": ">=0.10.0" + "node": ">= 8" } }, - "node_modules/pkg-dir": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-1.0.0.tgz", - "integrity": "sha1-ektQio1bstYp1EcFb/TpyTFM89Q=", - "dev": true, + "node_modules/which-boxed-primitive": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", + "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", "dependencies": { - "find-up": "^1.0.0" + "is-bigint": "^1.0.1", + "is-boolean-object": "^1.1.0", + "is-number-object": "^1.0.4", + "is-string": "^1.0.5", + "is-symbol": "^1.0.3" }, - "engines": { - "node": ">=0.10.0" + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/pkg-dir/node_modules/find-up": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", - "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", - "dev": true, + "node_modules/which-collection": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.1.tgz", + "integrity": "sha512-W8xeTUwaln8i3K/cY1nGXzdnVZlidBcagyNFtBdD5kxnb4TvGKR7FfSIS3mYpwWS1QUCutfKz8IY8RjftB0+1A==", "dependencies": { - "path-exists": "^2.0.0", - "pinkie-promise": "^2.0.0" + "is-map": "^2.0.1", + "is-set": "^2.0.1", + "is-weakmap": "^2.0.1", + "is-weakset": "^2.0.1" }, - "engines": { - "node": ">=0.10.0" + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/pkg-dir/node_modules/path-exists": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", - "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", - "dev": true, + "node_modules/which-typed-array": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.13.tgz", + "integrity": "sha512-P5Nra0qjSncduVPEAr7xhoF5guty49ArDTwzJ/yNuPIbZppyRxFQsRCWrocxIY+CnMVG+qfbU2FmDKyvSGClow==", "dependencies": { - "pinkie-promise": "^2.0.0" + "available-typed-arrays": "^1.0.5", + "call-bind": "^1.0.4", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-tostringtag": "^1.0.0" }, "engines": { - "node": ">=0.10.0" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/please-upgrade-node": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/please-upgrade-node/-/please-upgrade-node-3.2.0.tgz", - "integrity": "sha512-gQR3WpIgNIKwBMVLkpMUeR3e1/E1y42bqDQZfql+kDeXd8COYfM8PQA4X6y7a8u9Ua9FHmsrrmirW2vHs45hWg==", - "dev": true, + "node_modules/widest-line": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-5.0.0.tgz", + "integrity": "sha512-c9bZp7b5YtRj2wOe6dlj32MK+Bx/M/d+9VB2SHM1OtsUHR0aV0tdP6DWh/iMt0kWi1t5g1Iudu6hQRNd1A4PVA==", "dependencies": { - "semver-compare": "^1.0.0" + "string-width": "^7.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/preferred-pm": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/preferred-pm/-/preferred-pm-1.0.1.tgz", - "integrity": "sha512-9Uxgin5Xnsl67DBvlNFsmDIlBuG9/XKK2cVBTj//7/7wW6ZY+IC9/GlLqxyHABpoasAsJ1MARFOdYPxMUtndxA==", - "dev": true, + "node_modules/widest-line/node_modules/emoji-regex": { + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.3.0.tgz", + "integrity": "sha512-QpLs9D9v9kArv4lfDEgg1X/gN5XLnf/A6l9cs8SPZLRZR3ZkY9+kwIQTxm+fsSej5UMYGE8fdoaZVIBlqG0XTw==" + }, + "node_modules/widest-line/node_modules/string-width": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz", + "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", "dependencies": { - "path-exists": "^3.0.0", - "which-pm": "^1.0.1" + "emoji-regex": "^10.3.0", + "get-east-asian-width": "^1.0.0", + "strip-ansi": "^7.1.0" }, "engines": { - "node": ">=4" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/prelude-ls": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", - "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", - "dev": true, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/prepend-http": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-1.0.4.tgz", - "integrity": "sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw=", - "dev": true, + "node_modules/widest-line/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dependencies": { + "ansi-regex": "^6.0.1" + }, "engines": { - "node": ">=0.10.0" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" } }, - "node_modules/prettier": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.5.1.tgz", - "integrity": "sha512-vBZcPRUR5MZJwoyi3ZoyQlc1rXeEck8KgeC9AwwOn+exuxLxq5toTRDTSaVrXHxelDMHy9zlicw8u66yxoSUFg==", - "bin": { - "prettier": "bin-prettier.js" + "node_modules/winston": { + "version": "3.19.0", + "resolved": "https://registry.npmjs.org/winston/-/winston-3.19.0.tgz", + "integrity": "sha512-LZNJgPzfKR+/J3cHkxcpHKpKKvGfDZVPS4hfJCc4cCG0CgYzvlD6yE/S3CIL/Yt91ak327YCpiF/0MyeZHEHKA==", + "license": "MIT", + "dependencies": { + "@colors/colors": "^1.6.0", + "@dabh/diagnostics": "^2.0.8", + "async": "^3.2.3", + "is-stream": "^2.0.0", + "logform": "^2.7.0", + "one-time": "^1.0.0", + "readable-stream": "^3.4.0", + "safe-stable-stringify": "^2.3.1", + "stack-trace": "0.0.x", + "triple-beam": "^1.3.0", + "winston-transport": "^4.9.0" }, "engines": { - "node": ">=10.13.0" + "node": ">= 12.0.0" } }, - "node_modules/prettier-linter-helpers": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz", - "integrity": "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==", - "dev": true, + "node_modules/winston-transport": { + "version": "4.9.0", + "resolved": "https://registry.npmjs.org/winston-transport/-/winston-transport-4.9.0.tgz", + "integrity": "sha512-8drMJ4rkgaPo1Me4zD/3WLfI/zPdA9o2IipKODunnGDcuqbHwjsbB79ylv04LCGGzU0xQ6vTznOMpQGaLhhm6A==", "dependencies": { - "fast-diff": "^1.1.2" + "logform": "^2.7.0", + "readable-stream": "^3.6.2", + "triple-beam": "^1.3.0" }, "engines": { - "node": ">=6.0.0" + "node": ">= 12.0.0" } }, - "node_modules/progress": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", - "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", + "node_modules/workerpool": { + "version": "9.3.4", + "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-9.3.4.tgz", + "integrity": "sha512-TmPRQYYSAnnDiEB0P/Ytip7bFGvqnSU6I2BcuSw7Hx+JSg/DsUi5ebYfc8GYaSdpuvOcEs6dXxPurOYpe9QFwg==", "dev": true, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/pseudomap": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", - "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=", - "dev": true - }, - "node_modules/psl": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/psl/-/psl-1.4.0.tgz", - "integrity": "sha512-HZzqCGPecFLyoRj5HLfuDSKYTJkAfB5thKBIkRHtGjWwY7p1dAyveIbXIq4tO0KYfDF2tHqPUgY9SDnGm00uFw==" + "license": "Apache-2.0" }, - "node_modules/pump": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", - "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "node_modules/wrap-ansi": { + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-9.0.2.tgz", + "integrity": "sha512-42AtmgqjV+X1VpdOfyTGOYRi0/zsoLqtXQckTmqTeybT+BDIbM/Guxo7x3pE2vtpr1ok6xRqM9OpBe+Jyoqyww==", + "license": "MIT", "dependencies": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" - } - }, - "node_modules/punycode": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", - "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", + "ansi-styles": "^6.2.1", + "string-width": "^7.0.0", + "strip-ansi": "^7.1.0" + }, "engines": { - "node": ">=6" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, - "node_modules/pupa": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/pupa/-/pupa-2.1.1.tgz", - "integrity": "sha512-l1jNAspIBSFqbT+y+5FosojNpVpF94nlI+wDUpqP9enwOTfHx9f0gh5nB96vl+6yTpsJsypeNrwfzPrKuHB41A==", + "node_modules/wrap-ansi-cjs": { + "name": "wrap-ansi", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, "dependencies": { - "escape-goat": "^2.0.0" + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" }, "engines": { - "node": ">=8" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, - "node_modules/qs": { - "version": "6.5.2", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", - "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==", + "node_modules/wrap-ansi/node_modules/ansi-styles": { + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz", + "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==", + "license": "MIT", "engines": { - "node": ">=0.6" - } - }, - "node_modules/ramda": { - "version": "0.27.1", - "resolved": "https://registry.npmjs.org/ramda/-/ramda-0.27.1.tgz", - "integrity": "sha512-PgIdVpn5y5Yns8vqb8FzBUEYn98V3xcPgawAkkgj0YJ0qDsnHCiNmZYfOGMgOvoB0eWFLpYbhxUR3mxfDIMvpw==", - "dev": true - }, - "node_modules/randombytes": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", - "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", - "dev": true, - "dependencies": { - "safe-buffer": "^5.1.0" - } - }, - "node_modules/rc": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", - "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", - "dependencies": { - "deep-extend": "^0.6.0", - "ini": "~1.3.0", - "minimist": "^1.2.0", - "strip-json-comments": "~2.0.1" + "node": ">=12" }, - "bin": { - "rc": "cli.js" + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/read-pkg": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz", - "integrity": "sha1-nLxoaXj+5l0WwA4rGcI3/Pbjg4k=", - "dev": true, - "dependencies": { - "load-json-file": "^4.0.0", - "normalize-package-data": "^2.3.2", - "path-type": "^3.0.0" - }, - "engines": { - "node": ">=4" - } + "node_modules/wrap-ansi/node_modules/emoji-regex": { + "version": "10.6.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.6.0.tgz", + "integrity": "sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A==", + "license": "MIT" }, - "node_modules/read-pkg-up": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz", - "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=", - "dev": true, + "node_modules/wrap-ansi/node_modules/string-width": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz", + "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", + "license": "MIT", "dependencies": { - "find-up": "^1.0.0", - "read-pkg": "^1.0.0" + "emoji-regex": "^10.3.0", + "get-east-asian-width": "^1.0.0", + "strip-ansi": "^7.1.0" }, "engines": { - "node": ">=0.10.0" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/read-pkg-up/node_modules/find-up": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", - "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", - "dev": true, + "node_modules/wrap-ansi/node_modules/strip-ansi": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.2.tgz", + "integrity": "sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA==", + "license": "MIT", "dependencies": { - "path-exists": "^2.0.0", - "pinkie-promise": "^2.0.0" + "ansi-regex": "^6.0.1" }, "engines": { - "node": ">=0.10.0" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" } }, - "node_modules/read-pkg-up/node_modules/load-json-file": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", - "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", - "dev": true, - "dependencies": { - "graceful-fs": "^4.1.2", - "parse-json": "^2.2.0", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0", - "strip-bom": "^2.0.0" - }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "dev": true + }, + "node_modules/xdg-basedir": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-5.1.0.tgz", + "integrity": "sha512-GCPAHLvrIH13+c0SuacwvRYj2SxJXQ4kaVTT5xgL3kPrz56XxkF21IGhjSE1+W0aw7gpBWRGXLCPnPby6lSpmQ==", "engines": { - "node": ">=0.10.0" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/read-pkg-up/node_modules/parse-json": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", - "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", - "dev": true, - "dependencies": { - "error-ex": "^1.2.0" - }, + "node_modules/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", "engines": { - "node": ">=0.10.0" + "node": ">=10" } }, - "node_modules/read-pkg-up/node_modules/path-exists": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", - "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", + "node_modules/yaml": { + "version": "2.8.2", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.8.2.tgz", + "integrity": "sha512-mplynKqc1C2hTVYxd0PU2xQAc22TI1vShAYGksCCfxbn/dFwnHTNi1bvYsBTkhdUNtGIf5xNOg938rrSSYvS9A==", "dev": true, - "dependencies": { - "pinkie-promise": "^2.0.0" + "license": "ISC", + "bin": { + "yaml": "bin.mjs" }, "engines": { - "node": ">=0.10.0" + "node": ">= 14.6" + }, + "funding": { + "url": "https://github.com/sponsors/eemeli" } }, - "node_modules/read-pkg-up/node_modules/path-type": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", - "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=", - "dev": true, + "node_modules/yargs": { + "version": "18.0.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-18.0.0.tgz", + "integrity": "sha512-4UEqdc2RYGHZc7Doyqkrqiln3p9X2DZVxaGbwhn2pi7MrRagKaOcIKe8L3OxYcbhXLgLFUS3zAYuQjKBQgmuNg==", + "license": "MIT", "dependencies": { - "graceful-fs": "^4.1.2", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0" + "cliui": "^9.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "string-width": "^7.2.0", + "y18n": "^5.0.5", + "yargs-parser": "^22.0.0" }, "engines": { - "node": ">=0.10.0" + "node": "^20.19.0 || ^22.12.0 || >=23" } }, - "node_modules/read-pkg-up/node_modules/pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "node_modules/yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", "dev": true, "engines": { - "node": ">=0.10.0" + "node": ">=12" } }, - "node_modules/read-pkg-up/node_modules/read-pkg": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", - "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=", + "node_modules/yargs-unparser": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-2.0.0.tgz", + "integrity": "sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==", "dev": true, "dependencies": { - "load-json-file": "^1.0.0", - "normalize-package-data": "^2.3.2", - "path-type": "^1.0.0" + "camelcase": "^6.0.0", + "decamelize": "^4.0.0", + "flat": "^5.0.2", + "is-plain-obj": "^2.1.0" }, "engines": { - "node": ">=0.10.0" + "node": ">=10" } }, - "node_modules/read-pkg-up/node_modules/strip-bom": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", - "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", + "node_modules/yargs-unparser/node_modules/decamelize": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz", + "integrity": "sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==", "dev": true, - "dependencies": { - "is-utf8": "^0.2.0" - }, "engines": { - "node": ">=0.10.0" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/readable-stream": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", - "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "node_modules/yargs/node_modules/emoji-regex": { + "version": "10.6.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.6.0.tgz", + "integrity": "sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A==", + "license": "MIT" + }, + "node_modules/yargs/node_modules/string-width": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz", + "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", + "license": "MIT", "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" + "emoji-regex": "^10.3.0", + "get-east-asian-width": "^1.0.0", + "strip-ansi": "^7.1.0" }, "engines": { - "node": ">= 6" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/readdirp": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", - "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", - "dev": true, + "node_modules/yargs/node_modules/strip-ansi": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.2.tgz", + "integrity": "sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA==", + "license": "MIT", "dependencies": { - "picomatch": "^2.2.1" + "ansi-regex": "^6.0.1" }, "engines": { - "node": ">=8.10.0" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" } }, - "node_modules/readline2": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/readline2/-/readline2-1.0.1.tgz", - "integrity": "sha1-QQWWCP/BVHV7cV2ZidGZ/783LjU=", - "dev": true, - "dependencies": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "mute-stream": "0.0.5" + "node_modules/yargs/node_modules/yargs-parser": { + "version": "22.0.0", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-22.0.0.tgz", + "integrity": "sha512-rwu/ClNdSMpkSrUb+d6BRsSkLUq1fmfsY6TOpYzTwvwkg1/NRG85KBy3kq++A8LKQwX6lsu+aWad+2khvuXrqw==", + "license": "ISC", + "engines": { + "node": "^20.19.0 || ^22.12.0 || >=23" } }, - "node_modules/readline2/node_modules/is-fullwidth-code-point": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", - "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", - "dev": true, - "dependencies": { - "number-is-nan": "^1.0.0" - }, + "node_modules/yocto-queue": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-1.2.2.tgz", + "integrity": "sha512-4LCcse/U2MHZ63HAJVE+v71o7yOdIe4cZ70Wpf8D/IyjDKYQLV5GD46B+hSTjJsvV5PztjvHoU580EftxjDZFQ==", + "license": "MIT", "engines": { - "node": ">=0.10.0" + "node": ">=12.20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/readline2/node_modules/mute-stream": { - "version": "0.0.5", - "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.5.tgz", - "integrity": "sha1-j7+rsKmKJT0xhDMfno3rc3L6xsA=", - "dev": true - }, - "node_modules/redent": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/redent/-/redent-1.0.0.tgz", - "integrity": "sha1-z5Fqsf1fHxbfsggi3W7H9zDCr94=", - "dev": true, + "node_modules/yocto-spinner": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/yocto-spinner/-/yocto-spinner-1.1.0.tgz", + "integrity": "sha512-/BY0AUXnS7IKO354uLLA2eRcWiqDifEbd6unXCsOxkFDAkhgUL3PH9X2bFoaU0YchnDXsF+iKleeTLJGckbXfA==", + "license": "MIT", "dependencies": { - "indent-string": "^2.1.0", - "strip-indent": "^1.0.1" + "yoctocolors": "^2.1.1" }, "engines": { - "node": ">=0.10.0" + "node": ">=18.19" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/reduce-extract": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/reduce-extract/-/reduce-extract-1.0.0.tgz", - "integrity": "sha1-Z/I4W+2mUGG19fQxJmLosIDKFSU=", - "dev": true, - "dependencies": { - "test-value": "^1.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/reduce-extract/node_modules/array-back": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/array-back/-/array-back-1.0.4.tgz", - "integrity": "sha1-ZEun8JX3/898Q7Xw3DnTwfA8Bjs=", - "dev": true, - "dependencies": { - "typical": "^2.6.0" - }, - "engines": { - "node": ">=0.12.0" - } - }, - "node_modules/reduce-extract/node_modules/test-value": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/test-value/-/test-value-1.1.0.tgz", - "integrity": "sha1-oJE29y7AQ9J8iTcHwrFZv6196T8=", - "dev": true, - "dependencies": { - "array-back": "^1.0.2", - "typical": "^2.4.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/reduce-flatten": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/reduce-flatten/-/reduce-flatten-1.0.1.tgz", - "integrity": "sha1-JYx479FT3fk8tWEjf2EYTzaW4yc=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/reduce-unique": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/reduce-unique/-/reduce-unique-2.0.1.tgz", - "integrity": "sha512-x4jH/8L1eyZGR785WY+ePtyMNhycl1N2XOLxhCbzZFaqF4AXjLzqSxa2UHgJ2ZVR/HHyPOvl1L7xRnW8ye5MdA==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/reduce-without": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/reduce-without/-/reduce-without-1.0.1.tgz", - "integrity": "sha1-aK0OrRGFXJo31OglbBW7+Hly/Iw=", - "dev": true, - "dependencies": { - "test-value": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/reduce-without/node_modules/array-back": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/array-back/-/array-back-1.0.4.tgz", - "integrity": "sha1-ZEun8JX3/898Q7Xw3DnTwfA8Bjs=", - "dev": true, - "dependencies": { - "typical": "^2.6.0" - }, - "engines": { - "node": ">=0.12.0" - } - }, - "node_modules/reduce-without/node_modules/test-value": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/test-value/-/test-value-2.1.0.tgz", - "integrity": "sha1-Edpv9nDzRxpztiXKTz/c97t0gpE=", - "dev": true, - "dependencies": { - "array-back": "^1.0.3", - "typical": "^2.6.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/regenerator-runtime": { - "version": "0.11.1", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz", - "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==", - "dev": true - }, - "node_modules/regexpp": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz", - "integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==", - "dev": true, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/mysticatea" - } - }, - "node_modules/registry-auth-token": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-3.4.0.tgz", - "integrity": "sha512-4LM6Fw8eBQdwMYcES4yTnn2TqIasbXuwDx3um+QRs7S55aMKCBKBxvPXl2RiUjHwuJLTyYfxSpmfSAjQpcuP+A==", - "dev": true, - "dependencies": { - "rc": "^1.1.6", - "safe-buffer": "^5.0.1" - } - }, - "node_modules/registry-url": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/registry-url/-/registry-url-3.1.0.tgz", - "integrity": "sha1-PU74cPc93h138M+aOBQyRE4XSUI=", - "dev": true, - "dependencies": { - "rc": "^1.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/repeating": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/repeating/-/repeating-2.0.1.tgz", - "integrity": "sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo=", - "dev": true, - "dependencies": { - "is-finite": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/request": { - "version": "2.88.0", - "resolved": "https://registry.npmjs.org/request/-/request-2.88.0.tgz", - "integrity": "sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg==", - "dependencies": { - "aws-sign2": "~0.7.0", - "aws4": "^1.8.0", - "caseless": "~0.12.0", - "combined-stream": "~1.0.6", - "extend": "~3.0.2", - "forever-agent": "~0.6.1", - "form-data": "~2.3.2", - "har-validator": "~5.1.0", - "http-signature": "~1.2.0", - "is-typedarray": "~1.0.0", - "isstream": "~0.1.2", - "json-stringify-safe": "~5.0.1", - "mime-types": "~2.1.19", - "oauth-sign": "~0.9.0", - "performance-now": "^2.1.0", - "qs": "~6.5.2", - "safe-buffer": "^5.1.2", - "tough-cookie": "~2.4.3", - "tunnel-agent": "^0.6.0", - "uuid": "^3.3.2" - }, - "engines": { - "node": ">= 4" - } - }, - "node_modules/require-directory": { + "node_modules/yoctocolors": { "version": "2.1.1", - "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/require-main-filename": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", - "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", - "dev": true - }, - "node_modules/require-package-name": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/require-package-name/-/require-package-name-2.0.1.tgz", - "integrity": "sha1-wR6XJ2tluOKSP3Xav1+y7ww4Qbk=", - "dev": true - }, - "node_modules/requizzle": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/requizzle/-/requizzle-0.2.3.tgz", - "integrity": "sha512-YanoyJjykPxGHii0fZP0uUPEXpvqfBDxWV7s6GKAiiOsiqhX6vHNyW3Qzdmqp/iq/ExbhaGbVrjB4ruEVSM4GQ==", - "dev": true, - "dependencies": { - "lodash": "^4.17.14" - } - }, - "node_modules/resolve": { - "version": "1.12.0", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.12.0.tgz", - "integrity": "sha512-B/dOmuoAik5bKcD6s6nXDCjzUKnaDvdkRyAk6rsmsKLipWj4797iothd7jmmUhWTfinVMU+wc56rYKsit2Qy4w==", - "dev": true, - "dependencies": { - "path-parse": "^1.0.6" - } - }, - "node_modules/resolve-dir": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/resolve-dir/-/resolve-dir-1.0.1.tgz", - "integrity": "sha1-eaQGRMNivoLybv/nOcm7U4IEb0M=", - "dev": true, - "dependencies": { - "expand-tilde": "^2.0.0", - "global-modules": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/resolve-from": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", - "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/responselike": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/responselike/-/responselike-1.0.2.tgz", - "integrity": "sha1-kYcg7ztjHFZCvgaPFa3lpG9Loec=", - "dependencies": { - "lowercase-keys": "^1.0.0" - } - }, - "node_modules/restore-cursor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", - "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", - "dependencies": { - "onetime": "^5.1.0", - "signal-exit": "^3.0.2" - }, + "resolved": "https://registry.npmjs.org/yoctocolors/-/yoctocolors-2.1.1.tgz", + "integrity": "sha512-GQHQqAopRhwU8Kt1DDM8NjibDXHC8eoh1erhGAJPEyveY9qqVeXvVikNKrDz69sHowPMorbPUrH/mx8c50eiBQ==", "engines": { - "node": ">=8" - } - }, - "node_modules/rfdc": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.3.0.tgz", - "integrity": "sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA==", - "dev": true - }, - "node_modules/rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dev": true, - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/run-async": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.4.1.tgz", - "integrity": "sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==", - "engines": { - "node": ">=0.12.0" - } - }, - "node_modules/rx-lite": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/rx-lite/-/rx-lite-3.1.2.tgz", - "integrity": "sha1-Gc5QLKVyZl87ZHsQk5+X/RYV8QI=", - "dev": true - }, - "node_modules/rxjs": { - "version": "7.4.0", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.4.0.tgz", - "integrity": "sha512-7SQDi7xeTMCJpqViXh8gL/lebcwlp3d831F05+9B44A4B0WfsEwUQHR64gsH1kvJ+Ep/J9K2+n1hVl1CsGN23w==", - "dependencies": { - "tslib": "~2.1.0" - } - }, - "node_modules/safe-buffer": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.0.tgz", - "integrity": "sha512-fZEwUGbVl7kouZs1jCdMLdt95hdIv0ZeHg6L7qPeciMZhZ+/gdesW4wgTARkrFWEpspjEATAzUGPG8N2jJiwbg==" - }, - "node_modules/safe-stable-stringify": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/safe-stable-stringify/-/safe-stable-stringify-1.1.1.tgz", - "integrity": "sha512-ERq4hUjKDbJfE4+XtZLFPCDi8Vb1JqaxAPTxWFLBx8XcAlf9Bda/ZJdVezs/NAfsMQScyIlUMx+Yeu7P7rx5jw==" - }, - "node_modules/safer-buffer": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" - }, - "node_modules/sax": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", - "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==" - }, - "node_modules/semver": { - "version": "7.3.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", - "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", - "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/semver-compare": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/semver-compare/-/semver-compare-1.0.0.tgz", - "integrity": "sha1-De4hahyUGrN+nvsXiPavxf9VN/w=", - "dev": true - }, - "node_modules/semver-diff": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/semver-diff/-/semver-diff-2.1.0.tgz", - "integrity": "sha1-S7uEN8jTfksM8aaP1ybsbWRdbTY=", - "dev": true, - "dependencies": { - "semver": "^5.0.3" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/semver-diff/node_modules/semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true, - "bin": { - "semver": "bin/semver" - } - }, - "node_modules/semver/node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/semver/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" - }, - "node_modules/serialize-javascript": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz", - "integrity": "sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==", - "dev": true, - "dependencies": { - "randombytes": "^2.1.0" - } - }, - "node_modules/set-blocking": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", - "dev": true - }, - "node_modules/sfmc-fuelsdk-node": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/sfmc-fuelsdk-node/-/sfmc-fuelsdk-node-2.4.0.tgz", - "integrity": "sha512-Orl/Mjc9KlFBjXuJvlzMaXkK1Kl4ns9Y+NS3WwczcmPj4PnNEsdJC7x+KLarxGbKzgR6iGA+PVG8Fhs3tTb1Ww==", - "dependencies": { - "fuel-auth": "^3.3.0", - "fuel-rest": "^3.2.2", - "fuel-soap": "^2.2.3", - "lodash.merge": "^4.6.1", - "request": "^2.88.0", - "uuid": "^3.3.2" - } - }, - "node_modules/shebang-command": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", - "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", - "dev": true, - "dependencies": { - "shebang-regex": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/shebang-regex": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", - "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/shell-quote": { - "version": "1.7.2", - "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.7.2.tgz", - "integrity": "sha512-mRz/m/JVscCrkMyPqHc/bczi3OQHkLTqXHEFu0zDhK/qfv3UcOA4SVmRCLmos4bhjr9ekVQubj/R7waKapmiQg==", - "dev": true - }, - "node_modules/signal-exit": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.6.tgz", - "integrity": "sha512-sDl4qMFpijcGw22U5w63KmD3cZJfBuFlVNbVMKje2keoKML7X2UzWbc4XrmEbDwg0NXJc3yv4/ox7b+JWb57kQ==" - }, - "node_modules/simple-git": { - "version": "2.48.0", - "resolved": "https://registry.npmjs.org/simple-git/-/simple-git-2.48.0.tgz", - "integrity": "sha512-z4qtrRuaAFJS4PUd0g+xy7aN4y+RvEt/QTJpR184lhJguBA1S/LsVlvE/CM95RsYMOFJG3NGGDjqFCzKU19S/A==", - "dependencies": { - "@kwsites/file-exists": "^1.1.1", - "@kwsites/promise-deferred": "^1.1.1", - "debug": "^4.3.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/steveukx/" - } - }, - "node_modules/simple-swizzle": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz", - "integrity": "sha1-pNprY1/8zMoz9w0Xy5JZLeleVXo=", - "dependencies": { - "is-arrayish": "^0.3.1" - } - }, - "node_modules/slice-ansi": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-5.0.0.tgz", - "integrity": "sha512-FC+lgizVPfie0kkhqUScwRu1O/lF6NOgJmlCgK+/LYxDCTk8sGelYaHDhFcDN+Sn3Cv+3VSa4Byeo+IMCzpMgQ==", - "dev": true, - "dependencies": { - "ansi-styles": "^6.0.0", - "is-fullwidth-code-point": "^4.0.0" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/slice-ansi?sponsor=1" - } - }, - "node_modules/slice-ansi/node_modules/ansi-styles": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.1.0.tgz", - "integrity": "sha512-VbqNsoz55SYGczauuup0MFUyXNQviSpFTj1RQtFzmQLk18qbVSpTFFGMT293rmDaQuKCT6InmbuEyUne4mTuxQ==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/slice-ansi/node_modules/is-fullwidth-code-point": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-4.0.0.tgz", - "integrity": "sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ==", - "dev": true, - "engines": { - "node": ">=12" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } - }, - "node_modules/sort-array": { - "version": "4.1.4", - "resolved": "https://registry.npmjs.org/sort-array/-/sort-array-4.1.4.tgz", - "integrity": "sha512-GVFN6Y1sHKrWaSYOJTk9093ZnrBMc9sP3nuhANU44S4xg3rE6W5Z5WyamuT8VpMBbssnetx5faKCua0LEmUnSw==", - "dev": true, - "dependencies": { - "array-back": "^5.0.0", - "typical": "^6.0.1" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/sort-array/node_modules/array-back": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/array-back/-/array-back-5.0.0.tgz", - "integrity": "sha512-kgVWwJReZWmVuWOQKEOohXKJX+nD02JAZ54D1RRWlv8L0NebauKAaFxACKzB74RTclt1+WNz5KHaLRDAPZbDEw==", - "dev": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/sort-array/node_modules/typical": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/typical/-/typical-6.0.1.tgz", - "integrity": "sha512-+g3NEp7fJLe9DPa1TArHm9QAA7YciZmWnfAqEaFrBihQ7epOv9i99rjtgb6Iz0wh3WuQDjsCTDfgRoGnmHN81A==", - "dev": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/spdx-correct": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.0.tgz", - "integrity": "sha512-lr2EZCctC2BNR7j7WzJ2FpDznxky1sjfxvvYEyzxNyb6lZXHODmEoJeFu4JupYlkfha1KZpJyoqiJ7pgA1qq8Q==", - "dev": true, - "dependencies": { - "spdx-expression-parse": "^3.0.0", - "spdx-license-ids": "^3.0.0" - } - }, - "node_modules/spdx-exceptions": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.2.0.tgz", - "integrity": "sha512-2XQACfElKi9SlVb1CYadKDXvoajPgBVPn/gOQLrTvHdElaVhr7ZEbqJaRnJLVNeaI4cMEAgVCeBMKF6MWRDCRA==", - "dev": true - }, - "node_modules/spdx-expression-parse": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz", - "integrity": "sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg==", - "dev": true, - "dependencies": { - "spdx-exceptions": "^2.1.0", - "spdx-license-ids": "^3.0.0" - } - }, - "node_modules/spdx-license-ids": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.5.tgz", - "integrity": "sha512-J+FWzZoynJEXGphVIS+XEh3kFSjZX/1i9gFBaWQcB+/tmpe2qUsSBABpcxqxnAxFdiUFEgAX1bjYGQvIZmoz9Q==", - "dev": true - }, - "node_modules/sprintf-js": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", - "dev": true - }, - "node_modules/sql-formatter-plus": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/sql-formatter-plus/-/sql-formatter-plus-1.3.6.tgz", - "integrity": "sha512-3pelcpLve9GgsXshWL/59zyDkhICkXDURKjXyUN+PJqVGAt+ZmNPB2JY+hgnaQG5X9TQI7Q+WiyLEprHQAWuaQ==", - "dependencies": { - "@babel/polyfill": "^7.6.0", - "lodash": "^4.17.15" - } - }, - "node_modules/sshpk": { - "version": "1.16.1", - "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz", - "integrity": "sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==", - "dependencies": { - "asn1": "~0.2.3", - "assert-plus": "^1.0.0", - "bcrypt-pbkdf": "^1.0.0", - "dashdash": "^1.12.0", - "ecc-jsbn": "~0.1.1", - "getpass": "^0.1.1", - "jsbn": "~0.1.0", - "safer-buffer": "^2.0.2", - "tweetnacl": "~0.14.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/stack-trace": { - "version": "0.0.10", - "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz", - "integrity": "sha1-VHxws0fo0ytOEI6hoqFZ5f3eGcA=", - "engines": { - "node": "*" - } - }, - "node_modules/stackframe": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/stackframe/-/stackframe-0.3.1.tgz", - "integrity": "sha1-M6qE8Rd6VUjIk1Uzy/6zQgl19aQ=", - "dev": true - }, - "node_modules/stream-connect": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/stream-connect/-/stream-connect-1.0.2.tgz", - "integrity": "sha1-GLyB8u2zW4tdmoAJIAqYUxRCipc=", - "dev": true, - "dependencies": { - "array-back": "^1.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/stream-connect/node_modules/array-back": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/array-back/-/array-back-1.0.4.tgz", - "integrity": "sha1-ZEun8JX3/898Q7Xw3DnTwfA8Bjs=", - "dev": true, - "dependencies": { - "typical": "^2.6.0" - }, - "engines": { - "node": ">=0.12.0" - } - }, - "node_modules/stream-via": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/stream-via/-/stream-via-1.0.4.tgz", - "integrity": "sha512-DBp0lSvX5G9KGRDTkR/R+a29H+Wk2xItOF+MpZLLNDWbEV9tGPnqLPxHEYjmiz8xGtJHRIqmI+hCjmNzqoA4nQ==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/string_decoder": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", - "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", - "dependencies": { - "safe-buffer": "~5.2.0" - } - }, - "node_modules/string-argv": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/string-argv/-/string-argv-0.3.1.tgz", - "integrity": "sha512-a1uQGz7IyVy9YwhqjZIZu1c8JO8dNIe20xBmSS6qu9kv++k3JGzCVmprbNN5Kn+BgzD5E7YYwg1CcjuJMRNsvg==", - "dev": true, - "engines": { - "node": ">=0.6.19" - } - }, - "node_modules/string-width": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", - "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", - "dev": true, - "dependencies": { - "emoji-regex": "^7.0.1", - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^5.1.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/string.prototype.padend": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/string.prototype.padend/-/string.prototype.padend-3.0.0.tgz", - "integrity": "sha1-86rvfBcZ8XDF6rHDK/eA2W4h8vA=", - "dev": true, - "dependencies": { - "define-properties": "^1.1.2", - "es-abstract": "^1.4.3", - "function-bind": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/string.prototype.trimleft": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/string.prototype.trimleft/-/string.prototype.trimleft-2.1.0.tgz", - "integrity": "sha512-FJ6b7EgdKxxbDxc79cOlok6Afd++TTs5szo+zJTUyow3ycrRfJVE2pq3vcN53XexvKZu/DJMDfeI/qMiZTrjTw==", - "dependencies": { - "define-properties": "^1.1.3", - "function-bind": "^1.1.1" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/string.prototype.trimright": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/string.prototype.trimright/-/string.prototype.trimright-2.1.0.tgz", - "integrity": "sha512-fXZTSV55dNBwv16uw+hh5jkghxSnc5oHq+5K/gXgizHwAvMetdAJlHqqoFC1FSDVPYWLkAKl2cxpUT41sV7nSg==", - "dependencies": { - "define-properties": "^1.1.3", - "function-bind": "^1.1.1" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", - "dev": true, - "dependencies": { - "ansi-regex": "^4.1.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/strip-bom": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", - "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/strip-eof": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", - "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/strip-final-newline": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", - "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/strip-indent": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-1.0.1.tgz", - "integrity": "sha1-DHlipq3vp7vUrDZkYKY4VSrhoKI=", - "dev": true, - "dependencies": { - "get-stdin": "^4.0.1" - }, - "bin": { - "strip-indent": "cli.js" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/strip-indent/node_modules/get-stdin": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz", - "integrity": "sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/strip-json-comments": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", - "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "dependencies": { - "has-flag": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/table-layout": { - "version": "0.4.5", - "resolved": "https://registry.npmjs.org/table-layout/-/table-layout-0.4.5.tgz", - "integrity": "sha512-zTvf0mcggrGeTe/2jJ6ECkJHAQPIYEwDoqsiqBjI24mvRmQbInK5jq33fyypaCBxX08hMkfmdOqj6haT33EqWw==", - "dev": true, - "dependencies": { - "array-back": "^2.0.0", - "deep-extend": "~0.6.0", - "lodash.padend": "^4.6.1", - "typical": "^2.6.1", - "wordwrapjs": "^3.0.0" - }, - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/table-layout/node_modules/array-back": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/array-back/-/array-back-2.0.0.tgz", - "integrity": "sha512-eJv4pLLufP3g5kcZry0j6WXpIbzYw9GUB4mVJZno9wfwiBxbizTnHCw3VJb07cBihbFX48Y7oSrW9y+gt4glyw==", - "dev": true, - "dependencies": { - "typical": "^2.6.1" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/taffydb": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/taffydb/-/taffydb-2.6.2.tgz", - "integrity": "sha1-fLy2S1oUG2ou/CxdLGe04VCyomg=", - "dev": true - }, - "node_modules/temp-path": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/temp-path/-/temp-path-1.0.0.tgz", - "integrity": "sha1-JLFUOXOrRCiW2a02fdnL2/r+kYs=", - "dev": true - }, - "node_modules/term-size": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/term-size/-/term-size-2.2.1.tgz", - "integrity": "sha512-wK0Ri4fOGjv/XPy8SBHZChl8CM7uMc5VML7SqiQ0zG7+J5Vr+RMQDoHa2CNT6KHUnTGIXH34UDMkPzAUyapBZg==", - "engines": { - "node": ">=8" - } - }, - "node_modules/test-value": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/test-value/-/test-value-3.0.0.tgz", - "integrity": "sha512-sVACdAWcZkSU9x7AOmJo5TqE+GyNJknHaHsMrR6ZnhjVlVN9Yx6FjHrsKZ3BjIpPCT68zYesPWkakrNupwfOTQ==", - "dev": true, - "dependencies": { - "array-back": "^2.0.0", - "typical": "^2.6.1" - }, - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/test-value/node_modules/array-back": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/array-back/-/array-back-2.0.0.tgz", - "integrity": "sha512-eJv4pLLufP3g5kcZry0j6WXpIbzYw9GUB4mVJZno9wfwiBxbizTnHCw3VJb07cBihbFX48Y7oSrW9y+gt4glyw==", - "dev": true, - "dependencies": { - "typical": "^2.6.1" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/text-hex": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/text-hex/-/text-hex-1.0.0.tgz", - "integrity": "sha512-uuVGNWzgJ4yhRaNSiubPY7OjISw4sw4E5Uv0wbjp+OzcbmVU/rsT8ujgcXJhn9ypzsgr5vlzpPqP+MBBKcGvbg==" - }, - "node_modules/text-table": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", - "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", - "dev": true - }, - "node_modules/throat": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/throat/-/throat-2.0.2.tgz", - "integrity": "sha1-qfzoCLaeEzpjJZB4DzQsMKYkmwI=", - "dev": true - }, - "node_modules/through": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", - "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=" - }, - "node_modules/timed-out": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/timed-out/-/timed-out-4.0.1.tgz", - "integrity": "sha1-8y6srFoXW+ol1/q1Zas+2HQe9W8=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/tmp": { - "version": "0.0.33", - "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", - "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", - "dependencies": { - "os-tmpdir": "~1.0.2" - }, - "engines": { - "node": ">=0.6.0" - } - }, - "node_modules/to-fast-properties": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", - "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/to-readable-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/to-readable-stream/-/to-readable-stream-1.0.0.tgz", - "integrity": "sha512-Iq25XBt6zD5npPhlLVXGFN3/gyR2/qODcKNNyTMd4vbm39HUaOiAM4PMq0eMVC/Tkxz+Zjdsc55g9yyz+Yq00Q==", - "engines": { - "node": ">=6" - } - }, - "node_modules/to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dev": true, - "dependencies": { - "is-number": "^7.0.0" - }, - "engines": { - "node": ">=8.0" - } - }, - "node_modules/toposort": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/toposort/-/toposort-2.0.2.tgz", - "integrity": "sha1-riF2gXXRVZ1IvvNUILL0li8JwzA=" - }, - "node_modules/tough-cookie": { - "version": "2.4.3", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.4.3.tgz", - "integrity": "sha512-Q5srk/4vDM54WJsJio3XNn6K2sCG+CQ8G5Wz6bZhRZoAe/+TxjWB/GlFAnYEbkYVlON9FMk/fE3h2RLpPXo4lQ==", - "dependencies": { - "psl": "^1.1.24", - "punycode": "^1.4.1" - }, - "engines": { - "node": ">=0.8" - } - }, - "node_modules/tough-cookie/node_modules/punycode": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", - "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=" - }, - "node_modules/traverse": { - "version": "0.6.6", - "resolved": "https://registry.npmjs.org/traverse/-/traverse-0.6.6.tgz", - "integrity": "sha1-y99WD9e5r2MlAv7UD5GMFX6pcTc=" - }, - "node_modules/trim-newlines": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-1.0.0.tgz", - "integrity": "sha1-WIeWa7WCpFA6QetST301ARgVphM=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/triple-beam": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/triple-beam/-/triple-beam-1.3.0.tgz", - "integrity": "sha512-XrHUvV5HpdLmIj4uVMxHggLbFSZYIn7HEWsqePZcI50pco+MPqJ50wMGY794X7AOOhxOBAjbkqfAbEe/QMp2Lw==" - }, - "node_modules/tslib": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.1.0.tgz", - "integrity": "sha512-hcVC3wYEziELGGmEEXue7D75zbwIIVUMWAVbHItGPx0ziyXxrOMQx4rQEVEV45Ut/1IotuEvwqPopzIOkDMf0A==" - }, - "node_modules/tunnel-agent": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", - "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", - "dependencies": { - "safe-buffer": "^5.0.1" - }, - "engines": { - "node": "*" - } - }, - "node_modules/tweetnacl": { - "version": "0.14.5", - "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", - "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=" - }, - "node_modules/type-check": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", - "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", - "dev": true, - "dependencies": { - "prelude-ls": "^1.2.1" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/type-detect": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", - "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/type-fest": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", - "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", - "engines": { - "node": ">=8" - } - }, - "node_modules/typedarray-to-buffer": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz", - "integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==", - "dependencies": { - "is-typedarray": "^1.0.0" - } - }, - "node_modules/typical": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/typical/-/typical-2.6.1.tgz", - "integrity": "sha1-XAgOXWYcu+OCWdLnCjxyU+hziB0=", - "dev": true - }, - "node_modules/uc.micro": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-1.0.6.tgz", - "integrity": "sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA==", - "dev": true - }, - "node_modules/uglify-js": { - "version": "3.13.1", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.13.1.tgz", - "integrity": "sha512-EWhx3fHy3M9JbaeTnO+rEqzCe1wtyQClv6q3YWq0voOj4E+bMZBErVS1GAHPDiRGONYq34M1/d8KuQMgvi6Gjw==", - "dev": true, - "optional": true, - "bin": { - "uglifyjs": "bin/uglifyjs" - }, - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/underscore": { - "version": "1.13.1", - "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.13.1.tgz", - "integrity": "sha512-hzSoAVtJF+3ZtiFX0VgfFPHEDRm7Y/QPjGyNo4TVdnDTdft3tr8hEkD25a1jC+TjTuE7tkHGKkhwCgs9dgBB2g==", - "dev": true - }, - "node_modules/unique-string": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-2.0.0.tgz", - "integrity": "sha512-uNaeirEPvpZWSgzwsPGtU2zVSTrn/8L5q/IexZmH0eH6SA73CmAA5U4GwORTxQAZs95TAXLNqeLoPPNO5gZfWg==", - "dependencies": { - "crypto-random-string": "^2.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/universalify": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-1.0.0.tgz", - "integrity": "sha512-rb6X1W158d7pRQBg5gkR8uPaSfiids68LTJQYOtEUhoJUWBdaQHsuT/EUduxXYxcrt4r5PJ4fuHW1MHT6p0qug==", - "engines": { - "node": ">= 10.0.0" - } - }, - "node_modules/unzip-response": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/unzip-response/-/unzip-response-2.0.1.tgz", - "integrity": "sha1-0vD3N9FrBhXnKmk17QQhRXLVb5c=", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/update-notifier-git": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/update-notifier-git/-/update-notifier-git-5.0.3.tgz", - "integrity": "sha512-Ikg++hC5EUKURxT+aCsnA58ZYq67Hiof2jK0rlFCJuF/lQsm3g2AKx1BrQZ9cO2x0mksUhabzWvAAJH45nXSJw==", - "dependencies": { - "boxen": "^4.2.0", - "chalk": "^3.0.0", - "configstore": "^5.0.1", - "git-version-tag": "^1.0.2", - "has-yarn": "^2.1.0", - "import-lazy": "^2.1.0", - "is-ci": "^2.0.0", - "is-npm": "^4.0.0", - "is-yarn-global": "^0.3.0", - "latest-version": "^5.0.0", - "pupa": "^2.0.1", - "semver-diff": "^3.1.1", - "xdg-basedir": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/update-notifier-git/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/update-notifier-git/node_modules/chalk": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", - "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/update-notifier-git/node_modules/ci-info": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz", - "integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==" - }, - "node_modules/update-notifier-git/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/update-notifier-git/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" - }, - "node_modules/update-notifier-git/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "engines": { - "node": ">=8" - } - }, - "node_modules/update-notifier-git/node_modules/is-ci": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-2.0.0.tgz", - "integrity": "sha512-YfJT7rkpQB0updsdHLGWrvhBJfcfzNNawYDNIyQXJz0IViGf75O8EBPKSdvw2rF+LGCsX4FZ8tcr3b19LcZq4w==", - "dependencies": { - "ci-info": "^2.0.0" - }, - "bin": { - "is-ci": "bin.js" - } - }, - "node_modules/update-notifier-git/node_modules/semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/update-notifier-git/node_modules/semver-diff": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/semver-diff/-/semver-diff-3.1.1.tgz", - "integrity": "sha512-GX0Ix/CJcHyB8c4ykpHGIAvLyOwOobtM/8d+TQkAd81/bEjgPHrfba41Vpesr7jX/t8Uh+R3EX9eAS5be+jQYg==", - "dependencies": { - "semver": "^6.3.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/update-notifier-git/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/uri-js": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz", - "integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==", - "dependencies": { - "punycode": "^2.1.0" - } - }, - "node_modules/url-parse-lax": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-1.0.0.tgz", - "integrity": "sha1-evjzA2Rem9eaJy56FKxovAYJ2nM=", - "dev": true, - "dependencies": { - "prepend-http": "^1.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" - }, - "node_modules/util.promisify": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/util.promisify/-/util.promisify-1.0.0.tgz", - "integrity": "sha512-i+6qA2MPhvoKLuxnJNpXAGhg7HphQOSUq2LKMZD0m15EiskXUkMvKdF4Uui0WYeCUGea+o2cw/ZuwehtfsrNkA==", - "dependencies": { - "define-properties": "^1.1.2", - "object.getownpropertydescriptors": "^2.0.3" - } - }, - "node_modules/uuid": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.3.tgz", - "integrity": "sha512-pW0No1RGHgzlpHJO1nsVrHKpOEIxkGg1xB+v0ZmdNH5OAeAwzAVrCnI2/6Mtx+Uys6iaylxa+D3g4j63IKKjSQ==", - "bin": { - "uuid": "bin/uuid" - } - }, - "node_modules/v8-compile-cache": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.2.0.tgz", - "integrity": "sha512-gTpR5XQNKFwOd4clxfnhaqvfqMpqEwr4tOtCyz4MtYZX2JYhfr1JvBFKdS+7K/9rfpZR3VLX+YWBbKoxCgS43Q==", - "dev": true - }, - "node_modules/validate-npm-package-license": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", - "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", - "dev": true, - "dependencies": { - "spdx-correct": "^3.0.0", - "spdx-expression-parse": "^3.0.0" - } - }, - "node_modules/verror": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", - "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", - "engines": [ - "node >=0.6.0" - ], - "dependencies": { - "assert-plus": "^1.0.0", - "core-util-is": "1.0.2", - "extsprintf": "^1.2.0" - } - }, - "node_modules/vue-template-compiler": { - "version": "2.6.11", - "resolved": "https://registry.npmjs.org/vue-template-compiler/-/vue-template-compiler-2.6.11.tgz", - "integrity": "sha512-KIq15bvQDrcCjpGjrAhx4mUlyyHfdmTaoNfeoATHLAiWB+MU3cx4lOzMwrnUh9cCxy0Lt1T11hAFY6TQgroUAA==", - "dev": true, - "dependencies": { - "de-indent": "^1.0.2", - "he": "^1.1.0" - } - }, - "node_modules/walk-back": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/walk-back/-/walk-back-5.1.0.tgz", - "integrity": "sha512-Uhxps5yZcVNbLEAnb+xaEEMdgTXl9qAQDzKYejG2AZ7qPwRQ81lozY9ECDbjLPNWm7YsO1IK5rsP1KoQzXAcGA==", - "dev": true, - "engines": { - "node": ">=12.17" - } - }, - "node_modules/walkdir": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/walkdir/-/walkdir-0.3.2.tgz", - "integrity": "sha512-0Twghia4Z5wDGDYWURlhZmI47GvERMCsXIu0QZWVVZyW9ZjpbbZvD9Zy9M6cWiQQRRbAcYajIyKNavaZZDt1Uw==", - "dev": true, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/wcwidth": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz", - "integrity": "sha1-8LDc+RW8X/FSivrbLA4XtTLaL+g=", - "dependencies": { - "defaults": "^1.0.3" - } - }, - "node_modules/which": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", - "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", - "dev": true, - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "which": "bin/which" - } - }, - "node_modules/which-module": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", - "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", - "dev": true - }, - "node_modules/which-pm": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/which-pm/-/which-pm-1.1.0.tgz", - "integrity": "sha512-7GHHJQpALk7BWMD8I+xSILSbHyngvBlfSXlwGpdRFY2voFwVCx+eJAybXTzTnUYmt7zio6B9SEdI81T0fBjxNA==", - "dev": true, - "dependencies": { - "load-yaml-file": "^0.1.0", - "path-exists": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/widest-line": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-3.1.0.tgz", - "integrity": "sha512-NsmoXalsWVDMGupxZ5R08ka9flZjjiLvHVAWYOKtiKM8ujtZWr9cRffak+uSE48+Ob8ObalXpwyeUiyDD6QFgg==", - "dependencies": { - "string-width": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/widest-line/node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "engines": { - "node": ">=8" - } - }, - "node_modules/widest-line/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" - }, - "node_modules/widest-line/node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "engines": { - "node": ">=8" - } - }, - "node_modules/widest-line/node_modules/string-width": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz", - "integrity": "sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==", - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/widest-line/node_modules/strip-ansi": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", - "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", - "dependencies": { - "ansi-regex": "^5.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/winston": { - "version": "3.3.4", - "resolved": "https://registry.npmjs.org/winston/-/winston-3.3.4.tgz", - "integrity": "sha512-zWJrfmqE+2IXtVJ125vxpA2m303TjwchLhfRbcnma7c76Qd4pv80JIp37l8uGnWbCoG4X6PMz3vAQeh+vH1CtA==", - "dependencies": { - "@dabh/diagnostics": "^2.0.2", - "async": "^3.2.3", - "is-stream": "^2.0.0", - "logform": "^2.3.2", - "one-time": "^1.0.0", - "readable-stream": "^3.4.0", - "stack-trace": "0.0.x", - "triple-beam": "^1.3.0", - "winston-transport": "^4.4.2" - }, - "engines": { - "node": ">= 6.4.0" - } - }, - "node_modules/winston-transport": { - "version": "4.4.2", - "resolved": "https://registry.npmjs.org/winston-transport/-/winston-transport-4.4.2.tgz", - "integrity": "sha512-9jmhltAr5ygt5usgUTQbEiw/7RYXpyUbEAFRCSicIacpUzPkrnQsQZSPGEI12aLK9Jth4zNcYJx3Cvznwrl8pw==", - "dependencies": { - "logform": "^2.3.2", - "readable-stream": "^3.4.0", - "triple-beam": "^1.2.0" - }, - "engines": { - "node": ">= 6.4.0" - } - }, - "node_modules/winston/node_modules/is-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.0.tgz", - "integrity": "sha512-XCoy+WlUr7d1+Z8GgSuXmpuUFC9fOhRXglJMx+dwLKTkL44Cjd4W1Z5P+BQZpr+cR93aGP4S/s7Ftw6Nd/kiEw==", - "engines": { - "node": ">=8" - } - }, - "node_modules/word-wrap": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", - "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/wordwrap": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", - "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=", - "dev": true - }, - "node_modules/wordwrapjs": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/wordwrapjs/-/wordwrapjs-3.0.0.tgz", - "integrity": "sha512-mO8XtqyPvykVCsrwj5MlOVWvSnCdT+C+QVbm6blradR7JExAhbkZ7hZ9A+9NUtwzSqrlUo9a67ws0EiILrvRpw==", - "dev": true, - "dependencies": { - "reduce-flatten": "^1.0.1", - "typical": "^2.6.1" - }, - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/workerpool": { - "version": "6.1.5", - "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.1.5.tgz", - "integrity": "sha512-XdKkCK0Zqc6w3iTxLckiuJ81tiD/o5rBE/m+nXpRCB+/Sq4DqkfXZ/x0jW02DG1tGsfUGXbTJyZDP+eu67haSw==", - "dev": true - }, - "node_modules/wrap-ansi": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz", - "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==", - "dev": true, - "dependencies": { - "ansi-styles": "^3.2.0", - "string-width": "^3.0.0", - "strip-ansi": "^5.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" - }, - "node_modules/write-file-atomic": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz", - "integrity": "sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==", - "dependencies": { - "imurmurhash": "^0.1.4", - "is-typedarray": "^1.0.0", - "signal-exit": "^3.0.2", - "typedarray-to-buffer": "^3.1.5" - } - }, - "node_modules/xdg-basedir": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-4.0.0.tgz", - "integrity": "sha512-PSNhEJDejZYV7h50BohL09Er9VaIefr2LMAf3OEmpCkjOi34eYyQYAXUTjEQtZJTKcF0E2UKTh+osDLsgNim9Q==", - "engines": { - "node": ">=8" - } - }, - "node_modules/xml2js": { - "version": "0.4.22", - "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.22.tgz", - "integrity": "sha512-MWTbxAQqclRSTnehWWe5nMKzI3VmJ8ltiJEco8akcC6j3miOhjjfzKum5sId+CWhfxdOs/1xauYr8/ZDBtQiRw==", - "dependencies": { - "sax": ">=0.6.0", - "util.promisify": "~1.0.0", - "xmlbuilder": "~11.0.0" - }, - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/xmlbuilder": { - "version": "11.0.1", - "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-11.0.1.tgz", - "integrity": "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==", - "engines": { - "node": ">=4.0" - } - }, - "node_modules/xmlcreate": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/xmlcreate/-/xmlcreate-2.0.4.tgz", - "integrity": "sha512-nquOebG4sngPmGPICTS5EnxqhKbCmz5Ox5hsszI2T6U5qdrJizBc+0ilYSEjTSzU0yZcmvppztXe/5Al5fUwdg==", - "dev": true - }, - "node_modules/xtend": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", - "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", - "dev": true, - "engines": { - "node": ">=0.4" - } - }, - "node_modules/y18n": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", - "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==", - "dev": true - }, - "node_modules/yallist": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", - "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=", - "dev": true - }, - "node_modules/yaml": { - "version": "1.10.2", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", - "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", - "dev": true, - "engines": { - "node": ">= 6" - } - }, - "node_modules/yargs": { - "version": "17.3.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.3.0.tgz", - "integrity": "sha512-GQl1pWyDoGptFPJx9b9L6kmR33TGusZvXIZUT+BOz9f7X2L94oeAskFYLEg/FkhV06zZPBYLvLZRWeYId29lew==", - "dependencies": { - "cliui": "^7.0.2", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.3", - "y18n": "^5.0.5", - "yargs-parser": "^21.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/yargs-parser": { - "version": "13.1.2", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.2.tgz", - "integrity": "sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==", - "dev": true, - "dependencies": { - "camelcase": "^5.0.0", - "decamelize": "^1.2.0" - } - }, - "node_modules/yargs-unparser": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-2.0.0.tgz", - "integrity": "sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==", - "dev": true, - "dependencies": { - "camelcase": "^6.0.0", - "decamelize": "^4.0.0", - "flat": "^5.0.2", - "is-plain-obj": "^2.1.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/yargs-unparser/node_modules/camelcase": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.2.0.tgz", - "integrity": "sha512-c7wVvbw3f37nuobQNtgsgG9POC9qMbNuMQmTCqZv23b6MIz0fcYpBiOlv9gEN/hdLdnZTDQhg6e9Dq5M1vKvfg==", - "dev": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/yargs-unparser/node_modules/decamelize": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz", - "integrity": "sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==", - "dev": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/yargs/node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "engines": { - "node": ">=8" - } - }, - "node_modules/yargs/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/yargs/node_modules/cliui": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.3.tgz", - "integrity": "sha512-Gj3QHTkVMPKqwP3f7B4KPkBZRMR9r4rfi5bXFpg1a+Svvj8l7q5CnkBkVQzfxT5DFSsGk2+PascOgL0JYkL2kw==", - "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", - "wrap-ansi": "^7.0.0" - } - }, - "node_modules/yargs/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/yargs/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" - }, - "node_modules/yargs/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" - }, - "node_modules/yargs/node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "engines": { - "node": ">=8" - } - }, - "node_modules/yargs/node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/yargs/node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/yargs/node_modules/wrap-ansi": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/yargs/node_modules/y18n": { - "version": "5.0.5", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.5.tgz", - "integrity": "sha512-hsRUr4FFrvhhRH12wOdfs38Gy7k2FFzB9qgN9v3aLykRq0dRcdcpz5C9FxdS2NuhOrI/628b/KSTJ3rwHysYSg==", - "engines": { - "node": ">=10" - } - }, - "node_modules/yargs/node_modules/yargs-parser": { - "version": "21.0.0", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.0.0.tgz", - "integrity": "sha512-z9kApYUOCwoeZ78rfRYYWdiU/iNL6mwwYlkkZfJoyMR1xps+NEBX5X7XmRpxkZHhXJ6+Ey00IwKxBBSW9FIjyA==", - "engines": { - "node": ">=12" - } - } - }, - "dependencies": { - "@babel/code-frame": { - "version": "7.12.11", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.12.11.tgz", - "integrity": "sha512-Zt1yodBx1UcyiePMSkWnU4hPqhwq7hGi2nFL1LeA3EUl+q2LQx16MISgJ0+z7dnmgvP9QtIleuETGOiOH1RcIw==", - "dev": true, - "requires": { - "@babel/highlight": "^7.10.4" - } - }, - "@babel/generator": { - "version": "7.9.5", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.9.5.tgz", - "integrity": "sha512-GbNIxVB3ZJe3tLeDm1HSn2AhuD/mVcyLDpgtLXa5tplmWrJdF/elxB56XNqCuD6szyNkDi6wuoKXln3QeBmCHQ==", - "dev": true, - "requires": { - "@babel/types": "^7.9.5", - "jsesc": "^2.5.1", - "lodash": "^4.17.13", - "source-map": "^0.5.0" - }, - "dependencies": { - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true - } - } - }, - "@babel/helper-function-name": { - "version": "7.9.5", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.9.5.tgz", - "integrity": "sha512-JVcQZeXM59Cd1qanDUxv9fgJpt3NeKUaqBqUEvfmQ+BCOKq2xUgaWZW2hr0dkbyJgezYuplEoh5knmrnS68efw==", - "dev": true, - "requires": { - "@babel/helper-get-function-arity": "^7.8.3", - "@babel/template": "^7.8.3", - "@babel/types": "^7.9.5" - } - }, - "@babel/helper-get-function-arity": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.8.3.tgz", - "integrity": "sha512-FVDR+Gd9iLjUMY1fzE2SR0IuaJToR4RkCDARVfsBBPSP53GEqSFjD8gNyxg246VUyc/ALRxFaAK8rVG7UT7xRA==", - "dev": true, - "requires": { - "@babel/types": "^7.8.3" - } - }, - "@babel/helper-split-export-declaration": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.8.3.tgz", - "integrity": "sha512-3x3yOeyBhW851hroze7ElzdkeRXQYQbFIb7gLK1WQYsw2GWDay5gAJNw1sWJ0VFP6z5J1whqeXH/WCdCjZv6dA==", - "dev": true, - "requires": { - "@babel/types": "^7.8.3" - } - }, - "@babel/helper-validator-identifier": { - "version": "7.9.5", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.9.5.tgz", - "integrity": "sha512-/8arLKUFq882w4tWGj9JYzRpAlZgiWUJ+dtteNTDqrRBz9Iguck9Rn3ykuBDoUwh2TO4tSAJlrxDUOXWklJe4g==", - "dev": true - }, - "@babel/highlight": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.10.4.tgz", - "integrity": "sha512-i6rgnR/YgPEQzZZnbTHHuZdlE8qyoBNalD6F+q4vAFlcMEcqmkoG+mPqJYJCo63qPf74+Y1UZsl3l6f7/RIkmA==", - "dev": true, - "requires": { - "@babel/helper-validator-identifier": "^7.10.4", - "chalk": "^2.0.0", - "js-tokens": "^4.0.0" - }, - "dependencies": { - "@babel/helper-validator-identifier": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.10.4.tgz", - "integrity": "sha512-3U9y+43hz7ZM+rzG24Qe2mufW5KhvFg/NhnNph+i9mgCtdTCtMJuI1TMkrIUiK7Ix4PYlRF9I5dhqaLYA/ADXw==", - "dev": true - } - } - }, - "@babel/parser": { - "version": "7.15.3", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.15.3.tgz", - "integrity": "sha512-O0L6v/HvqbdJawj0iBEfVQMc3/6WP+AeOsovsIgBFyJaG+W2w7eqvZB7puddATmWuARlm1SX7DwxJ/JJUnDpEA==", - "dev": true - }, - "@babel/polyfill": { - "version": "7.10.1", - "resolved": "https://registry.npmjs.org/@babel/polyfill/-/polyfill-7.10.1.tgz", - "integrity": "sha512-TviueJ4PBW5p48ra8IMtLXVkDucrlOZAIZ+EXqS3Ot4eukHbWiqcn7DcqpA1k5PcKtmJ4Xl9xwdv6yQvvcA+3g==", - "requires": { - "core-js": "^2.6.5", - "regenerator-runtime": "^0.13.4" - }, - "dependencies": { - "regenerator-runtime": { - "version": "0.13.5", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.5.tgz", - "integrity": "sha512-ZS5w8CpKFinUzOwW3c83oPeVXoNsrLsaCoLtJvAClH135j/R77RuymhiSErhm2lKcwSCIpmvIWSbDkIfAqKQlA==" - } - } - }, - "@babel/template": { - "version": "7.8.6", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.8.6.tgz", - "integrity": "sha512-zbMsPMy/v0PWFZEhQJ66bqjhH+z0JgMoBWuikXybgG3Gkd/3t5oQ1Rw2WQhnSrsOmsKXnZOx15tkC4qON/+JPg==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.8.3", - "@babel/parser": "^7.8.6", - "@babel/types": "^7.8.6" - } - }, - "@babel/traverse": { - "version": "7.9.5", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.9.5.tgz", - "integrity": "sha512-c4gH3jsvSuGUezlP6rzSJ6jf8fYjLj3hsMZRx/nX0h+fmHN0w+ekubRrHPqnMec0meycA2nwCsJ7dC8IPem2FQ==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.8.3", - "@babel/generator": "^7.9.5", - "@babel/helper-function-name": "^7.9.5", - "@babel/helper-split-export-declaration": "^7.8.3", - "@babel/parser": "^7.9.0", - "@babel/types": "^7.9.5", - "debug": "^4.1.0", - "globals": "^11.1.0", - "lodash": "^4.17.13" - }, - "dependencies": { - "globals": { - "version": "11.12.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", - "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", - "dev": true - } - } - }, - "@babel/types": { - "version": "7.9.5", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.9.5.tgz", - "integrity": "sha512-XjnvNqenk818r5zMaba+sLQjnbda31UfUURv3ei0qPQw4u+j2jMyJ5b11y8ZHYTRSI3NnInQkkkRT4fLqqPdHg==", - "dev": true, - "requires": { - "@babel/helper-validator-identifier": "^7.9.5", - "lodash": "^4.17.13", - "to-fast-properties": "^2.0.0" - } - }, - "@dabh/diagnostics": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@dabh/diagnostics/-/diagnostics-2.0.2.tgz", - "integrity": "sha512-+A1YivoVDNNVCdfozHSR8v/jyuuLTMXwjWuxPFlFlUapXoGc+Gj9mDlTDDfrwl7rXCl2tNZ0kE8sIBO6YOn96Q==", - "requires": { - "colorspace": "1.1.x", - "enabled": "2.0.x", - "kuler": "^2.0.0" - } - }, - "@eslint/eslintrc": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.0.5.tgz", - "integrity": "sha512-BLxsnmK3KyPunz5wmCCpqy0YelEoxxGmH73Is+Z74oOTMtExcjkr3dDR6quwrjh1YspA8DH9gnX1o069KiS9AQ==", - "dev": true, - "requires": { - "ajv": "^6.12.4", - "debug": "^4.3.2", - "espree": "^9.2.0", - "globals": "^13.9.0", - "ignore": "^4.0.6", - "import-fresh": "^3.2.1", - "js-yaml": "^4.1.0", - "minimatch": "^3.0.4", - "strip-json-comments": "^3.1.1" - }, - "dependencies": { - "argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true - }, - "js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "dev": true, - "requires": { - "argparse": "^2.0.1" - } - }, - "strip-json-comments": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", - "dev": true - } - } - }, - "@humanwhocodes/config-array": { - "version": "0.9.2", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.9.2.tgz", - "integrity": "sha512-UXOuFCGcwciWckOpmfKDq/GyhlTf9pN/BzG//x8p8zTOFEcGuA68ANXheFS0AGvy3qgZqLBUkMs7hqzqCKOVwA==", - "dev": true, - "requires": { - "@humanwhocodes/object-schema": "^1.2.1", - "debug": "^4.1.1", - "minimatch": "^3.0.4" - } - }, - "@humanwhocodes/object-schema": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz", - "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", - "dev": true - }, - "@kwsites/file-exists": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@kwsites/file-exists/-/file-exists-1.1.1.tgz", - "integrity": "sha512-m9/5YGR18lIwxSFDwfE3oA7bWuq9kdau6ugN4H2rJeyhFQZcG9AgSHkQtSD15a8WvTgfz9aikZMrKPHvbpqFiw==", - "requires": { - "debug": "^4.1.1" - } - }, - "@kwsites/promise-deferred": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@kwsites/promise-deferred/-/promise-deferred-1.1.1.tgz", - "integrity": "sha512-GaHYm+c0O9MjZRu0ongGBRbinu8gVAMd2UZjji6jVmqKtZluZnptXGWhz1E8j8D2HJ3f/yMxKAUC0b+57wncIw==" - }, - "@sindresorhus/is": { - "version": "0.14.0", - "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-0.14.0.tgz", - "integrity": "sha512-9NET910DNaIPngYnLLPeg+Ogzqsi9uM4mSboU5y6p8S5DzMTVEsJZrawi+BoDNUVBa2DhJqQYUFvMDfgU062LQ==" - }, - "@szmarczak/http-timer": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-1.1.2.tgz", - "integrity": "sha512-XIB2XbzHTN6ieIjfIMV9hlVcfPU26s2vafYWQcZHWXHOxiaRZYEDKEwdl129Zyg50+foYV2jCgtrqSA6qNuNSA==", - "requires": { - "defer-to-connect": "^1.0.1" - } - }, - "@ungap/promise-all-settled": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@ungap/promise-all-settled/-/promise-all-settled-1.1.2.tgz", - "integrity": "sha512-sL/cEvJWAnClXw0wHk85/2L0G6Sj8UB0Ctc1TEMbKSsmpRosqhwj9gWgFRZSrBr2f9tiXISwNhCPmlfqUqyb9Q==", - "dev": true - }, - "acorn": { - "version": "8.6.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.6.0.tgz", - "integrity": "sha512-U1riIR+lBSNi3IbxtaHOIKdH8sLFv3NYfNv8sg7ZsNhcfl4HF2++BfqqrNAxoCLQW1iiylOj76ecnaUxz+z9yw==", - "dev": true - }, - "acorn-jsx": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", - "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", - "dev": true, - "requires": {} - }, - "aggregate-error": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", - "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", - "dev": true, - "requires": { - "clean-stack": "^2.0.0", - "indent-string": "^4.0.0" - }, - "dependencies": { - "indent-string": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", - "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", - "dev": true - } - } - }, - "ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "requires": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - } - }, - "ansi-align": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.1.tgz", - "integrity": "sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w==", - "requires": { - "string-width": "^4.1.0" - }, - "dependencies": { - "ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==" - }, - "emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" - }, - "is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==" - }, - "string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "requires": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - } - }, - "strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "requires": { - "ansi-regex": "^5.0.1" - } - } - } - }, - "ansi-colors": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", - "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", - "dev": true - }, - "ansi-escape-sequences": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/ansi-escape-sequences/-/ansi-escape-sequences-4.1.0.tgz", - "integrity": "sha512-dzW9kHxH011uBsidTXd14JXgzye/YLb2LzeKZ4bsgl/Knwx8AtbSFkkGxagdNOoh0DlqHCmfiEjWKBaqjOanVw==", - "dev": true, - "requires": { - "array-back": "^3.0.1" - }, - "dependencies": { - "array-back": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/array-back/-/array-back-3.1.0.tgz", - "integrity": "sha512-TkuxA4UCOvxuDK6NZYXCalszEzj+TLszyASooky+i742l9TqsOdYCMJJupxRic61hwquNtppB3hgcuq9SVSH1Q==", - "dev": true - } - } - }, - "ansi-escapes": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.1.tgz", - "integrity": "sha512-JWF7ocqNrp8u9oqpgV+wH5ftbt+cfvv+PTjOvKLT3AdYly/LmORARfEVT1iyjwN+4MqE5UmVKoAdIBqeoCHgLA==", - "requires": { - "type-fest": "^0.11.0" - }, - "dependencies": { - "type-fest": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.11.0.tgz", - "integrity": "sha512-OdjXJxnCN1AvyLSzeKIgXTXxV+99ZuXl3Hpo9XpJAv9MBcHrrJOQ5kV7ypXOuQie+AmWG25hLbiKdwYTifzcfQ==" - } - } - }, - "ansi-regex": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", - "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", - "dev": true - }, - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "anymatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", - "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==", - "dev": true, - "requires": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" - } - }, - "argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "dev": true, - "requires": { - "sprintf-js": "~1.0.2" - } - }, - "array-back": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/array-back/-/array-back-4.0.1.tgz", - "integrity": "sha512-Z/JnaVEXv+A9xabHzN43FiiiWEE7gPCRXMrVmRm00tWbjZRul1iHm7ECzlyNq1p4a4ATXz+G9FJ3GqGOkOV3fg==", - "dev": true - }, - "array-find-index": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/array-find-index/-/array-find-index-1.0.2.tgz", - "integrity": "sha1-3wEKoSh+Fku9pvlyOwqWoexBh6E=", - "dev": true - }, - "array-union": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", - "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=", - "dev": true, - "requires": { - "array-uniq": "^1.0.1" - } - }, - "array-uniq": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", - "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=", - "dev": true - }, - "arrify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", - "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=", - "dev": true - }, - "asn1": { - "version": "0.2.4", - "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz", - "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==", - "requires": { - "safer-buffer": "~2.1.0" - } - }, - "assert-plus": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=" - }, - "assertion-error": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", - "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==", - "dev": true - }, - "astral-regex": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", - "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", - "dev": true - }, - "async": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/async/-/async-3.2.3.tgz", - "integrity": "sha512-spZRyzKL5l5BZQrr/6m/SqFdBN0q3OCI0f9rjfBzCMBIP4p75P620rR3gTmaksNOhmzgdxcaxdNfMy6anrbM0g==" - }, - "asynckit": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" - }, - "aws-sign2": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", - "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=" - }, - "aws4": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.8.0.tgz", - "integrity": "sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ==" - }, - "babel-runtime": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", - "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=", - "dev": true, - "requires": { - "core-js": "^2.4.0", - "regenerator-runtime": "^0.11.0" - } - }, - "balanced-match": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", - "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", - "dev": true - }, - "base64-js": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", - "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==" - }, - "bcrypt-pbkdf": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", - "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", - "requires": { - "tweetnacl": "^0.14.3" - } - }, - "binary-extensions": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", - "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", - "dev": true - }, - "bl": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", - "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", - "requires": { - "buffer": "^5.5.0", - "inherits": "^2.0.4", - "readable-stream": "^3.4.0" - } - }, - "bluebird": { - "version": "3.7.2", - "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", - "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==" - }, - "boxen": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/boxen/-/boxen-4.2.0.tgz", - "integrity": "sha512-eB4uT9RGzg2odpER62bBwSLvUeGC+WbRjjyyFhGsKnc8wp/m0+hQsMUvUe3H2V0D5vw0nBdO1hCJoZo5mKeuIQ==", - "requires": { - "ansi-align": "^3.0.0", - "camelcase": "^5.3.1", - "chalk": "^3.0.0", - "cli-boxes": "^2.2.0", - "string-width": "^4.1.0", - "term-size": "^2.1.0", - "type-fest": "^0.8.1", - "widest-line": "^3.1.0" - }, - "dependencies": { - "ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==" - }, - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "requires": { - "color-convert": "^2.0.1" - } - }, - "chalk": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", - "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" - }, - "emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" - }, - "is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==" - }, - "string-width": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz", - "integrity": "sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==", - "requires": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.0" - } - }, - "strip-ansi": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", - "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", - "requires": { - "ansi-regex": "^5.0.0" - } - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "requires": { - "has-flag": "^4.0.0" - } - } - } - }, - "brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "requires": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", - "dev": true, - "requires": { - "fill-range": "^7.0.1" - } - }, - "browser-stdout": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", - "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", - "dev": true - }, - "buffer": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", - "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", - "requires": { - "base64-js": "^1.3.1", - "ieee754": "^1.1.13" - } - }, - "builtin-modules": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-3.1.0.tgz", - "integrity": "sha512-k0KL0aWZuBt2lrxrcASWDfwOLMnodeQjodT/1SxEQAXsHANgo6ZC/VEaSEHCXt7aSTZ4/4H5LKa+tBXmW7Vtvw==", - "dev": true - }, - "cache-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/cache-point/-/cache-point-2.0.0.tgz", - "integrity": "sha512-4gkeHlFpSKgm3vm2gJN5sPqfmijYRFYCQ6tv5cLw0xVmT6r1z1vd4FNnpuOREco3cBs1G709sZ72LdgddKvL5w==", - "dev": true, - "requires": { - "array-back": "^4.0.1", - "fs-then-native": "^2.0.0", - "mkdirp2": "^1.0.4" - } - }, - "cacheable-request": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-6.1.0.tgz", - "integrity": "sha512-Oj3cAGPCqOZX7Rz64Uny2GYAZNliQSqfbePrgAQ1wKAihYmCUnraBtJtKcGR4xz7wF+LoJC+ssFZvv5BgF9Igg==", - "requires": { - "clone-response": "^1.0.2", - "get-stream": "^5.1.0", - "http-cache-semantics": "^4.0.0", - "keyv": "^3.0.0", - "lowercase-keys": "^2.0.0", - "normalize-url": "^4.1.0", - "responselike": "^1.0.2" - }, - "dependencies": { - "get-stream": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", - "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", - "requires": { - "pump": "^3.0.0" - } - }, - "lowercase-keys": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz", - "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==" - } - } - }, - "callsite": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/callsite/-/callsite-1.0.0.tgz", - "integrity": "sha1-KAOY5dZkvXQDi28JBRU+borxvCA=", - "dev": true - }, - "callsite-record": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/callsite-record/-/callsite-record-3.2.2.tgz", - "integrity": "sha1-mgOQZC5D/ou4I5ReUUZPafQWQ94=", - "dev": true, - "requires": { - "callsite": "^1.0.0", - "chalk": "^1.1.1", - "error-stack-parser": "^1.3.3", - "highlight-es": "^1.0.0", - "lodash": "4.6.1 || ^4.16.1", - "pinkie-promise": "^2.0.0" - }, - "dependencies": { - "ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", - "dev": true - }, - "ansi-styles": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", - "dev": true - }, - "chalk": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", - "dev": true, - "requires": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" - } - }, - "strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "dev": true, - "requires": { - "ansi-regex": "^2.0.0" - } - }, - "supports-color": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", - "dev": true - } - } - }, - "callsites": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", - "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", - "dev": true - }, - "camelcase": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==" - }, - "camelcase-keys": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-2.1.0.tgz", - "integrity": "sha1-MIvur/3ygRkFHvodkyITyRuPkuc=", - "dev": true, - "requires": { - "camelcase": "^2.0.0", - "map-obj": "^1.0.0" - }, - "dependencies": { - "camelcase": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-2.1.1.tgz", - "integrity": "sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8=", - "dev": true - } - } - }, - "capture-stack-trace": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/capture-stack-trace/-/capture-stack-trace-1.0.1.tgz", - "integrity": "sha512-mYQLZnx5Qt1JgB1WEiMCf2647plpGeQ2NMR/5L0HNZzGQo4fuSPnK+wjfPnKZV0aiJDgzmWqqkV/g7JD+DW0qw==", - "dev": true - }, - "caseless": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", - "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=" - }, - "catharsis": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/catharsis/-/catharsis-0.9.0.tgz", - "integrity": "sha512-prMTQVpcns/tzFgFVkVp6ak6RykZyWb3gu8ckUpd6YkTlacOd3DXGJjIpD4Q6zJirizvaiAjSSHlOsA+6sNh2A==", - "dev": true, - "requires": { - "lodash": "^4.17.15" - } - }, - "chai": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/chai/-/chai-4.3.4.tgz", - "integrity": "sha512-yS5H68VYOCtN1cjfwumDSuzn/9c+yza4f3reKXlE5rUg7SFcCEy90gJvydNgOYtblyf4Zi6jIWRnXOgErta0KA==", - "dev": true, - "requires": { - "assertion-error": "^1.1.0", - "check-error": "^1.0.2", - "deep-eql": "^3.0.1", - "get-func-name": "^2.0.0", - "pathval": "^1.1.1", - "type-detect": "^4.0.5" - } - }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "chardet": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz", - "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==" - }, - "check-error": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz", - "integrity": "sha1-V00xLt2Iu13YkS6Sht1sCu1KrII=", - "dev": true - }, - "chokidar": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.2.tgz", - "integrity": "sha512-ekGhOnNVPgT77r4K/U3GDhu+FQ2S8TnK/s2KbIGXi0SZWuwkZ2QNyfWdZW+TVfn84DpEP7rLeCt2UI6bJ8GwbQ==", - "dev": true, - "requires": { - "anymatch": "~3.1.2", - "braces": "~3.0.2", - "fsevents": "~2.3.2", - "glob-parent": "~5.1.2", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.6.0" - } - }, - "ci-info": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-1.6.0.tgz", - "integrity": "sha512-vsGdkwSCDpWmP80ncATX7iea5DWQemg1UgCW5J8tqjU3lYw4FBYuj89J0CTVomA7BEfvSZd84GmHko+MxFQU2A==", - "dev": true - }, - "clean-stack": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", - "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", - "dev": true - }, - "cli-boxes": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-2.2.1.tgz", - "integrity": "sha512-y4coMcylgSCdVinjiDBuR8PCC2bLjyGTwEmPb9NHR/QaNU6EUOXcTY/s6VjGMD6ENSEaeQYHCY0GNGS5jfMwPw==" - }, - "cli-cursor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", - "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", - "requires": { - "restore-cursor": "^3.1.0" - } - }, - "cli-progress": { - "version": "3.10.0", - "resolved": "https://registry.npmjs.org/cli-progress/-/cli-progress-3.10.0.tgz", - "integrity": "sha512-kLORQrhYCAtUPLZxqsAt2YJGOvRdt34+O6jl5cQGb7iF3dM55FQZlTR+rQyIK9JUcO9bBMwZsTlND+3dmFU2Cw==", - "requires": { - "string-width": "^4.2.0" - }, - "dependencies": { - "ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==" - }, - "emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" - }, - "is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==" - }, - "string-width": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz", - "integrity": "sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==", - "requires": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.0" - } - }, - "strip-ansi": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", - "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", - "requires": { - "ansi-regex": "^5.0.0" - } - } - } - }, - "cli-spinners": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-0.1.2.tgz", - "integrity": "sha1-u3ZNiOGF+54eaiofGXcjGPYF4xw=", - "dev": true - }, - "cli-truncate": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-3.1.0.tgz", - "integrity": "sha512-wfOBkjXteqSnI59oPcJkcPl/ZmwvMMOj340qUIY1SKZCv0B9Cf4D4fAucRkIKQmsIuYK3x1rrgU7MeGRruiuiA==", - "dev": true, - "requires": { - "slice-ansi": "^5.0.0", - "string-width": "^5.0.0" - }, - "dependencies": { - "ansi-regex": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", - "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", - "dev": true - }, - "emoji-regex": { - "version": "9.2.2", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", - "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", - "dev": true - }, - "is-fullwidth-code-point": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-4.0.0.tgz", - "integrity": "sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ==", - "dev": true - }, - "string-width": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.0.1.tgz", - "integrity": "sha512-5ohWO/M4//8lErlUUtrFy3b11GtNOuMOU0ysKCDXFcfXuuvUXu95akgj/i8ofmaGdN0hCqyl6uu9i8dS/mQp5g==", - "dev": true, - "requires": { - "emoji-regex": "^9.2.2", - "is-fullwidth-code-point": "^4.0.0", - "strip-ansi": "^7.0.1" - } - }, - "strip-ansi": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.0.1.tgz", - "integrity": "sha512-cXNxvT8dFNRVfhVME3JAe98mkXDYN2O1l7jmcwMnOslDeESg1rF/OZMtK0nRAhiari1unG5cD4jG3rapUAkLbw==", - "dev": true, - "requires": { - "ansi-regex": "^6.0.1" - } - } - } - }, - "cli-width": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.0.tgz", - "integrity": "sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk=", - "dev": true - }, - "cliui": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", - "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", - "dev": true, - "requires": { - "string-width": "^3.1.0", - "strip-ansi": "^5.2.0", - "wrap-ansi": "^5.1.0" - } - }, - "clone": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", - "integrity": "sha1-2jCcwmPfFZlMaIypAheco8fNfH4=" - }, - "clone-response": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.2.tgz", - "integrity": "sha1-0dyXOSAxTfZ/vrlCI7TuNQI56Ws=", - "requires": { - "mimic-response": "^1.0.0" - } - }, - "co": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", - "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=", - "dev": true - }, - "code-point-at": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", - "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", - "dev": true - }, - "collect-all": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/collect-all/-/collect-all-1.0.4.tgz", - "integrity": "sha512-RKZhRwJtJEP5FWul+gkSMEnaK6H3AGPTTWOiRimCcs+rc/OmQE3Yhy1Q7A7KsdkG3ZXVdZq68Y6ONSdvkeEcKA==", - "dev": true, - "requires": { - "stream-connect": "^1.0.2", - "stream-via": "^1.0.4" - } - }, - "color": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/color/-/color-3.0.0.tgz", - "integrity": "sha512-jCpd5+s0s0t7p3pHQKpnJ0TpQKKdleP71LWcA0aqiljpiuAkOSUFN/dyH8ZwF0hRmFlrIuRhufds1QyEP9EB+w==", - "requires": { - "color-convert": "^1.9.1", - "color-string": "^1.5.2" - } - }, - "color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "requires": { - "color-name": "1.1.3" - } - }, - "color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" - }, - "color-string": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.9.0.tgz", - "integrity": "sha512-9Mrz2AQLefkH1UvASKj6v6hj/7eWgjnT/cVsR8CumieLoT+g900exWeNogqtweI8dxloXN9BDQTYro1oWu/5CQ==", - "requires": { - "color-name": "^1.0.0", - "simple-swizzle": "^0.2.2" - } - }, - "colorette": { - "version": "2.0.16", - "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.16.tgz", - "integrity": "sha512-hUewv7oMjCp+wkBv5Rm0v87eJhq4woh5rSR+42YSQJKecCqgIqNkZ6lAlQms/BwHPJA5NKMRlpxPRv0n8HQW6g==", - "dev": true - }, - "colors": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz", - "integrity": "sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==" - }, - "colorspace": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/colorspace/-/colorspace-1.1.2.tgz", - "integrity": "sha512-vt+OoIP2d76xLhjwbBaucYlNSpPsrJWPlBTtwCpQKIu6/CSMutyzX93O/Do0qzpH3YoHEes8YEFXyZ797rEhzQ==", - "requires": { - "color": "3.0.x", - "text-hex": "1.0.x" - } - }, - "combined-stream": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", - "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", - "requires": { - "delayed-stream": "~1.0.0" - } - }, - "command-exists": { - "version": "1.2.9", - "resolved": "https://registry.npmjs.org/command-exists/-/command-exists-1.2.9.tgz", - "integrity": "sha512-LTQ/SGc+s0Xc0Fu5WaKnR0YiygZkm9eKFvyS+fRsU7/ZWFF8ykFM6Pc9aCVf1+xasOOZpO3BAVgVrKvsqKHV7w==" - }, - "command-line-args": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/command-line-args/-/command-line-args-5.1.1.tgz", - "integrity": "sha512-hL/eG8lrll1Qy1ezvkant+trihbGnaKaeEjj6Scyr3DN+RC7iQ5Rz84IeLERfAWDGo0HBSNAakczwgCilDXnWg==", - "dev": true, - "requires": { - "array-back": "^3.0.1", - "find-replace": "^3.0.0", - "lodash.camelcase": "^4.3.0", - "typical": "^4.0.0" - }, - "dependencies": { - "array-back": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/array-back/-/array-back-3.1.0.tgz", - "integrity": "sha512-TkuxA4UCOvxuDK6NZYXCalszEzj+TLszyASooky+i742l9TqsOdYCMJJupxRic61hwquNtppB3hgcuq9SVSH1Q==", - "dev": true - }, - "typical": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/typical/-/typical-4.0.0.tgz", - "integrity": "sha512-VAH4IvQ7BDFYglMd7BPRDfLgxZZX4O4TFcRDA6EN5X7erNJJq+McIEp8np9aVtxrCJ6qx4GTYVfOWNjcqwZgRw==", - "dev": true - } - } - }, - "command-line-tool": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/command-line-tool/-/command-line-tool-0.8.0.tgz", - "integrity": "sha512-Xw18HVx/QzQV3Sc5k1vy3kgtOeGmsKIqwtFFoyjI4bbcpSgnw2CWVULvtakyw4s6fhyAdI6soQQhXc2OzJy62g==", - "dev": true, - "requires": { - "ansi-escape-sequences": "^4.0.0", - "array-back": "^2.0.0", - "command-line-args": "^5.0.0", - "command-line-usage": "^4.1.0", - "typical": "^2.6.1" - }, - "dependencies": { - "array-back": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/array-back/-/array-back-2.0.0.tgz", - "integrity": "sha512-eJv4pLLufP3g5kcZry0j6WXpIbzYw9GUB4mVJZno9wfwiBxbizTnHCw3VJb07cBihbFX48Y7oSrW9y+gt4glyw==", - "dev": true, - "requires": { - "typical": "^2.6.1" - } - } - } - }, - "command-line-usage": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/command-line-usage/-/command-line-usage-4.1.0.tgz", - "integrity": "sha512-MxS8Ad995KpdAC0Jopo/ovGIroV/m0KHwzKfXxKag6FHOkGsH8/lv5yjgablcRxCJJC0oJeUMuO/gmaq+Wq46g==", - "dev": true, - "requires": { - "ansi-escape-sequences": "^4.0.0", - "array-back": "^2.0.0", - "table-layout": "^0.4.2", - "typical": "^2.6.1" - }, - "dependencies": { - "array-back": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/array-back/-/array-back-2.0.0.tgz", - "integrity": "sha512-eJv4pLLufP3g5kcZry0j6WXpIbzYw9GUB4mVJZno9wfwiBxbizTnHCw3VJb07cBihbFX48Y7oSrW9y+gt4glyw==", - "dev": true, - "requires": { - "typical": "^2.6.1" - } - } - } - }, - "commander": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz", - "integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==", - "dev": true - }, - "common-sequence": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/common-sequence/-/common-sequence-2.0.2.tgz", - "integrity": "sha512-jAg09gkdkrDO9EWTdXfv80WWH3yeZl5oT69fGfedBNS9pXUKYInVJ1bJ+/ht2+Moeei48TmSbQDYMc8EOx9G0g==", - "dev": true - }, - "concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", - "dev": true - }, - "config-master": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/config-master/-/config-master-3.1.0.tgz", - "integrity": "sha1-ZnZjWQUFooO/JqSE1oSJ10xUhdo=", - "dev": true, - "requires": { - "walk-back": "^2.0.1" - }, - "dependencies": { - "walk-back": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/walk-back/-/walk-back-2.0.1.tgz", - "integrity": "sha1-VU4qnYdPrEeoywBr9EwvDEmYoKQ=", - "dev": true - } - } - }, - "configstore": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/configstore/-/configstore-5.0.1.tgz", - "integrity": "sha512-aMKprgk5YhBNyH25hj8wGt2+D52Sw1DRRIzqBwLp2Ya9mFmY8KPvvtvmna8SxVR9JMZ4kzMD68N22vlaRpkeFA==", - "requires": { - "dot-prop": "^5.2.0", - "graceful-fs": "^4.1.2", - "make-dir": "^3.0.0", - "unique-string": "^2.0.0", - "write-file-atomic": "^3.0.0", - "xdg-basedir": "^4.0.0" - } - }, - "console.table": { - "version": "0.10.0", - "resolved": "https://registry.npmjs.org/console.table/-/console.table-0.10.0.tgz", - "integrity": "sha1-CRcCVYiHW+/XDPLv9L7yxuLXXQQ=", - "requires": { - "easy-table": "1.1.0" - } - }, - "core-js": { - "version": "2.6.11", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.11.tgz", - "integrity": "sha512-5wjnpaT/3dV+XB4borEsnAYQchn00XSgTAWKDkEqv+K8KevjbzmofK6hfJ9TZIlpj2N0xQpazy7PiRQiWHqzWg==" - }, - "core-util-is": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" - }, - "create-error-class": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/create-error-class/-/create-error-class-3.0.2.tgz", - "integrity": "sha1-Br56vvlHo/FKMP1hBnHUAbyot7Y=", - "dev": true, - "requires": { - "capture-stack-trace": "^1.0.0" - } - }, - "cross-spawn": { - "version": "6.0.5", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", - "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", - "dev": true, - "requires": { - "nice-try": "^1.0.4", - "path-key": "^2.0.1", - "semver": "^5.5.0", - "shebang-command": "^1.2.0", - "which": "^1.2.9" - }, - "dependencies": { - "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true - } - } - }, - "cross-spawn-async": { - "version": "2.2.5", - "resolved": "https://registry.npmjs.org/cross-spawn-async/-/cross-spawn-async-2.2.5.tgz", - "integrity": "sha1-hF/wwINKPe2dFg2sptOQkGuyiMw=", - "dev": true, - "requires": { - "lru-cache": "^4.0.0", - "which": "^1.2.8" - } - }, - "crypto-random-string": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-2.0.0.tgz", - "integrity": "sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA==" - }, - "currently-unhandled": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/currently-unhandled/-/currently-unhandled-0.4.1.tgz", - "integrity": "sha1-mI3zP+qxke95mmE2nddsF635V+o=", - "dev": true, - "requires": { - "array-find-index": "^1.0.1" - } - }, - "dashdash": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", - "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", - "requires": { - "assert-plus": "^1.0.0" - } - }, - "de-indent": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/de-indent/-/de-indent-1.0.2.tgz", - "integrity": "sha1-sgOOhG3DO6pXlhKNCAS0VbjB4h0=", - "dev": true - }, - "debug": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", - "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", - "requires": { - "ms": "2.1.2" - } - }, - "decamelize": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", - "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", - "dev": true - }, - "decompress-response": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-3.3.0.tgz", - "integrity": "sha1-gKTdMjdIOEv6JICDYirt7Jgq3/M=", - "requires": { - "mimic-response": "^1.0.0" - } - }, - "deep-eql": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-3.0.1.tgz", - "integrity": "sha512-+QeIQyN5ZuO+3Uk5DYh6/1eKO0m0YmJFGNmFHGACpf1ClL1nmlV/p4gNgbl2pJGxgXb4faqo6UE+M5ACEMyVcw==", - "dev": true, - "requires": { - "type-detect": "^4.0.0" - } - }, - "deep-extend": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", - "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==" - }, - "deep-is": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", - "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", - "dev": true - }, - "defaults": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.3.tgz", - "integrity": "sha1-xlYFHpgX2f8I7YgUd/P+QBnz730=", - "requires": { - "clone": "^1.0.2" - } - }, - "defer-to-connect": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-1.1.3.tgz", - "integrity": "sha512-0ISdNousHvZT2EiFlZeZAHBUvSxmKswVCEf8hW7KWgG4a8MVEu/3Vb6uWYozkjylyCxe0JBIiRB1jV45S70WVQ==" - }, - "define-properties": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", - "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", - "requires": { - "object-keys": "^1.0.12" - } - }, - "delayed-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" - }, - "depcheck": { - "version": "0.8.3", - "resolved": "https://registry.npmjs.org/depcheck/-/depcheck-0.8.3.tgz", - "integrity": "sha512-xcLTnaovCFFTts5Ge7mUUhMGHSu6eRfftvVvOjN7gXO5EFUhJfX6UQa1b08a0SIwKfzG9eKNn5mzZlXp0mZARA==", - "dev": true, - "requires": { - "@babel/parser": "^7.3.1", - "@babel/traverse": "^7.2.3", - "builtin-modules": "^3.0.0", - "deprecate": "^1.0.0", - "deps-regex": "^0.1.4", - "js-yaml": "^3.4.2", - "lodash": "^4.17.11", - "minimatch": "^3.0.2", - "node-sass-tilde-importer": "^1.0.2", - "please-upgrade-node": "^3.1.1", - "require-package-name": "^2.0.1", - "resolve": "^1.10.0", - "vue-template-compiler": "^2.6.10", - "walkdir": "^0.3.2", - "yargs": "^13.2.2" - }, - "dependencies": { - "yargs": { - "version": "13.3.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.2.tgz", - "integrity": "sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw==", - "dev": true, - "requires": { - "cliui": "^5.0.0", - "find-up": "^3.0.0", - "get-caller-file": "^2.0.1", - "require-directory": "^2.1.1", - "require-main-filename": "^2.0.0", - "set-blocking": "^2.0.0", - "string-width": "^3.0.0", - "which-module": "^2.0.0", - "y18n": "^4.0.0", - "yargs-parser": "^13.1.2" - } - } - } - }, - "deprecate": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/deprecate/-/deprecate-1.1.1.tgz", - "integrity": "sha512-ZGDXefq1xknT292LnorMY5s8UVU08/WKdzDZCUT6t9JzsiMSP4uzUhgpqugffNVcT5WC6wMBiSQ+LFjlv3v7iQ==", - "dev": true - }, - "deps-regex": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/deps-regex/-/deps-regex-0.1.4.tgz", - "integrity": "sha1-UYZnt2kUYKXn4KNBvnbrfOgJAYQ=", - "dev": true - }, - "diff": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-5.0.0.tgz", - "integrity": "sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==", - "dev": true - }, - "dmd": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/dmd/-/dmd-6.0.0.tgz", - "integrity": "sha512-PwWZlqZnJPETwqZZ70haRa+UDZcD5jeBD3ywW1Kf+jYYv0MHu/S7Ri9jsSoeTMwkcMVW9hXOMA1IZUMEufBhOg==", - "dev": true, - "requires": { - "array-back": "^5.0.0", - "cache-point": "^2.0.0", - "common-sequence": "^2.0.0", - "file-set": "^4.0.1", - "handlebars": "^4.7.7", - "marked": "^2.0.0", - "object-get": "^2.1.1", - "reduce-flatten": "^3.0.0", - "reduce-unique": "^2.0.1", - "reduce-without": "^1.0.1", - "test-value": "^3.0.0", - "walk-back": "^5.0.0" - }, - "dependencies": { - "array-back": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/array-back/-/array-back-5.0.0.tgz", - "integrity": "sha512-kgVWwJReZWmVuWOQKEOohXKJX+nD02JAZ54D1RRWlv8L0NebauKAaFxACKzB74RTclt1+WNz5KHaLRDAPZbDEw==", - "dev": true - }, - "reduce-flatten": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/reduce-flatten/-/reduce-flatten-3.0.0.tgz", - "integrity": "sha512-eczl8wAYBxJ6Egl6I1ECIF+8z6sHu+KE7BzaEDZTpPXKXfy9SUDQlVYwkRcNTjJLC3Iakxbhss50KuT/R6SYfg==", - "dev": true - } - } - }, - "doctrine": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", - "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", - "dev": true, - "requires": { - "esutils": "^2.0.2" - } - }, - "dot-prop": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-5.3.0.tgz", - "integrity": "sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q==", - "requires": { - "is-obj": "^2.0.0" - } - }, - "duplexer3": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.4.tgz", - "integrity": "sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI=" - }, - "easy-table": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/easy-table/-/easy-table-1.1.0.tgz", - "integrity": "sha1-hvmrTBAvA3G3KXuSplHVgkvIy3M=", - "requires": { - "wcwidth": ">=1.0.1" - } - }, - "ecc-jsbn": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", - "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=", - "requires": { - "jsbn": "~0.1.0", - "safer-buffer": "^2.1.0" - } - }, - "emoji-regex": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", - "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", - "dev": true - }, - "enabled": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/enabled/-/enabled-2.0.0.tgz", - "integrity": "sha512-AKrN98kuwOzMIdAizXGI86UFBoo26CL21UM763y1h/GMSJ4/OHU9k2YlsmBpyScFo/wbLzWQJBMCW4+IO3/+OQ==" - }, - "end-of-stream": { - "version": "1.4.4", - "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", - "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", - "requires": { - "once": "^1.4.0" - } - }, - "enquirer": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz", - "integrity": "sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==", - "dev": true, - "requires": { - "ansi-colors": "^4.1.1" - } - }, - "entities": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/entities/-/entities-2.0.3.tgz", - "integrity": "sha512-MyoZ0jgnLvB2X3Lg5HqpFmn1kybDiIfEQmKzTb5apr51Rb+T3KdmMiqa70T+bhGnyv7bQ6WMj2QMHpGMmlrUYQ==", - "dev": true - }, - "error-ex": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", - "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", - "dev": true, - "requires": { - "is-arrayish": "^0.2.1" - }, - "dependencies": { - "is-arrayish": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", - "dev": true - } - } - }, - "error-stack-parser": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/error-stack-parser/-/error-stack-parser-1.3.6.tgz", - "integrity": "sha1-4Oc7k+QXE40c18C3RrGkoUhUwpI=", - "dev": true, - "requires": { - "stackframe": "^0.3.1" - } - }, - "es-abstract": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.15.0.tgz", - "integrity": "sha512-bhkEqWJ2t2lMeaJDuk7okMkJWI/yqgH/EoGwpcvv0XW9RWQsRspI4wt6xuyuvMvvQE3gg/D9HXppgk21w78GyQ==", - "requires": { - "es-to-primitive": "^1.2.0", - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.0", - "is-callable": "^1.1.4", - "is-regex": "^1.0.4", - "object-inspect": "^1.6.0", - "object-keys": "^1.1.1", - "string.prototype.trimleft": "^2.1.0", - "string.prototype.trimright": "^2.1.0" - } - }, - "es-to-primitive": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.0.tgz", - "integrity": "sha512-qZryBOJjV//LaxLTV6UC//WewneB3LcXOL9NP++ozKVXsIIIpm/2c13UDiD9Jp2eThsecw9m3jPqDwTyobcdbg==", - "requires": { - "is-callable": "^1.1.4", - "is-date-object": "^1.0.1", - "is-symbol": "^1.0.2" - } - }, - "escalade": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", - "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==" - }, - "escape-goat": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/escape-goat/-/escape-goat-2.1.1.tgz", - "integrity": "sha512-8/uIhbG12Csjy2JEW7D9pHbreaVaS/OpN3ycnyvElTdwM5n6GY6W6e2IPemfvGZeUMqZ9A/3GqIZMgKnBhAw/Q==" - }, - "escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=" - }, - "eslint": { - "version": "8.4.1", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.4.1.tgz", - "integrity": "sha512-TxU/p7LB1KxQ6+7aztTnO7K0i+h0tDi81YRY9VzB6Id71kNz+fFYnf5HD5UOQmxkzcoa0TlVZf9dpMtUv0GpWg==", - "dev": true, - "requires": { - "@eslint/eslintrc": "^1.0.5", - "@humanwhocodes/config-array": "^0.9.2", - "ajv": "^6.10.0", - "chalk": "^4.0.0", - "cross-spawn": "^7.0.2", - "debug": "^4.3.2", - "doctrine": "^3.0.0", - "enquirer": "^2.3.5", - "escape-string-regexp": "^4.0.0", - "eslint-scope": "^7.1.0", - "eslint-utils": "^3.0.0", - "eslint-visitor-keys": "^3.1.0", - "espree": "^9.2.0", - "esquery": "^1.4.0", - "esutils": "^2.0.2", - "fast-deep-equal": "^3.1.3", - "file-entry-cache": "^6.0.1", - "functional-red-black-tree": "^1.0.1", - "glob-parent": "^6.0.1", - "globals": "^13.6.0", - "ignore": "^4.0.6", - "import-fresh": "^3.0.0", - "imurmurhash": "^0.1.4", - "is-glob": "^4.0.0", - "js-yaml": "^4.1.0", - "json-stable-stringify-without-jsonify": "^1.0.1", - "levn": "^0.4.1", - "lodash.merge": "^4.6.2", - "minimatch": "^3.0.4", - "natural-compare": "^1.4.0", - "optionator": "^0.9.1", - "progress": "^2.0.0", - "regexpp": "^3.2.0", - "semver": "^7.2.1", - "strip-ansi": "^6.0.1", - "strip-json-comments": "^3.1.0", - "text-table": "^0.2.0", - "v8-compile-cache": "^2.0.3" - }, - "dependencies": { - "ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true - }, - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true - }, - "chalk": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", - "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", - "dev": true, - "requires": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - } - }, - "escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "dev": true - }, - "glob-parent": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", - "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", - "dev": true, - "requires": { - "is-glob": "^4.0.3" - } - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "dev": true, - "requires": { - "argparse": "^2.0.1" - } - }, - "path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true - }, - "shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dev": true, - "requires": { - "shebang-regex": "^3.0.0" - } - }, - "shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "dev": true - }, - "strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, - "requires": { - "ansi-regex": "^5.0.1" - } - }, - "strip-json-comments": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", - "dev": true - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - }, - "which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, - "requires": { - "isexe": "^2.0.0" - } - } - } - }, - "eslint-config-prettier": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-8.3.0.tgz", - "integrity": "sha512-BgZuLUSeKzvlL/VUjx/Yb787VQ26RU3gGjA3iiFvdsp/2bMfVIWUVP7tjxtjS0e+HP409cPlPvNkQloz8C91ew==", - "dev": true, - "requires": {} - }, - "eslint-config-ssjs": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/eslint-config-ssjs/-/eslint-config-ssjs-1.1.11.tgz", - "integrity": "sha512-8C7J0TgjkwQM4j7vra9/SuqjhZa+rq6CrPzwPnPRqcrVclfOFqI6uoo3LXMnxCI/ovOoOy0KqmD++uzIXsmr5g==", - "dev": true - }, - "eslint-plugin-mocha": { - "version": "10.0.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-mocha/-/eslint-plugin-mocha-10.0.1.tgz", - "integrity": "sha512-XSsqkSE0ViKLjYWO5Z9AcNvPBupTXDlI60TEUsJMNYQFUKZmDzO0Gh3OsSmZ2j5iYl0qT8muJzxTKRwVC6M0wA==", - "dev": true, - "requires": { - "eslint-utils": "^3.0.0", - "ramda": "^0.27.1" - } - }, - "eslint-plugin-prettier": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-4.0.0.tgz", - "integrity": "sha512-98MqmCJ7vJodoQK359bqQWaxOE0CS8paAz/GgjaZLyex4TTk3g9HugoO89EqWCrFiOqn9EVvcoo7gZzONCWVwQ==", - "dev": true, - "requires": { - "prettier-linter-helpers": "^1.0.0" - } - }, - "eslint-scope": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.1.0.tgz", - "integrity": "sha512-aWwkhnS0qAXqNOgKOK0dJ2nvzEbhEvpy8OlJ9kZ0FeZnA6zpjv1/Vei+puGFFX7zkPCkHHXb7IDX3A+7yPrRWg==", - "dev": true, - "requires": { - "esrecurse": "^4.3.0", - "estraverse": "^5.2.0" - } - }, - "eslint-utils": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz", - "integrity": "sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==", - "dev": true, - "requires": { - "eslint-visitor-keys": "^2.0.0" - }, - "dependencies": { - "eslint-visitor-keys": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", - "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", - "dev": true - } - } - }, - "eslint-visitor-keys": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.1.0.tgz", - "integrity": "sha512-yWJFpu4DtjsWKkt5GeNBBuZMlNcYVs6vRCLoCVEJrTjaSB6LC98gFipNK/erM2Heg/E8mIK+hXG/pJMLK+eRZA==", - "dev": true - }, - "espree": { - "version": "9.2.0", - "resolved": "https://registry.npmjs.org/espree/-/espree-9.2.0.tgz", - "integrity": "sha512-oP3utRkynpZWF/F2x/HZJ+AGtnIclaR7z1pYPxy7NYM2fSO6LgK/Rkny8anRSPK/VwEA1eqm2squui0T7ZMOBg==", - "dev": true, - "requires": { - "acorn": "^8.6.0", - "acorn-jsx": "^5.3.1", - "eslint-visitor-keys": "^3.1.0" - } - }, - "esprima": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", - "dev": true - }, - "esquery": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.4.0.tgz", - "integrity": "sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==", - "dev": true, - "requires": { - "estraverse": "^5.1.0" - } - }, - "esrecurse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", - "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", - "dev": true, - "requires": { - "estraverse": "^5.2.0" - } - }, - "estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true - }, - "esutils": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", - "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", - "dev": true - }, - "execa": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/execa/-/execa-0.2.2.tgz", - "integrity": "sha1-4urUcsLDGq1vc/GslW7vReEjIMs=", - "dev": true, - "requires": { - "cross-spawn-async": "^2.1.1", - "npm-run-path": "^1.0.0", - "object-assign": "^4.0.1", - "path-key": "^1.0.0", - "strip-eof": "^1.0.0" - }, - "dependencies": { - "path-key": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-1.0.0.tgz", - "integrity": "sha1-XVPVeAGWRsDWiADbThRua9wqx68=", - "dev": true - } - } - }, - "exit-hook": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/exit-hook/-/exit-hook-1.1.1.tgz", - "integrity": "sha1-8FyiM7SMBdVP/wd2XfhQfpXAL/g=", - "dev": true - }, - "expand-tilde": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-2.0.2.tgz", - "integrity": "sha1-l+gBqgUt8CRU3kawK/YhZCzchQI=", - "dev": true, - "requires": { - "homedir-polyfill": "^1.0.1" - } - }, - "extend": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", - "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" - }, - "external-editor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz", - "integrity": "sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==", - "requires": { - "chardet": "^0.7.0", - "iconv-lite": "^0.4.24", - "tmp": "^0.0.33" - } - }, - "extsprintf": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", - "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=" - }, - "fast-deep-equal": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" - }, - "fast-diff": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.2.0.tgz", - "integrity": "sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w==", - "dev": true - }, - "fast-json-stable-stringify": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", - "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=" - }, - "fast-levenshtein": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", - "dev": true - }, - "fecha": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/fecha/-/fecha-4.2.1.tgz", - "integrity": "sha512-MMMQ0ludy/nBs1/o0zVOiKTpG7qMbonKUzjJgQFEuvq6INZ1OraKPRAWkBq5vlKLOUMpmNYG1JoN3oDPUQ9m3Q==" - }, - "figures": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", - "integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==", - "requires": { - "escape-string-regexp": "^1.0.5" - } - }, - "file-entry-cache": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", - "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", - "dev": true, - "requires": { - "flat-cache": "^3.0.4" - } - }, - "file-set": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/file-set/-/file-set-4.0.2.tgz", - "integrity": "sha512-fuxEgzk4L8waGXaAkd8cMr73Pm0FxOVkn8hztzUW7BAHhOGH90viQNXbiOsnecCWmfInqU6YmAMwxRMdKETceQ==", - "dev": true, - "requires": { - "array-back": "^5.0.0", - "glob": "^7.1.6" - }, - "dependencies": { - "array-back": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/array-back/-/array-back-5.0.0.tgz", - "integrity": "sha512-kgVWwJReZWmVuWOQKEOohXKJX+nD02JAZ54D1RRWlv8L0NebauKAaFxACKzB74RTclt1+WNz5KHaLRDAPZbDEw==", - "dev": true - } - } - }, - "fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", - "dev": true, - "requires": { - "to-regex-range": "^5.0.1" - } - }, - "find-parent-dir": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/find-parent-dir/-/find-parent-dir-0.3.0.tgz", - "integrity": "sha1-M8RLQpqysvBkYpnF+fcY83b/jVQ=", - "dev": true - }, - "find-replace": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/find-replace/-/find-replace-3.0.0.tgz", - "integrity": "sha512-6Tb2myMioCAgv5kfvP5/PkZZ/ntTpVK39fHY7WkWBgvbeE+VHd/tZuZ4mrC+bxh4cfOZeYKVPaJIZtZXV7GNCQ==", - "dev": true, - "requires": { - "array-back": "^3.0.1" - }, - "dependencies": { - "array-back": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/array-back/-/array-back-3.1.0.tgz", - "integrity": "sha512-TkuxA4UCOvxuDK6NZYXCalszEzj+TLszyASooky+i742l9TqsOdYCMJJupxRic61hwquNtppB3hgcuq9SVSH1Q==", - "dev": true - } - } - }, - "find-up": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", - "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", - "dev": true, - "requires": { - "locate-path": "^3.0.0" - } - }, - "flat": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", - "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", - "dev": true - }, - "flat-cache": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", - "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", - "dev": true, - "requires": { - "flatted": "^3.1.0", - "rimraf": "^3.0.2" - } - }, - "flatted": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.1.1.tgz", - "integrity": "sha512-zAoAQiudy+r5SvnSw3KJy5os/oRJYHzrzja/tBDqrZtNhUw8bt6y8OBzMWcjWr+8liV8Eb6yOhw8WZ7VFZ5ZzA==", - "dev": true - }, - "fn.name": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/fn.name/-/fn.name-1.1.0.tgz", - "integrity": "sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw==" - }, - "forever-agent": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", - "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=" - }, - "form-data": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", - "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", - "requires": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.6", - "mime-types": "^2.1.12" - } - }, - "fs-extra": { - "version": "10.0.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.0.0.tgz", - "integrity": "sha512-C5owb14u9eJwizKGdchcDUQeFtlSHHthBk8pbX9Vc1PFZrLombudjDnNns88aYslCyF6IY5SUw3Roz6xShcEIQ==", - "requires": { - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - }, - "dependencies": { - "universalify": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", - "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==" - } - } - }, - "fs-then-native": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/fs-then-native/-/fs-then-native-2.0.0.tgz", - "integrity": "sha1-GaEk2U2QwiyOBF8ujdbr6jbUjGc=", - "dev": true - }, - "fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", - "dev": true - }, - "fsevents": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", - "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", - "dev": true, - "optional": true - }, - "fuel-auth": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/fuel-auth/-/fuel-auth-3.3.0.tgz", - "integrity": "sha512-ZJSfLmhcTHkY8h9i7Wmb8hebYjC064zLC+LxUaFj78qUQ/T/5v2rVwJ5dtpqhJ6BLwpVepKa0hDMfHak8+WaYA==", - "requires": { - "lodash.merge": "^4.6.1", - "request": "~2.88.0" - } - }, - "fuel-rest": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/fuel-rest/-/fuel-rest-3.2.2.tgz", - "integrity": "sha512-vqCvpOblssPQPLtn9QKCz4pMleRBneUUY0OXQc8tGyv+7qynwpkNw62OJw346RzKG4TtN9EuHb80Cm26aJCz6Q==", - "requires": { - "fuel-auth": "^3.3.0", - "lodash.clone": "~4.5.0", - "lodash.isplainobject": "~4.0.4", - "lodash.merge": "^4.6.1", - "request": "~2.88.0" - } - }, - "fuel-soap": { - "version": "2.2.4", - "resolved": "https://registry.npmjs.org/fuel-soap/-/fuel-soap-2.2.4.tgz", - "integrity": "sha512-0+glcwMlBuF7NUpNNJ6x0gpUWOJzgT58GYnLIIuOaDrG7eS3i8JnOG+oElBCKdbymrmAqLwUBLsdBDYm/EdbQA==", - "requires": { - "fuel-auth": "^3.3.0", - "lodash.clone": "^4.5.0", - "lodash.isempty": "^4.4.0", - "lodash.isplainobject": "^4.0.3", - "lodash.merge": "^4.6.0", - "request": "^2.81.0", - "xml2js": "^0.4.16" - } - }, - "function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" - }, - "functional-red-black-tree": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", - "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", - "dev": true - }, - "get-caller-file": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==" - }, - "get-func-name": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.0.tgz", - "integrity": "sha1-6td0q+5y4gQJQzoGY2YCPdaIekE=", - "dev": true - }, - "get-stream": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", - "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=", - "dev": true - }, - "getpass": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", - "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", - "requires": { - "assert-plus": "^1.0.0" - } - }, - "git-version-tag": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/git-version-tag/-/git-version-tag-1.0.2.tgz", - "integrity": "sha512-342rLtHtBdXcgngQOPhHt+IhxLbrijmd+Pa9rWDnQ9ubZYrWWSOWSQd9MTi8xo599RkrWkYh4lTYrNzPNxTmsQ==", - "requires": { - "semver": "^5.6.0", - "simple-git": "^2.17.0" - }, - "dependencies": { - "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==" - } - } - }, - "giturl": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/giturl/-/giturl-1.0.1.tgz", - "integrity": "sha512-wQourBdI13n8tbjcZTDl6k+ZrCRMU6p9vfp9jknZq+zfWc8xXNztpZFM4XkPHVzHcMSUZxEMYYKZjIGkPlei6Q==", - "dev": true - }, - "glob": { - "version": "7.1.7", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.7.tgz", - "integrity": "sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==", - "dev": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "requires": { - "is-glob": "^4.0.1" - } - }, - "global-modules": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-1.0.0.tgz", - "integrity": "sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg==", - "dev": true, - "requires": { - "global-prefix": "^1.0.1", - "is-windows": "^1.0.1", - "resolve-dir": "^1.0.0" - } - }, - "global-prefix": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-1.0.2.tgz", - "integrity": "sha1-2/dDxsFJklk8ZVVoy2btMsASLr4=", - "dev": true, - "requires": { - "expand-tilde": "^2.0.2", - "homedir-polyfill": "^1.0.1", - "ini": "^1.3.4", - "is-windows": "^1.0.1", - "which": "^1.2.14" - } - }, - "globals": { - "version": "13.12.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.12.0.tgz", - "integrity": "sha512-uS8X6lSKN2JumVoXrbUz+uG4BYG+eiawqm3qFcT7ammfbUHeCBoJMlHcec/S3krSk73/AE/f0szYFmgAA3kYZg==", - "dev": true, - "requires": { - "type-fest": "^0.20.2" - }, - "dependencies": { - "type-fest": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", - "dev": true - } - } - }, - "globby": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-4.1.0.tgz", - "integrity": "sha1-CA9UVJ7BuCpsYOYx/ILhIR2+lfg=", - "dev": true, - "requires": { - "array-union": "^1.0.1", - "arrify": "^1.0.0", - "glob": "^6.0.1", - "object-assign": "^4.0.1", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0" - }, - "dependencies": { - "glob": { - "version": "6.0.4", - "resolved": "https://registry.npmjs.org/glob/-/glob-6.0.4.tgz", - "integrity": "sha1-DwiGD2oVUSey+t1PnOJLGqtuTSI=", - "dev": true, - "requires": { - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "2 || 3", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", - "dev": true - } - } - }, - "got": { - "version": "6.7.1", - "resolved": "https://registry.npmjs.org/got/-/got-6.7.1.tgz", - "integrity": "sha1-JAzQV4WpoY5WHcG0S0HHY+8ejbA=", - "dev": true, - "requires": { - "create-error-class": "^3.0.0", - "duplexer3": "^0.1.4", - "get-stream": "^3.0.0", - "is-redirect": "^1.0.0", - "is-retry-allowed": "^1.0.0", - "is-stream": "^1.0.0", - "lowercase-keys": "^1.0.0", - "safe-buffer": "^5.0.1", - "timed-out": "^4.0.0", - "unzip-response": "^2.0.1", - "url-parse-lax": "^1.0.0" - } - }, - "graceful-fs": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.2.tgz", - "integrity": "sha512-IItsdsea19BoLC7ELy13q1iJFNmd7ofZH5+X/pJr90/nRoPEX0DJo1dHDbgtYWOhJhcCgMDTOw84RZ72q6lB+Q==" - }, - "growl": { - "version": "1.10.5", - "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz", - "integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==", - "dev": true - }, - "handlebars": { - "version": "4.7.7", - "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.7.tgz", - "integrity": "sha512-aAcXm5OAfE/8IXkcZvCepKU3VzW1/39Fb5ZuqMtgI/hT8X2YgoMvBY5dLhq/cpOvw7Lk1nK/UF71aLG/ZnVYRA==", - "dev": true, - "requires": { - "minimist": "^1.2.5", - "neo-async": "^2.6.0", - "source-map": "^0.6.1", - "uglify-js": "^3.1.4", - "wordwrap": "^1.0.0" - } - }, - "har-schema": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", - "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=" - }, - "har-validator": { - "version": "5.1.3", - "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.3.tgz", - "integrity": "sha512-sNvOCzEQNr/qrvJgc3UG/kD4QtlHycrzwS+6mfTrrSq97BvaYcPZZI1ZSqGSPR73Cxn4LKTD4PttRwfU7jWq5g==", - "requires": { - "ajv": "^6.5.5", - "har-schema": "^2.0.0" - } - }, - "has": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "requires": { - "function-bind": "^1.1.1" - } - }, - "has-ansi": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", - "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", - "dev": true, - "requires": { - "ansi-regex": "^2.0.0" - }, - "dependencies": { - "ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", - "dev": true - } - } - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true - }, - "has-symbols": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.0.tgz", - "integrity": "sha1-uhqPGvKg/DllD1yFA2dwQSIGO0Q=" - }, - "has-yarn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/has-yarn/-/has-yarn-2.1.0.tgz", - "integrity": "sha512-UqBRqi4ju7T+TqGNdqAO0PaSVGsDGJUBQvk9eUWNGRY1CFGDzYhLWoM7JQEemnlvVcv/YEmc2wNW8BC24EnUsw==" - }, - "he": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", - "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", - "dev": true - }, - "highlight-es": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/highlight-es/-/highlight-es-1.0.3.tgz", - "integrity": "sha512-s/SIX6yp/5S1p8aC/NRDC1fwEb+myGIfp8/TzZz0rtAv8fzsdX7vGl3Q1TrXCsczFq8DI3CBFBCySPClfBSdbg==", - "dev": true, - "requires": { - "chalk": "^2.4.0", - "is-es2016-keyword": "^1.0.0", - "js-tokens": "^3.0.0" - }, - "dependencies": { - "js-tokens": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz", - "integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls=", - "dev": true - } - } - }, - "homedir-polyfill": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz", - "integrity": "sha512-eSmmWE5bZTK2Nou4g0AI3zZ9rswp7GRKoKXS1BLUkvPviOqs4YTN1djQIqrXy9k5gEtdLPy86JjRwsNM9tnDcA==", - "dev": true, - "requires": { - "parse-passwd": "^1.0.0" - } - }, - "hosted-git-info": { - "version": "2.8.9", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", - "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", - "dev": true - }, - "http-cache-semantics": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz", - "integrity": "sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ==" - }, - "http-signature": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", - "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", - "requires": { - "assert-plus": "^1.0.0", - "jsprim": "^1.2.2", - "sshpk": "^1.7.0" - } - }, - "human-signals": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", - "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", - "dev": true - }, - "husky": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/husky/-/husky-7.0.4.tgz", - "integrity": "sha512-vbaCKN2QLtP/vD4yvs6iz6hBEo6wkSzs8HpRah1Z6aGmF2KW5PdYuAd7uX5a+OyBZHBhd+TFLqgjUgytQr4RvQ==", - "dev": true - }, - "iconv-lite": { - "version": "0.4.24", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", - "requires": { - "safer-buffer": ">= 2.1.2 < 3" - } - }, - "ieee754": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", - "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==" - }, - "ignore": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", - "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", - "dev": true - }, - "import-fresh": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.2.2.tgz", - "integrity": "sha512-cTPNrlvJT6twpYy+YmKUKrTSjWFs3bjYjAhCwm+z4EOCubZxAuO+hHpRN64TqjEaYSHs7tJAE0w1CKMGmsG/lw==", - "dev": true, - "requires": { - "parent-module": "^1.0.0", - "resolve-from": "^4.0.0" - } - }, - "import-lazy": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/import-lazy/-/import-lazy-2.1.0.tgz", - "integrity": "sha1-BWmOPUXIjo1+nZLLBYTnfwlvPkM=" - }, - "imurmurhash": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=" - }, - "indent-string": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-2.1.0.tgz", - "integrity": "sha1-ji1INIdCEhtKghi3oTfppSBJ3IA=", - "dev": true, - "requires": { - "repeating": "^2.0.0" - } - }, - "inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", - "dev": true, - "requires": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" - }, - "ini": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", - "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==" - }, - "inquirer": { - "version": "8.2.0", - "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-8.2.0.tgz", - "integrity": "sha512-0crLweprevJ02tTuA6ThpoAERAGyVILC4sS74uib58Xf/zSr1/ZWtmm7D5CI+bSQEaA04f0K7idaHpQbSWgiVQ==", - "requires": { - "ansi-escapes": "^4.2.1", - "chalk": "^4.1.1", - "cli-cursor": "^3.1.0", - "cli-width": "^3.0.0", - "external-editor": "^3.0.3", - "figures": "^3.0.0", - "lodash": "^4.17.21", - "mute-stream": "0.0.8", - "ora": "^5.4.1", - "run-async": "^2.4.0", - "rxjs": "^7.2.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0", - "through": "^2.3.6" - }, - "dependencies": { - "ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==" - }, - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "requires": { - "color-convert": "^2.0.1" - } - }, - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "cli-spinners": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.6.1.tgz", - "integrity": "sha512-x/5fWmGMnbKQAaNwN+UZlV79qBLM9JFnJuJ03gIi5whrob0xV0ofNVHy9DhwGdsMJQc2OKv0oGmLzvaqvAVv+g==" - }, - "cli-width": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-3.0.0.tgz", - "integrity": "sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw==" - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" - }, - "emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" - }, - "is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==" - }, - "ora": { - "version": "5.4.1", - "resolved": "https://registry.npmjs.org/ora/-/ora-5.4.1.tgz", - "integrity": "sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==", - "requires": { - "bl": "^4.1.0", - "chalk": "^4.1.0", - "cli-cursor": "^3.1.0", - "cli-spinners": "^2.5.0", - "is-interactive": "^1.0.0", - "is-unicode-supported": "^0.1.0", - "log-symbols": "^4.1.0", - "strip-ansi": "^6.0.0", - "wcwidth": "^1.0.1" - } - }, - "string-width": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz", - "integrity": "sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==", - "requires": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.0" - } - }, - "strip-ansi": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", - "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", - "requires": { - "ansi-regex": "^5.0.0" - } - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "requires": { - "has-flag": "^4.0.0" - } - } - } - }, - "is-arrayish": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz", - "integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==" - }, - "is-binary-path": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", - "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", - "dev": true, - "requires": { - "binary-extensions": "^2.0.0" - } - }, - "is-callable": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.4.tgz", - "integrity": "sha512-r5p9sxJjYnArLjObpjA4xu5EKI3CuKHkJXMhT7kwbpUyIFD1n5PMAsoPvWnvtZiNz7LjkYDRZhd7FlI0eMijEA==" - }, - "is-ci": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-1.2.1.tgz", - "integrity": "sha512-s6tfsaQaQi3JNciBH6shVqEDvhGut0SUXr31ag8Pd8BBbVVlcGfWhpPmEOoM6RJ5TFhbypvf5yyRw/VXW1IiWg==", - "dev": true, - "requires": { - "ci-info": "^1.5.0" - } - }, - "is-date-object": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.1.tgz", - "integrity": "sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY=" - }, - "is-es2016-keyword": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-es2016-keyword/-/is-es2016-keyword-1.0.0.tgz", - "integrity": "sha1-9uVOEQxeT40mXmnS7Q6vjPX0dxg=", - "dev": true - }, - "is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", - "dev": true - }, - "is-finite": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-finite/-/is-finite-1.1.0.tgz", - "integrity": "sha512-cdyMtqX/BOqqNBBiKlIVkytNHm49MtMlYyn1zxzvJKWmFMlGzm+ry5BBfYyeY9YmNKbRSo/o7OX9w9ale0wg3w==", - "dev": true - }, - "is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", - "dev": true - }, - "is-glob": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", - "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", - "dev": true, - "requires": { - "is-extglob": "^2.1.1" - } - }, - "is-interactive": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-1.0.0.tgz", - "integrity": "sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==" - }, - "is-npm": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/is-npm/-/is-npm-4.0.0.tgz", - "integrity": "sha512-96ECIfh9xtDDlPylNPXhzjsykHsMJZ18ASpaWzQyBr4YRTcVjUvzaHayDAES2oU/3KpljhHUjtSRNiDwi0F0ig==" - }, - "is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "dev": true - }, - "is-obj": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz", - "integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==" - }, - "is-plain-obj": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", - "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", - "dev": true - }, - "is-redirect": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-redirect/-/is-redirect-1.0.0.tgz", - "integrity": "sha1-HQPd7VO9jbDzDCbk+V02/HyH3CQ=", - "dev": true - }, - "is-regex": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.4.tgz", - "integrity": "sha1-VRdIm1RwkbCTDglWVM7SXul+lJE=", - "requires": { - "has": "^1.0.1" - } - }, - "is-retry-allowed": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/is-retry-allowed/-/is-retry-allowed-1.2.0.tgz", - "integrity": "sha512-RUbUeKwvm3XG2VYamhJL1xFktgjvPzL0Hq8C+6yrWIswDy3BIXGqCxhxkc30N9jqK311gVU137K8Ei55/zVJRg==", - "dev": true - }, - "is-stream": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", - "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=", - "dev": true - }, - "is-symbol": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.2.tgz", - "integrity": "sha512-HS8bZ9ox60yCJLH9snBpIwv9pYUAkcuLhSA1oero1UB5y9aiQpRA8y2ex945AOtCZL1lJDeIk3G5LthswI46Lw==", - "requires": { - "has-symbols": "^1.0.0" - } - }, - "is-typedarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", - "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=" - }, - "is-unicode-supported": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", - "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==" - }, - "is-utf8": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", - "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=", - "dev": true - }, - "is-windows": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", - "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", - "dev": true - }, - "is-yarn-global": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/is-yarn-global/-/is-yarn-global-0.3.0.tgz", - "integrity": "sha512-VjSeb/lHmkoyd8ryPVIKvOCn4D1koMqY+vqyjjUfc3xyKtP4dYOxM44sZrnqQSzSds3xyOrUTLTC9LVCVgLngw==" - }, - "isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", - "dev": true - }, - "isstream": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", - "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=" - }, - "js-tokens": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "dev": true - }, - "js-yaml": { - "version": "3.13.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz", - "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==", - "dev": true, - "requires": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" - } - }, - "js2xmlparser": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/js2xmlparser/-/js2xmlparser-4.0.2.tgz", - "integrity": "sha512-6n4D8gLlLf1n5mNLQPRfViYzu9RATblzPEtm1SthMX1Pjao0r9YI9nw7ZIfRxQMERS87mcswrg+r/OYrPRX6jA==", - "dev": true, - "requires": { - "xmlcreate": "^2.0.4" - } - }, - "jsbn": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", - "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=" - }, - "jsdoc": { - "version": "3.6.7", - "resolved": "https://registry.npmjs.org/jsdoc/-/jsdoc-3.6.7.tgz", - "integrity": "sha512-sxKt7h0vzCd+3Y81Ey2qinupL6DpRSZJclS04ugHDNmRUXGzqicMJ6iwayhSA0S0DwwX30c5ozyUthr1QKF6uw==", - "dev": true, - "requires": { - "@babel/parser": "^7.9.4", - "bluebird": "^3.7.2", - "catharsis": "^0.9.0", - "escape-string-regexp": "^2.0.0", - "js2xmlparser": "^4.0.1", - "klaw": "^3.0.0", - "markdown-it": "^10.0.0", - "markdown-it-anchor": "^5.2.7", - "marked": "^2.0.3", - "mkdirp": "^1.0.4", - "requizzle": "^0.2.3", - "strip-json-comments": "^3.1.0", - "taffydb": "2.6.2", - "underscore": "~1.13.1" - }, - "dependencies": { - "escape-string-regexp": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", - "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", - "dev": true - }, - "strip-json-comments": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", - "dev": true - } - } - }, - "jsdoc-api": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/jsdoc-api/-/jsdoc-api-7.1.0.tgz", - "integrity": "sha512-yjIiZa6LFOgd0dyFW/R+3unnVUhhbU1CeBhisgjBPRHkar83rkgDtTMRdgQotSvt+pGlmknZqfwR5AQuMh9/6w==", - "dev": true, - "requires": { - "array-back": "^6.2.0", - "cache-point": "^2.0.0", - "collect-all": "^1.0.4", - "file-set": "^4.0.2", - "fs-then-native": "^2.0.0", - "jsdoc": "^3.6.7", - "object-to-spawn-args": "^2.0.1", - "temp-path": "^1.0.0", - "walk-back": "^5.1.0" - }, - "dependencies": { - "array-back": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/array-back/-/array-back-6.2.0.tgz", - "integrity": "sha512-mixVv03GOOn/ubHE4STQ+uevX42ETdk0JoMVEjNkSOCT7WgERh7C8/+NyhWYNpE3BN69pxFyJIBcF7CxWz/+4A==", - "dev": true - } - } - }, - "jsdoc-parse": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/jsdoc-parse/-/jsdoc-parse-6.0.1.tgz", - "integrity": "sha512-ij3Az5y2dp+ajMxYnEJH7kjKK5v6+yZ3Cg/KtRdoT15pIm6qTk/W8q72QdNLZ9jQm/U2/ifENFXXTOe6xIxGeA==", - "dev": true, - "requires": { - "array-back": "^6.1.1", - "lodash.omit": "^4.5.0", - "lodash.pick": "^4.4.0", - "reduce-extract": "^1.0.0", - "sort-array": "^4.1.4", - "test-value": "^3.0.0" - }, - "dependencies": { - "array-back": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/array-back/-/array-back-6.2.0.tgz", - "integrity": "sha512-mixVv03GOOn/ubHE4STQ+uevX42ETdk0JoMVEjNkSOCT7WgERh7C8/+NyhWYNpE3BN69pxFyJIBcF7CxWz/+4A==", - "dev": true - } - } - }, - "jsdoc-to-markdown": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/jsdoc-to-markdown/-/jsdoc-to-markdown-7.1.0.tgz", - "integrity": "sha512-LJAiwrUaOpPqOmllqnVVqfBZh6KI/rHHfSwL7DerTpjLQWHfpndz/JUNlF5ngYjbL4aHNf7uJ1TuXl6xGfq5rg==", - "dev": true, - "requires": { - "array-back": "^6.2.0", - "command-line-tool": "^0.8.0", - "config-master": "^3.1.0", - "dmd": "^6.0.0", - "jsdoc-api": "^7.1.0", - "jsdoc-parse": "^6.0.1", - "walk-back": "^5.1.0" - }, - "dependencies": { - "array-back": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/array-back/-/array-back-6.2.0.tgz", - "integrity": "sha512-mixVv03GOOn/ubHE4STQ+uevX42ETdk0JoMVEjNkSOCT7WgERh7C8/+NyhWYNpE3BN69pxFyJIBcF7CxWz/+4A==", - "dev": true - } - } - }, - "jsesc": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", - "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", - "dev": true - }, - "json-buffer": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.0.tgz", - "integrity": "sha1-Wx85evx11ne96Lz8Dkfh+aPZqJg=" - }, - "json-parse-better-errors": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", - "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", - "dev": true - }, - "json-schema": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz", - "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==" - }, - "json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" - }, - "json-stable-stringify-without-jsonify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", - "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", - "dev": true - }, - "json-stringify-safe": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", - "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=" - }, - "json-to-table": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/json-to-table/-/json-to-table-4.2.1.tgz", - "integrity": "sha512-4PSWfPZyFssRj5BwjusoMSPSKoqfoULLZdrAgHvDkpXSZVID4gSe32NdemeePANf7oLa+x8znIWVIc8ba4gM/g==", - "requires": { - "lodash": "~4.17.20", - "traverse": "~0.6.6" - } - }, - "jsonfile": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.0.1.tgz", - "integrity": "sha512-jR2b5v7d2vIOust+w3wtFKZIfpC2pnRmFAhAC/BuweZFQR8qZzxH1OyrQ10HmdVYiXWkYUqPVsz91cG7EL2FBg==", - "requires": { - "graceful-fs": "^4.1.6", - "universalify": "^1.0.0" - } - }, - "jsprim": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.2.tgz", - "integrity": "sha512-P2bSOMAc/ciLz6DzgjVlGJP9+BrJWu5UDGK70C2iweC5QBIeFf0ZXRvGjEj2uYgrY2MkAAhsSWHDWlFtEroZWw==", - "requires": { - "assert-plus": "1.0.0", - "extsprintf": "1.3.0", - "json-schema": "0.4.0", - "verror": "1.10.0" - } - }, - "keyv": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/keyv/-/keyv-3.1.0.tgz", - "integrity": "sha512-9ykJ/46SN/9KPM/sichzQ7OvXyGDYKGTaDlKMGCAlg2UK8KRy4jb0d8sFc+0Tt0YYnThq8X2RZgCg74RPxgcVA==", - "requires": { - "json-buffer": "3.0.0" - } - }, - "klaw": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/klaw/-/klaw-3.0.0.tgz", - "integrity": "sha512-0Fo5oir+O9jnXu5EefYbVK+mHMBeEVEy2cmctR1O1NECcCkPRreJKrS6Qt/j3KC2C148Dfo9i3pCmCMsdqGr0g==", - "dev": true, - "requires": { - "graceful-fs": "^4.1.9" - } - }, - "kuler": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/kuler/-/kuler-2.0.0.tgz", - "integrity": "sha512-Xq9nH7KlWZmXAtodXDDRE7vs6DU1gTU8zYDHDiWLSip45Egwq3plLHzPn27NgvzL2r1LMPC1vdqh98sQxtqj4A==" - }, - "latest-version": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/latest-version/-/latest-version-5.1.0.tgz", - "integrity": "sha512-weT+r0kTkRQdCdYCNtkMwWXQTMEswKrFBkm4ckQOMVhhqhIMI1UT2hMj+1iigIhgSZm5gTmrRXBNoGUgaTY1xA==", - "requires": { - "package-json": "^6.3.0" - }, - "dependencies": { - "get-stream": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", - "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", - "requires": { - "pump": "^3.0.0" - } - }, - "got": { - "version": "9.6.0", - "resolved": "https://registry.npmjs.org/got/-/got-9.6.0.tgz", - "integrity": "sha512-R7eWptXuGYxwijs0eV+v3o6+XH1IqVK8dJOEecQfTmkncw9AV4dcw/Dhxi8MdlqPthxxpZyizMzyg8RTmEsG+Q==", - "requires": { - "@sindresorhus/is": "^0.14.0", - "@szmarczak/http-timer": "^1.1.2", - "cacheable-request": "^6.0.0", - "decompress-response": "^3.3.0", - "duplexer3": "^0.1.4", - "get-stream": "^4.1.0", - "lowercase-keys": "^1.0.1", - "mimic-response": "^1.0.1", - "p-cancelable": "^1.0.0", - "to-readable-stream": "^1.0.0", - "url-parse-lax": "^3.0.0" - } - }, - "package-json": { - "version": "6.5.0", - "resolved": "https://registry.npmjs.org/package-json/-/package-json-6.5.0.tgz", - "integrity": "sha512-k3bdm2n25tkyxcjSKzB5x8kfVxlMdgsbPr0GkZcwHsLpba6cBjqCt1KlcChKEvxHIcTB1FVMuwoijZ26xex5MQ==", - "requires": { - "got": "^9.6.0", - "registry-auth-token": "^4.0.0", - "registry-url": "^5.0.0", - "semver": "^6.2.0" - } - }, - "prepend-http": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-2.0.0.tgz", - "integrity": "sha1-6SQ0v6XqjBn0HN/UAddBo8gZ2Jc=" - }, - "registry-auth-token": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-4.2.0.tgz", - "integrity": "sha512-P+lWzPrsgfN+UEpDS3U8AQKg/UjZX6mQSJueZj3EK+vNESoqBSpBUD3gmu4sF9lOsjXWjF11dQKUqemf3veq1w==", - "requires": { - "rc": "^1.2.8" - } - }, - "registry-url": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/registry-url/-/registry-url-5.1.0.tgz", - "integrity": "sha512-8acYXXTI0AkQv6RAOjE3vOaIXZkT9wo4LOFbBKYQEEnnMNBpKqdUrI6S4NT0KPIo/WVvJ5tE/X5LF/TQUf0ekw==", - "requires": { - "rc": "^1.2.8" - } - }, - "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==" - }, - "url-parse-lax": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-3.0.0.tgz", - "integrity": "sha1-FrXK/Afb42dsGxmZF3gj1lA6yww=", - "requires": { - "prepend-http": "^2.0.0" - } - } - } - }, - "levn": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", - "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", - "dev": true, - "requires": { - "prelude-ls": "^1.2.1", - "type-check": "~0.4.0" - } - }, - "lilconfig": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.0.4.tgz", - "integrity": "sha512-bfTIN7lEsiooCocSISTWXkiWJkRqtL9wYtYy+8EK3Y41qh3mpwPU0ycTOgjdY9ErwXCc8QyrQp82bdL0Xkm9yA==", - "dev": true - }, - "linkify-it": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-2.2.0.tgz", - "integrity": "sha512-GnAl/knGn+i1U/wjBz3akz2stz+HrHLsxMwHQGofCDfPvlf+gDKN58UtfmUquTY4/MXeE2x7k19KQmeoZi94Iw==", - "dev": true, - "requires": { - "uc.micro": "^1.0.1" - } - }, - "lint-staged": { - "version": "12.1.2", - "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-12.1.2.tgz", - "integrity": "sha512-bSMcQVqMW98HLLLR2c2tZ+vnDCnx4fd+0QJBQgN/4XkdspGRPc8DGp7UuOEBe1ApCfJ+wXXumYnJmU+wDo7j9A==", - "dev": true, - "requires": { - "cli-truncate": "^3.1.0", - "colorette": "^2.0.16", - "commander": "^8.3.0", - "debug": "^4.3.2", - "enquirer": "^2.3.6", - "execa": "^5.1.1", - "lilconfig": "2.0.4", - "listr2": "^3.13.3", - "micromatch": "^4.0.4", - "normalize-path": "^3.0.0", - "object-inspect": "^1.11.0", - "string-argv": "^0.3.1", - "supports-color": "^9.0.2", - "yaml": "^1.10.2" - }, - "dependencies": { - "cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", - "dev": true, - "requires": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - } - }, - "execa": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", - "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", - "dev": true, - "requires": { - "cross-spawn": "^7.0.3", - "get-stream": "^6.0.0", - "human-signals": "^2.1.0", - "is-stream": "^2.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^4.0.1", - "onetime": "^5.1.2", - "signal-exit": "^3.0.3", - "strip-final-newline": "^2.0.0" - } - }, - "get-stream": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", - "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", - "dev": true - }, - "is-stream": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", - "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", - "dev": true - }, - "npm-run-path": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", - "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", - "dev": true, - "requires": { - "path-key": "^3.0.0" - } - }, - "path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true - }, - "shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dev": true, - "requires": { - "shebang-regex": "^3.0.0" - } - }, - "shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "dev": true - }, - "supports-color": { - "version": "9.2.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-9.2.1.tgz", - "integrity": "sha512-Obv7ycoCTG51N7y175StI9BlAXrmgZrFhZOb0/PyjHBher/NmsdBgbbQ1Inhq+gIhz6+7Gb+jWF2Vqi7Mf1xnQ==", - "dev": true - }, - "which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, - "requires": { - "isexe": "^2.0.0" - } - } - } - }, - "listr2": { - "version": "3.13.5", - "resolved": "https://registry.npmjs.org/listr2/-/listr2-3.13.5.tgz", - "integrity": "sha512-3n8heFQDSk+NcwBn3CgxEibZGaRzx+pC64n3YjpMD1qguV4nWus3Al+Oo3KooqFKTQEJ1v7MmnbnyyNspgx3NA==", - "dev": true, - "requires": { - "cli-truncate": "^2.1.0", - "colorette": "^2.0.16", - "log-update": "^4.0.0", - "p-map": "^4.0.0", - "rfdc": "^1.3.0", - "rxjs": "^7.4.0", - "through": "^2.3.8", - "wrap-ansi": "^7.0.0" - }, - "dependencies": { - "ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true - }, - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "cli-truncate": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-2.1.0.tgz", - "integrity": "sha512-n8fOixwDD6b/ObinzTrp1ZKFzbgvKZvuz/TvejnLn1aQfC6r52XEx85FmuC+3HI+JM7coBRXUvNqEU2PHVrHpg==", - "dev": true, - "requires": { - "slice-ansi": "^3.0.0", - "string-width": "^4.2.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true - }, - "is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true - }, - "slice-ansi": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-3.0.0.tgz", - "integrity": "sha512-pSyv7bSTC7ig9Dcgbw9AuRNUb5k5V6oDudjZoMBSr13qpLBG7tB+zgCkARjq7xIUgdz5P1Qe8u+rSGdouOOIyQ==", - "dev": true, - "requires": { - "ansi-styles": "^4.0.0", - "astral-regex": "^2.0.0", - "is-fullwidth-code-point": "^3.0.0" - } - }, - "string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "requires": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - } - }, - "strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, - "requires": { - "ansi-regex": "^5.0.1" - } - }, - "wrap-ansi": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dev": true, - "requires": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - } - } - } - }, - "load-json-file": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz", - "integrity": "sha1-L19Fq5HjMhYjT9U62rZo607AmTs=", - "dev": true, - "requires": { - "graceful-fs": "^4.1.2", - "parse-json": "^4.0.0", - "pify": "^3.0.0", - "strip-bom": "^3.0.0" - } - }, - "load-yaml-file": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/load-yaml-file/-/load-yaml-file-0.1.1.tgz", - "integrity": "sha512-G910TofXH7u0NfslAzqv6c9pHpvBzObNOo2hMG0/KUDpdHeFY0wE/fTBMExt0Gb12gg5bXS7Hj6pb0e+xbBXLA==", - "dev": true, - "requires": { - "graceful-fs": "^4.1.5", - "js-yaml": "^3.13.0", - "pify": "^2.3.0", - "strip-bom": "^3.0.0" - }, - "dependencies": { - "pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", - "dev": true - } - } - }, - "locate-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", - "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", - "dev": true, - "requires": { - "p-locate": "^3.0.0", - "path-exists": "^3.0.0" - } - }, - "lodash": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" - }, - "lodash.camelcase": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", - "integrity": "sha1-soqmKIorn8ZRA1x3EfZathkDMaY=", - "dev": true - }, - "lodash.clone": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.clone/-/lodash.clone-4.5.0.tgz", - "integrity": "sha1-GVhwRQ9aExkkeN9Lw9I9LeoZB7Y=" - }, - "lodash.isempty": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/lodash.isempty/-/lodash.isempty-4.4.0.tgz", - "integrity": "sha1-b4bL7di+TsmHvpqvM8loTbGzHn4=" - }, - "lodash.isplainobject": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", - "integrity": "sha1-fFJqUtibRcRcxpC4gWO+BJf1UMs=" - }, - "lodash.merge": { - "version": "4.6.2", - "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", - "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==" - }, - "lodash.omit": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.omit/-/lodash.omit-4.5.0.tgz", - "integrity": "sha1-brGa5aHuHdnfC5aeZs4Lf6MLXmA=", - "dev": true - }, - "lodash.padend": { - "version": "4.6.1", - "resolved": "https://registry.npmjs.org/lodash.padend/-/lodash.padend-4.6.1.tgz", - "integrity": "sha1-U8y6BH0G4VjTEfRdpiX05J5vFm4=", - "dev": true - }, - "lodash.pick": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/lodash.pick/-/lodash.pick-4.4.0.tgz", - "integrity": "sha1-UvBWEP/53tQiYRRB7R/BI6AwAbM=", - "dev": true - }, - "lodash.toarray": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/lodash.toarray/-/lodash.toarray-4.4.0.tgz", - "integrity": "sha1-JMS/zWsvuji/0FlNsRedjptlZWE=", - "dev": true - }, - "log-symbols": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", - "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", - "requires": { - "chalk": "^4.1.0", - "is-unicode-supported": "^0.1.0" - }, - "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "requires": { - "color-convert": "^2.0.1" - } - }, - "chalk": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", - "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "requires": { - "has-flag": "^4.0.0" - } - } - } - }, - "log-update": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/log-update/-/log-update-4.0.0.tgz", - "integrity": "sha512-9fkkDevMefjg0mmzWFBW8YkFP91OrizzkW3diF7CpG+S2EYdy4+TVfGwz1zeF8x7hCx1ovSPTOE9Ngib74qqUg==", - "dev": true, - "requires": { - "ansi-escapes": "^4.3.0", - "cli-cursor": "^3.1.0", - "slice-ansi": "^4.0.0", - "wrap-ansi": "^6.2.0" - }, - "dependencies": { - "ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true - }, - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true - }, - "is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true - }, - "slice-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz", - "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==", - "dev": true, - "requires": { - "ansi-styles": "^4.0.0", - "astral-regex": "^2.0.0", - "is-fullwidth-code-point": "^3.0.0" - } - }, - "string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "requires": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - } - }, - "strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, - "requires": { - "ansi-regex": "^5.0.1" - } - }, - "wrap-ansi": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", - "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", - "dev": true, - "requires": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - } - } - } - }, - "logform": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/logform/-/logform-2.3.2.tgz", - "integrity": "sha512-V6JiPThZzTsbVRspNO6TmHkR99oqYTs8fivMBYQkjZj6rxW92KxtDCPE6IkAk1DNBnYKNkjm4jYBm6JDUcyhOA==", - "requires": { - "colors": "1.4.0", - "fecha": "^4.2.0", - "ms": "^2.1.1", - "safe-stable-stringify": "^1.1.0", - "triple-beam": "^1.3.0" - } - }, - "loud-rejection": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/loud-rejection/-/loud-rejection-1.6.0.tgz", - "integrity": "sha1-W0b4AUft7leIcPCG0Eghz5mOVR8=", - "dev": true, - "requires": { - "currently-unhandled": "^0.4.1", - "signal-exit": "^3.0.0" - } - }, - "lowercase-keys": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz", - "integrity": "sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==" - }, - "lru-cache": { - "version": "4.1.5", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", - "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==", - "dev": true, - "requires": { - "pseudomap": "^1.0.2", - "yallist": "^2.1.2" - } - }, - "make-dir": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", - "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", - "requires": { - "semver": "^6.0.0" - }, - "dependencies": { - "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==" - } - } - }, - "map-obj": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz", - "integrity": "sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0=", - "dev": true - }, - "markdown-it": { - "version": "10.0.0", - "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-10.0.0.tgz", - "integrity": "sha512-YWOP1j7UbDNz+TumYP1kpwnP0aEa711cJjrAQrzd0UXlbJfc5aAq0F/PZHjiioqDC1NKgvIMX+o+9Bk7yuM2dg==", - "dev": true, - "requires": { - "argparse": "^1.0.7", - "entities": "~2.0.0", - "linkify-it": "^2.0.0", - "mdurl": "^1.0.1", - "uc.micro": "^1.0.5" - } - }, - "markdown-it-anchor": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/markdown-it-anchor/-/markdown-it-anchor-5.3.0.tgz", - "integrity": "sha512-/V1MnLL/rgJ3jkMWo84UR+K+jF1cxNG1a+KwqeXqTIJ+jtA8aWSHuigx8lTzauiIjBDbwF3NcWQMotd0Dm39jA==", - "dev": true, - "requires": {} - }, - "marked": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/marked/-/marked-2.1.3.tgz", - "integrity": "sha512-/Q+7MGzaETqifOMWYEA7HVMaZb4XbcRfaOzcSsHZEith83KGlvaSG33u0SKu89Mj5h+T8V2hM+8O45Qc5XTgwA==", - "dev": true - }, - "mdurl": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-1.0.1.tgz", - "integrity": "sha1-/oWy7HWlkDfyrf7BAP1sYBdhFS4=", - "dev": true - }, - "memorystream": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/memorystream/-/memorystream-0.3.1.tgz", - "integrity": "sha1-htcJCzDORV1j+64S3aUaR93K+bI=", - "dev": true - }, - "meow": { - "version": "3.7.0", - "resolved": "https://registry.npmjs.org/meow/-/meow-3.7.0.tgz", - "integrity": "sha1-cstmi0JSKCkKu/qFaJJYcwioAfs=", - "dev": true, - "requires": { - "camelcase-keys": "^2.0.0", - "decamelize": "^1.1.2", - "loud-rejection": "^1.0.0", - "map-obj": "^1.0.1", - "minimist": "^1.1.3", - "normalize-package-data": "^2.3.4", - "object-assign": "^4.0.1", - "read-pkg-up": "^1.0.1", - "redent": "^1.0.0", - "trim-newlines": "^1.0.0" - } - }, - "merge-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", - "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", - "dev": true - }, - "micromatch": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.4.tgz", - "integrity": "sha512-pRmzw/XUcwXGpD9aI9q/0XOwLNygjETJ8y0ao0wdqprrzDa4YnxLcz7fQRZr8voh8V10kGhABbNcHVk5wHgWwg==", - "dev": true, - "requires": { - "braces": "^3.0.1", - "picomatch": "^2.2.3" - } - }, - "mime-db": { - "version": "1.40.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.40.0.tgz", - "integrity": "sha512-jYdeOMPy9vnxEqFRRo6ZvTZ8d9oPb+k18PKoYNYUe2stVEBPPwsln/qWzdbmaIvnhZ9v2P+CuecK+fpUfsV2mA==" - }, - "mime-types": { - "version": "2.1.24", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.24.tgz", - "integrity": "sha512-WaFHS3MCl5fapm3oLxU4eYDw77IQM2ACcxQ9RIxfaC3ooc6PFuBMGZZsYpvoXS5D5QTWPieo1jjLdAm3TBP3cQ==", - "requires": { - "mime-db": "1.40.0" - } - }, - "mimic-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", - "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==" - }, - "mimic-response": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz", - "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==" - }, - "minimatch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", - "dev": true, - "requires": { - "brace-expansion": "^1.1.7" - } - }, - "minimist": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", - "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==" - }, - "mkdirp": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", - "dev": true - }, - "mkdirp2": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mkdirp2/-/mkdirp2-1.0.4.tgz", - "integrity": "sha512-Q2PKB4ZR4UPtjLl76JfzlgSCUZhSV1AXQgAZa1qt5RiaALFjP/CDrGvFBrOz7Ck6McPcwMAxTsJvWOUjOU8XMw==", - "dev": true - }, - "mocha": { - "version": "9.1.3", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-9.1.3.tgz", - "integrity": "sha512-Xcpl9FqXOAYqI3j79pEtHBBnQgVXIhpULjGQa7DVb0Po+VzmSIK9kanAiWLHoRR/dbZ2qpdPshuXr8l1VaHCzw==", - "dev": true, - "requires": { - "@ungap/promise-all-settled": "1.1.2", - "ansi-colors": "4.1.1", - "browser-stdout": "1.3.1", - "chokidar": "3.5.2", - "debug": "4.3.2", - "diff": "5.0.0", - "escape-string-regexp": "4.0.0", - "find-up": "5.0.0", - "glob": "7.1.7", - "growl": "1.10.5", - "he": "1.2.0", - "js-yaml": "4.1.0", - "log-symbols": "4.1.0", - "minimatch": "3.0.4", - "ms": "2.1.3", - "nanoid": "3.1.25", - "serialize-javascript": "6.0.0", - "strip-json-comments": "3.1.1", - "supports-color": "8.1.1", - "which": "2.0.2", - "workerpool": "6.1.5", - "yargs": "16.2.0", - "yargs-parser": "20.2.4", - "yargs-unparser": "2.0.0" - }, - "dependencies": { - "ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true - }, - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true - }, - "cliui": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", - "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", - "dev": true, - "requires": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", - "wrap-ansi": "^7.0.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true - }, - "escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "dev": true - }, - "find-up": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", - "dev": true, - "requires": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" - } - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true - }, - "js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "dev": true, - "requires": { - "argparse": "^2.0.1" - } - }, - "locate-path": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", - "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", - "dev": true, - "requires": { - "p-locate": "^5.0.0" - } - }, - "ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true - }, - "p-limit": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.0.2.tgz", - "integrity": "sha512-iwqZSOoWIW+Ew4kAGUlN16J4M7OB3ysMLSZtnhmqx7njIHFPlxWBX8xo3lVTyFVq6mI/lL9qt2IsN1sHwaxJkg==", - "dev": true, - "requires": { - "p-try": "^2.0.0" - } - }, - "p-locate": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", - "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", - "dev": true, - "requires": { - "p-limit": "^3.0.2" - } - }, - "path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "dev": true - }, - "string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "requires": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - } - }, - "strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, - "requires": { - "ansi-regex": "^5.0.1" - } - }, - "strip-json-comments": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", - "dev": true - }, - "supports-color": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - }, - "which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, - "requires": { - "isexe": "^2.0.0" - } - }, - "wrap-ansi": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dev": true, - "requires": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - } - }, - "y18n": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", - "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", - "dev": true - }, - "yargs": { - "version": "16.2.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", - "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", - "dev": true, - "requires": { - "cliui": "^7.0.2", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.0", - "y18n": "^5.0.5", - "yargs-parser": "^20.2.2" - } - }, - "yargs-parser": { - "version": "20.2.4", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.4.tgz", - "integrity": "sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==", - "dev": true - } - } - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" - }, - "mustache": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/mustache/-/mustache-4.2.0.tgz", - "integrity": "sha512-71ippSywq5Yb7/tVYyGbkBggbU8H3u5Rz56fH60jGFgr8uHwxs+aSKeqmluIVzM0m0kB7xQjKS6qPfd0b2ZoqQ==" - }, - "mute-stream": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz", - "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==" - }, - "nanoid": { - "version": "3.1.25", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.1.25.tgz", - "integrity": "sha512-rdwtIXaXCLFAQbnfqDRnI6jaRHp9fTcYBjtFKE8eezcZ7LuLjhUaQGNeMXf1HmRoCH32CLz6XwX0TtxEOS/A3Q==", - "dev": true - }, - "natural-compare": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", - "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", - "dev": true - }, - "neo-async": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", - "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", - "dev": true - }, - "nice-try": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", - "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==", - "dev": true - }, - "node-emoji": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/node-emoji/-/node-emoji-1.10.0.tgz", - "integrity": "sha512-Yt3384If5H6BYGVHiHwTL+99OzJKHhgp82S8/dktEK73T26BazdgZ4JZh92xSVtGNJvz9UbXdNAc5hcrXV42vw==", - "dev": true, - "requires": { - "lodash.toarray": "^4.4.0" - } - }, - "node-sass-tilde-importer": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/node-sass-tilde-importer/-/node-sass-tilde-importer-1.0.2.tgz", - "integrity": "sha512-Swcmr38Y7uB78itQeBm3mThjxBy9/Ah/ykPIaURY/L6Nec9AyRoL/jJ7ECfMR+oZeCTVQNxVMu/aHU+TLRVbdg==", - "dev": true, - "requires": { - "find-parent-dir": "^0.3.0" - } - }, - "normalize-package-data": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", - "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", - "dev": true, - "requires": { - "hosted-git-info": "^2.1.4", - "resolve": "^1.10.0", - "semver": "2 || 3 || 4 || 5", - "validate-npm-package-license": "^3.0.1" - }, - "dependencies": { - "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true - } - } - }, - "normalize-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", - "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", - "dev": true - }, - "normalize-url": { - "version": "4.5.1", - "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-4.5.1.tgz", - "integrity": "sha512-9UZCFRHQdNrfTpGg8+1INIg93B6zE0aXMVFkw1WFwvO4SlZywU6aLg5Of0Ap/PgcbSw4LNxvMWXMeugwMCX0AA==" - }, - "npm-check": { - "version": "5.9.2", - "resolved": "https://registry.npmjs.org/npm-check/-/npm-check-5.9.2.tgz", - "integrity": "sha512-YlTZGP1A8+Rad5wldGil9STYxgZpZl18X6GZI03f4Ch6qTI1TLHIYM0ISco19qgg8M3UHfooEqMfYOpOkF3AeA==", - "dev": true, - "requires": { - "babel-runtime": "^6.6.1", - "callsite-record": "^3.0.0", - "chalk": "^1.1.3", - "co": "^4.6.0", - "depcheck": "0.8.3", - "execa": "^0.2.2", - "giturl": "^1.0.0", - "global-modules": "^1.0.0", - "globby": "^4.0.0", - "inquirer": "^0.12.0", - "is-ci": "^1.0.8", - "lodash": "^4.17.15", - "meow": "^3.7.0", - "minimatch": "^3.0.2", - "node-emoji": "^1.0.3", - "ora": "^0.2.1", - "package-json": "^4.0.1", - "path-exists": "^2.1.0", - "pkg-dir": "^1.0.0", - "preferred-pm": "^1.0.1", - "semver": "^5.0.1", - "semver-diff": "^2.0.0", - "text-table": "^0.2.0", - "throat": "^2.0.2", - "update-notifier": "^2.1.0", - "xtend": "^4.0.1" - }, - "dependencies": { - "ansi-align": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-2.0.0.tgz", - "integrity": "sha1-w2rsy6VjuJzrVW82kPCx2eNUf38=", - "dev": true, - "requires": { - "string-width": "^2.0.0" - }, - "dependencies": { - "ansi-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", - "dev": true - }, - "is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", - "dev": true - }, - "string-width": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", - "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", - "dev": true, - "requires": { - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^4.0.0" - } - }, - "strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", - "dev": true, - "requires": { - "ansi-regex": "^3.0.0" - } - } - } - }, - "ansi-escapes": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-1.4.0.tgz", - "integrity": "sha1-06ioOzGapneTZisT52HHkRQiMG4=", - "dev": true - }, - "ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", - "dev": true - }, - "ansi-styles": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", - "dev": true - }, - "boxen": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/boxen/-/boxen-1.3.0.tgz", - "integrity": "sha512-TNPjfTr432qx7yOjQyaXm3dSR0MH9vXp7eT1BFSl/C51g+EFnOR9hTg1IreahGBmDNCehscshe45f+C1TBZbLw==", - "dev": true, - "requires": { - "ansi-align": "^2.0.0", - "camelcase": "^4.0.0", - "chalk": "^2.0.1", - "cli-boxes": "^1.0.0", - "string-width": "^2.0.0", - "term-size": "^1.2.0", - "widest-line": "^2.0.0" - }, - "dependencies": { - "ansi-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", - "dev": true - }, - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", - "dev": true - }, - "string-width": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", - "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", - "dev": true, - "requires": { - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^4.0.0" - } - }, - "strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", - "dev": true, - "requires": { - "ansi-regex": "^3.0.0" - } - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, - "camelcase": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz", - "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=", - "dev": true - }, - "chalk": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", - "dev": true, - "requires": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" - } - }, - "cli-boxes": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-1.0.0.tgz", - "integrity": "sha1-T6kXw+WclKAEzWH47lCdplFocUM=", - "dev": true - }, - "cli-cursor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-1.0.2.tgz", - "integrity": "sha1-ZNo/fValRBLll5S9Ytw1KV6PKYc=", - "dev": true, - "requires": { - "restore-cursor": "^1.0.1" - } - }, - "configstore": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/configstore/-/configstore-3.1.5.tgz", - "integrity": "sha512-nlOhI4+fdzoK5xmJ+NY+1gZK56bwEaWZr8fYuXohZ9Vkc1o3a4T/R3M+yE/w7x/ZVJ1zF8c+oaOvF0dztdUgmA==", - "dev": true, - "requires": { - "dot-prop": "^4.2.1", - "graceful-fs": "^4.1.2", - "make-dir": "^1.0.0", - "unique-string": "^1.0.0", - "write-file-atomic": "^2.0.0", - "xdg-basedir": "^3.0.0" - } - }, - "cross-spawn": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", - "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=", - "dev": true, - "requires": { - "lru-cache": "^4.0.1", - "shebang-command": "^1.2.0", - "which": "^1.2.9" - } - }, - "crypto-random-string": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-1.0.0.tgz", - "integrity": "sha1-ojD2T1aDEOFJgAmUB5DsmVRbyn4=", - "dev": true - }, - "dot-prop": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-4.2.1.tgz", - "integrity": "sha512-l0p4+mIuJIua0mhxGoh4a+iNL9bmeK5DvnSVQa6T0OhrVmaEa1XScX5Etc673FePCJOArq/4Pa2cLGODUWTPOQ==", - "dev": true, - "requires": { - "is-obj": "^1.0.0" - } - }, - "figures": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/figures/-/figures-1.7.0.tgz", - "integrity": "sha1-y+Hjr/zxzUS4DK3+0o3Hk6lwHS4=", - "dev": true, - "requires": { - "escape-string-regexp": "^1.0.5", - "object-assign": "^4.1.0" - } - }, - "global-dirs": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-0.1.1.tgz", - "integrity": "sha1-sxnA3UYH81PzvpzKTHL8FIxJ9EU=", - "dev": true, - "requires": { - "ini": "^1.3.4" - } - }, - "inquirer": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-0.12.0.tgz", - "integrity": "sha1-HvK/1jUE3wvHV4X/+MLEHfEvB34=", - "dev": true, - "requires": { - "ansi-escapes": "^1.1.0", - "ansi-regex": "^2.0.0", - "chalk": "^1.0.0", - "cli-cursor": "^1.0.1", - "cli-width": "^2.0.0", - "figures": "^1.3.5", - "lodash": "^4.3.0", - "readline2": "^1.0.1", - "run-async": "^0.1.0", - "rx-lite": "^3.1.2", - "string-width": "^1.0.1", - "strip-ansi": "^3.0.0", - "through": "^2.3.6" - } - }, - "is-fullwidth-code-point": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", - "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", - "dev": true, - "requires": { - "number-is-nan": "^1.0.0" - } - }, - "is-installed-globally": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/is-installed-globally/-/is-installed-globally-0.1.0.tgz", - "integrity": "sha1-Df2Y9akRFxbdU13aZJL2e/PSWoA=", - "dev": true, - "requires": { - "global-dirs": "^0.1.0", - "is-path-inside": "^1.0.0" - } - }, - "is-npm": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-npm/-/is-npm-1.0.0.tgz", - "integrity": "sha1-8vtjpl5JBbQGyGBydloaTceTufQ=", - "dev": true - }, - "is-obj": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz", - "integrity": "sha1-PkcprB9f3gJc19g6iW2rn09n2w8=", - "dev": true - }, - "is-path-inside": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-1.0.1.tgz", - "integrity": "sha1-jvW33lBDej/cprToZe96pVy0gDY=", - "dev": true, - "requires": { - "path-is-inside": "^1.0.1" - } - }, - "latest-version": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/latest-version/-/latest-version-3.1.0.tgz", - "integrity": "sha1-ogU4P+oyKzO1rjsYq+4NwvNW7hU=", - "dev": true, - "requires": { - "package-json": "^4.0.0" - } - }, - "make-dir": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-1.3.0.tgz", - "integrity": "sha512-2w31R7SJtieJJnQtGc7RVL2StM2vGYVfqUOvUDxH6bC6aJTxPxTF0GnIgCyu7tjockiUWAYQRbxa7vKn34s5sQ==", - "dev": true, - "requires": { - "pify": "^3.0.0" - } - }, - "npm-run-path": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", - "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=", - "dev": true, - "requires": { - "path-key": "^2.0.0" - } - }, - "onetime": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-1.1.0.tgz", - "integrity": "sha1-ofeDj4MUxRbwXs78vEzP4EtO14k=", - "dev": true - }, - "path-exists": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", - "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", - "dev": true, - "requires": { - "pinkie-promise": "^2.0.0" - } - }, - "restore-cursor": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-1.0.1.tgz", - "integrity": "sha1-NGYfRohjJ/7SmRR5FSJS35LapUE=", - "dev": true, - "requires": { - "exit-hook": "^1.0.0", - "onetime": "^1.0.0" - } - }, - "run-async": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/run-async/-/run-async-0.1.0.tgz", - "integrity": "sha1-yK1KXhEGYeQCp9IbUw4AnyX444k=", - "dev": true, - "requires": { - "once": "^1.3.0" - } - }, - "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true - }, - "string-width": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", - "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", - "dev": true, - "requires": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" - } - }, - "strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "dev": true, - "requires": { - "ansi-regex": "^2.0.0" - } - }, - "supports-color": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", - "dev": true - }, - "term-size": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/term-size/-/term-size-1.2.0.tgz", - "integrity": "sha1-RYuDiH8oj8Vtb/+/rSYuJmOO+mk=", - "dev": true, - "requires": { - "execa": "^0.7.0" - }, - "dependencies": { - "execa": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/execa/-/execa-0.7.0.tgz", - "integrity": "sha1-lEvs00zEHuMqY6n68nrVpl/Fl3c=", - "dev": true, - "requires": { - "cross-spawn": "^5.0.1", - "get-stream": "^3.0.0", - "is-stream": "^1.1.0", - "npm-run-path": "^2.0.0", - "p-finally": "^1.0.0", - "signal-exit": "^3.0.0", - "strip-eof": "^1.0.0" - } - } - } - }, - "unique-string": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-1.0.0.tgz", - "integrity": "sha1-nhBXzKhRq7kzmPizOuGHuZyuwRo=", - "dev": true, - "requires": { - "crypto-random-string": "^1.0.0" - } - }, - "update-notifier": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/update-notifier/-/update-notifier-2.5.0.tgz", - "integrity": "sha512-gwMdhgJHGuj/+wHJJs9e6PcCszpxR1b236igrOkUofGhqJuG+amlIKwApH1IW1WWl7ovZxsX49lMBWLxSdm5Dw==", - "dev": true, - "requires": { - "boxen": "^1.2.1", - "chalk": "^2.0.1", - "configstore": "^3.0.0", - "import-lazy": "^2.1.0", - "is-ci": "^1.0.10", - "is-installed-globally": "^0.1.0", - "is-npm": "^1.0.0", - "latest-version": "^3.0.0", - "semver-diff": "^2.0.0", - "xdg-basedir": "^3.0.0" - }, - "dependencies": { - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, - "widest-line": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-2.0.1.tgz", - "integrity": "sha512-Ba5m9/Fa4Xt9eb2ELXt77JxVDV8w7qQrH0zS/TWSJdLyAwQjWoOzpzj5lwVftDz6n/EOu3tNACS84v509qwnJA==", - "dev": true, - "requires": { - "string-width": "^2.1.1" - }, - "dependencies": { - "ansi-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", - "dev": true - }, - "is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", - "dev": true - }, - "string-width": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", - "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", - "dev": true, - "requires": { - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^4.0.0" - } - }, - "strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", - "dev": true, - "requires": { - "ansi-regex": "^3.0.0" - } - } - } - }, - "write-file-atomic": { - "version": "2.4.3", - "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-2.4.3.tgz", - "integrity": "sha512-GaETH5wwsX+GcnzhPgKcKjJ6M2Cq3/iZp1WyY/X1CSqrW+jVNM9Y7D8EC2sM4ZG/V8wZlSniJnCKWPmBYAucRQ==", - "dev": true, - "requires": { - "graceful-fs": "^4.1.11", - "imurmurhash": "^0.1.4", - "signal-exit": "^3.0.2" - } - }, - "xdg-basedir": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-3.0.0.tgz", - "integrity": "sha1-SWsswQnsqNus/i3HK2A8F8WHCtQ=", - "dev": true - } - } - }, - "npm-run-all": { - "version": "4.1.5", - "resolved": "https://registry.npmjs.org/npm-run-all/-/npm-run-all-4.1.5.tgz", - "integrity": "sha512-Oo82gJDAVcaMdi3nuoKFavkIHBRVqQ1qvMb+9LHk/cF4P6B2m8aP04hGf7oL6wZ9BuGwX1onlLhpuoofSyoQDQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "chalk": "^2.4.1", - "cross-spawn": "^6.0.5", - "memorystream": "^0.3.1", - "minimatch": "^3.0.4", - "pidtree": "^0.3.0", - "read-pkg": "^3.0.0", - "shell-quote": "^1.6.1", - "string.prototype.padend": "^3.0.0" - } - }, - "npm-run-path": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-1.0.0.tgz", - "integrity": "sha1-9cMr9ZX+ga6Sfa7FLoL4sACsPI8=", - "dev": true, - "requires": { - "path-key": "^1.0.0" - }, - "dependencies": { - "path-key": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-1.0.0.tgz", - "integrity": "sha1-XVPVeAGWRsDWiADbThRua9wqx68=", - "dev": true - } - } - }, - "number-is-nan": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", - "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", - "dev": true - }, - "oauth-sign": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", - "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==" - }, - "object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", - "dev": true - }, - "object-get": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/object-get/-/object-get-2.1.1.tgz", - "integrity": "sha512-7n4IpLMzGGcLEMiQKsNR7vCe+N5E9LORFrtNUVy4sO3dj9a3HedZCxEL2T7QuLhcHN1NBuBsMOKaOsAYI9IIvg==", - "dev": true - }, - "object-inspect": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.11.1.tgz", - "integrity": "sha512-If7BjFlpkzzBeV1cqgT3OSWT3azyoxDGajR+iGnFBfVV2EWyDyWaZZW2ERDjUaY2QM8i5jI3Sj7mhsM4DDAqWA==" - }, - "object-keys": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", - "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==" - }, - "object-to-spawn-args": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/object-to-spawn-args/-/object-to-spawn-args-2.0.1.tgz", - "integrity": "sha512-6FuKFQ39cOID+BMZ3QaphcC8Y4cw6LXBLyIgPU+OhIYwviJamPAn+4mITapnSBQrejB+NNp+FMskhD8Cq+Ys3w==", - "dev": true - }, - "object.getownpropertydescriptors": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.0.3.tgz", - "integrity": "sha1-h1jIRvW0B62rDyNuCYbxSwUcqhY=", - "requires": { - "define-properties": "^1.1.2", - "es-abstract": "^1.5.1" - } - }, - "once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", - "requires": { - "wrappy": "1" - } - }, - "one-time": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/one-time/-/one-time-1.0.0.tgz", - "integrity": "sha512-5DXOiRKwuSEcQ/l0kGCF6Q3jcADFv5tSmRaJck/OqkVFcOzutB134KRSfF0xDrL39MNnqxbHBbUUcjZIhTgb2g==", - "requires": { - "fn.name": "1.x.x" - } - }, - "onetime": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", - "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", - "requires": { - "mimic-fn": "^2.1.0" - } - }, - "optionator": { - "version": "0.9.1", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", - "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==", - "dev": true, - "requires": { - "deep-is": "^0.1.3", - "fast-levenshtein": "^2.0.6", - "levn": "^0.4.1", - "prelude-ls": "^1.2.1", - "type-check": "^0.4.0", - "word-wrap": "^1.2.3" - } - }, - "ora": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/ora/-/ora-0.2.3.tgz", - "integrity": "sha1-N1J9Igrc1Tw5tzVx11QVbV22V6Q=", - "dev": true, - "requires": { - "chalk": "^1.1.1", - "cli-cursor": "^1.0.2", - "cli-spinners": "^0.1.2", - "object-assign": "^4.0.1" - }, - "dependencies": { - "ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", - "dev": true - }, - "ansi-styles": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", - "dev": true - }, - "chalk": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", - "dev": true, - "requires": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" - } - }, - "cli-cursor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-1.0.2.tgz", - "integrity": "sha1-ZNo/fValRBLll5S9Ytw1KV6PKYc=", - "dev": true, - "requires": { - "restore-cursor": "^1.0.1" - } - }, - "onetime": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-1.1.0.tgz", - "integrity": "sha1-ofeDj4MUxRbwXs78vEzP4EtO14k=", - "dev": true - }, - "restore-cursor": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-1.0.1.tgz", - "integrity": "sha1-NGYfRohjJ/7SmRR5FSJS35LapUE=", - "dev": true, - "requires": { - "exit-hook": "^1.0.0", - "onetime": "^1.0.0" - } - }, - "strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "dev": true, - "requires": { - "ansi-regex": "^2.0.0" - } - }, - "supports-color": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", - "dev": true - } - } - }, - "os-tmpdir": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", - "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=" - }, - "p-cancelable": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-1.1.0.tgz", - "integrity": "sha512-s73XxOZ4zpt1edZYZzvhqFa6uvQc1vwUa0K0BdtIZgQMAJj9IbebH+JkgKZc9h+B05PKHLOTl4ajG1BmNrVZlw==" - }, - "p-finally": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", - "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=", - "dev": true - }, - "p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dev": true, - "requires": { - "p-try": "^2.0.0" - } - }, - "p-locate": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", - "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", - "dev": true, - "requires": { - "p-limit": "^2.0.0" - } - }, - "p-map": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", - "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", - "dev": true, - "requires": { - "aggregate-error": "^3.0.0" - } - }, - "p-try": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", - "dev": true - }, - "package-json": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/package-json/-/package-json-4.0.1.tgz", - "integrity": "sha1-iGmgQBJTZhxMTKPabCEh7VVfXu0=", - "dev": true, - "requires": { - "got": "^6.7.1", - "registry-auth-token": "^3.0.1", - "registry-url": "^3.0.3", - "semver": "^5.1.0" - }, - "dependencies": { - "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true - } - } - }, - "parent-module": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", - "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", - "dev": true, - "requires": { - "callsites": "^3.0.0" - } - }, - "parse-json": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", - "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=", - "dev": true, - "requires": { - "error-ex": "^1.3.1", - "json-parse-better-errors": "^1.0.1" - } - }, - "parse-passwd": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz", - "integrity": "sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY=", - "dev": true - }, - "path-exists": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", - "dev": true - }, - "path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", - "dev": true - }, - "path-is-inside": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz", - "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=", - "dev": true - }, - "path-key": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", - "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", - "dev": true - }, - "path-parse": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", - "dev": true - }, - "path-type": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz", - "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==", - "dev": true, - "requires": { - "pify": "^3.0.0" - } - }, - "pathval": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.1.tgz", - "integrity": "sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==", - "dev": true - }, - "performance-now": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", - "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=" - }, - "picomatch": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.0.tgz", - "integrity": "sha512-lY1Q/PiJGC2zOv/z391WOTD+Z02bCgsFfvxoXXf6h7kv9o+WmsmzYqrAwY63sNgOxE4xEdq0WyUnXfKeBrSvYw==", - "dev": true - }, - "pidtree": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/pidtree/-/pidtree-0.3.0.tgz", - "integrity": "sha512-9CT4NFlDcosssyg8KVFltgokyKZIFjoBxw8CTGy+5F38Y1eQWrt8tRayiUOXE+zVKQnYu5BR8JjCtvK3BcnBhg==", - "dev": true - }, - "pify": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", - "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", - "dev": true - }, - "pinkie": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", - "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=", - "dev": true - }, - "pinkie-promise": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", - "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", - "dev": true, - "requires": { - "pinkie": "^2.0.0" - } - }, - "pkg-dir": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-1.0.0.tgz", - "integrity": "sha1-ektQio1bstYp1EcFb/TpyTFM89Q=", - "dev": true, - "requires": { - "find-up": "^1.0.0" - }, - "dependencies": { - "find-up": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", - "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", - "dev": true, - "requires": { - "path-exists": "^2.0.0", - "pinkie-promise": "^2.0.0" - } - }, - "path-exists": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", - "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", - "dev": true, - "requires": { - "pinkie-promise": "^2.0.0" - } - } - } - }, - "please-upgrade-node": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/please-upgrade-node/-/please-upgrade-node-3.2.0.tgz", - "integrity": "sha512-gQR3WpIgNIKwBMVLkpMUeR3e1/E1y42bqDQZfql+kDeXd8COYfM8PQA4X6y7a8u9Ua9FHmsrrmirW2vHs45hWg==", - "dev": true, - "requires": { - "semver-compare": "^1.0.0" - } - }, - "preferred-pm": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/preferred-pm/-/preferred-pm-1.0.1.tgz", - "integrity": "sha512-9Uxgin5Xnsl67DBvlNFsmDIlBuG9/XKK2cVBTj//7/7wW6ZY+IC9/GlLqxyHABpoasAsJ1MARFOdYPxMUtndxA==", - "dev": true, - "requires": { - "path-exists": "^3.0.0", - "which-pm": "^1.0.1" - } - }, - "prelude-ls": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", - "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", - "dev": true - }, - "prepend-http": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-1.0.4.tgz", - "integrity": "sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw=", - "dev": true - }, - "prettier": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.5.1.tgz", - "integrity": "sha512-vBZcPRUR5MZJwoyi3ZoyQlc1rXeEck8KgeC9AwwOn+exuxLxq5toTRDTSaVrXHxelDMHy9zlicw8u66yxoSUFg==" - }, - "prettier-linter-helpers": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz", - "integrity": "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==", - "dev": true, - "requires": { - "fast-diff": "^1.1.2" - } - }, - "progress": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", - "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", - "dev": true - }, - "pseudomap": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", - "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=", - "dev": true - }, - "psl": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/psl/-/psl-1.4.0.tgz", - "integrity": "sha512-HZzqCGPecFLyoRj5HLfuDSKYTJkAfB5thKBIkRHtGjWwY7p1dAyveIbXIq4tO0KYfDF2tHqPUgY9SDnGm00uFw==" - }, - "pump": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", - "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", - "requires": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" - } - }, - "punycode": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", - "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==" - }, - "pupa": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/pupa/-/pupa-2.1.1.tgz", - "integrity": "sha512-l1jNAspIBSFqbT+y+5FosojNpVpF94nlI+wDUpqP9enwOTfHx9f0gh5nB96vl+6yTpsJsypeNrwfzPrKuHB41A==", - "requires": { - "escape-goat": "^2.0.0" - } - }, - "qs": { - "version": "6.5.2", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", - "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==" - }, - "ramda": { - "version": "0.27.1", - "resolved": "https://registry.npmjs.org/ramda/-/ramda-0.27.1.tgz", - "integrity": "sha512-PgIdVpn5y5Yns8vqb8FzBUEYn98V3xcPgawAkkgj0YJ0qDsnHCiNmZYfOGMgOvoB0eWFLpYbhxUR3mxfDIMvpw==", - "dev": true - }, - "randombytes": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", - "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", - "dev": true, - "requires": { - "safe-buffer": "^5.1.0" - } - }, - "rc": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", - "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", - "requires": { - "deep-extend": "^0.6.0", - "ini": "~1.3.0", - "minimist": "^1.2.0", - "strip-json-comments": "~2.0.1" - } - }, - "read-pkg": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz", - "integrity": "sha1-nLxoaXj+5l0WwA4rGcI3/Pbjg4k=", - "dev": true, - "requires": { - "load-json-file": "^4.0.0", - "normalize-package-data": "^2.3.2", - "path-type": "^3.0.0" - } - }, - "read-pkg-up": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz", - "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=", - "dev": true, - "requires": { - "find-up": "^1.0.0", - "read-pkg": "^1.0.0" - }, - "dependencies": { - "find-up": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", - "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", - "dev": true, - "requires": { - "path-exists": "^2.0.0", - "pinkie-promise": "^2.0.0" - } - }, - "load-json-file": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", - "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", - "dev": true, - "requires": { - "graceful-fs": "^4.1.2", - "parse-json": "^2.2.0", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0", - "strip-bom": "^2.0.0" - } - }, - "parse-json": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", - "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", - "dev": true, - "requires": { - "error-ex": "^1.2.0" - } - }, - "path-exists": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", - "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", - "dev": true, - "requires": { - "pinkie-promise": "^2.0.0" - } - }, - "path-type": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", - "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=", - "dev": true, - "requires": { - "graceful-fs": "^4.1.2", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0" - } - }, - "pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", - "dev": true - }, - "read-pkg": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", - "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=", - "dev": true, - "requires": { - "load-json-file": "^1.0.0", - "normalize-package-data": "^2.3.2", - "path-type": "^1.0.0" - } - }, - "strip-bom": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", - "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", - "dev": true, - "requires": { - "is-utf8": "^0.2.0" - } - } - } - }, - "readable-stream": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", - "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", - "requires": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - } - }, - "readdirp": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", - "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", - "dev": true, - "requires": { - "picomatch": "^2.2.1" - } - }, - "readline2": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/readline2/-/readline2-1.0.1.tgz", - "integrity": "sha1-QQWWCP/BVHV7cV2ZidGZ/783LjU=", - "dev": true, - "requires": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "mute-stream": "0.0.5" - }, - "dependencies": { - "is-fullwidth-code-point": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", - "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", - "dev": true, - "requires": { - "number-is-nan": "^1.0.0" - } - }, - "mute-stream": { - "version": "0.0.5", - "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.5.tgz", - "integrity": "sha1-j7+rsKmKJT0xhDMfno3rc3L6xsA=", - "dev": true - } - } - }, - "redent": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/redent/-/redent-1.0.0.tgz", - "integrity": "sha1-z5Fqsf1fHxbfsggi3W7H9zDCr94=", - "dev": true, - "requires": { - "indent-string": "^2.1.0", - "strip-indent": "^1.0.1" - } - }, - "reduce-extract": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/reduce-extract/-/reduce-extract-1.0.0.tgz", - "integrity": "sha1-Z/I4W+2mUGG19fQxJmLosIDKFSU=", - "dev": true, - "requires": { - "test-value": "^1.0.1" - }, - "dependencies": { - "array-back": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/array-back/-/array-back-1.0.4.tgz", - "integrity": "sha1-ZEun8JX3/898Q7Xw3DnTwfA8Bjs=", - "dev": true, - "requires": { - "typical": "^2.6.0" - } - }, - "test-value": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/test-value/-/test-value-1.1.0.tgz", - "integrity": "sha1-oJE29y7AQ9J8iTcHwrFZv6196T8=", - "dev": true, - "requires": { - "array-back": "^1.0.2", - "typical": "^2.4.2" - } - } - } - }, - "reduce-flatten": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/reduce-flatten/-/reduce-flatten-1.0.1.tgz", - "integrity": "sha1-JYx479FT3fk8tWEjf2EYTzaW4yc=", - "dev": true - }, - "reduce-unique": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/reduce-unique/-/reduce-unique-2.0.1.tgz", - "integrity": "sha512-x4jH/8L1eyZGR785WY+ePtyMNhycl1N2XOLxhCbzZFaqF4AXjLzqSxa2UHgJ2ZVR/HHyPOvl1L7xRnW8ye5MdA==", - "dev": true - }, - "reduce-without": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/reduce-without/-/reduce-without-1.0.1.tgz", - "integrity": "sha1-aK0OrRGFXJo31OglbBW7+Hly/Iw=", - "dev": true, - "requires": { - "test-value": "^2.0.0" - }, - "dependencies": { - "array-back": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/array-back/-/array-back-1.0.4.tgz", - "integrity": "sha1-ZEun8JX3/898Q7Xw3DnTwfA8Bjs=", - "dev": true, - "requires": { - "typical": "^2.6.0" - } - }, - "test-value": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/test-value/-/test-value-2.1.0.tgz", - "integrity": "sha1-Edpv9nDzRxpztiXKTz/c97t0gpE=", - "dev": true, - "requires": { - "array-back": "^1.0.3", - "typical": "^2.6.0" - } - } - } - }, - "regenerator-runtime": { - "version": "0.11.1", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz", - "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==", - "dev": true - }, - "regexpp": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz", - "integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==", - "dev": true - }, - "registry-auth-token": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-3.4.0.tgz", - "integrity": "sha512-4LM6Fw8eBQdwMYcES4yTnn2TqIasbXuwDx3um+QRs7S55aMKCBKBxvPXl2RiUjHwuJLTyYfxSpmfSAjQpcuP+A==", - "dev": true, - "requires": { - "rc": "^1.1.6", - "safe-buffer": "^5.0.1" - } - }, - "registry-url": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/registry-url/-/registry-url-3.1.0.tgz", - "integrity": "sha1-PU74cPc93h138M+aOBQyRE4XSUI=", - "dev": true, - "requires": { - "rc": "^1.0.1" - } - }, - "repeating": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/repeating/-/repeating-2.0.1.tgz", - "integrity": "sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo=", - "dev": true, - "requires": { - "is-finite": "^1.0.0" - } - }, - "request": { - "version": "2.88.0", - "resolved": "https://registry.npmjs.org/request/-/request-2.88.0.tgz", - "integrity": "sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg==", - "requires": { - "aws-sign2": "~0.7.0", - "aws4": "^1.8.0", - "caseless": "~0.12.0", - "combined-stream": "~1.0.6", - "extend": "~3.0.2", - "forever-agent": "~0.6.1", - "form-data": "~2.3.2", - "har-validator": "~5.1.0", - "http-signature": "~1.2.0", - "is-typedarray": "~1.0.0", - "isstream": "~0.1.2", - "json-stringify-safe": "~5.0.1", - "mime-types": "~2.1.19", - "oauth-sign": "~0.9.0", - "performance-now": "^2.1.0", - "qs": "~6.5.2", - "safe-buffer": "^5.1.2", - "tough-cookie": "~2.4.3", - "tunnel-agent": "^0.6.0", - "uuid": "^3.3.2" - } - }, - "require-directory": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=" - }, - "require-main-filename": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", - "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", - "dev": true - }, - "require-package-name": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/require-package-name/-/require-package-name-2.0.1.tgz", - "integrity": "sha1-wR6XJ2tluOKSP3Xav1+y7ww4Qbk=", - "dev": true - }, - "requizzle": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/requizzle/-/requizzle-0.2.3.tgz", - "integrity": "sha512-YanoyJjykPxGHii0fZP0uUPEXpvqfBDxWV7s6GKAiiOsiqhX6vHNyW3Qzdmqp/iq/ExbhaGbVrjB4ruEVSM4GQ==", - "dev": true, - "requires": { - "lodash": "^4.17.14" - } - }, - "resolve": { - "version": "1.12.0", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.12.0.tgz", - "integrity": "sha512-B/dOmuoAik5bKcD6s6nXDCjzUKnaDvdkRyAk6rsmsKLipWj4797iothd7jmmUhWTfinVMU+wc56rYKsit2Qy4w==", - "dev": true, - "requires": { - "path-parse": "^1.0.6" - } - }, - "resolve-dir": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/resolve-dir/-/resolve-dir-1.0.1.tgz", - "integrity": "sha1-eaQGRMNivoLybv/nOcm7U4IEb0M=", - "dev": true, - "requires": { - "expand-tilde": "^2.0.0", - "global-modules": "^1.0.0" - } - }, - "resolve-from": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", - "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", - "dev": true - }, - "responselike": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/responselike/-/responselike-1.0.2.tgz", - "integrity": "sha1-kYcg7ztjHFZCvgaPFa3lpG9Loec=", - "requires": { - "lowercase-keys": "^1.0.0" - } - }, - "restore-cursor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", - "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", - "requires": { - "onetime": "^5.1.0", - "signal-exit": "^3.0.2" - } - }, - "rfdc": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.3.0.tgz", - "integrity": "sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA==", - "dev": true - }, - "rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dev": true, - "requires": { - "glob": "^7.1.3" - } - }, - "run-async": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.4.1.tgz", - "integrity": "sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==" - }, - "rx-lite": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/rx-lite/-/rx-lite-3.1.2.tgz", - "integrity": "sha1-Gc5QLKVyZl87ZHsQk5+X/RYV8QI=", - "dev": true - }, - "rxjs": { - "version": "7.4.0", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.4.0.tgz", - "integrity": "sha512-7SQDi7xeTMCJpqViXh8gL/lebcwlp3d831F05+9B44A4B0WfsEwUQHR64gsH1kvJ+Ep/J9K2+n1hVl1CsGN23w==", - "requires": { - "tslib": "~2.1.0" - } - }, - "safe-buffer": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.0.tgz", - "integrity": "sha512-fZEwUGbVl7kouZs1jCdMLdt95hdIv0ZeHg6L7qPeciMZhZ+/gdesW4wgTARkrFWEpspjEATAzUGPG8N2jJiwbg==" - }, - "safe-stable-stringify": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/safe-stable-stringify/-/safe-stable-stringify-1.1.1.tgz", - "integrity": "sha512-ERq4hUjKDbJfE4+XtZLFPCDi8Vb1JqaxAPTxWFLBx8XcAlf9Bda/ZJdVezs/NAfsMQScyIlUMx+Yeu7P7rx5jw==" - }, - "safer-buffer": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" - }, - "sax": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", - "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==" - }, - "semver": { - "version": "7.3.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", - "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", - "requires": { - "lru-cache": "^6.0.0" - }, - "dependencies": { - "lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "requires": { - "yallist": "^4.0.0" - } - }, - "yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" - } - } - }, - "semver-compare": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/semver-compare/-/semver-compare-1.0.0.tgz", - "integrity": "sha1-De4hahyUGrN+nvsXiPavxf9VN/w=", - "dev": true - }, - "semver-diff": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/semver-diff/-/semver-diff-2.1.0.tgz", - "integrity": "sha1-S7uEN8jTfksM8aaP1ybsbWRdbTY=", - "dev": true, - "requires": { - "semver": "^5.0.3" - }, - "dependencies": { - "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true - } - } - }, - "serialize-javascript": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz", - "integrity": "sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==", - "dev": true, - "requires": { - "randombytes": "^2.1.0" - } - }, - "set-blocking": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", - "dev": true - }, - "sfmc-fuelsdk-node": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/sfmc-fuelsdk-node/-/sfmc-fuelsdk-node-2.4.0.tgz", - "integrity": "sha512-Orl/Mjc9KlFBjXuJvlzMaXkK1Kl4ns9Y+NS3WwczcmPj4PnNEsdJC7x+KLarxGbKzgR6iGA+PVG8Fhs3tTb1Ww==", - "requires": { - "fuel-auth": "^3.3.0", - "fuel-rest": "^3.2.2", - "fuel-soap": "^2.2.3", - "lodash.merge": "^4.6.1", - "request": "^2.88.0", - "uuid": "^3.3.2" - } - }, - "shebang-command": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", - "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", - "dev": true, - "requires": { - "shebang-regex": "^1.0.0" - } - }, - "shebang-regex": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", - "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", - "dev": true - }, - "shell-quote": { - "version": "1.7.2", - "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.7.2.tgz", - "integrity": "sha512-mRz/m/JVscCrkMyPqHc/bczi3OQHkLTqXHEFu0zDhK/qfv3UcOA4SVmRCLmos4bhjr9ekVQubj/R7waKapmiQg==", - "dev": true - }, - "signal-exit": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.6.tgz", - "integrity": "sha512-sDl4qMFpijcGw22U5w63KmD3cZJfBuFlVNbVMKje2keoKML7X2UzWbc4XrmEbDwg0NXJc3yv4/ox7b+JWb57kQ==" - }, - "simple-git": { - "version": "2.48.0", - "resolved": "https://registry.npmjs.org/simple-git/-/simple-git-2.48.0.tgz", - "integrity": "sha512-z4qtrRuaAFJS4PUd0g+xy7aN4y+RvEt/QTJpR184lhJguBA1S/LsVlvE/CM95RsYMOFJG3NGGDjqFCzKU19S/A==", - "requires": { - "@kwsites/file-exists": "^1.1.1", - "@kwsites/promise-deferred": "^1.1.1", - "debug": "^4.3.2" - } - }, - "simple-swizzle": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz", - "integrity": "sha1-pNprY1/8zMoz9w0Xy5JZLeleVXo=", - "requires": { - "is-arrayish": "^0.3.1" - } - }, - "slice-ansi": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-5.0.0.tgz", - "integrity": "sha512-FC+lgizVPfie0kkhqUScwRu1O/lF6NOgJmlCgK+/LYxDCTk8sGelYaHDhFcDN+Sn3Cv+3VSa4Byeo+IMCzpMgQ==", - "dev": true, - "requires": { - "ansi-styles": "^6.0.0", - "is-fullwidth-code-point": "^4.0.0" - }, - "dependencies": { - "ansi-styles": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.1.0.tgz", - "integrity": "sha512-VbqNsoz55SYGczauuup0MFUyXNQviSpFTj1RQtFzmQLk18qbVSpTFFGMT293rmDaQuKCT6InmbuEyUne4mTuxQ==", - "dev": true - }, - "is-fullwidth-code-point": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-4.0.0.tgz", - "integrity": "sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ==", - "dev": true - } - } - }, - "sort-array": { - "version": "4.1.4", - "resolved": "https://registry.npmjs.org/sort-array/-/sort-array-4.1.4.tgz", - "integrity": "sha512-GVFN6Y1sHKrWaSYOJTk9093ZnrBMc9sP3nuhANU44S4xg3rE6W5Z5WyamuT8VpMBbssnetx5faKCua0LEmUnSw==", - "dev": true, - "requires": { - "array-back": "^5.0.0", - "typical": "^6.0.1" - }, - "dependencies": { - "array-back": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/array-back/-/array-back-5.0.0.tgz", - "integrity": "sha512-kgVWwJReZWmVuWOQKEOohXKJX+nD02JAZ54D1RRWlv8L0NebauKAaFxACKzB74RTclt1+WNz5KHaLRDAPZbDEw==", - "dev": true - }, - "typical": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/typical/-/typical-6.0.1.tgz", - "integrity": "sha512-+g3NEp7fJLe9DPa1TArHm9QAA7YciZmWnfAqEaFrBihQ7epOv9i99rjtgb6Iz0wh3WuQDjsCTDfgRoGnmHN81A==", - "dev": true - } - } - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - }, - "spdx-correct": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.0.tgz", - "integrity": "sha512-lr2EZCctC2BNR7j7WzJ2FpDznxky1sjfxvvYEyzxNyb6lZXHODmEoJeFu4JupYlkfha1KZpJyoqiJ7pgA1qq8Q==", - "dev": true, - "requires": { - "spdx-expression-parse": "^3.0.0", - "spdx-license-ids": "^3.0.0" - } - }, - "spdx-exceptions": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.2.0.tgz", - "integrity": "sha512-2XQACfElKi9SlVb1CYadKDXvoajPgBVPn/gOQLrTvHdElaVhr7ZEbqJaRnJLVNeaI4cMEAgVCeBMKF6MWRDCRA==", - "dev": true - }, - "spdx-expression-parse": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz", - "integrity": "sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg==", - "dev": true, - "requires": { - "spdx-exceptions": "^2.1.0", - "spdx-license-ids": "^3.0.0" - } - }, - "spdx-license-ids": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.5.tgz", - "integrity": "sha512-J+FWzZoynJEXGphVIS+XEh3kFSjZX/1i9gFBaWQcB+/tmpe2qUsSBABpcxqxnAxFdiUFEgAX1bjYGQvIZmoz9Q==", - "dev": true - }, - "sprintf-js": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", - "dev": true - }, - "sql-formatter-plus": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/sql-formatter-plus/-/sql-formatter-plus-1.3.6.tgz", - "integrity": "sha512-3pelcpLve9GgsXshWL/59zyDkhICkXDURKjXyUN+PJqVGAt+ZmNPB2JY+hgnaQG5X9TQI7Q+WiyLEprHQAWuaQ==", - "requires": { - "@babel/polyfill": "^7.6.0", - "lodash": "^4.17.15" - } - }, - "sshpk": { - "version": "1.16.1", - "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz", - "integrity": "sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==", - "requires": { - "asn1": "~0.2.3", - "assert-plus": "^1.0.0", - "bcrypt-pbkdf": "^1.0.0", - "dashdash": "^1.12.0", - "ecc-jsbn": "~0.1.1", - "getpass": "^0.1.1", - "jsbn": "~0.1.0", - "safer-buffer": "^2.0.2", - "tweetnacl": "~0.14.0" - } - }, - "stack-trace": { - "version": "0.0.10", - "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz", - "integrity": "sha1-VHxws0fo0ytOEI6hoqFZ5f3eGcA=" - }, - "stackframe": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/stackframe/-/stackframe-0.3.1.tgz", - "integrity": "sha1-M6qE8Rd6VUjIk1Uzy/6zQgl19aQ=", - "dev": true - }, - "stream-connect": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/stream-connect/-/stream-connect-1.0.2.tgz", - "integrity": "sha1-GLyB8u2zW4tdmoAJIAqYUxRCipc=", - "dev": true, - "requires": { - "array-back": "^1.0.2" - }, - "dependencies": { - "array-back": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/array-back/-/array-back-1.0.4.tgz", - "integrity": "sha1-ZEun8JX3/898Q7Xw3DnTwfA8Bjs=", - "dev": true, - "requires": { - "typical": "^2.6.0" - } - } - } - }, - "stream-via": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/stream-via/-/stream-via-1.0.4.tgz", - "integrity": "sha512-DBp0lSvX5G9KGRDTkR/R+a29H+Wk2xItOF+MpZLLNDWbEV9tGPnqLPxHEYjmiz8xGtJHRIqmI+hCjmNzqoA4nQ==", - "dev": true - }, - "string_decoder": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", - "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", - "requires": { - "safe-buffer": "~5.2.0" - } - }, - "string-argv": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/string-argv/-/string-argv-0.3.1.tgz", - "integrity": "sha512-a1uQGz7IyVy9YwhqjZIZu1c8JO8dNIe20xBmSS6qu9kv++k3JGzCVmprbNN5Kn+BgzD5E7YYwg1CcjuJMRNsvg==", - "dev": true - }, - "string-width": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", - "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", - "dev": true, - "requires": { - "emoji-regex": "^7.0.1", - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^5.1.0" - } - }, - "string.prototype.padend": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/string.prototype.padend/-/string.prototype.padend-3.0.0.tgz", - "integrity": "sha1-86rvfBcZ8XDF6rHDK/eA2W4h8vA=", - "dev": true, - "requires": { - "define-properties": "^1.1.2", - "es-abstract": "^1.4.3", - "function-bind": "^1.0.2" - } - }, - "string.prototype.trimleft": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/string.prototype.trimleft/-/string.prototype.trimleft-2.1.0.tgz", - "integrity": "sha512-FJ6b7EgdKxxbDxc79cOlok6Afd++TTs5szo+zJTUyow3ycrRfJVE2pq3vcN53XexvKZu/DJMDfeI/qMiZTrjTw==", - "requires": { - "define-properties": "^1.1.3", - "function-bind": "^1.1.1" - } - }, - "string.prototype.trimright": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/string.prototype.trimright/-/string.prototype.trimright-2.1.0.tgz", - "integrity": "sha512-fXZTSV55dNBwv16uw+hh5jkghxSnc5oHq+5K/gXgizHwAvMetdAJlHqqoFC1FSDVPYWLkAKl2cxpUT41sV7nSg==", - "requires": { - "define-properties": "^1.1.3", - "function-bind": "^1.1.1" - } - }, - "strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", - "dev": true, - "requires": { - "ansi-regex": "^4.1.0" - } - }, - "strip-bom": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", - "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", - "dev": true - }, - "strip-eof": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", - "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=", - "dev": true - }, - "strip-final-newline": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", - "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", - "dev": true - }, - "strip-indent": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-1.0.1.tgz", - "integrity": "sha1-DHlipq3vp7vUrDZkYKY4VSrhoKI=", - "dev": true, - "requires": { - "get-stdin": "^4.0.1" - }, - "dependencies": { - "get-stdin": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz", - "integrity": "sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4=", - "dev": true - } - } - }, - "strip-json-comments": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", - "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=" - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - }, - "table-layout": { - "version": "0.4.5", - "resolved": "https://registry.npmjs.org/table-layout/-/table-layout-0.4.5.tgz", - "integrity": "sha512-zTvf0mcggrGeTe/2jJ6ECkJHAQPIYEwDoqsiqBjI24mvRmQbInK5jq33fyypaCBxX08hMkfmdOqj6haT33EqWw==", - "dev": true, - "requires": { - "array-back": "^2.0.0", - "deep-extend": "~0.6.0", - "lodash.padend": "^4.6.1", - "typical": "^2.6.1", - "wordwrapjs": "^3.0.0" - }, - "dependencies": { - "array-back": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/array-back/-/array-back-2.0.0.tgz", - "integrity": "sha512-eJv4pLLufP3g5kcZry0j6WXpIbzYw9GUB4mVJZno9wfwiBxbizTnHCw3VJb07cBihbFX48Y7oSrW9y+gt4glyw==", - "dev": true, - "requires": { - "typical": "^2.6.1" - } - } - } - }, - "taffydb": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/taffydb/-/taffydb-2.6.2.tgz", - "integrity": "sha1-fLy2S1oUG2ou/CxdLGe04VCyomg=", - "dev": true - }, - "temp-path": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/temp-path/-/temp-path-1.0.0.tgz", - "integrity": "sha1-JLFUOXOrRCiW2a02fdnL2/r+kYs=", - "dev": true - }, - "term-size": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/term-size/-/term-size-2.2.1.tgz", - "integrity": "sha512-wK0Ri4fOGjv/XPy8SBHZChl8CM7uMc5VML7SqiQ0zG7+J5Vr+RMQDoHa2CNT6KHUnTGIXH34UDMkPzAUyapBZg==" - }, - "test-value": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/test-value/-/test-value-3.0.0.tgz", - "integrity": "sha512-sVACdAWcZkSU9x7AOmJo5TqE+GyNJknHaHsMrR6ZnhjVlVN9Yx6FjHrsKZ3BjIpPCT68zYesPWkakrNupwfOTQ==", - "dev": true, - "requires": { - "array-back": "^2.0.0", - "typical": "^2.6.1" - }, - "dependencies": { - "array-back": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/array-back/-/array-back-2.0.0.tgz", - "integrity": "sha512-eJv4pLLufP3g5kcZry0j6WXpIbzYw9GUB4mVJZno9wfwiBxbizTnHCw3VJb07cBihbFX48Y7oSrW9y+gt4glyw==", - "dev": true, - "requires": { - "typical": "^2.6.1" - } - } - } - }, - "text-hex": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/text-hex/-/text-hex-1.0.0.tgz", - "integrity": "sha512-uuVGNWzgJ4yhRaNSiubPY7OjISw4sw4E5Uv0wbjp+OzcbmVU/rsT8ujgcXJhn9ypzsgr5vlzpPqP+MBBKcGvbg==" - }, - "text-table": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", - "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", - "dev": true - }, - "throat": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/throat/-/throat-2.0.2.tgz", - "integrity": "sha1-qfzoCLaeEzpjJZB4DzQsMKYkmwI=", - "dev": true - }, - "through": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", - "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=" - }, - "timed-out": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/timed-out/-/timed-out-4.0.1.tgz", - "integrity": "sha1-8y6srFoXW+ol1/q1Zas+2HQe9W8=", - "dev": true - }, - "tmp": { - "version": "0.0.33", - "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", - "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", - "requires": { - "os-tmpdir": "~1.0.2" - } - }, - "to-fast-properties": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", - "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", - "dev": true - }, - "to-readable-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/to-readable-stream/-/to-readable-stream-1.0.0.tgz", - "integrity": "sha512-Iq25XBt6zD5npPhlLVXGFN3/gyR2/qODcKNNyTMd4vbm39HUaOiAM4PMq0eMVC/Tkxz+Zjdsc55g9yyz+Yq00Q==" - }, - "to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dev": true, - "requires": { - "is-number": "^7.0.0" - } - }, - "toposort": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/toposort/-/toposort-2.0.2.tgz", - "integrity": "sha1-riF2gXXRVZ1IvvNUILL0li8JwzA=" - }, - "tough-cookie": { - "version": "2.4.3", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.4.3.tgz", - "integrity": "sha512-Q5srk/4vDM54WJsJio3XNn6K2sCG+CQ8G5Wz6bZhRZoAe/+TxjWB/GlFAnYEbkYVlON9FMk/fE3h2RLpPXo4lQ==", - "requires": { - "psl": "^1.1.24", - "punycode": "^1.4.1" - }, - "dependencies": { - "punycode": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", - "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=" - } - } - }, - "traverse": { - "version": "0.6.6", - "resolved": "https://registry.npmjs.org/traverse/-/traverse-0.6.6.tgz", - "integrity": "sha1-y99WD9e5r2MlAv7UD5GMFX6pcTc=" - }, - "trim-newlines": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-1.0.0.tgz", - "integrity": "sha1-WIeWa7WCpFA6QetST301ARgVphM=", - "dev": true - }, - "triple-beam": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/triple-beam/-/triple-beam-1.3.0.tgz", - "integrity": "sha512-XrHUvV5HpdLmIj4uVMxHggLbFSZYIn7HEWsqePZcI50pco+MPqJ50wMGY794X7AOOhxOBAjbkqfAbEe/QMp2Lw==" - }, - "tslib": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.1.0.tgz", - "integrity": "sha512-hcVC3wYEziELGGmEEXue7D75zbwIIVUMWAVbHItGPx0ziyXxrOMQx4rQEVEV45Ut/1IotuEvwqPopzIOkDMf0A==" - }, - "tunnel-agent": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", - "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", - "requires": { - "safe-buffer": "^5.0.1" - } - }, - "tweetnacl": { - "version": "0.14.5", - "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", - "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=" - }, - "type-check": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", - "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", - "dev": true, - "requires": { - "prelude-ls": "^1.2.1" - } - }, - "type-detect": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", - "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", - "dev": true - }, - "type-fest": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", - "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==" - }, - "typedarray-to-buffer": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz", - "integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==", - "requires": { - "is-typedarray": "^1.0.0" - } - }, - "typical": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/typical/-/typical-2.6.1.tgz", - "integrity": "sha1-XAgOXWYcu+OCWdLnCjxyU+hziB0=", - "dev": true - }, - "uc.micro": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-1.0.6.tgz", - "integrity": "sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA==", - "dev": true - }, - "uglify-js": { - "version": "3.13.1", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.13.1.tgz", - "integrity": "sha512-EWhx3fHy3M9JbaeTnO+rEqzCe1wtyQClv6q3YWq0voOj4E+bMZBErVS1GAHPDiRGONYq34M1/d8KuQMgvi6Gjw==", - "dev": true, - "optional": true - }, - "underscore": { - "version": "1.13.1", - "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.13.1.tgz", - "integrity": "sha512-hzSoAVtJF+3ZtiFX0VgfFPHEDRm7Y/QPjGyNo4TVdnDTdft3tr8hEkD25a1jC+TjTuE7tkHGKkhwCgs9dgBB2g==", - "dev": true - }, - "unique-string": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-2.0.0.tgz", - "integrity": "sha512-uNaeirEPvpZWSgzwsPGtU2zVSTrn/8L5q/IexZmH0eH6SA73CmAA5U4GwORTxQAZs95TAXLNqeLoPPNO5gZfWg==", - "requires": { - "crypto-random-string": "^2.0.0" - } - }, - "universalify": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-1.0.0.tgz", - "integrity": "sha512-rb6X1W158d7pRQBg5gkR8uPaSfiids68LTJQYOtEUhoJUWBdaQHsuT/EUduxXYxcrt4r5PJ4fuHW1MHT6p0qug==" - }, - "unzip-response": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/unzip-response/-/unzip-response-2.0.1.tgz", - "integrity": "sha1-0vD3N9FrBhXnKmk17QQhRXLVb5c=", - "dev": true - }, - "update-notifier-git": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/update-notifier-git/-/update-notifier-git-5.0.3.tgz", - "integrity": "sha512-Ikg++hC5EUKURxT+aCsnA58ZYq67Hiof2jK0rlFCJuF/lQsm3g2AKx1BrQZ9cO2x0mksUhabzWvAAJH45nXSJw==", - "requires": { - "boxen": "^4.2.0", - "chalk": "^3.0.0", - "configstore": "^5.0.1", - "git-version-tag": "^1.0.2", - "has-yarn": "^2.1.0", - "import-lazy": "^2.1.0", - "is-ci": "^2.0.0", - "is-npm": "^4.0.0", - "is-yarn-global": "^0.3.0", - "latest-version": "^5.0.0", - "pupa": "^2.0.1", - "semver-diff": "^3.1.1", - "xdg-basedir": "^4.0.0" - }, - "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "requires": { - "color-convert": "^2.0.1" - } - }, - "chalk": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", - "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "ci-info": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz", - "integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==" - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" - }, - "is-ci": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-2.0.0.tgz", - "integrity": "sha512-YfJT7rkpQB0updsdHLGWrvhBJfcfzNNawYDNIyQXJz0IViGf75O8EBPKSdvw2rF+LGCsX4FZ8tcr3b19LcZq4w==", - "requires": { - "ci-info": "^2.0.0" - } - }, - "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==" - }, - "semver-diff": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/semver-diff/-/semver-diff-3.1.1.tgz", - "integrity": "sha512-GX0Ix/CJcHyB8c4ykpHGIAvLyOwOobtM/8d+TQkAd81/bEjgPHrfba41Vpesr7jX/t8Uh+R3EX9eAS5be+jQYg==", - "requires": { - "semver": "^6.3.0" - } - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "requires": { - "has-flag": "^4.0.0" - } - } - } - }, - "uri-js": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz", - "integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==", - "requires": { - "punycode": "^2.1.0" - } - }, - "url-parse-lax": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-1.0.0.tgz", - "integrity": "sha1-evjzA2Rem9eaJy56FKxovAYJ2nM=", - "dev": true, - "requires": { - "prepend-http": "^1.0.1" - } - }, - "util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" - }, - "util.promisify": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/util.promisify/-/util.promisify-1.0.0.tgz", - "integrity": "sha512-i+6qA2MPhvoKLuxnJNpXAGhg7HphQOSUq2LKMZD0m15EiskXUkMvKdF4Uui0WYeCUGea+o2cw/ZuwehtfsrNkA==", - "requires": { - "define-properties": "^1.1.2", - "object.getownpropertydescriptors": "^2.0.3" - } - }, - "uuid": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.3.tgz", - "integrity": "sha512-pW0No1RGHgzlpHJO1nsVrHKpOEIxkGg1xB+v0ZmdNH5OAeAwzAVrCnI2/6Mtx+Uys6iaylxa+D3g4j63IKKjSQ==" - }, - "v8-compile-cache": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.2.0.tgz", - "integrity": "sha512-gTpR5XQNKFwOd4clxfnhaqvfqMpqEwr4tOtCyz4MtYZX2JYhfr1JvBFKdS+7K/9rfpZR3VLX+YWBbKoxCgS43Q==", - "dev": true - }, - "validate-npm-package-license": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", - "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", - "dev": true, - "requires": { - "spdx-correct": "^3.0.0", - "spdx-expression-parse": "^3.0.0" - } - }, - "verror": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", - "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", - "requires": { - "assert-plus": "^1.0.0", - "core-util-is": "1.0.2", - "extsprintf": "^1.2.0" - } - }, - "vue-template-compiler": { - "version": "2.6.11", - "resolved": "https://registry.npmjs.org/vue-template-compiler/-/vue-template-compiler-2.6.11.tgz", - "integrity": "sha512-KIq15bvQDrcCjpGjrAhx4mUlyyHfdmTaoNfeoATHLAiWB+MU3cx4lOzMwrnUh9cCxy0Lt1T11hAFY6TQgroUAA==", - "dev": true, - "requires": { - "de-indent": "^1.0.2", - "he": "^1.1.0" - } - }, - "walk-back": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/walk-back/-/walk-back-5.1.0.tgz", - "integrity": "sha512-Uhxps5yZcVNbLEAnb+xaEEMdgTXl9qAQDzKYejG2AZ7qPwRQ81lozY9ECDbjLPNWm7YsO1IK5rsP1KoQzXAcGA==", - "dev": true - }, - "walkdir": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/walkdir/-/walkdir-0.3.2.tgz", - "integrity": "sha512-0Twghia4Z5wDGDYWURlhZmI47GvERMCsXIu0QZWVVZyW9ZjpbbZvD9Zy9M6cWiQQRRbAcYajIyKNavaZZDt1Uw==", - "dev": true - }, - "wcwidth": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz", - "integrity": "sha1-8LDc+RW8X/FSivrbLA4XtTLaL+g=", - "requires": { - "defaults": "^1.0.3" - } - }, - "which": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", - "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", - "dev": true, - "requires": { - "isexe": "^2.0.0" - } - }, - "which-module": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", - "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", - "dev": true - }, - "which-pm": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/which-pm/-/which-pm-1.1.0.tgz", - "integrity": "sha512-7GHHJQpALk7BWMD8I+xSILSbHyngvBlfSXlwGpdRFY2voFwVCx+eJAybXTzTnUYmt7zio6B9SEdI81T0fBjxNA==", - "dev": true, - "requires": { - "load-yaml-file": "^0.1.0", - "path-exists": "^3.0.0" - } - }, - "widest-line": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-3.1.0.tgz", - "integrity": "sha512-NsmoXalsWVDMGupxZ5R08ka9flZjjiLvHVAWYOKtiKM8ujtZWr9cRffak+uSE48+Ob8ObalXpwyeUiyDD6QFgg==", - "requires": { - "string-width": "^4.0.0" - }, - "dependencies": { - "ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==" - }, - "emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" - }, - "is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==" - }, - "string-width": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz", - "integrity": "sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==", - "requires": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.0" - } - }, - "strip-ansi": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", - "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", - "requires": { - "ansi-regex": "^5.0.0" - } - } - } - }, - "winston": { - "version": "3.3.4", - "resolved": "https://registry.npmjs.org/winston/-/winston-3.3.4.tgz", - "integrity": "sha512-zWJrfmqE+2IXtVJ125vxpA2m303TjwchLhfRbcnma7c76Qd4pv80JIp37l8uGnWbCoG4X6PMz3vAQeh+vH1CtA==", - "requires": { - "@dabh/diagnostics": "^2.0.2", - "async": "^3.2.3", - "is-stream": "^2.0.0", - "logform": "^2.3.2", - "one-time": "^1.0.0", - "readable-stream": "^3.4.0", - "stack-trace": "0.0.x", - "triple-beam": "^1.3.0", - "winston-transport": "^4.4.2" - }, - "dependencies": { - "is-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.0.tgz", - "integrity": "sha512-XCoy+WlUr7d1+Z8GgSuXmpuUFC9fOhRXglJMx+dwLKTkL44Cjd4W1Z5P+BQZpr+cR93aGP4S/s7Ftw6Nd/kiEw==" - } - } - }, - "winston-transport": { - "version": "4.4.2", - "resolved": "https://registry.npmjs.org/winston-transport/-/winston-transport-4.4.2.tgz", - "integrity": "sha512-9jmhltAr5ygt5usgUTQbEiw/7RYXpyUbEAFRCSicIacpUzPkrnQsQZSPGEI12aLK9Jth4zNcYJx3Cvznwrl8pw==", - "requires": { - "logform": "^2.3.2", - "readable-stream": "^3.4.0", - "triple-beam": "^1.2.0" - } - }, - "word-wrap": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", - "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", - "dev": true - }, - "wordwrap": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", - "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=", - "dev": true - }, - "wordwrapjs": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/wordwrapjs/-/wordwrapjs-3.0.0.tgz", - "integrity": "sha512-mO8XtqyPvykVCsrwj5MlOVWvSnCdT+C+QVbm6blradR7JExAhbkZ7hZ9A+9NUtwzSqrlUo9a67ws0EiILrvRpw==", - "dev": true, - "requires": { - "reduce-flatten": "^1.0.1", - "typical": "^2.6.1" - } - }, - "workerpool": { - "version": "6.1.5", - "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.1.5.tgz", - "integrity": "sha512-XdKkCK0Zqc6w3iTxLckiuJ81tiD/o5rBE/m+nXpRCB+/Sq4DqkfXZ/x0jW02DG1tGsfUGXbTJyZDP+eu67haSw==", - "dev": true - }, - "wrap-ansi": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz", - "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.0", - "string-width": "^3.0.0", - "strip-ansi": "^5.0.0" - } - }, - "wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" - }, - "write-file-atomic": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz", - "integrity": "sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==", - "requires": { - "imurmurhash": "^0.1.4", - "is-typedarray": "^1.0.0", - "signal-exit": "^3.0.2", - "typedarray-to-buffer": "^3.1.5" - } - }, - "xdg-basedir": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-4.0.0.tgz", - "integrity": "sha512-PSNhEJDejZYV7h50BohL09Er9VaIefr2LMAf3OEmpCkjOi34eYyQYAXUTjEQtZJTKcF0E2UKTh+osDLsgNim9Q==" - }, - "xml2js": { - "version": "0.4.22", - "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.22.tgz", - "integrity": "sha512-MWTbxAQqclRSTnehWWe5nMKzI3VmJ8ltiJEco8akcC6j3miOhjjfzKum5sId+CWhfxdOs/1xauYr8/ZDBtQiRw==", - "requires": { - "sax": ">=0.6.0", - "util.promisify": "~1.0.0", - "xmlbuilder": "~11.0.0" - } - }, - "xmlbuilder": { - "version": "11.0.1", - "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-11.0.1.tgz", - "integrity": "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==" - }, - "xmlcreate": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/xmlcreate/-/xmlcreate-2.0.4.tgz", - "integrity": "sha512-nquOebG4sngPmGPICTS5EnxqhKbCmz5Ox5hsszI2T6U5qdrJizBc+0ilYSEjTSzU0yZcmvppztXe/5Al5fUwdg==", - "dev": true - }, - "xtend": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", - "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", - "dev": true - }, - "y18n": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", - "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==", - "dev": true - }, - "yallist": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", - "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=", - "dev": true - }, - "yaml": { - "version": "1.10.2", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", - "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", - "dev": true - }, - "yargs": { - "version": "17.3.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.3.0.tgz", - "integrity": "sha512-GQl1pWyDoGptFPJx9b9L6kmR33TGusZvXIZUT+BOz9f7X2L94oeAskFYLEg/FkhV06zZPBYLvLZRWeYId29lew==", - "requires": { - "cliui": "^7.0.2", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.3", - "y18n": "^5.0.5", - "yargs-parser": "^21.0.0" - }, - "dependencies": { - "ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==" - }, - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "requires": { - "color-convert": "^2.0.1" - } - }, - "cliui": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.3.tgz", - "integrity": "sha512-Gj3QHTkVMPKqwP3f7B4KPkBZRMR9r4rfi5bXFpg1a+Svvj8l7q5CnkBkVQzfxT5DFSsGk2+PascOgL0JYkL2kw==", - "requires": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", - "wrap-ansi": "^7.0.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" - }, - "emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" - }, - "is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==" - }, - "string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "requires": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - } - }, - "strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "requires": { - "ansi-regex": "^5.0.1" - } - }, - "wrap-ansi": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "requires": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - } - }, - "y18n": { - "version": "5.0.5", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.5.tgz", - "integrity": "sha512-hsRUr4FFrvhhRH12wOdfs38Gy7k2FFzB9qgN9v3aLykRq0dRcdcpz5C9FxdS2NuhOrI/628b/KSTJ3rwHysYSg==" - }, - "yargs-parser": { - "version": "21.0.0", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.0.0.tgz", - "integrity": "sha512-z9kApYUOCwoeZ78rfRYYWdiU/iNL6mwwYlkkZfJoyMR1xps+NEBX5X7XmRpxkZHhXJ6+Ey00IwKxBBSW9FIjyA==" - } - } - }, - "yargs-parser": { - "version": "13.1.2", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.2.tgz", - "integrity": "sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==", - "dev": true, - "requires": { - "camelcase": "^5.0.0", - "decamelize": "^1.2.0" - } - }, - "yargs-unparser": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-2.0.0.tgz", - "integrity": "sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==", - "dev": true, - "requires": { - "camelcase": "^6.0.0", - "decamelize": "^4.0.0", - "flat": "^5.0.2", - "is-plain-obj": "^2.1.0" - }, - "dependencies": { - "camelcase": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.2.0.tgz", - "integrity": "sha512-c7wVvbw3f37nuobQNtgsgG9POC9qMbNuMQmTCqZv23b6MIz0fcYpBiOlv9gEN/hdLdnZTDQhg6e9Dq5M1vKvfg==", - "dev": true - }, - "decamelize": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz", - "integrity": "sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==", - "dev": true - } - } } } } diff --git a/package.json b/package.json index f3c6ec6d3..27999db79 100644 --- a/package.json +++ b/package.json @@ -1,14 +1,14 @@ { "name": "mcdev", - "version": "3.1.3", + "version": "9.0.2", "description": "Accenture Salesforce Marketing Cloud DevTools", - "author": "joern.berkefeld, douglas.midgley, robert.zimmermann, maciej.barnas", + "author": "Accenture: joern.berkefeld, douglas.midgley, robert.zimmermann, maciej.barnas", "license": "MIT", "repository": { "type": "git", "url": "https://github.com/Accenture/sfmc-devtools.git" }, - "homepage": "https://github.com/Accenture/sfmc-devtools#readme", + "homepage": "https://github.com/Accenture/sfmc-devtools/wiki", "bugs": { "url": "https://github.com/Accenture/sfmc-devtools/issues", "email": "joern.berkefeld@accenture.com" @@ -17,61 +17,113 @@ "type": "corporate", "url": "https://github.com/Accenture/sfmc-devtools" }, + "keywords": [ + "sfmc", + "ide", + "devops", + "developer", + "exacttarget", + "salesforce", + "marketing cloud", + "package manager", + "fuel", + "soap", + "rest" + ], "main": "./lib/index.js", + "exports": { + ".": { + "types": "./@types/lib/index.d.ts", + "default": "./lib/index.js" + }, + "./*": { + "types": "./@types/lib/*.d.ts", + "default": "./lib/*.js" + } + }, "bin": { "mcdev": "./lib/cli.js" }, "engines": { - "node": ">=14.16" + "node": "^20.19.0 || ^22.13.0 || >=24" }, "scripts": { - "start": "node lib/index.js", - "mcdev": "node lib/index.js", - "build": "run-s lint docs", - "debug": "node --nolazy --inspect-brk=9229 lib/index.js", - "docs": "jsdoc2md --files lib/**/*.js > docs/dist/documentation.md", - "lint": "eslint --fix lib/**/*.js && eslint --fix test/**/*.js && prettier --write lib/**/*.js", - "test": "mocha --recursive", - "upgrade": "npm-check --update", - "prepare": "husky install" + "start": "node lib/cli.js", + "mcdev": "node lib/cli.js", + "build": "run-s lint:fix docs test", + "debug": "node --nolazy --inspect-brk=9229 lib/cli.js", + "lint:fix": "eslint --fix lib/**/*.js types/*.js test/**/*.js", + "lint": "eslint lib/**/*.js types/*.js test/**/*.js", + "lint-ts": "tsc -p tsconfig.npmScripts.json", + "prepare": "husky || true", + "lint-and-test": "run-s lint test", + "test": "mocha --reporter-option maxDiffSize=25000", + "coverage": "c8 npm run test", + "prepare-release:audit-fix": "npm audit fix", + "prepare-release:git": "node prepare-release.js", + "prepare-release": "run-s --continue-on-error prepare-release:audit-fix lint-ts lint:fix prepare-release:git", + "version:major": "npm version --no-commit-hooks major", + "version:minor": "npm version --no-commit-hooks minor", + "version:patch": "npm version --no-commit-hooks patch" }, "dependencies": { - "bluebird": "3.7.2", - "cli-progress": "3.10.0", + "beauty-amp-core2": "0.4.9", + "cli-progress": "3.12.0", "command-exists": "1.2.9", + "conf": "15.1.0", "console.table": "0.10.0", - "fs-extra": "10.0.0", - "inquirer": "8.2.0", + "deep-equal": "2.2.3", + "fs-extra": "11.3.4", + "inquirer": "13.3.0", "json-to-table": "4.2.1", "mustache": "4.2.0", - "prettier": "2.5.1", - "semver": "7.3.5", - "sfmc-fuelsdk-node": "2.4.0", - "simple-git": "2.48.0", - "sql-formatter-plus": "1.3.6", + "p-limit": "7.3.0", + "prettier": "3.8.1", + "prettier-plugin-sql": "0.19.2", + "semver": "7.7.4", + "sfmc-sdk": "3.0.1", + "simple-git": "3.32.3", "toposort": "2.0.2", - "update-notifier-git": "5.0.3", - "winston": "3.3.4", - "yargs": "17.3.0" + "update-notifier": "7.3.1", + "winston": "3.19.0", + "yargs": "18.0.0", + "yocto-spinner": "1.1.0" }, "devDependencies": { - "chai": "4.3.4", - "eslint": "8.4.1", - "eslint-config-prettier": "8.3.0", - "eslint-config-ssjs": "1.1.11", - "eslint-plugin-mocha": "10.0.1", - "eslint-plugin-prettier": "4.0.0", - "husky": "7.0.4", - "jsdoc-to-markdown": "7.1.0", - "lint-staged": "12.1.2", - "mocha": "9.1.3", - "npm-check": "5.9.2", - "npm-run-all": "4.1.5" + "@eslint/js": "10.0.1", + "@types/fs-extra": "11.0.4", + "@types/inquirer": "9.0.9", + "@types/mocha": "10.0.8", + "@types/node": "25.3.5", + "@types/yargs": "17.0.35", + "assert": "2.1.0", + "axios-mock-adapter": "2.0.0", + "c8": "11.0.0", + "chai": "6.2.2", + "chai-files": "1.4.0", + "eslint": "10.0.3", + "eslint-config-ssjs": "2.0.0", + "eslint-plugin-jsdoc": "62.7.1", + "eslint-plugin-mocha": "11.2.0", + "eslint-plugin-prettier": "5.5.5", + "eslint-plugin-unicorn": "63.0.0", + "fast-xml-parser": "5.4.2", + "globals": "17.4.0", + "husky": "9.1.7", + "lint-staged": "16.3.2", + "mocha": "11.7.5", + "mock-fs": "5.3.0", + "npm-run-all": "4.1.5", + "prettier-eslint": "16.4.2", + "typescript": "5.9.3" + }, + "optionalDependencies": { + "fsevents": "*" }, "lint-staged": { - "*.{js,jsx,ts,tsx}": [ - "eslint --fix", - "prettier --write" + "*.js": [ + "eslint --fix" ] - } + }, + "type": "module" } diff --git a/prepare-release.js b/prepare-release.js new file mode 100644 index 000000000..8f099e3cd --- /dev/null +++ b/prepare-release.js @@ -0,0 +1,37 @@ +/* eslint-disable no-console */ +import { exec } from 'node:child_process'; + +console.log('> git status --porcelain'); +exec('git status --porcelain', (err, stdout, stderr) => { + if (err) { + console.error(`Error executing git status: ${stderr}`); + return; + } + + if (stdout) { + console.log( + ' Found changes:', + '\n - ' + stdout.split('\n').filter(Boolean).join('\n - ') + ); + console.log('> git add .'); + exec('git add .', (err, stdout, stderr) => { + if (err) { + console.error(`Error executing git add: ${stderr}`); + return; + } + + console.log('> git commit -n -m "prepare-release changes"'); + exec('git commit -n -m "prepare-release changes"', (err, stdout, stderr) => { + if (err) { + console.error(`Error executing git commit: ${stderr}`); + return; + } else { + console.log('✅ Changes committed successfully.'); + } + }); + }); + } else { + console.log('✅ No untracked files to commit.'); + } +}); +/* eslint-enable no-console */ diff --git a/test/general.test.js b/test/general.test.js new file mode 100644 index 000000000..946edab3c --- /dev/null +++ b/test/general.test.js @@ -0,0 +1,2709 @@ +import * as chai from 'chai'; +const assert = chai.assert; +const expect = chai.expect; + +import chaiFiles from 'chai-files'; +import * as testUtils from './utils.js'; +import handler from '../lib/index.js'; +chai.use(chaiFiles); + +describe('GENERAL', () => { + beforeEach(() => { + testUtils.mockSetup(); + }); + + afterEach(() => { + testUtils.mockReset(); + }); + + describe('ReplaceContentBlockByX ================', () => { + describe('with types specified ================', () => { + it('Should replace references with ContentBlockByName w/o deploy', async () => { + handler.setOptions({ skipDeploy: true }); + + // WHEN + const replace = await handler.replaceCbReference( + 'testInstance/testBU', + { + journey: null, + senderProfile: null, + }, + 'name' + ); + // THEN + assert.equal(process.exitCode, 0, 'retrieve should not have thrown an error'); + // retrieve result + assert.deepEqual( + replace['testInstance/testBU'].journey, + ['testExisting_journey_Quicksend'], + 'should have found the right journeys that need updating' + ); + assert.deepEqual( + replace['testInstance/testBU'].senderProfile, + ['testExisting_senderProfile_rcb'], + 'should have found the right senderProfiles that need updating' + ); + + // check if conversions happened + assert.deepEqual( + await testUtils.getActualJson('testExisting_journey_Quicksend', 'journey'), + await testUtils.getExpectedJson('9999999', 'journey', 'get-quicksend-rcb-name'), + 'returned JSON was not equal expected' + ); + assert.deepEqual( + await testUtils.getActualJson( + 'testExisting_senderProfile_rcb', + 'senderProfile' + ), + await testUtils.getExpectedJson('9999999', 'senderProfile', 'get-rcb-name'), + 'returned JSON was not equal expected' + ); + assert.equal( + testUtils.getAPIHistoryLength(), + 46, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + return; + }); + + it('Should replace references with ContentBlockById w/o deploy', async () => { + handler.setOptions({ skipDeploy: true }); + + // WHEN + const replace = await handler.replaceCbReference( + 'testInstance/testBU', + { + journey: null, + senderProfile: null, + }, + 'id' + ); + // THEN + assert.equal(process.exitCode, 0, 'retrieve should not have thrown an error'); + // retrieve result + assert.deepEqual( + replace['testInstance/testBU'].journey, + ['testExisting_journey_Quicksend'], + 'should have found the right journeys that need updating' + ); + assert.deepEqual( + replace['testInstance/testBU'].senderProfile, + ['testExisting_senderProfile_rcb'], + 'should have found the right senderProfiles that need updating' + ); + + // check if conversions happened + assert.deepEqual( + await testUtils.getActualJson('testExisting_journey_Quicksend', 'journey'), + await testUtils.getExpectedJson('9999999', 'journey', 'get-quicksend-rcb-id'), + 'returned JSON was not equal expected' + ); + assert.deepEqual( + await testUtils.getActualJson( + 'testExisting_senderProfile_rcb', + 'senderProfile' + ), + await testUtils.getExpectedJson('9999999', 'senderProfile', 'get-rcb-id'), + 'returned JSON was not equal expected' + ); + assert.equal( + testUtils.getAPIHistoryLength(), + 46, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + return; + }); + + it('Should replace references with ContentBlockByKey w/o deploy', async () => { + handler.setOptions({ skipDeploy: true }); + + // WHEN + const replace = await handler.replaceCbReference( + 'testInstance/testBU', + { + journey: null, + senderProfile: null, + }, + 'key' + ); + // THEN + assert.equal(process.exitCode, 0, 'retrieve should not have thrown an error'); + // retrieve result + assert.deepEqual( + replace['testInstance/testBU'].journey, + ['testExisting_journey_Quicksend'], + 'should have found the right assets that need updating' + ); + assert.deepEqual( + replace['testInstance/testBU'].senderProfile, + ['testExisting_senderProfile_rcb'], + 'should have found the right senderProfiles that need updating' + ); + + // check if conversions happened + assert.deepEqual( + await testUtils.getActualJson('testExisting_journey_Quicksend', 'journey'), + await testUtils.getExpectedJson('9999999', 'journey', 'get-quicksend-rcb-key'), + 'returned JSON was not equal expected' + ); + assert.deepEqual( + await testUtils.getActualJson( + 'testExisting_senderProfile_rcb', + 'senderProfile' + ), + await testUtils.getExpectedJson('9999999', 'senderProfile', 'get-rcb-key'), + 'returned JSON was not equal expected' + ); + + assert.equal( + testUtils.getAPIHistoryLength(), + 46, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + return; + }); + }); + + describe('without types specified ================', () => { + it('Should replace references with ContentBlockByName w/o deploy', async () => { + handler.setOptions({ skipDeploy: true }); + + // WHEN + const replace = await handler.replaceCbReference( + 'testInstance/testBU', + undefined, + 'name' + ); + // THEN + assert.equal(process.exitCode, 0, 'retrieve should not have thrown an error'); + // retrieve result + assert.deepEqual( + replace['testInstance/testBU'].asset, + [ + 'testExisting_asset_htmlblock', + 'testExisting_htmlblock1', + 'testExisting_htmlblock 3 spaces', + 'testExisting_asset_message', + ], + 'should have found the right assets that need updating' + ); + assert.deepEqual( + replace['testInstance/testBU'].journey, + ['testExisting_journey_Quicksend'], + 'should have found the right assets that need updating' + ); + assert.deepEqual( + replace['testInstance/testBU'].script, + [ + 'testExisting_script_ampscript', + 'testExisting_script_ampincluded', + 'testExisting_script_mixed', + ], + 'should have found the right scripts that need updating' + ); + assert.deepEqual( + replace['testInstance/testBU'].senderProfile, + ['testExisting_senderProfile_rcb'], + 'should have found the right senderProfiles that need updating' + ); + + // check if conversions happened + assert.deepEqual( + await testUtils.getActualJson('testExisting_journey_Quicksend', 'journey'), + await testUtils.getExpectedJson('9999999', 'journey', 'get-quicksend-rcb-name'), + 'returned JSON was not equal expected' + ); + assert.deepEqual( + await testUtils.getActualJson( + 'testExisting_senderProfile_rcb', + 'senderProfile' + ), + await testUtils.getExpectedJson('9999999', 'senderProfile', 'get-rcb-name'), + 'returned JSON was not equal expected' + ); + + assert.equal( + testUtils.getAPIHistoryLength(), + 82, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + return; + }); + + it('Should replace references with ContentBlockById w/o deploy', async () => { + handler.setOptions({ skipDeploy: true }); + + // WHEN + const replace = await handler.replaceCbReference( + 'testInstance/testBU', + undefined, + 'id' + ); + // THEN + assert.equal(process.exitCode, 0, 'retrieve should not have thrown an error'); + // retrieve result + assert.deepEqual( + replace['testInstance/testBU'].asset, + [ + 'testExisting_htmlblock1', + 'testExisting_htmlblock 3 spaces', + 'testExisting_asset_message', + ], + 'should have found the right assets that need updating' + ); + assert.deepEqual( + replace['testInstance/testBU'].journey, + ['testExisting_journey_Quicksend'], + 'should have found the right assets that need updating' + ); + assert.deepEqual( + replace['testInstance/testBU'].script, + ['testExisting_script_ampscript', 'testExisting_script_mixed'], + 'should have found the right scripts that need updating' + ); + assert.deepEqual( + replace['testInstance/testBU'].senderProfile, + ['testExisting_senderProfile_rcb'], + 'should have found the right senderProfiles that need updating' + ); + + // check if conversions happened + assert.deepEqual( + await testUtils.getActualJson('testExisting_journey_Quicksend', 'journey'), + await testUtils.getExpectedJson('9999999', 'journey', 'get-quicksend-rcb-id'), + 'returned JSON was not equal expected' + ); + assert.deepEqual( + await testUtils.getActualJson( + 'testExisting_senderProfile_rcb', + 'senderProfile' + ), + await testUtils.getExpectedJson('9999999', 'senderProfile', 'get-rcb-id'), + 'returned JSON was not equal expected' + ); + + assert.equal( + testUtils.getAPIHistoryLength(), + 82, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + return; + }); + + it('Should replace references with ContentBlockByKey w/o deploy', async () => { + handler.setOptions({ skipDeploy: true }); + + // WHEN + const replace = await handler.replaceCbReference( + 'testInstance/testBU', + undefined, + 'key' + ); + // THEN + assert.equal(process.exitCode, 0, 'retrieve should not have thrown an error'); + // retrieve result + assert.deepEqual( + replace['testInstance/testBU'].asset, + [ + 'testExisting_asset_htmlblock', + 'testExisting_htmlblock1', + 'testExisting_asset_message', + ], + 'should have found the right assets that need updating' + ); + assert.deepEqual( + replace['testInstance/testBU'].journey, + ['testExisting_journey_Quicksend'], + 'should have found the right assets that need updating' + ); + assert.deepEqual( + replace['testInstance/testBU'].script, + ['testExisting_script_ampscript', 'testExisting_script_ampincluded'], + 'should have found the right scripts that need updating' + ); + assert.deepEqual( + replace['testInstance/testBU'].senderProfile, + ['testExisting_senderProfile_rcb'], + 'should have found the right senderProfiles that need updating' + ); + + // check if conversions happened + assert.deepEqual( + await testUtils.getActualJson('testExisting_journey_Quicksend', 'journey'), + await testUtils.getExpectedJson('9999999', 'journey', 'get-quicksend-rcb-key'), + 'returned JSON was not equal expected' + ); + assert.deepEqual( + await testUtils.getActualJson( + 'testExisting_senderProfile_rcb', + 'senderProfile' + ), + await testUtils.getExpectedJson('9999999', 'senderProfile', 'get-rcb-key'), + 'returned JSON was not equal expected' + ); + + assert.equal( + testUtils.getAPIHistoryLength(), + 82, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + return; + }); + }); + }); + + describe('with --metadata ================', () => { + describe('retrieve --metadata ~~~', () => { + it('retrieve single type without keys', async () => { + const argvMetadata = ['dataExtract']; + const typeKeyCombo = handler.metadataToTypeKey(argvMetadata); + assert.notEqual( + typeof typeKeyCombo, + 'undefined', + 'typeKeyCombo should not be undefined' + ); + const buName = 'testInstance/testBU'; + const result = await handler.retrieve(buName, typeKeyCombo); + // THEN + assert.equal(process.exitCode, 0, 'retrieve should not have thrown an error'); + + const retrievedTypes = Object.keys(result[buName]); + assert.equal(retrievedTypes.length, 1, 'retrieve should have returned 1 type'); + assert.equal( + retrievedTypes[0], + 'dataExtract', + 'retrieve should have returned 1 type' + ); + assert.equal( + testUtils.getAPIHistoryLength(), + 9, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + }); + + it('retrieve multiple type without keys', async () => { + const argvMetadata = ['dataExtension', 'senderProfile']; + const typeKeyCombo = handler.metadataToTypeKey(argvMetadata); + assert.notEqual( + typeof typeKeyCombo, + 'undefined', + 'typeKeyCombo should not be undefined' + ); + const buName = 'testInstance/testBU'; + const result = await handler.retrieve(buName, typeKeyCombo); + // THEN + assert.equal(process.exitCode, 0, 'retrieve should not have thrown an error'); + + const retrievedTypes = Object.keys(result[buName]); + assert.equal(retrievedTypes.length, 2, 'retrieve should have returned 2 types'); + assert.equal( + retrievedTypes[0], + 'dataExtension', + 'retrieve should have returned dataExtension' + ); + assert.equal( + retrievedTypes[1], + 'senderProfile', + 'retrieve should have returned senderProfile' + ); + assert.equal( + Object.keys(result[buName]['senderProfile']).length, + 3, + 'retrieve should have returned 3 senderProfile' + ); + assert.equal( + testUtils.getAPIHistoryLength(), + 10, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + }); + + it('retrieve multiple type with keys', async () => { + const argvMetadata = [ + 'dataExtension', + 'dataExtract:wrong-key', + 'senderProfile:Default', + 'query:testExisting_query', + 'query:key:testExisting_query2', + ]; + const typeKeyCombo = handler.metadataToTypeKey(argvMetadata); + assert.notEqual( + typeof typeKeyCombo, + 'undefined', + 'typeKeyCombo should not be undefined' + ); + const buName = 'testInstance/testBU'; + const result = await handler.retrieve(buName, typeKeyCombo); + // THEN + assert.equal(process.exitCode, 0, 'retrieve should not have thrown an error'); + + const retrievedTypes = Object.keys(result[buName]); + assert.equal(retrievedTypes.length, 4, 'retrieve should have returned 4 types'); + assert.equal( + retrievedTypes.includes('dataExtension'), + true, + 'retrieve should have returned dataExtension' + ); + assert.equal( + retrievedTypes.includes('dataExtract'), + true, + 'retrieve should have returned dataExtract' + ); + assert.equal( + retrievedTypes.includes('senderProfile'), + true, + 'retrieve should have returned senderProfile' + ); + assert.equal( + retrievedTypes.includes('query'), + true, + 'retrieve should have returned query' + ); + assert.equal( + Object.keys(result[buName]['dataExtension']).length, + 8, + 'retrieve should have returned 7 dataExtension' + ); + assert.equal( + Object.keys(result[buName]['dataExtract']).length, + 0, + 'retrieve should have returned 0 dataExtracts' + ); + assert.equal( + Object.keys(result[buName]['senderProfile']).length, + 1, + 'retrieve should have returned 1 senderProfile' + ); + assert.equal( + Object.keys(result[buName]['query']).length, + 2, + 'retrieve should have returned 2 query' + ); + assert.equal( + testUtils.getAPIHistoryLength(), + 18, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + }); + }); + + describe('deploy --metadata ~~~', () => { + beforeEach(() => { + testUtils.mockSetup(true); + }); + + it('deploy single type without keys', async () => { + const argvMetadata = ['dataExtract']; + const typeKeyCombo = handler.metadataToTypeKey(argvMetadata); + assert.notEqual( + typeof typeKeyCombo, + 'undefined', + 'typeKeyCombo should not be undefined' + ); + const buName = 'testInstance/testBU'; + const result = await handler.deploy(buName, typeKeyCombo); + // THEN + assert.equal(process.exitCode, 0, 'deploy should not have thrown an error'); + + const deployedTypes = Object.keys(result[buName]); + assert.equal(deployedTypes.length, 1, 'deploy should have returned 1 type'); + assert.equal(deployedTypes[0], 'dataExtract', 'deploy should have returned 1 type'); + assert.equal( + testUtils.getAPIHistoryLength(), + 13, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + }); + + it('deploy multiple type without keys', async () => { + const argvMetadata = ['dataExtension', 'senderProfile']; + const typeKeyCombo = handler.metadataToTypeKey(argvMetadata); + assert.notEqual( + typeof typeKeyCombo, + 'undefined', + 'typeKeyCombo should not be undefined' + ); + const buName = 'testInstance/testBU'; + const result = await handler.deploy(buName, typeKeyCombo); + // THEN + assert.equal(process.exitCode, 0, 'deploy should not have thrown an error'); + + const deployedTypes = Object.keys(result[buName]); + assert.equal(deployedTypes.length, 2, 'deploy should have returned 2 types'); + assert.equal( + deployedTypes[0], + 'dataExtension', + 'deploy should have returned dataExtension' + ); + assert.equal( + deployedTypes[1], + 'senderProfile', + 'deploy should have returned senderProfile' + ); + assert.equal( + Object.keys(result[buName]['dataExtension']).length, + 2, + 'deploy should have returned 2 dataExtension' + ); + assert.equal( + Object.keys(result[buName]['senderProfile']).length, + 2, + 'deploy should have returned 2 senderProfile' + ); + assert.equal( + testUtils.getAPIHistoryLength(), + 20, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + }); + + it('deploy multiple type with keys', async () => { + const argvMetadata = [ + 'dataExtension', + 'dataExtract:wrong-key', + 'senderProfile:testExisting_senderProfile', + 'query:testExisting_query', + 'query:key:wrong-key2', + ]; + const typeKeyCombo = handler.metadataToTypeKey(argvMetadata); + assert.notEqual( + typeof typeKeyCombo, + 'undefined', + 'typeKeyCombo should not be undefined' + ); + const buName = 'testInstance/testBU'; + const result = await handler.deploy(buName, typeKeyCombo); + // THEN + assert.equal(process.exitCode, 0, 'deploy should not have thrown an error'); + + const deployedTypes = Object.keys(result[buName]); + assert.equal(deployedTypes.length, 3, 'deploy should have returned 3 types'); + assert.equal( + deployedTypes.includes('dataExtension'), + true, + 'deploy should have returned dataExtension' + ); + assert.equal( + deployedTypes.includes('dataExtract'), + false, + 'deploy should have returned dataExtract' + ); + assert.equal( + deployedTypes.includes('senderProfile'), + true, + 'deploy should have returned senderProfile' + ); + assert.equal( + deployedTypes.includes('query'), + true, + 'deploy should have returned query' + ); + assert.equal( + Object.keys(result[buName]['dataExtension']).length, + 2, + 'deploy should have returned 2 dataExtension' + ); + assert.equal( + Object.keys(result[buName]['senderProfile']).length, + 1, + 'deploy should have returned 1 senderProfile' + ); + assert.equal( + Object.keys(result[buName]['query']).length, + 1, + 'deploy should have returned 1 query' + ); + assert.equal( + testUtils.getAPIHistoryLength(), + 19, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + }); + + it('deploy multiple type with keys and --noUpdate', async () => { + handler.setOptions({ noUpdate: true }); + + const argvMetadata = [ + 'dataExtension', + 'dataExtract:wrong-key', + 'senderProfile:testExisting_senderProfile', + 'query:testExisting_query', + 'query:key:wrong-key2', + ]; + const typeKeyCombo = handler.metadataToTypeKey(argvMetadata); + assert.notEqual( + typeof typeKeyCombo, + 'undefined', + 'typeKeyCombo should not be undefined' + ); + const buName = 'testInstance/testBU'; + const result = await handler.deploy(buName, typeKeyCombo); + // THEN + assert.equal(process.exitCode, 0, 'deploy should not have thrown an error'); + + const deployedTypes = Object.keys(result[buName]); + assert.equal(deployedTypes.length, 3, 'deploy should have returned 3 types'); + assert.equal( + deployedTypes.includes('dataExtension'), + true, + 'deploy should have returned dataExtension' + ); + assert.equal( + deployedTypes.includes('dataExtract'), + false, + 'deploy should have returned dataExtract' + ); + assert.equal( + deployedTypes.includes('senderProfile'), + true, + 'deploy should have returned senderProfile' + ); + assert.equal( + deployedTypes.includes('query'), + true, + 'deploy should have returned query' + ); + assert.equal( + Object.keys(result[buName]['dataExtension']).length, + 1, + 'deploy should have returned 1 dataExtension' + ); + assert.equal( + Object.keys(result[buName]['senderProfile']).length, + 0, + 'deploy should have returned 0 senderProfile' + ); + assert.equal( + Object.keys(result[buName]['query']).length, + 0, + 'deploy should have returned 0 query' + ); + assert.equal( + testUtils.getAPIHistoryLength(), + 16, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + }); + + it('skip deploy event with bad filename or bad extension', async () => { + testUtils.copyToDeploy('event-deploy', 'event'); + + const argvMetadata = [ + 'event:testNew_event_badExtension', + 'event:testNew_event_badName', + ]; + const typeKeyCombo = handler.metadataToTypeKey(argvMetadata); + const buName = 'testInstance/testBU'; + await handler.deploy(buName, typeKeyCombo); + // THEN + assert.equal(process.exitCode, 1, 'deploy should not have thrown an error'); + + assert.equal( + testUtils.getAPIHistoryLength(), + 0, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + }); + + it('skip deploy asset with bad filename or bad extension', async () => { + testUtils.copyToDeploy('asset-deploy', 'asset'); + const argvMetadata = [ + 'asset:testNew_asset_badExtension', + 'asset:testNew_asset_badName', + ]; + const typeKeyCombo = handler.metadataToTypeKey(argvMetadata); + const buName = 'testInstance/testBU'; + await handler.deploy(buName, typeKeyCombo); + + // THEN + assert.equal(process.exitCode, 1, 'deploy should have thrown an error'); + + assert.equal( + testUtils.getAPIHistoryLength(), + 0, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + }); + + it('skip deploy based on validation rule "filterPrefixByBu" with --fix without error', async () => { + testUtils.copyToDeploy('asset-deploy2', 'asset'); + testUtils.copyToDeploy('dataExtension-deploy', 'dataExtension'); + + const buName = 'testInstance/testBU'; + + handler.setOptions({ fix: true }); + + await handler.deploy(buName, { + asset: ['testBlacklist_asset_htmlblock'], + dataExtension: ['testBlacklist_dataExtension'], + }); + + // THEN + assert.equal(process.exitCode, 0, 'deploy should not have thrown an error'); + + assert.equal( + testUtils.getAPIHistoryLength(), + 8, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + }); + + it('skip deploy based on validation rule "filterPrefixByBu" without --fix but with error', async () => { + testUtils.copyToDeploy('asset-deploy2', 'asset'); + testUtils.copyToDeploy('dataExtension-deploy', 'dataExtension'); + + const buName = 'testInstance/testBU'; + + await handler.deploy(buName, { + asset: ['testBlacklist_asset_htmlblock'], + dataExtension: ['testBlacklist_dataExtension'], + }); + + // THEN + assert.equal(process.exitCode, 1, 'deploy should have thrown an error'); + + assert.equal( + testUtils.getAPIHistoryLength(), + 8, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + }); + }); + + describe('template --metadata ~~~', () => { + it('buildTemplate + buildDefinition for multiple types with keys', async () => { + // download first before we test buildTemplate + await handler.retrieve('testInstance/testBU', ['automation', 'query']); + + const expectedApiCallsRetrieve = 37; + assert.equal( + testUtils.getAPIHistoryLength(), + expectedApiCallsRetrieve, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + + // preparation + const argvMetadata = [ + 'automation:testExisting_automation', + 'query:testExisting_query', + 'query:bad', + ]; + const typeKeyCombo = handler.metadataToTypeKey(argvMetadata); + assert.notEqual( + typeof typeKeyCombo, + 'undefined', + 'typeKeyCombo should not be undefined' + ); + const buName = 'testInstance/testBU'; + + // *** buildTemplate *** + const templateResult = await handler.buildTemplate( + buName, + typeKeyCombo, + undefined, + ['testSourceMarket'] + ); + assert.equal(process.exitCode, 0, 'buildTemplate should not have thrown an error'); + // check automation + assert.equal( + templateResult.automation ? Object.keys(templateResult.automation).length : 0, + 1, + 'only one automation expected' + ); + assert.deepEqual( + await testUtils.getActualTemplateJson('testExisting_automation', 'automation'), + await testUtils.getExpectedJson('9999999', 'automation', 'template'), + 'returned template was not equal expected' + ); + // check query + assert.equal( + templateResult.query ? Object.keys(templateResult.query).length : 0, + 1, + 'only one query expected' + ); + assert.deepEqual( + await testUtils.getActualTemplateJson('testExisting_query', 'query'), + await testUtils.getExpectedJson('9999999', 'query', 'template'), + 'returned template JSON of retrieveAsTemplate was not equal expected' + ); + expect( + await testUtils.getActualTemplateFile('testExisting_query', 'query', 'sql') + ).to.equal(await testUtils.getExpectedFile('9999999', 'query', 'template', 'sql')); + + // *** buildDefinition *** + const definitionResult = await handler.buildDefinition( + buName, + typeKeyCombo, + undefined, + ['testTargetMarket'] + ); + assert.equal( + process.exitCode, + 0, + 'buildDefinition should not have thrown an error' + ); + + // check automation + assert.equal( + definitionResult.automation + ? Object.keys(definitionResult.automation).length + : 0, + 1, + 'only one automation expected' + ); + assert.deepEqual( + await testUtils.getActualDeployJson('testTemplated_automation', 'automation'), + await testUtils.getExpectedJson('9999999', 'automation', 'build'), + 'returned deployment file was not equal expected' + ); + + // check query + assert.equal( + definitionResult.query ? Object.keys(definitionResult.query).length : 0, + 1, + 'only one query expected' + ); + assert.deepEqual( + await testUtils.getActualDeployJson('testTemplated_query', 'query'), + await testUtils.getExpectedJson('9999999', 'query', 'build'), + 'returned deployment JSON was not equal expected' + ); + expect( + await testUtils.getActualDeployFile('testTemplated_query', 'query', 'sql') + ).to.equal(await testUtils.getExpectedFile('9999999', 'query', 'build', 'sql')); + + assert.equal( + testUtils.getAPIHistoryLength() - expectedApiCallsRetrieve, + 0, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + }); + + it('buildTemplate + buildDefinition for multiple types with keys and --retrieve', async () => { + const expectedApiCallsRetrieve = 34; + + // preparation + const argvMetadata = [ + 'automation:testExisting_automation', + 'query:testExisting_query', + 'query:bad', + ]; + const typeKeyCombo = handler.metadataToTypeKey(argvMetadata); + assert.notEqual( + typeof typeKeyCombo, + 'undefined', + 'typeKeyCombo should not be undefined' + ); + const buName = 'testInstance/testBU'; + + handler.setOptions({ retrieve: true }); + + // *** buildTemplate *** + const templateResult = await handler.buildTemplate( + buName, + typeKeyCombo, + undefined, + ['testSourceMarket'] + ); + assert.equal(process.exitCode, 0, 'buildTemplate should not have thrown an error'); + // check automation + assert.equal( + templateResult.automation ? Object.keys(templateResult.automation).length : 0, + 1, + 'only one automation expected' + ); + assert.deepEqual( + await testUtils.getActualTemplateJson('testExisting_automation', 'automation'), + await testUtils.getExpectedJson('9999999', 'automation', 'template'), + 'returned template was not equal expected' + ); + // check query + assert.equal( + templateResult.query ? Object.keys(templateResult.query).length : 0, + 1, + 'only one query expected' + ); + assert.deepEqual( + await testUtils.getActualTemplateJson('testExisting_query', 'query'), + await testUtils.getExpectedJson('9999999', 'query', 'template'), + 'returned template JSON of retrieveAsTemplate was not equal expected' + ); + expect( + await testUtils.getActualTemplateFile('testExisting_query', 'query', 'sql') + ).to.equal(await testUtils.getExpectedFile('9999999', 'query', 'template', 'sql')); + + // *** buildDefinition *** + const definitionResult = await handler.buildDefinition( + buName, + typeKeyCombo, + undefined, + ['testTargetMarket'] + ); + assert.equal( + process.exitCode, + 0, + 'buildDefinition should not have thrown an error' + ); + + // check automation + assert.equal( + definitionResult.automation + ? Object.keys(definitionResult.automation).length + : 0, + 1, + 'only one automation expected' + ); + assert.deepEqual( + await testUtils.getActualDeployJson('testTemplated_automation', 'automation'), + await testUtils.getExpectedJson('9999999', 'automation', 'build'), + 'returned deployment file was not equal expected' + ); + + // check query + assert.equal( + definitionResult.query ? Object.keys(definitionResult.query).length : 0, + 1, + 'only one query expected' + ); + assert.deepEqual( + await testUtils.getActualDeployJson('testTemplated_query', 'query'), + await testUtils.getExpectedJson('9999999', 'query', 'build'), + 'returned deployment JSON was not equal expected' + ); + expect( + await testUtils.getActualDeployFile('testTemplated_query', 'query', 'sql') + ).to.equal(await testUtils.getExpectedFile('9999999', 'query', 'build', 'sql')); + + assert.equal( + testUtils.getAPIHistoryLength(), + expectedApiCallsRetrieve, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + }); + + it('buildTemplate + buildDefinition for multiple types with keys and --dependencies', async () => { + // download first before we test buildTemplate + await handler.retrieve('testInstance/testBU'); + + const expectedApiCallsRetrieve = 109; + assert.equal( + testUtils.getAPIHistoryLength(), + expectedApiCallsRetrieve, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + + // preparation + const argvMetadata = [ + 'automation:testExisting_automation', + 'query:testExisting_query', + 'query:bad', + ]; + const typeKeyCombo = handler.metadataToTypeKey(argvMetadata); + assert.notEqual( + typeof typeKeyCombo, + 'undefined', + 'typeKeyCombo should not be undefined' + ); + const buName = 'testInstance/testBU'; + + // set skipInteraction to true to skip re-retrieving question + handler.setOptions({ dependencies: true, skipInteraction: true }); + + // *** buildTemplate *** + const templateResult = await handler.buildTemplate( + buName, + typeKeyCombo, + undefined, + ['testSourceMarket'] + ); + assert.equal(process.exitCode, 0, 'buildTemplate should not have thrown an error'); + + // check type list + assert.deepEqual( + Object.keys(templateResult), + [ + 'automation', + 'dataExtension', + 'dataExtract', + 'domainVerification', + 'emailSend', + 'fileTransfer', + 'importFile', + 'query', + 'script', + 'sendClassification', + 'senderProfile', + 'verification', + ], + 'did not create deployment packages for all relevant types' + ); + + // check automation + assert.equal( + templateResult.automation ? Object.keys(templateResult.automation).length : 0, + 1, + 'only one automation expected' + ); + assert.deepEqual( + await testUtils.getActualTemplateJson('testExisting_automation', 'automation'), + await testUtils.getExpectedJson('9999999', 'automation', 'template'), + 'returned template was not equal expected' + ); + // check query + assert.equal( + templateResult.query ? Object.keys(templateResult.query).length : 0, + 1, + 'only one query expected' + ); + assert.deepEqual( + await testUtils.getActualTemplateJson('testExisting_query', 'query'), + await testUtils.getExpectedJson('9999999', 'query', 'template'), + 'returned template JSON of retrieveAsTemplate was not equal expected' + ); + expect( + await testUtils.getActualTemplateFile('testExisting_query', 'query', 'sql') + ).to.equal(await testUtils.getExpectedFile('9999999', 'query', 'template', 'sql')); + + // *** buildDefinition *** + const definitionResult = await handler.buildDefinition( + buName, + typeKeyCombo, + undefined, + ['testTargetMarket'] + ); + assert.equal( + process.exitCode, + 0, + 'buildDefinition should not have thrown an error' + ); + + // check automation + assert.equal( + definitionResult.automation + ? Object.keys(definitionResult.automation).length + : 0, + 1, + 'only one automation expected' + ); + assert.deepEqual( + await testUtils.getActualDeployJson('testTemplated_automation', 'automation'), + await testUtils.getExpectedJson('9999999', 'automation', 'build'), + 'returned deployment file was not equal expected' + ); + + // check query + assert.equal( + definitionResult.query ? Object.keys(definitionResult.query).length : 0, + 1, + 'only one query expected' + ); + assert.deepEqual( + await testUtils.getActualDeployJson('testTemplated_query', 'query'), + await testUtils.getExpectedJson('9999999', 'query', 'build'), + 'returned deployment JSON was not equal expected' + ); + expect( + await testUtils.getActualDeployFile('testTemplated_query', 'query', 'sql') + ).to.equal(await testUtils.getExpectedFile('9999999', 'query', 'build', 'sql')); + + assert.equal( + testUtils.getAPIHistoryLength() - expectedApiCallsRetrieve, + 4, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + }); + + it('buildTemplate + buildDefinition for multiple types with keys and --dependencies and --retrieve', async () => { + // preparation + const argvMetadata = [ + 'automation:testExisting_automation', + 'query:testExisting_query', + 'query:bad', + ]; + const typeKeyCombo = handler.metadataToTypeKey(argvMetadata); + assert.notEqual( + typeof typeKeyCombo, + 'undefined', + 'typeKeyCombo should not be undefined' + ); + const buName = 'testInstance/testBU'; + + handler.setOptions({ dependencies: true, retrieve: true }); + + // *** buildTemplate *** + const templateResult = await handler.buildTemplate( + buName, + typeKeyCombo, + undefined, + ['testSourceMarket'] + ); + assert.equal(process.exitCode, 0, 'buildTemplate should not have thrown an error'); + + // check type list + assert.deepEqual( + Object.keys(templateResult), + [ + 'automation', + 'dataExtension', + 'dataExtract', + 'domainVerification', + 'emailSend', + 'fileTransfer', + 'importFile', + 'query', + 'script', + 'sendClassification', + 'senderProfile', + 'verification', + ], + 'did not create deployment packages for all relevant types' + ); + + // check automation + assert.equal( + templateResult.automation ? Object.keys(templateResult.automation).length : 0, + 1, + 'only one automation expected' + ); + assert.deepEqual( + await testUtils.getActualTemplateJson('testExisting_automation', 'automation'), + await testUtils.getExpectedJson('9999999', 'automation', 'template'), + 'returned template was not equal expected' + ); + // check query + assert.equal( + templateResult.query ? Object.keys(templateResult.query).length : 0, + 1, + 'only one query expected' + ); + assert.deepEqual( + await testUtils.getActualTemplateJson('testExisting_query', 'query'), + await testUtils.getExpectedJson('9999999', 'query', 'template'), + 'returned template JSON of retrieveAsTemplate was not equal expected' + ); + expect( + await testUtils.getActualTemplateFile('testExisting_query', 'query', 'sql') + ).to.equal(await testUtils.getExpectedFile('9999999', 'query', 'template', 'sql')); + + // *** buildDefinition *** + const definitionResult = await handler.buildDefinition( + buName, + typeKeyCombo, + undefined, + ['testTargetMarket'] + ); + assert.equal( + process.exitCode, + 0, + 'buildDefinition should not have thrown an error' + ); + + // check automation + assert.equal( + definitionResult.automation + ? Object.keys(definitionResult.automation).length + : 0, + 1, + 'only one automation expected' + ); + assert.deepEqual( + await testUtils.getActualDeployJson('testTemplated_automation', 'automation'), + await testUtils.getExpectedJson('9999999', 'automation', 'build'), + 'returned deployment file was not equal expected' + ); + + // check query + assert.equal( + definitionResult.query ? Object.keys(definitionResult.query).length : 0, + 1, + 'only one query expected' + ); + assert.deepEqual( + await testUtils.getActualDeployJson('testTemplated_query', 'query'), + await testUtils.getExpectedJson('9999999', 'query', 'build'), + 'returned deployment JSON was not equal expected' + ); + expect( + await testUtils.getActualDeployFile('testTemplated_query', 'query', 'sql') + ).to.equal(await testUtils.getExpectedFile('9999999', 'query', 'build', 'sql')); + + const expectedApiCallsRetrieve = 113; + assert.equal( + testUtils.getAPIHistoryLength(), + expectedApiCallsRetrieve, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + }); + + it('buildTemplate + buildDefinitionBulk multiple type with keys', async () => { + // download first before we test buildTemplate + await handler.retrieve('testInstance/testBU', ['automation', 'query']); + + const expectedApiCallsRetrieve = 37; + assert.equal( + testUtils.getAPIHistoryLength(), + expectedApiCallsRetrieve, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + + // preparation + const argvMetadata = [ + 'automation:testExisting_automation', + 'query:testExisting_query', + 'query:bad', + ]; + const typeKeyCombo = handler.metadataToTypeKey(argvMetadata); + assert.notEqual( + typeof typeKeyCombo, + 'undefined', + 'typeKeyCombo should not be undefined' + ); + const buName = 'testInstance/testBU'; + + // *** buildTemplate *** + const templateResult = await handler.buildTemplate( + buName, + typeKeyCombo, + undefined, + ['testSourceMarket'] + ); + assert.equal(process.exitCode, 0, 'buildTemplate should not have thrown an error'); + // check automation + assert.equal( + templateResult.automation ? Object.keys(templateResult.automation).length : 0, + 1, + 'only one automation expected' + ); + assert.deepEqual( + await testUtils.getActualTemplateJson('testExisting_automation', 'automation'), + await testUtils.getExpectedJson('9999999', 'automation', 'template'), + 'returned template was not equal expected' + ); + // check query + assert.equal( + templateResult.query ? Object.keys(templateResult.query).length : 0, + 1, + 'only one query expected' + ); + assert.deepEqual( + await testUtils.getActualTemplateJson('testExisting_query', 'query'), + await testUtils.getExpectedJson('9999999', 'query', 'template'), + 'returned template JSON of retrieveAsTemplate was not equal expected' + ); + expect( + await testUtils.getActualTemplateFile('testExisting_query', 'query', 'sql') + ).to.equal(await testUtils.getExpectedFile('9999999', 'query', 'template', 'sql')); + + // *** buildDefinitionBulk chained *** + const definitionResult = await handler.buildDefinitionBulk( + 'deployment-target', + typeKeyCombo + ); + assert.equal( + process.exitCode, + 0, + 'buildDefinitionBulk should not have thrown an error' + ); + + // check automation + assert.equal( + definitionResult.automation?.['testInstance/testBU']?.testSourceMarket + ? Object.keys( + definitionResult.automation?.['testInstance/testBU']?.testSourceMarket + ).length + : 0, + 1, + 'only one automation expected' + ); + assert.equal( + definitionResult.automation?.['testInstance/testBU']?.testTargetMarket + ? Object.keys( + definitionResult.automation?.['testInstance/testBU']?.testTargetMarket + ).length + : 0, + 1, + 'only one automation expected' + ); + assert.equal( + definitionResult.automation?.['testInstance/_ParentBU_']?.testTargetMarket + ? Object.keys( + definitionResult.automation?.['testInstance/_ParentBU_'] + ?.testTargetMarket + ).length + : 0, + 1, + 'only one automation expected' + ); + assert.deepEqual( + await testUtils.getActualDeployJson('testTemplated_automation', 'automation'), + await testUtils.getExpectedJson('9999999', 'automation', 'build'), + 'returned deployment file was not equal expected' + ); + + // check if files were also created for other BU-market combos + // testBU: testSourceMarket + expect( + await testUtils.getActualDeployFile( + 'testExisting_automation', + 'automation', + 'json' + ) + ).to.exist; + // _ParentBU_: testTargetMarket + expect( + await testUtils.getActualDeployFile( + 'testTemplated_automation', + 'automation', + 'json', + '_ParentBU_' + ) + ).to.exist; + + // check query + assert.equal( + definitionResult.query?.['testInstance/testBU']?.testSourceMarket + ? Object.keys( + definitionResult.query?.['testInstance/testBU']?.testSourceMarket + ).length + : 0, + 1, + 'only one query expected' + ); + assert.equal( + definitionResult.query?.['testInstance/testBU']?.testTargetMarket + ? Object.keys( + definitionResult.query?.['testInstance/testBU']?.testTargetMarket + ).length + : 0, + 1, + 'only one query expected' + ); + assert.equal( + definitionResult.query?.['testInstance/_ParentBU_']?.testTargetMarket + ? Object.keys( + definitionResult.query?.['testInstance/_ParentBU_']?.testTargetMarket + ).length + : 0, + 1, + 'only one query expected' + ); + assert.deepEqual( + await testUtils.getActualDeployJson('testTemplated_query', 'query'), + await testUtils.getExpectedJson('9999999', 'query', 'build'), + 'returned deployment JSON was not equal expected' + ); + expect( + await testUtils.getActualDeployFile('testTemplated_query', 'query', 'sql') + ).to.equal(await testUtils.getExpectedFile('9999999', 'query', 'build', 'sql')); + + // check if files were also created for other BU-market combos + // testBU: testSourceMarket + expect(await testUtils.getActualDeployFile('testExisting_query', 'query', 'json')) + .to.exist; + expect(await testUtils.getActualDeployFile('testExisting_query', 'query', 'sql')).to + .exist; + // _ParentBU_: testTargetMarket + expect( + await testUtils.getActualDeployFile( + 'testTemplated_query', + 'query', + 'json', + '_ParentBU_' + ) + ).to.exist; + expect( + await testUtils.getActualDeployFile( + 'testTemplated_query', + 'query', + 'sql', + '_ParentBU_' + ) + ).to.exist; + + assert.equal( + testUtils.getAPIHistoryLength() - expectedApiCallsRetrieve, + 0, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + }); + + it('clone multiple type with keys', async () => { + // download first before we test buildTemplate + await handler.retrieve('testInstance/testBU', ['automation', 'query']); + + const expectedApiCallsRetrieve = 37; + assert.equal( + testUtils.getAPIHistoryLength(), + expectedApiCallsRetrieve, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + + // preparation + const argvMetadata = [ + 'automation:testExisting_automation', + 'query:testExisting_query', + 'query:bad', + ]; + const typeKeyCombo = handler.metadataToTypeKey(argvMetadata); + assert.notEqual( + typeof typeKeyCombo, + 'undefined', + 'typeKeyCombo should not be undefined' + ); + const buName = 'testInstance/testBU'; + + handler.setOptions({ skipInteraction: true, purge: false }); + // *** build: buildTemplate and buildDefinition chained *** + const definitionResult = await handler.clone(buName, buName, typeKeyCombo); + assert.equal(process.exitCode, 0, 'build should not have thrown an error'); + + // *** buildTemplate *** + // cannot be checked in build anymore because it writes templates into a temporary folder and deletes them afterwards + + // *** buildDefinition *** + + // check automation + assert.equal( + definitionResult.automation + ? Object.keys(definitionResult.automation).length + : 0, + 1, + 'only one automation expected' + ); + assert.deepEqual( + await testUtils.getActualDeployJson('testExisting_automation', 'automation'), + await testUtils.getExpectedJson('9999999', 'automation', 'clone'), + 'returned deployment file was not equal expected' + ); + + // check query + assert.equal( + definitionResult.query ? Object.keys(definitionResult.query).length : 0, + 1, + 'only one query expected' + ); + assert.deepEqual( + await testUtils.getActualDeployJson('testExisting_query', 'query'), + await testUtils.getExpectedJson('9999999', 'query', 'clone'), + 'returned deployment JSON was not equal expected' + ); + expect( + await testUtils.getActualDeployFile('testExisting_query', 'query', 'sql') + ).to.equal(await testUtils.getExpectedFile('9999999', 'query', 'clone', 'sql')); + + assert.equal( + testUtils.getAPIHistoryLength() - expectedApiCallsRetrieve, + 0, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + }); + + it('build multiple type with keys', async () => { + // download first before we test buildTemplate + await handler.retrieve('testInstance/testBU', ['automation', 'query']); + + const expectedApiCallsRetrieve = 37; + assert.equal( + testUtils.getAPIHistoryLength(), + expectedApiCallsRetrieve, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + + // preparation + const argvMetadata = [ + 'automation:testExisting_automation', + 'query:testExisting_query', + 'query:bad', + ]; + const typeKeyCombo = handler.metadataToTypeKey(argvMetadata); + assert.notEqual( + typeof typeKeyCombo, + 'undefined', + 'typeKeyCombo should not be undefined' + ); + const buName = 'testInstance/testBU'; + + handler.setOptions({ skipInteraction: true, purge: false }); + // *** build: buildTemplate and buildDefinition chained *** + const definitionResult = await handler.build( + buName, + buName, + typeKeyCombo, + ['testSourceMarket'], + ['testTargetMarket'] + ); + assert.equal(process.exitCode, 0, 'build should not have thrown an error'); + + // *** buildTemplate *** + + // check automation + // assert.deepEqual( + // await testUtils.getActualTemporaryTemplateJson( + // 'testExisting_automation', + // 'automation' + // ), + // await testUtils.getExpectedJson('9999999', 'automation', 'template'), + // 'returned template was not equal expected' + // ); + // // check query + // assert.deepEqual( + // await testUtils.getActualTemporaryTemplateJson('testExisting_query', 'query'), + // await testUtils.getExpectedJson('9999999', 'query', 'template'), + // 'returned template JSON of retrieveAsTemplate was not equal expected' + // ); + // expect( + // await testUtils.getActualTemporaryTemplateFile( + // 'testExisting_query', + // 'query', + // 'sql' + // ) + // ).to.equal(await testUtils.getExpectedFile('9999999', 'query', 'template', 'sql')); + + // *** buildDefinition *** + + // check automation + assert.equal( + definitionResult.automation + ? Object.keys(definitionResult.automation).length + : 0, + 1, + 'only one automation expected' + ); + assert.deepEqual( + await testUtils.getActualDeployJson('testTemplated_automation', 'automation'), + await testUtils.getExpectedJson('9999999', 'automation', 'build'), + 'returned deployment file was not equal expected' + ); + + // check query + assert.equal( + definitionResult.query ? Object.keys(definitionResult.query).length : 0, + 1, + 'only one query expected' + ); + assert.deepEqual( + await testUtils.getActualDeployJson('testTemplated_query', 'query'), + await testUtils.getExpectedJson('9999999', 'query', 'build'), + 'returned deployment JSON was not equal expected' + ); + expect( + await testUtils.getActualDeployFile('testTemplated_query', 'query', 'sql') + ).to.equal(await testUtils.getExpectedFile('9999999', 'query', 'build', 'sql')); + + assert.equal( + testUtils.getAPIHistoryLength() - expectedApiCallsRetrieve, + 0, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + }); + + it('build multiple type with keys and --dependencies', async () => { + // download everything before we test buildTemplate + await handler.retrieve('testInstance/testBU'); + + const expectedApiCallsRetrieve = 109; + assert.equal( + testUtils.getAPIHistoryLength(), + expectedApiCallsRetrieve, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + + // preparation + const argvMetadata = [ + 'automation:testExisting_automation', + 'query:testExisting_query', + 'query:bad', + ]; + const typeKeyCombo = handler.metadataToTypeKey(argvMetadata); + assert.notEqual( + typeof typeKeyCombo, + 'undefined', + 'typeKeyCombo should not be undefined' + ); + const buName = 'testInstance/testBU'; + + // set skipInteraction to true to skip re-retrieving question + handler.setOptions({ dependencies: true, skipInteraction: true, purge: true }); + + // *** build: buildTemplate and buildDefinition chained *** + const definitionResult = await handler.build( + buName, + buName, + typeKeyCombo, + ['testSourceMarket'], + ['testTargetMarket'] + ); + assert.equal(process.exitCode, 0, 'build should not have thrown an error'); + + // *** buildTemplate *** + + // // check automation + // assert.deepEqual( + // await testUtils.getActualTemplateJson('testExisting_automation', 'automation'), + // await testUtils.getExpectedJson('9999999', 'automation', 'template'), + // 'returned template was not equal expected' + // ); + // // check query + // assert.deepEqual( + // await testUtils.getActualTemplateJson('testExisting_query', 'query'), + // await testUtils.getExpectedJson('9999999', 'query', 'template'), + // 'returned template JSON of retrieveAsTemplate was not equal expected' + // ); + // expect( + // await testUtils.getActualTemplateFile('testExisting_query', 'query', 'sql') + // ).to.equal(await testUtils.getExpectedFile('9999999', 'query', 'template', 'sql')); + + // *** buildDefinition *** + + // check type list + assert.deepEqual( + Object.keys(definitionResult), + [ + 'automation', + 'dataExtension', + 'dataExtract', + 'domainVerification', + 'emailSend', + 'fileTransfer', + 'importFile', + 'query', + 'script', + 'sendClassification', + 'senderProfile', + 'verification', + ], + 'did not create deployment packages for all relevant types' + ); + + // check automation + assert.equal( + definitionResult.automation + ? Object.keys(definitionResult.automation).length + : 0, + 1, + 'only one automation expected' + ); + assert.deepEqual( + await testUtils.getActualDeployJson('testTemplated_automation', 'automation'), + await testUtils.getExpectedJson('9999999', 'automation', 'build'), + 'returned deployment file was not equal expected' + ); + + // check query + assert.equal( + definitionResult.query ? Object.keys(definitionResult.query).length : 0, + 1, + 'only one query expected' + ); + assert.deepEqual( + await testUtils.getActualDeployJson('testTemplated_query', 'query'), + await testUtils.getExpectedJson('9999999', 'query', 'build'), + 'returned deployment JSON was not equal expected' + ); + expect( + await testUtils.getActualDeployFile('testTemplated_query', 'query', 'sql') + ).to.equal(await testUtils.getExpectedFile('9999999', 'query', 'build', 'sql')); + + assert.equal( + testUtils.getAPIHistoryLength() - expectedApiCallsRetrieve, + 4, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + }); + + it('build multiple type with keys and --dependencies and --retrieve', async () => { + // preparation + const argvMetadata = [ + 'automation:testExisting_automation', + 'query:testExisting_query', + 'query:bad', + ]; + const typeKeyCombo = handler.metadataToTypeKey(argvMetadata); + assert.notEqual( + typeof typeKeyCombo, + 'undefined', + 'typeKeyCombo should not be undefined' + ); + const buName = 'testInstance/testBU'; + + handler.setOptions({ + dependencies: true, + retrieve: true, + skipInteraction: true, + purge: true, + }); + + // *** build: buildTemplate and buildDefinition chained *** + const definitionResult = await handler.build( + buName, + buName, + typeKeyCombo, + ['testSourceMarket'], + ['testTargetMarket'] + ); + assert.equal(process.exitCode, 0, 'build should not have thrown an error'); + + // *** buildTemplate *** + + // check automation + // assert.deepEqual( + // await testUtils.getActualTemplateJson('testExisting_automation', 'automation'), + // await testUtils.getExpectedJson('9999999', 'automation', 'template'), + // 'returned template was not equal expected' + // ); + // // check query + // assert.deepEqual( + // await testUtils.getActualTemplateJson('testExisting_query', 'query'), + // await testUtils.getExpectedJson('9999999', 'query', 'template'), + // 'returned template JSON of retrieveAsTemplate was not equal expected' + // ); + // expect( + // await testUtils.getActualTemplateFile('testExisting_query', 'query', 'sql') + // ).to.equal(await testUtils.getExpectedFile('9999999', 'query', 'template', 'sql')); + + // *** buildDefinition *** + + // check type list + assert.deepEqual( + Object.keys(definitionResult), + [ + 'automation', + 'dataExtension', + 'dataExtract', + 'domainVerification', + 'emailSend', + 'fileTransfer', + 'importFile', + 'query', + 'script', + 'sendClassification', + 'senderProfile', + 'verification', + ], + 'did not create deployment packages for all relevant types' + ); + + // check automation + assert.equal( + definitionResult.automation + ? Object.keys(definitionResult.automation).length + : 0, + 1, + 'only one automation expected' + ); + assert.deepEqual( + await testUtils.getActualDeployJson('testTemplated_automation', 'automation'), + await testUtils.getExpectedJson('9999999', 'automation', 'build'), + 'returned deployment file was not equal expected' + ); + + // check query + assert.equal( + definitionResult.query ? Object.keys(definitionResult.query).length : 0, + 1, + 'only one query expected' + ); + assert.deepEqual( + await testUtils.getActualDeployJson('testTemplated_query', 'query'), + await testUtils.getExpectedJson('9999999', 'query', 'build'), + 'returned deployment JSON was not equal expected' + ); + expect( + await testUtils.getActualDeployFile('testTemplated_query', 'query', 'sql') + ).to.equal(await testUtils.getExpectedFile('9999999', 'query', 'build', 'sql')); + + const expectedApiCallsRetrieve = 113; + assert.equal( + testUtils.getAPIHistoryLength(), + expectedApiCallsRetrieve, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + }); + + it('build multiple type with keys and --bulk', async () => { + // download first before we test buildTemplate + await handler.retrieve('testInstance/testBU', ['automation', 'query']); + + const expectedApiCallsRetrieve = 37; + assert.equal( + testUtils.getAPIHistoryLength(), + expectedApiCallsRetrieve, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + + // preparation + const argvMetadata = [ + 'automation:testExisting_automation', + 'query:testExisting_query', + 'query:bad', + ]; + const typeKeyCombo = handler.metadataToTypeKey(argvMetadata); + assert.notEqual( + typeof typeKeyCombo, + 'undefined', + 'typeKeyCombo should not be undefined' + ); + const buName = 'testInstance/testBU'; + handler.setOptions({ skipInteraction: true, purge: false }); + + // *** build: buildTemplate and buildDefinition chained *** + const definitionResult = await handler.build( + buName, + 'ignored', + typeKeyCombo, + ['testSourceMarket'], + ['deployment-target'], + true + ); + assert.equal(process.exitCode, 0, 'build should not have thrown an error'); + + // *** buildTemplate *** + + // // check automation + // assert.deepEqual( + // await testUtils.getActualTemplateJson('testExisting_automation', 'automation'), + // await testUtils.getExpectedJson('9999999', 'automation', 'template'), + // 'returned template was not equal expected' + // ); + // // check query + // assert.deepEqual( + // await testUtils.getActualTemplateJson('testExisting_query', 'query'), + // await testUtils.getExpectedJson('9999999', 'query', 'template'), + // 'returned template JSON of retrieveAsTemplate was not equal expected' + // ); + // expect( + // await testUtils.getActualTemplateFile('testExisting_query', 'query', 'sql') + // ).to.equal(await testUtils.getExpectedFile('9999999', 'query', 'template', 'sql')); + + // *** buildDefinitionBulk *** + + // check automation + assert.equal( + definitionResult.automation?.['testInstance/testBU']?.testSourceMarket + ? Object.keys( + definitionResult.automation?.['testInstance/testBU']?.testSourceMarket + ).length + : 0, + 1, + 'only one automation expected' + ); + assert.equal( + definitionResult.automation?.['testInstance/testBU']?.testTargetMarket + ? Object.keys( + definitionResult.automation?.['testInstance/testBU']?.testTargetMarket + ).length + : 0, + 1, + 'only one automation expected' + ); + assert.equal( + definitionResult.automation?.['testInstance/_ParentBU_']?.testTargetMarket + ? Object.keys( + definitionResult.automation?.['testInstance/_ParentBU_'] + ?.testTargetMarket + ).length + : 0, + 1, + 'only one automation expected' + ); + assert.deepEqual( + await testUtils.getActualDeployJson('testTemplated_automation', 'automation'), + await testUtils.getExpectedJson('9999999', 'automation', 'build'), + 'returned deployment file was not equal expected' + ); + + // check if files were also created for other BU-market combos + // testBU: testSourceMarket + expect( + await testUtils.getActualDeployFile( + 'testExisting_automation', + 'automation', + 'json' + ) + ).to.exist; + // _ParentBU_: testTargetMarket + expect( + await testUtils.getActualDeployFile( + 'testTemplated_automation', + 'automation', + 'json', + '_ParentBU_' + ) + ).to.exist; + + // check query + assert.equal( + definitionResult.query?.['testInstance/testBU']?.testSourceMarket + ? Object.keys( + definitionResult.query?.['testInstance/testBU']?.testSourceMarket + ).length + : 0, + 1, + 'only one query expected' + ); + assert.equal( + definitionResult.query?.['testInstance/testBU']?.testTargetMarket + ? Object.keys( + definitionResult.query?.['testInstance/testBU']?.testTargetMarket + ).length + : 0, + 1, + 'only one query expected' + ); + assert.equal( + definitionResult.query?.['testInstance/_ParentBU_']?.testTargetMarket + ? Object.keys( + definitionResult.query?.['testInstance/_ParentBU_']?.testTargetMarket + ).length + : 0, + 1, + 'only one query expected' + ); + assert.deepEqual( + await testUtils.getActualDeployJson('testTemplated_query', 'query'), + await testUtils.getExpectedJson('9999999', 'query', 'build'), + 'returned deployment JSON was not equal expected' + ); + expect( + await testUtils.getActualDeployFile('testTemplated_query', 'query', 'sql') + ).to.equal(await testUtils.getExpectedFile('9999999', 'query', 'build', 'sql')); + + // check if files were also created for other BU-market combos + // testBU: testSourceMarket + expect(await testUtils.getActualDeployFile('testExisting_query', 'query', 'json')) + .to.exist; + expect(await testUtils.getActualDeployFile('testExisting_query', 'query', 'sql')).to + .exist; + // _ParentBU_: testTargetMarket + expect( + await testUtils.getActualDeployFile( + 'testTemplated_query', + 'query', + 'json', + '_ParentBU_' + ) + ).to.exist; + expect( + await testUtils.getActualDeployFile( + 'testTemplated_query', + 'query', + 'sql', + '_ParentBU_' + ) + ).to.exist; + + assert.equal( + testUtils.getAPIHistoryLength() - expectedApiCallsRetrieve, + 0, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + }); + + it('build multiple type with keys and --bulk and --dependencies', async () => { + // download first before we test buildTemplate + await handler.retrieve('testInstance/testBU'); + + const expectedApiCallsRetrieve = 109; + assert.equal( + testUtils.getAPIHistoryLength(), + expectedApiCallsRetrieve, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + + // preparation + const argvMetadata = [ + 'automation:testExisting_automation', + 'query:testExisting_query', + 'query:bad', + ]; + const typeKeyCombo = handler.metadataToTypeKey(argvMetadata); + assert.notEqual( + typeof typeKeyCombo, + 'undefined', + 'typeKeyCombo should not be undefined' + ); + const buName = 'testInstance/testBU'; + + // set skipInteraction to true to skip re-retrieving question + handler.setOptions({ dependencies: true, skipInteraction: true, purge: true }); + + // *** build: buildTemplate and buildDefinition chained *** + const definitionResult = await handler.build( + buName, + 'ignored', + typeKeyCombo, + ['testSourceMarket'], + ['deployment-target'], + true + ); + assert.equal(process.exitCode, 0, 'build should not have thrown an error'); + + // *** buildTemplate *** + + // // check automation + // assert.deepEqual( + // await testUtils.getActualTemplateJson('testExisting_automation', 'automation'), + // await testUtils.getExpectedJson('9999999', 'automation', 'template'), + // 'returned template was not equal expected' + // ); + // // check query + // assert.deepEqual( + // await testUtils.getActualTemplateJson('testExisting_query', 'query'), + // await testUtils.getExpectedJson('9999999', 'query', 'template'), + // 'returned template JSON of retrieveAsTemplate was not equal expected' + // ); + // expect( + // await testUtils.getActualTemplateFile('testExisting_query', 'query', 'sql') + // ).to.equal(await testUtils.getExpectedFile('9999999', 'query', 'template', 'sql')); + + // *** buildDefinitionBulk *** + + // check type list + assert.deepEqual( + Object.keys(definitionResult), + [ + 'automation', + 'dataExtension', + 'dataExtract', + 'domainVerification', + 'emailSend', + 'fileTransfer', + 'importFile', + 'query', + 'script', + 'sendClassification', + 'senderProfile', + 'verification', + ], + 'did not create deployment packages for all relevant types' + ); + + // check automation + assert.equal( + definitionResult.automation?.['testInstance/testBU']?.testSourceMarket + ? Object.keys( + definitionResult.automation?.['testInstance/testBU']?.testSourceMarket + ).length + : 0, + 1, + 'only one automation expected' + ); + assert.equal( + definitionResult.automation?.['testInstance/testBU']?.testTargetMarket + ? Object.keys( + definitionResult.automation?.['testInstance/testBU']?.testTargetMarket + ).length + : 0, + 1, + 'only one automation expected' + ); + assert.equal( + definitionResult.automation?.['testInstance/_ParentBU_']?.testTargetMarket + ? Object.keys( + definitionResult.automation?.['testInstance/_ParentBU_'] + ?.testTargetMarket + ).length + : 0, + 1, + 'only one automation expected' + ); + assert.deepEqual( + await testUtils.getActualDeployJson('testTemplated_automation', 'automation'), + await testUtils.getExpectedJson('9999999', 'automation', 'build'), + 'returned deployment file was not equal expected' + ); + + // check if files were also created for other BU-market combos + // testBU: testSourceMarket + expect( + await testUtils.getActualDeployFile( + 'testExisting_automation', + 'automation', + 'json' + ) + ).to.exist; + // _ParentBU_: testTargetMarket + expect( + await testUtils.getActualDeployFile( + 'testTemplated_automation', + 'automation', + 'json', + '_ParentBU_' + ) + ).to.exist; + + // check query + assert.equal( + definitionResult.query?.['testInstance/testBU']?.testSourceMarket + ? Object.keys( + definitionResult.query?.['testInstance/testBU']?.testSourceMarket + ).length + : 0, + 1, + 'only one query expected' + ); + assert.equal( + definitionResult.query?.['testInstance/testBU']?.testTargetMarket + ? Object.keys( + definitionResult.query?.['testInstance/testBU']?.testTargetMarket + ).length + : 0, + 1, + 'only one query expected' + ); + assert.equal( + definitionResult.query?.['testInstance/_ParentBU_']?.testTargetMarket + ? Object.keys( + definitionResult.query?.['testInstance/_ParentBU_']?.testTargetMarket + ).length + : 0, + 1, + 'only one query expected' + ); + assert.deepEqual( + await testUtils.getActualDeployJson('testTemplated_query', 'query'), + await testUtils.getExpectedJson('9999999', 'query', 'build'), + 'returned deployment JSON was not equal expected' + ); + expect( + await testUtils.getActualDeployFile('testTemplated_query', 'query', 'sql') + ).to.equal(await testUtils.getExpectedFile('9999999', 'query', 'build', 'sql')); + + // check if files were also created for other BU-market combos + // testBU: testSourceMarket + expect(await testUtils.getActualDeployFile('testExisting_query', 'query', 'json')) + .to.exist; + expect(await testUtils.getActualDeployFile('testExisting_query', 'query', 'sql')).to + .exist; + // _ParentBU_: testTargetMarket + expect( + await testUtils.getActualDeployFile( + 'testTemplated_query', + 'query', + 'json', + '_ParentBU_' + ) + ).to.exist; + expect( + await testUtils.getActualDeployFile( + 'testTemplated_query', + 'query', + 'sql', + '_ParentBU_' + ) + ).to.exist; + + assert.equal( + testUtils.getAPIHistoryLength() - expectedApiCallsRetrieve, + 4, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + }); + + it('build but error after buildTemplate step because keys were not found', async () => { + const buName = 'testInstance/testBU'; + const typeKeyCombo = { + asset: ['404'], + dataExtension: ['404'], + }; + + // handler.setOptions({ skipInteraction: true, purge: false, fix: true }); + + await handler.build( + buName, + 'ignored', + typeKeyCombo, + ['testSourceMarket'], + ['parent'], + true + ); + + // THEN + assert.equal(process.exitCode, 1, 'build should not have thrown an error'); + + assert.equal( + testUtils.getAPIHistoryLength(), + 0, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + }); + + it('skip build based on validation rule "filterPrefixByBu" with --fix without error', async () => { + const buName = 'testInstance/testBU'; + const typeKeyCombo = { + asset: ['testExisting_asset_htmlblock'], + dataExtension: ['testExisting_dataExtension'], + }; + await handler.retrieve(buName, typeKeyCombo); + + const expectedApiCallsRetrieve = 11; + assert.equal( + testUtils.getAPIHistoryLength(), + expectedApiCallsRetrieve, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + + handler.setOptions({ skipInteraction: true, purge: false, fix: true }); + + const definitionResult = await handler.build( + buName, + 'ignored', + typeKeyCombo, + ['testSourceMarket'], + ['parent'], + true + ); + + // THEN + assert.equal(process.exitCode, 0, 'build should not have thrown an error'); + + // confirm that no deployment package was created + assert.equal( + definitionResult.asset?.['testInstance/_ParentBU_']?.testTargetMarket + ? Object.keys( + definitionResult.asset?.['testInstance/_ParentBU_']?.testTargetMarket + ).length + : 0, + 0, + '0 asset expected' + ); + assert.equal( + definitionResult.dataExtension?.['testInstance/_ParentBU_']?.testTargetMarket + ? Object.keys( + definitionResult.dataExtension?.['testInstance/_ParentBU_'] + ?.testTargetMarket + ).length + : 0, + 0, + '0 dataExtension expected' + ); + + assert.equal( + testUtils.getAPIHistoryLength() - expectedApiCallsRetrieve, + 0, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + }); + + it('skip deploy based on validation rule "filterPrefixByBu" without --fix but with error', async () => { + const buName = 'testInstance/testBU'; + const typeKeyCombo = { + asset: ['testExisting_asset_htmlblock'], + dataExtension: ['testExisting_dataExtension'], + }; + await handler.retrieve(buName, typeKeyCombo); + + const expectedApiCallsRetrieve = 11; + assert.equal( + testUtils.getAPIHistoryLength(), + expectedApiCallsRetrieve, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + + handler.setOptions({ skipInteraction: true, purge: false }); + + const definitionResult = await handler.build( + buName, + 'ignored', + typeKeyCombo, + ['testSourceMarket'], + ['parent'], + true + ); + + // THEN + assert.equal(process.exitCode, 1, 'build should have thrown an error'); + + // confirm that no deployment package was created + assert.equal( + definitionResult.asset?.['testInstance/_ParentBU_']?.testTargetMarket + ? Object.keys( + definitionResult.asset?.['testInstance/_ParentBU_']?.testTargetMarket + ).length + : 0, + 0, + '0 asset expected' + ); + assert.equal( + definitionResult.dataExtension?.['testInstance/_ParentBU_']?.testTargetMarket + ? Object.keys( + definitionResult.dataExtension?.['testInstance/_ParentBU_'] + ?.testTargetMarket + ).length + : 0, + 0, + '0 dataExtension expected' + ); + + assert.equal( + testUtils.getAPIHistoryLength() - expectedApiCallsRetrieve, + 0, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + }); + }); + + describe('Delete --metadata ~~~', () => { + it('Should delete the items', async () => { + const argvMetadata = [ + 'asset:testExisting_asset', + 'automation:testExisting_automation', + 'journey:testExisting_journey_Quicksend/1', + 'journey:testExisting_journey_Multistep/1', + ]; + const typeKeyCombo = handler.metadataToTypeKey(argvMetadata); + // WHEN + const isDeleted = await handler.deleteByKey('testInstance/testBU', typeKeyCombo); + // THEN + assert.equal(process.exitCode, 0, 'deleteByKey should not have thrown an error'); + assert.equal(isDeleted, true, 'deleteByKey should have returned true'); + return; + }); + }); + + describe('Publish --metadata ~~~', () => { + it('Should publish the journey', async () => { + handler.setOptions({ skipStatusCheck: true }); + const argvMetadata = [ + 'journey:testExisting_journey_Multistep', + 'journey:testExisting_temail_notPublished', + ]; + const typeKeyCombo = handler.metadataToTypeKey(argvMetadata); + // WHEN + const publish = await handler.publish('testInstance/testBU', typeKeyCombo); + // THEN + assert.equal(process.exitCode, 0, 'publish should not have thrown an error'); + assert.deepEqual( + publish['testInstance/testBU']?.journey, + ['testExisting_journey_Multistep', 'testExisting_temail_notPublished'], + 'should have published the right journey' + ); + return; + }); + }); + + describe('Execute/Start --metadata ~~~', () => { + it('Should execute the item', async () => { + const argvMetadata = [ + 'query:testExisting_query', + 'automation:testExisting_automation', + ]; + const typeKeyCombo = handler.metadataToTypeKey(argvMetadata); + // WHEN + const executedKeys = await handler.execute('testInstance/testBU', typeKeyCombo); + assert.equal(process.exitCode, 0, 'execute should not have thrown an error'); + + // query + assert.equal( + executedKeys['testInstance/testBU']?.query?.length, + 1, + 'returned number of keys does not correspond to number of expected fixed keys' + ); + assert.equal( + executedKeys['testInstance/testBU']?.query[0], + 'testExisting_query', + 'returned keys do not correspond to expected fixed keys' + ); + + // automation + assert.equal( + executedKeys['testInstance/testBU']?.automation?.length, + 1, + 'automation was supposed to be executed' + ); + assert.equal( + executedKeys['testInstance/testBU']?.automation[0], + 'testExisting_automation', + 'returned keys do not correspond to expected fixed keys' + ); + + return; + }); + }); + + describe('Pause --metadata ~~~', () => { + it('Should pause the item', async () => { + const argvMetadata = ['automation:testExisting_automation_pause']; + const typeKeyCombo = handler.metadataToTypeKey(argvMetadata); + // WHEN + const pausedKeys = await handler.pause('testInstance/testBU', typeKeyCombo); + assert.equal(process.exitCode, 0, 'pause should not have thrown an error'); + + // automation + assert.equal( + pausedKeys['testInstance/testBU']?.automation?.length, + 1, + 'returned number of keys does not correspond to number of expected fixed keys' + ); + assert.equal( + pausedKeys['testInstance/testBU']?.automation[0], + 'testExisting_automation_pause', + 'returned keys do not correspond to expected fixed keys' + ); + + return; + }); + }); + + describe('Schedule --metadata ~~~', () => { + it('Should schedule the item', async () => { + const argvMetadata = ['automation:testExisting_automation']; + const typeKeyCombo = handler.metadataToTypeKey(argvMetadata); + // WHEN + const scheduled = await handler.schedule('testInstance/testBU', typeKeyCombo); + assert.equal(process.exitCode, 0, 'execute should not have thrown an error'); + + // automation + assert.equal( + scheduled['testInstance/testBU']?.automation?.length, + 1, + 'returned number of keys does not correspond to number of expected fixed keys' + ); + assert.equal( + scheduled['testInstance/testBU']?.automation[0], + 'testExisting_automation', + 'returned keys do not correspond to expected fixed keys' + ); + + return; + }); + }); + }); + + describe('without --metadata ================', () => { + describe('retrieve without --metadata ~~~', () => { + it('retrieve multiple type with keys', async () => { + const buName = 'testInstance/testBU'; + const result = await handler.retrieve( + buName, + ['dataExtract', 'senderProfile'], + ['wrong-key', 'Default'] + ); + // THEN + assert.equal(process.exitCode, 0, 'retrieve should not have thrown an error'); + + const retrievedTypes = Object.keys(result[buName]); + assert.equal(retrievedTypes.length, 2, 'retrieve should have returned 2 types'); + assert.equal( + retrievedTypes.includes('dataExtract'), + true, + 'retrieve should have returned dataExtract' + ); + assert.equal( + retrievedTypes.includes('senderProfile'), + true, + 'retrieve should have returned senderProfile' + ); + assert.equal( + Object.keys(result[buName]['dataExtract']).length, + 0, + 'retrieve should have returned 0 dataExtracts' + ); + assert.equal( + Object.keys(result[buName]['senderProfile']).length, + 1, + 'retrieve should have returned 1 senderProfile' + ); + assert.equal( + testUtils.getAPIHistoryLength(), + 12, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + }); + }); + + describe('deploy without --metadata ~~~', () => { + beforeEach(() => { + testUtils.mockSetup(true); + }); + + it('deploy multiple type without keys', async () => { + const argvMetadata = ['dataExtension', 'senderProfile']; + const buName = 'testInstance/testBU'; + const result = await handler.deploy(buName, argvMetadata); + // THEN + assert.equal(process.exitCode, 0, 'deploy should not have thrown an error'); + + const deployedTypes = Object.keys(result[buName]); + assert.equal(deployedTypes.length, 2, 'deploy should have returned 2 types'); + assert.equal( + deployedTypes[0], + 'dataExtension', + 'deploy should have returned dataExtension' + ); + assert.equal( + deployedTypes[1], + 'senderProfile', + 'deploy should have returned senderProfile' + ); + assert.equal( + Object.keys(result[buName]['dataExtension']).length, + 2, + 'deploy should have returned 2 dataExtension' + ); + assert.equal( + Object.keys(result[buName]['senderProfile']).length, + 2, + 'deploy should have returned 2 senderProfile' + ); + assert.equal( + testUtils.getAPIHistoryLength(), + 20, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + }); + + it('deploy multiple type with keys', async () => { + const buName = 'testInstance/testBU'; + const result = await handler.deploy( + buName, + ['dataExtension', 'dataExtract', 'senderProfile', 'query'], + ['wrong-key', 'wrong-key2', 'testExisting_senderProfile', 'testExisting_query'] + ); + // THEN + assert.equal(process.exitCode, 0, 'deploy should not have thrown an error'); + + const deployedTypes = Object.keys(result[buName]); + assert.equal(deployedTypes.length, 2, 'deploy should have returned 2 types'); + assert.equal( + deployedTypes.includes('dataExtension'), + false, + 'deploy should have returned dataExtension' + ); + assert.equal( + deployedTypes.includes('dataExtract'), + false, + 'deploy should have returned dataExtract' + ); + assert.equal( + deployedTypes.includes('senderProfile'), + true, + 'deploy should have returned senderProfile' + ); + assert.equal( + deployedTypes.includes('query'), + true, + 'deploy should have returned query' + ); + assert.equal( + Object.keys(result[buName]['senderProfile']).length, + 1, + 'deploy should have returned 1 senderProfile' + ); + assert.equal( + Object.keys(result[buName]['query']).length, + 1, + 'deploy should have returned 1 query' + ); + assert.equal( + testUtils.getAPIHistoryLength(), + 13, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + }); + }); + + describe('Refresh ================', () => { + it('Should not refresh anything due to missing type', async () => { + // WHEN + const replace = await handler.refresh('testInstance/testBU', null); + // THEN + assert.equal(process.exitCode, 1, 'refresh should have thrown an error'); + // retrieve result + + assert.deepEqual( + Object.keys(replace).length, + 0, + 'should not have replaced anything' + ); + + assert.equal( + testUtils.getAPIHistoryLength(), + 0, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + return; + }); + }); + }); + + describe('init ================', () => { + it('should init a local project without downloading BUs'); + + it('should init a local project and download all BUs'); + }); + + describe('join ================', () => { + it('should clone a project from git'); + }); + + describe('upgrade ================', () => { + it('should upgrade a project to the latest version'); + }); + + describe('reloadBUs ================', () => { + it('should load all BUs from the server and refresh the config'); + }); + + describe('selectTypes ================', () => { + it('should change which types are selected for default retrieval'); + }); + + describe('explainTypes ================', () => { + it('without options', () => { + handler.explainTypes(); + assert.equal(process.exitCode, 0, 'explainTypes should not have thrown an error'); + + return; + }); + + it('with --json set', () => { + handler.setOptions({ json: true }); + const typeArr = handler.explainTypes(); + + assert.equal( + process.exitCode, + 0, + 'explainTypes --json should not have thrown an error' + ); + + // check if properties are all there + expect(typeArr[0]).to.have.all.keys( + 'name', + 'apiName', + 'retrieveByDefault', + 'description', + 'supports' + ); + expect(typeArr[0].supports).to.have.all.keys( + 'retrieve', + 'create', + 'update', + 'delete', + 'changeKey', + 'buildTemplate', + 'retrieveAsTemplate' + ); + + // check if certain types were returned + assert.equal( + typeArr.find((type) => type.apiName === 'dataExtension')?.apiName, + 'dataExtension', + 'Expected to find dataExtension type' + ); + + return; + }); + }); + + describe('createDeltaPkg ================', () => { + it('should show diff to master branch'); + // mcdev createDeltaPkg master # resolves to master..HEAD + it('should show diff between master and develop branch'); + // mcdev createDeltaPkg master..develop + it( + 'should show diff between master and develop branch and filter the results to only show MyProject/BU1' + ); + // mcdev createDeltaPkg master..develop --filter 'MyProject/BU1' + }); +}); diff --git a/test/mockRoot/.mcdev-auth.json b/test/mockRoot/.mcdev-auth.json new file mode 100644 index 000000000..0a2baf96e --- /dev/null +++ b/test/mockRoot/.mcdev-auth.json @@ -0,0 +1,8 @@ +{ + "testInstance": { + "client_id": "71fzp43cyb1aksgflc159xxx", + "client_secret": "oDZE354QsMXzcFqKQlGgDxxx", + "auth_url": "https://mct0l7nxfq2r988t1kxfy8sc4xxx.auth.marketingcloudapis.com/", + "account_id": 1111111 + } +} diff --git a/test/mockRoot/.mcdev-validations.js b/test/mockRoot/.mcdev-validations.js new file mode 100644 index 000000000..ad58e5cf9 --- /dev/null +++ b/test/mockRoot/.mcdev-validations.js @@ -0,0 +1,93 @@ +/* eslint-disable no-unused-vars */ +'use strict'; +/** + * @typedef {Object.<string, any>} MetadataTypeItem generic metadata item + * + * @typedef {object} CodeExtract + * @property {string[]} subFolder mostly set to null, otherwise subfolders path split into elements + * @property {string} fileName name of file w/o extension + * @property {string} fileExt file extension + * @property {string} content file content + * @property {'base64'} [encoding] optional for binary files + * + * @callback validationRuleFix + * @returns {boolean|null} true = test passed; false = test failed & fixed; null = test failed & item removed to fix + * + * @callback validationRuleTest + * @returns {boolean} true = test passed; false = test failed + * + * @typedef {object} validationRule + * @property {string} failedMsg error message to display in case of a failed test + * @property {validationRuleTest} passed test to run + * @property {validationRuleFix} [fix] test to run + * + * @typedef {Object.<string, validationRule>} validationRuleList key=rule name + */ + +/** @type {Object.<string, string[]>} */ +const buPrefixBlacklistMap = { + testBU: ['testBlacklist_'], + _ParentBU_: ['testBlacklist_'], +}; + +/** + * + * @param {any} definition type definition + * @param {MetadataTypeItem} item MetadataItem + * @param {string} targetDir folder in which the MetadataItem is deployed from (deploy/cred/bu) + * @param {CodeExtract[]} codeExtractItemArr array of code snippets + * @param {any} Util utility functions + * @returns {validationRuleList} MetadataItem + */ +export function validation(definition, item, targetDir, codeExtractItemArr, Util) { + const bu = + (targetDir.includes('/') ? targetDir.split('/').pop() : targetDir.split('\\').pop()) || + 'not-found'; + const prefixBlacklist = buPrefixBlacklistMap[bu] || []; + + const temp = codeExtractItemArr; + + return { + filterPrefixByBu: { + /** + * @returns {string} failedMsg + */ + get failedMsg() { + return `Prefix not allowed on this BU. Blacklisted prefixes: ${prefixBlacklist.join(', ')}`; + }, + /** @type {validationRuleFix} */ + fix: function () { + // to fix we skip the component + return this.passed() || null; + }, + /** @type {validationRuleTest} */ + passed: function () { + // this rule aims to prevent deploying things that dont belong on a BU + if (prefixBlacklist.length === 0) { + // no blacklist defined for current BU + return true; + } + for (const prefix of prefixBlacklist) { + // most components have the brand prefixes in the key + if ( + item[definition.keyField] && + ('' + item[definition.keyField]).startsWith(prefix) + ) { + // return false to issue an error or null to skip the item entirely (which is the "fix" of this rule) + return false; + } + // some components have unreadable keys and hence only have the brand prefix in the name + if ( + item[definition.nameField] && + ('' + item[definition.nameField]).startsWith(prefix) + ) { + // return false to issue an error or null to skip the item entirely (which is the "fix" of this rule) + return false; + } + } + // not found + return true; + }, + }, + }; +} diff --git a/test/mockRoot/.mcdevrc.json b/test/mockRoot/.mcdevrc.json new file mode 100644 index 000000000..a39729e9f --- /dev/null +++ b/test/mockRoot/.mcdevrc.json @@ -0,0 +1,182 @@ +{ + "credentials": { + "testInstance": { + "eid": 1111111, + "businessUnits": { + "_ParentBU_": 1111111, + "testBU": 9999999 + } + } + }, + "options": { + "formatOnSave": true, + "formatErrorLog": false, + "deployment": { + "commitHistory": 10, + "sourceTargetMapping": { + "deployment-source": "deployment-target" + }, + "branchSourceTargetMapping": { + "sit": { + "deployment-sit-source": "deployment-sit-target" + }, + "uat": { + "deployment-uat-source": "deployment-uat-target" + }, + "prod": { + "deployment-prod-source": "deployment-prod-target" + } + }, + "targetBranchBuMapping": { + "release/*": "MySandbox/QA-DE", + "master": ["MyProduction/PROD-DE", "MyProduction/PROD-NL"] + } + }, + "validation": { + "retrieve": { + "noAmpscriptHtmlTag": "warn", + "noGuidKeys": "warn", + "noRootFolder": "warn" + }, + "buildDefinition": { + "noAmpscriptHtmlTag": "warn", + "noGuidKeys": "warn", + "noRootFolder": "warn", + "filterPrefixByBu": "error" + }, + "deploy": { + "noAmpscriptHtmlTag": "warn", + "noGuidKeys": "warn", + "noRootFolder": "warn", + "filterPrefixByBu": "error", + "overrides": [ + { + "type": ["journey"], + "options": { + "noGuidKeys": "warn" + } + } + ] + } + }, + "documentType": "md", + "exclude": {}, + "include": {}, + "serverTimeOffset": -6, + "documentStandardRoles": false + }, + "directories": { + "businessUnits": "businessUnits/", + "deploy": "deploy/", + "docs": "docs/", + "retrieve": "retrieve/", + "template": "template/", + "templateBuilds": ["retrieve/", "deploy/"] + }, + "markets": { + "testSourceMarket": { + "mid": "9999999", + "buName": "testBU", + "secret": "secret", + "sharedFolder": "/Shared Data Extensions/test", + "suffix": "_test", + "prefix": "testExisting_", + "prefixUpper": "TESTEXISTING_", + "description": "bla bla", + "countryCodeIn": "'test'" + }, + "testTargetMarket": { + "mid": "1111111", + "buName": "testBUTarget", + "secret": "target secret", + "sharedFolder": "/Shared Data Extensions/test target", + "suffix": "_testTarget", + "prefix": "testTemplated_", + "prefixUpper": "TESTTEMPLATED_", + "description": "foobar", + "countryCodeIn": "'testTarget'" + }, + "testBlacklistMarket": { + "mid": "1111111", + "buName": "testBUTarget", + "secret": "target secret", + "sharedFolder": "/Shared Data Extensions/test target", + "suffix": "_testTarget", + "prefix": "testBlacklist_", + "prefixUpper": "TESTTEMPLATED_", + "description": "foobar", + "countryCodeIn": "'testTarget'" + } + }, + "marketList": { + "deployment-source": { + "description": "Define one 1:1 BU-Market combo here to as source for automated creation of deployment packages; you can create more than one source market list", + "testInstance/testBU": "testSourceMarket" + }, + "deployment-target": { + "description": "Define n BU-Market combo here to as target for automated creation of deployment packages; you can create more than one target market list and they can be as complex as you like", + "testInstance/testBU": ["testSourceMarket", "testTargetMarket"], + "testInstance/_ParentBU_": ["testTargetMarket"] + }, + "parent": { + "testInstance/_ParentBU_": ["testBlacklistMarket"] + } + }, + "metaDataTypes": { + "documentOnRetrieve": ["user", "automation", "dataExtension", "role"], + "retrieve": [ + "asset", + "attributeGroup", + "attributeSet", + "automation", + "dataExtension", + "dataExtract", + "dataFilter", + "domainVerification", + "emailSend", + "event", + "fileLocation", + "fileTransfer", + "filter", + "importFile", + "journey", + "list", + "mobileCode", + "mobileKeyword", + "mobileMessage", + "query", + "role", + "script", + "sendClassification", + "senderProfile", + "transactionalEmail", + "transactionalPush", + "transactionalSMS", + "verification" + ], + "createDeltaPkg": [ + "asset", + "automation", + "dataExtension", + "dataExtract", + "dataFilter", + "emailSend", + "event", + "fileTransfer", + "filter", + "importFile", + "journey", + "mobileCode", + "mobileKeyword", + "mobileMessage", + "query", + "script", + "sendClassification", + "senderProfile", + "transactionalPush", + "transactionalSMS", + "verification" + ] + }, + "version": "9.0.2" +} diff --git a/test/mockRoot/deploy/testInstance/_ParentBU_/dataExtension/testExisting_dataExtensionShared.dataExtension-meta.json b/test/mockRoot/deploy/testInstance/_ParentBU_/dataExtension/testExisting_dataExtensionShared.dataExtension-meta.json new file mode 100644 index 000000000..2314d37a5 --- /dev/null +++ b/test/mockRoot/deploy/testInstance/_ParentBU_/dataExtension/testExisting_dataExtensionShared.dataExtension-meta.json @@ -0,0 +1,58 @@ +{ + "CustomerKey": "testExisting_dataExtensionShared", + "Name": "testExisting_dataExtensionShared", + "Description": "Container for my test emails", + "IsSendable": true, + "IsTestable": true, + "SendableDataExtensionField": { "Name": "ContactKey" }, + "SendableSubscriberField": { "Name": "Subscriber Key" }, + "DataRetentionPeriodLength": 6, + "ResetRetentionPeriodOnImport": false, + "Fields": [ + { + "Name": "FirstName", + "DefaultValue": "", + "MaxLength": 50, + "IsRequired": false, + "IsPrimaryKey": false, + "FieldType": "Text" + }, + { + "Name": "LastName", + "DefaultValue": "", + "MaxLength": 55, + "IsRequired": false, + "IsPrimaryKey": false, + "FieldType": "Text" + }, + { + "Name": "EmailAddress", + "DefaultValue": "", + "MaxLength": 254, + "IsRequired": true, + "IsPrimaryKey": false, + "FieldType": "EmailAddress" + }, + { + "Name": "newField", + "DefaultValue": "", + "MaxLength": 254, + "IsRequired": false, + "IsPrimaryKey": false, + "FieldType": "Text" + }, + { + "Name": "ContactKey", + "DefaultValue": "", + "MaxLength": 50, + "IsRequired": true, + "IsPrimaryKey": true, + "FieldType": "Text" + } + ], + "c__dataRetentionPeriodUnitOfMeasure": "Days", + "c__retainUntil": "2024-5-9", + "c__retentionPolicy": "allRecords", + "r__folder_ContentType": "shared_dataextension", + "r__folder_Path": "Shared Items/Shared Data Extensions" +} diff --git a/test/mockRoot/deploy/testInstance/_ParentBU_/dataExtension/testNew_dataExtensionShared.dataExtension-meta.json b/test/mockRoot/deploy/testInstance/_ParentBU_/dataExtension/testNew_dataExtensionShared.dataExtension-meta.json new file mode 100644 index 000000000..8770af6d2 --- /dev/null +++ b/test/mockRoot/deploy/testInstance/_ParentBU_/dataExtension/testNew_dataExtensionShared.dataExtension-meta.json @@ -0,0 +1,20 @@ +{ + "CustomerKey": "testNew_dataExtensionShared", + "Name": "testNew_dataExtensionShared", + "Description": "", + "IsSendable": false, + "IsTestable": false, + "Fields": [ + { + "Name": "testField", + "DefaultValue": "", + "MaxLength": 254, + "IsRequired": true, + "IsPrimaryKey": false, + "FieldType": "Text" + } + ], + "c__retentionPolicy": "none", + "r__folder_ContentType": "shared_dataextension", + "r__folder_Path": "Shared Items/Shared Data Extensions" +} diff --git a/test/mockRoot/deploy/testInstance/_ParentBU_/query/testNew_query.query-meta.json b/test/mockRoot/deploy/testInstance/_ParentBU_/query/testNew_query.query-meta.json new file mode 100644 index 000000000..e0f734fef --- /dev/null +++ b/test/mockRoot/deploy/testInstance/_ParentBU_/query/testNew_query.query-meta.json @@ -0,0 +1,11 @@ +{ + "name": "testNew_query", + "key": "testNew_query", + "description": "created on deploy", + "r__dataExtension_key": "testExisting_dataExtensionShared", + "createdDate": "2022-04-26T15:21:16.453", + "modifiedDate": "2022-04-26T16:04:15.88", + "targetUpdateTypeName": "Overwrite", + "isFrozen": false, + "r__folder_Path": "Query" +} diff --git a/test/mockRoot/deploy/testInstance/_ParentBU_/query/testNew_query.query-meta.sql b/test/mockRoot/deploy/testInstance/_ParentBU_/query/testNew_query.query-meta.sql new file mode 100644 index 000000000..8020314ea --- /dev/null +++ b/test/mockRoot/deploy/testInstance/_ParentBU_/query/testNew_query.query-meta.sql @@ -0,0 +1,4 @@ +SELECT + SubscriberKey as testField +FROM + _Subscribers diff --git a/test/mockRoot/deploy/testInstance/_ParentBU_/user/testBlocked_user.user-meta.json b/test/mockRoot/deploy/testInstance/_ParentBU_/user/testBlocked_user.user-meta.json new file mode 100644 index 000000000..4bd81fc50 --- /dev/null +++ b/test/mockRoot/deploy/testInstance/_ParentBU_/user/testBlocked_user.user-meta.json @@ -0,0 +1,23 @@ +{ + "CreatedDate": "2019-09-06T01:59:07.097", + "ModifiedDate": "2022-06-21T01:43:02.64", + "CustomerKey": "testBlocked_user", + "UserID": "user_test@accenture.asgr", + "Name": "user test", + "Email": "user_test@accenture.com", + "MustChangePassword": false, + "ActiveFlag": true, + "LastSuccessfulLogin": "2023-02-23T10:14:11.443", + "IsAPIUser": false, + "NotificationEmailAddress": "user_test@accenture.com", + "DefaultBusinessUnit": 9999999, + "c__type": "User", + "c__AssociatedBusinessUnits": [9999999], + "c__RoleNamesGlobal": [ + "Administrator", + "Distributed Sending User", + "Marketing Cloud Administrator" + ], + "c__TimeZoneName": "(GMT+01:00) Amsterdam, Berlin, Bern, Rome, Stockholm, Vienna *", + "c__LocaleCode": "en-GB" +} diff --git a/test/mockRoot/deploy/testInstance/_ParentBU_/user/testExisting_user.user-meta.json b/test/mockRoot/deploy/testInstance/_ParentBU_/user/testExisting_user.user-meta.json new file mode 100644 index 000000000..4c20e3d32 --- /dev/null +++ b/test/mockRoot/deploy/testInstance/_ParentBU_/user/testExisting_user.user-meta.json @@ -0,0 +1,31 @@ +{ + "CreatedDate": "2019-09-06T01:59:07.097", + "ModifiedDate": "2022-06-21T01:43:02.64", + "CustomerKey": "testExisting_user", + "UserID": "user_test@accenture.asgr", + "Name": "user test", + "Email": "user_test@accenture.com", + "MustChangePassword": false, + "ActiveFlag": true, + "UserPermissions": [ + { + "ID": 2 + }, + { + "ID": 3 + } + ], + "LastSuccessfulLogin": "2023-02-23T10:14:11.443", + "IsAPIUser": false, + "NotificationEmailAddress": "user_test@accenture.com", + "DefaultBusinessUnit": 9999999, + "c__type": "User", + "c__AssociatedBusinessUnits": [9999999], + "c__RoleNamesGlobal": [ + "Administrator", + "Distributed Sending User", + "Individual role for 700301950" + ], + "c__TimeZoneName": "(GMT+01:00) Amsterdam, Berlin, Bern, Rome, Stockholm, Vienna *", + "c__LocaleCode": "en-GB" +} diff --git a/test/mockRoot/deploy/testInstance/_ParentBU_/user/testNew_user.user-meta.json b/test/mockRoot/deploy/testInstance/_ParentBU_/user/testNew_user.user-meta.json new file mode 100644 index 000000000..106b2c6ad --- /dev/null +++ b/test/mockRoot/deploy/testInstance/_ParentBU_/user/testNew_user.user-meta.json @@ -0,0 +1,27 @@ +{ + "CreatedDate": "2019-09-06T01:59:07.097", + "ModifiedDate": "2022-06-21T01:43:02.64", + "CustomerKey": "testNew_user", + "UserID": "testNew_user@accenture.asgr", + "Name": "new user", + "Email": "testNew_user@accenture.com", + "MustChangePassword": false, + "ActiveFlag": true, + "UserPermissions": [ + { + "ID": 2 + }, + { + "ID": 3 + } + ], + "LastSuccessfulLogin": "2023-02-23T10:14:11.443", + "IsAPIUser": false, + "NotificationEmailAddress": "testNew_user@accenture.com", + "DefaultBusinessUnit": 1111111, + "c__type": "User", + "c__AssociatedBusinessUnits": [1111111, 9999999], + "c__RoleNamesGlobal": ["Administrator", "Distributed Sending User"], + "c__TimeZoneName": "(GMT+01:00) Amsterdam, Berlin, Bern, Rome, Stockholm, Vienna *", + "c__LocaleCode": "en-GB" +} diff --git a/test/mockRoot/deploy/testInstance/testBU/asset/block/testExisting_asset_html-matchNamFail.asset-block-meta.html b/test/mockRoot/deploy/testInstance/testBU/asset/block/testExisting_asset_html-matchNamFail.asset-block-meta.html new file mode 100644 index 000000000..063fa056b --- /dev/null +++ b/test/mockRoot/deploy/testInstance/testBU/asset/block/testExisting_asset_html-matchNamFail.asset-block-meta.html @@ -0,0 +1,23 @@ +<table + cellpadding="0" + cellspacing="0" + width="100%" + role="presentation" + style="min-width: 100%; " + class="stylingblock-content-wrapper" +> + <tr> + <td class="stylingblock-content-wrapper camarker-inner"> + <div>my 1st html</div> +%%[ + /* my ampscript */ +]%% +<script runat="server"> + // my ssjs +</script> + + <div>my 2nd html</div> + <div>%%=ContentBlockById(1295065)=%%</div> + </td> + </tr> +</table> diff --git a/test/mockRoot/deploy/testInstance/testBU/asset/block/testExisting_asset_html-matchNamFail.asset-block-meta.json b/test/mockRoot/deploy/testInstance/testBU/asset/block/testExisting_asset_html-matchNamFail.asset-block-meta.json new file mode 100644 index 000000000..db6047eae --- /dev/null +++ b/test/mockRoot/deploy/testInstance/testBU/asset/block/testExisting_asset_html-matchNamFail.asset-block-meta.json @@ -0,0 +1,41 @@ +{ + "customerKey": "testExisting_asset_html-matchNamFail", + "assetType": { + "name": "htmlblock", + "displayName": "HTML Block" + }, + "fileProperties": { + "fileName": "testExisting_htmlblock_matchName" + }, + "name": "testExisting_htmlblock_matchName", + "owner": { + "email": "joern.berkefeld@accenture.com", + "name": "Jörn Berkefeld (ASGR)" + }, + "createdDate": "2024-01-08T08:26:58.277-06:00", + "createdBy": { + "email": "joern.berkefeld@accenture.com", + "name": "Jörn Berkefeld (ASGR)" + }, + "modifiedDate": "2024-01-08T08:28:01.6-06:00", + "modifiedBy": { + "email": "joern.berkefeld@accenture.com", + "name": "Jörn Berkefeld (ASGR)" + }, + "memberId": 9999999, + "status": { + "name": "Draft" + }, + "design": "", + "meta": { + "wrapperStyles": { + "mobile": { + "visible": true + }, + "styling": {} + } + }, + "availableViews": [], + "modelVersion": 2, + "r__folder_Path": "Content Builder" +} diff --git a/test/mockRoot/deploy/testInstance/testBU/asset/block/testExisting_asset_html-matchName.asset-block-meta.html b/test/mockRoot/deploy/testInstance/testBU/asset/block/testExisting_asset_html-matchName.asset-block-meta.html new file mode 100644 index 000000000..063fa056b --- /dev/null +++ b/test/mockRoot/deploy/testInstance/testBU/asset/block/testExisting_asset_html-matchName.asset-block-meta.html @@ -0,0 +1,23 @@ +<table + cellpadding="0" + cellspacing="0" + width="100%" + role="presentation" + style="min-width: 100%; " + class="stylingblock-content-wrapper" +> + <tr> + <td class="stylingblock-content-wrapper camarker-inner"> + <div>my 1st html</div> +%%[ + /* my ampscript */ +]%% +<script runat="server"> + // my ssjs +</script> + + <div>my 2nd html</div> + <div>%%=ContentBlockById(1295065)=%%</div> + </td> + </tr> +</table> diff --git a/test/mockRoot/deploy/testInstance/testBU/asset/block/testExisting_asset_html-matchName.asset-block-meta.json b/test/mockRoot/deploy/testInstance/testBU/asset/block/testExisting_asset_html-matchName.asset-block-meta.json new file mode 100644 index 000000000..018761670 --- /dev/null +++ b/test/mockRoot/deploy/testInstance/testBU/asset/block/testExisting_asset_html-matchName.asset-block-meta.json @@ -0,0 +1,41 @@ +{ + "customerKey": "testExisting_asset_html-matchName", + "assetType": { + "name": "htmlblock", + "displayName": "HTML Block" + }, + "fileProperties": { + "fileName": "dont strip non ssjs content" + }, + "name": "dont strip non ssjs content", + "owner": { + "email": "joern.berkefeld@accenture.com", + "name": "Jörn Berkefeld (ASGR)" + }, + "createdDate": "2024-01-08T08:26:58.277-06:00", + "createdBy": { + "email": "joern.berkefeld@accenture.com", + "name": "Jörn Berkefeld (ASGR)" + }, + "modifiedDate": "2024-01-08T08:28:01.6-06:00", + "modifiedBy": { + "email": "joern.berkefeld@accenture.com", + "name": "Jörn Berkefeld (ASGR)" + }, + "memberId": 9999999, + "status": { + "name": "Draft" + }, + "design": "", + "meta": { + "wrapperStyles": { + "mobile": { + "visible": true + }, + "styling": {} + } + }, + "availableViews": [], + "modelVersion": 2, + "r__folder_Path": "Content Builder" +} diff --git a/test/mockRoot/deploy/testInstance/testBU/asset/block/testExisting_asset_html-matchNameAdd.asset-block-meta.html b/test/mockRoot/deploy/testInstance/testBU/asset/block/testExisting_asset_html-matchNameAdd.asset-block-meta.html new file mode 100644 index 000000000..063fa056b --- /dev/null +++ b/test/mockRoot/deploy/testInstance/testBU/asset/block/testExisting_asset_html-matchNameAdd.asset-block-meta.html @@ -0,0 +1,23 @@ +<table + cellpadding="0" + cellspacing="0" + width="100%" + role="presentation" + style="min-width: 100%; " + class="stylingblock-content-wrapper" +> + <tr> + <td class="stylingblock-content-wrapper camarker-inner"> + <div>my 1st html</div> +%%[ + /* my ampscript */ +]%% +<script runat="server"> + // my ssjs +</script> + + <div>my 2nd html</div> + <div>%%=ContentBlockById(1295065)=%%</div> + </td> + </tr> +</table> diff --git a/test/mockRoot/deploy/testInstance/testBU/asset/block/testExisting_asset_html-matchNameAdd.asset-block-meta.json b/test/mockRoot/deploy/testInstance/testBU/asset/block/testExisting_asset_html-matchNameAdd.asset-block-meta.json new file mode 100644 index 000000000..5646e87eb --- /dev/null +++ b/test/mockRoot/deploy/testInstance/testBU/asset/block/testExisting_asset_html-matchNameAdd.asset-block-meta.json @@ -0,0 +1,41 @@ +{ + "customerKey": "testExisting_asset_html-matchNameAdd", + "assetType": { + "name": "htmlblock", + "displayName": "HTML Block" + }, + "fileProperties": { + "fileName": "testExisting_asset_html-matchNameAdd" + }, + "name": "testExisting_asset_html-matchNameAdd", + "owner": { + "email": "joern.berkefeld@accenture.com", + "name": "Jörn Berkefeld (ASGR)" + }, + "createdDate": "2024-01-08T08:26:58.277-06:00", + "createdBy": { + "email": "joern.berkefeld@accenture.com", + "name": "Jörn Berkefeld (ASGR)" + }, + "modifiedDate": "2024-01-08T08:28:01.6-06:00", + "modifiedBy": { + "email": "joern.berkefeld@accenture.com", + "name": "Jörn Berkefeld (ASGR)" + }, + "memberId": 9999999, + "status": { + "name": "Draft" + }, + "design": "", + "meta": { + "wrapperStyles": { + "mobile": { + "visible": true + }, + "styling": {} + } + }, + "availableViews": [], + "modelVersion": 2, + "r__folder_Path": "Content Builder" +} diff --git a/test/mockRoot/deploy/testInstance/testBU/asset/block/testNew_asset.asset-block-meta.html b/test/mockRoot/deploy/testInstance/testBU/asset/block/testNew_asset.asset-block-meta.html new file mode 100644 index 000000000..fc775a5d5 --- /dev/null +++ b/test/mockRoot/deploy/testInstance/testBU/asset/block/testNew_asset.asset-block-meta.html @@ -0,0 +1,12 @@ +<table + cellpadding="0" + cellspacing="0" + width="100%" + role="presentation" + style="min-width: 100%" + class="stylingblock-content-wrapper" +> + <tr> + <td class="stylingblock-content-wrapper camarker-inner">foobar</td> + </tr> +</table> diff --git a/test/mockRoot/deploy/testInstance/testBU/asset/block/testNew_asset.asset-block-meta.json b/test/mockRoot/deploy/testInstance/testBU/asset/block/testNew_asset.asset-block-meta.json new file mode 100644 index 000000000..3498923a0 --- /dev/null +++ b/test/mockRoot/deploy/testInstance/testBU/asset/block/testNew_asset.asset-block-meta.json @@ -0,0 +1,39 @@ +{ + "customerKey": "testNew_asset", + "assetType": { + "name": "textblock", + "displayName": "Text Block" + }, + "fileProperties": { + "fileName": "testNew_asset" + }, + "name": "testNew_asset", + "description": "bla bla", + "owner": { + "email": "joern.berkefeld@accenture.com", + "name": "Jörn Berkefeld" + }, + "createdDate": "2022-10-14T08:54:26.643-06:00", + "createdBy": { + "email": "joern.berkefeld@accenture.com", + "name": "Jörn Berkefeld" + }, + "modifiedDate": "2024-05-06T07:18:33.787-06:00", + "modifiedBy": { + "name": "SFMC DEVOPS app user" + }, + "memberId": 1111111, + "status": { + "name": "Draft" + }, + "meta": { + "wrapperStyles": { + "mobile": { + "visible": true + } + } + }, + "availableViews": [], + "modelVersion": 2, + "r__folder_Path": "Content Builder" +} diff --git a/test/mockRoot/deploy/testInstance/testBU/asset/block/testNew_asset_htmlblock.asset-block-meta.html b/test/mockRoot/deploy/testInstance/testBU/asset/block/testNew_asset_htmlblock.asset-block-meta.html new file mode 100644 index 000000000..18ecdcb79 --- /dev/null +++ b/test/mockRoot/deploy/testInstance/testBU/asset/block/testNew_asset_htmlblock.asset-block-meta.html @@ -0,0 +1 @@ +<html></html> diff --git a/test/mockRoot/deploy/testInstance/testBU/asset/block/testNew_asset_htmlblock.asset-block-meta.json b/test/mockRoot/deploy/testInstance/testBU/asset/block/testNew_asset_htmlblock.asset-block-meta.json new file mode 100644 index 000000000..0f364ee51 --- /dev/null +++ b/test/mockRoot/deploy/testInstance/testBU/asset/block/testNew_asset_htmlblock.asset-block-meta.json @@ -0,0 +1,39 @@ +{ + "customerKey": "testNew_asset_htmlblock", + "assetType": { + "name": "textblock", + "displayName": "Text Block" + }, + "fileProperties": { + "fileName": "testNew_asset_htmlblock" + }, + "name": "testNew_asset_htmlblock", + "description": "bla bla", + "owner": { + "email": "joern.berkefeld@accenture.com", + "name": "Jörn Berkefeld" + }, + "createdDate": "2022-10-14T08:54:26.643-06:00", + "createdBy": { + "email": "joern.berkefeld@accenture.com", + "name": "Jörn Berkefeld" + }, + "modifiedDate": "2024-05-06T07:18:33.787-06:00", + "modifiedBy": { + "name": "SFMC DEVOPS app user" + }, + "memberId": 9999999, + "status": { + "name": "Draft" + }, + "meta": { + "wrapperStyles": { + "mobile": { + "visible": true + } + } + }, + "availableViews": [], + "modelVersion": 2, + "r__folder_Path": "Content Builder" +} diff --git a/test/mockRoot/deploy/testInstance/testBU/asset/block/testNew_asset_withCBBK_notexisting.asset-block-meta.html b/test/mockRoot/deploy/testInstance/testBU/asset/block/testNew_asset_withCBBK_notexisting.asset-block-meta.html new file mode 100644 index 000000000..f1f79d732 --- /dev/null +++ b/test/mockRoot/deploy/testInstance/testBU/asset/block/testNew_asset_withCBBK_notexisting.asset-block-meta.html @@ -0,0 +1,4 @@ + +%%[ + ContentBlockByKey("testNew_asset_htmlblock") +]%% diff --git a/test/mockRoot/deploy/testInstance/testBU/asset/block/testNew_asset_withCBBK_notexisting.asset-block-meta.json b/test/mockRoot/deploy/testInstance/testBU/asset/block/testNew_asset_withCBBK_notexisting.asset-block-meta.json new file mode 100644 index 000000000..378038faf --- /dev/null +++ b/test/mockRoot/deploy/testInstance/testBU/asset/block/testNew_asset_withCBBK_notexisting.asset-block-meta.json @@ -0,0 +1,39 @@ +{ + "customerKey": "testNew_asset_withCBBK_notexisting", + "assetType": { + "name": "textblock", + "displayName": "Text Block" + }, + "fileProperties": { + "fileName": "testNew_asset_withCBBK_notexisting" + }, + "name": "testNew_asset_withCBBK_notexisting", + "description": "bla bla", + "owner": { + "email": "joern.berkefeld@accenture.com", + "name": "Jörn Berkefeld" + }, + "createdDate": "2022-10-14T08:54:26.643-06:00", + "createdBy": { + "email": "joern.berkefeld@accenture.com", + "name": "Jörn Berkefeld" + }, + "modifiedDate": "2024-05-06T07:18:33.787-06:00", + "modifiedBy": { + "name": "SFMC DEVOPS app user" + }, + "memberId": 9999999, + "status": { + "name": "Draft" + }, + "meta": { + "wrapperStyles": { + "mobile": { + "visible": true + } + } + }, + "availableViews": [], + "modelVersion": 2, + "r__folder_Path": "Content Builder" +} diff --git a/test/mockRoot/deploy/testInstance/testBU/asset/block/testNew_asset_withCBBK_preexisting.asset-block-meta.html b/test/mockRoot/deploy/testInstance/testBU/asset/block/testNew_asset_withCBBK_preexisting.asset-block-meta.html new file mode 100644 index 000000000..978d291e7 --- /dev/null +++ b/test/mockRoot/deploy/testInstance/testBU/asset/block/testNew_asset_withCBBK_preexisting.asset-block-meta.html @@ -0,0 +1,4 @@ + +%%[ + ContentBlockByKey("testExisting_asset_htmlblock") +]%% diff --git a/test/mockRoot/deploy/testInstance/testBU/asset/block/testNew_asset_withCBBK_preexisting.asset-block-meta.json b/test/mockRoot/deploy/testInstance/testBU/asset/block/testNew_asset_withCBBK_preexisting.asset-block-meta.json new file mode 100644 index 000000000..313cb6a23 --- /dev/null +++ b/test/mockRoot/deploy/testInstance/testBU/asset/block/testNew_asset_withCBBK_preexisting.asset-block-meta.json @@ -0,0 +1,39 @@ +{ + "customerKey": "testNew_asset_withCBBK_preexisting", + "assetType": { + "name": "textblock", + "displayName": "Text Block" + }, + "fileProperties": { + "fileName": "testNew_asset_withCBBK_preexisting" + }, + "name": "testNew_asset_withCBBK_preexisting", + "description": "bla bla", + "owner": { + "email": "joern.berkefeld@accenture.com", + "name": "Jörn Berkefeld" + }, + "createdDate": "2022-10-14T08:54:26.643-06:00", + "createdBy": { + "email": "joern.berkefeld@accenture.com", + "name": "Jörn Berkefeld" + }, + "modifiedDate": "2024-05-06T07:18:33.787-06:00", + "modifiedBy": { + "name": "SFMC DEVOPS app user" + }, + "memberId": 9999999, + "status": { + "name": "Draft" + }, + "meta": { + "wrapperStyles": { + "mobile": { + "visible": true + } + } + }, + "availableViews": [], + "modelVersion": 2, + "r__folder_Path": "Content Builder" +} diff --git a/test/mockRoot/deploy/testInstance/testBU/asset/block/test_slash.asset-block-meta.html b/test/mockRoot/deploy/testInstance/testBU/asset/block/test_slash.asset-block-meta.html new file mode 100644 index 000000000..a8e8a44e6 --- /dev/null +++ b/test/mockRoot/deploy/testInstance/testBU/asset/block/test_slash.asset-block-meta.html @@ -0,0 +1,12 @@ +<table + cellpadding="0" + cellspacing="0" + width="100%" + role="presentation" + style="min-width: 100%" + class="stylingblock-content-wrapper" +> + <tr> + <td class="stylingblock-content-wrapper camarker-inner">test</td> + </tr> +</table> diff --git a/test/mockRoot/deploy/testInstance/testBU/asset/block/test_slash.asset-block-meta.json b/test/mockRoot/deploy/testInstance/testBU/asset/block/test_slash.asset-block-meta.json new file mode 100644 index 000000000..f7c664638 --- /dev/null +++ b/test/mockRoot/deploy/testInstance/testBU/asset/block/test_slash.asset-block-meta.json @@ -0,0 +1,29 @@ +{ + "customerKey": "test_slash", + "assetType": { + "name": "htmlblock", + "displayName": "HTML Block" + }, + "fileProperties": { + "fileName": "test_slash" + }, + "name": "test_slash", + "createdBy": {}, + "modifiedBy": {}, + "memberId": "9999999", + "status": { + "name": "Draft" + }, + "design": "", + "meta": { + "wrapperStyles": { + "mobile": { + "visible": true + }, + "styling": {} + } + }, + "availableViews": [], + "modelVersion": 2, + "r__folder_Path": "Content Builder/bla∕blub" +} diff --git a/test/mockRoot/deploy/testInstance/testBU/asset/message/testNew_assetMessage/testNew_assetMessage.asset-message-meta.json b/test/mockRoot/deploy/testInstance/testBU/asset/message/testNew_assetMessage/testNew_assetMessage.asset-message-meta.json new file mode 100644 index 000000000..3ef97dc79 --- /dev/null +++ b/test/mockRoot/deploy/testInstance/testBU/asset/message/testNew_assetMessage/testNew_assetMessage.asset-message-meta.json @@ -0,0 +1,435 @@ +{ + "customerKey": "testNew_assetMessage", + "contentType": "application/vnd.etmc.email.Message; kind=template", + "assetType": { + "name": "templatebasedemail", + "displayName": "Template-Based Email" + }, + "fileProperties": { + "fileName": "testNew_assetMessage" + }, + "name": "testNew_assetMessage", + "owner": { + "email": "joern.berkefeld@accenture.com", + "name": "Jörn Berkefeld" + }, + "createdDate": "2022-11-08T09:59:30.727-06:00", + "createdBy": { + "email": "joern.berkefeld@accenture.com", + "name": "Jörn Berkefeld" + }, + "modifiedDate": "2024-08-07T06:12:40.75-06:00", + "modifiedBy": { + "name": "Jörn Berkefeld" + }, + "memberId": 9999999, + "status": { + "name": "Draft" + }, + "meta": { + "globalStyles": { + "isLocked": false, + "template": { + "background-color": "#FFFFFF", + "border-width": "0px", + "border-style": "solid" + }, + "body": { + "background-color": "#FFFFFF", + "font-family": "Arial,helvetica,sans-serif", + "font-size": "16px", + "color": "#000000", + "line-height": 1, + "padding": "0px", + "content-padding-top": "0px", + "content-padding-right": "0px", + "content-padding-bottom": "0px", + "content-padding-left": "0px" + }, + "h1": { + "font-family": "Arial,helvetica,sans-serif", + "font-size": "28px", + "color": "#808080", + "line-height": 1, + "font-weight": "bold", + "font-style": "normal" + }, + "h2": { + "font-family": "Arial,helvetica,sans-serif", + "font-size": "22px", + "color": "#808080", + "line-height": 1, + "font-weight": "bold", + "font-style": "normal" + }, + "h3": { + "font-family": "Arial,helvetica,sans-serif", + "font-size": "20px", + "color": "#808080", + "line-height": 1, + "font-weight": "bold", + "font-style": "normal" + }, + "links": { + "font-weight": "normal", + "color": "#808080", + "text-decoration": "none" + }, + "buttons": { + "font-family": "Arial,helvetica,sans-serif", + "font-size": "16px", + "color": "#FFFFFF", + "background-color": "#5D5D5D", + "border-radius": "3px", + "padding": "10px", + "border-color": "#5D5D5D", + "border-width": "1px", + "border-style": "solid" + }, + "mobile": { + "body": { + "padding": "0px", + "font-size": "16px", + "line-height": 1.5 + }, + "h1": { + "font-size": "22px", + "line-height": 1 + }, + "h2": { + "font-size": "20px", + "line-height": 1 + }, + "h3": { + "font-size": "18px", + "line-height": 1 + }, + "buttons": { + "font-family": "Arial,helvetica,sans-serif", + "font-size": "16px", + "color": "#FFFFFF", + "padding": "10px" + } + } + } + }, + "views": { + "subjectline": { + "contentType": "application/vnd.etmc.email.View; kind=subjectline", + "thumbnail": {}, + "content": "A note", + "availableViews": [], + "data": { + "email": { + "options": {} + } + }, + "modelVersion": 2 + }, + "preheader": { + "thumbnail": {}, + "availableViews": [], + "data": { + "email": { + "options": {} + } + }, + "modelVersion": 2 + }, + "text": { + "thumbnail": {}, + "availableViews": [], + "data": { + "email": { + "options": { + "generateFrom": "html" + } + } + }, + "generateFrom": "html", + "modelVersion": 2 + }, + "viewAsAWebPage": { + "thumbnail": {}, + "availableViews": [], + "data": { + "email": { + "options": {} + } + }, + "modelVersion": 2 + }, + "subscriptioncenter": { + "thumbnail": {}, + "availableViews": [], + "data": { + "email": { + "options": {} + } + }, + "modelVersion": 2 + }, + "forwardHTML": { + "thumbnail": {}, + "availableViews": [], + "data": { + "email": { + "options": {} + } + }, + "modelVersion": 2 + }, + "forwardText": { + "thumbnail": {}, + "availableViews": [], + "data": { + "email": { + "options": {} + } + }, + "modelVersion": 2 + }, + "html": { + "thumbnail": {}, + "availableViews": [], + "slots": { + "banner": { + "content": "<table cellpadding=\"0\" cellspacing=\"0\" width=\"100%\" role=\"presentation\" style=\"background-color: transparent; min-width: 100%; \" class=\"slot-styling\"><tr><td style=\"padding: 0px; \" class=\"slot-styling camarker-inner\"><div data-type=\"block\" data-key=\"ms2rjhckdsr\"></div><div data-type=\"block\" data-key=\"vlh4b2my8gp\"></div><div data-type=\"block\" data-key=\"x0ecuu93q1k\"></div><div data-type=\"block\" data-key=\"8uflrc8ao4r\"></div><div data-type=\"block\" data-key=\"1bd95vemqf4\"></div></td></tr></table>", + "design": "<table cellpadding=\"0\" cellspacing=\"0\" width=\"100%\" role=\"presentation\" style=\"background-color: transparent; min-width: 100%; \" class=\"slot-styling\"><tr><td style=\"padding: 0px; \" class=\"slot-styling camarker-inner\"><p style=\"font-family:Arial;color:#ccc;font-size:12px;text-align:center;vertical-align:middle;font-weight:bold;height:150px;display:flex;flex-direction:column;justify-content:center;padding:10px;margin:0;border: #cccccc dashed 1px;\">Drop blocks or content here</p></td></tr></table>", + "meta": { + "wrapperStyles": { + "mobile": { + "visible": true, + "columnOrder": "ltr" + }, + "styling": { + "background-color": "transparent", + "margin": "0px", + "padding": "0px" + } + } + }, + "availableViews": [], + "blocks": { + "vlh4b2my8gp": { + "assetType": { + "id": 196, + "name": "textblock" + }, + "name": "sample content block", + "design": "<table cellpadding=\"0\" cellspacing=\"0\" width=\"100%\" role=\"presentation\" style=\"background-color: transparent; min-width: 100%; \" class=\"stylingblock-content-wrapper\"><tr><td style=\"padding: 20px; \" class=\"stylingblock-content-wrapper camarker-inner\"><div class=\"default-design\" style=\"height:150px; overflow:hidden;\"><p class=\"textblock\" style=\"margin:0; padding:0; overflow:hidden; display:block;\">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Morbi vestibulum nunc feugiat porta consectetur. Sed vehicula vel ante suscipit sagittis. Ut metus metus, feugiat ut laoreet blandit, viverra non mi. Phasellus convallis, mauris ac vehicula posuere, ligula magna mattis ipsum, in sollicitudin nibh lacus eget sapien. Mauris ultricies laoreet ex, a viverra leo ornare eu. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Mauris commodo scelerisque arcu, id semper sem pharetra vel. Sed ut erat auctor lectus pretium blandit gravida vitae enim. Nullam eget ex et enim molestie porttitor. Duis vitae est fringilla, placerat nisi condimentum, tristique purus. Fusce lobortis mauris quis iaculis ultrices. In tempor ligula ac ex tempor rutrum. Pellentesque quis convallis mi.<br><br>Duis mattis, ex a hendrerit ullamcorper, eros massa consectetur elit, vel lobortis justo arcu ac mi magna, blandit sit amet eros id, dapibus cursus justo. Suspendisse mauris odio, aliquet ut ligula in, porta mollis risus. Ut ultrices lectus dolor, sed euismod nulla ultrices ac. Phasellus laoreet ultricies facilisis. Fusce imperdiet maximus ipsum vitae rutrum. Maecenas faucibus vestibulum lorem sit amet varius. Vivamus et ultricies ligula. Mauris semper scelerisque ante id fermentum. Curabitur non odio pellentesque, consectetur odio eu, commodo risus. Mauris egestas elit vel ipsum sagittis fermentum. Cras varius quam ac enim eleifend, eu porttitor odio finibus. Aenean quis finibus dolor. Nunc bibendum aliquam auctor.</p></div></td></tr></table>", + "meta": { + "wrapperStyles": { + "mobile": { + "visible": true, + "columnOrder": "ltr" + }, + "styling": { + "background-color": "transparent", + "margin": "0px", + "padding": "20px" + } + } + }, + "availableViews": [], + "data": { + "email": { + "options": {} + } + }, + "modelVersion": 2, + "r__asset_key": "testNew_asset_htmlblock" + }, + "ms2rjhckdsr": { + "assetType": { + "id": 199, + "name": "imageblock" + }, + "design": "<table cellpadding=\"0\" cellspacing=\"0\" width=\"100%\" role=\"presentation\" style=\"min-width: 100%; \" class=\"stylingblock-content-wrapper\"><tr><td class=\"stylingblock-content-wrapper camarker-inner\"><div class=\"default-design\"><div style=\"width:100%;height:150px;background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAABuoAAACWBAMAAADK78OEAAAAKlBMVEUFBwgFBwgFBwgFBwgFBwgFBwgFBwgFBwgFBwgFBwgFBwgFBwgFBwgFBwhamwL+AAAADXRSTlMwmGPLQ97yfrGki3G+5/n17AAACcpJREFUeF7s2kGL00AYh/FJNhLrKrSy4KlQZBEvhUrOhS6wy168CQiYi/QaWOl5QbwXehaEfoQF/BqCpqSC8P8uBpxjtFs6KTPx+X2E981DZkJMwAAAAAAAAAAAAAAAAAAAQHJujgpAVJr/FEB1yDJzVKA6SMYXoDqqA9WB6kB1MdU5BaqjOlAd1VEdqO6U6jBodkZ1LYmoDmpWmpZQ3YjqHKI6qqM6UB3VUR3VUR3VYZGpWZWtqK4NVIeh/mpCdQ5QHajOAar7MJAGz8xOSGdU54VobUI3VW1jdsK46Z6mfyl9rC4Jv7q+8U7STnXIyy5UF2cmdD0Pq3vYSnWIVHWgunga/q5PPKzuyayN6nAl9YOvLlmK6towvmujOkylMvTqfi5FdZYVj4wLw9VeXzBz1apdXzHxSFIVeHU9ieosK8319unMHGw62fdNd49d4Eq1fkNz4XSXOjrXXAwaHLO6lcvoatWrr+ZAxfdOVbfIbowPvqk2D7m6NHe06bEaHLO6icORWJvPI3OAWGWnqhuqbzxwaqcUbnVpLqprHIn17uyQ+8cPc1+9rJC1zVZUt+uAKa2Dre6iUFequ3xjnIhzZ8t6vMdYT/z9f8lKni/16dyXA6Y0D7E6G11XqkvyamZciNwt64G2Haou8uTRjfXHJtDqrgt1prpL6b1v1b2WRlTnftPWXZDVXUudqS4upO2NZ9XdSmuqc+2LrHmI1b1Uh6p7odovz6pbSh+pzrHf7N1BS9tgHMdxFisVx8Ayr0JIRXYRZA96zoTBLoJIwVMB3WCAFLzsKDjYVfAljN0F38BuuwpVTbWuv/cy1dk/jQ2J6dPmn+T3PduQNPlgkjxP6uCpXg7V1VEgdU4L9x3qUtcENhOaM2uQ8NlEuaO6afQ7zZ26Omyqe5Xxti7hoZ6vSV0FwFXCYdII1aa6+AnjX/Km7huKpK7awmMNTepeA7imOrs5kLo5U+egUOoO8L+Oq0KdLKlLdZHVzX3pTzABNzt1VFdFvz1F6qYABFQXcydglDcSNbJTR3UHkPZVqBNKSa40171lhLrwFqluSJUWJHTFYqLaVGetKiR0Rx1Wv2pjA+SoOk17+/eiJOpeNj9lCgO5WamjuhNIwLHlVypejLasOapLuNkp9jU2LaijOgtSVtSoO3u2OlRnJNPEQMlPMKVzqhuM6lrPdjTVIbpkszhCuSVVF7/NbjnVOQk+TnWSd5cfM9foBKG2PKqTQHWzuO+20Oocb7DFVOok9+VnVDlXR3VVY5r2jv4ZGaIb04faAkKd1+bzoG4qvNpUR3U2rk4vRhum25nMU/JauCKqc94iXFCjOglUtyFbP351CFc0dbIK4eOW6iSq+42H9lWoq9T6zRdTHdVRncx5PlShzkG/wC2qOqqjuiYe2tSmDnt61f3ySqWO6qrGrNpUV8FjV+rU4adadcBk1VGd4w00aXWvrA6uka/479jVOcYYhDN3HUfs8Bvfirq6MWuK1VFdiiMv3+pked3xq0NEK1F/07CibhmAHnVUR3Vy8hUoVNdxC6iO6qhONkehOlyPSd1l7XnzStWte5KvTp0jA+yoLsXsMVehOhzbUhdfZ06fuvBnbnxF6uSIOC+6Ou+dXXUy/3IuA3Wx9fyJqUPgqleHHT8DdVQH2FUna7WiUR02J6cOl3I/VZW69Oyozmm9/JKF6toTUSetKFeHbaoDkOa1KWlfu051VIdtReoA6Fb3CaHS/I4d1VEd3lNdUnWVJsLtUh3VJVGXlh3VLUEaZZwh1VEdflBdomYhpX76QnVUl5wd1VWOMKxG9urW+2u25edFHdV15qkuvo8YWsfNXN0G+rma1FGdfNvp2FFdK4pK5uqmZUfm5wyT6hDsU11cUKtuBk/18qCO6oRdQdQ5nueXTZ3c5rkdnzqqC7yHjuypQ+AWQ90b4LvM+iiHOkcWMC51VCdZVIdLtyDqnuqclkWdXHK2c6POPPan5OrQ84ulDu1cqqtJtaSP4M/y97xOTrHKrQ43fvbqqC7NHlnIrTrslV0dzn1V6qgOjYmqm8Kw3HGpix5SV18FgMCUQh12fFXqqC5wi6VOXsce/f9cjKEc6vBVlTqqw659df/Yu6OVBIIoDMAUUnSnBHQVyEIQQVAOEQHCFtB9EnQlRPUAvYBg0APso/gIAT2AruwKwXmXaFOPeFxm3XVHx/n/y5nBmXXO5wIrs+tVJz/g0Xl19LRg+prMkRl1UBf3tk+d/i91t+2k59IVddTS7BLDMaAO6ihcu7oPfvi5KnXao/uaSUfVGXXUKK4O6uQsVqrjhIXUaYo4gDr6XkZdpSZTt1jdgZomMKQO6oY+1FE3k7r0XajaqE4W3oUhdVBHLaijvkF1PGLgrDqoi3tm1UEd1EEd/SyjDuoqh6LvoZ5FnTeTM8fVQR19ZlMHdbw4ec16dU05bQnq5NNGfxPVQV3kL3jjc9dmdaGX5NxBdXL19ezqiPqG1EEdvSwomTdb1BUP1HGG6saMOqiL3+WRFKM86jjWqku7R8ZKqWB71XGGpauDOvl253tKEjmqTnMfX5U6qIM6+uIldnizbFMHdbxXG6wO6mTZtcdNXQvUQR3HXnVQx5M8a9RBHdRVvNn41qgLvXFO1qtOnu852gZ1UDc5tu+4DHU7c7zLVMd96ep2+QdAqFs2kfrPlQl1e/zt268O6jgOqONrqRZWxzGhrjNt86FuLi3vL6dQJ3qKqYM6ro0A6nQprg7qoG5fKW57VY3c6qAO6pRS11CnGyUHhu6pg7qoNk1OdZxBbnU1kXR1d94kJ0Ldbzt3j9JAEAZgGELAwmpAsJUFrQMDdinS24TUqaytPEcgF/AI3sUkIGnmLhIRN+usNib7kzzvEb6dhx1mYFIl6gaxbNlrdXm9VJfXorqU9Zu6PwdEXbXKD2F0tuqoo24Q0l7TK+qoo+74Z5gps3AkdZXbx8dYNqJu1yTsuqaOuiZ6o64c+oY66g4bddRtQwh9Vkcddauw6Ly6vAbVUUfduthbnZNQaZGp+3fUUUdd2apmyn1SRx111FFHHXXUUUcddcV3t9TlUUddC1FHHXXtRx111FFHHXXUzWIcN6OOOuqoK+unOurW5YNALagbnoc66qjLa03dXbPqqKOOuovUZXXUbcNX49NRR91LJ9VRl9eAumaWHXUPqR1126IoXs9RHXXUDeepK1FH3am3iZ/dpzNRRx11oi6POlFHHXXUUVfWZ3XPMcb045XKG+qoy2/NDqSOuvrPSx11NVFH3QGjjjrqqLt8oo66BtN7jPPU26ijTtRRJ+qoq93LzJZHUydRl2obnYQ6UUedRN0qhJBqm4awSBJ1HUyiTtIHMv/VI7tXCZsAAAAASUVORK5CYII=) repeat-x 0 0\"></div></div></td></tr></table>", + "meta": { + "wrapperStyles": { + "mobile": { + "visible": true + } + } + }, + "availableViews": [], + "data": { + "email": { + "options": {} + } + }, + "modelVersion": 2 + }, + "1bd95vemqf4": { + "assetType": { + "id": 195, + "name": "freeformblock", + "displayName": "Free Form Block" + }, + "fileProperties": { + "fileName": "Footer" + }, + "name": "Footer", + "owner": { + "id": 710265361, + "email": "joern.berkefeld@accenture.com", + "name": "Jörn Berkefeld", + "userId": "710265361" + }, + "createdDate": "2022-06-27T07:17:04Z", + "createdBy": { + "id": 710265361, + "email": "joern.berkefeld@accenture.com", + "name": "Jörn Berkefeld", + "userId": "710265361" + }, + "modifiedDate": "2022-06-27T07:19:07Z", + "modifiedBy": { + "id": 710265361, + "email": "joern.berkefeld@accenture.com", + "name": "Jörn Berkefeld", + "userId": "710265361" + }, + "enterpriseId": 510004860, + "memberId": 510006764, + "status": { + "id": 1, + "name": "Draft" + }, + "category": { + "id": 4795, + "name": "Content Builder", + "parentId": 0 + }, + "design": "<table cellpadding=\"0\" cellspacing=\"0\" width=\"100%\" role=\"presentation\" style=\"min-width: 100%; \" class=\"stylingblock-content-wrapper\"><tr><td class=\"stylingblock-content-wrapper camarker-inner\"><div class=\"default-design\" style=\"height:150px; overflow:hidden;\"><p class=\"textblock\" style=\"margin:0; padding:0; overflow:hidden;\"><span style=\"float:left; margin: 0 6px 6px 0; width:50%; height: 75px; overflow:hidden; background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAA2sAAABLCAMAAADZL+8JAAAAS1BMVEUBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQGt0wPNAAAAGHRSTlMw51fNi5ilsr9K83HZPWR+N/rhxmq4rESzSUQKAAAGxElEQVR4XuzYW46DMAxAUUMDacK7pcX7X+lMNX+IoUgF5Kj3rMBSdKPE8j0AAAAAAACAIGcAcDEwA6bsLscDrSFoLfaB1npaOwVorem/uDW03aKW1g4Qmi9uDVdd5OUAtBZoLWm0Zh+toYuDLhriSGu7y3NJmys0c6Osw9Ixh0L/5SZam6G1LW8eVHGhHa8rSnOtNcWUeGutvZH2bg1Npo/EW+td1CBJa0dzqRWynXP6Uq++IvFU1WreX7jqCm9qQ93cMtXkW6tkL+F5Kbu8lw+5u2wXZ5sza7pysnDI+iubteP1jUKsmMqoukNrIS7I5Sxjt1tpg74MtXftJ1fiI24f3g/6R2++t7lTN/Af/mHfbpeUBQEwDL8iaAACfvac/5G+W02xlqVtqGjcv9cZRa4R2MlWONVtz5qbWX6s4bEFXxD1NKJd6Wu1n0x/egoXivCkHZVAtf6UzXBJb9EaaQHswprxNaTe/hnKAboXazyI1S3BJVR2c9b0AdiJNQoArQ3JmgHaiX+ZK7jQ5jxaG8i6Uco2Zq1JAX/WWJpiIJV2i1ED0iIgax2QvLU0cpG9W7PFqXenGFxkU9Y6wKe1A56k/s2eewsVD8eaejqm0ZrBqTfvoYRL2etOUusaI+Var7suP+zHWoZbQn92BkCIL2sFAJgpd58I3JUkzTdYY9cmXZMOfqsoJiWjNS8xuFASD2tRH9Yadzr9uhwDyf1ZoweXQq8/vJqSfKm1QsoUT0qk9PgBH5+sMhBrDABUtDZlW0V/si8vbqhAP0X5V1ojeJneiDVCMn/W0qnn99rUuIsZ/uZJQ79FrNGkn/m7tfGRygTuE812rUVrAvBmzZY41SxxNpICr9dkTqFHawz96AzWXNkTPtFatKZxjoVgjeBWXaxtLVqL1ojWPq1RnEtnt0a0VrhL/1QMv56Ke7HGCen8WkOynLVoTdLf6YWtJRgs/2x4Szu3tWR8dpH+NseHtQOA7VqL1lL8Ltu2NeGePSxrAJ3HmsofI0Fao8x1DMyaZj/JXVuzhVdrbkToWtYSdatCv9x6sjZeprUmoVkTcJWsCMoacyMdorX+k5gP9nz+rEl3/eLWxuMLWHOlIVsDBLXBWKO0DtmabdGrpNHaSNFav8SEYg1AwNa4Aj5ZIkVr0RpQyWhttEbgMcVXt2ZwCa0Nx1q0ps2pEo8pHa29jmIwQVa2ZnFLhmAtWhu/h5rswprl3M5iLcVwbO3vmsK14zzWorWWnaq9WQNavgNrGqjzc1mxC2vT+VQb2a8Zda7m27Dm8mgN6I47sHaLbdBal7vMm2cj7UfWJBtIz2GNvfqxLTdnM3L31lCyYk1r0ZqAC8z/OeR/du5tWUEQCsBwIihCCNGu4f2fdI9UYi5T09Z44r/FaQrWd5HOCK31jjT7qTXJfRY+M4EQd2pt8HGbKmEE3Vq05nKzsLW8rPqVNQZW7wa+HtIv6J1aG3zcJqe8byBa07SOTLPm6ALWQGKutZt4dOnAobr3udynNZiVX1gjHJRt19o1eXWfbS0BFx3R2oCWhBzbmku/sFZ2rQ1bg8j4ktbgDXSOYC1agwk51lq0ZsBXE8UYazpr5D+RYFgr5Ft/460ZpdCtRWvwBsys/2vKd1vSWpr7LIK1E4VnM8YaHDmKYY2BXR5pzVqXaG3QrUVr7mbArzlPsRaabw0/aI1xzjvHTAhR7tVaqMC3Fq25HM4KOaC11H1uhdY4bw44A+vRWitJnqULWuPhln84k5VZi9Zg/daE9lkEayVvxDCtEVZleq0Z8kzNnyPxzKFbCycmTLTWTJOqbEPWYPOtmfzR2wUppjXt11SvtaI+JIQ5QrJmKA17dqckWgMd3JpyIGDtSilVC1vLqs5rttbaSYZoTdGQ2rC1S9bKbtdaUneZZi1UTLRWnNslH61J/upaM88enf7bt8NWB0EoAMN0bctjpy4VF/z/v/QyNqYDCcbBlex9vwqU4oMgGFNnPdeGfPpurGhNYkoatVauWWt5x1grz7hsbfc5YwPW0pLlB7L/7O9izemtX6xhrWZYe+7B/i1rW781ZS2oavyANaxhbXWZtb/upZisGTqttVR9a1jDWmoofLd9a1jDGtaCPluwlsIa1upntzZNU1VrWMMa1lLNWcPaqqrhIGtjwBrWDI3zPLt61trPZW/TTmoNa+HRYrB2fFiTe0Os0+a97/bvKkJMYW03rJkjrKn33n2JtUlEcmu9iNisEdYq1XmvDVu7FAYya4S1JRisVQlr9ugico2nC2tYo3asYe26lgZ+3rdG5B51sRDWNJYaDdaIsGaNCGtE9A9/OsOIx1k7gwAAAABJRU5ErkJggg==) repeat-x 0 0\"></span>In viverra et dui id fermentum. Nulla tortor libero, aliquam in dictum id, vestibulum nec lacus. Curabitur sit amet accumsan magna. Mauris mollis eu lorem sodales mattis. Mauris et iaculis odio. Suspendisse et metus maximus, dapibus lectus in, placerat est. Praesent sit amet lacinia ligula. Donec non magna dictum, feugiat arcu vel, volutpat augue. In hac habitasse platea dictumst. Nunc eleifend nulla elit, vel condimentum lectus dictum sit amet. Aliquam ante nulla, dapibus ut nisi vitae, convallis malesuada mauris. Duis mattis, ex a hendrerit ullamcorper, eros massa consectetur elit, vel lobortis justo arcu ac mi magna, blandit sit amet eros id, dapibus cursus justo. Suspendisse mauris odio, aliquet ut ligula in, porta mollis risus. Ut ultrices lectus dolor, sed euismod nulla ultrices ac. Phasellus laoreet ultricies facilisis. Fusce imperdiet maximus ipsum vitae rutrum. Maecenas faucibus vestibulum lorem sit amet varius. Vivamus et ultricies ligula. Mauris semper scelerisque ante id fermentum. Curabitur non odio pellentesque, consectetur odio eu, commodo risus. Mauris egestas elit vel ipsum sagittis fermentum. Cras varius quam ac enim eleifend, eu porttitor odio finibus. Aenean quis finibus dolor. Nunc bibendum aliquam auctor. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Morbi vestibulum nunc feugiat porta consectetur. Sed vehicula vel ante suscipit sagittis. Ut metus metus, feugiat ut laoreet blandit, viverra non mi. Phasellus convallis, mauris ac vehicula posuere, ligula magna mattis ipsum, in sollicitudin nibh lacus eget sapien.</p></div></td></tr></table>", + "meta": { + "wrapperStyles": { + "mobile": { + "visible": true + } + } + }, + "availableViews": [], + "data": { + "email": { + "options": {} + } + }, + "modelVersion": 2 + }, + "x0ecuu93q1k": { + "assetType": { + "id": 223, + "name": "referenceblock" + }, + "design": "<div class=\"default-design\"><div style=\"width:100%;height:150px;background-size:cover;background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAADawAAAEtCAIAAADRXFFBAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAALyhJREFUeNrs3ftvI+l+J2aOSF27JbWu7Z72nPEJdrOws5ss9hcj58R/vWEDQYLAhjdeZHfhcbeGYosiRfFWrHuFPZpty30btcRLFfk8IASKIt+q+r6UVMX61Pt+13r3rgYAAAAAAAAAAABQNY2rd1eqAAAAAAAAAAAAAFTOhhIAAAAAAAAAAAAAVSQECQAAAAAAAAAAAFSSECQAAAAAAAAAAABQSUKQAAAAAAAAAAAAQCUJQQIAAAAAAAAAAACVJAQJAAAAAAAAAAAAVJIQJAAAAAAAAAAAAFBJQpAAAAAAAAAAAABAJQlBAgAAAAAAAAAAAJUkBAkAAAAAAAAAAABUkhAkAAAAAAAAAAAAUElCkAAAAAAAAAAAAEAlCUECAAAAAAAAAAAAlSQECQAAAAAAAAAAAFSSECQAAAAAAAAAAABQSUKQAAAAAAAAAAAAQCUJQQIAAAAAAAAAAACVJAQJAAAAAAAAAAAAVJIQJAAAAAAAAAAAAFBJQpAAAAAAAAAAAABAJQlBAgAAAAAAAAAAAJUkBAkAAAAAAAAAAABUUkMJAAAAAADg4drt9ngSTe88290+Pz9XEAAAAIAlMhIkAAAAAAAAAAAAUElCkAAAAAAAAAAAAEAlCUECAAAAAAAAAAAAlSQECQAAAAAAAAAAAFRSo7Rr1mxexmn26eO///EH3QYAAAAAAAAAAAAYCRIAAAAAAAAAAACoJCFIAAAAAAAAAAAAoJKEIAEAAAAAAAAAAIBKEoIEAAAAAAAAAAAAKkkIEgAAAAAAAACYvSicKAIAMG9CkAAAAAAAAADA7MVxoggAwLwJQQIAAAAAAAAAs5fnmSIAAPMmBAkAAAAAAAAAzF5kJEgAYP6EIAEAAAAAAAAAAIBKEoIEAAAAAAAAAAAAKkkIEgAAAAAAAACYiyicKAIAMFdCkAAAAAAAAADAXMRxoggAwFwJQQIAAAAAAAAAAACV1FACAAAAmLlm8zJOM3X4yOnR4f7BgToAAAAAAACzYiRIAAAAAAAAAAAAoJKEIAEAAAAAAAAAAIBKEoIEAAAAAAAAAAAAKkkIEgAAAAAAAACYvaIo8jxTBwBgrhpKAAAAAAAAAADMXJpm0XeJOgAAc2UkSAAAAAAAAAAAAKCShCABAAAAAAAAAACAShKCBAAAAAAAAAAAACqpoQQAAADwFMF4lGX5Rw9meaEyn4qiqDYYfPTg3t5uvbGpOAAAAAAAwCMIQQIAAMCT9G4HcZqpw0MMg3B6++jB01pt/0AIEgAAAAAAeAzTYQMAAAAAAAAAAACVJAQJAAAAAAAAAMxFkqSKAADMlRAkAAAAAAAAAAAAUElCkAAAAAAAAAAAAEAlCUECAADwVFmaKAIAAAAAH8nyQhEAgHlrlGElfnpz8cQnP9vdPj8/150AAACLNxwMbm77P/7uB6UAAAAA4L4sz+sbdXUAAOaqoQQAAAA8WpYmN7f9vKi12+31uTit2byM00zvz0qn15/ePnx7enS4f3CgLAAAAAAAwEOYDhsAAIDH63Rv7iY1Gk+iYDxSEACAr+jf9qJwog4AAABQUcPBQBFKSAgSAACAxx/qB2H84dvOTV9NAAC+tOPUbF7e9EdxnKgGALBWksx8GgCsjsHQeBBlZDpsAAAAHqnXH97/NsvztZoUGwDgIYaDwWA4ilPn/gGANVUUagDAiojCyfQAf/p1e2dXNUpFCBIAAIDHaLfbWZ5/9GAQRg7+AQDuTPeLbnq3YZwqBQAAAKyAMAynX8fjwHmQshGCBAAA4JsF49F4En36eFHUOt3e69cO/gGAtSb+CAAAAKsnjOLp1yR1vF86QpAAAAB8s85N/0s/itOsc319enamSgDAGsrSpHvT++zlIgAAAEClRb9c7hi56LF8hCABAAD4Np3r608nwr5vNAn3TYoNAKyZu/hjEEZFoRgAAACwggf+dydHpl+n9+uNTTUpjw0lAAAA4OGicDKahF9/zt2k2GoFAKyPzvX1xeW78UQCEgAAAFZTEEw+3B+NRgpSKkaCBAAA4Bt0ur2HnNqP06x/2zt8caRiAMBqu+l2h+Mgl30EAPhEliZ3dyJzhsCyTX8Nb3q3Gxsb9Y2N7e3t/YMDNYFvNQn/ZYSIKE4UpFQWGoIcDgbz2nnKss82vre3a+hRAACAWelcX8dp9sAn9waj58+fOygDAFbYeBIpAgDAl3wYMSuOEyFIWJa7+GMYpx8eGQZhp9ff+K622Ziq7+7sbG1t+iWF35Qk6WfvUwYLDUFO/4bOqeXpH+sw/kzjp7Xa/oHzbQAAADOQpclvToR9X1HUrtqd779/pXQAwCoZDgZhZLwHAACg7D6NP96XF7UoSae3u4u7vvuutlmvb242GvX6zs723rPnCggfuT9IxMMHjGAxTIcNAADAg1y1O8U3zvMYJWmlJ8Vut9uGd1q8Tq//2asof//jD4oDwHLddLujIMzyXCngiaJwEq/Z5HH1+oYkAQCwyN2tr8QfP6so3oe67nJd/VFQ6/TqGxubjemtsb29bSJW+HSO4ukjZpYvDyFIAAAAflv/thc9anKHW5NiAwDVd9PtDsdBXqgEzOj4YjBct8uNthp1IUgAYAEeEX/8kizPszifNjUMwtq96bO3tzZ3dnZMn83a/XJF0aeP7KtLaQhBAsDqa7fbn9kJqNePT04UB4CHyNKkNxg97rV5Uet0b16+fKmMAEAV94L677Na4o8AAEDZzTD++Fn/avrs/vuPi7ca9UajvtlobG5uGg+PlRd/Mk5EnKTKUh5CkACw+j57Yf30sERlAHigR0yEfV8QxmaFAACqJUuT7k0vCKNC/BEAACi3eccfv+R/TJ8dT+93ev36xkajvtFo1Hd3dkyfzeqJ0/Q3H2GJhCABAAD4muFgED35csab276PvQCAShB/BAAAqmJZ8cfPH0zl+fT261CRvf5339U26/XNzcb21ubU3rPn+otK/659+inB9JFgPPLeLgkhSAAAAL4oS5Ob2/7T2zEpNgBQfnenD6MkFX8EAJitSRiaJATmcfxSkvjjZ00PrO6Givx1zrpO7/D53vHJib6jisbj4LOPh2EkBFkScwxBNpuXS9+8Xn84GI7uP3L04sCbDwAA4IE63Zt8RiGAIIxdEwkAlFP5Tx8CAFRRnmd3dwpXmYDjl1otzTLdR1V/7+L4mx5n8eYYgozT5f/x+mWs3X/9yEffAwAA8AXDwSAIZ3kA37np/04IEgAo2Q7PaDwWfwQAmLlgPOoNfh2xKAjjm27XCHAwE5dXHUWABYuT9JseZ/FMhw0AAMDnzWQi7PuyPG+32+fn52oLACzdcDAYDEdluJgfAGD19G97vcHo/viP/VGQpOnLly8VB4BqydLkS1NmTR+Pwsn2zq4qLZ0QJACsmptu9yGDyU+f02637z+yu7Ozf3CggADcmf6byOcwT9F4EpkUGwBYLvFHAIC5uul2+6Pg08eDMG61Wudnp/XGpioBUBWj0egrPw3DUAiyDIQgAWDVTMLoISdy8uJ9DOWjB4UgAbgTjEef/puYld7tQAgSAFiKm253OA7mcaUHAAAf9rg+m4C8E8Zps9V+/epcDhKAqgij+Os/PVSjEthQAgAAAD7SuenPr/E4zTrX14oMACzSTbf75u1FfyQBCQAw352uryQg72R5/vPlu2A8Ui4AKiGK00f/lIUxEiQAAAD/SrvdzvJ8rosYTcL9cGKGCABg3rI06d70JmEk+wgAMG8PSUDeme6btbu981rNbCEAlN/Xz5jM+3wKD2QkSAAAAP5FFE7mNxH2B0VR63R7qg0AzE+WJu12++Ly3XTfRgISAGDerq6uHpiAvFMUtatO76bbVToAymw4GMzkOcybECQAAAD/YmHZRJNiAwBzEoWTD/HHQvwRAGD+Wq1WEMaPeGF/FEz33BQQgNKahOFMnsO8mQ4bAACAX3Wur+M0W9jiRpPwKE3qjU2VBwBmIgonN73bME6VAgBgYVqt1lN2wMaTaNrCq1evVBKAEkqSdCbPYd6MBAkAAMB7UTgZTRZ6teL7aY/aHZUHAGayJ9NqtS6vOhKQAACL9MQE5J1pC28vmlmaqCcAZZNkvz1yxCJHl+BLjAQJAADAe51ub/HzRUZJ2r/tHb44Un8A4HGGg8FgOHK+Acrm63ObruFAKWmWfb0m5+fn3jZAtWRp0r6e2SUoWZ43W+3T48O9Z8/VFoCSCMajB543mT7Tv7DlemoIcjgYdHr9Cm3wdG0/u8Jbjfrr1997QwAAAOupf9tbVnSgNxg9f/7cpNgAwLcSf4QyG08iRbgvL9QEWClZmjRb7SzPZ9lmnre7vfNaTYgEgJIIgsnDn+n/13IZCRIAAGDdZWnSG4yWtfSiqLWvO69evdIRAMAD3XS7kzASfwQAWIp5JCDvvP+YqNs7CKPjkxN1BmDp4gePYR+v32j3ZSMECQAAsO6u2p3FT4R9Xxinw8Fg/+BAXwAAX3fT7Q7HQV6oBADAcswvAXmnKGr9UZDn+enZmWoDsFxJms78mczJhhIAAACss/5tLyrBFYo3t/0sTXQHAPCVnZY3by/enxGXgAQAWJJ5JyA/GAZhq9VScACWKAonD/8IYvrM6fMVbYmEIAEAANZXlia3y5sI+768qHW6N3oEAPiS0Xgi/ggAsETBePTz5bsFJCDvhHHabF66aBaAZRmPg7k+n9kSggQAAFhfne5NecIEQRgPBwOdAgAAAFA2wXjU7vYW/DlSnGbNVtvAWgAsxbfOcB3FsaItUUMJAACgDK6urtI0e0oLr19/r4x8k+FgEITlOia/ue3vHxzoGgAAAIDyuEtAFsu4kjbL81a7c35ytPfsuY4AYJGi+NtCkEmaK9oSCUECAEAppGkWPy0ECd8kS5Ob237Z1iovau12+/z8XAcBAAAAlMESE5B3pouersBRkhy+ONIdACxGliZZ/m2hxunzp6+qNzZVbylMhw0AALCOSjUR9n3jSRSMRzoIAAAAYOmGg8FyE5B3pitw0x/ddLt6BIDFGI1GC3sVM2EkSAAAgLUTjEdlmwj7vs5N/3cLmeFoWocs+9qlnFlmfNYSGQ4GX3/C3t6uq2wBAABgVm663f4oKM/6TFcmiuNXr17pGgDmLYqTR7wqjOJDtVsSIUgAAIC107npl3n1sjxfzKTYvduBaeir9L7t/cb79rRW2z8QggQAAIAZKFsC8k4Yp5eXrZfnpy6DZLX99OZCEWC5kiR9xKtSZxyW56EhyGbzcrXPDE237kv/RX7/4w/eKAAAwMpot9tZnpd8JceTKAon2zu7+gsAAABgwcqZgLwTJWmz1X796lwOEoD5eVxMzrALS2QkSAAAWBHtdntBRxH1+vHJiYJXVDAejSdRJVa10+29fi0ECQAAALBQ/dteaROQd7I8v7h89+r81AW0AMzDcDB4ymv3Dw7UcPGEIAEAYEUsLNm21airdnX1bgdVWdU4zTrX16dnZ3oNAAAAYGGiOCn/ShZFLY4TIUgA5mEShk95rRDkUmwoAQAAwJroXF9Xay6G0SSMwomOAwAAAAAAFiN9wpmU1IzYS2IkSAAA1lEwHmVZXqpVyvJCvzBXUTgZTcJqrXNRmBQbAAAAAABYnDhNl/JankIIEgCAddS7HcSuxGLNdLq9ooJR2+mvav+2d/jiSA8CAAAAAABzFYxHTzmZMn3ttIW9Z89VcsGEIAEAAFZf5SbCvq83GD1//rze2NSPAABQHldXVyZ6m6Fm8/IrP339+nslAgCABQjD6IktBMFECHLxhCABAABWXJYmlZsI+76iqF21O99//0pXAgBAeaRpZo6FGVJMAAAogyiOn9hCYkbsZdhQAgAAgNV21e5UcSLs+6Ik7d/2dCUAAAAAADA/cZIuvQUeQQgSAABglfVve9FKHG/3BqMsTXQoAAAAAAAwD1E4yZ88qMS0hWk7irlgpsMGAAC+TZxmP725+KaXnB4d7h8cKN0CtNvt8SRayU0ritrb5jtvLQAAAACg6oLxKMtydYCyCcNwJu2Mx8H2zq56LpIQJAAAAAAAAAAALEjvdhCnmTpA2YRRPJN2ktSM2IsmBAkAVFizeVndld/d2T4+OdGJAAAAAAAAAEsXxWmp2uHhHhqCfP36+88+vjJTrW016l/aRgCgtCp9kdxm5go/AAAAAAAAgOXL0iTLZzNP/bSdaWv1xqaqLsyGEgAAAAAAAAAAALC2gmBS2tb4TabDhser9Bys9xkGFQBgZRwe7O/u7NzdH43H4SpOuHB6dPjh/t7erk4HAAAAAACeaBKGs21t/+BAVRdGCBIer9JzsAIAsJK2d3ant3uH6ysYgvSpAQAAAAAAMFtJkpa2NX6T6bABAAAAAAAAAABYX7MdCs3AagsmBAkAAAAAAAAAAMCaCsajmbc5HAwUdmFMhw1UW7vdXtait7c2D18c6QIAAAAAAAAAgOoKgsnM24yiaF9lF0UIEqi28SRa4qKDSfjq1Su9AAAAAAAAAABQUXGSVqJNvsR02ACPF8Zps3mZpYlSAAAAAAAAAABUUZymlWiTLzESJMAT/2llP1++Ozs52nv2XDUAAAAAAAAA1tlNt5tm2def85tPABYpCidFMftmp21OW97e2VXhBRCCBHiqvKi1u72jJDl8caQaAPD5o8coqg0GHz24tbXpwA8AAAAAgFUyCaM4lXGEKhmPg/m17FzYYghBAsxAUdRu+qMoTs7Pz1UDAD41DMLp7aMHn+1unzvwAwAAAAAAYHmiOK5cy3xkQwkAZmU8iVqtVpYmSgEAAAAAAAAAUH5xklauZT5iJEj4jCicxPEa5diGn8xN+Zv29nbrjU1vlU+FcdpstV+eHRvQGAAAAAAA+Kyf3lxUZVV//+MP+gsAWGFZmuTFvBqftjxtX8BmAYQg4TP6g+F4Eq3P9nZ6/W99yWmttn/gb/QX/kHmeavdOT852nv2XDXg0Sr0ISAAAAAAAAAAVTQajebd/uGLI3WeN9NhA8xeUdSuOr2bblcpAAAAAAAAAADKKYziSrfPHSFIgHnpj4Krqyt1AAAAAAAAAAAooTTN5tp+FKeKvABCkABzFIRxs3mZpYlSAAAAAAAAAACUSjznEGSW54q8AEKQAHP/f9lstYPxSCkAAAAAAAAAAEpiOBiszFLWnBAkwNxled7u9vq3PaUAAAAAAAAAACiDSRiuzFLWXEMJABagKGo3/VGSpKdnZ6oB/I+d3ajZvFyHLd3Y+O787LTe2NTpAKynUl3mu39woEcAqKgonPQHw0e//PBgf3tnVxkBAAD4IEnSlVnKmhOCBFicYRAmrZYkEHAnL2pxmq3Jxl5cvnu+uyMIDsB66vT65VmZm9v+/rO945MT/QJA5cRxMp5Ej3757s6OECQAAAD3JVm2MktZc0KQAAsVxmmz1X796lwOElgrRfE+CB41L09PjpxzAoAlyotafxRMwuhg/7lRIQEAAACeYjgYfDrLbSrtBBURjEdFsYgFTZcyXdbes+dqPj9CkMBjjMbjT3fmeKAszy8u352fHPkPB6ybOM1a7c7ezvb5+blqAMBy/yl3ev3BcCQKCQAAAPBokzB8ymjlwHIFwWSRyxIRmSshSOAxwjit1VJ1eLSiqLW7vYMwMgkdsIZ/AMeT6O1F8/T40I4+ACzXXRRyNB4fH70wVDMAAAAAsFbyxYwDufBlrSchSIDlKH6ZhC5J05cvX6oGsG6yPL/q9PZG4+++++6hu631uuA4AMxDGKeXV52drYYoJAAAAMF4FEZJJVZ1NB6b3AAAuLOgEOTm5uYf//CXLw4Pn9hOkqR//Td/OxgM9RywIkeSYdy5vj49O1MKYD3/Bj78yVuNuooBwPyEcdpqd/Z2tk+Oj+qNTQUBAABYQ/3bXm8wqspIVdMj2bcXzdevzh3GAgAbi1nMTBKQtfdhysZf/fEPe3uGJQBWh0GPAQCAMpgemown0cXlu3a7naWJggAAAKyV6cHgTX9UrdNWWZ5PD2OD8Uj3AcCaW9BIkDNJQN7Z3Gzs7e4GweT+g7/709d/+sOfTu/8fPHz25+b+hUAAADgEe6ikJPLd/vP9o5PThQEAABg5WVpctXuREla0cPYq07vMIwcwwLAOmuswDb87k9f/6f/9B/v7nc6XZ0KAAAA8BR5UeuPguE4EIUEYMF+enOhCACwSMF4dN3t5RWft2x6DBvF8fnZqamxAWA9bVR9A+4nIKdSszUBAAAAzMJdFLLZvBwOBqoBAACwem663Xb1E5B3wjhtttpRONGtALCGqh2C/CgB+c9v3v7TT290KgAAAMCsxGnW6fVFIQEAAFbM1dVVfxQUxepsUZbnrXbH0SsArKEKT4f9UQIySdIgmPzP//bf3H2bpsm7q/b0EX0MAAAA8ER3UcjReHx89GJ7Z1dBAAAAqit7fzL9enqgt3qbVhS16dFrFEWnZ2c6GgDWR4VDkPcTkFObm42/+PN/d/+R//U/1P7xv/x///W//XfdDAAAAPB0YZxeXnV2thqikAAAABUVjEfXqzIF9pcMgzBptc7PTuuNTT0OAOtgY7U37y/+/N/9L3/x57oZAAAAYFbCOG21O+12O0sT1QAAAKiQm263veoJyA+Hrs1WOwpNHQkAa6HCIcgkSR/ytH/7b/6nvT0jEwAAAADMTFHUxpPo4vKdKCQAAEBVXF1d9UdBUazL9mZ53mp3hoOBrgeAlVfh6bD/+m/+9q/++IfNzV83IUnS6SODwXB6/+Bg//6P/uTl+T/99EZnAwAAAMzQXRRycvlu/9ne8cmJggAAAJRTlibvrq7jNFvD49ZOrx9F0enZmbcBAKywCo8EORgM//pv/vbDeJCbm42/+uMfDg72P/zowzMbjU09DQAAADAPeVHrj4I3by9uul3VAAAAKJtgPPr58t0aJiA/GAZhq9UyjwEArLCNSq/9pznIP3n58sOP9C4AAADAYtxFIZvNSxONAQAAlMdNt9vu9vJi3esQxmmz1Y7CibcEAO12u9m8nN4mYbSwhU6XdbfQ6dJ1wTxsVH0DPspBAgAAALAscZp1en1RSAAAgDK4urrqj4KiUIn3sjxvtTsOVwGo/fIx5vS2yIsEpsu6W6jiz0ljBbbhLgd5Nwbkzc2NTgUAAABYorso5HA0Pjl+sb2zqyAAAAALlqXJu6trSYuPFEVtergaRdHp2ZlqAKyt3Z2d8SRa4tJ1wTwsKAT5z2/e/tmPv5tVU53ux0nHwWBo/msAAABgtq6urlJnjB4rStLLq87OVuP4SBQSAABggYdj4eRdu2MK7C8ZBmF2dfXyl1GWAFhD+wcHnV5/iUvXBfOwoBDk3/39PwwGg0Zj84ntpGnyTz+90W0AAADAAqQmKHmyMH4fhXy2u31yfFR/8kdDAAAA/KY4TiQgf/N4XxEA1tlWo76UD36ny1X8OVncdNjCiwAAAADraTyJgst3ezuikAAAAADAkm1uNpYSgpwuV/HnZEMJAAAAAJi3ongfhby4fHfT7aoGAAAAALAsuzs7a7XcdSAECQAAAMCCFEWtPwrevL0QhQQAAAAAlmJvb3etlrsOjLEJAAAAwELlv0QhR0F4dLi/f3CgIAAA3yQYj3q3g6884fXr71UJAAC+pN7YrG9sZHm+0IVubEyXq/hzsqAQ5Obm5n/83/7D9OsT20mS5O/+/h+mX/UcAAAAQKVled7p9QfD0cH+c1FIAIBv2I/K8jjN1AEAAB5te6sRhPGCl6js87Og4v7xD3/54vBwJk09e7b3N3/7f8pBAgAArKd2uz2rptLMWUNYvjjNOr3+cDQ+OX6xvWM6GACAGWg2L+fR7OZm4/z8XHkBAFgBO9tbCw5BTpeo7POzoBDkrBKQd00dHux3ujc6DwAAYA2NJ5EiwOqJkvTyqrOz1Tg+EoUEAHiqOY0TOW327UXz9Phw79lzRQYAoNKeP39+0x8teInKPj+LHmYzCILROHjEC7e2NmeYpAQAAACgbML4fRTy2e72yfFRvbGpIAAAZZPl+VWntzcav3z5UjUAAKiuemNz47taXixocdNl+cBzrhYdgvznNxf/9b/990e88PTk+P/44/+uwwAqKgon/cFw5s1ub20evjhSXgAAWCXjSRRcvtvbEYUEACipBc8bCAAA87C12QjjdGHLUvC5Ul8AFiGOk3nMXDltM4xi1xwDAMCKKYpfo5AHz/aOT04UBAAAAGB9/PTmolTr8913tfOTo71n5jJeNfV6vVZLF7gs5mhjVTdsc9M4AQBrIQjjy8tWliZKAQAAK6Yoav1R8ObtxU23qxoAAAAALEVR1K46PZ9QQZmtZghyc3Pzj3/4S70LsCaiJG222sF4pBQAALB68l+ikG8vmsPBQDUAAAAAWIr+KOhcX6sDlFMlp8P+9//+L+L4ayN+PX+2N/Xh23dXV3oaYLVled7u9k6yfP/gQDUAAGAl9/k7vf5gODrYf263HwAAAIDFGwZh0mq9evVKKaBsKhmCfHF4+PAnt687g8GwbJsQjEdZlq/ne65e39h79tzvHjBzRVHr9PpRFJ2enakGAACspDjNprv9w9H45PjF9s6uggAAAACwSGGctlqt87PTemNTNaA8Gqu9ebf9/v/1f/8/JVyx3u0gTrP1fM9tNepCkMD8rOfFN+12+/63afbIfzFJkt5vqlGvH5+ceFMBAFA2UZJeXnV2thrHR6KQAAAAACxUGKfNVvv1q3M5SCiPSoYgb/v9r0+Hfefdu3cXP18mSaKbAdZtp/PtRXOtdjrHk2gm7cRpdj+jv9WoezsBAFDmPf/Lq86z3e2T4yOfOAMAAACwMFmeN1vtl2fHLtCFkqhkCPI//+d/7HRvdB4AX9npvLh8d35yZOhZAABYbeNJFFy+29sRhQQAAABgcbI8b7U7TklDSSw6BPlnP/5wevqYiTW3tnyKDbAgw8Gg0+tXfSuKotbu9g7CyITOAACw2qY7/3dRyINne/b/AQAAAFiMu1PSR0ly+OJINWC5Fh2C3PuFugOwmJ3O/ihIs+z8/Fw1AABgHfb/h+Ngf9WjkFmaBMFkrTp3/+DAOxwAAAAooaKo3fRHWZa7NBeWa0EhyH9+8/bPfvzdTJq67ff7g6GeA+CBxpPo8rL18vzU1HgAALDy8l+ikKMgPDrcX9XkXBBMVmDw/m8iBAkAAACUmaF5YOkWFIL8u7//hyRJDw+f+nllkiS/NJXoOQAeLkrSZqv98ux4e2d3JTfw2e723Z3xJHp6axvf1XZ33jfYqNe9eQAAqKIszzu9/mA4Oth/Lj8HAAAAwLyNJ1Hn+vr07EwpYCkWNx32//uP/0W5AViWLM9b7c7Ji8OVPAP64aKin95czGDnoF53lRIAACsgTrNOrz8cjU+OX6zqBVEAAAAAlEReFIoAy9JQAhYszbJ2u/2kd229fnxyopLAt5ruc3Z6/SRJ/A0BAID1ESXp5VVnZ6txfCQKCQAAAI/UbF7Gabb01dhq1F+//l53APARIUgWLS+eOlvrdLdGGYFH64+CKI5fvXqlFAAAsD7C+H0U8tnu9snxUb2xqSAAAAAAACtDCBKgekpyoVV1hXH69qL5+tW5c58AALBWxpMouHy3tyMKCQAA1XDT7U7CaFlLbzTqL1++1AsAAOUnBAnAOsry/OfLd2cnR3vPnqsGAACsj6L4NQr5fHfn9OxMQfjIT28uVn4bf//jDzoaAKiKNMuMCgEAwG/aUAIA1lNe1NrdXv+2pxQAALBuiqI2DMI3by9uul3VAAAAAACoNCNBArC+iqJ20x9FcXJ+fq4aAACwbvKi1h8FxycnSgHwCFE46Q+Gj3hho173txcAAACYISFIANbdeBK1Wq3zs9N6Y1M1AAAAAB4ijpPxJHrEC7caddUDAAAAZsh02ABQC+O02WpH4UQpAAAAAAAAAAAqRAgSAN7L8rzV7gTjkVIAAAAAAAAAAFSFECQA/Kooaled3k23qxQAAAAAAAAAAJXQUAIAuK8/CqI4fvXqlVIAAACsm9Ojw7s7vf4wy/OV2a76xsbR4b7+BQAAAGAlCUECwMfCOG02L//k5Vm9sakaAAAA62P/4ODuzmA4ylYnA1mrb3z3YdOooqurqzTNyrZWWV48+oXDweD9O7O+sffsuf4FAAAAnkgIEgA+I06zZqt9enzos3gAAABgudI0i8sXgny0LM87vf70zlaj7oMXWENROOkPhlVc892dHRcVAABAOQlBAsDnZXne7vaOkuTwxZFqAAAAAAA8XRwn40lU0ZUXglxbw8FgEoZf+unhwf72zq4qAQAskRAkAHxRUdRu+qMkSU/Pzsq/tnczST1dnGZZmpgKHAAAAAAApiZh+JXw7u7OjhAkAMByCUECwG8YBmHSap2fnZY8Fzgaj2fVVK93W4ncJwDAv9qH6Q8Hw9Fs20yyTGEBAADWU5pl7Xb7/bFhkqoGAECZCUECwG8L47TZar9+dV7aHGSWJtOVnFVrQRjrdACgcrI8z3JlAAAAYDbyovaQ2ds7vf709tkfnR4dmkUdAGABhCAB4EGyPL+4fHd+crT37HkJV6/Xu53txgbjUTm3lLWVZFmzeTnbBlUVAKAShoPBQ55Wr284igEAAACANSQECQAPVRS1q07vMIyOT07Ktm7jSTjbBvuDodOHlO0XME7FFgGAVfPAeN99URStW5W+NKzOR7YadUcxAAAAALCGhCAB4Nv0R0GSpi9fvizPKg0Hg7yYcZtRkmZpUtrpvwEAYDU8MN4HAAAAAMCXbCgBAHyrIIwvL1tZmpRkfUbj8czbLIpavz/Q1wAAAAAAAABAmRkJEgAeI0rSZqt9eny49NnWsjQJ43QeLY+C8PhEVwMAAAAAD5KlSRBMvv6cKIoUCgAAmC0hSAB4pCzP293eea223Bzk/MZrnG5gMB4tPeUJAAAAAFRCEEw6vb46AAAACyYECQCPVxS10ThYbkxwFITza7w/GApBAgAAAMByNZuX97/N8kJNAAAAPhCCBIAKC8ajLM/n136UpIoMAAAAAMsVp5kiAAAAfMmGEgBAdfUHw7m2XxS1m25XnQEAAAAAAACAchKCBICqytJkASM1TsJIqQEAAAAAAACAcjIdNgBUVb8/KIq5LyVOsyicbO/sKjgAAAAAAMC3ajYv4zQr7er9/scf9BEwWzfdbpo96e/e4cG+M9R8EyHIX2V5MRwMFrk4NQfgiUZBuJgF3fYHL+1iAgAAAABrbBJGzealOgAAPGTH6Ynh792dHSFIvokQ5K+yPO/0+upQkc6ae2I1yzJ1BkouGI+m/7wWtJMaxQoOAAAAAKyzvKiVeSA3AAB4tHa7PZ5E817K6dHh/sHBnBoXgqR6JFYBpoaj8cKWVRTvRyw/PjlRdgAAAAAAAACgVIQgAaCSFjw64ySM1BwAAAAAAFhJN93u/E6FJOYhBIA5E4IEgEoeihfFQpcYp1kUTrZ3dhUfAAAAAABYMWmWmfIeAKpLCBIAqmcp4zL2B8NzIUgAAKCs4jT76c2FOgAAAADAutlQAgColiicLOViRDNiAwAAAAAAAABlYyRIACijLE2CYPLZH43G46WsUl7UOtfX29vbn/3p/sGBXgMAAAAAAGB+srwYDgYPfPLW1ua2Wc4A1oMQJACUURBMOr1+2dZqGITT22d/JAQJAAAAAADAXGV5/vAzaM92t8+FIAHWg+mwAQAAAAAAAAAAgEoyEiQAAAAAAAAAzFin1y/hpE8AlEq73V69jUqzTM+yYI1m89K7FgAAKI9gPMqyfOmrsbW1uW2qFABgJSRZ9sTPgUuyFboSAACAFTOeRIrAnZ/eXKz2Bvb6w8FwNKfGG3HqkyMAAKBMh0C3gzIcpzzb3T4XggQAVkJR1HwODAAAAMASZXk+v1FQNtQXAAAAAAAAAAAAqCIhSAAAAAAAAAAAAKCShCABAAAAAAAAAACASmooAQCU0N7e7um9b0fjcRinpVrDna3G82fP9BQAAAAAAAAAsERCkABQRvXG5v7B5odvJ2FYq5UrBFmv1/cPDvQU8BRZlg0Hg888nhdlXr1l2dvbnf538LYBAAAAAACA+4QgAQCA5QjjNIz7Vu+BTmu1+/l4AACAD66urtI0m0lTuzvbxycnSgoAAECFCEECAAAAAABUWJpm8YxCkJtZpp4AAABUy4YSAAAAAAAAAAAAAFUkBAkAAAAAAAAAAABUkumwAQAAAAAAAACAOZqEUbN5qQ7APAhBAgAAAAAAAAAAc5QXtTjN1AGYByFIAAAAAAAA4Bv89OZCEQAAgJLYUAIAAAAAAAAAAACgiowECQAAAAAALFqWF8PBoIQrFoxHvdtBtYqZZGYVBAAAYH0JQQIAAAAAAIuW5Xmn1y/jimV5nMoUAgAAQGWYDhsAAAAAAAAAAACoJCFIAAAAAAAAAAAAoJKEIAEAAAAAAAAAAIBKEoIEAAAAAAAAAAAAKkkIEgAAAAAAAAAAAKgkIUgAAAAAAAAAAACgkhpKAAAAAAAAAMCn2u32EpeeJKkuAADgNwlBAgAAAAAAAPAZ40mkCAAAlJzpsAEAAAAAAAAAAIBKEoIEAAAAAAAAAAAAKkkIEgAAAAAAAAAAAKgkIUgAAAAAAAAAAACgkoQgAQAAAAAAAAAAgEpqKAEAAAAAAAAAwBpqt9sPeVqaZWoFQGkJQQIAAAAAAAAArKPxJFIEAKrOdNgAAAAAAAAAAABAJQlBAgAAAAAAAAAAAJUkBAkAAAAAAAAAAABUUkMJAAAAym80Hk/C8JtekiSpugGUVpYm7euOOgAAAAAAPJEQJAAAQAWEcVqrCTUCrIgsTZqtdpbnSgEAAAAA8ERCkAAAAACwOMF41O72ikIlAAAAAABmQAgSAAAAABbkptvtjwJ1AAAAAACYFSFIAAAAAFiEq6urIIzVAQAAAAC+otPrT2/qwMMJQQIAAADAfGVpctXuREmqFAAAAAAAsyUECbBkSZK22+1vekmaZeoGAABQFVE4ubq+yfJcKQAAAAAAZk4IEmDJ4jSb3tQBAABgJQXjUbvbKwqVAAAAAACYCyFIAAAAAJiLm263PwrUAaAMRuPxJAwf8szMNCwAAABQKUKQAAAAADB7rVYrjFN1AD7S6fWnN3VYvF/+JvuzDAAAACtICBIAAAAAZilLk3dX13FqIDEAAAAAgLkTggQAAABgfTWblzNvM82yvFBaAAAAAIBFEIIEAAAA4P9n745a2gbDMAwXKbgdqAg7HcP//6NERMEg25quNE2+N7XiiQiyupA1r70uelJaaPu0J4WbfMfL9RoBAAAAGC4ilnVtBzgIESQAAAAAAAAAAMC/a9rStAs7wEGcmAAAAAAAAAAAAADISAQJAAAAAAAAAAAApOQ4bAAAAAAAAAAAABhFRCzr2g7jEUECAAAAAAAAAADAKJq2NO3CDuNxHDYAAAAAAAAAAACQkitBAsDBXN/c5n3zq/Vm//d/9eO7rxsAAAAAAJiC6LdvziSNCLMAQF4iSAAAAAAAAADgWETfP/5yJikAfB6OwwYAAAAAAAAAAABSEkECAAAAAAAAAAAAKYkgAQAAAAAAAAAAgJREkAAAAAAAAHxAlC76rR0AAACYgrkJAAAAAAAA2NOyrn/+XmggAQAAmAgRJAAAAAAAAH8XpXuoHjddMQUAAADTIYIEAAAAAADg2brZ3N3dv/doF7F1AUgAAAAmRgQJAAAAAADAs347a0vYAQAAgEROTAAAAAAAAAAAAABkJIIEAAAAAAAAAAAAUhJBAgAAAAAAAAAAACnNTQAAAAAAAAAAwGfSdaWqqrFfws4AUyCCBID/ZPcva7XeHOdnv765fX332+XF2fm5nwQAAAAAAAAjaUvsbnYAOAaOwwYAAAAAAAAAAABSEkECAAAAAAAAAAAAKYkgAQAAAAAAAAAAgJREkAAAAAAAAAAAAEBKIkgAAAAAAAAAAAAgpbkJAGCIritVVe35THO9+LNarZvGDgAAAAAAAADAQCJIABikLbG72eFDmrbMZpJQAAAAAAAAAGAox2EDAAAAAAAAAAAAKYkgAQAAAAAAAAAAgJREkAAAAAAAAAAAAEBKIkgAAAAAAAAAAAAgJREkAAAAAAAAAAAAkJIIEgAAAAAAAAAAAEhp/vXLqRUAAAAAAAAAAACAdJ4EGAD0UiXBHYVPBAAAAABJRU5ErkJggg==)\"></div></div>", + "meta": { + "options": { + "id": 760, + "assetType": { + "id": 197, + "name": "htmlblock", + "displayName": "HTML Block" + } + } + }, + "availableViews": [], + "data": { + "email": { + "options": {} + } + }, + "modelVersion": 2 + }, + "8uflrc8ao4r": { + "assetType": { + "id": 223, + "name": "referenceblock" + }, + "design": "<div class=\"default-design\"><div style=\"width:100%;height:150px;background-size:cover;background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAADawAAAEtCAIAAADRXFFBAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAALyhJREFUeNrs3ftvI+l+J2aOSF27JbWu7Z72nPEJdrOws5ss9hcj58R/vWEDQYLAhjdeZHfhcbeGYosiRfFWrHuFPZpty30btcRLFfk8IASKIt+q+r6UVMX61Pt+13r3rgYAAAAAAAAAAABQNY2rd1eqAAAAAAAAAAAAAFTOhhIAAAAAAAAAAAAAVSQECQAAAAAAAAAAAFSSECQAAAAAAAAAAABQSUKQAAAAAAAAAAAAQCUJQQIAAAAAAAAAAACVJAQJAAAAAAAAAAAAVJIQJAAAAAAAAAAAAFBJQpAAAAAAAAAAAABAJQlBAgAAAAAAAAAAAJUkBAkAAAAAAAAAAABUkhAkAAAAAAAAAAAAUElCkAAAAAAAAAAAAEAlCUECAAAAAAAAAAAAlSQECQAAAAAAAAAAAFSSECQAAAAAAAAAAABQSUKQAAAAAAAAAAAAQCUJQQIAAAAAAAAAAACVJAQJAAAAAAAAAAAAVJIQJAAAAAAAAAAAAFBJQpAAAAAAAAAAAABAJQlBAgAAAAAAAAAAAJUkBAkAAAAAAAAAAABUUkMJAAAAAADg4drt9ngSTe88290+Pz9XEAAAAIAlMhIkAAAAAAAAAAAAUElCkAAAAAAAAAAAAEAlCUECAAAAAAAAAAAAlSQECQAAAAAAAAAAAFRSo7Rr1mxexmn26eO///EH3QYAAAAAAAAAAAAYCRIAAAAAAAAAAACoJCFIAAAAAAAAAAAAoJKEIAEAAAAAAAAAAIBKEoIEAAAAAAAAAAAAKkkIEgAAAAAAAACYvSicKAIAMG9CkAAAAAAAAADA7MVxoggAwLwJQQIAAAAAAAAAs5fnmSIAAPMmBAkAAAAAAAAAzF5kJEgAYP6EIAEAAAAAAAAAAIBKEoIEAAAAAAAAAAAAKkkIEgAAAAAAAACYiyicKAIAMFdCkAAAAAAAAADAXMRxoggAwFwJQQIAAAAAAAAAAACV1FACAAAAmLlm8zJOM3X4yOnR4f7BgToAAAAAAACzYiRIAAAAAAAAAAAAoJKEIAEAAAAAAAAAAIBKEoIEAAAAAAAAAAAAKkkIEgAAAAAAAACYvaIo8jxTBwBgrhpKAAAAAAAAAADMXJpm0XeJOgAAc2UkSAAAAAAAAAAAAKCShCABAAAAAAAAAACAShKCBAAAAAAAAAAAACqpoQQAAADwFMF4lGX5Rw9meaEyn4qiqDYYfPTg3t5uvbGpOAAAAAAAwCMIQQIAAMCT9G4HcZqpw0MMg3B6++jB01pt/0AIEgAAAAAAeAzTYQMAAAAAAAAAAACVJAQJAAAAAAAAAMxFkqSKAADMlRAkAAAAAAAAAAAAUElCkAAAAAAAAAAAAEAlCUECAADwVFmaKAIAAAAAH8nyQhEAgHlrlGElfnpz8cQnP9vdPj8/150AAACLNxwMbm77P/7uB6UAAAAA4L4sz+sbdXUAAOaqoQQAAAA8WpYmN7f9vKi12+31uTit2byM00zvz0qn15/ePnx7enS4f3CgLAAAAAAAwEOYDhsAAIDH63Rv7iY1Gk+iYDxSEACAr+jf9qJwog4AAABQUcPBQBFKSAgSAACAxx/qB2H84dvOTV9NAAC+tOPUbF7e9EdxnKgGALBWksx8GgCsjsHQeBBlZDpsAAAAHqnXH97/NsvztZoUGwDgIYaDwWA4ilPn/gGANVUUagDAiojCyfQAf/p1e2dXNUpFCBIAAIDHaLfbWZ5/9GAQRg7+AQDuTPeLbnq3YZwqBQAAAKyAMAynX8fjwHmQshGCBAAA4JsF49F4En36eFHUOt3e69cO/gGAtSb+CAAAAKsnjOLp1yR1vF86QpAAAAB8s85N/0s/itOsc319enamSgDAGsrSpHvT++zlIgAAAEClRb9c7hi56LF8hCABAAD4Np3r608nwr5vNAn3TYoNAKyZu/hjEEZFoRgAAACwggf+dydHpl+n9+uNTTUpjw0lAAAA4OGicDKahF9/zt2k2GoFAKyPzvX1xeW78UQCEgAAAFZTEEw+3B+NRgpSKkaCBAAA4Bt0ur2HnNqP06x/2zt8caRiAMBqu+l2h+Mgl30EAPhEliZ3dyJzhsCyTX8Nb3q3Gxsb9Y2N7e3t/YMDNYFvNQn/ZYSIKE4UpFQWGoIcDgbz2nnKss82vre3a+hRAACAWelcX8dp9sAn9waj58+fOygDAFbYeBIpAgDAl3wYMSuOEyFIWJa7+GMYpx8eGQZhp9ff+K622Ziq7+7sbG1t+iWF35Qk6WfvUwYLDUFO/4bOqeXpH+sw/kzjp7Xa/oHzbQAAADOQpclvToR9X1HUrtqd779/pXQAwCoZDgZhZLwHAACg7D6NP96XF7UoSae3u4u7vvuutlmvb242GvX6zs723rPnCggfuT9IxMMHjGAxTIcNAADAg1y1O8U3zvMYJWmlJ8Vut9uGd1q8Tq//2asof//jD4oDwHLddLujIMzyXCngiaJwEq/Z5HH1+oYkAQCwyN2tr8QfP6so3oe67nJd/VFQ6/TqGxubjemtsb29bSJW+HSO4ukjZpYvDyFIAAAAflv/thc9anKHW5NiAwDVd9PtDsdBXqgEzOj4YjBct8uNthp1IUgAYAEeEX/8kizPszifNjUMwtq96bO3tzZ3dnZMn83a/XJF0aeP7KtLaQhBAsDqa7fbn9kJqNePT04UB4CHyNKkNxg97rV5Uet0b16+fKmMAEAV94L677Na4o8AAEDZzTD++Fn/avrs/vuPi7ca9UajvtlobG5uGg+PlRd/Mk5EnKTKUh5CkACw+j57Yf30sERlAHigR0yEfV8QxmaFAACqJUuT7k0vCKNC/BEAACi3eccfv+R/TJ8dT+93ev36xkajvtFo1Hd3dkyfzeqJ0/Q3H2GJhCABAAD4muFgED35csab276PvQCAShB/BAAAqmJZ8cfPH0zl+fT261CRvf5339U26/XNzcb21ubU3rPn+otK/659+inB9JFgPPLeLgkhSAAAAL4oS5Ob2/7T2zEpNgBQfnenD6MkFX8EAJitSRiaJATmcfxSkvjjZ00PrO6Givx1zrpO7/D53vHJib6jisbj4LOPh2EkBFkScwxBNpuXS9+8Xn84GI7uP3L04sCbDwAA4IE63Zt8RiGAIIxdEwkAlFP5Tx8CAFRRnmd3dwpXmYDjl1otzTLdR1V/7+L4mx5n8eYYgozT5f/x+mWs3X/9yEffAwAA8AXDwSAIZ3kA37np/04IEgAo2Q7PaDwWfwQAmLlgPOoNfh2xKAjjm27XCHAwE5dXHUWABYuT9JseZ/FMhw0AAMDnzWQi7PuyPG+32+fn52oLACzdcDAYDEdluJgfAGD19G97vcHo/viP/VGQpOnLly8VB4BqydLkS1NmTR+Pwsn2zq4qLZ0QJACsmptu9yGDyU+f02637z+yu7Ozf3CggADcmf6byOcwT9F4EpkUGwBYLvFHAIC5uul2+6Pg08eDMG61Wudnp/XGpioBUBWj0egrPw3DUAiyDIQgAWDVTMLoISdy8uJ9DOWjB4UgAbgTjEef/puYld7tQAgSAFiKm253OA7mcaUHAAAf9rg+m4C8E8Zps9V+/epcDhKAqgij+Os/PVSjEthQAgAAAD7SuenPr/E4zTrX14oMACzSTbf75u1FfyQBCQAw352uryQg72R5/vPlu2A8Ui4AKiGK00f/lIUxEiQAAAD/SrvdzvJ8rosYTcL9cGKGCABg3rI06d70JmEk+wgAMG8PSUDeme6btbu981rNbCEAlN/Xz5jM+3wKD2QkSAAAAP5FFE7mNxH2B0VR63R7qg0AzE+WJu12++Ly3XTfRgISAGDerq6uHpiAvFMUtatO76bbVToAymw4GMzkOcybECQAAAD/YmHZRJNiAwBzEoWTD/HHQvwRAGD+Wq1WEMaPeGF/FEz33BQQgNKahOFMnsO8mQ4bAACAX3Wur+M0W9jiRpPwKE3qjU2VBwBmIgonN73bME6VAgBgYVqt1lN2wMaTaNrCq1evVBKAEkqSdCbPYd6MBAkAAMB7UTgZTRZ6teL7aY/aHZUHAGayJ9NqtS6vOhKQAACL9MQE5J1pC28vmlmaqCcAZZNkvz1yxCJHl+BLjAQJAADAe51ub/HzRUZJ2r/tHb44Un8A4HGGg8FgOHK+Acrm63ObruFAKWmWfb0m5+fn3jZAtWRp0r6e2SUoWZ43W+3T48O9Z8/VFoCSCMajB543mT7Tv7DlemoIcjgYdHr9Cm3wdG0/u8Jbjfrr1997QwAAAOupf9tbVnSgNxg9f/7cpNgAwLcSf4QyG08iRbgvL9QEWClZmjRb7SzPZ9lmnre7vfNaTYgEgJIIgsnDn+n/13IZCRIAAGDdZWnSG4yWtfSiqLWvO69evdIRAMAD3XS7kzASfwQAWIp5JCDvvP+YqNs7CKPjkxN1BmDp4gePYR+v32j3ZSMECQAAsO6u2p3FT4R9Xxinw8Fg/+BAXwAAX3fT7Q7HQV6oBADAcswvAXmnKGr9UZDn+enZmWoDsFxJms78mczJhhIAAACss/5tLyrBFYo3t/0sTXQHAPCVnZY3by/enxGXgAQAWJJ5JyA/GAZhq9VScACWKAonD/8IYvrM6fMVbYmEIAEAANZXlia3y5sI+768qHW6N3oEAPiS0Xgi/ggAsETBePTz5bsFJCDvhHHabF66aBaAZRmPg7k+n9kSggQAAFhfne5NecIEQRgPBwOdAgAAAFA2wXjU7vYW/DlSnGbNVtvAWgAsxbfOcB3FsaItUUMJAACgDK6urtI0e0oLr19/r4x8k+FgEITlOia/ue3vHxzoGgAAAIDyuEtAFsu4kjbL81a7c35ytPfsuY4AYJGi+NtCkEmaK9oSCUECAEAppGkWPy0ECd8kS5Ob237Z1iovau12+/z8XAcBAAAAlMESE5B3pouersBRkhy+ONIdACxGliZZ/m2hxunzp6+qNzZVbylMhw0AALCOSjUR9n3jSRSMRzoIAAAAYOmGg8FyE5B3pitw0x/ddLt6BIDFGI1GC3sVM2EkSAAAgLUTjEdlmwj7vs5N/3cLmeFoWocs+9qlnFlmfNYSGQ4GX3/C3t6uq2wBAABgVm663f4oKM/6TFcmiuNXr17pGgDmLYqTR7wqjOJDtVsSIUgAAIC107npl3n1sjxfzKTYvduBaeir9L7t/cb79rRW2z8QggQAAIAZKFsC8k4Yp5eXrZfnpy6DZLX99OZCEWC5kiR9xKtSZxyW56EhyGbzcrXPDE237kv/RX7/4w/eKAAAwMpot9tZnpd8JceTKAon2zu7+gsAAABgwcqZgLwTJWmz1X796lwOEoD5eVxMzrALS2QkSAAAWBHtdntBRxH1+vHJiYJXVDAejSdRJVa10+29fi0ECQAAALBQ/dteaROQd7I8v7h89+r81AW0AMzDcDB4ymv3Dw7UcPGEIAEAYEUsLNm21airdnX1bgdVWdU4zTrX16dnZ3oNAAAAYGGiOCn/ShZFLY4TIUgA5mEShk95rRDkUmwoAQAAwJroXF9Xay6G0SSMwomOAwAAAAAAFiN9wpmU1IzYS2IkSAAA1lEwHmVZXqpVyvJCvzBXUTgZTcJqrXNRmBQbAAAAAABYnDhNl/JankIIEgCAddS7HcSuxGLNdLq9ooJR2+mvav+2d/jiSA8CAAAAAABzFYxHTzmZMn3ttIW9Z89VcsGEIAEAAFZf5SbCvq83GD1//rze2NSPAABQHldXVyZ6m6Fm8/IrP339+nslAgCABQjD6IktBMFECHLxhCABAABWXJYmlZsI+76iqF21O99//0pXAgBAeaRpZo6FGVJMAAAogyiOn9hCYkbsZdhQAgAAgNV21e5UcSLs+6Ik7d/2dCUAAAAAADA/cZIuvQUeQQgSAABglfVve9FKHG/3BqMsTXQoAAAAAAAwD1E4yZ88qMS0hWk7irlgpsMGAAC+TZxmP725+KaXnB4d7h8cKN0CtNvt8SRayU0ritrb5jtvLQAAAACg6oLxKMtydYCyCcNwJu2Mx8H2zq56LpIQJAAAAAAAAAAALEjvdhCnmTpA2YRRPJN2ktSM2IsmBAkAVFizeVndld/d2T4+OdGJAAAAAAAAAEsXxWmp2uHhHhqCfP36+88+vjJTrW016l/aRgCgtCp9kdxm5go/AAAAAAAAgOXL0iTLZzNP/bSdaWv1xqaqLsyGEgAAAAAAAAAAALC2gmBS2tb4TabDhser9Bys9xkGFQBgZRwe7O/u7NzdH43H4SpOuHB6dPjh/t7erk4HAAAAAACeaBKGs21t/+BAVRdGCBIer9JzsAIAsJK2d3ant3uH6ysYgvSpAQAAAAAAMFtJkpa2NX6T6bABAAAAAAAAAABYX7MdCs3AagsmBAkAAAAAAAAAAMCaCsajmbc5HAwUdmFMhw1UW7vdXtait7c2D18c6QIAAAAAAAAAgOoKgsnM24yiaF9lF0UIEqi28SRa4qKDSfjq1Su9AAAAAAAAAABQUXGSVqJNvsR02ACPF8Zps3mZpYlSAAAAAAAAAABUUZymlWiTLzESJMAT/2llP1++Ozs52nv2XDUAAAAAAAAA1tlNt5tm2def85tPABYpCidFMftmp21OW97e2VXhBRCCBHiqvKi1u72jJDl8caQaAPD5o8coqg0GHz24tbXpwA8AAAAAgFUyCaM4lXGEKhmPg/m17FzYYghBAsxAUdRu+qMoTs7Pz1UDAD41DMLp7aMHn+1unzvwAwAAAAAAYHmiOK5cy3xkQwkAZmU8iVqtVpYmSgEAAAAAAAAAUH5xklauZT5iJEj4jCicxPEa5diGn8xN+Zv29nbrjU1vlU+FcdpstV+eHRvQGAAAAAAA+Kyf3lxUZVV//+MP+gsAWGFZmuTFvBqftjxtX8BmAYQg4TP6g+F4Eq3P9nZ6/W99yWmttn/gb/QX/kHmeavdOT852nv2XDXg0Sr0ISAAAAAAAAAAVTQajebd/uGLI3WeN9NhA8xeUdSuOr2bblcpAAAAAAAAAADKKYziSrfPHSFIgHnpj4Krqyt1AAAAAAAAAAAooTTN5tp+FKeKvABCkABzFIRxs3mZpYlSAAAAAAAAAACUSjznEGSW54q8AEKQAHP/f9lstYPxSCkAAAAAAAAAAEpiOBiszFLWnBAkwNxled7u9vq3PaUAAAAAAAAAACiDSRiuzFLWXEMJABagKGo3/VGSpKdnZ6oB/I+d3ajZvFyHLd3Y+O787LTe2NTpAKynUl3mu39woEcAqKgonPQHw0e//PBgf3tnVxkBAAD4IEnSlVnKmhOCBFicYRAmrZYkEHAnL2pxmq3Jxl5cvnu+uyMIDsB66vT65VmZm9v+/rO945MT/QJA5cRxMp5Ej3757s6OECQAAAD3JVm2MktZc0KQAAsVxmmz1X796lwOElgrRfE+CB41L09PjpxzAoAlyotafxRMwuhg/7lRIQEAAACeYjgYfDrLbSrtBBURjEdFsYgFTZcyXdbes+dqPj9CkMBjjMbjT3fmeKAszy8u352fHPkPB6ybOM1a7c7ezvb5+blqAMBy/yl3ev3BcCQKCQAAAPBokzB8ymjlwHIFwWSRyxIRmSshSOAxwjit1VJ1eLSiqLW7vYMwMgkdsIZ/AMeT6O1F8/T40I4+ACzXXRRyNB4fH70wVDMAAAAAsFbyxYwDufBlrSchSIDlKH6ZhC5J05cvX6oGsG6yPL/q9PZG4+++++6hu631uuA4AMxDGKeXV52drYYoJAAAAMF4FEZJJVZ1NB6b3AAAuLOgEOTm5uYf//CXLw4Pn9hOkqR//Td/OxgM9RywIkeSYdy5vj49O1MKYD3/Bj78yVuNuooBwPyEcdpqd/Z2tk+Oj+qNTQUBAABYQ/3bXm8wqspIVdMj2bcXzdevzh3GAgAbi1nMTBKQtfdhysZf/fEPe3uGJQBWh0GPAQCAMpgemown0cXlu3a7naWJggAAAKyV6cHgTX9UrdNWWZ5PD2OD8Uj3AcCaW9BIkDNJQN7Z3Gzs7e4GweT+g7/709d/+sOfTu/8fPHz25+b+hUAAADgEe6ikJPLd/vP9o5PThQEAABg5WVpctXuREla0cPYq07vMIwcwwLAOmuswDb87k9f/6f/9B/v7nc6XZ0KAAAA8BR5UeuPguE4EIUEYMF+enOhCACwSMF4dN3t5RWft2x6DBvF8fnZqamxAWA9bVR9A+4nIKdSszUBAAAAzMJdFLLZvBwOBqoBAACwem663Xb1E5B3wjhtttpRONGtALCGqh2C/CgB+c9v3v7TT290KgAAAMCsxGnW6fVFIQEAAFbM1dVVfxQUxepsUZbnrXbH0SsArKEKT4f9UQIySdIgmPzP//bf3H2bpsm7q/b0EX0MAAAA8ER3UcjReHx89GJ7Z1dBAAAAqit7fzL9enqgt3qbVhS16dFrFEWnZ2c6GgDWR4VDkPcTkFObm42/+PN/d/+R//U/1P7xv/x///W//XfdDAAAAPB0YZxeXnV2thqikAAAABUVjEfXqzIF9pcMgzBptc7PTuuNTT0OAOtgY7U37y/+/N/9L3/x57oZAAAAYFbCOG21O+12O0sT1QAAAKiQm263veoJyA+Hrs1WOwpNHQkAa6HCIcgkSR/ytH/7b/6nvT0jEwAAAADMTFHUxpPo4vKdKCQAAEBVXF1d9UdBUazL9mZ53mp3hoOBrgeAlVfh6bD/+m/+9q/++IfNzV83IUnS6SODwXB6/+Bg//6P/uTl+T/99EZnAwAAAMzQXRRycvlu/9ne8cmJggAAAJRTlibvrq7jNFvD49ZOrx9F0enZmbcBAKywCo8EORgM//pv/vbDeJCbm42/+uMfDg72P/zowzMbjU09DQAAADAPeVHrj4I3by9uul3VAAAAKJtgPPr58t0aJiA/GAZhq9UyjwEArLCNSq/9pznIP3n58sOP9C4AAADAYtxFIZvNSxONAQAAlMdNt9vu9vJi3esQxmmz1Y7CibcEAO12u9m8nN4mYbSwhU6XdbfQ6dJ1wTxsVH0DPspBAgAAALAscZp1en1RSAAAgDK4urrqj4KiUIn3sjxvtTsOVwGo/fIx5vS2yIsEpsu6W6jiz0ljBbbhLgd5Nwbkzc2NTgUAAABYorso5HA0Pjl+sb2zqyAAAAALlqXJu6trSYuPFEVtergaRdHp2ZlqAKyt3Z2d8SRa4tJ1wTwsKAT5z2/e/tmPv5tVU53ux0nHwWBo/msAAABgtq6urlJnjB4rStLLq87OVuP4SBQSAABggYdj4eRdu2MK7C8ZBmF2dfXyl1GWAFhD+wcHnV5/iUvXBfOwoBDk3/39PwwGg0Zj84ntpGnyTz+90W0AAADAAqQmKHmyMH4fhXy2u31yfFR/8kdDAAAA/KY4TiQgf/N4XxEA1tlWo76UD36ny1X8OVncdNjCiwAAAADraTyJgst3ezuikAAAAADAkm1uNpYSgpwuV/HnZEMJAAAAAJi3ongfhby4fHfT7aoGAAAAALAsuzs7a7XcdSAECQAAAMCCFEWtPwrevL0QhQQAAAAAlmJvb3etlrsOjLEJAAAAwELlv0QhR0F4dLi/f3CgIAAA3yQYj3q3g6884fXr71UJAAC+pN7YrG9sZHm+0IVubEyXq/hzsqAQ5Obm5n/83/7D9OsT20mS5O/+/h+mX/UcAAAAQKVled7p9QfD0cH+c1FIAIBv2I/K8jjN1AEAAB5te6sRhPGCl6js87Og4v7xD3/54vBwJk09e7b3N3/7f8pBAgAArKd2uz2rptLMWUNYvjjNOr3+cDQ+OX6xvWM6GACAGWg2L+fR7OZm4/z8XHkBAFgBO9tbCw5BTpeo7POzoBDkrBKQd00dHux3ujc6DwAAYA2NJ5EiwOqJkvTyqrOz1Tg+EoUEAHiqOY0TOW327UXz9Phw79lzRQYAoNKeP39+0x8teInKPj+LHmYzCILROHjEC7e2NmeYpAQAAACgbML4fRTy2e72yfFRvbGpIAAAZZPl+VWntzcav3z5UjUAAKiuemNz47taXixocdNl+cBzrhYdgvznNxf/9b/990e88PTk+P/44/+uwwAqKgon/cFw5s1ub20evjhSXgAAWCXjSRRcvtvbEYUEACipBc8bCAAA87C12QjjdGHLUvC5Ul8AFiGOk3nMXDltM4xi1xwDAMCKKYpfo5AHz/aOT04UBAAAAGB9/PTmolTr8913tfOTo71n5jJeNfV6vVZLF7gs5mhjVTdsc9M4AQBrIQjjy8tWliZKAQAAK6Yoav1R8ObtxU23qxoAAAAALEVR1K46PZ9QQZmtZghyc3Pzj3/4S70LsCaiJG222sF4pBQAALB68l+ikG8vmsPBQDUAAAAAWIr+KOhcX6sDlFMlp8P+9//+L+L4ayN+PX+2N/Xh23dXV3oaYLVled7u9k6yfP/gQDUAAGAl9/k7vf5gODrYf263HwAAAIDFGwZh0mq9evVKKaBsKhmCfHF4+PAnt687g8GwbJsQjEdZlq/ne65e39h79tzvHjBzRVHr9PpRFJ2enakGAACspDjNprv9w9H45PjF9s6uggAAAACwSGGctlqt87PTemNTNaA8Gqu9ebf9/v/1f/8/JVyx3u0gTrP1fM9tNepCkMD8rOfFN+12+/63afbIfzFJkt5vqlGvH5+ceFMBAFA2UZJeXnV2thrHR6KQAAAAACxUGKfNVvv1q3M5SCiPSoYgb/v9r0+Hfefdu3cXP18mSaKbAdZtp/PtRXOtdjrHk2gm7cRpdj+jv9WoezsBAFDmPf/Lq86z3e2T4yOfOAMAAACwMFmeN1vtl2fHLtCFkqhkCPI//+d/7HRvdB4AX9npvLh8d35yZOhZAABYbeNJFFy+29sRhQQAAABgcbI8b7U7TklDSSw6BPlnP/5wevqYiTW3tnyKDbAgw8Gg0+tXfSuKotbu9g7CyITOAACw2qY7/3dRyINne/b/AQAAAFiMu1PSR0ly+OJINWC5Fh2C3PuFugOwmJ3O/ihIs+z8/Fw1AABgHfb/h+Ngf9WjkFmaBMFkrTp3/+DAOxwAAAAooaKo3fRHWZa7NBeWa0EhyH9+8/bPfvzdTJq67ff7g6GeA+CBxpPo8rL18vzU1HgAALDy8l+ikKMgPDrcX9XkXBBMVmDw/m8iBAkAAACUmaF5YOkWFIL8u7//hyRJDw+f+nllkiS/NJXoOQAeLkrSZqv98ux4e2d3JTfw2e723Z3xJHp6axvf1XZ33jfYqNe9eQAAqKIszzu9/mA4Oth/Lj8HAAAAwLyNJ1Hn+vr07EwpYCkWNx32//uP/0W5AViWLM9b7c7Ji8OVPAP64aKin95czGDnoF53lRIAACsgTrNOrz8cjU+OX6zqBVEAAAAAlEReFIoAy9JQAhYszbJ2u/2kd229fnxyopLAt5ruc3Z6/SRJ/A0BAID1ESXp5VVnZ6txfCQKCQAAAI/UbF7Gabb01dhq1F+//l53APARIUgWLS+eOlvrdLdGGYFH64+CKI5fvXqlFAAAsD7C+H0U8tnu9snxUb2xqSAAAAAAACtDCBKgekpyoVV1hXH69qL5+tW5c58AALBWxpMouHy3tyMKCQAA1XDT7U7CaFlLbzTqL1++1AsAAOUnBAnAOsry/OfLd2cnR3vPnqsGAACsj6L4NQr5fHfn9OxMQfjIT28uVn4bf//jDzoaAKiKNMuMCgEAwG/aUAIA1lNe1NrdXv+2pxQAALBuiqI2DMI3by9uul3VAAAAAACoNCNBArC+iqJ20x9FcXJ+fq4aAACwbvKi1h8FxycnSgHwCFE46Q+Gj3hho173txcAAACYISFIANbdeBK1Wq3zs9N6Y1M1AAAAAB4ijpPxJHrEC7caddUDAAAAZsh02ABQC+O02WpH4UQpAAAAAAAAAAAqRAgSAN7L8rzV7gTjkVIAAAAAAAAAAFSFECQA/Kooaled3k23qxQAAAAAAAAAAJXQUAIAuK8/CqI4fvXqlVIAAACsm9Ojw7s7vf4wy/OV2a76xsbR4b7+BQAAAGAlCUECwMfCOG02L//k5Vm9sakaAAAA62P/4ODuzmA4ylYnA1mrb3z3YdOooqurqzTNyrZWWV48+oXDweD9O7O+sffsuf4FAAAAnkgIEgA+I06zZqt9enzos3gAAABgudI0i8sXgny0LM87vf70zlaj7oMXWENROOkPhlVc892dHRcVAABAOQlBAsDnZXne7vaOkuTwxZFqAAAAAAA8XRwn40lU0ZUXglxbw8FgEoZf+unhwf72zq4qAQAskRAkAHxRUdRu+qMkSU/Pzsq/tnczST1dnGZZmpgKHAAAAAAApiZh+JXw7u7OjhAkAMByCUECwG8YBmHSap2fnZY8Fzgaj2fVVK93W4ncJwDAv9qH6Q8Hw9Fs20yyTGEBAADWU5pl7Xb7/bFhkqoGAECZCUECwG8L47TZar9+dV7aHGSWJtOVnFVrQRjrdACgcrI8z3JlAAAAYDbyovaQ2ds7vf709tkfnR4dmkUdAGABhCAB4EGyPL+4fHd+crT37HkJV6/Xu53txgbjUTm3lLWVZFmzeTnbBlUVAKAShoPBQ55Wr284igEAAACANSQECQAPVRS1q07vMIyOT07Ktm7jSTjbBvuDodOHlO0XME7FFgGAVfPAeN99URStW5W+NKzOR7YadUcxAAAAALCGhCAB4Nv0R0GSpi9fvizPKg0Hg7yYcZtRkmZpUtrpvwEAYDU8MN4HAAAAAMCXbCgBAHyrIIwvL1tZmpRkfUbj8czbLIpavz/Q1wAAAAAAAABAmRkJEgAeI0rSZqt9eny49NnWsjQJ43QeLY+C8PhEVwMAAAAAD5KlSRBMvv6cKIoUCgAAmC0hSAB4pCzP293eea223Bzk/MZrnG5gMB4tPeUJAAAAAFRCEEw6vb46AAAACyYECQCPVxS10ThYbkxwFITza7w/GApBAgAAAMByNZuX97/N8kJNAAAAPhCCBIAKC8ajLM/n136UpIoMAAAAAMsVp5kiAAAAfMmGEgBAdfUHw7m2XxS1m25XnQEAAAAAAACAchKCBICqytJkASM1TsJIqQEAAAAAAACAcjIdNgBUVb8/KIq5LyVOsyicbO/sKjgAAAAAAMC3ajYv4zQr7er9/scf9BEwWzfdbpo96e/e4cG+M9R8EyHIX2V5MRwMFrk4NQfgiUZBuJgF3fYHL+1iAgAAAABrbBJGzealOgAAPGTH6Ynh792dHSFIvokQ5K+yPO/0+upQkc6ae2I1yzJ1BkouGI+m/7wWtJMaxQoOAAAAAKyzvKiVeSA3AAB4tHa7PZ5E817K6dHh/sHBnBoXgqR6JFYBpoaj8cKWVRTvRyw/PjlRdgAAAAAAAACgVIQgAaCSFjw64ySM1BwAAAAAAFhJN93u/E6FJOYhBIA5E4IEgEoeihfFQpcYp1kUTrZ3dhUfAAAAAABYMWmWmfIeAKpLCBIAqmcp4zL2B8NzIUgAAKCs4jT76c2FOgAAAADAutlQAgColiicLOViRDNiAwAAAAAAAABlYyRIACijLE2CYPLZH43G46WsUl7UOtfX29vbn/3p/sGBXgMAAAAAAGB+srwYDgYPfPLW1ua2Wc4A1oMQJACUURBMOr1+2dZqGITT22d/JAQJAAAAAADAXGV5/vAzaM92t8+FIAHWg+mwAQAAAAAAAAAAgEoyEiQAAAAAAAAAzFin1y/hpE8AlEq73V69jUqzTM+yYI1m89K7FgAAKI9gPMqyfOmrsbW1uW2qFABgJSRZ9sTPgUuyFboSAACAFTOeRIrAnZ/eXKz2Bvb6w8FwNKfGG3HqkyMAAKBMh0C3gzIcpzzb3T4XggQAVkJR1HwODAAAAMASZXk+v1FQNtQXAAAAAAAAAAAAqCIhSAAAAAAAAAAAAKCShCABAAAAAAAAAACASmooAQCU0N7e7um9b0fjcRinpVrDna3G82fP9BQAAAAAAAAAsERCkABQRvXG5v7B5odvJ2FYq5UrBFmv1/cPDvQU8BRZlg0Hg888nhdlXr1l2dvbnf538LYBAAAAAACA+4QgAQCA5QjjNIz7Vu+BTmu1+/l4AACAD66urtI0m0lTuzvbxycnSgoAAECFCEECAAAAAABUWJpm8YxCkJtZpp4AAABUy4YSAAAAAAAAAAAAAFUkBAkAAAAAAAAAAABUkumwAQAAAAAAAACAOZqEUbN5qQ7APAhBAgAAAAAAAAAAc5QXtTjN1AGYByFIAAAAAAAA4Bv89OZCEQAAgJLYUAIAAAAAAAAAAACgiowECQAAAAAALFqWF8PBoIQrFoxHvdtBtYqZZGYVBAAAYH0JQQIAAAAAAIuW5Xmn1y/jimV5nMoUAgAAQGWYDhsAAAAAAAAAAACoJCFIAAAAAAAAAAAAoJKEIAEAAAAAAAAAAIBKEoIEAAAAAAAAAAAAKkkIEgAAAAAAAAAAAKgkIUgAAAAAAAAAAACgkhpKAAAAAAAAAMCn2u32EpeeJKkuAADgNwlBAgAAAAAAAPAZ40mkCAAAlJzpsAEAAAAAAAAAAIBKEoIEAAAAAAAAAAAAKkkIEgAAAAAAAAAAAKgkIUgAAAAAAAAAAACgkoQgAQAAAAAAAAAAgEpqKAEAAAAAAAAAwBpqt9sPeVqaZWoFQGkJQQIAAAAAAAAArKPxJFIEAKrOdNgAAAAAAAAAAABAJQlBAgAAAAAAAAAAAJUkBAkAAAAAAAAAAABUUkMJAAAAym80Hk/C8JtekiSpugGUVpYm7euOOgAAAAAAPJEQJAAAQAWEcVqrCTUCrIgsTZqtdpbnSgEAAAAA8ERCkAAAAACwOMF41O72ikIlAAAAAABmQAgSAAAAABbkptvtjwJ1AAAAAACYFSFIAAAAAFiEq6urIIzVAQAAAAC+otPrT2/qwMMJQQIAAADAfGVpctXuREmqFAAAAAAAsyUECbBkSZK22+1vekmaZeoGAABQFVE4ubq+yfJcKQAAAAAAZk4IEmDJ4jSb3tQBAABgJQXjUbvbKwqVAAAAAACYCyFIAAAAAJiLm263PwrUAaAMRuPxJAwf8szMNCwAAABQKUKQAAAAADB7rVYrjFN1AD7S6fWnN3VYvF/+JvuzDAAAACtICBIAAAAAZilLk3dX13FqIDEAAAAAgLkTggQAAABgfTWblzNvM82yvFBaAAAAAIBFEIIEAAAA4P9n745a2gbDMAwXKbgdqAg7HcP//6NERMEg25quNE2+N7XiiQiyupA1r70uelJaaPu0J4WbfMfL9RoBAAAAGC4ilnVtBzgIESQAAAAAAAAAAMC/a9rStAs7wEGcmAAAAAAAAAAAAADISAQJAAAAAAAAAAAApOQ4bAAAAAAAAAAAABhFRCzr2g7jEUECAAAAAAAAAADAKJq2NO3CDuNxHDYAAAAAAAAAAACQkitBAsDBXN/c5n3zq/Vm//d/9eO7rxsAAAAAAJiC6LdvziSNCLMAQF4iSAAAAAAAAADgWETfP/5yJikAfB6OwwYAAAAAAAAAAABSEkECAAAAAAAAAAAAKYkgAQAAAAAAAAAAgJREkAAAAAAAAHxAlC76rR0AAACYgrkJAAAAAAAA2NOyrn/+XmggAQAAmAgRJAAAAAAAAH8XpXuoHjddMQUAAADTIYIEAAAAAADg2brZ3N3dv/doF7F1AUgAAAAmRgQJAAAAAADAs347a0vYAQAAgEROTAAAAAAAAAAAAABkJIIEAAAAAAAAAAAAUhJBAgAAAAAAAAAAACnNTQAAAAAAAAAAwGfSdaWqqrFfws4AUyCCBID/ZPcva7XeHOdnv765fX332+XF2fm5nwQAAAAAAAAjaUvsbnYAOAaOwwYAAAAAAAAAAABSEkECAAAAAAAAAAAAKYkgAQAAAAAAAAAAgJREkAAAAAAAAAAAAEBKIkgAAAAAAAAAAAAgpbkJAGCIritVVe35THO9+LNarZvGDgAAAAAAAADAQCJIABikLbG72eFDmrbMZpJQAAAAAAAAAGAox2EDAAAAAAAAAAAAKYkgAQAAAAAAAAAAgJREkAAAAAAAAAAAAEBKIkgAAAAAAAAAAAAgJREkAAAAAAAAAAAAkJIIEgAAAAAAAAAAAEhp/vXLqRUAAAAAAAAAAACAdJ4EGAD0UiXBHYVPBAAAAABJRU5ErkJggg==)\"></div></div>", + "meta": { + "options": { + "id": 761, + "assetType": { + "id": 197, + "name": "htmlblock", + "displayName": "HTML Block" + } + } + }, + "availableViews": [], + "data": { + "email": { + "options": {} + } + }, + "modelVersion": 2 + } + }, + "data": { + "email": { + "options": {} + } + }, + "modelVersion": 2 + } + }, + "template": { + "id": 0, + "assetType": { + "id": 214, + "name": "defaulttemplate" + }, + "name": "CONTENTTEMPLATES_BLANK_PAGE", + "meta": { + "contentHash": -765177524 + }, + "availableViews": [], + "slots": { + "banner": { + "locked": false, + "availableViews": [], + "data": { + "email": { + "options": {} + } + }, + "modelVersion": 2 + } + }, + "data": { + "email": { + "options": {} + } + }, + "modelVersion": 2 + }, + "data": { + "email": { + "options": {} + } + }, + "modelVersion": 2 + } + }, + "availableViews": [ + "subjectline", + "preheader", + "text", + "viewAsAWebPage", + "subscriptioncenter", + "forwardHTML", + "forwardText", + "html" + ], + "data": { + "email": { + "options": { + "characterEncoding": "utf-8" + } + } + }, + "modelVersion": 2, + "r__folder_Path": "Content Builder" +} diff --git a/test/mockRoot/deploy/testInstance/testBU/asset/message/testNew_assetMessage/views.html.content.asset-message-meta.html b/test/mockRoot/deploy/testInstance/testBU/asset/message/testNew_assetMessage/views.html.content.asset-message-meta.html new file mode 100644 index 000000000..0473ba80a --- /dev/null +++ b/test/mockRoot/deploy/testInstance/testBU/asset/message/testNew_assetMessage/views.html.content.asset-message-meta.html @@ -0,0 +1,150 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> +<html> + <head> + <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=0" /> + <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> + <style type="text/css"> + ReadMsgBody{ width: 100%;} + .ExternalClass {width: 100%;} + .ExternalClass, .ExternalClass p, .ExternalClass span, .ExternalClass font, .ExternalClass td, .ExternalClass div {line-height: 100%;} + body {-webkit-text-size-adjust:100%; -ms-text-size-adjust:100%;margin:0 !important;} + p { margin: 1em 0;} + table td { border-collapse: collapse;} + img {outline:0;} + a img {border:none;} + @-ms-viewport{ width: device-width;} + </style> + <style type="text/css"> + @media only screen and (max-width: 480px) { + .container {width: 100% !important;} + .footer { width:auto !important; margin-left:0; } + .mobile-hidden { display:none !important; } + .logo { display:block !important; padding:0 !important; } + img { max-width:100% !important; height:auto !important; max-height:auto !important;} + .header img{max-width:100% !important;height:auto !important; max-height:auto !important;} + .photo img { width:100% !important; max-width:100% !important; height:auto !important;} + .drop { display:block !important; width: 100% !important; float:left; clear:both;} + .footerlogo { display:block !important; width: 100% !important; padding-top:15px; float:left; clear:both;} + .nav4, .nav5, .nav6 { display: none !important; } + .tableBlock {width:100% !important;} + .responsive-td {width:100% !important; display:block !important; padding:0 !important; } + .fluid, .fluid-centered { + width: 100% !important; + max-width: 100% !important; + height: auto !important; + margin-left: auto !important; + margin-right: auto !important; + } + .fluid-centered { + margin-left: auto !important; + margin-right: auto !important; + } + /* MOBILE GLOBAL STYLES - DO NOT CHANGE */ + body { padding: 0px !important; font-size: 16px !important; line-height: 150% !important;} + h1 { font-size: 22px !important; line-height: normal !important;} + h2 { font-size: 20px !important; line-height: normal !important;} + h3 { font-size: 18px !important; line-height: normal !important;} + .buttonstyles { + font-family:arial,helvetica,sans-serif !important; + font-size: 16px !important; + color: #FFFFFF !important; + padding: 10px !important; + } + /* END OF MOBILE GLOBAL STYLES - DO NOT CHANGE */ + } + @media only screen and (max-width: 640px) { + .container { width:100% !important; } + .mobile-hidden { display:none !important; } + .logo { display:block !important; padding:0 !important; } + .photo img { width:100% !important; height:auto !important;} + .nav5, .nav6 { display: none !important;} + .fluid, .fluid-centered { + width: 100% !important; + max-width: 100% !important; + height: auto !important; + margin-left: auto !important; + margin-right: auto !important; + } + .fluid-centered { + margin-left: auto !important; + margin-right: auto !important; + } + } + </style> + <!--[if mso]> + <style type="text/css"> + /* Begin Outlook Font Fix */ + body, table, td { + font-family: Arial, Helvetica, sans-serif ; + font-size:16px; + color:#000000; + line-height:1; + } + /* End Outlook Font Fix */ + </style> + <![endif]--> + </head> + <body bgcolor="#ffffff" text="#000000" style="background-color: #ffffff; color: #000000; padding: 0px; -webkit-text-size-adjust:none; font-size: 16px; font-family:arial,helvetica,sans-serif;"> + <div style="font-size:0; line-height:0;"><custom name="opencounter" type="tracking"><custom name="usermatch" type="tracking" /></div> + <table width="100%" border="0" cellpadding="0" cellspacing="0" align="center"> + <tr> + <td align="center" valign="top"> + <custom type="header"/> + </td> + </tr> + <tr> + <td align="center"> + <table cellspacing="0" cellpadding="0" border="0" width="600" class="container" align="center"> + <tr> + <td> + <table class="tb_properties border_style" style="background-color:#FFFFFF;" cellspacing="0" cellpadding="0" bgcolor="#ffffff" width="100%"> + <tr> + <td align="center" valign="top"> + <table align="left" border="0" cellpadding="0" cellspacing="0" width="100%"> + <tr> + <!-- added padding here --> + <td class="content_padding" style=""> + <!-- end of comment --> + <table border="0" cellpadding="0" cellspacing="0" width="100%"> + <tr> <!-- top slot --> + <td align="center" class="header" valign="top"> + <table align="left" border="0" cellpadding="0" cellspacing="0" width="100%"> + <tbody> + <tr> + <td align="left" valign="top"> + <table cellspacing="0" cellpadding="0" style="width:100%"> + <tbody> + <tr> + <td class="responsive-td" valign="top" style="width: 100%;"> + <div data-type="slot" data-key="banner"> + </div> + </td> + </tr> + </tbody> + </table> + </td> + </tr> + </tbody> + </table> + </td> + </tr> + </table> + </td> + </tr> + </table> + </td> + </tr> + </table> + </td> + </tr> + </table> + </td> + </tr> + <tr> + <td valign="top"> + <custom type="footer" /> + </td> + </tr> + </table> + </body> +</html> diff --git a/test/mockRoot/deploy/testInstance/testBU/asset/message/testNew_asset_templatebasedemail/testNew_asset_templatebasedemail.asset-message-meta.json b/test/mockRoot/deploy/testInstance/testBU/asset/message/testNew_asset_templatebasedemail/testNew_asset_templatebasedemail.asset-message-meta.json new file mode 100644 index 000000000..5d0de8b3a --- /dev/null +++ b/test/mockRoot/deploy/testInstance/testBU/asset/message/testNew_asset_templatebasedemail/testNew_asset_templatebasedemail.asset-message-meta.json @@ -0,0 +1,305 @@ +{ + "customerKey": "testNew_asset_templatebasedemail", + "contentType": "application/vnd.etmc.email.Message; kind=template", + "assetType": { + "name": "templatebasedemail", + "displayName": "Template-Based Email" + }, + "name": "testNew_asset_templatebasedemail", + "description": "", + "createdBy": {}, + "modifiedBy": {}, + "memberId": "9999999", + "status": { + "name": "Draft" + }, + "meta": { + "globalStyles": { + "isLocked": false, + "template": { + "background-color": "#FFFFFF", + "border-color": "", + "border-width": "0px", + "border-style": "solid" + }, + "body": { + "background-color": "#FFFFFF", + "font-family": "Arial,helvetica,sans-serif", + "font-size": "16px", + "color": "#000000", + "line-height": 1, + "margin": "0px", + "padding": "0px", + "content-padding-top": "0px", + "content-padding-right": "0px", + "content-padding-bottom": "0px", + "content-padding-left": "0px" + }, + "h1": { + "font-family": "Arial,helvetica,sans-serif", + "font-size": "28px", + "color": "#181818", + "line-height": 1, + "font-weight": "bold", + "font-style": "normal" + }, + "h2": { + "font-family": "Arial,helvetica,sans-serif", + "font-size": "22px", + "color": "#181818", + "line-height": 1, + "font-weight": "bold", + "font-style": "normal" + }, + "h3": { + "font-family": "Arial,helvetica,sans-serif", + "font-size": "20px", + "color": "#181818", + "line-height": 1, + "font-weight": "bold", + "font-style": "normal" + }, + "links": { + "font-weight": "normal", + "color": "#0176d3", + "text-decoration": "none" + }, + "buttons": { + "font-family": "Arial,helvetica,sans-serif", + "font-size": "16px", + "color": "#FFFFFF", + "background-color": "#5D5D5D", + "border-radius": "3px", + "padding": "10px", + "border-color": "#5D5D5D", + "border-width": "1px", + "border-style": "solid" + }, + "mobile": { + "body": { + "padding": "0px", + "font-size": "16px", + "line-height": 1.5 + }, + "h1": { + "font-size": "22px", + "line-height": 1 + }, + "h2": { + "font-size": "20px", + "line-height": 1 + }, + "h3": { + "font-size": "18px", + "line-height": 1 + }, + "buttons": { + "font-family": "Arial,helvetica,sans-serif", + "font-size": "16px", + "color": "#FFFFFF", + "padding": "10px" + } + } + } + }, + "views": { + "subjectline": { + "contentType": "application/vnd.etmc.email.View; kind=subjectline", + "thumbnail": {}, + "content": "my subject", + "meta": {}, + "availableViews": [], + "data": { + "email": { + "options": { + "generateFrom": "" + } + } + }, + "modelVersion": 2 + }, + "preheader": { + "thumbnail": {}, + "availableViews": [], + "data": { + "email": { + "options": { + "generateFrom": "" + } + } + }, + "modelVersion": 2 + }, + "html": { + "thumbnail": {}, + "availableViews": [], + "slots": { + "banner": { + "design": "<p style=\"font-family:Arial;color:#ccc;font-size:12px;text-align:center;vertical-align:middle;font-weight:bold;height:150px;display:flex;flex-direction:column;justify-content:center;padding:10px;margin:0;border: #cccccc dashed 1px;\">Drop blocks or content here</p>", + "availableViews": [], + "blocks": {}, + "slots": {}, + "data": { + "email": { + "options": { + "generateFrom": "" + } + } + }, + "modelVersion": 2 + } + }, + "template": { + "content": "", + "meta": { + "contentHash": 1850388723 + }, + "slots": { + "banner": { + "locked": false, + "availableViews": [], + "data": { + "email": { + "options": { + "generateFrom": "" + } + } + }, + "modelVersion": 2 + } + }, + "r__asset_key": "testNew_asset_template" + }, + "data": { + "email": { + "options": { + "generateFrom": "" + } + } + }, + "modelVersion": 2 + }, + "text": { + "thumbnail": {}, + "availableViews": [], + "data": { + "email": { + "options": { + "generateFrom": "html" + } + } + }, + "generateFrom": "html", + "modelVersion": 2 + }, + "viewAsAWebPage": { + "thumbnail": {}, + "availableViews": [], + "data": { + "email": { + "options": { + "generateFrom": "" + } + } + }, + "modelVersion": 2 + }, + "subscriptioncenter": { + "thumbnail": {}, + "availableViews": [], + "data": { + "email": { + "options": { + "generateFrom": "" + } + } + }, + "modelVersion": 2 + }, + "forwardHTML": { + "thumbnail": {}, + "availableViews": [], + "data": { + "email": { + "options": { + "generateFrom": "" + } + } + }, + "modelVersion": 2 + }, + "forwardText": { + "thumbnail": {}, + "availableViews": [], + "data": { + "email": { + "options": { + "generateFrom": "" + } + } + }, + "modelVersion": 2 + } + }, + "availableViews": [ + "subjectline", + "preheader", + "html", + "text", + "viewAsAWebPage", + "subscriptioncenter", + "forwardHTML", + "forwardText" + ], + "data": { + "email": { + "options": { + "characterEncoding": "utf-8" + }, + "attributes": [ + { + "displayName": "__AdditionalEmailAttribute1", + "name": "__AdditionalEmailAttribute1", + "value": "", + "order": 1, + "channel": "email", + "attributeType": "AdditionalEmailAttribute" + }, + { + "displayName": "__AdditionalEmailAttribute2", + "name": "__AdditionalEmailAttribute2", + "value": "", + "order": 2, + "channel": "email", + "attributeType": "AdditionalEmailAttribute" + }, + { + "displayName": "__AdditionalEmailAttribute3", + "name": "__AdditionalEmailAttribute3", + "value": "", + "order": 3, + "channel": "email", + "attributeType": "AdditionalEmailAttribute" + }, + { + "displayName": "__AdditionalEmailAttribute4", + "name": "__AdditionalEmailAttribute4", + "value": "", + "order": 4, + "channel": "email", + "attributeType": "AdditionalEmailAttribute" + }, + { + "displayName": "__AdditionalEmailAttribute5", + "name": "__AdditionalEmailAttribute5", + "value": "", + "order": 5, + "channel": "email", + "attributeType": "AdditionalEmailAttribute" + } + ] + } + }, + "modelVersion": 2, + "r__folder_Path": "Content Builder" +} diff --git a/test/mockRoot/deploy/testInstance/testBU/asset/message/testNew_asset_templatebasedemail/views.html.content.asset-message-meta.html b/test/mockRoot/deploy/testInstance/testBU/asset/message/testNew_asset_templatebasedemail/views.html.content.asset-message-meta.html new file mode 100644 index 000000000..096758f93 --- /dev/null +++ b/test/mockRoot/deploy/testInstance/testBU/asset/message/testNew_asset_templatebasedemail/views.html.content.asset-message-meta.html @@ -0,0 +1,150 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> +<html> + <head> + <meta name="viewport" content="width=device-width, initial-scale=1" /> + <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> + <style type="text/css"> + ReadMsgBody{ width: 100%;} + .ExternalClass {width: 100%;} + .ExternalClass, .ExternalClass p, .ExternalClass span, .ExternalClass font, .ExternalClass td, .ExternalClass div {line-height: 100%;} + body {-webkit-text-size-adjust:100%; -ms-text-size-adjust:100%;margin:0 !important;} + p { margin: 1em 0;} + table td { border-collapse: collapse;} + img {outline:0;} + a img {border:none;} + @-ms-viewport{ width: device-width;} + </style> + <style type="text/css"> + @media only screen and (max-width: 480px) { + .container {width: 100% !important;} + .footer { width:auto !important; margin-left:0; } + .mobile-hidden { display:none !important; } + .logo { display:block !important; padding:0 !important; } + img { max-width:100% !important; height:auto !important; max-height:auto !important;} + .header img{max-width:100% !important;height:auto !important; max-height:auto !important;} + .photo img { width:100% !important; max-width:100% !important; height:auto !important;} + .drop { display:block !important; width: 100% !important; float:left; clear:both;} + .footerlogo { display:block !important; width: 100% !important; padding-top:15px; float:left; clear:both;} + .nav4, .nav5, .nav6 { display: none !important; } + .tableBlock {width:100% !important;} + .responsive-td {width:100% !important; display:block !important; padding:0 !important; } + .fluid, .fluid-centered { + width: 100% !important; + max-width: 100% !important; + height: auto !important; + margin-left: auto !important; + margin-right: auto !important; + } + .fluid-centered { + margin-left: auto !important; + margin-right: auto !important; + } + /* MOBILE GLOBAL STYLES - DO NOT CHANGE */ + body { padding: 0px !important; font-size: 16px !important; line-height: 150% !important;} + h1 { font-size: 22px !important; line-height: normal !important;} + h2 { font-size: 20px !important; line-height: normal !important;} + h3 { font-size: 18px !important; line-height: normal !important;} + .buttonstyles { + font-family:arial,helvetica,sans-serif !important; + font-size: 16px !important; + color: #FFFFFF !important; + padding: 10px !important; + } + /* END OF MOBILE GLOBAL STYLES - DO NOT CHANGE */ + } + @media only screen and (max-width: 640px) { + .container { width:100% !important; } + .mobile-hidden { display:none !important; } + .logo { display:block !important; padding:0 !important; } + .photo img { width:100% !important; height:auto !important;} + .nav5, .nav6 { display: none !important;} + .fluid, .fluid-centered { + width: 100% !important; + max-width: 100% !important; + height: auto !important; + margin-left: auto !important; + margin-right: auto !important; + } + .fluid-centered { + margin-left: auto !important; + margin-right: auto !important; + } + } + </style> + <!--[if mso]> + <style type="text/css"> + /* Begin Outlook Font Fix */ + body, table, td { + font-family: Arial, Helvetica, sans-serif ; + font-size:16px; + color:#000000; + line-height:1; + } + /* End Outlook Font Fix */ + </style> + <![endif]--> + </head> + <body bgcolor="#ffffff" text="#000000" style="background-color: #ffffff; color: #000000; padding: 0px; -webkit-text-size-adjust:none; font-size: 16px; font-family:arial,helvetica,sans-serif;"> + <div style="font-size:0; line-height:0;"><custom name="opencounter" type="tracking"><custom name="usermatch" type="tracking" /></div> + <table width="100%" border="0" cellpadding="0" cellspacing="0" align="center"> + <tr> + <td align="center" valign="top"> + <custom type="header"/> + </td> + </tr> + <tr> + <td align="center"> + <table cellspacing="0" cellpadding="0" border="0" width="600" class="container" align="center"> + <tr> + <td> + <table class="tb_properties border_style" style="background-color:#FFFFFF;" cellspacing="0" cellpadding="0" bgcolor="#ffffff" width="100%"> + <tr> + <td align="center" valign="top"> + <table align="left" border="0" cellpadding="0" cellspacing="0" width="100%"> + <tr> + <!-- added padding here --> + <td class="content_padding" style=""> + <!-- end of comment --> + <table border="0" cellpadding="0" cellspacing="0" width="100%"> + <tr> <!-- top slot --> + <td align="center" class="header" valign="top"> + <table align="left" border="0" cellpadding="0" cellspacing="0" width="100%"> + <tbody> + <tr> + <td align="left" valign="top"> + <table cellspacing="0" cellpadding="0" style="width:100%"> + <tbody> + <tr> + <td class="responsive-td" valign="top" style="width: 100%;"> + <div data-type="slot" data-key="banner"> + </div> + </td> + </tr> + </tbody> + </table> + </td> + </tr> + </tbody> + </table> + </td> + </tr> + </table> + </td> + </tr> + </table> + </td> + </tr> + </table> + </td> + </tr> + </table> + </td> + </tr> + <tr> + <td valign="top"> + <custom type="footer" /> + </td> + </tr> + </table> + </body> +</html> diff --git a/test/mockRoot/deploy/testInstance/testBU/asset/template/testNew_asset_template/content.asset-template-meta.html b/test/mockRoot/deploy/testInstance/testBU/asset/template/testNew_asset_template/content.asset-template-meta.html new file mode 100644 index 000000000..096758f93 --- /dev/null +++ b/test/mockRoot/deploy/testInstance/testBU/asset/template/testNew_asset_template/content.asset-template-meta.html @@ -0,0 +1,150 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> +<html> + <head> + <meta name="viewport" content="width=device-width, initial-scale=1" /> + <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> + <style type="text/css"> + ReadMsgBody{ width: 100%;} + .ExternalClass {width: 100%;} + .ExternalClass, .ExternalClass p, .ExternalClass span, .ExternalClass font, .ExternalClass td, .ExternalClass div {line-height: 100%;} + body {-webkit-text-size-adjust:100%; -ms-text-size-adjust:100%;margin:0 !important;} + p { margin: 1em 0;} + table td { border-collapse: collapse;} + img {outline:0;} + a img {border:none;} + @-ms-viewport{ width: device-width;} + </style> + <style type="text/css"> + @media only screen and (max-width: 480px) { + .container {width: 100% !important;} + .footer { width:auto !important; margin-left:0; } + .mobile-hidden { display:none !important; } + .logo { display:block !important; padding:0 !important; } + img { max-width:100% !important; height:auto !important; max-height:auto !important;} + .header img{max-width:100% !important;height:auto !important; max-height:auto !important;} + .photo img { width:100% !important; max-width:100% !important; height:auto !important;} + .drop { display:block !important; width: 100% !important; float:left; clear:both;} + .footerlogo { display:block !important; width: 100% !important; padding-top:15px; float:left; clear:both;} + .nav4, .nav5, .nav6 { display: none !important; } + .tableBlock {width:100% !important;} + .responsive-td {width:100% !important; display:block !important; padding:0 !important; } + .fluid, .fluid-centered { + width: 100% !important; + max-width: 100% !important; + height: auto !important; + margin-left: auto !important; + margin-right: auto !important; + } + .fluid-centered { + margin-left: auto !important; + margin-right: auto !important; + } + /* MOBILE GLOBAL STYLES - DO NOT CHANGE */ + body { padding: 0px !important; font-size: 16px !important; line-height: 150% !important;} + h1 { font-size: 22px !important; line-height: normal !important;} + h2 { font-size: 20px !important; line-height: normal !important;} + h3 { font-size: 18px !important; line-height: normal !important;} + .buttonstyles { + font-family:arial,helvetica,sans-serif !important; + font-size: 16px !important; + color: #FFFFFF !important; + padding: 10px !important; + } + /* END OF MOBILE GLOBAL STYLES - DO NOT CHANGE */ + } + @media only screen and (max-width: 640px) { + .container { width:100% !important; } + .mobile-hidden { display:none !important; } + .logo { display:block !important; padding:0 !important; } + .photo img { width:100% !important; height:auto !important;} + .nav5, .nav6 { display: none !important;} + .fluid, .fluid-centered { + width: 100% !important; + max-width: 100% !important; + height: auto !important; + margin-left: auto !important; + margin-right: auto !important; + } + .fluid-centered { + margin-left: auto !important; + margin-right: auto !important; + } + } + </style> + <!--[if mso]> + <style type="text/css"> + /* Begin Outlook Font Fix */ + body, table, td { + font-family: Arial, Helvetica, sans-serif ; + font-size:16px; + color:#000000; + line-height:1; + } + /* End Outlook Font Fix */ + </style> + <![endif]--> + </head> + <body bgcolor="#ffffff" text="#000000" style="background-color: #ffffff; color: #000000; padding: 0px; -webkit-text-size-adjust:none; font-size: 16px; font-family:arial,helvetica,sans-serif;"> + <div style="font-size:0; line-height:0;"><custom name="opencounter" type="tracking"><custom name="usermatch" type="tracking" /></div> + <table width="100%" border="0" cellpadding="0" cellspacing="0" align="center"> + <tr> + <td align="center" valign="top"> + <custom type="header"/> + </td> + </tr> + <tr> + <td align="center"> + <table cellspacing="0" cellpadding="0" border="0" width="600" class="container" align="center"> + <tr> + <td> + <table class="tb_properties border_style" style="background-color:#FFFFFF;" cellspacing="0" cellpadding="0" bgcolor="#ffffff" width="100%"> + <tr> + <td align="center" valign="top"> + <table align="left" border="0" cellpadding="0" cellspacing="0" width="100%"> + <tr> + <!-- added padding here --> + <td class="content_padding" style=""> + <!-- end of comment --> + <table border="0" cellpadding="0" cellspacing="0" width="100%"> + <tr> <!-- top slot --> + <td align="center" class="header" valign="top"> + <table align="left" border="0" cellpadding="0" cellspacing="0" width="100%"> + <tbody> + <tr> + <td align="left" valign="top"> + <table cellspacing="0" cellpadding="0" style="width:100%"> + <tbody> + <tr> + <td class="responsive-td" valign="top" style="width: 100%;"> + <div data-type="slot" data-key="banner"> + </div> + </td> + </tr> + </tbody> + </table> + </td> + </tr> + </tbody> + </table> + </td> + </tr> + </table> + </td> + </tr> + </table> + </td> + </tr> + </table> + </td> + </tr> + </table> + </td> + </tr> + <tr> + <td valign="top"> + <custom type="footer" /> + </td> + </tr> + </table> + </body> +</html> diff --git a/test/mockRoot/deploy/testInstance/testBU/asset/template/testNew_asset_template/testNew_asset_template.asset-template-meta.json b/test/mockRoot/deploy/testInstance/testBU/asset/template/testNew_asset_template/testNew_asset_template.asset-template-meta.json new file mode 100644 index 000000000..ab11c12a3 --- /dev/null +++ b/test/mockRoot/deploy/testInstance/testBU/asset/template/testNew_asset_template/testNew_asset_template.asset-template-meta.json @@ -0,0 +1,116 @@ +{ + "customerKey": "testNew_asset_template", + "assetType": { + "name": "template", + "displayName": "Template" + }, + "fileProperties": { + "fileName": "testNew_asset_template" + }, + "name": "testNew_asset_template", + "createdBy": {}, + "modifiedBy": {}, + "memberId": "9999999", + "status": { + "name": "Draft" + }, + "meta": { + "globalStyles": { + "isLocked": false, + "template": { + "background-color": "#FFFFFF", + "border-color": "", + "border-width": "0px", + "border-style": "solid" + }, + "body": { + "background-color": "#FFFFFF", + "font-family": "Arial,helvetica,sans-serif", + "font-size": "16px", + "color": "#000000", + "line-height": 1, + "margin": "0px", + "padding": "0px", + "content-padding-top": "0px", + "content-padding-right": "0px", + "content-padding-bottom": "0px", + "content-padding-left": "0px" + }, + "h1": { + "font-family": "Arial,helvetica,sans-serif", + "font-size": "28px", + "color": "#181818", + "line-height": 1, + "font-weight": "bold", + "font-style": "normal" + }, + "h2": { + "font-family": "Arial,helvetica,sans-serif", + "font-size": "22px", + "color": "#181818", + "line-height": 1, + "font-weight": "bold", + "font-style": "normal" + }, + "h3": { + "font-family": "Arial,helvetica,sans-serif", + "font-size": "20px", + "color": "#181818", + "line-height": 1, + "font-weight": "bold", + "font-style": "normal" + }, + "links": { + "font-weight": "normal", + "color": "#0176d3", + "text-decoration": "none" + }, + "buttons": { + "font-family": "Arial,helvetica,sans-serif", + "font-size": "16px", + "color": "#FFFFFF", + "background-color": "#5D5D5D", + "border-radius": "3px", + "padding": "10px", + "border-color": "#5D5D5D", + "border-width": "1px", + "border-style": "solid" + }, + "mobile": { + "body": { + "padding": "0px", + "font-size": "16px", + "line-height": 1.5 + }, + "h1": { + "font-size": "22px", + "line-height": 1 + }, + "h2": { + "font-size": "20px", + "line-height": 1 + }, + "h3": { + "font-size": "18px", + "line-height": 1 + }, + "buttons": { + "font-family": "Arial,helvetica,sans-serif", + "font-size": "16px", + "color": "#FFFFFF", + "padding": "10px" + } + } + } + }, + "availableViews": [], + "slots": { + "banner": { + "thumbnail": {}, + "design": "<p style=\"font-family:Arial;color:#ccc;font-size:12px;text-align:center;vertical-align:middle;font-weight:bold;height:150px;display:flex;flex-direction:column;justify-content:center;padding:10px;margin:0;border: #cccccc dashed 1px;\">Drop blocks or content here</p>", + "modelVersion": 2 + } + }, + "modelVersion": 2, + "r__folder_Path": "Content Builder" +} diff --git a/test/mockRoot/deploy/testInstance/testBU/automation/testExisting_automation.automation-meta.json b/test/mockRoot/deploy/testInstance/testBU/automation/testExisting_automation.automation-meta.json new file mode 100644 index 000000000..cdca01d9e --- /dev/null +++ b/test/mockRoot/deploy/testInstance/testBU/automation/testExisting_automation.automation-meta.json @@ -0,0 +1,52 @@ +{ + "description": "updated on deploy", + "key": "testExisting_automation", + "name": "testExisting_automation", + "r__folder_Path": "my automations", + "schedule": { + "endDate": "2022-07-30T00:00:00", + "icalRecur": "FREQ=DAILY;COUNT=1;INTERVAL=1", + "startDate": "2022-07-30T00:00:00", + "timezoneName": "W. Europe Standard Time" + }, + "status": "PausedSchedule", + "steps": [ + { + "activities": [ + { + "r__key": "testExisting_dataExtract", + "r__type": "dataExtract" + }, + { + "r__key": "testExisting_emailSend", + "r__type": "emailSend" + }, + { + "r__key": "testExisting_fileTransfer", + "r__type": "fileTransfer" + }, + { + "r__key": "testExisting_importFile", + "r__type": "importFile" + }, + { + "r__key": "testExisting_query", + "r__type": "query" + }, + { + "r__key": "testExisting_script", + "r__type": "script" + } + ], + "name": "" + } + ], + "notifications": [ + { + "email": ["error-updated@test.accenture.com"], + "message": "test updated", + "type": "Error" + } + ], + "type": "scheduled" +} diff --git a/test/mockRoot/deploy/testInstance/testBU/automation/testNew_automation.automation-meta.json b/test/mockRoot/deploy/testInstance/testBU/automation/testNew_automation.automation-meta.json new file mode 100644 index 000000000..46b6aed7a --- /dev/null +++ b/test/mockRoot/deploy/testInstance/testBU/automation/testNew_automation.automation-meta.json @@ -0,0 +1,49 @@ +{ + "description": "created on deploy", + "key": "testNew_automation", + "name": "testNew_automation", + "r__folder_Path": "my automations", + "schedule": { + "startDate": "2020-05-14T02:30:32.11", + "endDate": "2079-06-06T21:00:00", + "icalRecur": "FREQ=MINUTELY;UNTIL=20790607T050000;INTERVAL=5", + "timezoneName": "W. Europe Standard Time" + }, + "status": "Scheduled", + "steps": [ + { + "activities": [ + { + "r__key": "testExisting_dataExtract", + "r__type": "dataExtract" + }, + { + "r__key": "testExisting_emailSend", + "r__type": "emailSend" + }, + { + "r__key": "testExisting_fileTransfer", + "r__type": "fileTransfer" + }, + { + "r__key": "testExisting_importFile", + "r__type": "importFile" + }, + { + "r__key": "testExisting_query", + "r__type": "query" + }, + { + "r__key": "testExisting_script", + "r__type": "script" + }, + { + "r__key": "testNew_automation__s1.7", + "r__type": "verification" + } + ], + "name": "" + } + ], + "type": "scheduled" +} diff --git a/test/mockRoot/deploy/testInstance/testBU/dataExtension/testExisting_dataExtension.dataExtension-meta.json b/test/mockRoot/deploy/testInstance/testBU/dataExtension/testExisting_dataExtension.dataExtension-meta.json new file mode 100644 index 000000000..7e78e6468 --- /dev/null +++ b/test/mockRoot/deploy/testInstance/testBU/dataExtension/testExisting_dataExtension.dataExtension-meta.json @@ -0,0 +1,59 @@ +{ + "CustomerKey": "testExisting_dataExtension", + "Name": "testExisting_dataExtension", + "Description": "Container for my test emails", + "IsSendable": true, + "IsTestable": true, + "SendableDataExtensionField": { "Name": "ContactKey" }, + "SendableSubscriberField": { "Name": "Subscriber Key" }, + "DataRetentionPeriodLength": 6, + "ResetRetentionPeriodOnImport": false, + "Fields": [ + { + "Name": "FirstName", + "DefaultValue": "", + "MaxLength": 50, + "IsRequired": false, + "IsPrimaryKey": false, + "FieldType": "Text" + }, + { + "Name": "LastName", + "DefaultValue": "", + "MaxLength": 55, + "IsRequired": false, + "IsPrimaryKey": false, + "FieldType": "Text" + }, + { + "Name": "EmailAddress", + "Name_new": "Email", + "DefaultValue": "", + "MaxLength": 254, + "IsRequired": true, + "IsPrimaryKey": false, + "FieldType": "EmailAddress" + }, + { + "Name": "testField", + "DefaultValue": "", + "MaxLength": 254, + "IsRequired": false, + "IsPrimaryKey": false, + "FieldType": "Text" + }, + { + "Name": "ContactKey", + "DefaultValue": "", + "MaxLength": 50, + "IsRequired": true, + "IsPrimaryKey": true, + "FieldType": "Text" + } + ], + "c__dataRetentionPeriodUnitOfMeasure": "Days", + "c__retainUntil": "2024-5-9", + "c__retentionPolicy": "allRecords", + "r__folder_ContentType": "dataextension", + "r__folder_Path": "Data Extensions" +} diff --git a/test/mockRoot/deploy/testInstance/testBU/dataExtension/testNew_dataExtension.dataExtension-meta.json b/test/mockRoot/deploy/testInstance/testBU/dataExtension/testNew_dataExtension.dataExtension-meta.json new file mode 100644 index 000000000..5701a0f7b --- /dev/null +++ b/test/mockRoot/deploy/testInstance/testBU/dataExtension/testNew_dataExtension.dataExtension-meta.json @@ -0,0 +1,20 @@ +{ + "CustomerKey": "testNew_dataExtension", + "Name": "testNew_dataExtension", + "Description": "", + "IsSendable": false, + "IsTestable": false, + "Fields": [ + { + "Name": "testField", + "DefaultValue": "", + "MaxLength": 254, + "IsRequired": true, + "IsPrimaryKey": false, + "FieldType": "Text" + } + ], + "c__retentionPolicy": "none", + "r__folder_ContentType": "dataextension", + "r__folder_Path": "Data Extensions" +} diff --git a/test/mockRoot/deploy/testInstance/testBU/dataExtract/testExisting_dataExtract.dataExtract-meta.json b/test/mockRoot/deploy/testInstance/testBU/dataExtract/testExisting_dataExtract.dataExtract-meta.json new file mode 100644 index 000000000..9db8c5648 --- /dev/null +++ b/test/mockRoot/deploy/testInstance/testBU/dataExtract/testExisting_dataExtract.dataExtract-meta.json @@ -0,0 +1,35 @@ +{ + "name": "testExisting_dataExtract", + "key": "testExisting_dataExtract", + "description": "updated on deploy", + "r__dataExtractType_name": "Data Extension Extract", + "fileSpec": "testExisting-%%Year%%-%%Month%%-%%Day%%", + "intervalType": 0, + "dataFields": [ + { + "name": "ColumnDelimiter", + "type": "string", + "value": "," + }, + { + "name": "DECustomerKey", + "type": "string", + "value": "testExisting_dataExtension" + }, + { + "name": "HasColumnHeaders", + "type": "bool", + "value": "False" + }, + { + "name": "TextQualified", + "type": "bool", + "value": "False" + }, + { + "name": "UsesLineFeed", + "type": "bool", + "value": "False" + } + ] +} diff --git a/test/mockRoot/deploy/testInstance/testBU/dataExtract/testNew_dataExtract.dataExtract-meta.json b/test/mockRoot/deploy/testInstance/testBU/dataExtract/testNew_dataExtract.dataExtract-meta.json new file mode 100644 index 000000000..da5bcf6d4 --- /dev/null +++ b/test/mockRoot/deploy/testInstance/testBU/dataExtract/testNew_dataExtract.dataExtract-meta.json @@ -0,0 +1,35 @@ +{ + "name": "testNew_dataExtract", + "key": "testNew_dataExtract", + "description": "created via deploy", + "r__dataExtractType_name": "Data Extension Extract", + "fileSpec": "testNew-%%Year%%-%%Month%%-%%Day%%", + "intervalType": 0, + "dataFields": [ + { + "name": "ColumnDelimiter", + "type": "string", + "value": "," + }, + { + "name": "DECustomerKey", + "type": "string", + "value": "testExisting_dataExtension" + }, + { + "name": "HasColumnHeaders", + "type": "bool", + "value": "False" + }, + { + "name": "TextQualified", + "type": "bool", + "value": "False" + }, + { + "name": "UsesLineFeed", + "type": "bool", + "value": "False" + } + ] +} diff --git a/test/mockRoot/deploy/testInstance/testBU/dataFilter/testExisting_dataFilter.dataFilter-meta.json b/test/mockRoot/deploy/testInstance/testBU/dataFilter/testExisting_dataFilter.dataFilter-meta.json new file mode 100644 index 000000000..fcbe01855 --- /dev/null +++ b/test/mockRoot/deploy/testInstance/testBU/dataFilter/testExisting_dataFilter.dataFilter-meta.json @@ -0,0 +1,19 @@ +{ + "description": "updated on deploy", + "key": "testExisting_dataFilter", + "name": "testExisting_dataFilter", + "isSendable": true, + "c__filterDefinition": { + "ConditionSet": { + "@_ConditionSetName": "Outer Grouping", + "@_Operator": "AND", + "Condition": { + "@_Operator": "Begins", + "Value": "testExisting_", + "r__dataExtensionField_name": "LastName" + } + } + }, + "r__folder_Path": "Data Filters", + "r__source_dataExtension_key": "testExisting_dataExtension" +} diff --git a/test/mockRoot/deploy/testInstance/testBU/dataFilter/testNew_dataFilter.dataFilter-meta.json b/test/mockRoot/deploy/testInstance/testBU/dataFilter/testNew_dataFilter.dataFilter-meta.json new file mode 100644 index 000000000..a2e847597 --- /dev/null +++ b/test/mockRoot/deploy/testInstance/testBU/dataFilter/testNew_dataFilter.dataFilter-meta.json @@ -0,0 +1,19 @@ +{ + "description": "created via deploy", + "key": "testNew_dataFilter", + "name": "testNew_dataFilter", + "isSendable": true, + "c__filterDefinition": { + "ConditionSet": { + "@_ConditionSetName": "Outer Grouping", + "@_Operator": "AND", + "Condition": { + "@_Operator": "Begins", + "Value": "testNew_", + "r__dataExtensionField_name": "LastName" + } + } + }, + "r__folder_Path": "Data Filters", + "r__source_dataExtension_key": "testExisting_dataExtension" +} diff --git a/test/mockRoot/deploy/testInstance/testBU/domainVerification/joern.berkefeld.New@accenture.com.domainVerification-meta.json b/test/mockRoot/deploy/testInstance/testBU/domainVerification/joern.berkefeld.New@accenture.com.domainVerification-meta.json new file mode 100644 index 000000000..5a0a50654 --- /dev/null +++ b/test/mockRoot/deploy/testInstance/testBU/domainVerification/joern.berkefeld.New@accenture.com.domainVerification-meta.json @@ -0,0 +1,6 @@ +{ + "domain": "joern.berkefeld.New@accenture.com", + "status": "Verified", + "domainType": "UserDomain", + "isSendable": true +} diff --git a/test/mockRoot/deploy/testInstance/testBU/domainVerification/joern.berkefeld@accenture.com.domainVerification-meta.json b/test/mockRoot/deploy/testInstance/testBU/domainVerification/joern.berkefeld@accenture.com.domainVerification-meta.json new file mode 100644 index 000000000..e8885eec4 --- /dev/null +++ b/test/mockRoot/deploy/testInstance/testBU/domainVerification/joern.berkefeld@accenture.com.domainVerification-meta.json @@ -0,0 +1,6 @@ +{ + "domain": "joern.berkefeld@accenture.com", + "status": "Verified", + "domainType": "UserDomain", + "isSendable": true +} diff --git a/test/mockRoot/deploy/testInstance/testBU/domainVerification/mcdev.accenture.com.domainVerification-meta.json b/test/mockRoot/deploy/testInstance/testBU/domainVerification/mcdev.accenture.com.domainVerification-meta.json new file mode 100644 index 000000000..345aedafc --- /dev/null +++ b/test/mockRoot/deploy/testInstance/testBU/domainVerification/mcdev.accenture.com.domainVerification-meta.json @@ -0,0 +1,6 @@ +{ + "domain": "mcdev.accenture.com", + "status": "Verified", + "domainType": "SAP", + "isSendable": true +} diff --git a/test/mockRoot/deploy/testInstance/testBU/emailSend/testExisting_emailSend.emailSend-meta.json b/test/mockRoot/deploy/testInstance/testBU/emailSend/testExisting_emailSend.emailSend-meta.json new file mode 100644 index 000000000..00d988c6b --- /dev/null +++ b/test/mockRoot/deploy/testInstance/testBU/emailSend/testExisting_emailSend.emailSend-meta.json @@ -0,0 +1,36 @@ +{ + "Additional": "", + "AutoBccEmail": "", + "BccEmail": "", + "CCEmail": "", + "CreatedDate": "2022-11-14T12:27:29.963", + "CustomerKey": "testExisting_emailSend", + "DeduplicateByEmail": false, + "Description": "updated on deploy", + "DynamicEmailSubject": "someSubject", + "EmailSubject": "someSubject", + "ExclusionFilter": "", + "IsMultipart": true, + "IsSendLogging": false, + "IsWrapped": true, + "ModifiedDate": "2022-11-14T12:27:29.963", + "Name": "testExisting_emailSend", + "SendDefinitionList": [ + { + "DataSourceTypeID": "CustomObject", + "IsTestObject": false, + "Name": "", + "SendDefinitionListType": "SourceList", + "r__dataExtension_key": "testExisting_dataExtension", + "r__list_PathName": "Publication Lists/Demo Publication List" + } + ], + "SuppressTracking": false, + "TestEmailAddr": "", + "r__asset_key": "testExisting_asset_message", + "r__asset_name_readOnly": "testExisting_asset_message", + "r__deliveryProfile_key": "Default", + "r__folder_Path": "User-Initiated", + "r__sendClassification_key": "testExisting_sendClassification", + "r__senderProfile_key": "testExisting_senderProfile" +} diff --git a/test/mockRoot/deploy/testInstance/testBU/emailSend/testNew_emailSend.emailSend-meta.json b/test/mockRoot/deploy/testInstance/testBU/emailSend/testNew_emailSend.emailSend-meta.json new file mode 100644 index 000000000..7bfb7438a --- /dev/null +++ b/test/mockRoot/deploy/testInstance/testBU/emailSend/testNew_emailSend.emailSend-meta.json @@ -0,0 +1,36 @@ +{ + "Additional": "", + "AutoBccEmail": "", + "BccEmail": "", + "CCEmail": "", + "CreatedDate": "2022-11-14T12:27:29.963", + "CustomerKey": "testNew_emailSend", + "DeduplicateByEmail": false, + "Description": "created on deploy", + "DynamicEmailSubject": "testExisting_asset_email", + "EmailSubject": "testExisting_asset_email", + "ExclusionFilter": "", + "IsMultipart": true, + "IsSendLogging": false, + "IsWrapped": true, + "ModifiedDate": "2022-11-14T12:27:29.963", + "Name": "testNew_emailSend", + "SendDefinitionList": [ + { + "DataSourceTypeID": "CustomObject", + "IsTestObject": false, + "Name": "", + "SendDefinitionListType": "SourceList", + "r__dataExtension_key": "testExisting_dataExtension", + "r__list_PathName": "Publication Lists/Demo Publication List" + } + ], + "SuppressTracking": false, + "TestEmailAddr": "", + "r__asset_key": "testExisting_asset_message", + "r__asset_name_readOnly": "testExisting_asset_message", + "r__deliveryProfile_key": "Default", + "r__folder_Path": "User-Initiated", + "r__sendClassification_key": "testExisting_sendClassification", + "r__senderProfile_key": "testExisting_senderProfile" +} diff --git a/test/mockRoot/deploy/testInstance/testBU/event/testExisting_event.event-meta.json b/test/mockRoot/deploy/testInstance/testBU/event/testExisting_event.event-meta.json new file mode 100644 index 000000000..992b65256 --- /dev/null +++ b/test/mockRoot/deploy/testInstance/testBU/event/testExisting_event.event-meta.json @@ -0,0 +1,201 @@ +{ + "type": "APIEvent", + "name": "testExisting_event", + "description": "updated on deploy", + "mode": "Production", + "eventDefinitionKey": "testExisting_event", + "schema": { + "fields": [ + { + "name": "ContactId", + "dataType": "Text", + "maxLength": 18, + "isNullable": false, + "isPrimaryKey": true + }, + { + "name": "Type", + "dataType": "Text", + "maxLength": "50", + "isNullable": false, + "isPrimaryKey": false + }, + { + "name": "Status", + "dataType": "Text", + "maxLength": "50", + "isNullable": false, + "isPrimaryKey": true + }, + { + "name": "Respondent", + "dataType": "Text", + "maxLength": "256", + "isNullable": true, + "isPrimaryKey": false + }, + { + "name": "FirstName", + "dataType": "Text", + "maxLength": "256", + "isNullable": true, + "isPrimaryKey": false + }, + { + "name": "LastName", + "dataType": "Text", + "maxLength": "256", + "isNullable": true, + "isPrimaryKey": false + }, + { + "name": "PreferredLanguage", + "dataType": "Text", + "maxLength": "50", + "isNullable": true, + "isPrimaryKey": false + }, + { + "name": "TouchPoint", + "dataType": "Text", + "maxLength": "256", + "isNullable": true, + "isPrimaryKey": false + }, + { + "name": "Datestamp", + "dataType": "Date", + "defaultValue": "GetDate()", + "isNullable": true, + "isPrimaryKey": false + }, + { + "name": "StartDate", + "dataType": "Date", + "isNullable": true, + "defaultValue": "", + "isPrimaryKey": false + }, + { + "name": "EndDate", + "dataType": "Date", + "isNullable": true, + "isPrimaryKey": false + }, + { + "name": "BroadcastedNotificationDate", + "dataType": "Date", + "isNullable": true, + "defaultValue": "", + "isPrimaryKey": false + }, + { + "name": "FirstReminderDate", + "dataType": "Date", + "isNullable": true, + "isPrimaryKey": false + }, + { + "name": "SecondReminderDate", + "dataType": "Date", + "isNullable": true, + "isPrimaryKey": false + }, + { + "name": "Title", + "dataType": "Text", + "maxLength": "256", + "isNullable": true, + "isPrimaryKey": false + }, + { + "name": "DisplayName", + "dataType": "Text", + "maxLength": "256", + "isNullable": true, + "isPrimaryKey": false + }, + { + "name": "Text", + "dataType": "Text", + "maxLength": "256", + "isNullable": true, + "isPrimaryKey": false + }, + { + "name": "Description", + "dataType": "Text", + "maxLength": "4000", + "isNullable": true, + "isPrimaryKey": false + }, + { + "name": "Channel", + "dataType": "Text", + "maxLength": "256", + "isNullable": true, + "isPrimaryKey": false + }, + { + "name": "FirstReminderChannel", + "dataType": "Text", + "maxLength": "256", + "isNullable": true, + "isPrimaryKey": false + }, + { + "name": "SecondReminderChannel", + "dataType": "Text", + "maxLength": "256", + "isNullable": true, + "isPrimaryKey": false + }, + { + "name": "Email", + "dataType": "Email", + "maxLength": "", + "isNullable": true, + "isPrimaryKey": false + }, + { + "name": "ArticleOrTaskID", + "dataType": "Text", + "maxLength": "18", + "isNullable": false, + "isPrimaryKey": true + }, + { + "name": "Points", + "dataType": "Number", + "maxLength": "", + "isNullable": true, + "isPrimaryKey": false + }, + { + "name": "TaskType", + "dataType": "Text", + "maxLength": "255", + "isNullable": true, + "isPrimaryKey": false + }, + { + "name": "TaskArea", + "dataType": "Text", + "maxLength": "255", + "isNullable": true, + "isPrimaryKey": false + }, + { + "name": "AddedField", + "dataType": "Text", + "maxLength": "255", + "isNullable": true, + "isPrimaryKey": false + } + ], + "sendableCustomObjectField": "ContactId", + "sendableSubscriberField": "_SubscriberKey" + }, + "isVisibleInPicker": true, + "r__dataExtension_key": "testExisting_event - 2024-07-05T080154625" +} diff --git a/test/mockRoot/deploy/testInstance/testBU/event/testNew_event_withExistingDE.event-meta.json b/test/mockRoot/deploy/testInstance/testBU/event/testNew_event_withExistingDE.event-meta.json new file mode 100644 index 000000000..b7ae93d48 --- /dev/null +++ b/test/mockRoot/deploy/testInstance/testBU/event/testNew_event_withExistingDE.event-meta.json @@ -0,0 +1,233 @@ +{ + "type": "APIEvent", + "name": "testNew_event_withExistingDE", + "description": "created on deploy", + "createdDate": "0001-01-01T00:00:00", + "createdBy": 0, + "modifiedDate": "0001-01-01T00:00:00", + "modifiedBy": 0, + "eventDefinitionKey": "testNew_event_withExistingDE", + "sourceApplicationExtensionId": "7db1f972-f8b7-49b6-91b5-fa218e13953d", + "schema": { + "fields": [ + { + "name": "ContactId", + "dataType": "Text", + "maxLength": "18", + "isNullable": false, + "isPrimaryKey": true, + "isDevicePreference": false + }, + { + "name": "Type", + "dataType": "Text", + "maxLength": "50", + "isNullable": false, + "isPrimaryKey": false, + "isDevicePreference": false + }, + { + "name": "Status", + "dataType": "Text", + "maxLength": "50", + "isNullable": false, + "isPrimaryKey": true, + "isDevicePreference": false + }, + { + "name": "Respondent", + "dataType": "Text", + "maxLength": "256", + "isNullable": true, + "isPrimaryKey": false, + "isDevicePreference": false + }, + { + "name": "FirstName", + "dataType": "Text", + "maxLength": "256", + "isNullable": true, + "isPrimaryKey": false, + "isDevicePreference": false + }, + { + "name": "LastName", + "dataType": "Text", + "maxLength": "256", + "isNullable": true, + "isPrimaryKey": false, + "isDevicePreference": false + }, + { + "name": "PreferredLanguage", + "dataType": "Text", + "maxLength": "50", + "isNullable": true, + "isPrimaryKey": false, + "isDevicePreference": false + }, + { + "name": "TouchPoint", + "dataType": "Text", + "maxLength": "256", + "isNullable": true, + "isPrimaryKey": false, + "isDevicePreference": false + }, + { + "name": "Datestamp", + "dataType": "Date", + "isNullable": true, + "defaultValue": "GetDate()", + "isPrimaryKey": false, + "isDevicePreference": false + }, + { + "name": "StartDate", + "dataType": "Date", + "isNullable": true, + "defaultValue": "", + "isPrimaryKey": false, + "isDevicePreference": false + }, + { + "name": "EndDate", + "dataType": "Date", + "isNullable": true, + "isPrimaryKey": false, + "isDevicePreference": false + }, + { + "name": "BroadcastedNotificationDate", + "dataType": "Date", + "isNullable": true, + "defaultValue": "", + "isPrimaryKey": false, + "isDevicePreference": false + }, + { + "name": "FirstReminderDate", + "dataType": "Date", + "isNullable": true, + "isPrimaryKey": false, + "isDevicePreference": false + }, + { + "name": "SecondReminderDate", + "dataType": "Date", + "isNullable": true, + "isPrimaryKey": false, + "isDevicePreference": false + }, + { + "name": "Title", + "dataType": "Text", + "maxLength": "256", + "isNullable": true, + "isPrimaryKey": false, + "isDevicePreference": false + }, + { + "name": "DisplayName", + "dataType": "Text", + "maxLength": "256", + "isNullable": true, + "isPrimaryKey": false, + "isDevicePreference": false + }, + { + "name": "Text", + "dataType": "Text", + "maxLength": "256", + "isNullable": true, + "isPrimaryKey": false, + "isDevicePreference": false + }, + { + "name": "Description", + "dataType": "Text", + "maxLength": "4000", + "isNullable": true, + "isPrimaryKey": false, + "isDevicePreference": false + }, + { + "name": "Channel", + "dataType": "Text", + "maxLength": "256", + "isNullable": true, + "isPrimaryKey": false, + "isDevicePreference": false + }, + { + "name": "FirstReminderChannel", + "dataType": "Text", + "maxLength": "256", + "isNullable": true, + "isPrimaryKey": false, + "isDevicePreference": false + }, + { + "name": "SecondReminderChannel", + "dataType": "Text", + "maxLength": "256", + "isNullable": true, + "isPrimaryKey": false, + "isDevicePreference": false + }, + { + "name": "Email", + "dataType": "Email", + "maxLength": "", + "isNullable": true, + "isPrimaryKey": false, + "isDevicePreference": false + }, + { + "name": "ArticleOrTaskID", + "dataType": "Text", + "maxLength": "18", + "isNullable": false, + "isPrimaryKey": true, + "isDevicePreference": false + }, + { + "name": "Points", + "dataType": "Number", + "maxLength": "", + "isNullable": true, + "isPrimaryKey": false, + "isDevicePreference": false + }, + { + "name": "TaskType", + "dataType": "Text", + "maxLength": "255", + "isNullable": true, + "isPrimaryKey": false, + "isDevicePreference": false + }, + { + "name": "TaskArea", + "dataType": "Text", + "maxLength": "255", + "isNullable": true, + "isPrimaryKey": false, + "isDevicePreference": false + } + ], + "sendableCustomObjectField": "ContactId", + "sendableSubscriberField": "_SubscriberKey" + }, + "filterDefinitionId": "00000000-0000-0000-0000-000000000000", + "arguments": { + "serializedObjectType": 11 + }, + "metaData": {}, + "interactionCount": 0, + "isVisibleInPicker": true, + "category": "Event", + "publishedInteractionCount": 0, + "automationId": "00000000-0000-0000-0000-000000000000", + "r__dataExtension_key": "testExisting_event - 2024-07-05T080154625" +} diff --git a/test/mockRoot/deploy/testInstance/testBU/event/testNew_event_withSchema.event-meta.json b/test/mockRoot/deploy/testInstance/testBU/event/testNew_event_withSchema.event-meta.json new file mode 100644 index 000000000..777120a33 --- /dev/null +++ b/test/mockRoot/deploy/testInstance/testBU/event/testNew_event_withSchema.event-meta.json @@ -0,0 +1,194 @@ +{ + "type": "APIEvent", + "name": "testNew_event_withSchema", + "description": "created on deploy", + "mode": "Production", + "eventDefinitionKey": "testNew_event_withSchema", + "sourceApplicationExtensionId": "7db1f972-f8b7-49b6-91b5-fa218e13953d", + "schema": { + "fields": [ + { + "name": "ContactId", + "dataType": "Text", + "maxLength": 18, + "isNullable": false, + "isPrimaryKey": true + }, + { + "name": "Type", + "dataType": "Text", + "maxLength": "50", + "isNullable": false, + "isPrimaryKey": false + }, + { + "name": "Status", + "dataType": "Text", + "maxLength": "50", + "isNullable": false, + "isPrimaryKey": true + }, + { + "name": "Respondent", + "dataType": "Text", + "maxLength": "256", + "isNullable": true, + "isPrimaryKey": false + }, + { + "name": "FirstName", + "dataType": "Text", + "maxLength": "256", + "isNullable": true, + "isPrimaryKey": false + }, + { + "name": "LastName", + "dataType": "Text", + "maxLength": "256", + "isNullable": true, + "isPrimaryKey": false + }, + { + "name": "PreferredLanguage", + "dataType": "Text", + "maxLength": "50", + "isNullable": true, + "isPrimaryKey": false + }, + { + "name": "TouchPoint", + "dataType": "Text", + "maxLength": "256", + "isNullable": true, + "isPrimaryKey": false + }, + { + "name": "Datestamp", + "dataType": "Date", + "defaultValue": "GetDate()", + "isNullable": true, + "isPrimaryKey": false + }, + { + "name": "StartDate", + "dataType": "Date", + "isNullable": true, + "defaultValue": "", + "isPrimaryKey": false + }, + { + "name": "EndDate", + "dataType": "Date", + "isNullable": true, + "isPrimaryKey": false + }, + { + "name": "BroadcastedNotificationDate", + "dataType": "Date", + "isNullable": true, + "defaultValue": "", + "isPrimaryKey": false + }, + { + "name": "FirstReminderDate", + "dataType": "Date", + "isNullable": true, + "isPrimaryKey": false + }, + { + "name": "SecondReminderDate", + "dataType": "Date", + "isNullable": true, + "isPrimaryKey": false + }, + { + "name": "Title", + "dataType": "Text", + "maxLength": "256", + "isNullable": true, + "isPrimaryKey": false + }, + { + "name": "DisplayName", + "dataType": "Text", + "maxLength": "256", + "isNullable": true, + "isPrimaryKey": false + }, + { + "name": "Text", + "dataType": "Text", + "maxLength": "256", + "isNullable": true, + "isPrimaryKey": false + }, + { + "name": "Description", + "dataType": "Text", + "maxLength": "4000", + "isNullable": true, + "isPrimaryKey": false + }, + { + "name": "Channel", + "dataType": "Text", + "maxLength": "256", + "isNullable": true, + "isPrimaryKey": false + }, + { + "name": "FirstReminderChannel", + "dataType": "Text", + "maxLength": "256", + "isNullable": true, + "isPrimaryKey": false + }, + { + "name": "SecondReminderChannel", + "dataType": "Text", + "maxLength": "256", + "isNullable": true, + "isPrimaryKey": false + }, + { + "name": "Email", + "dataType": "Email", + "maxLength": "", + "isNullable": true, + "isPrimaryKey": false + }, + { + "name": "ArticleOrTaskID", + "dataType": "Text", + "maxLength": "18", + "isNullable": false, + "isPrimaryKey": true + }, + { + "name": "Points", + "dataType": "Number", + "maxLength": "", + "isNullable": true, + "isPrimaryKey": false + }, + { + "name": "TaskType", + "dataType": "Text", + "maxLength": "255", + "isNullable": true, + "isPrimaryKey": false + }, + { + "name": "TaskArea", + "dataType": "Text", + "maxLength": "255", + "isNullable": true, + "isPrimaryKey": false + } + ], + "sendableCustomObjectField": "ContactId", + "sendableSubscriberField": "_SubscriberKey" + }, + "isVisibleInPicker": true +} diff --git a/test/mockRoot/deploy/testInstance/testBU/fileLocation/ExactTarget Enhanced FTP.fileLocation-meta.json b/test/mockRoot/deploy/testInstance/testBU/fileLocation/ExactTarget Enhanced FTP.fileLocation-meta.json new file mode 100644 index 000000000..63c978202 --- /dev/null +++ b/test/mockRoot/deploy/testInstance/testBU/fileLocation/ExactTarget Enhanced FTP.fileLocation-meta.json @@ -0,0 +1,5 @@ +{ + "name": "ExactTarget Enhanced FTP", + "customerKey": "ExactTarget Enhanced FTP", + "c__locationType": "Enhanced FTP Site Import Directory" +} diff --git a/test/mockRoot/deploy/testInstance/testBU/fileLocation/testExisting_fileLocation_aws.fileLocation-meta.json b/test/mockRoot/deploy/testInstance/testBU/fileLocation/testExisting_fileLocation_aws.fileLocation-meta.json new file mode 100644 index 000000000..a258da84c --- /dev/null +++ b/test/mockRoot/deploy/testInstance/testBU/fileLocation/testExisting_fileLocation_aws.fileLocation-meta.json @@ -0,0 +1,14 @@ +{ + "name": "testExisting_fileLocation_aws_name", + "customerKey": "testExisting_fileLocation_aws", + "description": "updated via deploy", + "awsFileTransferLocation": { + "regionName": "eucentral1", + "transferAccelerationEnabled": false, + "accessKeyId": "key-id", + "relativePath": "my/path", + "bucketName": "bucket-name", + "authType": "AccessKey" + }, + "c__locationType": "Amazon Simple Storage Service" +} diff --git a/test/mockRoot/deploy/testInstance/testBU/fileLocation/testExisting_fileLocation_exsftp.fileLocation-meta.json b/test/mockRoot/deploy/testInstance/testBU/fileLocation/testExisting_fileLocation_exsftp.fileLocation-meta.json new file mode 100644 index 000000000..d794debbf --- /dev/null +++ b/test/mockRoot/deploy/testInstance/testBU/fileLocation/testExisting_fileLocation_exsftp.fileLocation-meta.json @@ -0,0 +1,12 @@ +{ + "name": "testExisting_fileLocation_exsftp_name", + "customerKey": "testExisting_fileLocation_exsftp", + "description": "updated via deploy", + "sFtpFileTransferLocation": { + "portNumber": 22, + "userName": "abc", + "url": "sftp://test.com", + "authType": "Password" + }, + "c__locationType": "External SFTP Site" +} diff --git a/test/mockRoot/deploy/testInstance/testBU/fileTransfer/testExisting_fileTransfer.fileTransfer-meta.json b/test/mockRoot/deploy/testInstance/testBU/fileTransfer/testExisting_fileTransfer.fileTransfer-meta.json new file mode 100644 index 000000000..0c460f792 --- /dev/null +++ b/test/mockRoot/deploy/testInstance/testBU/fileTransfer/testExisting_fileTransfer.fileTransfer-meta.json @@ -0,0 +1,17 @@ +{ + "createdDate": "2022-11-09T05:31:56.477", + "customerKey": "testExisting_fileTransfer", + "description": "17.11.2022", + "fileSpec": "%%Year%% updated via deploy", + "isCompressed": false, + "isEncrypted": false, + "isFileSpecLocalized": false, + "isPgp": false, + "isUpload": true, + "maxFileAge": 0, + "maxFileAgeScheduleOffset": 0, + "maxImportFrequency": 0, + "modifiedDate": "2022-11-17T07:13:20.05", + "name": "testExisting_fileTransfer", + "r__fileLocation_name": "ExactTarget Enhanced FTP" +} diff --git a/test/mockRoot/deploy/testInstance/testBU/fileTransfer/testNew_fileTransfer.fileTransfer-meta.json b/test/mockRoot/deploy/testInstance/testBU/fileTransfer/testNew_fileTransfer.fileTransfer-meta.json new file mode 100644 index 000000000..30de51868 --- /dev/null +++ b/test/mockRoot/deploy/testInstance/testBU/fileTransfer/testNew_fileTransfer.fileTransfer-meta.json @@ -0,0 +1,17 @@ +{ + "createdDate": "2022-11-09T05:31:56.477", + "customerKey": "testNew_fileTransfer", + "description": "17.11.2022", + "fileSpec": "%%Year%% created on deploy", + "isCompressed": false, + "isEncrypted": false, + "isFileSpecLocalized": false, + "isPgp": false, + "isUpload": true, + "maxFileAge": 0, + "maxFileAgeScheduleOffset": 0, + "maxImportFrequency": 0, + "modifiedDate": "2022-11-17T07:13:20.05", + "name": "testNew_fileTransfer", + "r__fileLocation_name": "ExactTarget Enhanced FTP" +} diff --git a/test/mockRoot/deploy/testInstance/testBU/filter/testExisting_filter.filter-meta.json b/test/mockRoot/deploy/testInstance/testBU/filter/testExisting_filter.filter-meta.json new file mode 100644 index 000000000..f8d1fe557 --- /dev/null +++ b/test/mockRoot/deploy/testInstance/testBU/filter/testExisting_filter.filter-meta.json @@ -0,0 +1,10 @@ +{ + "customerKey": "testExisting_filter", + "name": "testExisting_filter", + "description": "updated on deploy", + "statusId": 1, + "r__dataFilter_key": "testExisting_dataFilter", + "r__destination_dataExtension_key": "testExisting_dataExtension_exclusion", + "r__source_dataExtension_key": "testExisting_dataExtension", + "r__folder_Path": "Filter" +} diff --git a/test/mockRoot/deploy/testInstance/testBU/filter/testNew_filter.filter-meta.json b/test/mockRoot/deploy/testInstance/testBU/filter/testNew_filter.filter-meta.json new file mode 100644 index 000000000..fa4ea3d10 --- /dev/null +++ b/test/mockRoot/deploy/testInstance/testBU/filter/testNew_filter.filter-meta.json @@ -0,0 +1,11 @@ +{ + "customerKey": "testNew_filter", + "name": "testNew_filter", + "description": "created via deploy", + "modifiedDate": "2026-01-28T10:14:46.717", + "statusId": 1, + "r__dataFilter_key": "testExisting_dataFilter", + "r__destination_dataExtension_key": "testExisting_dataExtension_exclusion", + "r__source_dataExtension_key": "testExisting_dataExtension", + "r__folder_Path": "Filter/filterSubfolder" +} diff --git a/test/mockRoot/deploy/testInstance/testBU/importFile/testExisting_importFile.importFile-meta.json b/test/mockRoot/deploy/testInstance/testBU/importFile/testExisting_importFile.importFile-meta.json new file mode 100644 index 000000000..86b0538ca --- /dev/null +++ b/test/mockRoot/deploy/testInstance/testBU/importFile/testExisting_importFile.importFile-meta.json @@ -0,0 +1,36 @@ +{ + "allowErrors": true, + "createdDate": "2022-11-09T05:32:30.533", + "customerKey": "testExisting_importFile", + "dateFormatLocale": "en-US", + "deleteFile": false, + "description": "updated on deploy", + "encodingName": "utf-8", + "fieldMappingType": "InferFromColumnHeadings", + "fieldMappings": [], + "fileNamingPattern": "blabla", + "fileTransferLocationTypeId": 0, + "fileType": "CSV", + "filter": "", + "hasColumnHeader": true, + "isOrderedImport": true, + "isSequential": true, + "maxFileAgeHours": 0, + "maxFileAgeScheduleOffsetHours": 0, + "maxImportFrequencyHours": 0, + "modifiedDate": "2022-11-17T07:13:03.95", + "name": "testExisting_importFile", + "sendEmailNotification": false, + "standardQuotedStrings": true, + "c__blankFileProcessing": "Process", + "c__dataAction": "AddUpdate", + "c__subscriberImportType": "DataExtension", + "destination": { + "c__type": "DataExtension", + "r__dataExtension_key": "testExisting_dataExtension" + }, + "source": { + "c__type": "File Location", + "r__fileLocation_name": "ExactTarget Enhanced FTP" + } +} diff --git a/test/mockRoot/deploy/testInstance/testBU/importFile/testNew_importFile.importFile-meta.json b/test/mockRoot/deploy/testInstance/testBU/importFile/testNew_importFile.importFile-meta.json new file mode 100644 index 000000000..d8846142f --- /dev/null +++ b/test/mockRoot/deploy/testInstance/testBU/importFile/testNew_importFile.importFile-meta.json @@ -0,0 +1,34 @@ +{ + "allowErrors": true, + "createdDate": "2022-11-09T05:32:30.533", + "customerKey": "testNew_importFile", + "dateFormatLocale": "en-US", + "deleteFile": false, + "description": "created via deploy", + "fieldMappingType": "InferFromColumnHeadings", + "fieldMappings": [], + "fileNamingPattern": "blabla", + "fileTransferLocationTypeId": 0, + "fileType": "CSV", + "filter": "", + "hasColumnHeader": true, + "isOrderedImport": true, + "isSequential": true, + "maxFileAgeHours": 0, + "maxFileAgeScheduleOffsetHours": 0, + "maxImportFrequencyHours": 0, + "modifiedDate": "2022-11-17T07:13:03.95", + "name": "testNew_importFile", + "sendEmailNotification": false, + "standardQuotedStrings": true, + "c__subscriberImportType": "DataExtension", + "c__dataAction": "AddUpdate", + "destination": { + "c__type": "DataExtension", + "r__dataExtension_key": "testExisting_dataExtension" + }, + "source": { + "c__type": "File Location", + "r__fileLocation_name": "ExactTarget Enhanced FTP" + } +} diff --git a/test/mockRoot/deploy/testInstance/testBU/journey/testExisting_journey_Multistep.journey-meta.json b/test/mockRoot/deploy/testInstance/testBU/journey/testExisting_journey_Multistep.journey-meta.json new file mode 100644 index 000000000..e12c3fa55 --- /dev/null +++ b/test/mockRoot/deploy/testInstance/testBU/journey/testExisting_journey_Multistep.journey-meta.json @@ -0,0 +1,418 @@ +{ + "key": "testExisting_journey_Multistep", + "name": "testExisting_journey_Multistep", + "lastPublishedDate": "0001-01-01T00:00:00", + "description": "", + "version": 1, + "workflowApiVersion": 1, + "createdDate": "2024-05-04T05:54:48.027", + "modifiedDate": "2024-05-04T17:25:57.9", + "activities": [ + { + "id": "7ba1e59a-6be4-46c7-b76f-4c06feb1268a", + "key": "EMAILV2-1", + "name": "my custom activity name", + "description": "", + "type": "EMAILV2", + "outcomes": [ + { + "key": "ff60a294-3804-4165-85cd-c7c19c8e3a6d", + "next": "WAITBYDURATION-1", + "arguments": {}, + "metaData": { "invalid": false } + } + ], + "arguments": {}, + "configurationArguments": { + "applicationExtensionKey": "jb-email-activity", + "isModified": true, + "googleAnalyticsCampaignName": "", + "r__triggeredSend_key": "testExisting_triggeredSend", + "triggeredSend": { + "autoAddSubscribers": false, + "autoUpdateSubscribers": false, + "bccEmail": [], + "ccEmail": [], + "created": { "name": "", "date": "" }, + "description": "my custom description", + "domainExclusions": [], + "dynamicEmailSubject": "You are successfully unsubscribed", + "emailSubject": "You are successfully unsubscribed", + "exclusionFilter": "", + "isSalesforceTracking": false, + "isMultipart": false, + "isSendLogging": true, + "isStoppedOnJobError": false, + "modified": { "name": "", "date": "" }, + "preHeader": "testExisting_ email preheader", + "throttleOpens": "1/1/0001 12:00:00 AM", + "throttleCloses": "1/1/0001 12:00:00 AM", + "isTrackingClicks": true, + "suppressTracking": false, + "triggeredSendStatus": "New", + "r__list_PathName": { "publicationList": "my subscribers/All Subscribers" }, + "r__deliveryProfile_key": "Default", + "r__senderProfile_key": "testExisting_senderProfile", + "r__sendClassification_key": "testExisting_sendClassification", + "c__priority": "Medium", + "r__asset_name_readOnly": "testExisting_asset_message", + "r__asset_key": "testExisting_asset_message", + "r__triggeredSend_key": "testExisting_triggeredSend" + } + }, + "metaData": { + "category": "message", + "version": "1.0", + "icon": "https://jb-email-activity.s7.marketingcloudapps.com/img/email-icon.svg", + "iconSmall": "https://jb-email-activity.s7.marketingcloudapps.com/img/email-icon.svg", + "statsContactIcon": null, + "original_icon": "/img/email-icon.svg", + "original_iconSmall": "/img/email-icon.svg", + "sections": {}, + "isConfigured": true + }, + "schema": { + "arguments": { + "requestID": { + "dataType": "Text", + "isNullable": true, + "direction": "Out", + "readOnly": false, + "access": "Hidden" + }, + "messageKey": { + "dataType": "Text", + "isNullable": true, + "direction": "Out", + "readOnly": false, + "access": "Hidden" + }, + "activityId": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "definitionId": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": true, + "access": "Hidden" + }, + "emailSubjectDataBound": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": true, + "access": "Hidden" + }, + "contactId": { + "dataType": "Number", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "contactKey": { + "dataType": "Text", + "isNullable": false, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "emailAddress": { + "dataType": "Text", + "isNullable": false, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "sourceCustomObjectId": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "sourceCustomObjectKey": { + "dataType": "LongNumber", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "fieldType": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "eventData": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "obfuscationProperties": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "customObjectKey": { + "dataType": "LongNumber", + "isNullable": true, + "direction": "In", + "readOnly": true, + "access": "Hidden" + }, + "definitionInstanceId": { + "dataType": "Text", + "isNullable": false, + "direction": "In", + "readOnly": false, + "access": "Hidden" + } + } + } + }, + { + "id": "342dd0aa-a6be-401e-8614-3538800bfd7c", + "key": "MULTICRITERIADECISIONV2-1", + "name": "", + "description": "", + "type": "MULTICRITERIADECISION", + "outcomes": [ + { + "key": "default_path_1", + "next": "EMAILV2-1", + "arguments": {}, + "metaData": { + "label": "send message", + "skipI18n": true, + "isLabelFromConversion": false, + "criteriaDescription": "Email is not null" + } + }, + { + "key": "remainder_path", + "next": "WAITBYDURATION-2", + "arguments": {}, + "metaData": { "label": null } + } + ], + "arguments": {}, + "configurationArguments": { + "criteria": { + "default_path_1": "<FilterDefinition><ConditionSet Operator=\"AND\" ConditionSetName=\"Individual Filter Grouping\"><Condition IsEphemeralAttribute=\"true\" Key=\"Event.DEAudience-2e3c73b6-48cc-2ec0-5522-48636e1a236e.Email\" Operator=\"IsNotNull\" UiMetaData=\"{}\"><Value><![CDATA[]]></Value></Condition></ConditionSet></FilterDefinition>" + }, + "schemaVersionId": "252" + }, + "metaData": { "isConfigured": true }, + "schema": { + "arguments": { + "actualChoice": { + "dataType": "Number", + "isNullable": false, + "direction": "Out", + "readOnly": false, + "access": "Hidden" + }, + "filterResult": { + "dataType": "Text", + "isNullable": false, + "direction": "In", + "readOnly": true, + "access": "Hidden" + } + } + } + }, + { + "id": "e2a486cf-c85f-4543-88a2-d579cac1e0de", + "key": "WAITBYDURATION-1", + "name": "1 day", + "description": "", + "type": "WAIT", + "outcomes": [ + { + "key": "97af222a-450a-429e-8925-649b72f01ccf", + "arguments": {}, + "metaData": { "invalid": false } + } + ], + "arguments": {}, + "configurationArguments": { "waitDuration": 1, "waitUnit": "DAYS" }, + "metaData": { "isConfigured": true, "uiType": "WAITBYDURATION" }, + "schema": { + "arguments": { + "endDate": { + "dataType": "Date", + "isNullable": false, + "direction": "Out", + "readOnly": false, + "access": "Hidden" + }, + "waitEndDateAttributeDataBound": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "waitDefinitionId": { + "dataType": "Text", + "isNullable": false, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "waitForEventId": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "executionMode": { + "dataType": "Text", + "isNullable": false, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "startActivityKey": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "waitQueueId": { + "dataType": "LongNumber", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + } + } + } + }, + { + "id": "70572b1a-e274-4f09-a3fa-6fc0732ec52b", + "key": "WAITBYDURATION-2", + "name": "", + "description": "", + "type": "WAIT", + "outcomes": [ + { + "key": "a0908f9f-bc3c-47f7-9489-7fef5af25ce3", + "arguments": {}, + "metaData": { "invalid": false } + } + ], + "arguments": {}, + "configurationArguments": { "waitDuration": 1, "waitUnit": "DAYS" }, + "metaData": { "isConfigured": true, "uiType": "WAITBYDURATION" }, + "schema": { + "arguments": { + "endDate": { + "dataType": "Date", + "isNullable": false, + "direction": "Out", + "readOnly": false, + "access": "Hidden" + }, + "waitEndDateAttributeDataBound": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "waitDefinitionId": { + "dataType": "Text", + "isNullable": false, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "waitForEventId": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "executionMode": { + "dataType": "Text", + "isNullable": false, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "startActivityKey": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "waitQueueId": { + "dataType": "LongNumber", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + } + } + } + } + ], + "triggers": [ + { + "key": "TRIGGER", + "name": "TRIGGER", + "description": "", + "type": "EmailAudience", + "outcomes": [], + "arguments": {}, + "configurationArguments": {}, + "metaData": { + "r__event_key": "DEAudience-2e3c73b6-48cc-2ec0-5522-48636e1a236e", + "chainType": "None", + "configurationRequired": false, + "iconUrl": "/images/icon-data-extension.svg", + "title": "Data Extension", + "entrySourceGroupConfigUrl": "jb:///data/entry/audience/entrysourcegroupconfig.json", + "sourceInteractionId": "00000000-0000-0000-0000-000000000000" + } + } + ], + "goals": [], + "exits": [], + "notifiers": [], + "entryMode": "NotSet", + "definitionType": "Multistep", + "channel": "", + "defaults": { + "email": ["{{Event.DEAudience-2e3c73b6-48cc-2ec0-5522-48636e1a236e.\"Email\"}}"], + "properties": { + "analyticsTracking": { + "enabled": true, + "analyticsType": "google", + "urlDomainsToTrack": [] + } + } + }, + "metaData": { "dataSource": "ContactsModel", "highThroughputSending": { "email": false } }, + "executionMode": "Production", + "status": "Draft", + "scheduledStatus": "Draft", + "r__folder_Path": "my journeys" +} diff --git a/test/mockRoot/deploy/testInstance/testBU/journey/testExisting_journey_Quicksend.journey-meta.json b/test/mockRoot/deploy/testInstance/testBU/journey/testExisting_journey_Quicksend.journey-meta.json new file mode 100644 index 000000000..237c73925 --- /dev/null +++ b/test/mockRoot/deploy/testInstance/testBU/journey/testExisting_journey_Quicksend.journey-meta.json @@ -0,0 +1,232 @@ +{ + "key": "testExisting_journey_Quicksend", + "name": "testExisting_journey_Quicksend", + "lastPublishedDate": "0001-01-01T00:00:00", + "description": "updated on deploy", + "version": 1, + "workflowApiVersion": 1, + "createdDate": "2024-04-24T12:18:43.47", + "modifiedDate": "2024-04-24T12:19:12.803", + "activities": [ + { + "id": "e20dcaa3-a750-44cf-9ce8-42d00378b8b4", + "key": "EMAILV2-1", + "name": "testExisting_asset_mail", + "description": "", + "type": "EMAILV2", + "outcomes": [ + { + "key": "a6b9c1af-cd89-4ce8-ba4f-bd4289188dc2", + "arguments": {}, + "metaData": { "invalid": false } + } + ], + "arguments": {}, + "configurationArguments": { + "isModified": true, + "googleAnalyticsCampaignName": "", + "triggeredSend": { + "autoAddSubscribers": true, + "autoUpdateSubscribers": true, + "bccEmail": "", + "ccEmail": "", + "created": {}, + "description": "my activity info text", + "dynamicEmailSubject": "testExisting_ email subject", + "emailSubject": "testExisting_ email subject", + "exclusionFilter": "/* insert ampscript here */", + "isSalesforceTracking": false, + "isMultipart": true, + "isSendLogging": true, + "isStoppedOnJobError": false, + "keyword": "", + "modified": {}, + "preHeader": "testExisting_ email preheader", + "suppressTracking": true, + "throttleLimit": 0, + "throttleOpens": "1/1/0001 12:00:00 AM", + "throttleCloses": "1/1/0001 12:00:00 AM", + "isTrackingClicks": true, + "r__list_PathName": { + "publicationList": "my subscribers/All Subscribers", + "suppressionLists": ["Suppression Lists/testExisting_suppressionList"] + }, + "r__dataExtension_key": { + "domainExclusions": ["testExisting_DomainExclusion"] + }, + "r__senderProfile_key": "testExisting_senderProfile", + "r__sendClassification_key": "testExisting_sendClassification", + "c__priority": "High", + "r__asset_name_readOnly": "testExisting_asset_message", + "r__asset_key": "testExisting_asset_message" + }, + "applicationExtensionKey": "jb-email-activity" + }, + "metaData": { + "category": "message", + "version": "1.0", + "icon": "https://jb-email-activity.s7.marketingcloudapps.com/img/email-icon.svg", + "iconSmall": "https://jb-email-activity.s7.marketingcloudapps.com/img/email-icon.svg", + "statsContactIcon": null, + "original_icon": "/img/email-icon.svg", + "original_iconSmall": "/img/email-icon.svg", + "sections": {}, + "isConfigured": true + }, + "schema": { + "arguments": { + "requestID": { + "dataType": "Text", + "isNullable": true, + "direction": "Out", + "readOnly": false, + "access": "Hidden" + }, + "messageKey": { + "dataType": "Text", + "isNullable": true, + "direction": "Out", + "readOnly": false, + "access": "Hidden" + }, + "activityId": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "definitionId": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": true, + "access": "Hidden" + }, + "emailSubjectDataBound": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": true, + "access": "Hidden" + }, + "contactId": { + "dataType": "Number", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "contactKey": { + "dataType": "Text", + "isNullable": false, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "emailAddress": { + "dataType": "Text", + "isNullable": false, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "sourceCustomObjectId": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "sourceCustomObjectKey": { + "dataType": "LongNumber", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "fieldType": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "eventData": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "obfuscationProperties": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "customObjectKey": { + "dataType": "LongNumber", + "isNullable": true, + "direction": "In", + "readOnly": true, + "access": "Hidden" + }, + "definitionInstanceId": { + "dataType": "Text", + "isNullable": false, + "direction": "In", + "readOnly": false, + "access": "Hidden" + } + } + } + } + ], + "triggers": [ + { + "key": "TRIGGER", + "name": "TRIGGER", + "description": "", + "type": "EmailAudience", + "outcomes": [], + "arguments": {}, + "configurationArguments": {}, + "metaData": { + "sourceInteractionId": "00000000-0000-0000-0000-000000000000", + "eventDefinitionKey": "DEAudience-11be962d-064c-83d9-2804-7d1befc10325", + "chainType": "None", + "configurationRequired": false, + "iconUrl": "/images/icon-data-extension.svg", + "title": "Data Extension", + "entrySourceGroupConfigUrl": "jb:///data/entry/audience/entrysourcegroupconfig.json" + } + } + ], + "goals": [], + "exits": [], + "notifiers": [], + "entryMode": "MultipleEntries", + "definitionType": "Quicksend", + "channel": "email", + "defaults": { + "email": ["{{Event.DEAudience-11be962d-064c-83d9-2804-7d1befc10325.\"Email\"}}"], + "properties": { + "analyticsTracking": { + "enabled": true, + "analyticsType": "google", + "urlDomainsToTrack": [] + } + } + }, + "metaData": { + "dataSource": "ContactsModel", + "isScheduleSet": true, + "highThroughputSending": { "email": false } + }, + "executionMode": "Production", + "status": "Draft", + "scheduledStatus": "Draft", + "r__folder_Path": "my journeys" +} diff --git a/test/mockRoot/deploy/testInstance/testBU/journey/testExisting_journey_updatecontact.journey-meta.json b/test/mockRoot/deploy/testInstance/testBU/journey/testExisting_journey_updatecontact.journey-meta.json new file mode 100644 index 000000000..7bdad926c --- /dev/null +++ b/test/mockRoot/deploy/testInstance/testBU/journey/testExisting_journey_updatecontact.journey-meta.json @@ -0,0 +1,108 @@ +{ + "key": "testExisting_journey_updatecontact", + "name": "testExisting_journey_updatecontact", + "lastPublishedDate": "0001-01-01T00:00:00", + "description": "", + "version": 1, + "workflowApiVersion": 1, + "createdDate": "2024-05-04T05:54:48.027", + "modifiedDate": "2024-05-04T17:25:57.9", + "activities": [ + { + "key": "UPDATECONTACTDATAV2-1", + "name": "Update Contact - TEST", + "description": "", + "type": "UPDATECONTACTDATA", + "outcomes": [ + { + "key": "9f21d42b-4679-4561-911a-4bccf84672ba", + "arguments": {}, + "metaData": { + "invalid": false + } + } + ], + "arguments": { + "activityData": { + "updateContactFields": [ + { + "r__dataExtension_key": "testExisting_dataExtension", + "r__dataExtensionField_name": "LastName", + "value": "TEST" + } + ] + } + }, + "configurationArguments": {}, + "metaData": { + "isConfigured": true + }, + "schema": { + "arguments": { + "activityData": { + "dataType": "Text", + "isNullable": false, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "contactKey": { + "dataType": "Text", + "isNullable": false, + "direction": "In", + "readOnly": false, + "access": "Hidden" + } + } + } + } + ], + "triggers": [ + { + "key": "TRIGGER", + "name": "TRIGGER", + "description": "", + "type": "EmailAudience", + "outcomes": [], + "arguments": {}, + "configurationArguments": {}, + "metaData": { + "r__event_key": "DEAudience-2e3c73b6-48cc-2ec0-5522-48636e1a236e", + "chainType": "None", + "configurationRequired": false, + "iconUrl": "/images/icon-data-extension.svg", + "title": "Data Extension", + "entrySourceGroupConfigUrl": "jb:///data/entry/audience/entrysourcegroupconfig.json", + "sourceInteractionId": "00000000-0000-0000-0000-000000000000" + } + } + ], + "goals": [], + "exits": [], + "notifiers": [], + "entryMode": "NotSet", + "definitionType": "Multistep", + "channel": "", + "defaults": { + "email": [ + "{{Event.DEAudience-2e3c73b6-48cc-2ec0-5522-48636e1a236e.\"Email\"}}" + ], + "properties": { + "analyticsTracking": { + "enabled": true, + "analyticsType": "google", + "urlDomainsToTrack": [] + } + } + }, + "metaData": { + "dataSource": "ContactsModel", + "highThroughputSending": { + "email": false + } + }, + "executionMode": "Production", + "status": "Draft", + "scheduledStatus": "Draft", + "r__folder_Path": "my journeys" +} \ No newline at end of file diff --git a/test/mockRoot/deploy/testInstance/testBU/journey/testExisting_temail.journey-meta.json b/test/mockRoot/deploy/testInstance/testBU/journey/testExisting_temail.journey-meta.json new file mode 100644 index 000000000..a5436a85c --- /dev/null +++ b/test/mockRoot/deploy/testInstance/testBU/journey/testExisting_temail.journey-meta.json @@ -0,0 +1,212 @@ +{ + "key": "testExisting_temail", + "name": "testExisting_temail", + "lastPublishedDate": "0001-01-01T00:00:00", + "description": "", + "version": 1, + "workflowApiVersion": 1, + "createdDate": "2022-03-24T02:20:32.74", + "modifiedDate": "2022-03-24T02:20:40.45", + "activities": [ + { + "id": "9606bcb0-9246-4610-9800-963bc77fc20a", + "key": "EMAILV2-4", + "name": "testExisting_temail", + "description": "", + "type": "EMAILV2", + "outcomes": [ + { + "key": "1f44021a-74ac-49be-a07c-67862228214d", + "arguments": {}, + "metaData": { "invalid": false } + } + ], + "arguments": {}, + "configurationArguments": { + "applicationExtensionKey": "jb-email-activity", + "isModified": true, + "triggeredSend": { + "autoAddSubscribers": true, + "autoUpdateSubscribers": true, + "bccEmail": [], + "ccEmail": [], + "created": {}, + "domainExclusions": [], + "dynamicEmailSubject": "test email", + "emailSubject": "test email", + "exclusionFilter": "", + "isSalesforceTracking": true, + "isMultipart": true, + "isSendLogging": false, + "isStoppedOnJobError": false, + "modified": {}, + "preHeader": "", + "throttleOpens": "1/1/0001 12:00:00 AM", + "throttleCloses": "1/1/0001 12:00:00 AM", + "isTrackingClicks": true, + "r__list_PathName": { "publicationList": "my subscribers/All Subscribers" }, + "r__deliveryProfile_key": "Default", + "r__senderProfile_key": "Default", + "r__sendClassification_key": "Default Transactional", + "c__priority": "Medium", + "r__asset_name_readOnly": "testExisting_asset_message", + "r__asset_key": "testExisting_asset_message" + }, + "r__transactionalEmail_key": "testExisting_temail" + }, + "metaData": { + "highThroughput": { "r__dataExtension_key": "testExisting_dataExtension" }, + "sections": {}, + "isConfigured": true + }, + "schema": { + "arguments": { + "requestID": { + "dataType": "Text", + "isNullable": true, + "direction": "Out", + "readOnly": false, + "access": "Hidden" + }, + "messageKey": { + "dataType": "Text", + "isNullable": true, + "direction": "Out", + "readOnly": false, + "access": "Hidden" + }, + "activityId": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "definitionId": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": true, + "access": "Hidden" + }, + "emailSubjectDataBound": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": true, + "access": "Hidden" + }, + "contactId": { + "dataType": "Number", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "contactKey": { + "dataType": "Text", + "isNullable": false, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "emailAddress": { + "dataType": "Text", + "isNullable": false, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "sourceCustomObjectId": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "sourceCustomObjectKey": { + "dataType": "LongNumber", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "fieldType": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "eventData": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "obfuscationProperties": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "customObjectKey": { + "dataType": "LongNumber", + "isNullable": true, + "direction": "In", + "readOnly": true, + "access": "Hidden" + }, + "definitionInstanceId": { + "dataType": "Text", + "isNullable": false, + "direction": "In", + "readOnly": false, + "access": "Hidden" + } + } + } + } + ], + "triggers": [ + { + "key": "TRIGGER", + "name": "TRIGGER", + "description": "", + "type": "transactional-api", + "outcomes": [], + "arguments": {}, + "configurationArguments": {}, + "metaData": { + "chainType": "none", + "configurationRequired": false, + "iconUrl": "/images/icon_journeyBuilder-event-transactional-blue.svg", + "title": "Transactional API Event", + "category": "Transactional", + "entrySourceGroupConfigUrl": "null" + } + } + ], + "goals": [], + "exits": [], + "notifiers": [], + "entryMode": "MultipleEntries", + "definitionType": "Transactional", + "channel": "email", + "defaults": { + "properties": { + "analyticsTracking": { + "enabled": false, + "analyticsType": "google", + "urlDomainsToTrack": [] + } + } + }, + "metaData": {}, + "executionMode": "Production", + "status": "Published", + "scheduledStatus": "Draft", + "r__folder_Path": "my journeys" +} diff --git a/test/mockRoot/deploy/testInstance/testBU/journey/testExisting_temail_notPublished.journey-meta.json b/test/mockRoot/deploy/testInstance/testBU/journey/testExisting_temail_notPublished.journey-meta.json new file mode 100644 index 000000000..26357c013 --- /dev/null +++ b/test/mockRoot/deploy/testInstance/testBU/journey/testExisting_temail_notPublished.journey-meta.json @@ -0,0 +1,217 @@ +{ + "activities": [ + { + "arguments": {}, + "configurationArguments": { + "applicationExtensionKey": "jb-email-activity", + "isModified": true, + "r__transactionalEmail_key": "testExisting_temail_notPublished", + "triggeredSend": { + "autoAddSubscribers": true, + "autoUpdateSubscribers": true, + "bccEmail": [], + "c__priority": "Medium", + "ccEmail": [], + "created": {}, + "domainExclusions": [], + "dynamicEmailSubject": "%%=treatascontent(@subject)=%%", + "emailSubject": "%%=treatascontent(@subject)=%%", + "exclusionFilter": "", + "isMultipart": true, + "isSalesforceTracking": true, + "isSendLogging": false, + "isStoppedOnJobError": false, + "isTrackingClicks": true, + "modified": {}, + "preHeader": "%%=treatascontent(@preheader)=%%\n", + "r__asset_key": "testExisting_asset_message", + "r__asset_name_readOnly": "testExisting_asset_message", + "r__deliveryProfile_key": "Default", + "r__list_PathName": { + "publicationList": "my subscribers/All Subscribers" + }, + "r__sendClassification_key": "Default Transactional", + "r__senderProfile_key": "Default", + "throttleCloses": "1/1/0001 12:00:00 AM", + "throttleOpens": "1/1/0001 12:00:00 AM" + } + }, + "description": "", + "id": "4ae63473-ea1e-4963-a257-6fea45a9038a", + "key": "EMAILV2-3", + "metaData": { + "highThroughput": { + "r__dataExtension_key": "testExisting_temail_notPublished" + }, + "isConfigured": true, + "sections": {} + }, + "name": "my email activity", + "outcomes": [ + { + "arguments": {}, + "key": "067f20ba-af36-4401-99d8-934100e1935d", + "metaData": { + "invalid": false + } + } + ], + "schema": { + "arguments": { + "activityId": { + "access": "Hidden", + "dataType": "Text", + "direction": "In", + "isNullable": true, + "readOnly": false + }, + "contactId": { + "access": "Hidden", + "dataType": "Number", + "direction": "In", + "isNullable": true, + "readOnly": false + }, + "contactKey": { + "access": "Hidden", + "dataType": "Text", + "direction": "In", + "isNullable": false, + "readOnly": false + }, + "customObjectKey": { + "access": "Hidden", + "dataType": "LongNumber", + "direction": "In", + "isNullable": true, + "readOnly": true + }, + "definitionId": { + "access": "Hidden", + "dataType": "Text", + "direction": "In", + "isNullable": true, + "readOnly": true + }, + "definitionInstanceId": { + "access": "Hidden", + "dataType": "Text", + "direction": "In", + "isNullable": false, + "readOnly": false + }, + "emailAddress": { + "access": "Hidden", + "dataType": "Text", + "direction": "In", + "isNullable": false, + "readOnly": false + }, + "emailSubjectDataBound": { + "access": "Hidden", + "dataType": "Text", + "direction": "In", + "isNullable": true, + "readOnly": true + }, + "eventData": { + "access": "Hidden", + "dataType": "Text", + "direction": "In", + "isNullable": true, + "readOnly": false + }, + "fieldType": { + "access": "Hidden", + "dataType": "Text", + "direction": "In", + "isNullable": true, + "readOnly": false + }, + "messageKey": { + "access": "Hidden", + "dataType": "Text", + "direction": "Out", + "isNullable": true, + "readOnly": false + }, + "obfuscationProperties": { + "access": "Hidden", + "dataType": "Text", + "direction": "In", + "isNullable": true, + "readOnly": false + }, + "requestID": { + "access": "Hidden", + "dataType": "Text", + "direction": "Out", + "isNullable": true, + "readOnly": false + }, + "sourceCustomObjectId": { + "access": "Hidden", + "dataType": "Text", + "direction": "In", + "isNullable": true, + "readOnly": false + }, + "sourceCustomObjectKey": { + "access": "Hidden", + "dataType": "LongNumber", + "direction": "In", + "isNullable": true, + "readOnly": false + } + } + }, + "type": "EMAILV2" + } + ], + "channel": "email", + "createdDate": "2024-08-23T01:29:33.233", + "defaults": { + "properties": {} + }, + "definitionType": "Transactional", + "description": "", + "entryMode": "MultipleEntries", + "executionMode": "Production", + "exits": [], + "goals": [], + "key": "testExisting_temail_notPublished", + "lastPublishedDate": "0001-01-01T00:00:00", + "metaData": { + "dataSource": "ContactsModel", + "highThroughputSending": { + "email": false + } + }, + "modifiedDate": "2024-08-23T02:00:44.57", + "name": "testExisting_temail_notPublished", + "notifiers": [], + "r__folder_Path": "my journeys", + "scheduledStatus": "Draft", + "status": "Published", + "triggers": [ + { + "arguments": {}, + "configurationArguments": {}, + "description": "", + "key": "TRIGGER", + "metaData": { + "category": "Transactional", + "chainType": "none", + "configurationRequired": false, + "entrySourceGroupConfigUrl": "null", + "iconUrl": "/images/icon_journeyBuilder-event-transactional-blue.svg", + "title": "Transactional API Event" + }, + "name": "TRIGGER", + "outcomes": [], + "type": "transactional-api" + } + ], + "version": 1, + "workflowApiVersion": 1 +} diff --git a/test/mockRoot/deploy/testInstance/testBU/journey/testNew_temail_notPublished.journey-meta.json b/test/mockRoot/deploy/testInstance/testBU/journey/testNew_temail_notPublished.journey-meta.json new file mode 100644 index 000000000..0002a6dd9 --- /dev/null +++ b/test/mockRoot/deploy/testInstance/testBU/journey/testNew_temail_notPublished.journey-meta.json @@ -0,0 +1,213 @@ +{ + "key": "testNew_temail_notPublished", + "name": "testNew_temail_notPublished", + "description": "", + "workflowApiVersion": 1, + "modifiedDate": "2024-12-06T19:36:30.563", + "activities": [ + { + "id": "848d91be-faa5-4307-94d7-22c9a5bcfb1d", + "key": "EMAILV2-1", + "name": "testNew_temail_notPublished_24Q3", + "description": "", + "type": "EMAILV2", + "outcomes": [ + { + "key": "920e8b4c-1598-48d0-b2c4-8a5072e0b738", + "arguments": {}, + "metaData": { + "invalid": false + } + } + ], + "arguments": {}, + "configurationArguments": { + "applicationExtensionKey": "jb-email-activity", + "isModified": true, + "triggeredSend": { + "autoAddSubscribers": true, + "autoUpdateSubscribers": true, + "bccEmail": [], + "c__priority": "Medium", + "ccEmail": [], + "created": {}, + "domainExclusions": [], + "dynamicEmailSubject": "%%=treatascontent(@subject)=%%", + "emailSubject": "%%=treatascontent(@subject)=%%", + "exclusionFilter": "", + "isMultipart": true, + "isSalesforceTracking": true, + "isSendLogging": false, + "isStoppedOnJobError": false, + "isTrackingClicks": true, + "modified": {}, + "preHeader": "%%=treatascontent(@preheader)=%%\n", + "r__asset_key": "testExisting_asset_message", + "r__deliveryProfile_key": "Default", + "r__list_PathName": { + "publicationList": "my subscribers/All Subscribers" + }, + "r__sendClassification_key": "testExisting_sendClassification", + "r__senderProfile_key": "testExisting_senderProfile", + "throttleCloses": "1/1/0001 12:00:00 AM", + "throttleLimit": 0, + "throttleOpens": "1/1/0001 12:00:00 AM" + }, + "r__transactionalEmail_key": "testNew_temail_notPublished" + }, + "metaData": { + "highThroughput": { + "r__dataExtension_key": "testExisting_dataExtension" + }, + "sections": {}, + "isConfigured": true + }, + "schema": { + "arguments": { + "requestID": { + "dataType": "Text", + "isNullable": true, + "direction": "Out", + "readOnly": false, + "access": "Hidden" + }, + "messageKey": { + "dataType": "Text", + "isNullable": true, + "direction": "Out", + "readOnly": false, + "access": "Hidden" + }, + "activityId": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "definitionId": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": true, + "access": "Hidden" + }, + "emailSubjectDataBound": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": true, + "access": "Hidden" + }, + "contactId": { + "dataType": "Number", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "contactKey": { + "dataType": "Text", + "isNullable": false, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "emailAddress": { + "dataType": "Text", + "isNullable": false, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "sourceCustomObjectId": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "sourceCustomObjectKey": { + "dataType": "LongNumber", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "fieldType": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "eventData": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "obfuscationProperties": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "customObjectKey": { + "dataType": "LongNumber", + "isNullable": true, + "direction": "In", + "readOnly": true, + "access": "Hidden" + }, + "definitionInstanceId": { + "dataType": "Text", + "isNullable": false, + "direction": "In", + "readOnly": false, + "access": "Hidden" + } + } + } + } + ], + "triggers": [ + { + "key": "TRIGGER", + "name": "TRIGGER", + "description": "", + "type": "transactional-api", + "outcomes": [], + "arguments": {}, + "configurationArguments": {}, + "metaData": { + "chainType": "none", + "configurationRequired": false, + "iconUrl": "/images/icon_journeyBuilder-event-transactional-blue.svg", + "title": "Transactional API Event", + "category": "Transactional", + "entrySourceGroupConfigUrl": "null" + } + } + ], + "goals": [], + "exits": [], + "notifiers": [], + "entryMode": "MultipleEntries", + "definitionType": "Transactional", + "channel": "email", + "defaults": { + "properties": {} + }, + "metaData": { + "dataSource": "ContactsModel", + "highThroughputSending": { + "email": false + } + }, + "executionMode": "Production", + "scheduledStatus": "Draft", + "r__folder_Path": "my journeys" +} diff --git a/test/mockRoot/deploy/testInstance/testBU/mobileKeyword/4912312345678.TESTNEW_KEYWORD.mobileKeyword-meta.amp b/test/mockRoot/deploy/testInstance/testBU/mobileKeyword/4912312345678.TESTNEW_KEYWORD.mobileKeyword-meta.amp new file mode 100644 index 000000000..f8be7bb82 --- /dev/null +++ b/test/mockRoot/deploy/testInstance/testBU/mobileKeyword/4912312345678.TESTNEW_KEYWORD.mobileKeyword-meta.amp @@ -0,0 +1,2 @@ +line1 +line2 \ No newline at end of file diff --git a/test/mockRoot/deploy/testInstance/testBU/mobileKeyword/4912312345678.TESTNEW_KEYWORD.mobileKeyword-meta.json b/test/mockRoot/deploy/testInstance/testBU/mobileKeyword/4912312345678.TESTNEW_KEYWORD.mobileKeyword-meta.json new file mode 100644 index 000000000..7a0204fbe --- /dev/null +++ b/test/mockRoot/deploy/testInstance/testBU/mobileKeyword/4912312345678.TESTNEW_KEYWORD.mobileKeyword-meta.json @@ -0,0 +1,8 @@ +{ + "c__codeKeyword": "4912312345678.TESTNEW_KEYWORD", + "r__mobileCode_key": "4912312345678", + "status": "Active", + "restriction": "NONE", + "keywordType": "STOP", + "isInherited": false +} diff --git a/test/mockRoot/deploy/testInstance/testBU/mobileKeyword/4912312345678.TESTNEW_KEYWORD_BLOCKED.mobileKeyword-meta.amp b/test/mockRoot/deploy/testInstance/testBU/mobileKeyword/4912312345678.TESTNEW_KEYWORD_BLOCKED.mobileKeyword-meta.amp new file mode 100644 index 000000000..f8be7bb82 --- /dev/null +++ b/test/mockRoot/deploy/testInstance/testBU/mobileKeyword/4912312345678.TESTNEW_KEYWORD_BLOCKED.mobileKeyword-meta.amp @@ -0,0 +1,2 @@ +line1 +line2 \ No newline at end of file diff --git a/test/mockRoot/deploy/testInstance/testBU/mobileKeyword/4912312345678.TESTNEW_KEYWORD_BLOCKED.mobileKeyword-meta.json b/test/mockRoot/deploy/testInstance/testBU/mobileKeyword/4912312345678.TESTNEW_KEYWORD_BLOCKED.mobileKeyword-meta.json new file mode 100644 index 000000000..89ded9225 --- /dev/null +++ b/test/mockRoot/deploy/testInstance/testBU/mobileKeyword/4912312345678.TESTNEW_KEYWORD_BLOCKED.mobileKeyword-meta.json @@ -0,0 +1,8 @@ +{ + "c__codeKeyword": "4912312345678.TESTNEW_KEYWORD_BLOCKED", + "r__mobileCode_key": "4912312345678", + "status": "Active", + "restriction": "NONE", + "keywordType": "NORMAL", + "isInherited": false +} diff --git a/test/mockRoot/deploy/testInstance/testBU/mobileMessage/NTIzOjc4OjA.mobileMessage-meta.amp b/test/mockRoot/deploy/testInstance/testBU/mobileMessage/NTIzOjc4OjA.mobileMessage-meta.amp new file mode 100644 index 000000000..0639ff611 --- /dev/null +++ b/test/mockRoot/deploy/testInstance/testBU/mobileMessage/NTIzOjc4OjA.mobileMessage-meta.amp @@ -0,0 +1 @@ +test message jb new \ No newline at end of file diff --git a/test/mockRoot/deploy/testInstance/testBU/mobileMessage/NTIzOjc4OjA.mobileMessage-meta.json b/test/mockRoot/deploy/testInstance/testBU/mobileMessage/NTIzOjc4OjA.mobileMessage-meta.json new file mode 100644 index 000000000..56fe1f4e7 --- /dev/null +++ b/test/mockRoot/deploy/testInstance/testBU/mobileMessage/NTIzOjc4OjA.mobileMessage-meta.json @@ -0,0 +1,59 @@ +{ + "id": "NTIzOjc4OjA", + "lastUpdated": "2023-03-08T16:30:00Z", + "type": "ExactTarget.Mobile.Sms.Core.Entities.SmsMessageEntity", + "name": "testExisting_mobileMessage", + "origin": "SMS Send", + "r__mobileCode_key": "4912312345678", + "r__campaign_key": ["testExisting_campaign"], + + "mtSendDate": "2020-07-16T22:46:00Z", + "template": { + "id": "Mzo4MDow", + "name": "Outbound" + }, + "status": "Active/Scheduled", + "invalidMessage": "", + "responseMessage": "", + "publishedMessage": "Text '<keyword>' to 4912312345678.", + "isTest": false, + "moTimezone": { + "offset": 1, + "name": "(GMT+01:00) Amsterdam, Berlin, Bern, Rome, Stockholm, Vienna *" + }, + "optinType": "NO_OPTIN", + "doubleOptinInitialMessage": "", + "doubleOptinConfirmMessage": "", + "optinMinimumAge": 0, + "optinInvalidAgeMessage": "", + "numberMessagesPerPeriod": 0, + "periodType": "NO_PERIOD", + "optinErrorMessage": "", + "isDuplicationAllowed": true, + "triggeredSendName": "DEV_InformUserAboutProposal - 267", + "isTimeZoneBased": false, + "surveyType": "NO_SURVEY", + "surveyCorrectResponseMessage": "", + "surveyTooManyEntriesMessage": "", + "isExpireSet": false, + "expireHours": 0, + "surveyIncorrectResponseMessage": "", + "statusId": 2, + "doubleOptinValidResponses": "y|yes", + "messagesPerPeriod": 0, + "minutesPerPeriod": 0, + "subscriberResponseMessage": "", + "isSubscriberResponseToAnySubscriptionForShortCode": false, + "sendMethod": "API", + "messageObjectId": "MzN3MUV5YVpmRVMtV1R1UXJUR3NzUTo2MjU6MA", + "allowSingleOptin": false, + "isSentImmediately": true, + "isSuppressMt": false, + "smsTriggeredSendDefinitionId": "39d0e022-b6c7-ea11-a2e9-1402ec938719", + "fromName": "4912312345678", + "concatenateMessage": true, + "isFromNameCertificationAccepted": false, + "isCertified": false, + "outboundSendTypeFlag": "Audience", + "outboundSendBehaviorFlag": "AutoAddSubscribers" +} diff --git a/test/mockRoot/deploy/testInstance/testBU/mobileMessage/new.mobileMessage-meta.amp b/test/mockRoot/deploy/testInstance/testBU/mobileMessage/new.mobileMessage-meta.amp new file mode 100644 index 000000000..5cd044454 --- /dev/null +++ b/test/mockRoot/deploy/testInstance/testBU/mobileMessage/new.mobileMessage-meta.amp @@ -0,0 +1 @@ +New Task Available \ No newline at end of file diff --git a/test/mockRoot/deploy/testInstance/testBU/mobileMessage/new.mobileMessage-meta.json b/test/mockRoot/deploy/testInstance/testBU/mobileMessage/new.mobileMessage-meta.json new file mode 100644 index 000000000..a8b835902 --- /dev/null +++ b/test/mockRoot/deploy/testInstance/testBU/mobileMessage/new.mobileMessage-meta.json @@ -0,0 +1,58 @@ +{ + "id": "new", + "lastUpdated": "2020-07-03T06:39:00Z", + "type": "ExactTarget.Mobile.Sms.Core.Entities.SmsMessageEntity", + "name": "testNew_mobileMessage", + "origin": "SMS Send", + "r__mobileCode_key": "4912312345678", + "r__campaign_key": ["testExisting_campaign"], + "mtSendDate": "2017-07-03T14:03:00Z", + "template": { + "id": "Mzo4MDow", + "name": "Outbound" + }, + "status": "Active/Scheduled", + "invalidMessage": "", + "responseMessage": "", + "publishedMessage": "Text '<keyword>' to 4912312345678.", + "isTest": false, + "moTimezone": { + "offset": 1, + "name": "(GMT+01:00) Amsterdam, Berlin, Bern, Rome, Stockholm, Vienna *" + }, + "optinType": "NO_OPTIN", + "doubleOptinInitialMessage": "", + "doubleOptinConfirmMessage": "", + "optinMinimumAge": 0, + "optinInvalidAgeMessage": "", + "numberMessagesPerPeriod": 0, + "periodType": "NO_PERIOD", + "optinErrorMessage": "", + "isDuplicationAllowed": true, + "triggeredSendName": "OneUserOneDevice_DEV - 93", + "isTimeZoneBased": false, + "surveyType": "NO_SURVEY", + "surveyCorrectResponseMessage": "", + "surveyTooManyEntriesMessage": "", + "isExpireSet": false, + "expireHours": 0, + "surveyIncorrectResponseMessage": "", + "statusId": 2, + "doubleOptinValidResponses": "y|yes", + "messagesPerPeriod": 0, + "minutesPerPeriod": 0, + "subscriberResponseMessage": "", + "isSubscriberResponseToAnySubscriptionForShortCode": false, + "sendMethod": "API", + "messageObjectId": "M09MU3o1YnRMVS1GNHppZTdCRDVCdzo2MjU6MA", + "allowSingleOptin": false, + "isSentImmediately": true, + "isSuppressMt": false, + "smsTriggeredSendDefinitionId": "58d59e53-f85f-e711-80cc-1402ec7222b4", + "fromName": "PMI_DEV", + "concatenateMessage": false, + "isFromNameCertificationAccepted": false, + "isCertified": false, + "outboundSendTypeFlag": "Audience", + "outboundSendBehaviorFlag": "AutoAddSubscribers" +} diff --git a/test/mockRoot/deploy/testInstance/testBU/query/testExisting_query.query-meta.json b/test/mockRoot/deploy/testInstance/testBU/query/testExisting_query.query-meta.json new file mode 100644 index 000000000..bb96f9b40 --- /dev/null +++ b/test/mockRoot/deploy/testInstance/testBU/query/testExisting_query.query-meta.json @@ -0,0 +1,11 @@ +{ + "name": "testExisting_query", + "key": "testExisting_query", + "description": "updated on deploy", + "r__dataExtension_key": "testExisting_dataExtension", + "createdDate": "2022-04-26T15:21:16.453", + "modifiedDate": "2022-04-26T16:04:15.88", + "targetUpdateTypeName": "Overwrite", + "isFrozen": false, + "r__folder_Path": "Query" +} diff --git a/test/mockRoot/deploy/testInstance/testBU/query/testExisting_query.query-meta.sql b/test/mockRoot/deploy/testInstance/testBU/query/testExisting_query.query-meta.sql new file mode 100644 index 000000000..e78525408 --- /dev/null +++ b/test/mockRoot/deploy/testInstance/testBU/query/testExisting_query.query-meta.sql @@ -0,0 +1,6 @@ +SELECT + SubscriberKey as testField +FROM + _Subscribers +WHERE + country IN ('test') diff --git a/test/mockRoot/deploy/testInstance/testBU/query/testExisting_query_fixKeys.query-meta.json b/test/mockRoot/deploy/testInstance/testBU/query/testExisting_query_fixKeys.query-meta.json new file mode 100644 index 000000000..42808b345 --- /dev/null +++ b/test/mockRoot/deploy/testInstance/testBU/query/testExisting_query_fixKeys.query-meta.json @@ -0,0 +1,11 @@ +{ + "name": "testExisting_query_fixedKeys", + "key": "testExisting_query_fixKeys", + "description": "updated on deploy", + "r__dataExtension_key": "testExisting_dataExtension", + "createdDate": "2022-04-26T15:21:16.453", + "modifiedDate": "2022-04-26T16:04:15.88", + "targetUpdateTypeName": "Overwrite", + "isFrozen": false, + "r__folder_Path": "Query" +} diff --git a/test/mockRoot/deploy/testInstance/testBU/query/testExisting_query_fixKeys.query-meta.sql b/test/mockRoot/deploy/testInstance/testBU/query/testExisting_query_fixKeys.query-meta.sql new file mode 100644 index 000000000..e78525408 --- /dev/null +++ b/test/mockRoot/deploy/testInstance/testBU/query/testExisting_query_fixKeys.query-meta.sql @@ -0,0 +1,6 @@ +SELECT + SubscriberKey as testField +FROM + _Subscribers +WHERE + country IN ('test') diff --git a/test/mockRoot/deploy/testInstance/testBU/query/testNew_query.query-meta.json b/test/mockRoot/deploy/testInstance/testBU/query/testNew_query.query-meta.json new file mode 100644 index 000000000..bc06864f0 --- /dev/null +++ b/test/mockRoot/deploy/testInstance/testBU/query/testNew_query.query-meta.json @@ -0,0 +1,11 @@ +{ + "name": "testNew_query", + "key": "testNew_query", + "description": "created on deploy", + "r__dataExtension_key": "testExisting_dataExtension", + "createdDate": "2022-04-26T15:21:16.453", + "modifiedDate": "2022-04-26T16:04:15.88", + "targetUpdateTypeName": "Overwrite", + "isFrozen": false, + "r__folder_Path": "Query" +} diff --git a/test/mockRoot/deploy/testInstance/testBU/query/testNew_query.query-meta.sql b/test/mockRoot/deploy/testInstance/testBU/query/testNew_query.query-meta.sql new file mode 100644 index 000000000..8020314ea --- /dev/null +++ b/test/mockRoot/deploy/testInstance/testBU/query/testNew_query.query-meta.sql @@ -0,0 +1,4 @@ +SELECT + SubscriberKey as testField +FROM + _Subscribers diff --git a/test/mockRoot/deploy/testInstance/testBU/script/testExisting_script.script-meta.json b/test/mockRoot/deploy/testInstance/testBU/script/testExisting_script.script-meta.json new file mode 100644 index 000000000..cefd0e179 --- /dev/null +++ b/test/mockRoot/deploy/testInstance/testBU/script/testExisting_script.script-meta.json @@ -0,0 +1,6 @@ +{ + "description": "updated on deploy", + "key": "testExisting_script", + "name": "testExisting_script", + "r__folder_Path": "Scripts" +} diff --git a/test/mockRoot/deploy/testInstance/testBU/script/testExisting_script.script-meta.ssjs b/test/mockRoot/deploy/testInstance/testBU/script/testExisting_script.script-meta.ssjs new file mode 100644 index 000000000..e20d1ee2d --- /dev/null +++ b/test/mockRoot/deploy/testInstance/testBU/script/testExisting_script.script-meta.ssjs @@ -0,0 +1 @@ +// dummy updated diff --git a/test/mockRoot/deploy/testInstance/testBU/script/testNew_script.script-meta.json b/test/mockRoot/deploy/testInstance/testBU/script/testNew_script.script-meta.json new file mode 100644 index 000000000..5a2f9b73a --- /dev/null +++ b/test/mockRoot/deploy/testInstance/testBU/script/testNew_script.script-meta.json @@ -0,0 +1,6 @@ +{ + "description": "created on deploy", + "key": "testNew_script", + "name": "testNew_script", + "r__folder_Path": "Scripts" +} diff --git a/test/mockRoot/deploy/testInstance/testBU/script/testNew_script.script-meta.ssjs b/test/mockRoot/deploy/testInstance/testBU/script/testNew_script.script-meta.ssjs new file mode 100644 index 000000000..bbfd28311 --- /dev/null +++ b/test/mockRoot/deploy/testInstance/testBU/script/testNew_script.script-meta.ssjs @@ -0,0 +1 @@ +// dummy created diff --git a/test/mockRoot/deploy/testInstance/testBU/sendClassification/testExisting_sendClassification.sendClassification-meta.json b/test/mockRoot/deploy/testInstance/testBU/sendClassification/testExisting_sendClassification.sendClassification-meta.json new file mode 100644 index 000000000..3cc32064a --- /dev/null +++ b/test/mockRoot/deploy/testInstance/testBU/sendClassification/testExisting_sendClassification.sendClassification-meta.json @@ -0,0 +1,8 @@ +{ + "CustomerKey": "testExisting_sendClassification", + "Name": "testExisting_sendClassification", + "Description": "updated on deploy", + "c__classification": "Commercial", + "r__senderProfile_key": "testExisting_senderProfile", + "r__deliveryProfile_key": "Default" +} diff --git a/test/mockRoot/deploy/testInstance/testBU/sendClassification/testNew_sendClassification.sendClassification-meta.json b/test/mockRoot/deploy/testInstance/testBU/sendClassification/testNew_sendClassification.sendClassification-meta.json new file mode 100644 index 000000000..51456ddc9 --- /dev/null +++ b/test/mockRoot/deploy/testInstance/testBU/sendClassification/testNew_sendClassification.sendClassification-meta.json @@ -0,0 +1,8 @@ +{ + "CustomerKey": "testNew_sendClassification", + "Name": "testNew_sendClassification", + "Description": "created on deploy", + "c__classification": "Commercial", + "r__senderProfile_key": "testExisting_senderProfile", + "r__deliveryProfile_key": "Default" +} diff --git a/test/mockRoot/deploy/testInstance/testBU/senderProfile/testExisting_senderProfile.senderProfile-meta.json b/test/mockRoot/deploy/testInstance/testBU/senderProfile/testExisting_senderProfile.senderProfile-meta.json new file mode 100644 index 000000000..9b0a19d13 --- /dev/null +++ b/test/mockRoot/deploy/testInstance/testBU/senderProfile/testExisting_senderProfile.senderProfile-meta.json @@ -0,0 +1,15 @@ +{ + "CustomerKey": "testExisting_senderProfile", + "Name": "testExisting_senderProfile", + "Description": "updated via deploy", + "FromName": "Jörn Berkefeld", + "FromAddress": "joern.berkefeld@accenture.com", + "FallbackFromAddress": "", + "UseDefaultRMMRules": false, + "AutoForwardToEmailAddress": "joern.berkefeld@accenture.com", + "AutoForwardToName": "Jörn Berkefeld", + "DirectForward": false, + "AutoReply": false, + "SenderHeaderEmailAddress": "", + "SenderHeaderName": "" +} diff --git a/test/mockRoot/deploy/testInstance/testBU/senderProfile/testNew_senderProfile.senderProfile-meta.json b/test/mockRoot/deploy/testInstance/testBU/senderProfile/testNew_senderProfile.senderProfile-meta.json new file mode 100644 index 000000000..be7aeab5c --- /dev/null +++ b/test/mockRoot/deploy/testInstance/testBU/senderProfile/testNew_senderProfile.senderProfile-meta.json @@ -0,0 +1,15 @@ +{ + "CustomerKey": "testNew_senderProfile", + "Name": "testNew_senderProfile", + "Description": "created on deploy", + "FromName": "Jörn Berkefeld", + "FromAddress": "joern.berkefeld@accenture.com", + "FallbackFromAddress": "joern.berkefeld.New@accenture.com", + "UseDefaultRMMRules": false, + "AutoForwardToEmailAddress": "joern.berkefeld@accenture.com", + "AutoForwardToName": "Jörn Berkefeld", + "DirectForward": false, + "AutoReply": false, + "SenderHeaderEmailAddress": "", + "SenderHeaderName": "" +} diff --git a/test/mockRoot/deploy/testInstance/testBU/transactionalEmail/testExisting_temail.transactionalEmail-meta.json b/test/mockRoot/deploy/testInstance/testBU/transactionalEmail/testExisting_temail.transactionalEmail-meta.json new file mode 100644 index 000000000..de4fcfac6 --- /dev/null +++ b/test/mockRoot/deploy/testInstance/testBU/transactionalEmail/testExisting_temail.transactionalEmail-meta.json @@ -0,0 +1,20 @@ +{ + "name": "testExisting_temail", + "definitionKey": "testExisting_temail", + "description": "updated via deploy", + "classification": "Default Transactional", + "status": "Active", + "createdDate": "2020-09-10T03:29:00", + "modifiedDate": "2020-09-10T03:29:00", + "subscriptions": { + "dataExtension": "testExisting_dataExtension", + "autoAddSubscriber": true, + "updateSubscriber": true, + "r__list_PathName": "my subscribers/All Subscribers" + }, + "options": { + "trackLinks": true + }, + "r__journey_key": "testExisting_interaction", + "r__asset_key": "testExisting_asset_message" +} diff --git a/test/mockRoot/deploy/testInstance/testBU/transactionalEmail/testNew_temail.transactionalEmail-meta.json b/test/mockRoot/deploy/testInstance/testBU/transactionalEmail/testNew_temail.transactionalEmail-meta.json new file mode 100644 index 000000000..aec6b1002 --- /dev/null +++ b/test/mockRoot/deploy/testInstance/testBU/transactionalEmail/testNew_temail.transactionalEmail-meta.json @@ -0,0 +1,19 @@ +{ + "name": "testNew_temail", + "definitionKey": "testNew_temail", + "description": "created on deploy", + "classification": "Default Transactional", + "status": "Active", + "createdDate": "2020-09-10T03:29:00", + "modifiedDate": "2020-09-10T03:29:00", + "subscriptions": { + "dataExtension": "testExisting_dataExtension", + "autoAddSubscriber": true, + "updateSubscriber": true, + "r__list_PathName": "my subscribers/All Subscribers" + }, + "options": { + "trackLinks": true + }, + "r__asset_key": "testExisting_asset_message" +} diff --git a/test/mockRoot/deploy/testInstance/testBU/transactionalPush/testExisting_tpush.transactionalPush-meta.json b/test/mockRoot/deploy/testInstance/testBU/transactionalPush/testExisting_tpush.transactionalPush-meta.json new file mode 100644 index 000000000..2cbfb8186 --- /dev/null +++ b/test/mockRoot/deploy/testInstance/testBU/transactionalPush/testExisting_tpush.transactionalPush-meta.json @@ -0,0 +1,16 @@ +{ + "definitionKey": "testExisting_tpush", + "name": "testExisting_tpush", + "status": "Active", + "applicationId": "ffbab4c9-fbf6-4b87-9c9a-10c6ce86e81d", + "description": "updated via deploy; note that applicationId can only be manually set up in Setup - Mobile Push", + "r__asset_key": "mobileMessage_test", + "options": { + "sound": "temp.wmv", + "badge": "1", + "customKeys": [ + { "key": "key1", "value": "value1" }, + { "key": "key2", "value": "value2" } + ] + } +} diff --git a/test/mockRoot/deploy/testInstance/testBU/transactionalPush/testNew_tpush.transactionalPush-meta.json b/test/mockRoot/deploy/testInstance/testBU/transactionalPush/testNew_tpush.transactionalPush-meta.json new file mode 100644 index 000000000..fcee47d50 --- /dev/null +++ b/test/mockRoot/deploy/testInstance/testBU/transactionalPush/testNew_tpush.transactionalPush-meta.json @@ -0,0 +1,16 @@ +{ + "definitionKey": "testNew_tpush", + "name": "testNew_tpush", + "status": "Active", + "applicationId": "ffbab4c9-fbf6-4b87-9c9a-10c6ce86e81d", + "description": "created on deploy; note that applicationId can only be manually set up in Setup - Mobile Push", + "r__asset_key": "mobileMessage_test", + "options": { + "sound": "temp.wmv", + "badge": "1", + "customKeys": [ + { "key": "key1", "value": "value1" }, + { "key": "key2", "value": "value2" } + ] + } +} diff --git a/test/mockRoot/deploy/testInstance/testBU/transactionalSMS/testExisting_tsms.transactionalSMS-meta.amp b/test/mockRoot/deploy/testInstance/testBU/transactionalSMS/testExisting_tsms.transactionalSMS-meta.amp new file mode 100644 index 000000000..e4c5aff95 --- /dev/null +++ b/test/mockRoot/deploy/testInstance/testBU/transactionalSMS/testExisting_tsms.transactionalSMS-meta.amp @@ -0,0 +1,4 @@ + +%%[ + SET @key = 'secret' +]%% diff --git a/test/mockRoot/deploy/testInstance/testBU/transactionalSMS/testExisting_tsms.transactionalSMS-meta.json b/test/mockRoot/deploy/testInstance/testBU/transactionalSMS/testExisting_tsms.transactionalSMS-meta.json new file mode 100644 index 000000000..5d2a9a074 --- /dev/null +++ b/test/mockRoot/deploy/testInstance/testBU/transactionalSMS/testExisting_tsms.transactionalSMS-meta.json @@ -0,0 +1,14 @@ +{ + "name": "testExisting_tsms", + "definitionKey": "testExisting_tsms", + "description": "bla bla", + "status": "Active", + "createdDate": "2022-11-07T02:24:00", + "modifiedDate": "2022-11-07T02:25:00", + "subscriptions": { + "countryCode": "", + "autoAddSubscriber": true, + "updateSubscriber": true, + "r__mobileKeyword_key": "4912312345678.TESTEXISTING_KEYWORD" + } +} diff --git a/test/mockRoot/deploy/testInstance/testBU/transactionalSMS/testNew_tsms.transactionalSMS-meta.amp b/test/mockRoot/deploy/testInstance/testBU/transactionalSMS/testNew_tsms.transactionalSMS-meta.amp new file mode 100644 index 000000000..e4c5aff95 --- /dev/null +++ b/test/mockRoot/deploy/testInstance/testBU/transactionalSMS/testNew_tsms.transactionalSMS-meta.amp @@ -0,0 +1,4 @@ + +%%[ + SET @key = 'secret' +]%% diff --git a/test/mockRoot/deploy/testInstance/testBU/transactionalSMS/testNew_tsms.transactionalSMS-meta.json b/test/mockRoot/deploy/testInstance/testBU/transactionalSMS/testNew_tsms.transactionalSMS-meta.json new file mode 100644 index 000000000..196a92a35 --- /dev/null +++ b/test/mockRoot/deploy/testInstance/testBU/transactionalSMS/testNew_tsms.transactionalSMS-meta.json @@ -0,0 +1,14 @@ +{ + "name": "testNew_tsms", + "definitionKey": "testNew_tsms", + "description": "created on deploy", + "status": "Active", + "createdDate": "2022-11-07T02:24:00", + "modifiedDate": "2022-11-07T02:25:00", + "subscriptions": { + "countryCode": "", + "autoAddSubscriber": true, + "updateSubscriber": true, + "r__mobileKeyword_key": "4912312345678.TESTEXISTING_KEYWORD" + } +} diff --git a/test/mockRoot/deploy/testInstance/testBU/triggeredSend/testExisting_triggeredSend.triggeredSend-meta.json b/test/mockRoot/deploy/testInstance/testBU/triggeredSend/testExisting_triggeredSend.triggeredSend-meta.json new file mode 100644 index 000000000..8d043390a --- /dev/null +++ b/test/mockRoot/deploy/testInstance/testBU/triggeredSend/testExisting_triggeredSend.triggeredSend-meta.json @@ -0,0 +1,27 @@ +{ + "AllowedSlots": 0, + "AutoAddSubscribers": false, + "AutoUpdateSubscribers": false, + "BatchInterval": 0, + "CreatedDate": "2018-06-25T05:58:00", + "CustomerKey": "testExisting_triggeredSend", + "Description": "updated on deploy", + "DynamicEmailSubject": "You are successfully unsubscribed", + "EmailSubject": "You are successfully unsubscribed", + "FromAddress": "unsubscribe@emails.mcdev.accenture.com", + "FromName": "unsubscribe", + "IsMultipart": false, + "IsWrapped": true, + "Keyword": "", + "ModifiedDate": "2018-06-25T05:58:00", + "Name": "testExisting_triggeredSend", + "NewSlotTrigger": 0, + "Priority": 4, + "SuppressTracking": false, + "TriggeredSendStatus": "New", + "TriggeredSendType": "Continuous", + "r__email_name": "Sporting Goods for September", + "r__folder_Path": "Triggered Sends", + "r__sendClassification_key": "testExisting_sendClassification", + "r__senderProfile_key": "testExisting_senderProfile" +} diff --git a/test/mockRoot/deploy/testInstance/testBU/triggeredSend/testNew_triggeredSend.triggeredSend-meta.json b/test/mockRoot/deploy/testInstance/testBU/triggeredSend/testNew_triggeredSend.triggeredSend-meta.json new file mode 100644 index 000000000..787881c14 --- /dev/null +++ b/test/mockRoot/deploy/testInstance/testBU/triggeredSend/testNew_triggeredSend.triggeredSend-meta.json @@ -0,0 +1,27 @@ +{ + "AllowedSlots": 0, + "AutoAddSubscribers": false, + "AutoUpdateSubscribers": false, + "BatchInterval": 0, + "CreatedDate": "2018-06-25T05:58:00", + "CustomerKey": "testNew_triggeredSend", + "Description": "created on deploy", + "DynamicEmailSubject": "You are successfully unsubscribed", + "EmailSubject": "You are successfully unsubscribed", + "FromAddress": "unsubscribe@emails.mcdev.accenture.com", + "FromName": "unsubscribe", + "IsMultipart": false, + "IsWrapped": true, + "Keyword": "", + "ModifiedDate": "2018-06-25T05:58:00", + "Name": "testNew_triggeredSend", + "NewSlotTrigger": 0, + "Priority": 4, + "SuppressTracking": false, + "TriggeredSendStatus": "New", + "TriggeredSendType": "Continuous", + "r__email_name": "Sporting Goods for September", + "r__folder_Path": "Triggered Sends", + "r__sendClassification_key": "testExisting_sendClassification", + "r__senderProfile_key": "testExisting_senderProfile" +} diff --git a/test/mockRoot/deploy/testInstance/testBU/verification/testExisting_automation__s1.7.verification-meta.json b/test/mockRoot/deploy/testInstance/testBU/verification/testExisting_automation__s1.7.verification-meta.json new file mode 100644 index 000000000..37e99eae7 --- /dev/null +++ b/test/mockRoot/deploy/testInstance/testBU/verification/testExisting_automation__s1.7.verification-meta.json @@ -0,0 +1,11 @@ +{ + "c__automation_step": "testExisting_automation__s1.7", + "notificationEmailAddress": "test@accenture.com", + "notificationEmailMessage": "", + "r__dataExtension_key": "testExisting_dataExtension", + "shouldEmailOnFailure": true, + "shouldStopOnFailure": true, + "value1": 1, + "value2": 0, + "verificationType": "IsEqualTo" +} diff --git a/test/mockRoot/deploy/testInstance/testBU/verification/testNew_automation__s1.7.verification-meta.json b/test/mockRoot/deploy/testInstance/testBU/verification/testNew_automation__s1.7.verification-meta.json new file mode 100644 index 000000000..dbdea96ed --- /dev/null +++ b/test/mockRoot/deploy/testInstance/testBU/verification/testNew_automation__s1.7.verification-meta.json @@ -0,0 +1,11 @@ +{ + "c__automation_step": "testNew_automation__s1.7", + "notificationEmailAddress": "", + "notificationEmailMessage": "", + "r__dataExtension_key": "testExisting_dataExtension", + "shouldEmailOnFailure": false, + "shouldStopOnFailure": false, + "value1": 2, + "value2": 0, + "verificationType": "IsEqualTo" +} diff --git a/test/resourceFactory.js b/test/resourceFactory.js new file mode 100644 index 000000000..fd8b5237d --- /dev/null +++ b/test/resourceFactory.js @@ -0,0 +1,494 @@ +import fs from 'fs-extra'; +import path from 'node:path'; +import { XMLParser } from 'fast-xml-parser'; +import { Util } from '../lib/util/util.js'; + +import { fileURLToPath } from 'node:url'; +const __dirname = path.dirname(fileURLToPath(import.meta.url)); +const projectRootHelper = __dirname.split(path.sep); +projectRootHelper.pop(); +const projectRoot = projectRootHelper.join(path.sep) + path.sep; + +const parser = new XMLParser(); +const attributeParser = new XMLParser({ ignoreAttributes: false }); +/** @type {typeof Util.color} */ +const color = Util.color; + +export const tWarn = `${color.bgYellow}${color.fgBlack}TEST-WARNING${color.reset}`; +export const tError = `${color.bgRed}${color.fgBlack}TEST-ERROR${color.reset}`; + +const loadingFile = 'loading server file:///'; + +/** + * gets mock SOAP metadata for responding + * + * @param {string} mcdevAction SOAP action + * @param {string} type metadata Type + * @param {string} mid of Business Unit + * @param {object|string} filter likely for customer key + * @param {boolean} [QueryAllAccounts] get data from other BUs or not + * @returns {Promise.<string>} relevant metadata stringified + */ +async function loadSOAPRecords(mcdevAction, type, mid, filter, QueryAllAccounts) { + type = type[0].toLowerCase() + type.slice(1); + const testPath = path.join('test', 'resources', mid.toString(), type, mcdevAction); + const filterPath = getFilterPath(filter, QueryAllAccounts); + if (await fs.pathExists(testPath + filterPath + '-response.xml')) { + console.log(loadingFile + projectRoot + testPath + filterPath + '-response.xml'); // eslint-disable-line no-console + return fs.readFile(testPath + filterPath + '-response.xml', { + encoding: 'utf8', + }); + } else if (await fs.pathExists(testPath + '-response.xml')) { + if (filterPath) { + /* eslint-disable no-console */ + console.log( + `${tWarn}: You are loading your reponse from ${ + testPath + '-response.xml' + } instead of the more specific ${ + testPath + filterPath + '-response.xml' + }. Make sure this is intended` + ); + /* eslint-enable no-console */ + } + console.log(loadingFile + projectRoot + testPath + '-response.xml'); // eslint-disable-line no-console + return fs.readFile(testPath + '-response.xml', { + encoding: 'utf8', + }); + } + /* eslint-disable no-console */ + console.log( + `${tError}: Please create file ${ + filterPath ? testPath + filterPath + '-response.xml or ' : '' + }${testPath + '-response.xml'}` + ); + /* eslint-enable no-console */ + + // return error + process.exitCode = 404; + return fs.readFile(path.join('test', 'resources', mcdevAction + '-response.xml'), { + encoding: 'utf8', + }); +} + +/** + * helper for {@link loadSOAPRecords} to get the filter path + * + * @param {object|string} filter likely for customer key + * @param {boolean} [QueryAllAccounts] get data from other BUs or not + * @param {number} [shorten] number of characters to shorten filters by to match windows max file length of 256 chars + * @returns {string} filterPath value + */ +function getFilterPath(filter, QueryAllAccounts, shorten) { + const filterPath = + (typeof filter === 'string' && filter ? '-' + filter : filterToPath(filter, shorten)) + + (QueryAllAccounts ? '-QAA' : ''); + if ((filterPath + '-response.xml').length > 256) { + shorten ||= 10; + return getFilterPath(filter, QueryAllAccounts, shorten - 1); + } else { + return filterPath; + } +} + +/** + * main filter to path function + * + * @param {object} filter main filter object + * @param {string} filter.Property field name + * @param {string} filter.SimpleOperator string representation of the comparison method + * @param {string} filter.Value field value to check for + * @param {object} filter.LeftOperand contains a filter object itself + * @param {'AND'|'OR'} filter.LogicalOperator string representation of the comparison method + * @param {object} filter.RightOperand field value to check for + * @param {number} [shorten] number of characters to shorten filters by to match windows max file length of 256 chars + * @returns {string} string represenation of the entire filter + */ +export function filterToPath(filter, shorten) { + if (filter) { + return '-' + _filterToPath(filter, shorten); + } + return ''; +} + +/** + * helper for filterToPath + * + * @param {object} filter main filter object + * @param {string} filter.Property field name + * @param {string} filter.SimpleOperator string representation of the comparison method + * @param {string} filter.Value field value to check for + * @param {object} filter.LeftOperand contains a filter object itself + * @param {'AND'|'OR'} filter.LogicalOperator string representation of the comparison method + * @param {object} filter.RightOperand field value to check for + * @param {number} [shorten] number of characters to shorten filters by to match windows max file length of 256 chars + * @returns {string} string represenation of the entire filter + */ +function _filterToPath(filter, shorten) { + if (filter.Property && filter.SimpleOperator) { + let value; + if (filter.Value === undefined) { + value = ''; + } else if (Array.isArray(filter.Value)) { + value = shorten + ? filter.Value.map((val) => val.slice(0, Math.max(0, shorten))).join(',') + : filter.Value.join(','); + } else { + value = shorten ? filter.Value.slice(0, Math.max(0, shorten)) : filter.Value; + } + return `${filter.Property}${filter.SimpleOperator.replace('equals', '=')}${value}`; + } else if (filter.LeftOperand && filter.LogicalOperator && filter.RightOperand) { + return ( + _filterToPath(filter.LeftOperand, shorten) + + filter.LogicalOperator + + _filterToPath(filter.RightOperand, shorten) + ); + } else { + throw new Error('unknown filter type'); + } +} + +/** + * based on request, respond with different soap data + * + * @param {object} config mock api request object + * @returns {Promise.<Array>} status code plus response in string form + */ +export const handleSOAPRequest = async (config) => { + const jObj = parser.parse(config.data); + const fullObj = attributeParser.parse(config.data); + let responseXML; + + switch (config.headers.SOAPAction) { + case 'Retrieve': { + responseXML = await loadSOAPRecords( + config.headers.SOAPAction.toLocaleLowerCase(), + jObj.Envelope.Body.RetrieveRequestMsg.RetrieveRequest.ObjectType, + jObj.Envelope.Header.fueloauth, + jObj.Envelope.Body.RetrieveRequestMsg.RetrieveRequest.Filter, + jObj.Envelope.Body.RetrieveRequestMsg.RetrieveRequest.QueryAllAccounts + ); + + break; + } + case 'Create': { + let filter = null; + if (fullObj.Envelope.Body.CreateRequest.Objects['@_xsi:type'] === 'DataFolder') { + filter = `ContentType=${fullObj.Envelope.Body.CreateRequest.Objects.ContentType},Name=${fullObj.Envelope.Body.CreateRequest.Objects.Name},ParentFolderID=${fullObj.Envelope.Body.CreateRequest.Objects.ParentFolder.ID}`; + } + responseXML = await loadSOAPRecords( + config.headers.SOAPAction.toLocaleLowerCase(), + fullObj.Envelope.Body.CreateRequest.Objects['@_xsi:type'], + jObj.Envelope.Header.fueloauth, + filter + ); + + break; + } + case 'Update': { + responseXML = await loadSOAPRecords( + config.headers.SOAPAction.toLocaleLowerCase(), + fullObj.Envelope.Body.UpdateRequest.Objects['@_xsi:type'], + jObj.Envelope.Header.fueloauth, + null + ); + + break; + } + case 'Configure': { + responseXML = await loadSOAPRecords( + config.headers.SOAPAction.toLocaleLowerCase(), + fullObj.Envelope.Body.ConfigureRequestMsg.Configurations.Configuration[0][ + '@_xsi:type' + ], + jObj.Envelope.Header.fueloauth, + null + ); + + break; + } + case 'Delete': { + responseXML = await loadSOAPRecords( + config.headers.SOAPAction.toLocaleLowerCase(), + fullObj.Envelope.Body.DeleteRequest.Objects['@_xsi:type'], + jObj.Envelope.Header.fueloauth, + null + ); + + break; + } + case 'Schedule': { + responseXML = await loadSOAPRecords( + config.headers.SOAPAction.toLocaleLowerCase(), + fullObj.Envelope.Body.ScheduleRequestMsg.Interactions.Interaction['@_xsi:type'], + jObj.Envelope.Header.fueloauth, + fullObj.Envelope.Body.ScheduleRequestMsg.Interactions.Interaction.ObjectID + ); + + break; + } + case 'Perform': { + responseXML = await loadSOAPRecords( + config.headers.SOAPAction.toLocaleLowerCase(), + fullObj.Envelope.Body.PerformRequestMsg.Definitions.Definition['@_xsi:type'], + jObj.Envelope.Header.fueloauth, + fullObj.Envelope.Body.PerformRequestMsg.Definitions.Definition.ObjectID + ); + + break; + } + default: { + throw new Error( + `The SOAP Action ${config.headers.SOAPAction} is not supported by test handler` + ); + } + } + + return [200, responseXML]; +}; + +/** + * helper to return soap base URL + * + * @returns {string} soap URL + */ +export const soapUrl = + 'https://mct0l7nxfq2r988t1kxfy8sc4xxx.soap.marketingcloudapis.com/Service.asmx'; + +/** + * based on request, respond with different soap data + * + * @param {object} config mock api request object + * @returns {Promise.<Array>} status code plus response in string form + */ +export const handleRESTRequest = async (config) => { + try { + // check if filtered + const urlObj = new URL( + config.baseURL + (config.url.startsWith('/') ? config.url.slice(1) : config.url) + ); + let filterName; + let filterBody; + if (urlObj.searchParams.get('$filter')) { + filterName = urlObj.searchParams.get('$filter').split(' eq ')[1]; + } else if (urlObj.searchParams.get('action')) { + filterName = urlObj.searchParams.get('action'); + } else if (urlObj.searchParams.get('mostRecentVersionOnly')) { + filterName = 'mostRecentVersionOnly'; + } else if (urlObj.searchParams.get('versionNumber')) { + filterName = 'versionNumber'; + } else if (urlObj.searchParams.get('status')) { + filterName = 'status'; + } else if (urlObj.searchParams.get('id')) { + filterName = 'id'; + } + + const testPath = path + .join( + 'test', + 'resources', + config.headers.Authorization.replace('Bearer ', ''), + urlObj.pathname, + config.method + '-response' + ) + .replace(':', '_'); // replace : with _ for Windows + const testPathFilter = filterName + ? testPath + + '-' + + (urlObj.searchParams.get('$filter') || urlObj.searchParams.get('action') || '') + .replaceAll(' eq ', '=') + .replaceAll(' ', '') + + (urlObj.searchParams.get('id') ? 'id=' + urlObj.searchParams.get('id') : '') + + (urlObj.searchParams.get('versionNumber') + ? 'versionNumber=' + urlObj.searchParams.get('versionNumber') + : '') + + (urlObj.searchParams.get('mostRecentVersionOnly') + ? 'mostRecentVersionOnly=' + urlObj.searchParams.get('mostRecentVersionOnly') + : '') + + (urlObj.searchParams.get('status') + ? 'status=' + urlObj.searchParams.get('status') + : '') + : null; + + if (!testPathFilter && config.method === 'post' && config.data) { + const simpleOperators = { equal: '=', in: 'IN' }; + const data = JSON.parse(config.data); + const myObj = data.query?.rightOperand || data.query; + if (myObj) { + const op = simpleOperators[myObj.simpleOperator]; + filterBody = `${myObj.property}${op}${op === 'IN' ? myObj.value.join(',') : myObj.value}`; + } else if (config.url === '/email/v1/category') { + const data = JSON.parse(config.data); + + filterBody = Object.keys(data) + .map((key) => `${key}=${data[key]}`) + .join(','); + } else if (config.url === '/asset/v1/content/assets/') { + const data = JSON.parse(config.data); + + if (data.customerKey) { + filterBody = 'key=' + data.customerKey; + } + } + } + const testPathFilterBody = filterBody ? testPath + '-' + filterBody : null; + if (testPathFilter && (await fs.pathExists(testPathFilter + '.json'))) { + // build filter logic to ensure templating works + if (filterName) { + const response = JSON.parse( + await fs.readFile(testPathFilter + '.json', { + encoding: 'utf8', + }) + ); + if ( + response.items && + filterName !== 'mostRecentVersionOnly' && + filterName !== 'versionNumber' && + filterName !== 'id' && + filterName !== 'status' + ) { + response.items = response.items.filter((def) => def.name == filterName); + } + console.log(loadingFile + projectRoot + testPathFilter + '.json'); // eslint-disable-line no-console + return [200, JSON.stringify(response)]; + } else { + console.log(loadingFile + projectRoot + testPathFilter + '.json'); // eslint-disable-line no-console + return [ + 200, + await fs.readFile(testPathFilter + '.json', { + encoding: 'utf8', + }), + ]; + } + } else if (testPathFilter && (await fs.pathExists(testPathFilter + '.txt'))) { + console.log(loadingFile + projectRoot + testPathFilter + '.txt'); // eslint-disable-line no-console + return [ + 200, + await fs.readFile(testPathFilter + '.txt', { + encoding: 'utf8', + }), + ]; + } else if (testPathFilterBody && (await fs.pathExists(testPathFilterBody + '.json'))) { + console.log(loadingFile + projectRoot + testPathFilterBody + '.json'); // eslint-disable-line no-console + return [ + 200, + await fs.readFile(testPathFilterBody + '.json', { + encoding: 'utf8', + }), + ]; + } else if (testPathFilterBody && (await fs.pathExists(testPathFilterBody + '.txt'))) { + console.log(loadingFile + projectRoot + testPathFilterBody + '.txt'); // eslint-disable-line no-console + return [ + 200, + await fs.readFile(testPathFilterBody + '.txt', { + encoding: 'utf8', + }), + ]; + } else if (await fs.pathExists(testPath + '.json')) { + if (testPathFilter) { + /* eslint-disable no-console */ + console.log( + `${tWarn}: You are loading your reponse from ${ + testPath + '.json' + } instead of the more specific ${ + testPathFilter + '.json' + }. Make sure this is intended` + ); + /* eslint-enable no-console */ + } + + if (testPathFilterBody) { + /* eslint-disable no-console */ + console.log( + `${tWarn}: You are loading your reponse from ${ + testPath + '.json' + } instead of the more specific ${ + testPathFilterBody + '.json' + }. Make sure this is intended` + ); + /* eslint-enable no-console */ + } + + // build filter logic to ensure templating works + if ( + filterName && + filterName !== 'mostRecentVersionOnly' && + filterName !== 'versionNumber' && + filterName !== 'id' && + filterName !== 'status' + ) { + const response = JSON.parse( + await fs.readFile(testPath + '.json', { + encoding: 'utf8', + }) + ); + response.items = response.items.filter((def) => def.name == filterName); + response.count = response.items.length; + console.log(loadingFile + projectRoot + testPath + '.json'); // eslint-disable-line no-console + return [200, JSON.stringify(response)]; + } else { + console.log(loadingFile + projectRoot + testPath + '.json'); // eslint-disable-line no-console + + return [ + 200, + await fs.readFile(testPath + '.json', { + encoding: 'utf8', + }), + ]; + } + } else if (await fs.pathExists(testPath + '.txt')) { + if (testPathFilter) { + /* eslint-disable no-console */ + console.log( + `${tWarn}: You are loading your reponse from ${ + testPath + '.txt' + } instead of the more specific ${ + testPathFilter + '.txt' + }. Make sure this is intended` + ); + /* eslint-enable no-console */ + } + if (testPathFilterBody) { + /* eslint-disable no-console */ + console.log( + `${tWarn}: You are loading your reponse from ${ + testPath + '.txt' + } instead of the more specific ${ + testPathFilterBody + '.txt' + }. Make sure this is intended` + ); + /* eslint-enable no-console */ + } + console.log(loadingFile + projectRoot + testPath + '.txt'); // eslint-disable-line no-console + return [ + 200, + await fs.readFile(testPath + '.txt', { + encoding: 'utf8', + }), + ]; + } else { + /* eslint-disable no-console */ + console.log( + `${tError}: Please create file ${testPath}.json/.txt${filterName ? ` or ${testPathFilter}.json/.txt` : testPathFilterBody ? ` or ${testPathFilterBody}.json/.txt` : ''}` + ); + /* eslint-enable no-console */ + process.exitCode = 404; + + return [ + 404, + await fs.readFile(path.join('test', 'resources', 'rest404-response.json'), { + encoding: 'utf8', + }), + ]; + } + } catch (ex) { + console.log(ex); // eslint-disable-line no-console + return [500, {}]; + } +}; + +/** + * helper to return rest base URL + * + * @returns {string} test URL + */ +export const restUrl = 'https://mct0l7nxfq2r988t1kxfy8sc4xxx.rest.marketingcloudapis.com/'; diff --git a/test/resources/1111111/accountUser/configure-response.xml b/test/resources/1111111/accountUser/configure-response.xml new file mode 100644 index 000000000..068ceffd4 --- /dev/null +++ b/test/resources/1111111/accountUser/configure-response.xml @@ -0,0 +1,70 @@ +<?xml version="1.0" encoding="utf-8"?> +<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:xsd="http://www.w3.org/2001/XMLSchema" + xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing" + xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" + xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"> + <soap:Header> + <wsa:Action>ConfigureResponse</wsa:Action> + <wsa:MessageID>urn:uuid:4838c660-b4cd-48fe-99c9-27972a520184</wsa:MessageID> + <wsa:RelatesTo>urn:uuid:ec22f28d-4bc7-4ffc-b3e9-4e731f82c095</wsa:RelatesTo> + <wsa:To>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</wsa:To> + <wsse:Security> + <wsu:Timestamp wsu:Id="Timestamp-419f984d-fb1b-49eb-a090-b0c08d8b11f9"> + <wsu:Created>2023-03-13T15:58:44Z</wsu:Created> + <wsu:Expires>2023-03-13T16:03:44Z</wsu:Expires> + </wsu:Timestamp> + </wsse:Security> + </soap:Header> + <soap:Body> + <ConfigureResponseMsg xmlns="http://exacttarget.com/wsdl/partnerAPI"> + <Results> + <Result> + <StatusCode>OK</StatusCode> + <StatusMessage>User Business Unit assignments successfully updated</StatusMessage> + <OrdinalID>0</OrdinalID> + <Object xsi:type="AccountUser"> + <Client> + <ID>1111111</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <ID>717510285</ID> + <ObjectID xsi:nil="true" /> + <Delete>0</Delete> + <BusinessUnitAssignmentConfiguration> + <BusinessUnitIds> + <BusinessUnitId>1111111</BusinessUnitId> + <BusinessUnitId>9999999</BusinessUnitId> + </BusinessUnitIds> + <IsDelete>false</IsDelete> + </BusinessUnitAssignmentConfiguration> + </Object> + </Result> + <Result> + <StatusCode>OK</StatusCode> + <StatusMessage>User Business Unit assignments successfully updated</StatusMessage> + <OrdinalID>1</OrdinalID> + <Object xsi:type="AccountUser"> + <Client> + <ID>1111111</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <ID>700301950</ID> + <ObjectID xsi:nil="true" /> + <Delete>0</Delete> + <BusinessUnitAssignmentConfiguration> + <BusinessUnitIds> + <BusinessUnitId>1111111</BusinessUnitId> + </BusinessUnitIds> + <IsDelete>true</IsDelete> + </BusinessUnitAssignmentConfiguration> + </Object> + </Result> + </Results> + <OverallStatus>OK</OverallStatus> + <OverallStatusMessage /> + <RequestID>abc28dae-6dfb-4ae9-ad07-63c74963c6d9</RequestID> + </ConfigureResponseMsg> + </soap:Body> +</soap:Envelope> \ No newline at end of file diff --git a/test/resources/1111111/accountUser/create-response.xml b/test/resources/1111111/accountUser/create-response.xml new file mode 100644 index 000000000..d933692ad --- /dev/null +++ b/test/resources/1111111/accountUser/create-response.xml @@ -0,0 +1,97 @@ +<?xml version="1.0" encoding="utf-8"?> +<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:xsd="http://www.w3.org/2001/XMLSchema" + xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing" + xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" + xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"> + <soap:Header> + <wsa:Action>CreateResponse</wsa:Action> + <wsa:MessageID>urn:uuid:545e5b90-8e55-4c57-ac1d-5d675fe15041</wsa:MessageID> + <wsa:RelatesTo>urn:uuid:9c5f9d10-a638-41d2-ad35-b1d1cdc097a8</wsa:RelatesTo> + <wsa:To>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</wsa:To> + <wsse:Security> + <wsu:Timestamp wsu:Id="Timestamp-19e06319-84b9-4b38-a12c-7c40b1eb5f3e"> + <wsu:Created>2023-03-12T00:40:30Z</wsu:Created> + <wsu:Expires>2023-03-12T00:45:30Z</wsu:Expires> + </wsu:Timestamp> + </wsse:Security> + </soap:Header> + <soap:Body> + <CreateResponse xmlns="http://exacttarget.com/wsdl/partnerAPI"> + <Results> + <StatusCode>OK</StatusCode> + <StatusMessage>Account User Updated / Created</StatusMessage> + <OrdinalID>0</OrdinalID> + <NewID>0</NewID> + <Object xsi:type="AccountUser"> + <Client> + <ID>1111111</ID> + <ModifiedBy>123456</ModifiedBy> + </Client> + <PartnerKey xsi:nil="true" /> + <ID>717510285</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>testNew_user</CustomerKey> + <AccountUserID>700301950</AccountUserID> + <UserID>testNew_user@accenture.asgr</UserID> + <Password /> + <Name>new user</Name> + <Email>testNew_user@accenture.com</Email> + <MustChangePassword>false</MustChangePassword> + <ActiveFlag>true</ActiveFlag> + <Delete>0</Delete> + <IsAPIUser>false</IsAPIUser> + <NotificationEmailAddress>testNew_user@accenture.com</NotificationEmailAddress> + <IsLocked>false</IsLocked> + <DefaultBusinessUnit>1111111</DefaultBusinessUnit> + <Locale> + <PartnerKey xsi:nil="true" /> + <ObjectID xsi:nil="true" /> + <LocaleCode>en-GB</LocaleCode> + </Locale> + <TimeZone> + <PartnerKey xsi:nil="true" /> + <ID>5</ID> + <ObjectID xsi:nil="true" /> + <Name>(GMT+01:00) Amsterdam, Berlin, Bern, Rome, Stockholm, Vienna *</Name> + </TimeZone> + <Roles> + <Role> + <Client> + <ID>1111111</ID> + <EnterpriseID>1111111</EnterpriseID> + </Client> + <PartnerKey xsi:nil="true" /> + <ObjectID>f1cfb80f-3550-e611-96fe-38eaa7142c61</ObjectID> + <Name>Administrator</Name> + <AssignmentConfigurations> + <AssignmentConfiguration> + <AccountUserId>717510285</AccountUserId> + <AssignmentConfigureType>RoleUser</AssignmentConfigureType> + </AssignmentConfiguration> + </AssignmentConfigurations> + </Role> + <Role> + <Client> + <ID>1111111</ID> + <EnterpriseID>1111111</EnterpriseID> + </Client> + <PartnerKey xsi:nil="true" /> + <ObjectID>fdcfb80f-3550-e611-96fe-38eaa7142c61</ObjectID> + <Name>Distributed Sending User</Name> + <AssignmentConfigurations> + <AssignmentConfiguration> + <AccountUserId>717510285</AccountUserId> + <AssignmentConfigureType>RoleUser</AssignmentConfigureType> + </AssignmentConfiguration> + </AssignmentConfigurations> + </Role> + </Roles> + </Object> + </Results> + <RequestID>84d01639-9b81-4a45-9928-bf438c0f86bf</RequestID> + <OverallStatus>OK</OverallStatus> + </CreateResponse> + </soap:Body> +</soap:Envelope> \ No newline at end of file diff --git a/test/resources/1111111/accountUser/retrieve-ActiveFlag=falseANDCustomerKey=testExisting_userANDEmaillike@-QAA-response.xml b/test/resources/1111111/accountUser/retrieve-ActiveFlag=falseANDCustomerKey=testExisting_userANDEmaillike@-QAA-response.xml new file mode 100644 index 000000000..af1dec2e2 --- /dev/null +++ b/test/resources/1111111/accountUser/retrieve-ActiveFlag=falseANDCustomerKey=testExisting_userANDEmaillike@-QAA-response.xml @@ -0,0 +1,27 @@ +<?xml version="1.0" encoding="UTF-8"?> +<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" + xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing" + xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" + xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" + xmlns:xsd="http://www.w3.org/2001/XMLSchema" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> + <soap:Header> + <wsa:Action>RetrieveResponse</wsa:Action> + <wsa:MessageID>urn:uuid:1babdae0-9282-4bba-b69f-2f1843deaf11</wsa:MessageID> + <wsa:RelatesTo>urn:uuid:39d1c021-b3df-49f9-a8f7-bb444172d2d3</wsa:RelatesTo> + <wsa:To>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</wsa:To> + <wsse:Security> + <wsu:Timestamp wsu:Id="Timestamp-291db2ee-625d-49f7-8f6f-110317b081a5"> + <wsu:Created>2023-03-11T13:53:00Z</wsu:Created> + <wsu:Expires>2023-03-11T13:58:00Z</wsu:Expires> + </wsu:Timestamp> + </wsse:Security> + </soap:Header> + <soap:Body> + <RetrieveResponseMsg xmlns="http://exacttarget.com/wsdl/partnerAPI"> + <OverallStatus>OK</OverallStatus> + <RequestID>5347bf1d-e801-486a-b4a9-c2d46a8909b6</RequestID> + + </RetrieveResponseMsg> + </soap:Body> +</soap:Envelope> \ No newline at end of file diff --git a/test/resources/1111111/accountUser/retrieve-ActiveFlag=falseANDEmaillike@-QAA-response.xml b/test/resources/1111111/accountUser/retrieve-ActiveFlag=falseANDEmaillike@-QAA-response.xml new file mode 100644 index 000000000..22ee9fd1e --- /dev/null +++ b/test/resources/1111111/accountUser/retrieve-ActiveFlag=falseANDEmaillike@-QAA-response.xml @@ -0,0 +1,156 @@ +<?xml version="1.0" encoding="UTF-8"?> +<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" + xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing" + xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" + xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" + xmlns:xsd="http://www.w3.org/2001/XMLSchema" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> + <soap:Header> + <wsa:Action>RetrieveResponse</wsa:Action> + <wsa:MessageID>urn:uuid:1babdae0-9282-4bba-b69f-2f1843deaf11</wsa:MessageID> + <wsa:RelatesTo>urn:uuid:39d1c021-b3df-49f9-a8f7-bb444172d2d3</wsa:RelatesTo> + <wsa:To>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</wsa:To> + <wsse:Security> + <wsu:Timestamp wsu:Id="Timestamp-291db2ee-625d-49f7-8f6f-110317b081a5"> + <wsu:Created>2023-03-11T13:53:00Z</wsu:Created> + <wsu:Expires>2023-03-11T13:58:00Z</wsu:Expires> + </wsu:Timestamp> + </wsse:Security> + </soap:Header> + <soap:Body> + <RetrieveResponseMsg xmlns="http://exacttarget.com/wsdl/partnerAPI"> + <OverallStatus>OK</OverallStatus> + <RequestID>5347bf1d-e801-486a-b4a9-c2d46a8909b6</RequestID> + <Results xsi:type="AccountUser"> + <Client> + <ID>1111111</ID> + <ModifiedBy>123456</ModifiedBy> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2019-09-06T01:59:07.097</CreatedDate> + <ModifiedDate>2022-06-21T01:43:02.64</ModifiedDate> + <ID>700301951</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>testExisting_user_inactive</CustomerKey> + <AccountUserID>700301951</AccountUserID> + <UserID>user_test-inactive@accenture.asgr</UserID> + <Name>user test-inactive</Name> + <Email>user_test-inactive@accenture.com</Email> + <MustChangePassword>false</MustChangePassword> + <ActiveFlag>false</ActiveFlag> + <UserPermissions> + <PartnerKey xsi:nil="true" /> + <ID>2</ID> + <ObjectID xsi:nil="true" /> + <Name xsi:nil="true" /> + <Value xsi:nil="true" /> + <Description xsi:nil="true" /> + <Delete>0</Delete> + </UserPermissions> + <UserPermissions> + <PartnerKey xsi:nil="true" /> + <ID>3</ID> + <ObjectID xsi:nil="true" /> + <Name xsi:nil="true" /> + <Value xsi:nil="true" /> + <Description xsi:nil="true" /> + <Delete>0</Delete> + </UserPermissions> + <Delete>0</Delete> + <LastSuccessfulLogin>2023-02-23T10:14:11.443</LastSuccessfulLogin> + <IsAPIUser>false</IsAPIUser> + <NotificationEmailAddress>user_test-inactive@accenture.com</NotificationEmailAddress> + <IsLocked>false</IsLocked> + <DefaultBusinessUnit>1111111</DefaultBusinessUnit> + <DefaultBusinessUnitObject> + <PartnerKey xsi:nil="true" /> + <ID>1111111</ID> + <ObjectID xsi:nil="true" /> + <AccountType>None</AccountType> + <Subscription xsi:nil="true" /> + </DefaultBusinessUnitObject> + <Locale> + <PartnerKey xsi:nil="true" /> + <ObjectID xsi:nil="true" /> + <LocaleCode>en-GB</LocaleCode> + </Locale> + <TimeZone> + <PartnerKey xsi:nil="true" /> + <ID>5</ID> + <ObjectID xsi:nil="true" /> + <Name>(GMT+01:00) Amsterdam, Berlin, Bern, Rome, Stockholm, Vienna *</Name> + </TimeZone> + <Roles> + <Role> + <Client> + <ID>1111111</ID> + <CreatedBy>-1000</CreatedBy> + <ModifiedBy>-1000</ModifiedBy> + <EnterpriseID>1111111</EnterpriseID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2016-07-22T17:52:36.93</CreatedDate> + <ModifiedDate>2016-07-22T17:52:36.93</ModifiedDate> + <ObjectID>f1cfb80f-3550-e611-96fe-38eaa7142c61</ObjectID> + <CustomerKey>SYS_DEF_ADMIN</CustomerKey> + <Name>Administrator</Name> + <Description>Administrator</Description> + <IsPrivate>false</IsPrivate> + <IsSystemDefined>true</IsSystemDefined> + </Role> + <Role> + <Client> + <ID>1111111</ID> + <CreatedBy>-1000</CreatedBy> + <ModifiedBy>-1000</ModifiedBy> + <EnterpriseID>1111111</EnterpriseID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2016-07-22T17:52:36.93</CreatedDate> + <ModifiedDate>2016-07-22T17:52:36.93</ModifiedDate> + <ObjectID>f4cfb80f-3550-e611-96fe-38eaa7142c61</ObjectID> + <CustomerKey>SYS_DEF_CONTENT</CustomerKey> + <Name>Content Creator</Name> + <Description>Content Creator</Description> + <IsPrivate>false</IsPrivate> + <IsSystemDefined>true</IsSystemDefined> + </Role> + <Role> + <Client> + <ID>1111111</ID> + <CreatedBy>-1000</CreatedBy> + <ModifiedBy>-1000</ModifiedBy> + <EnterpriseID>1111111</EnterpriseID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2019-09-06T07:59:07.8</CreatedDate> + <ModifiedDate>2019-09-06T07:59:07.8</ModifiedDate> + <ObjectID>bd251431-7cd0-e911-a2d3-1402ec936979</ObjectID> + <CustomerKey>Individual role for 700301951</CustomerKey> + <Name>Individual role for 700301951</Name> + <Description>Individual role for 700301951</Description> + <IsPrivate>true</IsPrivate> + <IsSystemDefined>false</IsSystemDefined> + </Role> + <Role> + <Client> + <ID>0</ID> + <CreatedBy>0</CreatedBy> + <ModifiedBy>0</ModifiedBy> + <EnterpriseID>0</EnterpriseID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2012-02-21T02:09:19.983</CreatedDate> + <ModifiedDate>2013-12-23T16:48:50.533</ModifiedDate> + <ObjectID>63a50610-315c-e111-beee-8e001800001f</ObjectID> + <CustomerKey>SYS_DEF_IMHADMIN</CustomerKey> + <Name>Marketing Cloud Administrator</Name> + <Description>Assign Marketing Cloud roles to users and manage Mobile, Social and Sites Channels, Hub Apps and Marketing Cloud Tools</Description> + <IsPrivate>false</IsPrivate> + <IsSystemDefined>true</IsSystemDefined> + </Role> + </Roles> + </Results> + </RetrieveResponseMsg> + </soap:Body> +</soap:Envelope> \ No newline at end of file diff --git a/test/resources/1111111/accountUser/retrieve-ActiveFlag=trueANDCustomerKey=testExisting_userANDEmaillike@-QAA-response.xml b/test/resources/1111111/accountUser/retrieve-ActiveFlag=trueANDCustomerKey=testExisting_userANDEmaillike@-QAA-response.xml new file mode 100644 index 000000000..e16046c89 --- /dev/null +++ b/test/resources/1111111/accountUser/retrieve-ActiveFlag=trueANDCustomerKey=testExisting_userANDEmaillike@-QAA-response.xml @@ -0,0 +1,156 @@ +<?xml version="1.0" encoding="UTF-8"?> +<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" + xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing" + xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" + xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" + xmlns:xsd="http://www.w3.org/2001/XMLSchema" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> + <soap:Header> + <wsa:Action>RetrieveResponse</wsa:Action> + <wsa:MessageID>urn:uuid:1babdae0-9282-4bba-b69f-2f1843deaf11</wsa:MessageID> + <wsa:RelatesTo>urn:uuid:39d1c021-b3df-49f9-a8f7-bb444172d2d3</wsa:RelatesTo> + <wsa:To>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</wsa:To> + <wsse:Security> + <wsu:Timestamp wsu:Id="Timestamp-291db2ee-625d-49f7-8f6f-110317b081a5"> + <wsu:Created>2023-03-11T13:53:00Z</wsu:Created> + <wsu:Expires>2023-03-11T13:58:00Z</wsu:Expires> + </wsu:Timestamp> + </wsse:Security> + </soap:Header> + <soap:Body> + <RetrieveResponseMsg xmlns="http://exacttarget.com/wsdl/partnerAPI"> + <OverallStatus>OK</OverallStatus> + <RequestID>5347bf1d-e801-486a-b4a9-c2d46a8909b6</RequestID> + <Results xsi:type="AccountUser"> + <Client> + <ID>1111111</ID> + <ModifiedBy>123456</ModifiedBy> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2019-09-06T01:59:07.097</CreatedDate> + <ModifiedDate>2022-06-21T01:43:02.64</ModifiedDate> + <ID>700301950</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>testExisting_user</CustomerKey> + <AccountUserID>700301950</AccountUserID> + <UserID>user_test@accenture.asgr</UserID> + <Name>user test</Name> + <Email>user_test@accenture.com</Email> + <MustChangePassword>false</MustChangePassword> + <ActiveFlag>true</ActiveFlag> + <UserPermissions> + <PartnerKey xsi:nil="true" /> + <ID>2</ID> + <ObjectID xsi:nil="true" /> + <Name xsi:nil="true" /> + <Value xsi:nil="true" /> + <Description xsi:nil="true" /> + <Delete>0</Delete> + </UserPermissions> + <UserPermissions> + <PartnerKey xsi:nil="true" /> + <ID>3</ID> + <ObjectID xsi:nil="true" /> + <Name xsi:nil="true" /> + <Value xsi:nil="true" /> + <Description xsi:nil="true" /> + <Delete>0</Delete> + </UserPermissions> + <Delete>0</Delete> + <LastSuccessfulLogin>2023-02-23T10:14:11.443</LastSuccessfulLogin> + <IsAPIUser>false</IsAPIUser> + <NotificationEmailAddress>user_test@accenture.com</NotificationEmailAddress> + <IsLocked>false</IsLocked> + <DefaultBusinessUnit>1111111</DefaultBusinessUnit> + <DefaultBusinessUnitObject> + <PartnerKey xsi:nil="true" /> + <ID>1111111</ID> + <ObjectID xsi:nil="true" /> + <AccountType>None</AccountType> + <Subscription xsi:nil="true" /> + </DefaultBusinessUnitObject> + <Locale> + <PartnerKey xsi:nil="true" /> + <ObjectID xsi:nil="true" /> + <LocaleCode>en-GB</LocaleCode> + </Locale> + <TimeZone> + <PartnerKey xsi:nil="true" /> + <ID>5</ID> + <ObjectID xsi:nil="true" /> + <Name>(GMT+01:00) Amsterdam, Berlin, Bern, Rome, Stockholm, Vienna *</Name> + </TimeZone> + <Roles> + <Role> + <Client> + <ID>1111111</ID> + <CreatedBy>-1000</CreatedBy> + <ModifiedBy>-1000</ModifiedBy> + <EnterpriseID>1111111</EnterpriseID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2016-07-22T17:52:36.93</CreatedDate> + <ModifiedDate>2016-07-22T17:52:36.93</ModifiedDate> + <ObjectID>f1cfb80f-3550-e611-96fe-38eaa7142c61</ObjectID> + <CustomerKey>SYS_DEF_ADMIN</CustomerKey> + <Name>Administrator</Name> + <Description>Administrator</Description> + <IsPrivate>false</IsPrivate> + <IsSystemDefined>true</IsSystemDefined> + </Role> + <Role> + <Client> + <ID>1111111</ID> + <CreatedBy>-1000</CreatedBy> + <ModifiedBy>-1000</ModifiedBy> + <EnterpriseID>1111111</EnterpriseID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2016-07-22T17:52:36.93</CreatedDate> + <ModifiedDate>2016-07-22T17:52:36.93</ModifiedDate> + <ObjectID>f4cfb80f-3550-e611-96fe-38eaa7142c61</ObjectID> + <CustomerKey>SYS_DEF_CONTENT</CustomerKey> + <Name>Content Creator</Name> + <Description>Content Creator</Description> + <IsPrivate>false</IsPrivate> + <IsSystemDefined>true</IsSystemDefined> + </Role> + <Role> + <Client> + <ID>1111111</ID> + <CreatedBy>-1000</CreatedBy> + <ModifiedBy>-1000</ModifiedBy> + <EnterpriseID>1111111</EnterpriseID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2019-09-06T07:59:07.8</CreatedDate> + <ModifiedDate>2019-09-06T07:59:07.8</ModifiedDate> + <ObjectID>bd251431-7cd0-e911-a2d3-1402ec936979</ObjectID> + <CustomerKey>Individual role for 700301950</CustomerKey> + <Name>Individual role for 700301950</Name> + <Description>Individual role for 700301950</Description> + <IsPrivate>true</IsPrivate> + <IsSystemDefined>false</IsSystemDefined> + </Role> + <Role> + <Client> + <ID>0</ID> + <CreatedBy>0</CreatedBy> + <ModifiedBy>0</ModifiedBy> + <EnterpriseID>0</EnterpriseID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2012-02-21T02:09:19.983</CreatedDate> + <ModifiedDate>2013-12-23T16:48:50.533</ModifiedDate> + <ObjectID>63a50610-315c-e111-beee-8e001800001f</ObjectID> + <CustomerKey>SYS_DEF_IMHADMIN</CustomerKey> + <Name>Marketing Cloud Administrator</Name> + <Description>Assign Marketing Cloud roles to users and manage Mobile, Social and Sites Channels, Hub Apps and Marketing Cloud Tools</Description> + <IsPrivate>false</IsPrivate> + <IsSystemDefined>true</IsSystemDefined> + </Role> + </Roles> + </Results> + </RetrieveResponseMsg> + </soap:Body> +</soap:Envelope> \ No newline at end of file diff --git a/test/resources/1111111/accountUser/retrieve-ActiveFlag=trueANDEmailisNullORNamelikeapp userANDMustChangePassword=false-QAA-response.xml b/test/resources/1111111/accountUser/retrieve-ActiveFlag=trueANDEmailisNullORNamelikeapp userANDMustChangePassword=false-QAA-response.xml new file mode 100644 index 000000000..5ac4001a5 --- /dev/null +++ b/test/resources/1111111/accountUser/retrieve-ActiveFlag=trueANDEmailisNullORNamelikeapp userANDMustChangePassword=false-QAA-response.xml @@ -0,0 +1,87 @@ +<?xml version="1.0" encoding="UTF-8"?> +<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" + xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing" + xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" + xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" + xmlns:xsd="http://www.w3.org/2001/XMLSchema" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> + <soap:Header> + <wsa:Action>RetrieveResponse</wsa:Action> + <wsa:MessageID>urn:uuid:1babdae0-9282-4bba-b69f-2f1843deaf11</wsa:MessageID> + <wsa:RelatesTo>urn:uuid:39d1c021-b3df-49f9-a8f7-bb444172d2d3</wsa:RelatesTo> + <wsa:To>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</wsa:To> + <wsse:Security> + <wsu:Timestamp wsu:Id="Timestamp-291db2ee-625d-49f7-8f6f-110317b081a5"> + <wsu:Created>2023-03-11T13:53:00Z</wsu:Created> + <wsu:Expires>2023-03-11T13:58:00Z</wsu:Expires> + </wsu:Timestamp> + </wsse:Security> + </soap:Header> + <soap:Body> + <RetrieveResponseMsg xmlns="http://exacttarget.com/wsdl/partnerAPI"> + <OverallStatus>OK</OverallStatus> + <RequestID>5347bf1d-e801-486a-b4a9-c2d46a8909b6</RequestID> + <Results xsi:type="AccountUser"> + <Client> + <ID>1111111</ID> + <ModifiedBy>0</ModifiedBy> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2016-07-22T11:52:37.42</CreatedDate> + <ModifiedDate>2023-05-27T07:05:55.113</ModifiedDate> + <ID>7471228</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>45372cbb-06e0-438e-88d8-008981f7a18b</CustomerKey> + <AccountUserID>7471228</AccountUserID> + <UserID>20f2d94a-9a7d-4580-9fb6-c36a1ce32fb9</UserID> + <Name>igopredictiveemail app user</Name> + <Email /> + <MustChangePassword>false</MustChangePassword> + <ActiveFlag>true</ActiveFlag> + <Delete>0</Delete> + <LastSuccessfulLogin></LastSuccessfulLogin> + <IsAPIUser>true</IsAPIUser> + <NotificationEmailAddress /> + <IsLocked>false</IsLocked> + <DefaultBusinessUnit>1111111</DefaultBusinessUnit> + <Locale> + <PartnerKey xsi:nil="true" /> + <ObjectID xsi:nil="true" /> + <LocaleCode>en-GB</LocaleCode> + </Locale> + <TimeZone> + <PartnerKey xsi:nil="true" /> + <ID>5</ID> + <ObjectID xsi:nil="true" /> + <Name>(GMT+01:00) Amsterdam, Berlin, Bern, Rome, Stockholm, Vienna</Name> + </TimeZone> + <DefaultBusinessUnitObject> + <PartnerKey xsi:nil="true" /> + <ID>1111111</ID> + <ObjectID xsi:nil="true" /> + <AccountType>None</AccountType> + <Subscription xsi:nil="true" /> + </DefaultBusinessUnitObject> + <Roles> + <Role> + <Client> + <ID>1111111</ID> + <CreatedBy>0</CreatedBy> + <ModifiedBy>0</ModifiedBy> + <EnterpriseID>1111111</EnterpriseID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2016-07-22T17:52:37.88</CreatedDate> + <ModifiedDate>2016-07-22T17:52:37.88</ModifiedDate> + <ObjectID>44d0b80f-3550-e611-96fe-38eaa7142c61</ObjectID> + <CustomerKey>Individual role for 7471228</CustomerKey> + <Name>Individual role for 7471228</Name> + <Description>Individual role for 7471228</Description> + <IsPrivate>true</IsPrivate> + <IsSystemDefined>false</IsSystemDefined> + </Role> + </Roles> + </Results> + </RetrieveResponseMsg> + </soap:Body> +</soap:Envelope> \ No newline at end of file diff --git a/test/resources/1111111/accountUser/retrieve-ActiveFlag=trueANDEmaillike@-QAA-response.xml b/test/resources/1111111/accountUser/retrieve-ActiveFlag=trueANDEmaillike@-QAA-response.xml new file mode 100644 index 000000000..e16046c89 --- /dev/null +++ b/test/resources/1111111/accountUser/retrieve-ActiveFlag=trueANDEmaillike@-QAA-response.xml @@ -0,0 +1,156 @@ +<?xml version="1.0" encoding="UTF-8"?> +<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" + xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing" + xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" + xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" + xmlns:xsd="http://www.w3.org/2001/XMLSchema" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> + <soap:Header> + <wsa:Action>RetrieveResponse</wsa:Action> + <wsa:MessageID>urn:uuid:1babdae0-9282-4bba-b69f-2f1843deaf11</wsa:MessageID> + <wsa:RelatesTo>urn:uuid:39d1c021-b3df-49f9-a8f7-bb444172d2d3</wsa:RelatesTo> + <wsa:To>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</wsa:To> + <wsse:Security> + <wsu:Timestamp wsu:Id="Timestamp-291db2ee-625d-49f7-8f6f-110317b081a5"> + <wsu:Created>2023-03-11T13:53:00Z</wsu:Created> + <wsu:Expires>2023-03-11T13:58:00Z</wsu:Expires> + </wsu:Timestamp> + </wsse:Security> + </soap:Header> + <soap:Body> + <RetrieveResponseMsg xmlns="http://exacttarget.com/wsdl/partnerAPI"> + <OverallStatus>OK</OverallStatus> + <RequestID>5347bf1d-e801-486a-b4a9-c2d46a8909b6</RequestID> + <Results xsi:type="AccountUser"> + <Client> + <ID>1111111</ID> + <ModifiedBy>123456</ModifiedBy> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2019-09-06T01:59:07.097</CreatedDate> + <ModifiedDate>2022-06-21T01:43:02.64</ModifiedDate> + <ID>700301950</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>testExisting_user</CustomerKey> + <AccountUserID>700301950</AccountUserID> + <UserID>user_test@accenture.asgr</UserID> + <Name>user test</Name> + <Email>user_test@accenture.com</Email> + <MustChangePassword>false</MustChangePassword> + <ActiveFlag>true</ActiveFlag> + <UserPermissions> + <PartnerKey xsi:nil="true" /> + <ID>2</ID> + <ObjectID xsi:nil="true" /> + <Name xsi:nil="true" /> + <Value xsi:nil="true" /> + <Description xsi:nil="true" /> + <Delete>0</Delete> + </UserPermissions> + <UserPermissions> + <PartnerKey xsi:nil="true" /> + <ID>3</ID> + <ObjectID xsi:nil="true" /> + <Name xsi:nil="true" /> + <Value xsi:nil="true" /> + <Description xsi:nil="true" /> + <Delete>0</Delete> + </UserPermissions> + <Delete>0</Delete> + <LastSuccessfulLogin>2023-02-23T10:14:11.443</LastSuccessfulLogin> + <IsAPIUser>false</IsAPIUser> + <NotificationEmailAddress>user_test@accenture.com</NotificationEmailAddress> + <IsLocked>false</IsLocked> + <DefaultBusinessUnit>1111111</DefaultBusinessUnit> + <DefaultBusinessUnitObject> + <PartnerKey xsi:nil="true" /> + <ID>1111111</ID> + <ObjectID xsi:nil="true" /> + <AccountType>None</AccountType> + <Subscription xsi:nil="true" /> + </DefaultBusinessUnitObject> + <Locale> + <PartnerKey xsi:nil="true" /> + <ObjectID xsi:nil="true" /> + <LocaleCode>en-GB</LocaleCode> + </Locale> + <TimeZone> + <PartnerKey xsi:nil="true" /> + <ID>5</ID> + <ObjectID xsi:nil="true" /> + <Name>(GMT+01:00) Amsterdam, Berlin, Bern, Rome, Stockholm, Vienna *</Name> + </TimeZone> + <Roles> + <Role> + <Client> + <ID>1111111</ID> + <CreatedBy>-1000</CreatedBy> + <ModifiedBy>-1000</ModifiedBy> + <EnterpriseID>1111111</EnterpriseID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2016-07-22T17:52:36.93</CreatedDate> + <ModifiedDate>2016-07-22T17:52:36.93</ModifiedDate> + <ObjectID>f1cfb80f-3550-e611-96fe-38eaa7142c61</ObjectID> + <CustomerKey>SYS_DEF_ADMIN</CustomerKey> + <Name>Administrator</Name> + <Description>Administrator</Description> + <IsPrivate>false</IsPrivate> + <IsSystemDefined>true</IsSystemDefined> + </Role> + <Role> + <Client> + <ID>1111111</ID> + <CreatedBy>-1000</CreatedBy> + <ModifiedBy>-1000</ModifiedBy> + <EnterpriseID>1111111</EnterpriseID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2016-07-22T17:52:36.93</CreatedDate> + <ModifiedDate>2016-07-22T17:52:36.93</ModifiedDate> + <ObjectID>f4cfb80f-3550-e611-96fe-38eaa7142c61</ObjectID> + <CustomerKey>SYS_DEF_CONTENT</CustomerKey> + <Name>Content Creator</Name> + <Description>Content Creator</Description> + <IsPrivate>false</IsPrivate> + <IsSystemDefined>true</IsSystemDefined> + </Role> + <Role> + <Client> + <ID>1111111</ID> + <CreatedBy>-1000</CreatedBy> + <ModifiedBy>-1000</ModifiedBy> + <EnterpriseID>1111111</EnterpriseID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2019-09-06T07:59:07.8</CreatedDate> + <ModifiedDate>2019-09-06T07:59:07.8</ModifiedDate> + <ObjectID>bd251431-7cd0-e911-a2d3-1402ec936979</ObjectID> + <CustomerKey>Individual role for 700301950</CustomerKey> + <Name>Individual role for 700301950</Name> + <Description>Individual role for 700301950</Description> + <IsPrivate>true</IsPrivate> + <IsSystemDefined>false</IsSystemDefined> + </Role> + <Role> + <Client> + <ID>0</ID> + <CreatedBy>0</CreatedBy> + <ModifiedBy>0</ModifiedBy> + <EnterpriseID>0</EnterpriseID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2012-02-21T02:09:19.983</CreatedDate> + <ModifiedDate>2013-12-23T16:48:50.533</ModifiedDate> + <ObjectID>63a50610-315c-e111-beee-8e001800001f</ObjectID> + <CustomerKey>SYS_DEF_IMHADMIN</CustomerKey> + <Name>Marketing Cloud Administrator</Name> + <Description>Assign Marketing Cloud roles to users and manage Mobile, Social and Sites Channels, Hub Apps and Marketing Cloud Tools</Description> + <IsPrivate>false</IsPrivate> + <IsSystemDefined>true</IsSystemDefined> + </Role> + </Roles> + </Results> + </RetrieveResponseMsg> + </soap:Body> +</soap:Envelope> \ No newline at end of file diff --git a/test/resources/1111111/accountUser/update-response.xml b/test/resources/1111111/accountUser/update-response.xml new file mode 100644 index 000000000..d84a68d36 --- /dev/null +++ b/test/resources/1111111/accountUser/update-response.xml @@ -0,0 +1,111 @@ +<?xml version="1.0" encoding="utf-8"?> +<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:xsd="http://www.w3.org/2001/XMLSchema" + xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing" + xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" + xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"> + <soap:Header> + <wsa:Action>UpdateResponse</wsa:Action> + <wsa:MessageID>urn:uuid:8ce806f1-f241-4c35-8f95-d875247b55e6</wsa:MessageID> + <wsa:RelatesTo>urn:uuid:076f561c-4ba4-4917-b2ed-1d0a8e42b8a5</wsa:RelatesTo> + <wsa:To>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</wsa:To> + <wsse:Security> + <wsu:Timestamp wsu:Id="Timestamp-f579dff1-d9b3-4616-b3b4-3f724fe1a8fc"> + <wsu:Created>2023-03-12T00:10:58Z</wsu:Created> + <wsu:Expires>2023-03-12T00:15:58Z</wsu:Expires> + </wsu:Timestamp> + </wsse:Security> + </soap:Header> + <soap:Body> + <UpdateResponse xmlns="http://exacttarget.com/wsdl/partnerAPI"> + <Results> + <StatusCode>OK</StatusCode> + <StatusMessage>Account User Updated / Created</StatusMessage> + <OrdinalID>0</OrdinalID> + <Object xsi:type="AccountUser"> + <Client> + <ID>1111111</ID> + <ModifiedBy>123456</ModifiedBy> + </Client> + <PartnerKey xsi:nil="true" /> + <ID>700301950</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>testExisting_user</CustomerKey> + <AccountUserID>700301950</AccountUserID> + <UserID>user_test@accenture.asgr</UserID> + <Password /> + <Name>user test</Name> + <Email>user_test@accenture.com</Email> + <MustChangePassword>false</MustChangePassword> + <ActiveFlag>true</ActiveFlag> + <Delete>0</Delete> + <IsAPIUser>false</IsAPIUser> + <NotificationEmailAddress>user_test@accenture.com</NotificationEmailAddress> + <IsLocked>false</IsLocked> + <DefaultBusinessUnit>9999999</DefaultBusinessUnit> + <Locale> + <PartnerKey xsi:nil="true" /> + <ObjectID xsi:nil="true" /> + <LocaleCode>en-GB</LocaleCode> + </Locale> + <TimeZone> + <PartnerKey xsi:nil="true" /> + <ID>5</ID> + <ObjectID xsi:nil="true" /> + <Name>(GMT+01:00) Amsterdam, Berlin, Bern, Rome, Stockholm, Vienna *</Name> + </TimeZone> + <Roles> + <Role> + <Client> + <ID>1111111</ID> + <EnterpriseID>1111111</EnterpriseID> + </Client> + <PartnerKey xsi:nil="true" /> + <ObjectID>f1cfb80f-3550-e611-96fe-38eaa7142c61</ObjectID> + <Name>Administrator</Name> + <AssignmentConfigurations> + <AssignmentConfiguration> + <AccountUserId>700301950</AccountUserId> + <AssignmentConfigureType>RoleUser</AssignmentConfigureType> + </AssignmentConfiguration> + </AssignmentConfigurations> + </Role> + <Role> + <Client> + <ID>1111111</ID> + <EnterpriseID>1111111</EnterpriseID> + </Client> + <PartnerKey xsi:nil="true" /> + <ObjectID>fdcfb80f-3550-e611-96fe-38eaa7142c61</ObjectID> + <Name>Distributed Sending User</Name> + <AssignmentConfigurations> + <AssignmentConfiguration> + <AccountUserId>700301950</AccountUserId> + <AssignmentConfigureType>RoleUser</AssignmentConfigureType> + </AssignmentConfiguration> + </AssignmentConfigurations> + </Role> + <Role> + <Client> + <ID>1111111</ID> + <EnterpriseID>1111111</EnterpriseID> + </Client> + <PartnerKey xsi:nil="true" /> + <ObjectID>bd251431-7cd0-e911-a2d3-1402ec936979</ObjectID> + <Name>Individual role for 700301950</Name> + <AssignmentConfigurations> + <AssignmentConfiguration> + <AccountUserId>700301950</AccountUserId> + <AssignmentConfigureType>RoleUser</AssignmentConfigureType> + </AssignmentConfiguration> + </AssignmentConfigurations> + </Role> + </Roles> + </Object> + </Results> + <RequestID>b2f921a5-e46e-4226-a2fa-8bdbb4d99a7a</RequestID> + <OverallStatus>OK</OverallStatus> + </UpdateResponse> + </soap:Body> +</soap:Envelope> \ No newline at end of file diff --git a/test/resources/1111111/accountUserAccount/retrieve-AccountUser.AccountUserID=700301950-response.xml b/test/resources/1111111/accountUserAccount/retrieve-AccountUser.AccountUserID=700301950-response.xml new file mode 100644 index 000000000..29e5e4173 --- /dev/null +++ b/test/resources/1111111/accountUserAccount/retrieve-AccountUser.AccountUserID=700301950-response.xml @@ -0,0 +1,60 @@ +<?xml version="1.0" encoding="utf-8"?> +<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:xsd="http://www.w3.org/2001/XMLSchema" + xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing" + xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" + xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"> + <soap:Header> + <wsa:Action>RetrieveResponse</wsa:Action> + <wsa:MessageID>urn:uuid:b9fbc10c-2775-48d0-b9bb-fddf1ed90616</wsa:MessageID> + <wsa:RelatesTo>urn:uuid:11d44cfe-e1d7-4fc2-b6ad-a2c806573859</wsa:RelatesTo> + <wsa:To>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</wsa:To> + <wsse:Security> + <wsu:Timestamp wsu:Id="Timestamp-d8079cba-e093-43dc-9f6c-0e7d50ec95dd"> + <wsu:Created>2023-03-11T13:52:52Z</wsu:Created> + <wsu:Expires>2023-03-11T13:57:52Z</wsu:Expires> + </wsu:Timestamp> + </wsse:Security> + </soap:Header> + <soap:Body> + <RetrieveResponseMsg xmlns="http://exacttarget.com/wsdl/partnerAPI"> + <OverallStatus>OK</OverallStatus> + <RequestID>f4057c93-40e3-47d6-a953-06839e221d40</RequestID> + <Results xsi:type="AccountUserAccount"> + <PartnerKey xsi:nil="true" /> + <ObjectID xsi:nil="true" /> + <AccountUser> + <PartnerKey xsi:nil="true" /> + <ObjectID xsi:nil="true" /> + <AccountUserID>700301950</AccountUserID> + <Delete>0</Delete> + </AccountUser> + <Account> + <PartnerKey xsi:nil="true" /> + <ID>1111111</ID> + <ObjectID xsi:nil="true" /> + <AccountType>None</AccountType> + <Subscription xsi:nil="true" /> + </Account> + </Results> + <Results xsi:type="AccountUserAccount"> + <PartnerKey xsi:nil="true" /> + <ObjectID xsi:nil="true" /> + <AccountUser> + <PartnerKey xsi:nil="true" /> + <ObjectID xsi:nil="true" /> + <AccountUserID>700301950</AccountUserID> + <Delete>0</Delete> + </AccountUser> + <Account> + <PartnerKey xsi:nil="true" /> + <ID>9999999</ID> + <ObjectID xsi:nil="true" /> + <AccountType>None</AccountType> + <Subscription xsi:nil="true" /> + </Account> + </Results> + </RetrieveResponseMsg> + </soap:Body> +</soap:Envelope> \ No newline at end of file diff --git a/test/resources/1111111/accountUserAccount/retrieve-AccountUser.AccountUserIDIN700301950,700301951,7471228-response.xml b/test/resources/1111111/accountUserAccount/retrieve-AccountUser.AccountUserIDIN700301950,700301951,7471228-response.xml new file mode 100644 index 000000000..1538cb334 --- /dev/null +++ b/test/resources/1111111/accountUserAccount/retrieve-AccountUser.AccountUserIDIN700301950,700301951,7471228-response.xml @@ -0,0 +1,77 @@ +<?xml version="1.0" encoding="utf-8"?> +<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:xsd="http://www.w3.org/2001/XMLSchema" + xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing" + xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" + xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"> + <soap:Header> + <wsa:Action>RetrieveResponse</wsa:Action> + <wsa:MessageID>urn:uuid:b9fbc10c-2775-48d0-b9bb-fddf1ed90616</wsa:MessageID> + <wsa:RelatesTo>urn:uuid:11d44cfe-e1d7-4fc2-b6ad-a2c806573859</wsa:RelatesTo> + <wsa:To>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</wsa:To> + <wsse:Security> + <wsu:Timestamp wsu:Id="Timestamp-d8079cba-e093-43dc-9f6c-0e7d50ec95dd"> + <wsu:Created>2023-03-11T13:52:52Z</wsu:Created> + <wsu:Expires>2023-03-11T13:57:52Z</wsu:Expires> + </wsu:Timestamp> + </wsse:Security> + </soap:Header> + <soap:Body> + <RetrieveResponseMsg xmlns="http://exacttarget.com/wsdl/partnerAPI"> + <OverallStatus>OK</OverallStatus> + <RequestID>f4057c93-40e3-47d6-a953-06839e221d40</RequestID> + <Results xsi:type="AccountUserAccount"> + <PartnerKey xsi:nil="true" /> + <ObjectID xsi:nil="true" /> + <AccountUser> + <PartnerKey xsi:nil="true" /> + <ObjectID xsi:nil="true" /> + <AccountUserID>717510285</AccountUserID> + <Delete>0</Delete> + </AccountUser> + <Account> + <PartnerKey xsi:nil="true" /> + <ID>1111111</ID> + <ObjectID xsi:nil="true" /> + <AccountType>None</AccountType> + <Subscription xsi:nil="true" /> + </Account> + </Results> + <Results xsi:type="AccountUserAccount"> + <PartnerKey xsi:nil="true" /> + <ObjectID xsi:nil="true" /> + <AccountUser> + <PartnerKey xsi:nil="true" /> + <ObjectID xsi:nil="true" /> + <AccountUserID>700301950</AccountUserID> + <Delete>0</Delete> + </AccountUser> + <Account> + <PartnerKey xsi:nil="true" /> + <ID>1111111</ID> + <ObjectID xsi:nil="true" /> + <AccountType>None</AccountType> + <Subscription xsi:nil="true" /> + </Account> + </Results> + <Results xsi:type="AccountUserAccount"> + <PartnerKey xsi:nil="true" /> + <ObjectID xsi:nil="true" /> + <AccountUser> + <PartnerKey xsi:nil="true" /> + <ObjectID xsi:nil="true" /> + <AccountUserID>700301950</AccountUserID> + <Delete>0</Delete> + </AccountUser> + <Account> + <PartnerKey xsi:nil="true" /> + <ID>9999999</ID> + <ObjectID xsi:nil="true" /> + <AccountType>None</AccountType> + <Subscription xsi:nil="true" /> + </Account> + </Results> + </RetrieveResponseMsg> + </soap:Body> +</soap:Envelope> \ No newline at end of file diff --git a/test/resources/1111111/automation/v1/queries/get-response.json b/test/resources/1111111/automation/v1/queries/get-response.json new file mode 100644 index 000000000..48f76672e --- /dev/null +++ b/test/resources/1111111/automation/v1/queries/get-response.json @@ -0,0 +1,6 @@ +{ + "count": 0, + "page": 1, + "pageSize": 50, + "items": [] +} diff --git a/test/resources/1111111/automation/v1/queries/post-response.json b/test/resources/1111111/automation/v1/queries/post-response.json new file mode 100644 index 000000000..566d55169 --- /dev/null +++ b/test/resources/1111111/automation/v1/queries/post-response.json @@ -0,0 +1,18 @@ +{ + "queryDefinitionId": "549f0568-607c-4940-afef-437965094d-keySuffix", + "name": "testNew_query", + "key": "testNew_query_DEV", + "description": "created on deploy", + "queryText": "SELECT\n SubscriberKey as testField\nFROM\n _Subscribers\n", + "targetName": "testExisting_dataExtensionShared", + "targetKey": "testExisting_dataExtensionShared", + "targetId": "21711373-72c1-ec11-b83b-shared", + "targetDescription": "", + "createdDate": "2022-04-26T15:21:16.453", + "modifiedDate": "2022-04-26T16:04:15.88", + "targetUpdateTypeId": 0, + "targetUpdateTypeName": "Overwrite", + "validatedQueryText": "SET NOCOUNT ON; SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;\r\n\r\nINSERT INTO C518001158.[testDataExtension] ([testField])\r\nSELECT querydef.[testField]\r\nFROM (SELECT SubscriberKey as testField FROM C518001158._Subscribers ) AS querydef \r\nSELECT @rcInsert = @@ROWCOUNT;;\r\n", + "categoryId": 9991, + "isFrozen": false +} diff --git a/test/resources/1111111/businessUnit/retrieve-ID=1111111-QAA-response.xml b/test/resources/1111111/businessUnit/retrieve-ID=1111111-QAA-response.xml new file mode 100644 index 000000000..e681ce9b6 --- /dev/null +++ b/test/resources/1111111/businessUnit/retrieve-ID=1111111-QAA-response.xml @@ -0,0 +1,33 @@ +<?xml version="1.0" encoding="utf-8"?> +<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:xsd="http://www.w3.org/2001/XMLSchema" + xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing" + xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" + xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"> + <soap:Header> + <wsa:Action>RetrieveResponse</wsa:Action> + <wsa:MessageID>urn:uuid:9e5f98fa-4112-4416-be42-4f9e6f6886e4</wsa:MessageID> + <wsa:RelatesTo>urn:uuid:b94fb623-e37d-40d3-8178-e6c8ee3b40b5</wsa:RelatesTo> + <wsa:To>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</wsa:To> + <wsse:Security> + <wsu:Timestamp wsu:Id="Timestamp-3f974942-511e-4e57-9faa-c89493b836ba"> + <wsu:Created>2022-11-29T19:42:20Z</wsu:Created> + <wsu:Expires>2022-11-29T19:47:20Z</wsu:Expires> + </wsu:Timestamp> + </wsse:Security> + </soap:Header> + <soap:Body> + <RetrieveResponseMsg xmlns="http://exacttarget.com/wsdl/partnerAPI"> + <OverallStatus>OK</OverallStatus> + <RequestID>233a302f-6c1f-4fea-8b32-82a843ae806d</RequestID> + <Results xsi:type="BusinessUnit"> + <PartnerKey xsi:nil="true" /> + <ObjectID xsi:nil="true" /> + <AccountType>None</AccountType> + <Subscription xsi:nil="true" /> + <MasterUnsubscribeBehavior>ENTIRE_ENTERPRISE</MasterUnsubscribeBehavior> + </Results> + </RetrieveResponseMsg> + </soap:Body> +</soap:Envelope> diff --git a/test/resources/1111111/data/v1/customobjectdata/key/testExisting_dataExtensionShared/rowset/get-response.json b/test/resources/1111111/data/v1/customobjectdata/key/testExisting_dataExtensionShared/rowset/get-response.json new file mode 100644 index 000000000..1156309d9 --- /dev/null +++ b/test/resources/1111111/data/v1/customobjectdata/key/testExisting_dataExtensionShared/rowset/get-response.json @@ -0,0 +1,13 @@ +{ + "links": { + "self": "/v1/customobjectdata/token/ea0a44dc-b679-4d7d-8b77-e5d3f106e854/rowset?$page=1" + }, + "requestToken": "ea0a44dc-b679-4d7d-8b77-e5d3f106e854", + "tokenExpireDateUtc": "2023-01-26T13:54:59.883", + "customObjectId": "30400c03-0ec4-ec11-b83c-48df37d1de8b", + "customObjectKey": "testExisting_dataExtensionShared", + "pageSize": 1, + "page": 1, + "count": 0, + "top": 0 +} diff --git a/test/resources/1111111/dataExtension/create-expected.json b/test/resources/1111111/dataExtension/create-expected.json new file mode 100644 index 000000000..9aad7ca07 --- /dev/null +++ b/test/resources/1111111/dataExtension/create-expected.json @@ -0,0 +1,20 @@ +{ + "CustomerKey": "testNew_dataExtensionShared", + "Name": "testNew_dataExtensionShared", + "Description": "", + "IsSendable": false, + "IsTestable": false, + "Fields": [ + { + "DefaultValue": "", + "FieldType": "Text", + "IsPrimaryKey": false, + "IsRequired": true, + "MaxLength": 254, + "Name": "testField" + } + ], + "c__retentionPolicy": "none", + "r__folder_ContentType": "shared_dataextension", + "r__folder_Path": "Shared Items/Shared Data Extensions" +} diff --git a/test/resources/1111111/dataExtension/create-response.xml b/test/resources/1111111/dataExtension/create-response.xml new file mode 100644 index 000000000..207f5ca3c --- /dev/null +++ b/test/resources/1111111/dataExtension/create-response.xml @@ -0,0 +1,59 @@ +<?xml version="1.0" encoding="utf-8"?> +<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:xsd="http://www.w3.org/2001/XMLSchema" + xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing" + xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" + xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"> + <soap:Header> + <wsa:Action>CreateResponse</wsa:Action> + <wsa:MessageID>urn:uuid:3a5f1edf-dacb-4d19-a0d3-4e0dcc9f507d</wsa:MessageID> + <wsa:RelatesTo>urn:uuid:fb395987-bf45-42d6-af73-f51816c7b73f</wsa:RelatesTo> + <wsa:To>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</wsa:To> + <wsse:Security> + <wsu:Timestamp wsu:Id="Timestamp-b5d88471-97ad-4070-a18f-4c148a52da96"> + <wsu:Created>2022-04-24T20:35:10Z</wsu:Created> + <wsu:Expires>2022-04-24T20:40:10Z</wsu:Expires> + </wsu:Timestamp> + </wsse:Security> + </soap:Header> + <soap:Body> + <CreateResponse xmlns="http://exacttarget.com/wsdl/partnerAPI"> + <Results> + <StatusCode>OK</StatusCode> + <StatusMessage>Data Extension created.</StatusMessage> + <OrdinalID>0</OrdinalID> + <NewID>0</NewID> + <NewObjectID>shared-0ec4-ec11-b83c-48df37d1de8a</NewObjectID> + <Object xsi:type="DataExtension"> + <PartnerKey xsi:nil="true" /> + <ObjectID>shared-0ec4-ec11-b83c-48df37d1de8a</ObjectID> + <CustomerKey>testNew_dataExtensionShared</CustomerKey> + <Name>testNew_dataExtensionShared</Name> + <Description /> + <IsSendable>false</IsSendable> + <IsTestable>false</IsTestable> + <RowBasedRetention>false</RowBasedRetention> + <ResetRetentionPeriodOnImport>false</ResetRetentionPeriodOnImport> + <DeleteAtEndOfRetentionPeriod>false</DeleteAtEndOfRetentionPeriod> + <RetainUntil /> + <Fields> + <Field> + <PartnerKey xsi:nil="true" /> + <ObjectID xsi:nil="true" /> + <Name>testField</Name> + <DefaultValue /> + <MaxLength>254</MaxLength> + <IsRequired>true</IsRequired> + <IsPrimaryKey>false</IsPrimaryKey> + <FieldType>Text</FieldType> + </Field> + </Fields> + <CategoryID>89356</CategoryID> + </Object> + </Results> + <RequestID>c41aa55a-90e3-4021-9f82-103796aae6da</RequestID> + <OverallStatus>OK</OverallStatus> + </CreateResponse> + </soap:Body> +</soap:Envelope> diff --git a/test/resources/1111111/dataExtension/retrieve-expected.json b/test/resources/1111111/dataExtension/retrieve-expected.json new file mode 100644 index 000000000..d15755909 --- /dev/null +++ b/test/resources/1111111/dataExtension/retrieve-expected.json @@ -0,0 +1,53 @@ +{ + "CustomerKey": "testExisting_dataExtensionShared", + "DataRetentionPeriodLength": 6, + "Description": "bla bla", + "Fields": [ + { + "DefaultValue": "", + "FieldType": "Text", + "IsPrimaryKey": false, + "IsRequired": false, + "MaxLength": 50, + "Name": "FirstName" + }, + { + "DefaultValue": "", + "FieldType": "Text", + "IsPrimaryKey": false, + "IsRequired": false, + "MaxLength": 50, + "Name": "LastName" + }, + { + "DefaultValue": "", + "FieldType": "EmailAddress", + "IsPrimaryKey": false, + "IsRequired": true, + "MaxLength": 254, + "Name": "EmailAddress" + }, + { + "DefaultValue": "", + "FieldType": "Text", + "IsPrimaryKey": true, + "IsRequired": true, + "MaxLength": 50, + "Name": "ContactKey" + } + ], + "IsSendable": true, + "IsTestable": true, + "Name": "testExisting_dataExtensionShared", + "ResetRetentionPeriodOnImport": false, + "SendableDataExtensionField": { + "Name": "ContactKey" + }, + "SendableSubscriberField": { + "Name": "Subscriber Key" + }, + "c__dataRetentionPeriodUnitOfMeasure": "Months", + "c__retentionPolicy": "individialRecords", + "r__folder_ContentType": "shared_dataextension", + "r__folder_Path": "Shared Items/Shared Data Extensions" +} diff --git a/test/resources/1111111/dataExtension/retrieve-expected.md b/test/resources/1111111/dataExtension/retrieve-expected.md new file mode 100644 index 000000000..5fe654993 --- /dev/null +++ b/test/resources/1111111/dataExtension/retrieve-expected.md @@ -0,0 +1,23 @@ +## testExisting_dataExtensionShared + +**Description:** bla bla + +**Folder:** Shared Items/Shared Data Extensions/ + +**Fields in table:** 4 + +**Sendable:** Yes (`ContactKey` to `Subscriber Key`) + +**Testable:** Yes + +**Retention Policy:** individialRecords + +- **Retention Period:** 6 Months +- **Reset Retention Period on import:** no + +| Name | FieldType | MaxLength | IsPrimaryKey | IsNullable | DefaultValue | +| --- | --- | --- | --- | --- | --- | +| FirstName | Text | 50 | - | + | | +| LastName | Text | 50 | - | + | | +| EmailAddress | EmailAddress | 254 | - | - | | +| ContactKey | Text | 50 | + | - | | diff --git a/test/resources/1111111/dataExtension/retrieve-response.xml b/test/resources/1111111/dataExtension/retrieve-response.xml new file mode 100644 index 000000000..cad82d0b3 --- /dev/null +++ b/test/resources/1111111/dataExtension/retrieve-response.xml @@ -0,0 +1,52 @@ +<?xml version="1.0" encoding="utf-8"?> +<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:xsd="http://www.w3.org/2001/XMLSchema" + xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing" + xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" + xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"> + <soap:Header> + <wsa:Action>RetrieveResponse</wsa:Action> + <wsa:MessageID>urn:uuid:c198cc12-c34c-4d1d-90b0-5b785a342efc</wsa:MessageID> + <wsa:RelatesTo>urn:uuid:a0506b59-1847-4405-8231-6a15e26bbcc9</wsa:RelatesTo> + <wsa:To>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</wsa:To> + <wsse:Security> + <wsu:Timestamp wsu:Id="Timestamp-52fe9187-6f22-4701-bd57-d0eaa4aef215"> + <wsu:Created>2022-04-21T19:21:50Z</wsu:Created> + <wsu:Expires>2022-04-21T19:26:50Z</wsu:Expires> + </wsu:Timestamp> + </wsse:Security> + </soap:Header> + <soap:Body> + <RetrieveResponseMsg xmlns="http://exacttarget.com/wsdl/partnerAPI"> + <OverallStatus>OK</OverallStatus> + <RequestID>d175de6e-c8e4-4f5d-9c1d-ad64426ff4b7</RequestID> + <Results xsi:type="DataExtension"> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2022-04-21T06:56:27.927</CreatedDate> + <ModifiedDate>2022-04-21T06:56:27.927</ModifiedDate> + <ObjectID>21711373-72c1-ec11-b83b-shared</ObjectID> + <CustomerKey>testExisting_dataExtensionShared</CustomerKey> + <Name>testExisting_dataExtensionShared</Name> + <Description>bla bla</Description> + <IsSendable>true</IsSendable> + <IsTestable>true</IsTestable> + <SendableDataExtensionField> + <PartnerKey xsi:nil="true" /> + <ObjectID xsi:nil="true" /> + <Name>ContactKey</Name> + </SendableDataExtensionField> + <SendableSubscriberField> + <Name>_SubscriberKey</Name> + </SendableSubscriberField> + <DataRetentionPeriodLength>6</DataRetentionPeriodLength> + <DataRetentionPeriodUnitOfMeasure>5</DataRetentionPeriodUnitOfMeasure> + <RowBasedRetention>true</RowBasedRetention> + <ResetRetentionPeriodOnImport>false</ResetRetentionPeriodOnImport> + <DeleteAtEndOfRetentionPeriod>false</DeleteAtEndOfRetentionPeriod> + <RetainUntil /> + <CategoryID>89356</CategoryID> + </Results> + </RetrieveResponseMsg> + </soap:Body> +</soap:Envelope> diff --git a/test/resources/1111111/dataExtension/update-expected.json b/test/resources/1111111/dataExtension/update-expected.json new file mode 100644 index 000000000..5192beebb --- /dev/null +++ b/test/resources/1111111/dataExtension/update-expected.json @@ -0,0 +1,55 @@ +{ + "CustomerKey": "testExisting_dataExtensionShared", + "Name": "testExisting_dataExtensionShared", + "Description": "Container for my test emails", + "IsSendable": false, + "IsTestable": false, + "DataRetentionPeriodLength": 6, + "ResetRetentionPeriodOnImport": false, + "Fields": [ + { + "DefaultValue": "", + "FieldType": "Text", + "IsPrimaryKey": false, + "IsRequired": false, + "MaxLength": 50, + "Name": "FirstName" + }, + { + "DefaultValue": "", + "FieldType": "Text", + "IsPrimaryKey": false, + "IsRequired": false, + "MaxLength": 55, + "Name": "LastName" + }, + { + "DefaultValue": "", + "FieldType": "EmailAddress", + "IsPrimaryKey": false, + "IsRequired": true, + "MaxLength": 254, + "Name": "EmailAddress" + }, + { + "DefaultValue": "", + "FieldType": "Text", + "IsPrimaryKey": true, + "IsRequired": true, + "MaxLength": 50, + "Name": "ContactKey" + }, + { + "DefaultValue": "", + "FieldType": "Text", + "IsPrimaryKey": false, + "IsRequired": false, + "MaxLength": 254, + "Name": "newField" + } + ], + "c__dataRetentionPeriodUnitOfMeasure": "Months", + "c__retentionPolicy": "allRecords", + "r__folder_ContentType": "shared_dataextension", + "r__folder_Path": "Shared Items/Shared Data Extensions" +} diff --git a/test/resources/1111111/dataExtension/update-response.xml b/test/resources/1111111/dataExtension/update-response.xml new file mode 100644 index 000000000..7016a65db --- /dev/null +++ b/test/resources/1111111/dataExtension/update-response.xml @@ -0,0 +1,59 @@ +<?xml version="1.0" encoding="utf-8"?> +<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:xsd="http://www.w3.org/2001/XMLSchema" + xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing" + xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" + xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"> + <soap:Header> + <wsa:Action>UpdateResponse</wsa:Action> + <wsa:MessageID>urn:uuid:994e213d-1125-450d-b187-32e3870147d1</wsa:MessageID> + <wsa:RelatesTo>urn:uuid:f1fc86ef-c0c8-4c17-a901-a15fc2631f76</wsa:RelatesTo> + <wsa:To>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</wsa:To> + <wsse:Security> + <wsu:Timestamp wsu:Id="Timestamp-88cf0bce-bf0f-4d5f-90a6-2897708181b5"> + <wsu:Created>2022-04-26T20:49:03Z</wsu:Created> + <wsu:Expires>2022-04-26T20:54:03Z</wsu:Expires> + </wsu:Timestamp> + </wsse:Security> + </soap:Header> + <soap:Body> + <UpdateResponse xmlns="http://exacttarget.com/wsdl/partnerAPI"> + <Results> + <StatusCode>OK</StatusCode> + <StatusMessage>Data Extension updated.</StatusMessage> + <OrdinalID>0</OrdinalID> + <Object xsi:type="DataExtension"> + <PartnerKey xsi:nil="true" /> + <ObjectID>21711373-72c1-ec11-b83b-shared</ObjectID> + <CustomerKey>testExisting_dataExtensionShared</CustomerKey> + <Name>testExisting_dataExtensionShared</Name> + <Description>Container for my test emails</Description> + <IsSendable>false</IsSendable> + <IsTestable>false</IsTestable> + <DataRetentionPeriodLength>6</DataRetentionPeriodLength> + <DataRetentionPeriodUnitOfMeasure>5</DataRetentionPeriodUnitOfMeasure> + <RowBasedRetention>false</RowBasedRetention> + <ResetRetentionPeriodOnImport>false</ResetRetentionPeriodOnImport> + <DeleteAtEndOfRetentionPeriod>true</DeleteAtEndOfRetentionPeriod> + <RetainUntil /> + <Fields> + <Field> + <PartnerKey xsi:nil="true" /> + <ObjectID xsi:nil="true" /> + <Name>testField</Name> + <DefaultValue /> + <MaxLength>254</MaxLength> + <IsRequired>true</IsRequired> + <IsPrimaryKey>false</IsPrimaryKey> + <FieldType>Text</FieldType> + </Field> + </Fields> + <CategoryID>89356</CategoryID> + </Object> + </Results> + <RequestID>dbfedcb6-a809-4101-b314-a7b920c9fb1e</RequestID> + <OverallStatus>OK</OverallStatus> + </UpdateResponse> + </soap:Body> +</soap:Envelope> diff --git a/test/resources/1111111/dataExtensionField/retrieve-CustomerKey=[testExisting_dataExtensionShared].[TriggerUpdate_randomNumber_]-response.xml b/test/resources/1111111/dataExtensionField/retrieve-CustomerKey=[testExisting_dataExtensionShared].[TriggerUpdate_randomNumber_]-response.xml new file mode 100644 index 000000000..ddb2cff52 --- /dev/null +++ b/test/resources/1111111/dataExtensionField/retrieve-CustomerKey=[testExisting_dataExtensionShared].[TriggerUpdate_randomNumber_]-response.xml @@ -0,0 +1,45 @@ +<?xml version="1.0" encoding="utf-8"?> +<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:xsd="http://www.w3.org/2001/XMLSchema" + xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing" + xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" + xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"> + <soap:Header> + <wsa:Action>RetrieveResponse</wsa:Action> + <wsa:MessageID>urn:uuid:6d2f81c8-80ab-44d5-8664-206753e7ac8d</wsa:MessageID> + <wsa:RelatesTo>urn:uuid:a7354389-079e-4844-93b5-af6b7bf1d535</wsa:RelatesTo> + <wsa:To>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</wsa:To> + <wsse:Security> + <wsu:Timestamp wsu:Id="Timestamp-468a08b7-c8fd-44bf-a2c8-fd6063127ca6"> + <wsu:Created>2022-04-21T19:21:52Z</wsu:Created> + <wsu:Expires>2022-04-21T19:26:52Z</wsu:Expires> + </wsu:Timestamp> + </wsse:Security> + </soap:Header> + <soap:Body> + <RetrieveResponseMsg xmlns="http://exacttarget.com/wsdl/partnerAPI"> + <OverallStatus>OK</OverallStatus> + <RequestID>cfe51e71-6a2b-4cb4-aecd-3777076d63bc</RequestID> + <Results xsi:type="DataExtensionField"> + <PartnerKey xsi:nil="true" /> + <ObjectID>TriggerUpdate-8018397d-880d-4f88-940e-3b4eca098a0c</ObjectID> + <CustomerKey>[testExisting_dataExtensionShared].[TriggerUpdate_randomNumber_]</CustomerKey> + <Name>TriggerUpdate_randomNumber_</Name> + <Scale>0</Scale> + <DefaultValue /> + <MaxLength>50</MaxLength> + <IsRequired>true</IsRequired> + <Ordinal>3</Ordinal> + <IsPrimaryKey>true</IsPrimaryKey> + <FieldType>Text</FieldType> + <DataExtension> + <PartnerKey xsi:nil="true" /> + <ObjectID xsi:nil="true" /> + <CustomerKey>testExisting_dataExtensionShared</CustomerKey> + </DataExtension> + </Results> + + </RetrieveResponseMsg> + </soap:Body> +</soap:Envelope> diff --git a/test/resources/1111111/dataExtensionField/retrieve-DataExtension.CustomerKey=testExisting_dataExtensionShared-response.xml b/test/resources/1111111/dataExtensionField/retrieve-DataExtension.CustomerKey=testExisting_dataExtensionShared-response.xml new file mode 100644 index 000000000..c3810d2ca --- /dev/null +++ b/test/resources/1111111/dataExtensionField/retrieve-DataExtension.CustomerKey=testExisting_dataExtensionShared-response.xml @@ -0,0 +1,98 @@ +<?xml version="1.0" encoding="utf-8"?> +<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:xsd="http://www.w3.org/2001/XMLSchema" + xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing" + xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" + xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"> + <soap:Header> + <wsa:Action>RetrieveResponse</wsa:Action> + <wsa:MessageID>urn:uuid:6d2f81c8-80ab-44d5-8664-206753e7ac8d</wsa:MessageID> + <wsa:RelatesTo>urn:uuid:a7354389-079e-4844-93b5-af6b7bf1d535</wsa:RelatesTo> + <wsa:To>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</wsa:To> + <wsse:Security> + <wsu:Timestamp wsu:Id="Timestamp-468a08b7-c8fd-44bf-a2c8-fd6063127ca6"> + <wsu:Created>2022-04-21T19:21:52Z</wsu:Created> + <wsu:Expires>2022-04-21T19:26:52Z</wsu:Expires> + </wsu:Timestamp> + </wsse:Security> + </soap:Header> + <soap:Body> + <RetrieveResponseMsg xmlns="http://exacttarget.com/wsdl/partnerAPI"> + <OverallStatus>OK</OverallStatus> + <RequestID>cfe51e71-6a2b-4cb4-aecd-3777076d63bc</RequestID> + <Results xsi:type="DataExtensionField"> + <PartnerKey xsi:nil="true" /> + <ObjectID>shared-8018397d-880d-4f88-940e-3b4eca098a0c</ObjectID> + <CustomerKey>[testExisting_dataExtensionShared].[ContactKey]</CustomerKey> + <Name>ContactKey</Name> + <Scale>0</Scale> + <DefaultValue /> + <MaxLength>50</MaxLength> + <IsRequired>true</IsRequired> + <Ordinal>3</Ordinal> + <IsPrimaryKey>true</IsPrimaryKey> + <FieldType>Text</FieldType> + <DataExtension> + <PartnerKey xsi:nil="true" /> + <ObjectID xsi:nil="true" /> + <CustomerKey>testExisting_dataExtensionShared</CustomerKey> + </DataExtension> + </Results> + <Results xsi:type="DataExtensionField"> + <PartnerKey xsi:nil="true" /> + <ObjectID>shared-bea0e308-5d45-4181-a673-da9972a7c674</ObjectID> + <CustomerKey>[testExisting_dataExtensionShared].[LastName]</CustomerKey> + <Name>LastName</Name> + <Scale>0</Scale> + <DefaultValue /> + <MaxLength>50</MaxLength> + <IsRequired>false</IsRequired> + <Ordinal>1</Ordinal> + <IsPrimaryKey>false</IsPrimaryKey> + <FieldType>Text</FieldType> + <DataExtension> + <PartnerKey xsi:nil="true" /> + <ObjectID xsi:nil="true" /> + <CustomerKey>testExisting_dataExtensionShared</CustomerKey> + </DataExtension> + </Results> + <Results xsi:type="DataExtensionField"> + <PartnerKey xsi:nil="true" /> + <ObjectID>shared-2557b461-a699-4744-950d-e80a19afc2dc</ObjectID> + <CustomerKey>[testExisting_dataExtensionShared].[EmailAddress]</CustomerKey> + <Name>EmailAddress</Name> + <Scale>0</Scale> + <DefaultValue /> + <MaxLength>254</MaxLength> + <IsRequired>true</IsRequired> + <Ordinal>2</Ordinal> + <IsPrimaryKey>false</IsPrimaryKey> + <FieldType>EmailAddress</FieldType> + <DataExtension> + <PartnerKey xsi:nil="true" /> + <ObjectID xsi:nil="true" /> + <CustomerKey>testExisting_dataExtensionShared</CustomerKey> + </DataExtension> + </Results> + <Results xsi:type="DataExtensionField"> + <PartnerKey xsi:nil="true" /> + <ObjectID>shared-42760528-a8c5-44dd-8c1d-ff34e5daee54</ObjectID> + <CustomerKey>[testExisting_dataExtensionShared].[FirstName]</CustomerKey> + <Name>FirstName</Name> + <Scale>0</Scale> + <DefaultValue /> + <MaxLength>50</MaxLength> + <IsRequired>false</IsRequired> + <Ordinal>0</Ordinal> + <IsPrimaryKey>false</IsPrimaryKey> + <FieldType>Text</FieldType> + <DataExtension> + <PartnerKey xsi:nil="true" /> + <ObjectID xsi:nil="true" /> + <CustomerKey>testExisting_dataExtensionShared</CustomerKey> + </DataExtension> + </Results> + </RetrieveResponseMsg> + </soap:Body> +</soap:Envelope> diff --git a/test/resources/1111111/dataExtensionField/retrieve-DataExtension.CustomerKey=testNew_dataExtensionSharedORDataExtension.CustomerKey=testExisting_dataExtensionShared-response.xml b/test/resources/1111111/dataExtensionField/retrieve-DataExtension.CustomerKey=testNew_dataExtensionSharedORDataExtension.CustomerKey=testExisting_dataExtensionShared-response.xml new file mode 100644 index 000000000..c3810d2ca --- /dev/null +++ b/test/resources/1111111/dataExtensionField/retrieve-DataExtension.CustomerKey=testNew_dataExtensionSharedORDataExtension.CustomerKey=testExisting_dataExtensionShared-response.xml @@ -0,0 +1,98 @@ +<?xml version="1.0" encoding="utf-8"?> +<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:xsd="http://www.w3.org/2001/XMLSchema" + xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing" + xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" + xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"> + <soap:Header> + <wsa:Action>RetrieveResponse</wsa:Action> + <wsa:MessageID>urn:uuid:6d2f81c8-80ab-44d5-8664-206753e7ac8d</wsa:MessageID> + <wsa:RelatesTo>urn:uuid:a7354389-079e-4844-93b5-af6b7bf1d535</wsa:RelatesTo> + <wsa:To>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</wsa:To> + <wsse:Security> + <wsu:Timestamp wsu:Id="Timestamp-468a08b7-c8fd-44bf-a2c8-fd6063127ca6"> + <wsu:Created>2022-04-21T19:21:52Z</wsu:Created> + <wsu:Expires>2022-04-21T19:26:52Z</wsu:Expires> + </wsu:Timestamp> + </wsse:Security> + </soap:Header> + <soap:Body> + <RetrieveResponseMsg xmlns="http://exacttarget.com/wsdl/partnerAPI"> + <OverallStatus>OK</OverallStatus> + <RequestID>cfe51e71-6a2b-4cb4-aecd-3777076d63bc</RequestID> + <Results xsi:type="DataExtensionField"> + <PartnerKey xsi:nil="true" /> + <ObjectID>shared-8018397d-880d-4f88-940e-3b4eca098a0c</ObjectID> + <CustomerKey>[testExisting_dataExtensionShared].[ContactKey]</CustomerKey> + <Name>ContactKey</Name> + <Scale>0</Scale> + <DefaultValue /> + <MaxLength>50</MaxLength> + <IsRequired>true</IsRequired> + <Ordinal>3</Ordinal> + <IsPrimaryKey>true</IsPrimaryKey> + <FieldType>Text</FieldType> + <DataExtension> + <PartnerKey xsi:nil="true" /> + <ObjectID xsi:nil="true" /> + <CustomerKey>testExisting_dataExtensionShared</CustomerKey> + </DataExtension> + </Results> + <Results xsi:type="DataExtensionField"> + <PartnerKey xsi:nil="true" /> + <ObjectID>shared-bea0e308-5d45-4181-a673-da9972a7c674</ObjectID> + <CustomerKey>[testExisting_dataExtensionShared].[LastName]</CustomerKey> + <Name>LastName</Name> + <Scale>0</Scale> + <DefaultValue /> + <MaxLength>50</MaxLength> + <IsRequired>false</IsRequired> + <Ordinal>1</Ordinal> + <IsPrimaryKey>false</IsPrimaryKey> + <FieldType>Text</FieldType> + <DataExtension> + <PartnerKey xsi:nil="true" /> + <ObjectID xsi:nil="true" /> + <CustomerKey>testExisting_dataExtensionShared</CustomerKey> + </DataExtension> + </Results> + <Results xsi:type="DataExtensionField"> + <PartnerKey xsi:nil="true" /> + <ObjectID>shared-2557b461-a699-4744-950d-e80a19afc2dc</ObjectID> + <CustomerKey>[testExisting_dataExtensionShared].[EmailAddress]</CustomerKey> + <Name>EmailAddress</Name> + <Scale>0</Scale> + <DefaultValue /> + <MaxLength>254</MaxLength> + <IsRequired>true</IsRequired> + <Ordinal>2</Ordinal> + <IsPrimaryKey>false</IsPrimaryKey> + <FieldType>EmailAddress</FieldType> + <DataExtension> + <PartnerKey xsi:nil="true" /> + <ObjectID xsi:nil="true" /> + <CustomerKey>testExisting_dataExtensionShared</CustomerKey> + </DataExtension> + </Results> + <Results xsi:type="DataExtensionField"> + <PartnerKey xsi:nil="true" /> + <ObjectID>shared-42760528-a8c5-44dd-8c1d-ff34e5daee54</ObjectID> + <CustomerKey>[testExisting_dataExtensionShared].[FirstName]</CustomerKey> + <Name>FirstName</Name> + <Scale>0</Scale> + <DefaultValue /> + <MaxLength>50</MaxLength> + <IsRequired>false</IsRequired> + <Ordinal>0</Ordinal> + <IsPrimaryKey>false</IsPrimaryKey> + <FieldType>Text</FieldType> + <DataExtension> + <PartnerKey xsi:nil="true" /> + <ObjectID xsi:nil="true" /> + <CustomerKey>testExisting_dataExtensionShared</CustomerKey> + </DataExtension> + </Results> + </RetrieveResponseMsg> + </soap:Body> +</soap:Envelope> diff --git a/test/resources/1111111/dataExtensionField/retrieve-response.xml b/test/resources/1111111/dataExtensionField/retrieve-response.xml new file mode 100644 index 000000000..c3810d2ca --- /dev/null +++ b/test/resources/1111111/dataExtensionField/retrieve-response.xml @@ -0,0 +1,98 @@ +<?xml version="1.0" encoding="utf-8"?> +<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:xsd="http://www.w3.org/2001/XMLSchema" + xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing" + xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" + xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"> + <soap:Header> + <wsa:Action>RetrieveResponse</wsa:Action> + <wsa:MessageID>urn:uuid:6d2f81c8-80ab-44d5-8664-206753e7ac8d</wsa:MessageID> + <wsa:RelatesTo>urn:uuid:a7354389-079e-4844-93b5-af6b7bf1d535</wsa:RelatesTo> + <wsa:To>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</wsa:To> + <wsse:Security> + <wsu:Timestamp wsu:Id="Timestamp-468a08b7-c8fd-44bf-a2c8-fd6063127ca6"> + <wsu:Created>2022-04-21T19:21:52Z</wsu:Created> + <wsu:Expires>2022-04-21T19:26:52Z</wsu:Expires> + </wsu:Timestamp> + </wsse:Security> + </soap:Header> + <soap:Body> + <RetrieveResponseMsg xmlns="http://exacttarget.com/wsdl/partnerAPI"> + <OverallStatus>OK</OverallStatus> + <RequestID>cfe51e71-6a2b-4cb4-aecd-3777076d63bc</RequestID> + <Results xsi:type="DataExtensionField"> + <PartnerKey xsi:nil="true" /> + <ObjectID>shared-8018397d-880d-4f88-940e-3b4eca098a0c</ObjectID> + <CustomerKey>[testExisting_dataExtensionShared].[ContactKey]</CustomerKey> + <Name>ContactKey</Name> + <Scale>0</Scale> + <DefaultValue /> + <MaxLength>50</MaxLength> + <IsRequired>true</IsRequired> + <Ordinal>3</Ordinal> + <IsPrimaryKey>true</IsPrimaryKey> + <FieldType>Text</FieldType> + <DataExtension> + <PartnerKey xsi:nil="true" /> + <ObjectID xsi:nil="true" /> + <CustomerKey>testExisting_dataExtensionShared</CustomerKey> + </DataExtension> + </Results> + <Results xsi:type="DataExtensionField"> + <PartnerKey xsi:nil="true" /> + <ObjectID>shared-bea0e308-5d45-4181-a673-da9972a7c674</ObjectID> + <CustomerKey>[testExisting_dataExtensionShared].[LastName]</CustomerKey> + <Name>LastName</Name> + <Scale>0</Scale> + <DefaultValue /> + <MaxLength>50</MaxLength> + <IsRequired>false</IsRequired> + <Ordinal>1</Ordinal> + <IsPrimaryKey>false</IsPrimaryKey> + <FieldType>Text</FieldType> + <DataExtension> + <PartnerKey xsi:nil="true" /> + <ObjectID xsi:nil="true" /> + <CustomerKey>testExisting_dataExtensionShared</CustomerKey> + </DataExtension> + </Results> + <Results xsi:type="DataExtensionField"> + <PartnerKey xsi:nil="true" /> + <ObjectID>shared-2557b461-a699-4744-950d-e80a19afc2dc</ObjectID> + <CustomerKey>[testExisting_dataExtensionShared].[EmailAddress]</CustomerKey> + <Name>EmailAddress</Name> + <Scale>0</Scale> + <DefaultValue /> + <MaxLength>254</MaxLength> + <IsRequired>true</IsRequired> + <Ordinal>2</Ordinal> + <IsPrimaryKey>false</IsPrimaryKey> + <FieldType>EmailAddress</FieldType> + <DataExtension> + <PartnerKey xsi:nil="true" /> + <ObjectID xsi:nil="true" /> + <CustomerKey>testExisting_dataExtensionShared</CustomerKey> + </DataExtension> + </Results> + <Results xsi:type="DataExtensionField"> + <PartnerKey xsi:nil="true" /> + <ObjectID>shared-42760528-a8c5-44dd-8c1d-ff34e5daee54</ObjectID> + <CustomerKey>[testExisting_dataExtensionShared].[FirstName]</CustomerKey> + <Name>FirstName</Name> + <Scale>0</Scale> + <DefaultValue /> + <MaxLength>50</MaxLength> + <IsRequired>false</IsRequired> + <Ordinal>0</Ordinal> + <IsPrimaryKey>false</IsPrimaryKey> + <FieldType>Text</FieldType> + <DataExtension> + <PartnerKey xsi:nil="true" /> + <ObjectID xsi:nil="true" /> + <CustomerKey>testExisting_dataExtensionShared</CustomerKey> + </DataExtension> + </Results> + </RetrieveResponseMsg> + </soap:Body> +</soap:Envelope> diff --git a/test/resources/1111111/dataExtensionTemplate/retrieve-response.xml b/test/resources/1111111/dataExtensionTemplate/retrieve-response.xml new file mode 100644 index 000000000..31b41f0b5 --- /dev/null +++ b/test/resources/1111111/dataExtensionTemplate/retrieve-response.xml @@ -0,0 +1,303 @@ +<?xml version="1.0" encoding="utf-8"?> +<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing" xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"> + <soap:Header> + <wsa:Action>RetrieveResponse</wsa:Action> + <wsa:MessageID>urn:uuid:110bbc72-d639-4e67-ab93-68e081bcf3a0</wsa:MessageID> + <wsa:RelatesTo>urn:uuid:753eed05-f925-4113-8a98-e81ca69c96fd</wsa:RelatesTo> + <wsa:To>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</wsa:To> + <wsse:Security> + <wsu:Timestamp wsu:Id="Timestamp-a81724ab-b6f6-4825-82e8-ec523642075e"> + <wsu:Created>2022-04-21T19:21:49Z</wsu:Created> + <wsu:Expires>2022-04-21T19:26:49Z</wsu:Expires> + </wsu:Timestamp> + </wsse:Security> + </soap:Header> + <soap:Body> + <RetrieveResponseMsg xmlns="http://exacttarget.com/wsdl/partnerAPI"> + <OverallStatus>OK</OverallStatus> + <RequestID>82fd5f74-ad8c-49ad-958f-867d4a4b53b0</RequestID> + <Results xsi:type="DataExtensionTemplate"> + <PartnerKey xsi:nil="true" /> + <PartnerProperties> + <Name>IsSendable</Name> + <Value>False</Value> + </PartnerProperties> + <PartnerProperties> + <Name>IsTestable</Name> + <Value>False</Value> + </PartnerProperties> + <PartnerProperties> + <Name>SendableCustomObjectField</Name> + <Value /> + </PartnerProperties> + <PartnerProperties> + <Name>SendableSubscriberField</Name> + <Value /> + </PartnerProperties> + <PartnerProperties> + <Name>DataRetentionPeriodLength</Name> + <Value /> + </PartnerProperties> + <PartnerProperties> + <Name>DataRetentionPeriodUnitOfMeasure</Name> + <Value /> + </PartnerProperties> + <PartnerProperties> + <Name>RowBasedRetention</Name> + <Value>False</Value> + </PartnerProperties> + <PartnerProperties> + <Name>ResetRetentionPeriodOnImport</Name> + <Value>False</Value> + </PartnerProperties> + <PartnerProperties> + <Name>DeleteAtEndOfRetentionPeriod</Name> + <Value>False</Value> + </PartnerProperties> + <PartnerProperties> + <Name>RetainUntil</Name> + <Value /> + </PartnerProperties> + <ObjectID>cfd6fc95-d594-ea11-a2e6-1402ec938a35</ObjectID> + <CustomerKey>086D14D3-5057-462B-AF33-01CA8D1FE87A</CustomerKey> + <Name>DomainExclusion</Name> + <Description>Domain Exclusion Data Extension Template</Description> + </Results> + <Results xsi:type="DataExtensionTemplate"> + <PartnerKey xsi:nil="true" /> + <PartnerProperties> + <Name>IsSendable</Name> + <Value>True</Value> + </PartnerProperties> + <PartnerProperties> + <Name>IsTestable</Name> + <Value>False</Value> + </PartnerProperties> + <PartnerProperties> + <Name>SendableCustomObjectField</Name> + <Value>SubscriberKey</Value> + </PartnerProperties> + <PartnerProperties> + <Name>SendableSubscriberField</Name> + <Value>_SubscriberKey</Value> + </PartnerProperties> + <PartnerProperties> + <Name>DataRetentionPeriodLength</Name> + <Value /> + </PartnerProperties> + <PartnerProperties> + <Name>DataRetentionPeriodUnitOfMeasure</Name> + <Value /> + </PartnerProperties> + <PartnerProperties> + <Name>RowBasedRetention</Name> + <Value>False</Value> + </PartnerProperties> + <PartnerProperties> + <Name>ResetRetentionPeriodOnImport</Name> + <Value>False</Value> + </PartnerProperties> + <PartnerProperties> + <Name>DeleteAtEndOfRetentionPeriod</Name> + <Value>False</Value> + </PartnerProperties> + <PartnerProperties> + <Name>RetainUntil</Name> + <Value /> + </PartnerProperties> + <ObjectID>1fd7fc95-d594-ea11-a2e6-1402ec938a35</ObjectID> + <CustomerKey>B6E8AE4C-3D93-49B1-B299-E0AE734213DD</CustomerKey> + <Name>TriggeredSendDataExtension</Name> + <Description>Triggered Send Source Data Extension Template</Description> + </Results> + <Results xsi:type="DataExtensionTemplate"> + <PartnerKey xsi:nil="true" /> + <PartnerProperties> + <Name>IsSendable</Name> + <Value>True</Value> + </PartnerProperties> + <PartnerProperties> + <Name>IsTestable</Name> + <Value>False</Value> + </PartnerProperties> + <PartnerProperties> + <Name>SendableCustomObjectField</Name> + <Value>Email Address</Value> + </PartnerProperties> + <PartnerProperties> + <Name>SendableSubscriberField</Name> + <Value>_EmailAddress</Value> + </PartnerProperties> + <PartnerProperties> + <Name>DataRetentionPeriodLength</Name> + <Value /> + </PartnerProperties> + <PartnerProperties> + <Name>DataRetentionPeriodUnitOfMeasure</Name> + <Value /> + </PartnerProperties> + <PartnerProperties> + <Name>RowBasedRetention</Name> + <Value>False</Value> + </PartnerProperties> + <PartnerProperties> + <Name>ResetRetentionPeriodOnImport</Name> + <Value>False</Value> + </PartnerProperties> + <PartnerProperties> + <Name>DeleteAtEndOfRetentionPeriod</Name> + <Value>False</Value> + </PartnerProperties> + <PartnerProperties> + <Name>RetainUntil</Name> + <Value /> + </PartnerProperties> + <ObjectID>bb1df59b-d594-ea11-a2e6-1402ec938a35</ObjectID> + <CustomerKey>23471ECA-8710-4512-9296-040CA86FBD9E</CustomerKey> + <Name>CONTEXTUAL_SUPPRESSION_LISTS</Name> + <Description>Used to create new auto-suppression lists</Description> + </Results> + <Results xsi:type="DataExtensionTemplate"> + <PartnerKey xsi:nil="true" /> + <PartnerProperties> + <Name>IsSendable</Name> + <Value>True</Value> + </PartnerProperties> + <PartnerProperties> + <Name>IsTestable</Name> + <Value>False</Value> + </PartnerProperties> + <PartnerProperties> + <Name>SendableCustomObjectField</Name> + <Value>EmailAddress</Value> + </PartnerProperties> + <PartnerProperties> + <Name>SendableSubscriberField</Name> + <Value>_SubscriberKey</Value> + </PartnerProperties> + <PartnerProperties> + <Name>DataRetentionPeriodLength</Name> + <Value /> + </PartnerProperties> + <PartnerProperties> + <Name>DataRetentionPeriodUnitOfMeasure</Name> + <Value /> + </PartnerProperties> + <PartnerProperties> + <Name>RowBasedRetention</Name> + <Value>False</Value> + </PartnerProperties> + <PartnerProperties> + <Name>ResetRetentionPeriodOnImport</Name> + <Value>False</Value> + </PartnerProperties> + <PartnerProperties> + <Name>DeleteAtEndOfRetentionPeriod</Name> + <Value>False</Value> + </PartnerProperties> + <PartnerProperties> + <Name>RetainUntil</Name> + <Value /> + </PartnerProperties> + <ObjectID>e61df59b-d594-ea11-a2e6-1402ec938a35</ObjectID> + <CustomerKey>00A4369E-0B57-4EF2-BFFA-E3F23B4D1098</CustomerKey> + <Name>SocialPages Default Template Extension</Name> + <Description>Required for contacts. Used by Smart Capture for Social Pages.</Description> + </Results> + <Results xsi:type="DataExtensionTemplate"> + <PartnerKey xsi:nil="true" /> + <PartnerProperties> + <Name>IsSendable</Name> + <Value>True</Value> + </PartnerProperties> + <PartnerProperties> + <Name>IsTestable</Name> + <Value>False</Value> + </PartnerProperties> + <PartnerProperties> + <Name>SendableCustomObjectField</Name> + <Value>SubscriberKey</Value> + </PartnerProperties> + <PartnerProperties> + <Name>SendableSubscriberField</Name> + <Value>_SubscriberKey</Value> + </PartnerProperties> + <PartnerProperties> + <Name>DataRetentionPeriodLength</Name> + <Value>6</Value> + </PartnerProperties> + <PartnerProperties> + <Name>DataRetentionPeriodUnitOfMeasure</Name> + <Value>5</Value> + </PartnerProperties> + <PartnerProperties> + <Name>RowBasedRetention</Name> + <Value>False</Value> + </PartnerProperties> + <PartnerProperties> + <Name>ResetRetentionPeriodOnImport</Name> + <Value>False</Value> + </PartnerProperties> + <PartnerProperties> + <Name>DeleteAtEndOfRetentionPeriod</Name> + <Value>False</Value> + </PartnerProperties> + <PartnerProperties> + <Name>RetainUntil</Name> + <Value /> + </PartnerProperties> + <ObjectID>37d8c7f2-ad19-4084-8d18-4dda1dc36772</ObjectID> + <CustomerKey>DAE95D91-762C-4124-B082-0433165ADD30</CustomerKey> + <Name>AudienceBuilderResult</Name> + <Description>Used for creating audience builder result destinations.</Description> + </Results> + <Results xsi:type="DataExtensionTemplate"> + <PartnerKey xsi:nil="true" /> + <PartnerProperties> + <Name>IsSendable</Name> + <Value>True</Value> + </PartnerProperties> + <PartnerProperties> + <Name>IsTestable</Name> + <Value>False</Value> + </PartnerProperties> + <PartnerProperties> + <Name>SendableCustomObjectField</Name> + <Value>ContactKey</Value> + </PartnerProperties> + <PartnerProperties> + <Name>SendableSubscriberField</Name> + <Value>_SubscriberKey</Value> + </PartnerProperties> + <PartnerProperties> + <Name>DataRetentionPeriodLength</Name> + <Value /> + </PartnerProperties> + <PartnerProperties> + <Name>DataRetentionPeriodUnitOfMeasure</Name> + <Value>0</Value> + </PartnerProperties> + <PartnerProperties> + <Name>RowBasedRetention</Name> + <Value>False</Value> + </PartnerProperties> + <PartnerProperties> + <Name>ResetRetentionPeriodOnImport</Name> + <Value>False</Value> + </PartnerProperties> + <PartnerProperties> + <Name>DeleteAtEndOfRetentionPeriod</Name> + <Value>False</Value> + </PartnerProperties> + <PartnerProperties> + <Name>RetainUntil</Name> + <Value /> + </PartnerProperties> + <ObjectID>941cf36b-f927-4674-8468-c9a3bed7cae4</ObjectID> + <CustomerKey>BE1B7591-BFA6-473F-A6CE-0E458204865B</CustomerKey> + <Name>Event DE Template</Name> + <Description>Event Data Extension Template</Description> + </Results> + </RetrieveResponseMsg> + </soap:Body> +</soap:Envelope> \ No newline at end of file diff --git a/test/resources/1111111/dataFolder/retrieve-ContentType=queryactivity-response.xml b/test/resources/1111111/dataFolder/retrieve-ContentType=queryactivity-response.xml new file mode 100644 index 000000000..03d2eeac5 --- /dev/null +++ b/test/resources/1111111/dataFolder/retrieve-ContentType=queryactivity-response.xml @@ -0,0 +1,48 @@ +<?xml version="1.0" encoding="utf-8"?> +<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:xsd="http://www.w3.org/2001/XMLSchema" + xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing" + xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" + xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"> + <soap:Header> + <wsa:Action>RetrieveResponse</wsa:Action> + <wsa:MessageID>urn:uuid:f36f3303-3b5a-4641-8109-b26447634d91</wsa:MessageID> + <wsa:RelatesTo>urn:uuid:33983968-28c4-4379-bb5f-f80ae32eb988</wsa:RelatesTo> + <wsa:To>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</wsa:To> + <wsse:Security> + <wsu:Timestamp wsu:Id="Timestamp-32ecc81b-6020-473c-9e99-4b5338921220"> + <wsu:Created>2022-04-19T20:03:41Z</wsu:Created> + <wsu:Expires>2022-04-19T20:08:41Z</wsu:Expires> + </wsu:Timestamp> + </wsse:Security> + </soap:Header> + <soap:Body> + <RetrieveResponseMsg xmlns="http://exacttarget.com/wsdl/partnerAPI"> + <OverallStatus>OK</OverallStatus> + <RequestID>02cd5ccb-8f84-4651-826f-71169eeecf05</RequestID> + <Results xsi:type="DataFolder"> + <Client> + <ID>1111111</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2016-07-22T11:52:20.407</CreatedDate> + <ModifiedDate>2016-07-22T11:52:20.407</ModifiedDate> + <ID>9991</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>queryactivity_default</CustomerKey> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>0</ID> + <ObjectID xsi:nil="true" /> + </ParentFolder> + <Name>Query</Name> + <Description /> + <ContentType>queryactivity</ContentType> + <IsActive>true</IsActive> + <IsEditable>false</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + </RetrieveResponseMsg> + </soap:Body> +</soap:Envelope> diff --git a/test/resources/1111111/dataFolder/retrieve-ContentTypeINdataextension,hidden,queryactivity,salesforcedataextension,shared_data,shared_dataextension,shared_salesforcedataextension,synchronizeddataextension-response.xml b/test/resources/1111111/dataFolder/retrieve-ContentTypeINdataextension,hidden,queryactivity,salesforcedataextension,shared_data,shared_dataextension,shared_salesforcedataextension,synchronizeddataextension-response.xml new file mode 100644 index 000000000..c2d830483 --- /dev/null +++ b/test/resources/1111111/dataFolder/retrieve-ContentTypeINdataextension,hidden,queryactivity,salesforcedataextension,shared_data,shared_dataextension,shared_salesforcedataextension,synchronizeddataextension-response.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="utf-8"?> +<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:xsd="http://www.w3.org/2001/XMLSchema" + xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing" + xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" + xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"> + <soap:Header> + <wsa:Action>RetrieveResponse</wsa:Action> + <wsa:MessageID>urn:uuid:998a6923-b781-40be-abad-0506f0f97477</wsa:MessageID> + <wsa:RelatesTo>urn:uuid:a5d518cc-9bfb-45f1-a4a7-5d11cc1a8d44</wsa:RelatesTo> + <wsa:To>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</wsa:To> + <wsse:Security> + <wsu:Timestamp wsu:Id="Timestamp-a6c00a2f-fcfa-4882-a72d-8b8983a8cc7e"> + <wsu:Created>2025-09-05T16:29:03Z</wsu:Created> + <wsu:Expires>2025-09-05T16:34:03Z</wsu:Expires> + </wsu:Timestamp> + </wsse:Security> + </soap:Header> + <soap:Body> + <RetrieveResponseMsg xmlns="http://exacttarget.com/wsdl/partnerAPI"> + <OverallStatus>OK</OverallStatus> + <RequestID>ac40bccd-e8cd-4232-b1ee-e3cfbbfd0b89</RequestID> + </RetrieveResponseMsg> + </soap:Body> +</soap:Envelope> diff --git a/test/resources/1111111/dataFolder/retrieve-ContentTypeINdataextension,hidden,salesforcedataextension,shared_data,shared_dataextension,shared_salesforcedataextension,synchronizeddataextension-response.xml b/test/resources/1111111/dataFolder/retrieve-ContentTypeINdataextension,hidden,salesforcedataextension,shared_data,shared_dataextension,shared_salesforcedataextension,synchronizeddataextension-response.xml new file mode 100644 index 000000000..41bb03f59 --- /dev/null +++ b/test/resources/1111111/dataFolder/retrieve-ContentTypeINdataextension,hidden,salesforcedataextension,shared_data,shared_dataextension,shared_salesforcedataextension,synchronizeddataextension-response.xml @@ -0,0 +1,387 @@ +<?xml version="1.0" encoding="utf-8"?> +<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:xsd="http://www.w3.org/2001/XMLSchema" + xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing" + xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" + xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"> + <soap:Header> + <wsa:Action>RetrieveResponse</wsa:Action> + <wsa:MessageID>urn:uuid:4d209b2f-d7ce-4e6e-916c-c8642d368866</wsa:MessageID> + <wsa:RelatesTo>urn:uuid:a850f043-1422-4d16-8443-702dd2f9f13a</wsa:RelatesTo> + <wsa:To>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</wsa:To> + <wsse:Security> + <wsu:Timestamp wsu:Id="Timestamp-5da63531-caa7-4ead-9f10-a33d9bf66745"> + <wsu:Created>2023-08-11T13:15:46Z</wsu:Created> + <wsu:Expires>2023-08-11T13:20:46Z</wsu:Expires> + </wsu:Timestamp> + </wsse:Security> + </soap:Header> + <soap:Body> + <RetrieveResponseMsg xmlns="http://exacttarget.com/wsdl/partnerAPI"> + <OverallStatus>OK</OverallStatus> + <RequestID>ba1b0c59-78c4-4608-8423-35dda2248d4d</RequestID> + <Results xsi:type="DataFolder"> + <Client> + <ID>1111111</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2016-07-22T11:52:18.73</CreatedDate> + <ModifiedDate>2016-07-22T11:52:19.603</ModifiedDate> + <ID>89344</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>shared_data_default</CustomerKey> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>0</ID> + <ObjectID xsi:nil="true" /> + </ParentFolder> + <Name>Shared Items</Name> + <Description /> + <ContentType>shared_data</ContentType> + <IsActive>true</IsActive> + <IsEditable>false</IsEditable> + <AllowChildren>false</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>1111111</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2016-07-22T11:52:19.6</CreatedDate> + <ModifiedDate>2016-07-22T11:52:19.6</ModifiedDate> + <ID>89355</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>dataextension_default</CustomerKey> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>0</ID> + <ObjectID xsi:nil="true" /> + </ParentFolder> + <Name>Data Extensions</Name> + <Description /> + <ContentType>dataextension</ContentType> + <IsActive>true</IsActive> + <IsEditable>false</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>1111111</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2016-07-22T11:52:19.603</CreatedDate> + <ModifiedDate>2016-07-22T11:52:19.603</ModifiedDate> + <ID>89356</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>shared_dataextension_default</CustomerKey> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>89344</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>shared_data_default</CustomerKey> + </ParentFolder> + <Name>Shared Data Extensions</Name> + <Description /> + <ContentType>shared_dataextension</ContentType> + <IsActive>true</IsActive> + <IsEditable>false</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>1111111</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2016-07-29T12:13:27.28</CreatedDate> + <ModifiedDate>2016-07-29T12:13:27.28</ModifiedDate> + <ID>90889</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>HiddenCategory_default</CustomerKey> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>0</ID> + <ObjectID xsi:nil="true" /> + </ParentFolder> + <Name>HiddenCategory</Name> + <Description>Hidden folder to store Hidden items</Description> + <ContentType>Hidden</ContentType> + <IsActive>true</IsActive> + <IsEditable>false</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>1111111</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2016-08-23T09:22:27.54</CreatedDate> + <ModifiedDate>2016-08-23T09:22:27.54</ModifiedDate> + <ID>93698</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>salesforcedataextension_default</CustomerKey> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>0</ID> + <ObjectID xsi:nil="true" /> + </ParentFolder> + <Name>Salesforce Data Extensions</Name> + <Description /> + <ContentType>salesforcedataextension</ContentType> + <IsActive>true</IsActive> + <IsEditable>false</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>1111111</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2016-08-23T09:22:27.55</CreatedDate> + <ModifiedDate>2016-08-23T09:22:27.55</ModifiedDate> + <ID>93699</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>shared_salesforcedataextension_defau</CustomerKey> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>89344</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>shared_data_default</CustomerKey> + </ParentFolder> + <Name>Shared Salesforce Data Extensions</Name> + <Description /> + <ContentType>shared_salesforcedataextension</ContentType> + <IsActive>true</IsActive> + <IsEditable>false</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>1111111</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2020-01-27T10:50:46.573</CreatedDate> + <ModifiedDate>2020-01-27T10:50:46.573</ModifiedDate> + <ID>309082</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey /> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>89355</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>dataextension_default</CustomerKey> + </ParentFolder> + <Name>QueryStudioResults</Name> + <Description /> + <ContentType>dataextension</ContentType> + <IsActive>true</IsActive> + <IsEditable>true</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>1111111</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2020-04-17T08:14:19.763</CreatedDate> + <ModifiedDate>2020-04-17T08:14:19.763</ModifiedDate> + <ID>587750</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey /> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>89356</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>shared_dataextension_default</CustomerKey> + </ParentFolder> + <Name>catalyst target 1</Name> + <Description /> + <ContentType>shared_dataextension</ContentType> + <IsActive>true</IsActive> + <IsEditable>true</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>1111111</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2020-07-09T02:30:12.38</CreatedDate> + <ModifiedDate>2021-12-16T03:43:30.753</ModifiedDate> + <ID>605618</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>dataextension_default</CustomerKey> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>89355</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>dataextension_default</CustomerKey> + </ParentFolder> + <Name>Audiences</Name> + <Description /> + <ContentType>dataextension</ContentType> + <IsActive>true</IsActive> + <IsEditable>true</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>1111111</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2020-12-25T06:11:40.107</CreatedDate> + <ModifiedDate>2021-12-23T10:51:24.393</ModifiedDate> + <ID>633441</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey /> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>89355</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>dataextension_default</CustomerKey> + </ParentFolder> + <Name>System DEs</Name> + <Description /> + <ContentType>dataextension</ContentType> + <IsActive>true</IsActive> + <IsEditable>true</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>1111111</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2021-01-30T11:54:36.11</CreatedDate> + <ModifiedDate>2021-01-30T11:54:36.11</ModifiedDate> + <ID>638814</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>0b72bf27-0678-484d-ac0b-a8762b9bec33</CustomerKey> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>89356</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>shared_dataextension_default</CustomerKey> + </ParentFolder> + <Name>Customer 360 Segments</Name> + <Description>All Customer 360 segments will be grouped here. Each sub-folder relates to an activation profile name.</Description> + <ContentType>shared_dataextension</ContentType> + <IsActive>true</IsActive> + <IsEditable>false</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>1111111</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2021-01-30T11:56:38.77</CreatedDate> + <ModifiedDate>2021-01-30T11:56:38.77</ModifiedDate> + <ID>638815</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>cedd206d-178e-41cb-8965-ce255975b046</CustomerKey> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>638814</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>0b72bf27-0678-484d-ac0b-a8762b9bec33</CustomerKey> + </ParentFolder> + <Name>FirstAudience360 Segment</Name> + <Description /> + <ContentType>shared_dataextension</ContentType> + <IsActive>true</IsActive> + <IsEditable>false</IsEditable> + <AllowChildren>false</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>1111111</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2021-02-07T10:44:01.413</CreatedDate> + <ModifiedDate>2021-12-16T03:43:33.38</ModifiedDate> + <ID>639967</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey /> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>89355</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>dataextension_default</CustomerKey> + </ParentFolder> + <Name>TestAudiences</Name> + <Description /> + <ContentType>dataextension</ContentType> + <IsActive>true</IsActive> + <IsEditable>true</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>1111111</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2021-08-04T15:17:18.533</CreatedDate> + <ModifiedDate>2021-08-04T15:17:18.567</ModifiedDate> + <ID>675203</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>A19F7E38-7369-497E-826F-D551F17FB0B4</CustomerKey> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>0</ID> + <ObjectID xsi:nil="true" /> + </ParentFolder> + <Name>Synchronized Data Extensions</Name> + <Description /> + <ContentType>synchronizeddataextension</ContentType> + <IsActive>true</IsActive> + <IsEditable>false</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>1111111</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2021-10-03T05:01:37.23</CreatedDate> + <ModifiedDate>2021-10-03T05:01:37.37</ModifiedDate> + <ID>688352</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>B80AE306-55BC-4C2E-A79F-8CCA486F0BA0</CustomerKey> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>0</ID> + <ObjectID xsi:nil="true" /> + </ParentFolder> + <Name>Synchronized Data Extensions</Name> + <Description /> + <ContentType>synchronizeddataextension</ContentType> + <IsActive>true</IsActive> + <IsEditable>false</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>1111111</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2022-10-26T09:48:38.293</CreatedDate> + <ModifiedDate>2022-10-26T09:48:38.31</ModifiedDate> + <ID>757145</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>0ACB800B-AA8B-4F0F-9642-4907592C919C</CustomerKey> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>0</ID> + <ObjectID xsi:nil="true" /> + </ParentFolder> + <Name>Synchronized Data Extensions</Name> + <Description /> + <ContentType>synchronizeddataextension</ContentType> + <IsActive>true</IsActive> + <IsEditable>false</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + </RetrieveResponseMsg> + </soap:Body> +</soap:Envelope> diff --git a/test/resources/1111111/dataFolder/retrieve-ContentTypeINshared_data,shared_dataextension,shared_salesforcedataextension,synchronizeddataextension-response.xml b/test/resources/1111111/dataFolder/retrieve-ContentTypeINshared_data,shared_dataextension,shared_salesforcedataextension,synchronizeddataextension-response.xml new file mode 100644 index 000000000..48b0d0baf --- /dev/null +++ b/test/resources/1111111/dataFolder/retrieve-ContentTypeINshared_data,shared_dataextension,shared_salesforcedataextension,synchronizeddataextension-response.xml @@ -0,0 +1,364 @@ +<?xml version="1.0" encoding="utf-8"?> +<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:xsd="http://www.w3.org/2001/XMLSchema" + xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing" + xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" + xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"> + <soap:Header> + <wsa:Action>RetrieveResponse</wsa:Action> + <wsa:MessageID>urn:uuid:4d209b2f-d7ce-4e6e-916c-c8642d368866</wsa:MessageID> + <wsa:RelatesTo>urn:uuid:a850f043-1422-4d16-8443-702dd2f9f13a</wsa:RelatesTo> + <wsa:To>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</wsa:To> + <wsse:Security> + <wsu:Timestamp wsu:Id="Timestamp-5da63531-caa7-4ead-9f10-a33d9bf66745"> + <wsu:Created>2023-08-11T13:15:46Z</wsu:Created> + <wsu:Expires>2023-08-11T13:20:46Z</wsu:Expires> + </wsu:Timestamp> + </wsse:Security> + </soap:Header> + <soap:Body> + <RetrieveResponseMsg xmlns="http://exacttarget.com/wsdl/partnerAPI"> + <OverallStatus>OK</OverallStatus> + <RequestID>ba1b0c59-78c4-4608-8423-35dda2248d4d</RequestID> + <Results xsi:type="DataFolder"> + <Client> + <ID>1111111</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2016-07-22T11:52:18.73</CreatedDate> + <ModifiedDate>2016-07-22T11:52:19.603</ModifiedDate> + <ID>89344</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>shared_data_default</CustomerKey> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>0</ID> + <ObjectID xsi:nil="true" /> + </ParentFolder> + <Name>Shared Items</Name> + <Description /> + <ContentType>shared_data</ContentType> + <IsActive>true</IsActive> + <IsEditable>false</IsEditable> + <AllowChildren>false</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>1111111</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2016-07-22T11:52:19.6</CreatedDate> + <ModifiedDate>2016-07-22T11:52:19.6</ModifiedDate> + <ID>89355</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>dataextension_default</CustomerKey> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>0</ID> + <ObjectID xsi:nil="true" /> + </ParentFolder> + <Name>Data Extensions</Name> + <Description /> + <ContentType>dataextension</ContentType> + <IsActive>true</IsActive> + <IsEditable>false</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>1111111</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2016-07-22T11:52:19.603</CreatedDate> + <ModifiedDate>2016-07-22T11:52:19.603</ModifiedDate> + <ID>89356</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>shared_dataextension_default</CustomerKey> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>89344</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>shared_data_default</CustomerKey> + </ParentFolder> + <Name>Shared Data Extensions</Name> + <Description /> + <ContentType>shared_dataextension</ContentType> + <IsActive>true</IsActive> + <IsEditable>false</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>1111111</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2016-07-29T12:13:27.28</CreatedDate> + <ModifiedDate>2016-07-29T12:13:27.28</ModifiedDate> + <ID>90889</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>HiddenCategory_default</CustomerKey> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>0</ID> + <ObjectID xsi:nil="true" /> + </ParentFolder> + <Name>HiddenCategory</Name> + <Description>Hidden folder to store Hidden items</Description> + <ContentType>Hidden</ContentType> + <IsActive>true</IsActive> + <IsEditable>false</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>1111111</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2016-08-23T09:22:27.54</CreatedDate> + <ModifiedDate>2016-08-23T09:22:27.54</ModifiedDate> + <ID>93698</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>salesforcedataextension_default</CustomerKey> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>0</ID> + <ObjectID xsi:nil="true" /> + </ParentFolder> + <Name>Salesforce Data Extensions</Name> + <Description /> + <ContentType>salesforcedataextension</ContentType> + <IsActive>true</IsActive> + <IsEditable>false</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>1111111</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2016-08-23T09:22:27.55</CreatedDate> + <ModifiedDate>2016-08-23T09:22:27.55</ModifiedDate> + <ID>93699</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>shared_salesforcedataextension_defau</CustomerKey> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>89344</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>shared_data_default</CustomerKey> + </ParentFolder> + <Name>Shared Salesforce Data Extensions</Name> + <Description /> + <ContentType>shared_salesforcedataextension</ContentType> + <IsActive>true</IsActive> + <IsEditable>false</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>1111111</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2020-01-27T10:50:46.573</CreatedDate> + <ModifiedDate>2020-01-27T10:50:46.573</ModifiedDate> + <ID>309082</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey /> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>89355</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>dataextension_default</CustomerKey> + </ParentFolder> + <Name>QueryStudioResults</Name> + <Description /> + <ContentType>dataextension</ContentType> + <IsActive>true</IsActive> + <IsEditable>true</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>1111111</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2020-04-17T08:14:19.763</CreatedDate> + <ModifiedDate>2020-04-17T08:14:19.763</ModifiedDate> + <ID>587750</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey /> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>89356</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>shared_dataextension_default</CustomerKey> + </ParentFolder> + <Name>catalyst target 1</Name> + <Description /> + <ContentType>shared_dataextension</ContentType> + <IsActive>true</IsActive> + <IsEditable>true</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>1111111</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2020-07-09T02:30:12.38</CreatedDate> + <ModifiedDate>2021-12-16T03:43:30.753</ModifiedDate> + <ID>605618</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>dataextension_default</CustomerKey> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>89355</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>dataextension_default</CustomerKey> + </ParentFolder> + <Name>Audiences</Name> + <Description /> + <ContentType>dataextension</ContentType> + <IsActive>true</IsActive> + <IsEditable>true</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>1111111</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2020-12-25T06:11:40.107</CreatedDate> + <ModifiedDate>2021-12-23T10:51:24.393</ModifiedDate> + <ID>633441</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey /> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>89355</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>dataextension_default</CustomerKey> + </ParentFolder> + <Name>System DEs</Name> + <Description /> + <ContentType>dataextension</ContentType> + <IsActive>true</IsActive> + <IsEditable>true</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>1111111</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2021-01-30T11:54:36.11</CreatedDate> + <ModifiedDate>2021-01-30T11:54:36.11</ModifiedDate> + <ID>638814</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>0b72bf27-0678-484d-ac0b-a8762b9bec33</CustomerKey> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>89356</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>shared_dataextension_default</CustomerKey> + </ParentFolder> + <Name>Customer 360 Segments</Name> + <Description>All Customer 360 segments will be grouped here. Each sub-folder relates to an activation profile name.</Description> + <ContentType>shared_dataextension</ContentType> + <IsActive>true</IsActive> + <IsEditable>false</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>1111111</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2021-01-30T11:56:38.77</CreatedDate> + <ModifiedDate>2021-01-30T11:56:38.77</ModifiedDate> + <ID>638815</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>cedd206d-178e-41cb-8965-ce255975b046</CustomerKey> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>638814</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>0b72bf27-0678-484d-ac0b-a8762b9bec33</CustomerKey> + </ParentFolder> + <Name>FirstAudience360 Segment</Name> + <Description /> + <ContentType>shared_dataextension</ContentType> + <IsActive>true</IsActive> + <IsEditable>false</IsEditable> + <AllowChildren>false</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>1111111</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2021-08-04T15:17:18.533</CreatedDate> + <ModifiedDate>2021-08-04T15:17:18.567</ModifiedDate> + <ID>675203</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>A19F7E38-7369-497E-826F-D551F17FB0B4</CustomerKey> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>0</ID> + <ObjectID xsi:nil="true" /> + </ParentFolder> + <Name>Synchronized Data Extensions</Name> + <Description /> + <ContentType>synchronizeddataextension</ContentType> + <IsActive>true</IsActive> + <IsEditable>false</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>1111111</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2021-10-03T05:01:37.23</CreatedDate> + <ModifiedDate>2021-10-03T05:01:37.37</ModifiedDate> + <ID>688352</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>B80AE306-55BC-4C2E-A79F-8CCA486F0BA0</CustomerKey> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>0</ID> + <ObjectID xsi:nil="true" /> + </ParentFolder> + <Name>Synchronized Data Extensions</Name> + <Description /> + <ContentType>synchronizeddataextension</ContentType> + <IsActive>true</IsActive> + <IsEditable>false</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>1111111</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2022-10-26T09:48:38.293</CreatedDate> + <ModifiedDate>2022-10-26T09:48:38.31</ModifiedDate> + <ID>757145</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>0ACB800B-AA8B-4F0F-9642-4907592C919C</CustomerKey> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>0</ID> + <ObjectID xsi:nil="true" /> + </ParentFolder> + <Name>Synchronized Data Extensions</Name> + <Description /> + <ContentType>synchronizeddataextension</ContentType> + <IsActive>true</IsActive> + <IsEditable>false</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + </RetrieveResponseMsg> + </soap:Body> +</soap:Envelope> diff --git a/test/resources/1111111/dataFolder/retrieve-response-.xml b/test/resources/1111111/dataFolder/retrieve-response-.xml new file mode 100644 index 000000000..41bb03f59 --- /dev/null +++ b/test/resources/1111111/dataFolder/retrieve-response-.xml @@ -0,0 +1,387 @@ +<?xml version="1.0" encoding="utf-8"?> +<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:xsd="http://www.w3.org/2001/XMLSchema" + xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing" + xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" + xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"> + <soap:Header> + <wsa:Action>RetrieveResponse</wsa:Action> + <wsa:MessageID>urn:uuid:4d209b2f-d7ce-4e6e-916c-c8642d368866</wsa:MessageID> + <wsa:RelatesTo>urn:uuid:a850f043-1422-4d16-8443-702dd2f9f13a</wsa:RelatesTo> + <wsa:To>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</wsa:To> + <wsse:Security> + <wsu:Timestamp wsu:Id="Timestamp-5da63531-caa7-4ead-9f10-a33d9bf66745"> + <wsu:Created>2023-08-11T13:15:46Z</wsu:Created> + <wsu:Expires>2023-08-11T13:20:46Z</wsu:Expires> + </wsu:Timestamp> + </wsse:Security> + </soap:Header> + <soap:Body> + <RetrieveResponseMsg xmlns="http://exacttarget.com/wsdl/partnerAPI"> + <OverallStatus>OK</OverallStatus> + <RequestID>ba1b0c59-78c4-4608-8423-35dda2248d4d</RequestID> + <Results xsi:type="DataFolder"> + <Client> + <ID>1111111</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2016-07-22T11:52:18.73</CreatedDate> + <ModifiedDate>2016-07-22T11:52:19.603</ModifiedDate> + <ID>89344</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>shared_data_default</CustomerKey> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>0</ID> + <ObjectID xsi:nil="true" /> + </ParentFolder> + <Name>Shared Items</Name> + <Description /> + <ContentType>shared_data</ContentType> + <IsActive>true</IsActive> + <IsEditable>false</IsEditable> + <AllowChildren>false</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>1111111</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2016-07-22T11:52:19.6</CreatedDate> + <ModifiedDate>2016-07-22T11:52:19.6</ModifiedDate> + <ID>89355</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>dataextension_default</CustomerKey> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>0</ID> + <ObjectID xsi:nil="true" /> + </ParentFolder> + <Name>Data Extensions</Name> + <Description /> + <ContentType>dataextension</ContentType> + <IsActive>true</IsActive> + <IsEditable>false</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>1111111</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2016-07-22T11:52:19.603</CreatedDate> + <ModifiedDate>2016-07-22T11:52:19.603</ModifiedDate> + <ID>89356</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>shared_dataextension_default</CustomerKey> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>89344</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>shared_data_default</CustomerKey> + </ParentFolder> + <Name>Shared Data Extensions</Name> + <Description /> + <ContentType>shared_dataextension</ContentType> + <IsActive>true</IsActive> + <IsEditable>false</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>1111111</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2016-07-29T12:13:27.28</CreatedDate> + <ModifiedDate>2016-07-29T12:13:27.28</ModifiedDate> + <ID>90889</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>HiddenCategory_default</CustomerKey> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>0</ID> + <ObjectID xsi:nil="true" /> + </ParentFolder> + <Name>HiddenCategory</Name> + <Description>Hidden folder to store Hidden items</Description> + <ContentType>Hidden</ContentType> + <IsActive>true</IsActive> + <IsEditable>false</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>1111111</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2016-08-23T09:22:27.54</CreatedDate> + <ModifiedDate>2016-08-23T09:22:27.54</ModifiedDate> + <ID>93698</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>salesforcedataextension_default</CustomerKey> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>0</ID> + <ObjectID xsi:nil="true" /> + </ParentFolder> + <Name>Salesforce Data Extensions</Name> + <Description /> + <ContentType>salesforcedataextension</ContentType> + <IsActive>true</IsActive> + <IsEditable>false</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>1111111</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2016-08-23T09:22:27.55</CreatedDate> + <ModifiedDate>2016-08-23T09:22:27.55</ModifiedDate> + <ID>93699</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>shared_salesforcedataextension_defau</CustomerKey> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>89344</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>shared_data_default</CustomerKey> + </ParentFolder> + <Name>Shared Salesforce Data Extensions</Name> + <Description /> + <ContentType>shared_salesforcedataextension</ContentType> + <IsActive>true</IsActive> + <IsEditable>false</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>1111111</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2020-01-27T10:50:46.573</CreatedDate> + <ModifiedDate>2020-01-27T10:50:46.573</ModifiedDate> + <ID>309082</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey /> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>89355</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>dataextension_default</CustomerKey> + </ParentFolder> + <Name>QueryStudioResults</Name> + <Description /> + <ContentType>dataextension</ContentType> + <IsActive>true</IsActive> + <IsEditable>true</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>1111111</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2020-04-17T08:14:19.763</CreatedDate> + <ModifiedDate>2020-04-17T08:14:19.763</ModifiedDate> + <ID>587750</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey /> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>89356</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>shared_dataextension_default</CustomerKey> + </ParentFolder> + <Name>catalyst target 1</Name> + <Description /> + <ContentType>shared_dataextension</ContentType> + <IsActive>true</IsActive> + <IsEditable>true</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>1111111</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2020-07-09T02:30:12.38</CreatedDate> + <ModifiedDate>2021-12-16T03:43:30.753</ModifiedDate> + <ID>605618</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>dataextension_default</CustomerKey> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>89355</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>dataextension_default</CustomerKey> + </ParentFolder> + <Name>Audiences</Name> + <Description /> + <ContentType>dataextension</ContentType> + <IsActive>true</IsActive> + <IsEditable>true</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>1111111</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2020-12-25T06:11:40.107</CreatedDate> + <ModifiedDate>2021-12-23T10:51:24.393</ModifiedDate> + <ID>633441</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey /> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>89355</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>dataextension_default</CustomerKey> + </ParentFolder> + <Name>System DEs</Name> + <Description /> + <ContentType>dataextension</ContentType> + <IsActive>true</IsActive> + <IsEditable>true</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>1111111</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2021-01-30T11:54:36.11</CreatedDate> + <ModifiedDate>2021-01-30T11:54:36.11</ModifiedDate> + <ID>638814</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>0b72bf27-0678-484d-ac0b-a8762b9bec33</CustomerKey> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>89356</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>shared_dataextension_default</CustomerKey> + </ParentFolder> + <Name>Customer 360 Segments</Name> + <Description>All Customer 360 segments will be grouped here. Each sub-folder relates to an activation profile name.</Description> + <ContentType>shared_dataextension</ContentType> + <IsActive>true</IsActive> + <IsEditable>false</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>1111111</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2021-01-30T11:56:38.77</CreatedDate> + <ModifiedDate>2021-01-30T11:56:38.77</ModifiedDate> + <ID>638815</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>cedd206d-178e-41cb-8965-ce255975b046</CustomerKey> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>638814</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>0b72bf27-0678-484d-ac0b-a8762b9bec33</CustomerKey> + </ParentFolder> + <Name>FirstAudience360 Segment</Name> + <Description /> + <ContentType>shared_dataextension</ContentType> + <IsActive>true</IsActive> + <IsEditable>false</IsEditable> + <AllowChildren>false</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>1111111</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2021-02-07T10:44:01.413</CreatedDate> + <ModifiedDate>2021-12-16T03:43:33.38</ModifiedDate> + <ID>639967</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey /> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>89355</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>dataextension_default</CustomerKey> + </ParentFolder> + <Name>TestAudiences</Name> + <Description /> + <ContentType>dataextension</ContentType> + <IsActive>true</IsActive> + <IsEditable>true</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>1111111</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2021-08-04T15:17:18.533</CreatedDate> + <ModifiedDate>2021-08-04T15:17:18.567</ModifiedDate> + <ID>675203</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>A19F7E38-7369-497E-826F-D551F17FB0B4</CustomerKey> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>0</ID> + <ObjectID xsi:nil="true" /> + </ParentFolder> + <Name>Synchronized Data Extensions</Name> + <Description /> + <ContentType>synchronizeddataextension</ContentType> + <IsActive>true</IsActive> + <IsEditable>false</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>1111111</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2021-10-03T05:01:37.23</CreatedDate> + <ModifiedDate>2021-10-03T05:01:37.37</ModifiedDate> + <ID>688352</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>B80AE306-55BC-4C2E-A79F-8CCA486F0BA0</CustomerKey> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>0</ID> + <ObjectID xsi:nil="true" /> + </ParentFolder> + <Name>Synchronized Data Extensions</Name> + <Description /> + <ContentType>synchronizeddataextension</ContentType> + <IsActive>true</IsActive> + <IsEditable>false</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>1111111</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2022-10-26T09:48:38.293</CreatedDate> + <ModifiedDate>2022-10-26T09:48:38.31</ModifiedDate> + <ID>757145</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>0ACB800B-AA8B-4F0F-9642-4907592C919C</CustomerKey> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>0</ID> + <ObjectID xsi:nil="true" /> + </ParentFolder> + <Name>Synchronized Data Extensions</Name> + <Description /> + <ContentType>synchronizeddataextension</ContentType> + <IsActive>true</IsActive> + <IsEditable>false</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + </RetrieveResponseMsg> + </soap:Body> +</soap:Envelope> diff --git a/test/resources/1111111/list/retrieve-CustomerKey=All SubscribersORListName=All Subscribers-response.xml b/test/resources/1111111/list/retrieve-CustomerKey=All SubscribersORListName=All Subscribers-response.xml new file mode 100644 index 000000000..6b43f89e8 --- /dev/null +++ b/test/resources/1111111/list/retrieve-CustomerKey=All SubscribersORListName=All Subscribers-response.xml @@ -0,0 +1,39 @@ +<?xml version="1.0" encoding="utf-8"?> +<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:xsd="http://www.w3.org/2001/XMLSchema" + xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing" + xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" + xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"> + <soap:Header> + <wsa:Action>RetrieveResponse</wsa:Action> + <wsa:MessageID>urn:uuid:26648e52-3bac-4eca-a5e1-ad71d38b56fe</wsa:MessageID> + <wsa:RelatesTo>urn:uuid:8552cfbd-466c-447e-a232-13d945e44a5c</wsa:RelatesTo> + <wsa:To>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</wsa:To> + <wsse:Security> + <wsu:Timestamp wsu:Id="Timestamp-c80ba907-ecc4-447d-8418-140c4ca108de"> + <wsu:Created>2022-11-29T19:42:21Z</wsu:Created> + <wsu:Expires>2022-11-29T19:47:21Z</wsu:Expires> + </wsu:Timestamp> + </wsse:Security> + </soap:Header> + <soap:Body> + <RetrieveResponseMsg xmlns="http://exacttarget.com/wsdl/partnerAPI"> + <OverallStatus>OK</OverallStatus> + <RequestID>11e9f8a8-e5e6-4082-93bd-5840060512ce</RequestID> + <Results xsi:type="List"> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2017-01-24T06:32:34.453</CreatedDate> + <ModifiedDate>2017-01-24T06:32:34.453</ModifiedDate> + <ID>15</ID> + <ObjectID>1f793b8b-cb23-4bb4-9ec4-1e0bf9511960</ObjectID> + <CustomerKey>All Subscribers - 277</CustomerKey> + <ListName>All Subscribers</ListName> + <Category>277</Category> + <Type>Private</Type> + <Description>Contains all subscribers</Description> + <ListClassification>ExactTargetList</ListClassification> + </Results> + </RetrieveResponseMsg> + </soap:Body> +</soap:Envelope> diff --git a/test/resources/1111111/platform/v1/setup/quickflow/data/get-response.json b/test/resources/1111111/platform/v1/setup/quickflow/data/get-response.json new file mode 100644 index 000000000..5e71e4ee4 --- /dev/null +++ b/test/resources/1111111/platform/v1/setup/quickflow/data/get-response.json @@ -0,0 +1,455 @@ +{ + "languages": [ + { + "Key": "en-US", + "Value": "English (United States)" + }, + { + "Key": "fr-CA", + "Value": "French (Canada)" + }, + { + "Key": "fr-FR", + "Value": "French (France)" + }, + { + "Key": "de-DE", + "Value": "German (Germany)" + }, + { + "Key": "it-IT", + "Value": "Italian (Italy)" + }, + { + "Key": "ja-JP", + "Value": "Japanese (Japan)" + }, + { + "Key": "pt-BR", + "Value": "Portuguese (Brazil)" + }, + { + "Key": "es-419", + "Value": "Spanish (Latin America)" + }, + { + "Key": "es-ES", + "Value": "Spanish (Spain)" + } + ], + "roles": [ + { + "roleID": "f1cfb80f-3550-e611-96fe-38eaa7142c61", + "roleName": "Administrator", + "description": "Administrator" + }, + { + "roleID": "facfb80f-3550-e611-96fe-38eaa7142c61", + "roleName": "Analyst", + "description": "Analyst" + }, + { + "roleID": "f4cfb80f-3550-e611-96fe-38eaa7142c61", + "roleName": "Content Creator", + "description": "Content Creator" + }, + { + "roleID": "1c564845-32d5-eb11-b82a-48df37d1deb7", + "roleName": "Custom Connector", + "description": "Custom Connector" + }, + { + "roleID": "f6cfb80f-3550-e611-96fe-38eaa7142c61", + "roleName": "Data Manager", + "description": "Data Manager" + }, + { + "roleID": "fdcfb80f-3550-e611-96fe-38eaa7142c61", + "roleName": "Distributed Sending User", + "description": "Distributed Sending User" + }, + { + "roleID": "63a50610-315c-e111-beee-8e001800001f", + "roleName": "Marketing Cloud Administrator", + "description": "Assign Marketing Cloud roles to users and manage Mobile, Social and Sites Channels, Marketing Cloud Apps and Tools." + }, + { + "roleID": "66a50610-315c-e111-beee-8e001800001f", + "roleName": "Marketing Cloud Channel Manager", + "description": "Create and execute cross-channel interactive marketing campaigns and administer Social and Mobile Channels" + }, + { + "roleID": "64a50610-315c-e111-beee-8e001800001f", + "roleName": "Marketing Cloud Content Editor/Publisher", + "description": "Create and deliver messages through Mobile and Sites Channel Apps" + }, + { + "roleID": "67a50610-315c-e111-beee-8e001800001f", + "roleName": "Marketing Cloud Security Administrator", + "description": "Maintain Watchdog security settings and manage user activity and alerts" + }, + { + "roleID": "65a50610-315c-e111-beee-8e001800001f", + "roleName": "Marketing Cloud Viewer", + "description": "View cross-channel marketing activity and results within the Marketing Cloud" + } + ], + "timeZones": [ + { + "id": "2", + "description": "(GMT) Casablanca *" + }, + { + "id": "3", + "description": "(GMT) Dublin, Edinburgh, Lisbon, London *" + }, + { + "id": "4", + "description": "(GMT) Monrovia, Reykjavik" + }, + { + "id": "5", + "description": "(GMT+01:00) Amsterdam, Berlin, Bern, Rome, Stockholm, Vienna *" + }, + { + "id": "6", + "description": "(GMT+01:00) Belgrade, Bratislava, Budapest, Ljubljana, Prague *" + }, + { + "id": "7", + "description": "(GMT+01:00) Brussels, Copenhagen, Madrid, Paris *" + }, + { + "id": "8", + "description": "(GMT+01:00) Sarajevo, Skopje, Warsaw, Zagreb *" + }, + { + "id": "9", + "description": "(GMT+01:00) West Central Africa" + }, + { + "id": "18", + "description": "(GMT+01:00) Windhoek *" + }, + { + "id": "10", + "description": "(GMT+02:00) Amman *" + }, + { + "id": "11", + "description": "(GMT+02:00) Athens, Bucharest *" + }, + { + "id": "12", + "description": "(GMT+02:00) Beirut *" + }, + { + "id": "13", + "description": "(GMT+02:00) Cairo " + }, + { + "id": "17", + "description": "(GMT+02:00) E. Europe *" + }, + { + "id": "14", + "description": "(GMT+02:00) Harare, Pretoria" + }, + { + "id": "15", + "description": "(GMT+02:00) Helsinki, Kyiv, Riga, Sofia, Tallinn, Vilnius *" + }, + { + "id": "16", + "description": "(GMT+02:00) Jerusalem *" + }, + { + "id": "19", + "description": "(GMT+03:00) Baghdad *" + }, + { + "id": "20", + "description": "(GMT+03:00) Kuwait, Riyadh" + }, + { + "id": "21", + "description": "(GMT+03:00) Moscow, St. Petersburg, Volgograd (RTZ 2)" + }, + { + "id": "22", + "description": "(GMT+03:00) Nairobi" + }, + { + "id": "24", + "description": "(GMT+03:30) Tehran *" + }, + { + "id": "25", + "description": "(GMT+04:00) Abu Dhabi, Muscat" + }, + { + "id": "26", + "description": "(GMT+04:00) Baku *" + }, + { + "id": "27", + "description": "(GMT+04:00) Yerevan *" + }, + { + "id": "28", + "description": "(GMT+04:00) Port Louis *" + }, + { + "id": "23", + "description": "(GMT+04:00) Tbilisi" + }, + { + "id": "30", + "description": "(GMT+04:30) Kabul" + }, + { + "id": "31", + "description": "(GMT+05:00) Ekaterinburg (RTZ 4)" + }, + { + "id": "33", + "description": "(GMT+05:00) Ashgabat, Tashkent" + }, + { + "id": "32", + "description": "(GMT+05:00) Islamabad, Karachi *" + }, + { + "id": "34", + "description": "(GMT+05:30) Chennai, Kolkata, Mumbai, New Delhi" + }, + { + "id": "35", + "description": "(GMT+05:30) Sri Jayawardenepura" + }, + { + "id": "36", + "description": "(GMT+05:45) Kathmandu" + }, + { + "id": "38", + "description": "(GMT+06:00) Astana" + }, + { + "id": "37", + "description": "(GMT+06:00) Novosibirsk (RTZ 5)" + }, + { + "id": "39", + "description": "(GMT+06:30) Yangon (Rangoon)" + }, + { + "id": "40", + "description": "(GMT+07:00) Bangkok, Hanoi, Jakarta" + }, + { + "id": "41", + "description": "(GMT+07:00) Krasnoyarsk (RTZ 6)" + }, + { + "id": "42", + "description": "(GMT+08:00) Beijing, Chongqing, Hong Kong, Urumqi" + }, + { + "id": "43", + "description": "(GMT+08:00) Irkutsk (RTZ 7)" + }, + { + "id": "44", + "description": "(GMT+08:00) Kuala Lumpur, Singapore" + }, + { + "id": "45", + "description": "(GMT+08:00) Perth *" + }, + { + "id": "46", + "description": "(GMT+08:00) Taipei" + }, + { + "id": "47", + "description": "(GMT+09:00) Osaka, Sapporo, Tokyo" + }, + { + "id": "48", + "description": "(GMT+09:00) Seoul" + }, + { + "id": "49", + "description": "(GMT+09:00) Yakutsk (RTZ 8)" + }, + { + "id": "50", + "description": "(GMT+09:30) Adelaide *" + }, + { + "id": "51", + "description": "(GMT+09:30) Darwin" + }, + { + "id": "52", + "description": "(GMT+10:00) Brisbane" + }, + { + "id": "53", + "description": "(GMT+10:00) Canberra, Melbourne, Sydney *" + }, + { + "id": "54", + "description": "(GMT+10:00) Guam, Port Moresby" + }, + { + "id": "55", + "description": "(GMT+10:00) Hobart *" + }, + { + "id": "56", + "description": "(GMT+10:00) Vladivostok, Magadan (RTZ 9)" + }, + { + "id": "57", + "description": "(GMT+11:00) Solomon Is., New Caledonia" + }, + { + "id": "58", + "description": "(GMT+12:00) Auckland, Wellington *" + }, + { + "id": "59", + "description": "(GMT+12:00) Fiji *" + }, + { + "id": "60", + "description": "(GMT+13:00) Nukualofa" + }, + { + "id": "91", + "description": "(GMT+13:00)Samoa *" + }, + { + "id": "61", + "description": "(GMT-01:00) Azores *" + }, + { + "id": "62", + "description": "(GMT-01:00) Cabo Verde Is." + }, + { + "id": "63", + "description": "(GMT-02:00) Mid-Atlantic - Old *" + }, + { + "id": "64", + "description": "(GMT-03:00) Brasilia" + }, + { + "id": "65", + "description": "(GMT-03:00) Buenos Aires *" + }, + { + "id": "67", + "description": "(GMT-03:00) Greenland *" + }, + { + "id": "68", + "description": "(GMT-03:00) Montevideo *" + }, + { + "id": "69", + "description": "(GMT-03:30) Newfoundland *" + }, + { + "id": "70", + "description": "(GMT-04:00) Atlantic Time (Canada) *" + }, + { + "id": "72", + "description": "(GMT-04:00) Cuiaba " + }, + { + "id": "66", + "description": "(GMT-04:00) Georgetown, La Paz, Manaus, San Juan" + }, + { + "id": "73", + "description": "(GMT-04:00) Santiago * " + }, + { + "id": "74", + "description": "(GMT-04:30) Caracas" + }, + { + "id": "75", + "description": "(GMT-05:00) Bogota, Lima, Quito, Rio Branco" + }, + { + "id": "76", + "description": "(GMT-05:00) Eastern Time (US & Canada) *" + }, + { + "id": "77", + "description": "(GMT-05:00) Indiana (East) *" + }, + { + "id": "78", + "description": "(GMT-06:00) Central America" + }, + { + "id": "79", + "description": "(GMT-06:00) Central Time (US & Canada) *" + }, + { + "id": "1", + "description": "(GMT-06:00) Central Time (No Daylight Savings)" + }, + { + "id": "80", + "description": "(GMT-06:00) Guadalajara, Mexico City, Monterrey *" + }, + { + "id": "82", + "description": "(GMT-06:00) Saskatchewan" + }, + { + "id": "83", + "description": "(GMT-07:00) Arizona" + }, + { + "id": "84", + "description": "(GMT-07:00) Chihuahua, La Paz, Mazatlan *" + }, + { + "id": "86", + "description": "(GMT-07:00) Mountain Time (US & Canada) *" + }, + { + "id": "88", + "description": "(GMT-08:00) Baja California *" + }, + { + "id": "87", + "description": "(GMT-08:00) Pacific Time (US & Canada) *" + }, + { + "id": "89", + "description": "(GMT-09:00) Alaska *" + }, + { + "id": "90", + "description": "(GMT-10:00) Hawaii" + }, + { + "id": "92", + "description": "(GMT-12:00) International Date Line West" + } + ], + "defaultUserData": { + "defaultTimeZone": "5", + "defaultLanguage": "en-GB" + } +} diff --git a/test/resources/1111111/query/patch_keySuffix-expected.json b/test/resources/1111111/query/patch_keySuffix-expected.json new file mode 100644 index 000000000..ab0d0a375 --- /dev/null +++ b/test/resources/1111111/query/patch_keySuffix-expected.json @@ -0,0 +1,11 @@ +{ + "name": "testNew_query", + "key": "testNew_query_DEV", + "description": "created on deploy", + "r__dataExtension_key": "testExisting_dataExtensionShared", + "createdDate": "2022-04-26T15:21:16.453", + "modifiedDate": "2022-04-26T16:04:15.88", + "targetUpdateTypeName": "Overwrite", + "isFrozen": false, + "r__folder_Path": "Query" +} diff --git a/test/resources/1111111/query/patch_keySuffix-expected.sql b/test/resources/1111111/query/patch_keySuffix-expected.sql new file mode 100644 index 000000000..4148833c4 --- /dev/null +++ b/test/resources/1111111/query/patch_keySuffix-expected.sql @@ -0,0 +1,4 @@ +SELECT + SubscriberKey AS testField +FROM + _Subscribers diff --git a/test/resources/1111111/role/retrieve-IsPrivate=false-response.xml b/test/resources/1111111/role/retrieve-IsPrivate=false-response.xml new file mode 100644 index 000000000..6bb51bb62 --- /dev/null +++ b/test/resources/1111111/role/retrieve-IsPrivate=false-response.xml @@ -0,0 +1,76 @@ +<?xml version="1.0" encoding="utf-8"?> +<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:xsd="http://www.w3.org/2001/XMLSchema" + xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing" + xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" + xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"> + <soap:Header> + <wsa:Action>RetrieveResponse</wsa:Action> + <wsa:MessageID>urn:uuid:e45d2dee-e7c7-4c09-a6fe-887dd4021950</wsa:MessageID> + <wsa:RelatesTo>urn:uuid:5f970206-bed2-4006-8590-e3aa52133e4c</wsa:RelatesTo> + <wsa:To>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</wsa:To> + <wsse:Security> + <wsu:Timestamp wsu:Id="Timestamp-c1c19a43-2495-43e6-81f4-a86863f894aa"> + <wsu:Created>2023-03-11T13:52:51Z</wsu:Created> + <wsu:Expires>2023-03-11T13:57:51Z</wsu:Expires> + </wsu:Timestamp> + </wsse:Security> + </soap:Header> + <soap:Body> + <RetrieveResponseMsg xmlns="http://exacttarget.com/wsdl/partnerAPI"> + <OverallStatus>OK</OverallStatus> + <RequestID>e4b2d26e-c429-4856-a410-eeb2951e84e0</RequestID> + <Results xsi:type="Role"> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2016-07-22T17:52:36.93</CreatedDate> + <ModifiedDate>2016-07-22T17:52:36.93</ModifiedDate> + <ObjectID>f1cfb80f-3550-e611-96fe-38eaa7142c61</ObjectID> + <CustomerKey>SYS_DEF_ADMIN</CustomerKey> + <Name>Administrator</Name> + <Description>Administrator</Description> + <IsSystemDefined>true</IsSystemDefined> + </Results> + <Results xsi:type="Role"> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2016-07-22T17:52:36.953</CreatedDate> + <ModifiedDate>2016-07-22T17:52:36.953</ModifiedDate> + <ObjectID>f4cfb80f-3550-e611-96fe-38eaa7142c61</ObjectID> + <CustomerKey>SYS_DEF_CONTENT</CustomerKey> + <Name>Content Creator</Name> + <Description>Content Creator</Description> + <IsSystemDefined>true</IsSystemDefined> + </Results> + <Results xsi:type="Role"> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2016-07-22T17:52:36.97</CreatedDate> + <ModifiedDate>2016-07-22T17:52:36.97</ModifiedDate> + <ObjectID>f6cfb80f-3550-e611-96fe-38eaa7142c61</ObjectID> + <CustomerKey>SYS_DEF_DATA</CustomerKey> + <Name>Data Manager</Name> + <Description>Data Manager</Description> + <IsSystemDefined>true</IsSystemDefined> + </Results> + <Results xsi:type="Role"> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2016-07-22T17:52:36.98</CreatedDate> + <ModifiedDate>2016-07-22T17:52:36.98</ModifiedDate> + <ObjectID>facfb80f-3550-e611-96fe-38eaa7142c61</ObjectID> + <CustomerKey>SYS_DEF_ANALYST</CustomerKey> + <Name>Analyst</Name> + <Description>Analyst</Description> + <IsSystemDefined>true</IsSystemDefined> + </Results> + <Results xsi:type="Role"> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2016-07-22T17:52:36.993</CreatedDate> + <ModifiedDate>2016-07-22T17:52:36.993</ModifiedDate> + <ObjectID>fdcfb80f-3550-e611-96fe-38eaa7142c61</ObjectID> + <CustomerKey>SYS_DEF_DS_USER</CustomerKey> + <Name>Distributed Sending User</Name> + <Description>Distributed Sending User</Description> + <IsSystemDefined>true</IsSystemDefined> + </Results> + </RetrieveResponseMsg> + </soap:Body> +</soap:Envelope> \ No newline at end of file diff --git a/test/resources/1111111/user/build-expected.json b/test/resources/1111111/user/build-expected.json new file mode 100644 index 000000000..e45160445 --- /dev/null +++ b/test/resources/1111111/user/build-expected.json @@ -0,0 +1,16 @@ +{ + "Client": {}, + "CustomerKey": "testTemplated_user", + "UserID": "user_testTarget@accenture.asgr", + "Name": "user test", + "Email": "user_testTarget@accenture.com", + "MustChangePassword": false, + "ActiveFlag": true, + "IsAPIUser": false, + "NotificationEmailAddress": "user_testTarget@accenture.com", + "DefaultBusinessUnit": "1111111", + "c__AssociatedBusinessUnits": ["1111111", "1111111"], + "c__RoleNamesGlobal": ["Administrator", "Content Creator", "Marketing Cloud Administrator"], + "c__TimeZoneName": "(GMT+01:00) Amsterdam, Berlin, Bern, Rome, Stockholm, Vienna *", + "c__LocaleCode": "en-GB" +} diff --git a/test/resources/1111111/user/create-expected.json b/test/resources/1111111/user/create-expected.json new file mode 100644 index 000000000..4fef1889b --- /dev/null +++ b/test/resources/1111111/user/create-expected.json @@ -0,0 +1,21 @@ +{ + "Client": { + "ModifiedBy": 123456 + }, + "CustomerKey": "testNew_user", + "UserID": "testNew_user@accenture.asgr", + "Name": "new user", + "Email": "testNew_user@accenture.com", + "MustChangePassword": false, + "ActiveFlag": true, + "IsAPIUser": false, + "NotificationEmailAddress": "testNew_user@accenture.com", + "DefaultBusinessUnit": 1111111, + "c__type": "User", + "c__AccountUserID": 700301950, + "c__IsLocked_readOnly": false, + "c__AssociatedBusinessUnits": [1111111, 9999999], + "c__RoleNamesGlobal": ["Administrator", "Distributed Sending User"], + "c__TimeZoneName": "(GMT+01:00) Amsterdam, Berlin, Bern, Rome, Stockholm, Vienna *", + "c__LocaleCode": "en-GB" +} diff --git a/test/resources/1111111/user/retrieve-expected.json b/test/resources/1111111/user/retrieve-expected.json new file mode 100644 index 000000000..d14eacb41 --- /dev/null +++ b/test/resources/1111111/user/retrieve-expected.json @@ -0,0 +1,24 @@ +{ + "Client": { + "ModifiedBy": 123456 + }, + "CreatedDate": "2019-09-06T01:59:07.097", + "ModifiedDate": "2022-06-21T01:43:02.64", + "CustomerKey": "testExisting_user", + "UserID": "user_test@accenture.asgr", + "Name": "user test", + "Email": "user_test@accenture.com", + "MustChangePassword": false, + "ActiveFlag": true, + "LastSuccessfulLogin": "2023-02-23T10:14:11.443", + "IsAPIUser": false, + "NotificationEmailAddress": "user_test@accenture.com", + "DefaultBusinessUnit": 1111111, + "c__type": "User", + "c__AccountUserID": 700301950, + "c__IsLocked_readOnly": false, + "c__AssociatedBusinessUnits": [1111111, 9999999], + "c__RoleNamesGlobal": ["Administrator", "Content Creator", "Marketing Cloud Administrator"], + "c__TimeZoneName": "(GMT+01:00) Amsterdam, Berlin, Bern, Rome, Stockholm, Vienna *", + "c__LocaleCode": "en-GB" +} diff --git a/test/resources/1111111/user/retrieve-expected.md b/test/resources/1111111/user/retrieve-expected.md new file mode 100644 index 000000000..acc1becbd --- /dev/null +++ b/test/resources/1111111/user/retrieve-expected.md @@ -0,0 +1,21 @@ +# User Overview - testInstance + +## Users (1) + +| Name | Last successful Login | Active | Access Locked out | API User | Must change PW | Default BU | BU Access | Roles | Login | ID | Key | E-Mail | Notification E-Mail | Timezone | SFMC Locale | Modified Date | Modified By | Created Date | +| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | +| user test | 96 days | ✓ | - | - | - | <nobr>_ParentBU_ (1111111)</nobr> | <nobr>_ParentBU_ (1111111)</nobr>,<br> <nobr>testBU (9999999)</nobr> | <nobr>Administrator,</nobr><br> <nobr>Content Creator,</nobr><br> <nobr>Marketing Cloud Administrator</nobr> | user_test@accenture.asgr | 700301950 | testExisting_user | user_test@accenture.com | user_test@accenture.com | GMT+01:00 | en-GB | 2022-06-21 01:43:02.64 | 123456 | 2019-09-06 01:59:07.097 | + + +## Inactivated Users (1) + +| Name | Last successful Login | Active | Access Locked out | API User | Must change PW | Default BU | BU Access | Roles | Login | ID | Key | E-Mail | Notification E-Mail | Timezone | SFMC Locale | Modified Date | Modified By | Created Date | +| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | +| user test-inactive | 96 days | - | - | - | - | <nobr>_ParentBU_ (1111111)</nobr> | <nobr>_ParentBU_ (1111111)</nobr> | <nobr>Administrator,</nobr><br> <nobr>Content Creator,</nobr><br> <nobr>Marketing Cloud Administrator</nobr> | user_test-inactive@accenture.asgr | 700301951 | testExisting_user_inactive | user_test-inactive@accenture.com | user_test-inactive@accenture.com | GMT+01:00 | en-GB | 2022-06-21 01:43:02.64 | 123456 | 2019-09-06 01:59:07.097 | + + +## Installed Packages (1) + +| Name | Last successful Login | Active | Access Locked out | API User | Must change PW | Default BU | BU Access | Roles | Login | ID | Key | E-Mail | Notification E-Mail | Timezone | SFMC Locale | Modified Date | Modified By | Created Date | +| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | +| igopredictiveemail app user | never | ✓ | - | ✓ | - | <nobr>_ParentBU_ (1111111)</nobr> | <nobr>_ParentBU_ (1111111)</nobr> | <nobr></nobr> | 20f2d94a-9a7d-4580-9fb6-c36a1ce32fb9 | 7471228 | 45372cbb-06e0-438e-88d8-008981f7a18b | | | GMT+01:00 | en-GB | 2023-05-27 07:05:55.113 | n/a | 2016-07-22 11:52:37.42 | diff --git a/test/resources/1111111/user/template-expected.json b/test/resources/1111111/user/template-expected.json new file mode 100644 index 000000000..1f31d14fc --- /dev/null +++ b/test/resources/1111111/user/template-expected.json @@ -0,0 +1,16 @@ +{ + "Client": {}, + "CustomerKey": "{{{prefix}}}user", + "UserID": "user{{{suffix}}}@accenture.asgr", + "Name": "user test", + "Email": "user{{{suffix}}}@accenture.com", + "MustChangePassword": false, + "ActiveFlag": true, + "IsAPIUser": false, + "NotificationEmailAddress": "user{{{suffix}}}@accenture.com", + "DefaultBusinessUnit": "1111111", + "c__AssociatedBusinessUnits": ["1111111", "{{{mid}}}"], + "c__RoleNamesGlobal": ["Administrator", "Content Creator", "Marketing Cloud Administrator"], + "c__TimeZoneName": "(GMT+01:00) Amsterdam, Berlin, Bern, Rome, Stockholm, Vienna *", + "c__LocaleCode": "en-GB" +} diff --git a/test/resources/1111111/user/update-expected.json b/test/resources/1111111/user/update-expected.json new file mode 100644 index 000000000..b7df1c4b9 --- /dev/null +++ b/test/resources/1111111/user/update-expected.json @@ -0,0 +1,21 @@ +{ + "Client": { + "ModifiedBy": 123456 + }, + "CustomerKey": "testExisting_user", + "UserID": "user_test@accenture.asgr", + "Name": "user test", + "Email": "user_test@accenture.com", + "MustChangePassword": false, + "ActiveFlag": true, + "IsAPIUser": false, + "NotificationEmailAddress": "user_test@accenture.com", + "DefaultBusinessUnit": 9999999, + "c__type": "User", + "c__AccountUserID": 700301950, + "c__IsLocked_readOnly": false, + "c__AssociatedBusinessUnits": [9999999], + "c__RoleNamesGlobal": ["Administrator", "Distributed Sending User"], + "c__TimeZoneName": "(GMT+01:00) Amsterdam, Berlin, Bern, Rome, Stockholm, Vienna *", + "c__LocaleCode": "en-GB" +} diff --git a/test/resources/9999999/accountUser/retrieve-response.xml b/test/resources/9999999/accountUser/retrieve-response.xml new file mode 100644 index 000000000..82b6c867f --- /dev/null +++ b/test/resources/9999999/accountUser/retrieve-response.xml @@ -0,0 +1,104 @@ +<?xml version="1.0" encoding="utf-8"?> +<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:xsd="http://www.w3.org/2001/XMLSchema" + xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing" + xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" + xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"> + <soap:Header> + <wsa:Action>RetrieveResponse</wsa:Action> + <wsa:MessageID>urn:uuid:18989827-614e-4b4b-833a-ca06d03565a3</wsa:MessageID> + <wsa:RelatesTo>urn:uuid:84c999df-4607-4423-8f68-77a0ebf4db2f</wsa:RelatesTo> + <wsa:To>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</wsa:To> + <wsse:Security> + <wsu:Timestamp wsu:Id="Timestamp-7515cb13-8659-4ef9-86ba-b67d78e3e566"> + <wsu:Created>2024-09-25T16:43:14Z</wsu:Created> + <wsu:Expires>2024-09-25T16:48:14Z</wsu:Expires> + </wsu:Timestamp> + </wsse:Security> + </soap:Header> + <soap:Body> + <RetrieveResponseMsg xmlns="http://exacttarget.com/wsdl/partnerAPI"> + <OverallStatus>OK</OverallStatus> + <RequestID>f346a727-d497-4f83-9559-77854ecf0be3</RequestID> + <Results xsi:type="AccountUser"> + <Client> + <ID>9999999</ID> + <ModifiedBy>700301950</ModifiedBy> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2024-03-06T07:46:36.397</CreatedDate> + <ModifiedDate>2024-09-04T06:41:51.233</ModifiedDate> + <ID>700301950</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>99b4a407-0efa-4f9e-9dd5-af7ace87e634</CustomerKey> + <AccountUserID>700301950</AccountUserID> + <UserID>joern.berkefeld@accenture.com</UserID> + <Name>Jörn Berkefeld</Name> + <Email>joern.berkefeld@accenture.com</Email> + <MustChangePassword>false</MustChangePassword> + <ActiveFlag>true</ActiveFlag> + <Delete>0</Delete> + <LastSuccessfulLogin>2024-09-25T09:07:52.743</LastSuccessfulLogin> + <IsAPIUser>false</IsAPIUser> + <NotificationEmailAddress>joern.berkefeld@accenture.com</NotificationEmailAddress> + <IsLocked>false</IsLocked> + <DefaultBusinessUnit>510007949</DefaultBusinessUnit> + <Locale> + <PartnerKey xsi:nil="true" /> + <ObjectID xsi:nil="true" /> + <LocaleCode>en-US</LocaleCode> + </Locale> + <TimeZone> + <PartnerKey xsi:nil="true" /> + <ID>5</ID> + <ObjectID xsi:nil="true" /> + <Name>(GMT+01:00) Amsterdam, Berlin, Bern, Rome, Stockholm, Vienna</Name> + </TimeZone> + <DefaultBusinessUnitObject> + <PartnerKey xsi:nil="true" /> + <ID>9999999</ID> + <ObjectID xsi:nil="true" /> + <AccountType>None</AccountType> + <Subscription xsi:nil="true" /> + </DefaultBusinessUnitObject> + <Roles> + <Role> + <Client> + <ID>9999999</ID> + <CreatedBy>500000009</CreatedBy> + <ModifiedBy>500000009</ModifiedBy> + <EnterpriseID>9999999</EnterpriseID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2021-06-21T17:55:14.7</CreatedDate> + <ModifiedDate>2021-06-21T17:55:14.7</ModifiedDate> + <ObjectID>f35c8ecf-b9d2-eb11-b83e-f40343c95998</ObjectID> + <CustomerKey>SYS_DEF_ADMIN</CustomerKey> + <Name>Administrator</Name> + <Description>Administrator</Description> + <IsPrivate>false</IsPrivate> + <IsSystemDefined>true</IsSystemDefined> + </Role> + <Role> + <Client> + <ID>0</ID> + <CreatedBy>0</CreatedBy> + <ModifiedBy>0</ModifiedBy> + <EnterpriseID>0</EnterpriseID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2012-02-21T02:09:19.983</CreatedDate> + <ModifiedDate>2013-12-23T16:48:50.533</ModifiedDate> + <ObjectID>63a50610-315c-e111-beee-8e001800001f</ObjectID> + <CustomerKey>SYS_DEF_IMHADMIN</CustomerKey> + <Name>Marketing Cloud Administrator</Name> + <Description>Assign Marketing Cloud roles to users and manage Mobile, Social and Sites Channels, Hub Apps and Marketing Cloud Tools</Description> + <IsPrivate>false</IsPrivate> + <IsSystemDefined>true</IsSystemDefined> + </Role> + </Roles> + </Results> + </RetrieveResponseMsg> + </soap:Body> +</soap:Envelope> diff --git a/test/resources/9999999/asset-deploy/block/testNew_asset_badExtension.bad-type-extension.json b/test/resources/9999999/asset-deploy/block/testNew_asset_badExtension.bad-type-extension.json new file mode 100644 index 000000000..6ca3b286b --- /dev/null +++ b/test/resources/9999999/asset-deploy/block/testNew_asset_badExtension.bad-type-extension.json @@ -0,0 +1,39 @@ +{ + "customerKey": "testNew_asset_badExtension", + "assetType": { + "name": "textblock", + "displayName": "Text Block" + }, + "fileProperties": { + "fileName": "testNew_asset_badExtension" + }, + "name": "testNew_asset_badExtension", + "description": "bla bla", + "owner": { + "email": "joern.berkefeld@accenture.com", + "name": "Jörn Berkefeld" + }, + "createdDate": "2022-10-14T08:54:26.643-06:00", + "createdBy": { + "email": "joern.berkefeld@accenture.com", + "name": "Jörn Berkefeld" + }, + "modifiedDate": "2024-05-06T07:18:33.787-06:00", + "modifiedBy": { + "name": "SFMC DEVOPS app user" + }, + "memberId": 1111111, + "status": { + "name": "Draft" + }, + "meta": { + "wrapperStyles": { + "mobile": { + "visible": true + } + } + }, + "availableViews": [], + "modelVersion": 2, + "r__folder_Path": "Content Builder" +} diff --git a/test/resources/9999999/asset-deploy/block/testNew_asset_badName_bad.asset-block-meta.json b/test/resources/9999999/asset-deploy/block/testNew_asset_badName_bad.asset-block-meta.json new file mode 100644 index 000000000..da7e8de39 --- /dev/null +++ b/test/resources/9999999/asset-deploy/block/testNew_asset_badName_bad.asset-block-meta.json @@ -0,0 +1,39 @@ +{ + "customerKey": "testNew_asset_badName", + "assetType": { + "name": "textblock", + "displayName": "Text Block" + }, + "fileProperties": { + "fileName": "testNew_asset_badName" + }, + "name": "testNew_asset_badName", + "description": "bla bla", + "owner": { + "email": "joern.berkefeld@accenture.com", + "name": "Jörn Berkefeld" + }, + "createdDate": "2022-10-14T08:54:26.643-06:00", + "createdBy": { + "email": "joern.berkefeld@accenture.com", + "name": "Jörn Berkefeld" + }, + "modifiedDate": "2024-05-06T07:18:33.787-06:00", + "modifiedBy": { + "name": "SFMC DEVOPS app user" + }, + "memberId": 1111111, + "status": { + "name": "Draft" + }, + "meta": { + "wrapperStyles": { + "mobile": { + "visible": true + } + } + }, + "availableViews": [], + "modelVersion": 2, + "r__folder_Path": "Content Builder" +} diff --git a/test/resources/9999999/asset-deploy2/block/testBlacklist_asset_htmlblock.asset-block-meta.html b/test/resources/9999999/asset-deploy2/block/testBlacklist_asset_htmlblock.asset-block-meta.html new file mode 100644 index 000000000..18ecdcb79 --- /dev/null +++ b/test/resources/9999999/asset-deploy2/block/testBlacklist_asset_htmlblock.asset-block-meta.html @@ -0,0 +1 @@ +<html></html> diff --git a/test/resources/9999999/asset-deploy2/block/testBlacklist_asset_htmlblock.asset-block-meta.json b/test/resources/9999999/asset-deploy2/block/testBlacklist_asset_htmlblock.asset-block-meta.json new file mode 100644 index 000000000..63906fa68 --- /dev/null +++ b/test/resources/9999999/asset-deploy2/block/testBlacklist_asset_htmlblock.asset-block-meta.json @@ -0,0 +1,39 @@ +{ + "customerKey": "testBlacklist_asset_htmlblock", + "assetType": { + "name": "textblock", + "displayName": "Text Block" + }, + "fileProperties": { + "fileName": "testBlacklist_asset_htmlblock" + }, + "name": "testBlacklist_asset_htmlblock", + "description": "bla bla", + "owner": { + "email": "joern.berkefeld@accenture.com", + "name": "Jörn Berkefeld" + }, + "createdDate": "2022-10-14T08:54:26.643-06:00", + "createdBy": { + "email": "joern.berkefeld@accenture.com", + "name": "Jörn Berkefeld" + }, + "modifiedDate": "2024-05-06T07:18:33.787-06:00", + "modifiedBy": { + "name": "SFMC DEVOPS app user" + }, + "memberId": 9999999, + "status": { + "name": "Draft" + }, + "meta": { + "wrapperStyles": { + "mobile": { + "visible": true + } + } + }, + "availableViews": [], + "modelVersion": 2, + "r__folder_Path": "Content Builder" +} diff --git a/test/resources/9999999/asset-slashfolder-deploy/block/test_slash.asset-block-meta.html b/test/resources/9999999/asset-slashfolder-deploy/block/test_slash.asset-block-meta.html new file mode 100644 index 000000000..a8e8a44e6 --- /dev/null +++ b/test/resources/9999999/asset-slashfolder-deploy/block/test_slash.asset-block-meta.html @@ -0,0 +1,12 @@ +<table + cellpadding="0" + cellspacing="0" + width="100%" + role="presentation" + style="min-width: 100%" + class="stylingblock-content-wrapper" +> + <tr> + <td class="stylingblock-content-wrapper camarker-inner">test</td> + </tr> +</table> diff --git a/test/resources/9999999/asset-slashfolder-deploy/block/test_slash.asset-block-meta.json b/test/resources/9999999/asset-slashfolder-deploy/block/test_slash.asset-block-meta.json new file mode 100644 index 000000000..f7c664638 --- /dev/null +++ b/test/resources/9999999/asset-slashfolder-deploy/block/test_slash.asset-block-meta.json @@ -0,0 +1,29 @@ +{ + "customerKey": "test_slash", + "assetType": { + "name": "htmlblock", + "displayName": "HTML Block" + }, + "fileProperties": { + "fileName": "test_slash" + }, + "name": "test_slash", + "createdBy": {}, + "modifiedBy": {}, + "memberId": "9999999", + "status": { + "name": "Draft" + }, + "design": "", + "meta": { + "wrapperStyles": { + "mobile": { + "visible": true + }, + "styling": {} + } + }, + "availableViews": [], + "modelVersion": 2, + "r__folder_Path": "Content Builder/bla∕blub" +} diff --git a/test/resources/9999999/asset/build-asset_htmlblock-expected.html b/test/resources/9999999/asset/build-asset_htmlblock-expected.html new file mode 100644 index 000000000..063fa056b --- /dev/null +++ b/test/resources/9999999/asset/build-asset_htmlblock-expected.html @@ -0,0 +1,23 @@ +<table + cellpadding="0" + cellspacing="0" + width="100%" + role="presentation" + style="min-width: 100%; " + class="stylingblock-content-wrapper" +> + <tr> + <td class="stylingblock-content-wrapper camarker-inner"> + <div>my 1st html</div> +%%[ + /* my ampscript */ +]%% +<script runat="server"> + // my ssjs +</script> + + <div>my 2nd html</div> + <div>%%=ContentBlockById(1295065)=%%</div> + </td> + </tr> +</table> diff --git a/test/resources/9999999/asset/build-asset_htmlblock-expected.json b/test/resources/9999999/asset/build-asset_htmlblock-expected.json new file mode 100644 index 000000000..419ee4c9f --- /dev/null +++ b/test/resources/9999999/asset/build-asset_htmlblock-expected.json @@ -0,0 +1,29 @@ +{ + "assetType": { + "displayName": "HTML Block", + "name": "htmlblock" + }, + "availableViews": [], + "createdBy": {}, + "customerKey": "testTemplated_asset_htmlblock", + "design": "", + "fileProperties": { + "fileName": "testTemplated_asset_htmlblock-Mcdev-strips-content" + }, + "memberId": "1111111", + "meta": { + "wrapperStyles": { + "mobile": { + "visible": true + }, + "styling": {} + } + }, + "modelVersion": 2, + "modifiedBy": {}, + "name": "testTemplated_asset_htmlblock-Mcdev-strips-content", + "r__folder_Path": "Content Builder", + "status": { + "name": "Draft" + } +} diff --git a/test/resources/9999999/asset/build-templatebasedemail-expected.json b/test/resources/9999999/asset/build-templatebasedemail-expected.json new file mode 100644 index 000000000..46ae6216b --- /dev/null +++ b/test/resources/9999999/asset/build-templatebasedemail-expected.json @@ -0,0 +1,145 @@ +{ + "customerKey": "testTemplated_asset_templatebasedemail", + "contentType": "application/vnd.etmc.email.Message; kind=template", + "assetType": { "name": "templatebasedemail", "displayName": "Template-Based Email" }, + "name": " testTemplated_asset_templatebasedemail", + "createdBy": {}, + "modifiedBy": {}, + "memberId": "1111111", + "status": { "name": "Draft" }, + "views": { + "subjectline": { + "contentType": "application/vnd.etmc.email.View; kind=subjectline", + "thumbnail": {}, + "content": "my subject line", + "availableViews": [], + "data": { "email": { "options": { "generateFrom": null } } }, + "modelVersion": 2 + }, + "preheader": { + "contentType": "application/vnd.etmc.email.View; kind=preheader", + "thumbnail": {}, + "availableViews": [], + "data": { "email": { "options": { "generateFrom": null } } }, + "modelVersion": 2 + }, + "text": { + "thumbnail": {}, + "availableViews": [], + "data": { "email": { "options": { "generateFrom": "html" } } }, + "generateFrom": "html", + "modelVersion": 2 + }, + "viewAsAWebPage": { + "thumbnail": {}, + "availableViews": [], + "data": { "email": { "options": { "generateFrom": null } } }, + "modelVersion": 2 + }, + "subscriptioncenter": { + "thumbnail": {}, + "availableViews": [], + "data": { "email": { "options": { "generateFrom": null } } }, + "modelVersion": 2 + }, + "forwardHTML": { + "thumbnail": {}, + "availableViews": [], + "data": { "email": { "options": { "generateFrom": null } } }, + "modelVersion": 2 + }, + "forwardText": { + "thumbnail": {}, + "availableViews": [], + "data": { "email": { "options": { "generateFrom": null } } }, + "modelVersion": 2 + }, + "html": { + "thumbnail": {}, + "availableViews": [], + "slots": { + "banner": { + "content": "<div data-type=\"block\" data-key=\"5v1vodxyvz\"></div><div data-type=\"block\" data-key=\"c2m5fa0c6ym\"></div><div data-type=\"block\" data-key=\"cdsuxkm6kyt\"></div><div data-type=\"block\" data-key=\"7xogokk59k\"></div><div data-type=\"block\" data-key=\"sf47b6tjg2m\"></div><div data-type=\"block\" data-key=\"hy6ik0ftsb4\"></div><div data-type=\"block\" data-key=\"csscq2x1lpr\"></div>", + "design": "<p style=\"font-family:Arial;color:#ccc;font-size:12px;text-align:center;vertical-align:middle;font-weight:bold;height:150px;display:flex;flex-direction:column;justify-content:center;padding:10px;margin:0;border: #cccccc dashed 1px;\">Drop blocks or content here</p>", + "availableViews": [], + "blocks": { + "hy6ik0ftsb4": { + "r__asset_key": "testTemplated_asset_htmlblock", + "assetType": { + "id": 197, + "name": "htmlblock", + "displayName": "HTML Block" + }, + "fileProperties": { + "fileName": "testTemplated_asset_htmlblock-Mcdev-strips-content" + }, + "name": "testTemplated_asset_htmlblock-Mcdev-strips-content", + "owner": { + "id": 700301950, + "email": "joern.berkefeld@accenture.com", + "name": "Jörn Berkefeld (ASGR)", + "userId": "700301950" + }, + "createdDate": "2024-01-08T08:26:58.277-06:00", + "createdBy": { + "id": 700301950, + "email": "joern.berkefeld@accenture.com", + "name": "Jörn Berkefeld (ASGR)", + "userId": "700301950" + }, + "modifiedDate": "2024-01-08T08:28:01.6-06:00", + "modifiedBy": { + "id": 700301950, + "email": "joern.berkefeld@accenture.com", + "name": "Jörn Berkefeld (ASGR)", + "userId": "700301950" + }, + "enterpriseId": 99991999, + "memberId": 99991999, + "status": { + "id": 1, + "name": "Draft" + }, + "design": "", + "meta": { + "wrapperStyles": { + "mobile": { + "visible": true + }, + "styling": {} + } + }, + "availableViews": [], + "modelVersion": 2 + } + }, + "data": { + "email": { + "options": {} + } + }, + "modelVersion": 2 + } + }, + "template": { + "meta": { "contentHash": -166410261 }, + "r__asset_key": "testTemplated_asset_template" + }, + "data": { "email": { "options": { "generateFrom": null } } }, + "modelVersion": 2 + } + }, + "availableViews": [ + "subjectline", + "preheader", + "text", + "viewAsAWebPage", + "subscriptioncenter", + "forwardHTML", + "forwardText", + "html" + ], + "data": { "email": { "options": { "characterEncoding": "utf-8" } } }, + "modelVersion": 2, + "r__folder_Path": "Content Builder" +} diff --git a/test/resources/9999999/asset/build-templatebasedemail-html-expected.html b/test/resources/9999999/asset/build-templatebasedemail-html-expected.html new file mode 100644 index 000000000..5ae3b84c4 --- /dev/null +++ b/test/resources/9999999/asset/build-templatebasedemail-html-expected.html @@ -0,0 +1,20 @@ +<a href="%%ftaf_url%%" + ><img + src="https://www.exacttarget.com/members/newsletters/gfx/forwardafriendicon.gif" + border="0" /></a +><a href="%%profile_center_url%%" alias="Update Profile">Update Profile</a> +<table cellpadding="2" cellspacing="0" width="600" id="Table5" border="0"> + <tr> + <td> + <font face="verdana" size="1" color="#444444" + >This email was sent by: <b>%%Member_Busname%%</b><br />%%Member_Addr%% + %%Member_City%%, %%Member_State%%, %%Member_PostalCode%%, %%Member_Country%%<br /><br + /></font> + </td> + </tr> +</table> +<a href="%%subscription_center_url%%" alias="Manage Subscriptions">Manage Subscriptions</a +><img src="https://www.exacttarget.com/images/Powered_By_1206.jpg" border="0" /><custom + name="opencounter" + type="tracking" +/> diff --git a/test/resources/9999999/asset/build-templatebasedemail-preheader-expected.amp b/test/resources/9999999/asset/build-templatebasedemail-preheader-expected.amp new file mode 100644 index 000000000..6a942e2ce --- /dev/null +++ b/test/resources/9999999/asset/build-templatebasedemail-preheader-expected.amp @@ -0,0 +1 @@ +my custom preheader text diff --git a/test/resources/9999999/asset/create-expected.json b/test/resources/9999999/asset/create-expected.json new file mode 100644 index 000000000..b76355d23 --- /dev/null +++ b/test/resources/9999999/asset/create-expected.json @@ -0,0 +1,18 @@ +{ + "customerKey": "testNew_asset-9999999", + "assetType": { "name": "textblock", "displayName": "Text Block" }, + "fileProperties": { "fileName": "testNew_asset" }, + "name": "testNew_asset", + "description": "bla bla", + "owner": { "email": "", "name": "SFMC DEVOPS app user" }, + "createdDate": "2024-05-07T05:08:46.927-06:00", + "createdBy": { "email": "", "name": "SFMC DEVOPS app user" }, + "modifiedDate": "2024-05-07T05:08:46.927-06:00", + "modifiedBy": { "email": "", "name": "SFMC DEVOPS app user" }, + "memberId": 9999999, + "status": { "name": "Draft" }, + "meta": { "wrapperStyles": { "mobile": { "visible": true } } }, + "availableViews": [], + "modelVersion": 2, + "r__folder_Path": "Content Builder" +} diff --git a/test/resources/9999999/asset/resolveId-1234-notFound-expected.json b/test/resources/9999999/asset/resolveId-1234-notFound-expected.json new file mode 100644 index 000000000..4d8a1e072 --- /dev/null +++ b/test/resources/9999999/asset/resolveId-1234-notFound-expected.json @@ -0,0 +1 @@ +{ "error": "id not found" } diff --git a/test/resources/9999999/asset/resolveId-1295064-noPath-expected.json b/test/resources/9999999/asset/resolveId-1295064-noPath-expected.json new file mode 100644 index 000000000..8ad5a40d6 --- /dev/null +++ b/test/resources/9999999/asset/resolveId-1295064-noPath-expected.json @@ -0,0 +1,8 @@ +{ + "folder": "Content Builder", + "isShared": false, + "key": "testExisting_asset_htmlblock", + "mid": 9999999, + "name": "testExisting_asset_htmlblock-Mcdev-strips-content", + "path": "./retrieve/testInstance/testBU/asset/block/testExisting_asset_htmlblock.asset-block-meta.html" +} diff --git a/test/resources/9999999/asset/resolveId-1295064-withPath-expected.json b/test/resources/9999999/asset/resolveId-1295064-withPath-expected.json new file mode 100644 index 000000000..8ad5a40d6 --- /dev/null +++ b/test/resources/9999999/asset/resolveId-1295064-withPath-expected.json @@ -0,0 +1,8 @@ +{ + "folder": "Content Builder", + "isShared": false, + "key": "testExisting_asset_htmlblock", + "mid": 9999999, + "name": "testExisting_asset_htmlblock-Mcdev-strips-content", + "path": "./retrieve/testInstance/testBU/asset/block/testExisting_asset_htmlblock.asset-block-meta.html" +} diff --git a/test/resources/9999999/asset/retrieve-templatebasedemail-expected.json b/test/resources/9999999/asset/retrieve-templatebasedemail-expected.json new file mode 100644 index 000000000..7e16bde1e --- /dev/null +++ b/test/resources/9999999/asset/retrieve-templatebasedemail-expected.json @@ -0,0 +1,148 @@ +{ + "customerKey": "testExisting_asset_templatebasedemail", + "contentType": "application/vnd.etmc.email.Message; kind=template", + "assetType": { "name": "templatebasedemail", "displayName": "Template-Based Email" }, + "name": " testExisting_asset_templatebasedemail", + "owner": { "email": "joern.berkefeld@accenture.com", "name": "Jörn Berkefeld" }, + "createdDate": "2024-04-22T06:36:03.117-06:00", + "createdBy": { "email": "joern.berkefeld@accenture.com", "name": "Jörn Berkefeld" }, + "modifiedDate": "2024-05-13T07:15:29.77-06:00", + "modifiedBy": { "name": "IDE - joern.berkefeld app user" }, + "memberId": 9999999, + "status": { "name": "Draft" }, + "views": { + "subjectline": { + "contentType": "application/vnd.etmc.email.View; kind=subjectline", + "thumbnail": {}, + "content": "my subject line", + "availableViews": [], + "data": { "email": { "options": { "generateFrom": null } } }, + "modelVersion": 2 + }, + "preheader": { + "contentType": "application/vnd.etmc.email.View; kind=preheader", + "thumbnail": {}, + "availableViews": [], + "data": { "email": { "options": { "generateFrom": null } } }, + "modelVersion": 2 + }, + "text": { + "thumbnail": {}, + "availableViews": [], + "data": { "email": { "options": { "generateFrom": "html" } } }, + "generateFrom": "html", + "modelVersion": 2 + }, + "viewAsAWebPage": { + "thumbnail": {}, + "availableViews": [], + "data": { "email": { "options": { "generateFrom": null } } }, + "modelVersion": 2 + }, + "subscriptioncenter": { + "thumbnail": {}, + "availableViews": [], + "data": { "email": { "options": { "generateFrom": null } } }, + "modelVersion": 2 + }, + "forwardHTML": { + "thumbnail": {}, + "availableViews": [], + "data": { "email": { "options": { "generateFrom": null } } }, + "modelVersion": 2 + }, + "forwardText": { + "thumbnail": {}, + "availableViews": [], + "data": { "email": { "options": { "generateFrom": null } } }, + "modelVersion": 2 + }, + "html": { + "thumbnail": {}, + "availableViews": [], + "slots": { + "banner": { + "content": "<div data-type=\"block\" data-key=\"5v1vodxyvz\"></div><div data-type=\"block\" data-key=\"c2m5fa0c6ym\"></div><div data-type=\"block\" data-key=\"cdsuxkm6kyt\"></div><div data-type=\"block\" data-key=\"7xogokk59k\"></div><div data-type=\"block\" data-key=\"sf47b6tjg2m\"></div><div data-type=\"block\" data-key=\"hy6ik0ftsb4\"></div><div data-type=\"block\" data-key=\"csscq2x1lpr\"></div>", + "design": "<p style=\"font-family:Arial;color:#ccc;font-size:12px;text-align:center;vertical-align:middle;font-weight:bold;height:150px;display:flex;flex-direction:column;justify-content:center;padding:10px;margin:0;border: #cccccc dashed 1px;\">Drop blocks or content here</p>", + "availableViews": [], + "blocks": { + "hy6ik0ftsb4": { + "r__asset_key": "testExisting_asset_htmlblock", + "assetType": { + "id": 197, + "name": "htmlblock", + "displayName": "HTML Block" + }, + "fileProperties": { + "fileName": "testExisting_asset_htmlblock-Mcdev-strips-content" + }, + "name": "testExisting_asset_htmlblock-Mcdev-strips-content", + "owner": { + "id": 700301950, + "email": "joern.berkefeld@accenture.com", + "name": "Jörn Berkefeld (ASGR)", + "userId": "700301950" + }, + "createdDate": "2024-01-08T08:26:58.277-06:00", + "createdBy": { + "id": 700301950, + "email": "joern.berkefeld@accenture.com", + "name": "Jörn Berkefeld (ASGR)", + "userId": "700301950" + }, + "modifiedDate": "2024-01-08T08:28:01.6-06:00", + "modifiedBy": { + "id": 700301950, + "email": "joern.berkefeld@accenture.com", + "name": "Jörn Berkefeld (ASGR)", + "userId": "700301950" + }, + "enterpriseId": 99991999, + "memberId": 99991999, + "status": { + "id": 1, + "name": "Draft" + }, + "design": "", + "meta": { + "wrapperStyles": { + "mobile": { + "visible": true + }, + "styling": {} + } + }, + "availableViews": [], + "modelVersion": 2 + } + }, + "data": { + "email": { + "options": {} + } + }, + "modelVersion": 2 + } + }, + "template": { + "meta": { "contentHash": -166410261 }, + "r__asset_key": "testExisting_asset_template" + }, + "data": { "email": { "options": { "generateFrom": null } } }, + "modelVersion": 2 + } + }, + "availableViews": [ + "subjectline", + "preheader", + "text", + "viewAsAWebPage", + "subscriptioncenter", + "forwardHTML", + "forwardText", + "html" + ], + "data": { "email": { "options": { "characterEncoding": "utf-8" } } }, + "modelVersion": 2, + "r__folder_Path": "Content Builder" +} diff --git a/test/resources/9999999/asset/retrieve-templatebasedemail-html-expected.html b/test/resources/9999999/asset/retrieve-templatebasedemail-html-expected.html new file mode 100644 index 000000000..5ae3b84c4 --- /dev/null +++ b/test/resources/9999999/asset/retrieve-templatebasedemail-html-expected.html @@ -0,0 +1,20 @@ +<a href="%%ftaf_url%%" + ><img + src="https://www.exacttarget.com/members/newsletters/gfx/forwardafriendicon.gif" + border="0" /></a +><a href="%%profile_center_url%%" alias="Update Profile">Update Profile</a> +<table cellpadding="2" cellspacing="0" width="600" id="Table5" border="0"> + <tr> + <td> + <font face="verdana" size="1" color="#444444" + >This email was sent by: <b>%%Member_Busname%%</b><br />%%Member_Addr%% + %%Member_City%%, %%Member_State%%, %%Member_PostalCode%%, %%Member_Country%%<br /><br + /></font> + </td> + </tr> +</table> +<a href="%%subscription_center_url%%" alias="Manage Subscriptions">Manage Subscriptions</a +><img src="https://www.exacttarget.com/images/Powered_By_1206.jpg" border="0" /><custom + name="opencounter" + type="tracking" +/> diff --git a/test/resources/9999999/asset/retrieve-templatebasedemail-preheader-expected.amp b/test/resources/9999999/asset/retrieve-templatebasedemail-preheader-expected.amp new file mode 100644 index 000000000..6a942e2ce --- /dev/null +++ b/test/resources/9999999/asset/retrieve-templatebasedemail-preheader-expected.amp @@ -0,0 +1 @@ +my custom preheader text diff --git a/test/resources/9999999/asset/template-emailTemplate-expected.json b/test/resources/9999999/asset/template-emailTemplate-expected.json new file mode 100644 index 000000000..f657557d5 --- /dev/null +++ b/test/resources/9999999/asset/template-emailTemplate-expected.json @@ -0,0 +1,20 @@ +{ + "assetType": { + "displayName": "Template", + "name": "template" + }, + "availableViews": [], + "createdBy": {}, + "customerKey": "{{{prefix}}}asset_template", + "fileProperties": { + "fileName": " {{{prefix}}}asset_template" + }, + "memberId": "510009653", + "modelVersion": 2, + "modifiedBy": {}, + "name": " {{{prefix}}}asset_template", + "r__folder_Path": "Content Builder", + "status": { + "name": "Draft" + } +} diff --git a/test/resources/9999999/asset/template-templatebasedemail-expected.json b/test/resources/9999999/asset/template-templatebasedemail-expected.json new file mode 100644 index 000000000..28fae2487 --- /dev/null +++ b/test/resources/9999999/asset/template-templatebasedemail-expected.json @@ -0,0 +1,145 @@ +{ + "customerKey": "{{{prefix}}}asset_templatebasedemail", + "contentType": "application/vnd.etmc.email.Message; kind=template", + "assetType": { "name": "templatebasedemail", "displayName": "Template-Based Email" }, + "name": " {{{prefix}}}asset_templatebasedemail", + "createdBy": {}, + "modifiedBy": {}, + "memberId": "{{{mid}}}", + "status": { "name": "Draft" }, + "views": { + "subjectline": { + "contentType": "application/vnd.etmc.email.View; kind=subjectline", + "thumbnail": {}, + "content": "my subject line", + "availableViews": [], + "data": { "email": { "options": { "generateFrom": null } } }, + "modelVersion": 2 + }, + "preheader": { + "contentType": "application/vnd.etmc.email.View; kind=preheader", + "thumbnail": {}, + "availableViews": [], + "data": { "email": { "options": { "generateFrom": null } } }, + "modelVersion": 2 + }, + "text": { + "thumbnail": {}, + "availableViews": [], + "data": { "email": { "options": { "generateFrom": "html" } } }, + "generateFrom": "html", + "modelVersion": 2 + }, + "viewAsAWebPage": { + "thumbnail": {}, + "availableViews": [], + "data": { "email": { "options": { "generateFrom": null } } }, + "modelVersion": 2 + }, + "subscriptioncenter": { + "thumbnail": {}, + "availableViews": [], + "data": { "email": { "options": { "generateFrom": null } } }, + "modelVersion": 2 + }, + "forwardHTML": { + "thumbnail": {}, + "availableViews": [], + "data": { "email": { "options": { "generateFrom": null } } }, + "modelVersion": 2 + }, + "forwardText": { + "thumbnail": {}, + "availableViews": [], + "data": { "email": { "options": { "generateFrom": null } } }, + "modelVersion": 2 + }, + "html": { + "thumbnail": {}, + "availableViews": [], + "slots": { + "banner": { + "content": "<div data-type=\"block\" data-key=\"5v1vodxyvz\"></div><div data-type=\"block\" data-key=\"c2m5fa0c6ym\"></div><div data-type=\"block\" data-key=\"cdsuxkm6kyt\"></div><div data-type=\"block\" data-key=\"7xogokk59k\"></div><div data-type=\"block\" data-key=\"sf47b6tjg2m\"></div><div data-type=\"block\" data-key=\"hy6ik0ftsb4\"></div><div data-type=\"block\" data-key=\"csscq2x1lpr\"></div>", + "design": "<p style=\"font-family:Arial;color:#ccc;font-size:12px;text-align:center;vertical-align:middle;font-weight:bold;height:150px;display:flex;flex-direction:column;justify-content:center;padding:10px;margin:0;border: #cccccc dashed 1px;\">Drop blocks or content here</p>", + "availableViews": [], + "blocks": { + "hy6ik0ftsb4": { + "r__asset_key": "{{{prefix}}}asset_htmlblock", + "assetType": { + "id": 197, + "name": "htmlblock", + "displayName": "HTML Block" + }, + "fileProperties": { + "fileName": "{{{prefix}}}asset_htmlblock-Mcdev-strips-content" + }, + "name": "{{{prefix}}}asset_htmlblock-Mcdev-strips-content", + "owner": { + "id": 700301950, + "email": "joern.berkefeld@accenture.com", + "name": "Jörn Berkefeld (ASGR)", + "userId": "700301950" + }, + "createdDate": "2024-01-08T08:26:58.277-06:00", + "createdBy": { + "id": 700301950, + "email": "joern.berkefeld@accenture.com", + "name": "Jörn Berkefeld (ASGR)", + "userId": "700301950" + }, + "modifiedDate": "2024-01-08T08:28:01.6-06:00", + "modifiedBy": { + "id": 700301950, + "email": "joern.berkefeld@accenture.com", + "name": "Jörn Berkefeld (ASGR)", + "userId": "700301950" + }, + "enterpriseId": 99991999, + "memberId": 99991999, + "status": { + "id": 1, + "name": "Draft" + }, + "design": "", + "meta": { + "wrapperStyles": { + "mobile": { + "visible": true + }, + "styling": {} + } + }, + "availableViews": [], + "modelVersion": 2 + } + }, + "data": { + "email": { + "options": {} + } + }, + "modelVersion": 2 + } + }, + "template": { + "meta": { "contentHash": -166410261 }, + "r__asset_key": "{{{prefix}}}asset_template" + }, + "data": { "email": { "options": { "generateFrom": null } } }, + "modelVersion": 2 + } + }, + "availableViews": [ + "subjectline", + "preheader", + "text", + "viewAsAWebPage", + "subscriptioncenter", + "forwardHTML", + "forwardText", + "html" + ], + "data": { "email": { "options": { "characterEncoding": "utf-8" } } }, + "modelVersion": 2, + "r__folder_Path": "Content Builder" +} diff --git a/test/resources/9999999/asset/template-templatebasedemail-html-expected.html b/test/resources/9999999/asset/template-templatebasedemail-html-expected.html new file mode 100644 index 000000000..5ae3b84c4 --- /dev/null +++ b/test/resources/9999999/asset/template-templatebasedemail-html-expected.html @@ -0,0 +1,20 @@ +<a href="%%ftaf_url%%" + ><img + src="https://www.exacttarget.com/members/newsletters/gfx/forwardafriendicon.gif" + border="0" /></a +><a href="%%profile_center_url%%" alias="Update Profile">Update Profile</a> +<table cellpadding="2" cellspacing="0" width="600" id="Table5" border="0"> + <tr> + <td> + <font face="verdana" size="1" color="#444444" + >This email was sent by: <b>%%Member_Busname%%</b><br />%%Member_Addr%% + %%Member_City%%, %%Member_State%%, %%Member_PostalCode%%, %%Member_Country%%<br /><br + /></font> + </td> + </tr> +</table> +<a href="%%subscription_center_url%%" alias="Manage Subscriptions">Manage Subscriptions</a +><img src="https://www.exacttarget.com/images/Powered_By_1206.jpg" border="0" /><custom + name="opencounter" + type="tracking" +/> diff --git a/test/resources/9999999/asset/template-templatebasedemail-preheader-expected.amp b/test/resources/9999999/asset/template-templatebasedemail-preheader-expected.amp new file mode 100644 index 000000000..6a942e2ce --- /dev/null +++ b/test/resources/9999999/asset/template-templatebasedemail-preheader-expected.amp @@ -0,0 +1 @@ +my custom preheader text diff --git a/test/resources/9999999/asset/template-testExisting_asset_htmlblock-expected.json b/test/resources/9999999/asset/template-testExisting_asset_htmlblock-expected.json new file mode 100644 index 000000000..f365586bf --- /dev/null +++ b/test/resources/9999999/asset/template-testExisting_asset_htmlblock-expected.json @@ -0,0 +1,29 @@ +{ + "assetType": { + "displayName": "HTML Block", + "name": "htmlblock" + }, + "availableViews": [], + "createdBy": {}, + "customerKey": "{{{prefix}}}asset_htmlblock", + "design": "", + "fileProperties": { + "fileName": "{{{prefix}}}asset_htmlblock-Mcdev-strips-content" + }, + "memberId": "{{{mid}}}", + "meta": { + "wrapperStyles": { + "mobile": { + "visible": true + }, + "styling": {} + } + }, + "modelVersion": 2, + "modifiedBy": {}, + "name": "{{{prefix}}}asset_htmlblock-Mcdev-strips-content", + "r__folder_Path": "Content Builder", + "status": { + "name": "Draft" + } +} diff --git a/test/resources/9999999/asset/testExisting_asset_htmlblock-retrieve-expected.html b/test/resources/9999999/asset/testExisting_asset_htmlblock-retrieve-expected.html new file mode 100644 index 000000000..063fa056b --- /dev/null +++ b/test/resources/9999999/asset/testExisting_asset_htmlblock-retrieve-expected.html @@ -0,0 +1,23 @@ +<table + cellpadding="0" + cellspacing="0" + width="100%" + role="presentation" + style="min-width: 100%; " + class="stylingblock-content-wrapper" +> + <tr> + <td class="stylingblock-content-wrapper camarker-inner"> + <div>my 1st html</div> +%%[ + /* my ampscript */ +]%% +<script runat="server"> + // my ssjs +</script> + + <div>my 2nd html</div> + <div>%%=ContentBlockById(1295065)=%%</div> + </td> + </tr> +</table> diff --git a/test/resources/9999999/asset/testExisting_asset_htmlblock-retrieve-expected.json b/test/resources/9999999/asset/testExisting_asset_htmlblock-retrieve-expected.json new file mode 100644 index 000000000..5ed7ebd4b --- /dev/null +++ b/test/resources/9999999/asset/testExisting_asset_htmlblock-retrieve-expected.json @@ -0,0 +1,41 @@ +{ + "customerKey": "testExisting_asset_htmlblock", + "assetType": { + "name": "htmlblock", + "displayName": "HTML Block" + }, + "fileProperties": { + "fileName": "testExisting_asset_htmlblock-Mcdev-strips-content" + }, + "name": "testExisting_asset_htmlblock-Mcdev-strips-content", + "owner": { + "email": "joern.berkefeld@accenture.com", + "name": "Jörn Berkefeld (ASGR)" + }, + "createdDate": "2024-01-08T08:26:58.277-06:00", + "createdBy": { + "email": "joern.berkefeld@accenture.com", + "name": "Jörn Berkefeld (ASGR)" + }, + "modifiedDate": "2024-01-08T08:28:01.6-06:00", + "modifiedBy": { + "email": "joern.berkefeld@accenture.com", + "name": "Jörn Berkefeld (ASGR)" + }, + "memberId": 9999999, + "status": { + "name": "Draft" + }, + "design": "", + "meta": { + "wrapperStyles": { + "mobile": { + "visible": true + }, + "styling": {} + } + }, + "availableViews": [], + "modelVersion": 2, + "r__folder_Path": "Content Builder" +} diff --git a/test/resources/9999999/asset/testExisting_asset_message-html-rcb-id-expected.html b/test/resources/9999999/asset/testExisting_asset_message-html-rcb-id-expected.html new file mode 100644 index 000000000..37ccf3a44 --- /dev/null +++ b/test/resources/9999999/asset/testExisting_asset_message-html-rcb-id-expected.html @@ -0,0 +1,33 @@ +<a href="%%ftaf_url%%" + ><img + src="https://www.exacttarget.com/members/newsletters/gfx/forwardafriendicon.gif" + border="0" /></a +><a href="%%profile_center_url%%" alias="Update Profile">Update Profile</a> +<table cellpadding="2" cellspacing="0" width="600" id="Table5" border="0"> + <tr> + <td> + <font face="verdana" size="1" color="#444444" + >This email was sent by: <b>%%Member_Busname%%</b + ><br />%%Member_Addr%% %%Member_City%%, %%Member_State%%, + %%Member_PostalCode%%, %%Member_Country%%<br /><br + /></font> + </td> + </tr> +</table> +<a href="%%subscription_center_url%%" alias="Manage Subscriptions" + >Manage Subscriptions</a +><img + src="https://www.exacttarget.com/images/Powered_By_1206.jpg" + border="0" +/><custom name="opencounter" type="tracking" /> %%= ContentBlockById(1295064) =%% +<script runat="server"> + Platform.Function.ContentBlockById(1295064); +</script> +%%= ContentBlockById(1295064) =%% +<script runat="server"> + Platform.Function.ContentBlockById(1295064); +</script> +%%= ContentBlockById(1295064) =%% +<script runat="server"> + Platform.Function.ContentBlockById(1295064); +</script> diff --git a/test/resources/9999999/asset/testExisting_asset_message-html-rcb-key-expected.html b/test/resources/9999999/asset/testExisting_asset_message-html-rcb-key-expected.html new file mode 100644 index 000000000..525389a12 --- /dev/null +++ b/test/resources/9999999/asset/testExisting_asset_message-html-rcb-key-expected.html @@ -0,0 +1,33 @@ +<a href="%%ftaf_url%%" + ><img + src="https://www.exacttarget.com/members/newsletters/gfx/forwardafriendicon.gif" + border="0" /></a +><a href="%%profile_center_url%%" alias="Update Profile">Update Profile</a> +<table cellpadding="2" cellspacing="0" width="600" id="Table5" border="0"> + <tr> + <td> + <font face="verdana" size="1" color="#444444" + >This email was sent by: <b>%%Member_Busname%%</b + ><br />%%Member_Addr%% %%Member_City%%, %%Member_State%%, + %%Member_PostalCode%%, %%Member_Country%%<br /><br + /></font> + </td> + </tr> +</table> +<a href="%%subscription_center_url%%" alias="Manage Subscriptions" + >Manage Subscriptions</a +><img + src="https://www.exacttarget.com/images/Powered_By_1206.jpg" + border="0" +/><custom name="opencounter" type="tracking" /> %%= ContentBlockByKey("testExisting_asset_htmlblock") =%% +<script runat="server"> + Platform.Function.ContentBlockByKey("testExisting_asset_htmlblock"); +</script> +%%= ContentBlockByKey("testExisting_asset_htmlblock") =%% +<script runat="server"> + Platform.Function.ContentBlockByKey("testExisting_asset_htmlblock"); +</script> +%%= ContentBlockByKey("testExisting_asset_htmlblock") =%% +<script runat="server"> + Platform.Function.ContentBlockByKey("testExisting_asset_htmlblock"); +</script> diff --git a/test/resources/9999999/asset/testExisting_asset_message-html-rcb-name-expected.html b/test/resources/9999999/asset/testExisting_asset_message-html-rcb-name-expected.html new file mode 100644 index 000000000..1bf9d9da6 --- /dev/null +++ b/test/resources/9999999/asset/testExisting_asset_message-html-rcb-name-expected.html @@ -0,0 +1,35 @@ +<a href="%%ftaf_url%%" + ><img + src="https://www.exacttarget.com/members/newsletters/gfx/forwardafriendicon.gif" + border="0" /></a +><a href="%%profile_center_url%%" alias="Update Profile">Update Profile</a> +<table cellpadding="2" cellspacing="0" width="600" id="Table5" border="0"> + <tr> + <td> + <font face="verdana" size="1" color="#444444" + >This email was sent by: <b>%%Member_Busname%%</b + ><br />%%Member_Addr%% %%Member_City%%, %%Member_State%%, + %%Member_PostalCode%%, %%Member_Country%%<br /><br + /></font> + </td> + </tr> +</table> +<a href="%%subscription_center_url%%" alias="Manage Subscriptions" + >Manage Subscriptions</a +><img + src="https://www.exacttarget.com/images/Powered_By_1206.jpg" + border="0" +/><custom name="opencounter" type="tracking" /> %%= ContentBlockByName("Content Builder\dont strip non ssjs content") =%% +<script runat="server"> + Platform.Function.ContentBlockByName("Content Builder\\dont strip non ssjs content"); +</script> +%%= ContentBlockByName("Content Builder\dont strip non ssjs content") =%% +<script runat="server"> + Platform.Function.ContentBlockByName("Content Builder\\dont strip non ssjs content"); +</script> +%%= ContentBlockByName("Content Builder\dont strip non ssjs content") =%% +<script runat="server"> + Platform.Function.ContentBlockByName( + "Content Builder\\dont strip non ssjs content" + ); +</script> diff --git a/test/resources/9999999/asset/testExisting_asset_message-preheader-rcb-id-expected.amp b/test/resources/9999999/asset/testExisting_asset_message-preheader-rcb-id-expected.amp new file mode 100644 index 000000000..1525776c7 --- /dev/null +++ b/test/resources/9999999/asset/testExisting_asset_message-preheader-rcb-id-expected.amp @@ -0,0 +1,4 @@ +%%= ContentBlockById(1295064) =%% <script runat="server"> +Platform.Function.ContentBlockById(1295064);</script>%%= ContentBlockById(1295065) =%% <script runat="server"> +Platform.Function.ContentBlockById(1295064);</script>%%= ContentBlockById(1295064) =%% <script runat="server"> +Platform.Function.ContentBlockById(1295064);</script> diff --git a/test/resources/9999999/asset/testExisting_asset_message-preheader-rcb-key-expected.amp b/test/resources/9999999/asset/testExisting_asset_message-preheader-rcb-key-expected.amp new file mode 100644 index 000000000..6484e800c --- /dev/null +++ b/test/resources/9999999/asset/testExisting_asset_message-preheader-rcb-key-expected.amp @@ -0,0 +1,4 @@ +%%= ContentBlockByKey("testExisting_asset_htmlblock") =%% <script runat="server"> +Platform.Function.ContentBlockByKey("testExisting_asset_htmlblock");</script>%%= ContentBlockByKey("testExisting_htmlblock1") =%% <script runat="server"> +Platform.Function.ContentBlockByKey("testExisting_asset_htmlblock");</script>%%= ContentBlockByKey("testExisting_asset_htmlblock") =%% <script runat="server"> +Platform.Function.ContentBlockByKey("testExisting_asset_htmlblock");</script> diff --git a/test/resources/9999999/asset/testExisting_asset_message-preheader-rcb-name-expected.amp b/test/resources/9999999/asset/testExisting_asset_message-preheader-rcb-name-expected.amp new file mode 100644 index 000000000..bf00148dd --- /dev/null +++ b/test/resources/9999999/asset/testExisting_asset_message-preheader-rcb-name-expected.amp @@ -0,0 +1,4 @@ +%%= ContentBlockByName("Content Builder\dont strip non ssjs content") =%% <script runat="server"> +Platform.Function.ContentBlockByName("Content Builder\\dont strip non ssjs content");</script>%%= ContentBlockByName("Content Builder\testExisting_htmlblock1") =%% <script runat="server"> +Platform.Function.ContentBlockByName("Content Builder\\dont strip non ssjs content");</script>%%= ContentBlockByName("Content Builder\dont strip non ssjs content") =%% <script runat="server"> +Platform.Function.ContentBlockByName("Content Builder\\dont strip non ssjs content");</script> diff --git a/test/resources/9999999/asset/testExisting_asset_message-text-rcb-id-expected.amp b/test/resources/9999999/asset/testExisting_asset_message-text-rcb-id-expected.amp new file mode 100644 index 000000000..2c521eee7 --- /dev/null +++ b/test/resources/9999999/asset/testExisting_asset_message-text-rcb-id-expected.amp @@ -0,0 +1,4 @@ +%%= ContentBlockById(1295064) =%% <script runat="server"> +Platform.Function.ContentBlockById(1295064);</script>%%= ContentBlockById(1295064) =%% <script runat="server"> +Platform.Function.ContentBlockById(1295064);</script>%%= ContentBlockById(1295064) =%% <script runat="server"> +Platform.Function.ContentBlockById(1295064);</script> diff --git a/test/resources/9999999/asset/testExisting_asset_message-text-rcb-key-expected.amp b/test/resources/9999999/asset/testExisting_asset_message-text-rcb-key-expected.amp new file mode 100644 index 000000000..b8b084519 --- /dev/null +++ b/test/resources/9999999/asset/testExisting_asset_message-text-rcb-key-expected.amp @@ -0,0 +1,4 @@ +%%= ContentBlockByKey("testExisting_asset_htmlblock") =%% <script runat="server"> +Platform.Function.ContentBlockByKey("testExisting_asset_htmlblock");</script>%%= ContentBlockByKey("testExisting_asset_htmlblock") =%% <script runat="server"> +Platform.Function.ContentBlockByKey("testExisting_asset_htmlblock");</script>%%= ContentBlockByKey("testExisting_asset_htmlblock") =%% <script runat="server"> +Platform.Function.ContentBlockByKey("testExisting_asset_htmlblock");</script> diff --git a/test/resources/9999999/asset/testExisting_asset_message-text-rcb-name-expected.amp b/test/resources/9999999/asset/testExisting_asset_message-text-rcb-name-expected.amp new file mode 100644 index 000000000..20d5640d3 --- /dev/null +++ b/test/resources/9999999/asset/testExisting_asset_message-text-rcb-name-expected.amp @@ -0,0 +1,4 @@ +%%= ContentBlockByName("Content Builder\dont strip non ssjs content") =%% <script runat="server"> +Platform.Function.ContentBlockByName("Content Builder\\dont strip non ssjs content");</script>%%= ContentBlockByName("Content Builder\dont strip non ssjs content") =%% <script runat="server"> +Platform.Function.ContentBlockByName("Content Builder\\dont strip non ssjs content");</script>%%= ContentBlockByName("Content Builder\dont strip non ssjs content") =%% <script runat="server"> +Platform.Function.ContentBlockByName("Content Builder\\dont strip non ssjs content");</script> diff --git a/test/resources/9999999/asset/test_coderesource_js-retrieve-expected.js b/test/resources/9999999/asset/test_coderesource_js-retrieve-expected.js new file mode 100644 index 000000000..b88ef7e84 --- /dev/null +++ b/test/resources/9999999/asset/test_coderesource_js-retrieve-expected.js @@ -0,0 +1 @@ +/* insert code here */ diff --git a/test/resources/9999999/asset/test_coderesource_js-retrieve-expected.json b/test/resources/9999999/asset/test_coderesource_js-retrieve-expected.json new file mode 100644 index 000000000..7a2773d3b --- /dev/null +++ b/test/resources/9999999/asset/test_coderesource_js-retrieve-expected.json @@ -0,0 +1,45 @@ +{ + "assetType": { + "displayName": "Javascript Code Resource", + "name": "jscoderesource" + }, + "availableViews": [], + "contentType": "application/javascript", + "createdBy": { + "email": "joern.berkefeld@accenture.com", + "name": "Jörn Berkefeld" + }, + "createdDate": "2025-03-24T05:20:40.82-06:00", + "customerKey": "test_coderesource_js", + "data": { + "site": { + "content": { + "url": "https://oss-test.accenture.com/test_coderesource" + } + } + }, + "description": "", + "memberId": 9999999, + "meta": { + "cloudPages": { + "c__published": true, + "publishDate": "2025-03-24 06:05:23.203" + } + }, + "modelVersion": 2, + "modifiedBy": { + "email": "joern.berkefeld@accenture.com", + "name": "Jörn Berkefeld" + }, + "modifiedDate": "2025-03-25T03:03:20.603-06:00", + "name": "test_coderesource_js", + "owner": { + "email": "joern.berkefeld@accenture.com", + "name": "Jörn Berkefeld" + }, + "status": { + "name": "Draft" + }, + "version": 1, + "r__folder_Path": "Content Builder/Test Folder" +} diff --git a/test/resources/9999999/asset/test_coderesource_json-retrieve-expected.json b/test/resources/9999999/asset/test_coderesource_json-retrieve-expected.json new file mode 100644 index 000000000..1fd804f6f --- /dev/null +++ b/test/resources/9999999/asset/test_coderesource_json-retrieve-expected.json @@ -0,0 +1,45 @@ +{ + "assetType": { + "displayName": "JSON Code Resource", + "name": "jsoncoderesource" + }, + "availableViews": [], + "contentType": "application/json", + "createdBy": { + "email": "joern.berkefeld@accenture.com", + "name": "Jörn Berkefeld" + }, + "createdDate": "2025-03-25T03:15:22.72-06:00", + "customerKey": "test_coderesource_json", + "data": { + "site": { + "content": { + "url": "https://oss-test.accenture.com/test_coderesource_json" + } + } + }, + "description": "", + "memberId": 9999999, + "meta": { + "cloudPages": { + "c__published": true, + "publishDate": "2025-03-25 03:16:40.913" + } + }, + "modelVersion": 2, + "modifiedBy": { + "email": "joern.berkefeld@accenture.com", + "name": "Jörn Berkefeld" + }, + "modifiedDate": "2025-03-25T03:16:40.913-06:00", + "name": "test_coderesource_json", + "owner": { + "email": "joern.berkefeld@accenture.com", + "name": "Jörn Berkefeld" + }, + "status": { + "name": "Draft" + }, + "version": 1, + "r__folder_Path": "Content Builder/Test Folder" +} diff --git a/test/resources/9999999/asset/test_coderesource_json-retrieve-expected.jsonc b/test/resources/9999999/asset/test_coderesource_json-retrieve-expected.jsonc new file mode 100644 index 000000000..42a102133 --- /dev/null +++ b/test/resources/9999999/asset/test_coderesource_json-retrieve-expected.jsonc @@ -0,0 +1 @@ +{ "test": true } diff --git a/test/resources/9999999/asset/test_coderesource_xml-retrieve-expected.json b/test/resources/9999999/asset/test_coderesource_xml-retrieve-expected.json new file mode 100644 index 000000000..2a8ce23d1 --- /dev/null +++ b/test/resources/9999999/asset/test_coderesource_xml-retrieve-expected.json @@ -0,0 +1,44 @@ +{ + "assetType": { + "displayName": "XML Code Resource", + "name": "xmlcoderesource" + }, + "availableViews": [], + "contentType": "application/xml", + "createdBy": { + "email": "joern.berkefeld@accenture.com", + "name": "Jörn Berkefeld" + }, + "createdDate": "2025-03-25T03:03:45.713-06:00", + "customerKey": "test_coderesource_xml", + "data": { + "site": { + "content": { + "url": "https://oss-test.accenture.com/test_coderesource_xml" + } + } + }, + "description": "", + "memberId": 9999999, + "meta": { + "cloudPages": { + "c__published": false + } + }, + "modelVersion": 2, + "modifiedBy": { + "email": "joern.berkefeld@accenture.com", + "name": "Jörn Berkefeld" + }, + "modifiedDate": "2025-03-25T03:04:06.48-06:00", + "name": "test_coderesource_xml", + "owner": { + "email": "joern.berkefeld@accenture.com", + "name": "Jörn Berkefeld" + }, + "status": { + "name": "Draft" + }, + "version": 1, + "r__folder_Path": "Content Builder/Test Folder" +} diff --git a/test/resources/9999999/asset/test_coderesource_xml-retrieve-expected.xml b/test/resources/9999999/asset/test_coderesource_xml-retrieve-expected.xml new file mode 100644 index 000000000..6aa2d8f5d --- /dev/null +++ b/test/resources/9999999/asset/test_coderesource_xml-retrieve-expected.xml @@ -0,0 +1 @@ +<xml>test</xml> diff --git a/test/resources/9999999/asset/test_interactivecontent-retrieve-expected.json b/test/resources/9999999/asset/test_interactivecontent-retrieve-expected.json new file mode 100644 index 000000000..4d6bb115c --- /dev/null +++ b/test/resources/9999999/asset/test_interactivecontent-retrieve-expected.json @@ -0,0 +1,41 @@ +{ + "assetType": { + "displayName": "Interactive Email Page", + "name": "interactivecontent" + }, + "availableViews": [], + "content": { + "url": "https://oss-test.accenture.com/test_interactivecontent" + }, + "createdBy": { + "email": "joern.berkefeld@accenture.com", + "name": "Jörn Berkefeld" + }, + "createdDate": "2025-03-25T03:02:46.823-06:00", + "customerKey": "test_interactivecontent", + "description": "", + "memberId": 9999999, + "meta": { + "cloudPages": { + "c__published": true, + "publishDate": "2025-03-25 03:02:55.307" + }, + "r__asset_key": "test_interactivecontent_content" + }, + "modelVersion": 2, + "modifiedBy": { + "email": "joern.berkefeld@accenture.com", + "name": "Jörn Berkefeld" + }, + "modifiedDate": "2025-03-25T03:02:55.307-06:00", + "name": "test_interactivecontent", + "owner": { + "email": "joern.berkefeld@accenture.com", + "name": "Jörn Berkefeld" + }, + "status": { + "name": "Draft" + }, + "version": 1, + "r__folder_Path": "Content Builder/Test Folder" +} diff --git a/test/resources/9999999/asset/test_landingpage-retrieve-expected.json b/test/resources/9999999/asset/test_landingpage-retrieve-expected.json new file mode 100644 index 000000000..802c9b31c --- /dev/null +++ b/test/resources/9999999/asset/test_landingpage-retrieve-expected.json @@ -0,0 +1,40 @@ +{ + "assetType": { + "displayName": "Landing Page", + "name": "landingpage" + }, + "availableViews": [], + "content": { + "url": "https://oss-test.accenture.com/test_landingpage" + }, + "createdBy": { + "email": "joern.berkefeld@accenture.com", + "name": "Jörn Berkefeld" + }, + "createdDate": "2025-03-25T03:17:51.88-06:00", + "customerKey": "test_landingpage", + "description": "", + "memberId": 9999999, + "meta": { + "cloudPages": { + "c__published": false + }, + "r__asset_key": "test_landingpage_content" + }, + "modelVersion": 2, + "modifiedBy": { + "email": "joern.berkefeld@accenture.com", + "name": "Jörn Berkefeld" + }, + "modifiedDate": "2025-03-25T03:17:52.187-06:00", + "name": "test_landingpage", + "owner": { + "email": "joern.berkefeld@accenture.com", + "name": "Jörn Berkefeld" + }, + "status": { + "name": "Draft" + }, + "version": 1, + "r__folder_Path": "Content Builder/Test Folder" +} diff --git a/test/resources/9999999/asset/test_microsite-retrieve-expected.json b/test/resources/9999999/asset/test_microsite-retrieve-expected.json new file mode 100644 index 000000000..2606c6b55 --- /dev/null +++ b/test/resources/9999999/asset/test_microsite-retrieve-expected.json @@ -0,0 +1,41 @@ +{ + "assetType": { + "displayName": "Microsite", + "name": "microsite" + }, + "availableViews": [], + "content": { + "url": "https://cloud.eu.randstad.com/test_microsite" + }, + "createdBy": { + "email": "joern.berkefeld@randstad.com", + "name": "Jörn Berkefeld" + }, + "createdDate": "2025-03-25T03:01:05.467-06:00", + "customerKey": "test_microsite", + "description": "", + "memberId": 9999999, + "meta": { + "cloudPages": { + "c__published": true, + "publishDate": "2025-03-25 03:12:51.850" + }, + "r__asset_key": "test_microsite_content" + }, + "modelVersion": 2, + "modifiedBy": { + "email": "joern.berkefeld@randstad.com", + "name": "Jörn Berkefeld" + }, + "modifiedDate": "2025-03-25T03:12:51.85-06:00", + "name": "test_microsite", + "owner": { + "email": "joern.berkefeld@randstad.com", + "name": "Jörn Berkefeld" + }, + "status": { + "name": "Draft" + }, + "version": 1, + "r__folder_Path": "Content Builder/Test Folder" +} diff --git a/test/resources/9999999/asset/v1/content/assets/1209971/get-response.json b/test/resources/9999999/asset/v1/content/assets/1209971/get-response.json new file mode 100644 index 000000000..7b01d7328 --- /dev/null +++ b/test/resources/9999999/asset/v1/content/assets/1209971/get-response.json @@ -0,0 +1,61 @@ +{ + "customerKey": "mobileMessage_test", + "assetType": { + "name": "jsonmessage", + "displayName": "JSON Message" + }, + "name": "Mobile Message November 22, 2021(4:20:55 PM)", + "owner": { + "email": "joern.berkefeld@accenture.com", + "name": "Jörn Berkefeld" + }, + "createdDate": "2021-11-22T09:21:11.933-06:00", + "createdBy": { + "email": "joern.berkefeld@accenture.com", + "name": "Jörn Berkefeld" + }, + "modifiedDate": "2021-12-16T02:56:24.29-06:00", + "modifiedBy": { + "name": "SFMC DEVOPS app user" + }, + "memberId": 9999999, + "status": { + "name": "Draft" + }, + "views": { + "push": { + "thumbnail": {}, + "content": "<!doctype html>\n<html>\n\t<head>\n\t\t<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n\t\t<meta name=\"description\" content=\"Push Preview\">\n\t\t<style>\n\thtml,\n\tbody {\n\t\tmargin: 0;\n\t\tpadding: 0;\n\t\theight: 100%;\n\t\twidth: 100%;\n\t\tline-height: 1.4;\n\t}\n\n\t.push-previewer {\n\t\twidth: inherit;\n\t\theight: inherit;\n\t\tposition: relative;\n\t}\n\n\t.device {\n\t\theight: inherit;\n\t\twidth: inherit;\n\t\tbackground-size: cover;\n\t\tbackground-repeat: no-repeat;\n\t}\n</style> <style>\n\t@font-face {\n\t\tfont-family: 'SF Pro Text - Regular';\n\t\tsrc: url('https://mobilepush-device-previewer.s7.marketingcloudapps.com/fonts/SFProText-Regular.woff') format('woff');\n\t\tfont-weight: normal;\n\t\tfont-style: normal;\n\t}\n\t\n\t@font-face {\n\t\tfont-family: 'Helvetica Neue - Roman';\n\t\tsrc: url('https://mobilepush-device-previewer.s7.marketingcloudapps.com/fonts/HelveticaNeue-Roman.woff') format('woff');\n\t\tfont-weight: normal;\n\t\tfont-style: normal;\n\t}\n\t\n\t@font-face {\n\t\tfont-family: 'SF Compact Text - Light';\n\t\tsrc: url('https://mobilepush-device-previewer.s7.marketingcloudapps.com/fonts/SFCompactText-Light.woff') format('woff');\n\t\tfont-weight: normal;\n\t\tfont-style: normal;\n\t}\n\t\n\t.device.iphone.lock-screen {\n\t\tfont-family: 'SF Pro Text - Regular';\n\t\tbackground-image: url('https://image.s8.exacttarget.com/lib/fe8e1c72746d057a70/m/1/d1948d1e-93af-4b9d-8b28-a087a351e8a8.jpg');\n\t}\n\t\n\t.device.iphone.lock-screen .header {\n\t\ttext-align: center;\n\t\tmargin-bottom: 20px;\n\t}\n\t\n\t.device.iphone.lock-screen .header .time {\n\t\tcolor: #FFFFFF;\n\t\tfont-family: 'SF Compact Text - Light';\n\t\tfont-size: 60px;\n\t\theight: 70px;\n\t}\n\n\t.device.iphone.lock-screen .header .date {\n\t\tcolor: #FFFFFF;\n\t\tfont-family: 'Helvetica Neue - Roman';\n\t\tfont-size: 17px;\n\t}\n\t\n\t.device.iphone.lock-screen .body {\n\t\tbackground: rgba(240, 240, 240, 0.97);\n\t\tborder-radius: 12px;\n\t\tpadding: 10px;\n\t\tmargin: 0 4px;\n\t\topacity: 1;\n\t\tposition: relative;\n\t}\n\t\n\t.device.iphone.lock-screen .body .application {\n\t\tdisplay: flex;\n\t\talign-items: center;\n\t\tborder-radius: 12px 12px 0 0;\n\t\tbackground: #F0F0F0;\n\t\tmargin: -10px -10px 0 -10px;\n\t\tpadding: 10px;\n\t}\n\t\n\t.device.iphone.lock-screen .body .application .icon {\n\t\t\n\t}\n\t\n\t.device.iphone.lock-screen .body .application .icon .icon-placeholder {\n\t\theight: 17px;\n\t\twidth: 17px;\n\t\tborder-radius: 3px;\n\t\tbackground-color: grey;\n\t\tdisplay: inline-block;\n\t\tvertical-align: middle;\n\t}\n\t\n\t.device.iphone.lock-screen .body .application .name {\n\t\tcolor: #000000;\n\t\topacity: .50;\n\t\tfont-size: 12px;\n\t\ttext-overflow: ellipsis;\n\t\toverflow: hidden;\n\t\twhite-space: nowrap;\n\t\twidth: 100%;\n\t\tpadding: 2px 5px 0 10px;\n\t}\n\t\n\t.device.iphone.lock-screen .body .application .timestamp {\n\t\tfont-size: 11px;\n\t\topacity: .50;\n\t\tfont-weight: bold;\n\t\tmargin-left: auto;\n\t}\n\t\n\t.device.iphone.lock-screen .body .media {\n\t\tborder-radius: 3px;\n\t\twidth: 26px;\n\t\theight: 26px;\n\t\tposition: absolute;\n\t\tright: 10px;\n\t\tbottom: 10px;\n\t}\n\t\n\t.device.iphone.lock-screen .body .media img {\n\t\theight: 100%;\n\t\tmax-height: 26px;\n\t\twidth: 100%;\n\t\tmax-width: 26px;\n\t}\n\t\n\t.device.iphone.lock-screen .body .content {\n\t\tcolor: #000000;\n\t\tfont-size: 13px;\n\t\tpadding-top: 5px;\n\t}\n\t\n\t.device.iphone.lock-screen .body .content > div {\n\t\ttext-overflow: ellipsis;\n\t\toverflow: hidden;\n\t}\n\t\n\t.device.iphone.lock-screen .body .content .title {\n\t\tfont-weight: bold;\n\t\twhite-space: nowrap;\n\t}\n\t\n\t.device.iphone.lock-screen .body .content .subtitle {\n\t\tfont-weight: bold;\n\t\twhite-space: nowrap;\n\t}\n\t\n\t.device.iphone.lock-screen .body .content .message {\n\t\twhite-space: pre-wrap;\n\t\tdisplay: -webkit-box;\n\t\t-webkit-line-clamp: 4;\n\t\t-webkit-box-orient: vertical;\n\t\ttext-overflow: ellipsis;\n\t\t-o-text-overflow: ellipsis;\n\t\t-ms-text-overflow: ellipsis;\n\t\tword-break: break-word;\n\t\t-ms-word-wrap: break-word;\n\t\tword-wrap: break-word;\n\t\tmax-height: 75px;\n\t}\n\t\n\t.device.iphone.lock-screen .body .content .message.hasTitle {\n\t\tmax-height: 55px;\n\t\t-webkit-line-clamp: 3;\n\t}\n\t\n\t.device.iphone.lock-screen .body .content .message.hasSubtitle {\n\t\tmax-height: 35px;\n\t\t-webkit-line-clamp: 2;\n\t}\n\t\n\t.device.iphone.lock-screen .body .content.hasMedia .message {\n\t\tpadding-right: 50px;\n\t}\n\t\n\t.device.iphone.lock-screen .body .action {\n\t\tcolor: #157EBF;\n\t\tfont-size: 11px;\n\t\topacity: .3;\n\t\tmargin-top: 5px;\n\t}\n\t\n\t.device.iphone.lock-screen .body .buttons {\n\t\tdisplay: none;\n\t}\n\t\n\t.device.iphone.lock-screen .footer {\n\t\tdisplay: none;\n\t}\n</style>\n\t</head>\n\t<body>\n\t\t<div class=\"push-previewer\">\n\t\t\t<div class=\"device iphone lock-screen\">\n\t\t\t\t<div class=\"header\">\n\t\t\t\t\t<div class=\"time\">12:00 AM</div>\n\t\t\t\t\t<div class=\"date\">January 1, 2020</div>\n\t\t\t\t</div>\n\t\t\t\t<div class=\"body\">\n\t\t\t\t\t<div class=\"application\">\n\t\t\t\t\t\t<div class=\"icon\">\n\t\t\t\t\t\t\t<div class=\"icon-placeholder\"></div>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t\t<div class=\"name\">App Name</div>\n\t\t\t\t\t\t<div class=\"timestamp\">now</div>\n\t\t\t\t\t</div>\n\t\t\t\t\t<div class=\"media\"></div>\n\t\t\t\t\t<div class=\"content \">\n\t\t\t\t\t\t<div class=\"title\">test</div>\n\t\t\t\t\t\t<div class=\"subtitle\"></div>\n\t\t\t\t\t\t<div class=\"message hasTitle \">asdfasf </div>\n\t\t\t\t\t</div>\n\t\t\t\t\t<div class=\"action\"></div>\n\t\t\t\t\t<div class=\"buttons\">\n\t\t\t\t\t\t<div class=\"button1\"></div>\n\t\t\t\t\t\t<div class=\"button2\"></div>\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t\t<div class=\"footer\"></div>\n\t\t\t</div>\n\t\t</div>\n\t</body>\n</html>", + "meta": { + "options": { + "customBlockData": { + "display:title": "test", + "channel": "push", + "showTemplatePicker": false, + "display:title:display": "test", + "stack": "S7", + "openBehavior:actionType": { + "label": "Open the App", + "value": "openApp", + "id": "openApp_0", + "localizedLabel": "Open the App" + }, + "display:message": "asdfasf ", + "currentColumn": 0, + "display:message:display": "asdfasf ", + "template": "push", + "uncheckedPanels": ["pushmedia", "subtitle"] + } + } + }, + "modelVersion": 2 + } + }, + "availableViews": ["push"], + "modelVersion": 2, + "category": { + "id": 89397, + "name": "Content Builder", + "parentId": 0 + } +} diff --git a/test/resources/9999999/asset/v1/content/assets/1295064/get-response.json b/test/resources/9999999/asset/v1/content/assets/1295064/get-response.json new file mode 100644 index 000000000..d768091d1 --- /dev/null +++ b/test/resources/9999999/asset/v1/content/assets/1295064/get-response.json @@ -0,0 +1,60 @@ +{ + "id": 1295064, + "customerKey": "testExisting_asset_htmlblock", + "objectID": "972974ed-dc44-4df2-ab6e-53bae9070339", + "assetType": { + "id": 197, + "name": "htmlblock", + "displayName": "HTML Block" + }, + "fileProperties": { + "fileName": "testExisting_asset_htmlblock-Mcdev-strips-content" + }, + "name": "testExisting_asset_htmlblock-Mcdev-strips-content", + "owner": { + "id": 700301950, + "email": "joern.berkefeld@accenture.com", + "name": "Jörn Berkefeld (ASGR)", + "userId": "700301950" + }, + "createdDate": "2024-01-08T08:26:58.277-06:00", + "createdBy": { + "id": 700301950, + "email": "joern.berkefeld@accenture.com", + "name": "Jörn Berkefeld (ASGR)", + "userId": "700301950" + }, + "modifiedDate": "2024-01-08T08:28:01.6-06:00", + "modifiedBy": { + "id": 700301950, + "email": "joern.berkefeld@accenture.com", + "name": "Jörn Berkefeld (ASGR)", + "userId": "700301950" + }, + "enterpriseId": 9999999, + "memberId": 9999999, + "status": { + "id": 1, + "name": "Draft" + }, + "thumbnail": { + "thumbnailUrl": "/v1/assets/1295064/thumbnail" + }, + "category": { + "id": 89397, + "name": "Content Builder", + "parentId": 0 + }, + "content": "<table cellpadding=\"0\" cellspacing=\"0\" width=\"100%\" role=\"presentation\" style=\"min-width: 100%; \" class=\"stylingblock-content-wrapper\"><tr><td class=\"stylingblock-content-wrapper camarker-inner\"><div>\n my 1st html\n</div>\n\n%%[ /* my ampscript */ ]%%\n\n<script runat=\"server\">\n// my ssjs\n</script>\n\n<div>\n my 2nd html\n</div>\n<div>%%=ContentBlockById(1295065)=%%</div></td></tr></table>", + "design": "", + "meta": { + "wrapperStyles": { + "mobile": { + "visible": true + }, + "styling": {} + } + }, + "availableViews": [], + "modelVersion": 2 +} diff --git a/test/resources/9999999/asset/v1/content/assets/1295064/patch-response.json b/test/resources/9999999/asset/v1/content/assets/1295064/patch-response.json new file mode 100644 index 000000000..5589e010b --- /dev/null +++ b/test/resources/9999999/asset/v1/content/assets/1295064/patch-response.json @@ -0,0 +1,59 @@ +{ + "id": 1295064, + "customerKey": "testExisting_asset_html-matchName", + "objectID": "26fdf503-eeed-49eb-b428-cb3b4bc2ba48", + "assetType": { + "id": 196, + "name": "textblock", + "displayName": "Text Block" + }, + "fileProperties": { + "fileName": "testNew_asset" + }, + "name": "testNew_asset", + "description": "bla bla", + "owner": { + "id": 700304523, + "email": "", + "name": "SFMC DEVOPS app user", + "userId": "700304523" + }, + "createdDate": "2024-05-07T05:08:46.927-06:00", + "createdBy": { + "id": 700304523, + "email": "", + "name": "SFMC DEVOPS app user", + "userId": "700304523" + }, + "modifiedDate": "2024-05-07T05:08:46.927-06:00", + "modifiedBy": { + "id": 700304523, + "email": "", + "name": "SFMC DEVOPS app user", + "userId": "700304523" + }, + "enterpriseId": 1111111, + "memberId": 9999999, + "status": { + "id": 1, + "name": "Draft" + }, + "thumbnail": { + "thumbnailUrl": "/v1/assets/1324776/thumbnail" + }, + "category": { + "id": 89397, + "name": "Content Builder", + "parentId": 0 + }, + "content": "<table\n cellpadding=\"0\"\n cellspacing=\"0\"\n width=\"100%\"\n role=\"presentation\"\n style=\"min-width: 100%\"\n class=\"stylingblock-content-wrapper\"\n>\n <tr>\n <td class=\"stylingblock-content-wrapper camarker-inner\">foobar</td>\n </tr>\n</table>\n", + "meta": { + "wrapperStyles": { + "mobile": { + "visible": true + } + } + }, + "availableViews": [], + "modelVersion": 2 +} diff --git a/test/resources/9999999/asset/v1/content/assets/1295065/get-response.json b/test/resources/9999999/asset/v1/content/assets/1295065/get-response.json new file mode 100644 index 000000000..b738ce19d --- /dev/null +++ b/test/resources/9999999/asset/v1/content/assets/1295065/get-response.json @@ -0,0 +1,60 @@ +{ + "id": 1295065, + "customerKey": "testExisting_htmlblock1", + "objectID": "972974ed-dc44-4df2-ab6e-53bae9070335", + "assetType": { + "id": 197, + "name": "htmlblock", + "displayName": "HTML Block" + }, + "fileProperties": { + "fileName": "testExisting_htmlblock1" + }, + "name": "testExisting_htmlblock1", + "owner": { + "id": 700301950, + "email": "joern.berkefeld@accenture.com", + "name": "Jörn Berkefeld (ASGR)", + "userId": "700301950" + }, + "createdDate": "2024-01-08T08:26:58.277-06:00", + "createdBy": { + "id": 700301950, + "email": "joern.berkefeld@accenture.com", + "name": "Jörn Berkefeld (ASGR)", + "userId": "700301950" + }, + "modifiedDate": "2024-01-08T08:28:01.6-06:00", + "modifiedBy": { + "id": 700301950, + "email": "joern.berkefeld@accenture.com", + "name": "Jörn Berkefeld (ASGR)", + "userId": "700301950" + }, + "enterpriseId": 9999999, + "memberId": 9999999, + "status": { + "id": 1, + "name": "Draft" + }, + "thumbnail": { + "thumbnailUrl": "/v1/assets/1295065/thumbnail" + }, + "category": { + "id": 89397, + "name": "Content Builder", + "parentId": 0 + }, + "content": "<table cellpadding=\"0\" cellspacing=\"0\" width=\"100%\" role=\"presentation\" style=\"min-width: 100%; \" class=\"stylingblock-content-wrapper\"><tr><td class=\"stylingblock-content-wrapper camarker-inner\"><div>\n my 1st html\n</div>\n\n%%[ /* my ampscript */ ]%%\n\n<script runat=\"server\">\n// my ssjs\n</script>\n\n<div>\n my 2nd html\n</div>\n<div>%%= ContentBlockById(1295066)=%%%%= ContentBlockByKey(\"testExisting_htmlblock 3 spaces\")=%%</div></td></tr></table>", + "design": "", + "meta": { + "wrapperStyles": { + "mobile": { + "visible": true + }, + "styling": {} + } + }, + "availableViews": [], + "modelVersion": 2 +} diff --git a/test/resources/9999999/asset/v1/content/assets/1295066/get-response.json b/test/resources/9999999/asset/v1/content/assets/1295066/get-response.json new file mode 100644 index 000000000..74721c537 --- /dev/null +++ b/test/resources/9999999/asset/v1/content/assets/1295066/get-response.json @@ -0,0 +1,60 @@ +{ + "id": 1295066, + "customerKey": "testExisting_htmlblock2", + "objectID": "972974ed-dc44-4df2-ab6e-53bae9070336", + "assetType": { + "id": 197, + "name": "htmlblock", + "displayName": "HTML Block" + }, + "fileProperties": { + "fileName": "testExisting_htmlblock2" + }, + "name": "testExisting_htmlblock2", + "owner": { + "id": 700301950, + "email": "joern.berkefeld@accenture.com", + "name": "Jörn Berkefeld (ASGR)", + "userId": "700301950" + }, + "createdDate": "2024-01-08T08:26:58.277-06:00", + "createdBy": { + "id": 700301950, + "email": "joern.berkefeld@accenture.com", + "name": "Jörn Berkefeld (ASGR)", + "userId": "700301950" + }, + "modifiedDate": "2024-01-08T08:28:01.6-06:00", + "modifiedBy": { + "id": 700301950, + "email": "joern.berkefeld@accenture.com", + "name": "Jörn Berkefeld (ASGR)", + "userId": "700301950" + }, + "enterpriseId": 9999999, + "memberId": 9999999, + "status": { + "id": 1, + "name": "Draft" + }, + "thumbnail": { + "thumbnailUrl": "/v1/assets/1295066/thumbnail" + }, + "category": { + "id": 89397, + "name": "Content Builder", + "parentId": 0 + }, + "content": "<table cellpadding=\"0\" cellspacing=\"0\" width=\"100%\" role=\"presentation\" style=\"min-width: 100%; \" class=\"stylingblock-content-wrapper\"><tr><td class=\"stylingblock-content-wrapper camarker-inner\"><div>\n my 1st html\n</div>\n\n%%[ /* my ampscript */ ]%%\n\n<script runat=\"server\">\n// my ssjs\n</script>\n\n<div>\n my 2nd html\n</div>\n<div>%%=TreatAsContent(ContentBlockByFake(\"Content Builder\\my very long path\\Content Blocks Library\\COMMON\\some other folder\\my code snippet\"))=%%</div></td></tr></table>", + "design": "", + "meta": { + "wrapperStyles": { + "mobile": { + "visible": true + }, + "styling": {} + } + }, + "availableViews": [], + "modelVersion": 2 +} diff --git a/test/resources/9999999/asset/v1/content/assets/1295067/get-response.json b/test/resources/9999999/asset/v1/content/assets/1295067/get-response.json new file mode 100644 index 000000000..74627e779 --- /dev/null +++ b/test/resources/9999999/asset/v1/content/assets/1295067/get-response.json @@ -0,0 +1,60 @@ +{ + "id": 1295067, + "customerKey": "testExisting_htmlblock 3 spaces", + "objectID": "972974ed-dc44-4df2-ab6e-53bae9070336", + "assetType": { + "id": 197, + "name": "htmlblock", + "displayName": "HTML Block" + }, + "fileProperties": { + "fileName": "testExisting_htmlblock 3 spaces" + }, + "name": "testExisting_htmlblock 3 spaces", + "owner": { + "id": 700301950, + "email": "joern.berkefeld@accenture.com", + "name": "Jörn Berkefeld (ASGR)", + "userId": "700301950" + }, + "createdDate": "2024-01-08T08:26:58.277-06:00", + "createdBy": { + "id": 700301950, + "email": "joern.berkefeld@accenture.com", + "name": "Jörn Berkefeld (ASGR)", + "userId": "700301950" + }, + "modifiedDate": "2024-01-08T08:28:01.6-06:00", + "modifiedBy": { + "id": 700301950, + "email": "joern.berkefeld@accenture.com", + "name": "Jörn Berkefeld (ASGR)", + "userId": "700301950" + }, + "enterpriseId": 9999999, + "memberId": 9999999, + "status": { + "id": 1, + "name": "Draft" + }, + "thumbnail": { + "thumbnailUrl": "/v1/assets/1295066/thumbnail" + }, + "category": { + "id": 89397, + "name": "Content Builder", + "parentId": 0 + }, + "content": "<table cellpadding=\"0\" cellspacing=\"0\" width=\"100%\" role=\"presentation\" style=\"min-width: 100%; \" class=\"stylingblock-content-wrapper\"><tr><td class=\"stylingblock-content-wrapper camarker-inner\"><div>\n my 1st html\n</div>\n\n%%[ /* my ampscript */ ]%%\n\n<script runat=\"server\">\n// my ssjs\n</script>\n\n<div>\n my 2nd html\n</div>\n<div>%%=TreatAsContent(ContentBlockByFake(\"Content Builder\\my very long path\\Content Blocks Library\\COMMON\\some other folder\\my code snippet\"))=%% %%= ContentBlockByKey(\"testExisting_htmlblock1\")=%% %%= ContentBlockByKey(\"testExisting_htmlblock1 \")=%%</div></td></tr></table>", + "design": "", + "meta": { + "wrapperStyles": { + "mobile": { + "visible": true + }, + "styling": {} + } + }, + "availableViews": [], + "modelVersion": 2 +} diff --git a/test/resources/9999999/asset/v1/content/assets/16992/get-response.json b/test/resources/9999999/asset/v1/content/assets/16992/get-response.json new file mode 100644 index 000000000..f877af15d --- /dev/null +++ b/test/resources/9999999/asset/v1/content/assets/16992/get-response.json @@ -0,0 +1,60 @@ +{ + "id": 16992, + "customerKey": "test_slash", + "objectID": "13f34d9c-f555-4fce-b862-26ff7f9fef7a", + "assetType": { + "id": 197, + "name": "htmlblock", + "displayName": "HTML Block" + }, + "fileProperties": { + "fileName": "test_slash" + }, + "name": "test_slash", + "owner": { + "id": 710420432, + "email": "", + "name": "IDE - joern.berkefeld app user", + "userId": "710420432" + }, + "createdDate": "2026-03-06T07:47:11.04-06:00", + "createdBy": { + "id": 710420432, + "email": "", + "name": "IDE - joern.berkefeld app user", + "userId": "710420432" + }, + "modifiedDate": "2026-03-06T07:47:11.04-06:00", + "modifiedBy": { + "id": 710420432, + "email": "", + "name": "IDE - joern.berkefeld app user", + "userId": "710420432" + }, + "enterpriseId": 1111111, + "memberId": 9999999, + "status": { + "id": 1, + "name": "Draft" + }, + "thumbnail": { + "thumbnailUrl": "/v1/assets/16992/thumbnail" + }, + "category": { + "id": 38491, + "name": "bla/blub", + "parentId": 89397 + }, + "content": "<table\n cellpadding=\"0\"\n cellspacing=\"0\"\n width=\"100%\"\n role=\"presentation\"\n style=\"min-width: 100%\"\n class=\"stylingblock-content-wrapper\"\n>\n <tr>\n <td class=\"stylingblock-content-wrapper camarker-inner\">test</td>\n </tr>\n</table>\n", + "design": "", + "meta": { + "wrapperStyles": { + "mobile": { + "visible": true + }, + "styling": {} + } + }, + "availableViews": [], + "modelVersion": 2 +} diff --git a/test/resources/9999999/asset/v1/content/assets/5286/get-response.json b/test/resources/9999999/asset/v1/content/assets/5286/get-response.json new file mode 100644 index 000000000..df910f095 --- /dev/null +++ b/test/resources/9999999/asset/v1/content/assets/5286/get-response.json @@ -0,0 +1,48 @@ +{ + "id": 5286, + "customerKey": "testExisting_asset_template", + "objectID": "50855339-3f87-47a7-8677-a8c63eb36a43", + "assetType": { + "id": 4, + "name": "template", + "displayName": "Template" + }, + "fileProperties": { + "fileName": " testExisting_asset_template" + }, + "name": " testExisting_asset_template", + "owner": { + "id": 710411605, + "email": "joern.berkefeld@accenture.com", + "name": "Jörn Berkefeld", + "userId": "710411605" + }, + "createdDate": "2024-04-22T03:33:08.253-06:00", + "createdBy": { + "id": 710411605, + "email": "joern.berkefeld@accenture.com", + "name": "Jörn Berkefeld", + "userId": "710411605" + }, + "modifiedDate": "2024-05-13T07:12:13.117-06:00", + "modifiedBy": { + "id": 710420432, + "name": "joern.berkefeld app user", + "userId": "710420432" + }, + "enterpriseId": 510004860, + "memberId": 510009653, + "status": { + "id": 1, + "name": "Draft" + }, + "thumbnail": { + "thumbnailUrl": "/v1/assets/5286/thumbnail" + }, + "category": { + "id": 89397 + }, + "content": "<a href=\"%%ftaf_url%%\"\n ><img\n src=\"https://www.exacttarget.com/members/newsletters/gfx/forwardafriendicon.gif\"\n border=\"0\" /></a\n><a href=\"%%profile_center_url%%\" alias=\"Update Profile\">Update Profile</a>\n<table cellpadding=\"2\" cellspacing=\"0\" width=\"600\" id=\"Table5\" border=\"0\">\n <tr>\n <td>\n <font face=\"verdana\" size=\"1\" color=\"#444444\"\n >This email was sent by: <b>%%Member_Busname%%</b><br />%%Member_Addr%%\n %%Member_City%%, %%Member_State%%, %%Member_PostalCode%%, %%Member_Country%%<br /><br\n /></font>\n </td>\n </tr>\n</table>\n<a href=\"%%subscription_center_url%%\" alias=\"Manage Subscriptions\">Manage Subscriptions</a\n><img src=\"https://www.exacttarget.com/images/Powered_By_1206.jpg\" border=\"0\" /><custom\n name=\"opencounter\"\n type=\"tracking\"\n/>\n", + "availableViews": [], + "modelVersion": 2 +} diff --git a/test/resources/9999999/asset/v1/content/assets/5289/get-response.json b/test/resources/9999999/asset/v1/content/assets/5289/get-response.json new file mode 100644 index 000000000..d36f9b5f3 --- /dev/null +++ b/test/resources/9999999/asset/v1/content/assets/5289/get-response.json @@ -0,0 +1,273 @@ +{ + "id": 5289, + "customerKey": "testExisting_asset_templatebasedemail", + "objectID": "26c925ba-af6e-4c2a-a04a-a67f39cceeee", + "contentType": "application/vnd.etmc.email.Message; kind=template", + "assetType": { + "id": 207, + "name": "templatebasedemail", + "displayName": "Template-Based Email" + }, + "name": " testExisting_asset_templatebasedemail", + "owner": { + "id": 710369861, + "email": "joern.berkefeld@accenture.com", + "name": "Jörn Berkefeld", + "userId": "710369861" + }, + "createdDate": "2024-04-22T06:36:03.117-06:00", + "createdBy": { + "id": 710369861, + "email": "joern.berkefeld@accenture.com", + "name": "Jörn Berkefeld", + "userId": "710369861" + }, + "modifiedDate": "2024-05-13T07:15:29.77-06:00", + "modifiedBy": { + "id": 710420432, + "name": "IDE - joern.berkefeld app user", + "userId": "710420432" + }, + "enterpriseId": 1111111, + "memberId": 9999999, + "status": { + "id": 1, + "name": "Draft" + }, + "thumbnail": { + "thumbnailUrl": "/v1/assets/5289/thumbnail" + }, + "category": { + "id": 89397 + }, + "views": { + "subjectline": { + "contentType": "application/vnd.etmc.email.View; kind=subjectline", + "thumbnail": {}, + "content": "my subject line", + "availableViews": [], + "data": { + "email": { + "options": { + "generateFrom": null + } + } + }, + "modelVersion": 2 + }, + "preheader": { + "contentType": "application/vnd.etmc.email.View; kind=preheader", + "thumbnail": {}, + "content": "my custom preheader text", + "availableViews": [], + "data": { + "email": { + "options": { + "generateFrom": null + } + } + }, + "modelVersion": 2 + }, + "text": { + "thumbnail": {}, + "availableViews": [], + "data": { + "email": { + "options": { + "generateFrom": "html" + } + } + }, + "generateFrom": "html", + "modelVersion": 2 + }, + "viewAsAWebPage": { + "thumbnail": {}, + "availableViews": [], + "data": { + "email": { + "options": { + "generateFrom": null + } + } + }, + "modelVersion": 2 + }, + "subscriptioncenter": { + "thumbnail": {}, + "availableViews": [], + "data": { + "email": { + "options": { + "generateFrom": null + } + } + }, + "modelVersion": 2 + }, + "forwardHTML": { + "thumbnail": {}, + "availableViews": [], + "data": { + "email": { + "options": { + "generateFrom": null + } + } + }, + "modelVersion": 2 + }, + "forwardText": { + "thumbnail": {}, + "availableViews": [], + "data": { + "email": { + "options": { + "generateFrom": null + } + } + }, + "modelVersion": 2 + }, + "html": { + "thumbnail": {}, + "content": "<a href=\"%%ftaf_url%%\"\n ><img\n src=\"https://www.exacttarget.com/members/newsletters/gfx/forwardafriendicon.gif\"\n border=\"0\" /></a\n><a href=\"%%profile_center_url%%\" alias=\"Update Profile\">Update Profile</a>\n<table cellpadding=\"2\" cellspacing=\"0\" width=\"600\" id=\"Table5\" border=\"0\">\n <tr>\n <td>\n <font face=\"verdana\" size=\"1\" color=\"#444444\"\n >This email was sent by: <b>%%Member_Busname%%</b><br />%%Member_Addr%%\n %%Member_City%%, %%Member_State%%, %%Member_PostalCode%%, %%Member_Country%%<br /><br\n /></font>\n </td>\n </tr>\n</table>\n<a href=\"%%subscription_center_url%%\" alias=\"Manage Subscriptions\">Manage Subscriptions</a\n><img src=\"https://www.exacttarget.com/images/Powered_By_1206.jpg\" border=\"0\" /><custom\n name=\"opencounter\"\n type=\"tracking\"\n/>\n", + "availableViews": [], + "slots": { + "banner": { + "content": "<div data-type=\"block\" data-key=\"5v1vodxyvz\"></div><div data-type=\"block\" data-key=\"c2m5fa0c6ym\"></div><div data-type=\"block\" data-key=\"cdsuxkm6kyt\"></div><div data-type=\"block\" data-key=\"7xogokk59k\"></div><div data-type=\"block\" data-key=\"sf47b6tjg2m\"></div><div data-type=\"block\" data-key=\"hy6ik0ftsb4\"></div><div data-type=\"block\" data-key=\"csscq2x1lpr\"></div>", + "design": "<p style=\"font-family:Arial;color:#ccc;font-size:12px;text-align:center;vertical-align:middle;font-weight:bold;height:150px;display:flex;flex-direction:column;justify-content:center;padding:10px;margin:0;border: #cccccc dashed 1px;\">Drop blocks or content here</p>", + "availableViews": [], + "blocks": { + "hy6ik0ftsb4": { + "id": 1295064, + "customerKey": "testExisting_asset_htmlblock", + "objectID": "972974ed-dc44-4df2-ab6e-53bae9070339", + "assetType": { + "id": 197, + "name": "htmlblock", + "displayName": "HTML Block" + }, + "fileProperties": { + "fileName": "testExisting_asset_htmlblock-Mcdev-strips-content" + }, + "name": "testExisting_asset_htmlblock-Mcdev-strips-content", + "owner": { + "id": 700301950, + "email": "joern.berkefeld@accenture.com", + "name": "Jörn Berkefeld (ASGR)", + "userId": "700301950" + }, + "createdDate": "2024-01-08T08:26:58.277-06:00", + "createdBy": { + "id": 700301950, + "email": "joern.berkefeld@accenture.com", + "name": "Jörn Berkefeld (ASGR)", + "userId": "700301950" + }, + "modifiedDate": "2024-01-08T08:28:01.6-06:00", + "modifiedBy": { + "id": 700301950, + "email": "joern.berkefeld@accenture.com", + "name": "Jörn Berkefeld (ASGR)", + "userId": "700301950" + }, + "enterpriseId": 99991999, + "memberId": 99991999, + "status": { + "id": 1, + "name": "Draft" + }, + "thumbnail": { + "thumbnailUrl": "/v1/assets/1295064/thumbnail" + }, + "category": { + "id": 89397, + "name": "Content Builder", + "parentId": 0 + }, + "content": "<table cellpadding=\"0\" cellspacing=\"0\" width=\"100%\" role=\"presentation\" style=\"min-width: 100%; \" class=\"stylingblock-content-wrapper\"><tr><td class=\"stylingblock-content-wrapper camarker-inner\"><div>\n my 1st html\n</div>\n\n%%[ /* my ampscript */ ]%%\n\n<script runat=\"server\">\n// my ssjs\n</script>\n\n<div>\n my 2nd html\n</div>\n<div>%%=TreatAsContent(ContentBlockByFake(\"Content Builder\\my very long path\\Content Blocks Library\\COMMON\\some other folder\\my code snippet\"))=%%</div></td></tr></table>", + "design": "", + "meta": { + "wrapperStyles": { + "mobile": { + "visible": true + }, + "styling": {} + } + }, + "availableViews": [], + "modelVersion": 2 + } + }, + "data": { + "email": { + "options": {} + } + }, + "modelVersion": 2 + } + }, + "template": { + "id": 5286, + "assetType": { + "id": 4, + "name": "template", + "displayName": "Template" + }, + "name": "testExisting_asset_template", + "meta": { + "contentHash": -166410261 + }, + "availableViews": [], + "data": { + "email": { + "options": { + "generateFrom": null + } + } + }, + "modelVersion": 2 + }, + "data": { + "email": { + "options": { + "generateFrom": null + } + } + }, + "modelVersion": 2 + } + }, + "availableViews": [ + "subjectline", + "preheader", + "text", + "viewAsAWebPage", + "subscriptioncenter", + "forwardHTML", + "forwardText", + "html" + ], + "data": { + "email": { + "options": { + "characterEncoding": "utf-8" + }, + "legacy": { + "legacyId": 1643, + "legacyKey": "9b6edc22-d19a-429a-a705-da88c3a16543", + "legacyType": "email", + "legacyCategoryId": 10251 + } + } + }, + "legacyData": { + "legacyId": 1643, + "legacyKey": "9b6edc22-d19a-429a-a705-da88c3a16543", + "legacyType": "email", + "legacyCategoryId": 10251 + }, + "modelVersion": 2 +} diff --git a/test/resources/9999999/asset/v1/content/assets/808714/get-response.json b/test/resources/9999999/asset/v1/content/assets/808714/get-response.json new file mode 100644 index 000000000..14751c40c --- /dev/null +++ b/test/resources/9999999/asset/v1/content/assets/808714/get-response.json @@ -0,0 +1,185 @@ +{ + "id": 808714, + "customerKey": "testExisting_asset_message", + "objectID": "01f883be-c5c3-4eb1-b6e1-d7036f8153d4", + "contentType": "application/vnd.etmc.email.Message; kind=paste", + "assetType": { + "id": 208, + "name": "htmlemail", + "displayName": "HTML Email" + }, + "name": "testExisting_asset_message", + "owner": { + "id": 717129834, + "email": "joern.berkefeld@accenture.com", + "name": "Jörn Berkefeld", + "userId": "717129834" + }, + "createdDate": "2020-03-06T02:35:15.677-06:00", + "createdBy": { + "id": 717129834, + "email": "joern.berkefeld@accenture.com", + "name": "Jörn Berkefeld", + "userId": "717129834" + }, + "modifiedDate": "2023-08-02T07:08:00.86-06:00", + "modifiedBy": { + "id": 700304523, + "name": "SFMC DEVOPS app user", + "userId": "700304523" + }, + "enterpriseId": 7281698, + "memberId": 7281698, + "status": { + "id": 1, + "name": "Draft" + }, + "thumbnail": { + "thumbnailUrl": "/v1/assets/808714/thumbnail" + }, + "category": { + "id": 89397, + "name": "Content Builder", + "parentId": 0 + }, + "views": { + "subjectline": { + "contentType": "application/vnd.etmc.email.View; kind=subjectline", + "thumbnail": {}, + "content": "TEST", + "availableViews": [], + "data": { + "email": { + "options": { + "generateFrom": null + } + } + }, + "modelVersion": 2 + }, + "preheader": { + "thumbnail": {}, + "content": "%%= ContentBlockByKey(\"testExisting_asset_htmlblock\") =%% <script runat=\"server\">\nPlatform.Function.ContentBlockByKey(\"testExisting_asset_htmlblock\");</script>%%= ContentBlockById(1295065) =%% <script runat=\"server\">\nPlatform.Function.ContentBlockById(1295064);</script>%%= ContentBlockByName(\"Content Builder\\dont strip non ssjs content\") =%% <script runat=\"server\">\nPlatform.Function.ContentBlockByName(\"Content Builder\\\\dont strip non ssjs content\");</script>", + "availableViews": [], + "data": { + "email": { + "options": { + "generateFrom": null + } + } + }, + "modelVersion": 2 + }, + "html": { + "thumbnail": {}, + "content": "<a href=\"%%ftaf_url%%\"\n ><img\n src=\"https://www.exacttarget.com/members/newsletters/gfx/forwardafriendicon.gif\"\n border=\"0\" /></a\n><a href=\"%%profile_center_url%%\" alias=\"Update Profile\">Update Profile</a>\n<table cellpadding=\"2\" cellspacing=\"0\" width=\"600\" id=\"Table5\" border=\"0\">\n <tr>\n <td>\n <font face=\"verdana\" size=\"1\" color=\"#444444\"\n >This email was sent by: <b>%%Member_Busname%%</b><br />%%Member_Addr%%\n %%Member_City%%, %%Member_State%%, %%Member_PostalCode%%, %%Member_Country%%<br /><br\n /></font>\n </td>\n </tr>\n</table>\n<a href=\"%%subscription_center_url%%\" alias=\"Manage Subscriptions\">Manage Subscriptions</a\n><img src=\"https://www.exacttarget.com/images/Powered_By_1206.jpg\" border=\"0\" /><custom\n name=\"opencounter\"\n type=\"tracking\"\n/>\n%%= ContentBlockByKey(\"testExisting_asset_htmlblock\") =%% <script runat=\"server\">\nPlatform.Function.ContentBlockByKey(\"testExisting_asset_htmlblock\");</script>%%= ContentBlockById(1295064) =%% <script runat=\"server\">\nPlatform.Function.ContentBlockById(1295064);</script>%%= ContentBlockByName(\"Content Builder\\dont strip non ssjs content\") =%% <script runat=\"server\">\nPlatform.Function.ContentBlockByName(\"Content Builder\\\\dont strip non ssjs content\");</script>", + "availableViews": [], + "data": { + "email": { + "options": { + "generateFrom": null + } + } + }, + "modelVersion": 2 + }, + "text": { + "thumbnail": {}, + "content": "%%= ContentBlockByKey(\"testExisting_asset_htmlblock\") =%% <script runat=\"server\">\nPlatform.Function.ContentBlockByKey(\"testExisting_asset_htmlblock\");</script>%%= ContentBlockById(1295064) =%% <script runat=\"server\">\nPlatform.Function.ContentBlockById(1295064);</script>%%= ContentBlockByName(\"Content Builder\\dont strip non ssjs content\") =%% <script runat=\"server\">\nPlatform.Function.ContentBlockByName(\"Content Builder\\\\dont strip non ssjs content\");</script>", + "availableViews": [], + "data": { + "email": { + "options": { + "generateFrom": null + } + } + }, + "modelVersion": 2 + }, + "viewAsAWebPage": { + "thumbnail": {}, + "availableViews": [], + "data": { + "email": { + "options": { + "generateFrom": null + } + } + }, + "modelVersion": 2 + }, + "subscriptioncenter": { + "thumbnail": {}, + "availableViews": [], + "data": { + "email": { + "options": { + "generateFrom": null + } + } + }, + "modelVersion": 2 + }, + "forwardHTML": { + "thumbnail": {}, + "availableViews": [], + "data": { + "email": { + "options": { + "generateFrom": null + } + } + }, + "modelVersion": 2 + }, + "forwardText": { + "thumbnail": {}, + "availableViews": [], + "data": { + "email": { + "options": { + "generateFrom": null + } + } + }, + "modelVersion": 2 + } + }, + "availableViews": [ + "subjectline", + "preheader", + "html", + "text", + "viewAsAWebPage", + "subscriptioncenter", + "forwardHTML", + "forwardText" + ], + "data": { + "email": { + "options": { + "characterEncoding": "utf-8" + }, + "legacy": { + "legacyId": 429827, + "legacyKey": "c7308370-bb2c-4bd4-83dd-0ea422e2009d", + "legacyType": "email", + "legacyCategoryId": 90890 + } + }, + "approvals": { + "approvalStatus": { + "id": 4, + "name": "Approved", + "displayName": "Approved" + } + } + }, + "legacyData": { + "legacyId": 429827, + "legacyKey": "c7308370-bb2c-4bd4-83dd-0ea422e2009d", + "legacyType": "email", + "legacyCategoryId": 90890 + }, + "modelVersion": 2 +} diff --git a/test/resources/9999999/asset/v1/content/assets/9451/get-response.json b/test/resources/9999999/asset/v1/content/assets/9451/get-response.json new file mode 100644 index 000000000..64289acc2 --- /dev/null +++ b/test/resources/9999999/asset/v1/content/assets/9451/get-response.json @@ -0,0 +1,61 @@ +{ + "id": 9451, + "customerKey": "test_coderesource_js", + "objectID": "cbd96028-3fd4-49cc-910b-e3640d4686e5", + "contentType": "application/javascript", + "assetType": { + "id": 240, + "name": "jscoderesource", + "displayName": "Javascript Code Resource" + }, + "version": 1, + "name": "test_coderesource_js", + "description": "", + "owner": { + "id": 710420418, + "email": "joern.berkefeld@accenture.com", + "name": "Jörn Berkefeld", + "userId": "710420418" + }, + "createdDate": "2025-03-24T05:20:40.82-06:00", + "createdBy": { + "id": 710420418, + "email": "joern.berkefeld@accenture.com", + "name": "Jörn Berkefeld", + "userId": "710420418" + }, + "modifiedDate": "2025-03-25T03:03:20.603-06:00", + "modifiedBy": { + "id": 710420418, + "email": "joern.berkefeld@accenture.com", + "name": "Jörn Berkefeld", + "userId": "710420418" + }, + "enterpriseId": 1111111, + "memberId": 9999999, + "status": { + "id": 1, + "name": "Draft" + }, + "thumbnail": { + "thumbnailUrl": "/v1/assets/9451/thumbnail" + }, + "category": { + "id": 90888, + "name": "Test Folder", + "parentId": 89397 + }, + "content": "/* insert code here */\n", + "meta": { + "cloudPages": { + "publishDate": "2025-03-24 06:05:23.203" + } + }, + "availableViews": [], + "data": { + "site": { + "content": "{\"url\":\"https://oss-test.accenture.com/test_coderesource\"}" + } + }, + "modelVersion": 2 +} diff --git a/test/resources/9999999/asset/v1/content/assets/9456/get-response.json b/test/resources/9999999/asset/v1/content/assets/9456/get-response.json new file mode 100644 index 000000000..8ce0fb7be --- /dev/null +++ b/test/resources/9999999/asset/v1/content/assets/9456/get-response.json @@ -0,0 +1,56 @@ +{ + "id": 9456, + "customerKey": "test_microsite", + "objectID": "5f717219-6766-48da-9843-e514cc9aa919", + "assetType": { + "id": 248, + "name": "microsite", + "displayName": "Microsite" + }, + "version": 1, + "name": "test_microsite", + "description": "", + "owner": { + "id": 710420418, + "email": "joern.berkefeld@randstad.com", + "name": "Jörn Berkefeld", + "userId": "710420418" + }, + "createdDate": "2025-03-25T03:01:05.467-06:00", + "createdBy": { + "id": 710420418, + "email": "joern.berkefeld@randstad.com", + "name": "Jörn Berkefeld", + "userId": "710420418" + }, + "modifiedDate": "2025-03-25T03:12:51.85-06:00", + "modifiedBy": { + "id": 710420418, + "email": "joern.berkefeld@randstad.com", + "name": "Jörn Berkefeld", + "userId": "710420418" + }, + "enterpriseId": 1111111, + "memberId": 9999999, + "status": { + "id": 1, + "name": "Draft" + }, + "thumbnail": { + "thumbnailUrl": "/v1/assets/9456/thumbnail" + }, + "category": { + "id": 90888, + "name": "Test Folder", + "parentId": 89397 + }, + "content": "{\"url\":\"https://cloud.eu.randstad.com/test_microsite\"}", + "meta": { + "thumbnailRefAssetId": 9461, + "cloudPages": { + "publishDate": "2025-03-25 03:12:51.850" + } + }, + "availableViews": [], + "modelVersion": 2 +} diff --git a/test/resources/9999999/asset/v1/content/assets/9458/get-response.json b/test/resources/9999999/asset/v1/content/assets/9458/get-response.json new file mode 100644 index 000000000..cb25196ae --- /dev/null +++ b/test/resources/9999999/asset/v1/content/assets/9458/get-response.json @@ -0,0 +1,56 @@ +{ + "id": 9458, + "customerKey": "test_interactivecontent", + "objectID": "02b1c184-87fb-4c58-ba3d-22d811c6cbbd", + "assetType": { + "id": 249, + "name": "interactivecontent", + "displayName": "Interactive Email Page" + }, + "version": 1, + "name": "test_interactivecontent", + "description": "", + "owner": { + "id": 710420418, + "email": "joern.berkefeld@accenture.com", + "name": "Jörn Berkefeld", + "userId": "710420418" + }, + "createdDate": "2025-03-25T03:02:46.823-06:00", + "createdBy": { + "id": 710420418, + "email": "joern.berkefeld@accenture.com", + "name": "Jörn Berkefeld", + "userId": "710420418" + }, + "modifiedDate": "2025-03-25T03:02:55.307-06:00", + "modifiedBy": { + "id": 710420418, + "email": "joern.berkefeld@accenture.com", + "name": "Jörn Berkefeld", + "userId": "710420418" + }, + "enterpriseId": 1111111, + "memberId": 9999999, + "status": { + "id": 1, + "name": "Draft" + }, + "thumbnail": { + "thumbnailUrl": "/v1/assets/9458/thumbnail" + }, + "category": { + "id": 90888, + "name": "Test Folder", + "parentId": 89397 + }, + "content": "{\"url\":\"https://oss-test.accenture.com/test_interactivecontent\"}", + "meta": { + "thumbnailRefAssetId": 9459, + "cloudPages": { + "publishDate": "2025-03-25 03:02:55.307" + } + }, + "availableViews": [], + "modelVersion": 2 +} diff --git a/test/resources/9999999/asset/v1/content/assets/9460/get-response.json b/test/resources/9999999/asset/v1/content/assets/9460/get-response.json new file mode 100644 index 000000000..8d2c851fd --- /dev/null +++ b/test/resources/9999999/asset/v1/content/assets/9460/get-response.json @@ -0,0 +1,59 @@ +{ + "id": 9460, + "customerKey": "test_coderesource_xml", + "objectID": "66787c5f-3d36-4a61-91a5-34e760391505", + "contentType": "application/xml", + "assetType": { + "id": 245, + "name": "xmlcoderesource", + "displayName": "XML Code Resource" + }, + "version": 1, + "name": "test_coderesource_xml", + "description": "", + "owner": { + "id": 710420418, + "email": "joern.berkefeld@accenture.com", + "name": "Jörn Berkefeld", + "userId": "710420418" + }, + "createdDate": "2025-03-25T03:03:45.713-06:00", + "createdBy": { + "id": 710420418, + "email": "joern.berkefeld@accenture.com", + "name": "Jörn Berkefeld", + "userId": "710420418" + }, + "modifiedDate": "2025-03-25T03:04:06.48-06:00", + "modifiedBy": { + "id": 710420418, + "email": "joern.berkefeld@accenture.com", + "name": "Jörn Berkefeld", + "userId": "710420418" + }, + "enterpriseId": 1111111, + "memberId": 9999999, + "status": { + "id": 1, + "name": "Draft" + }, + "thumbnail": { + "thumbnailUrl": "/v1/assets/9460/thumbnail" + }, + "category": { + "id": 90888, + "name": "Test Folder", + "parentId": 89397 + }, + "content": "<xml>test</xml>", + "meta": { + "cloudPages": {} + }, + "availableViews": [], + "data": { + "site": { + "content": "{\"url\":\"https://oss-test.accenture.com/test_coderesource_xml\"}" + } + }, + "modelVersion": 2 +} diff --git a/test/resources/9999999/asset/v1/content/assets/9463/get-response.json b/test/resources/9999999/asset/v1/content/assets/9463/get-response.json new file mode 100644 index 000000000..ce2228150 --- /dev/null +++ b/test/resources/9999999/asset/v1/content/assets/9463/get-response.json @@ -0,0 +1,61 @@ +{ + "id": 9463, + "customerKey": "test_coderesource_json", + "objectID": "5974959b-c531-404b-9361-e27d0d760b37", + "contentType": "application/json", + "assetType": { + "id": 242, + "name": "jsoncoderesource", + "displayName": "JSON Code Resource" + }, + "version": 1, + "name": "test_coderesource_json", + "description": "", + "owner": { + "id": 710420418, + "email": "joern.berkefeld@accenture.com", + "name": "Jörn Berkefeld", + "userId": "710420418" + }, + "createdDate": "2025-03-25T03:15:22.72-06:00", + "createdBy": { + "id": 710420418, + "email": "joern.berkefeld@accenture.com", + "name": "Jörn Berkefeld", + "userId": "710420418" + }, + "modifiedDate": "2025-03-25T03:16:40.913-06:00", + "modifiedBy": { + "id": 710420418, + "email": "joern.berkefeld@accenture.com", + "name": "Jörn Berkefeld", + "userId": "710420418" + }, + "enterpriseId": 1111111, + "memberId": 9999999, + "status": { + "id": 1, + "name": "Draft" + }, + "thumbnail": { + "thumbnailUrl": "/v1/assets/9463/thumbnail" + }, + "category": { + "id": 90888, + "name": "Test Folder", + "parentId": 89397 + }, + "content": "{\n\"test\": true\n}", + "meta": { + "cloudPages": { + "publishDate": "2025-03-25 03:16:40.913" + } + }, + "availableViews": [], + "data": { + "site": { + "content": "{\"url\":\"https://oss-test.accenture.com/test_coderesource_json\"}" + } + }, + "modelVersion": 2 +} diff --git a/test/resources/9999999/asset/v1/content/assets/9465/get-response.json b/test/resources/9999999/asset/v1/content/assets/9465/get-response.json new file mode 100644 index 000000000..652473d9d --- /dev/null +++ b/test/resources/9999999/asset/v1/content/assets/9465/get-response.json @@ -0,0 +1,54 @@ +{ + "id": 9465, + "customerKey": "test_landingpage", + "objectID": "7e515e0c-e13e-442e-b076-fe768782b453", + "assetType": { + "id": 247, + "name": "landingpage", + "displayName": "Landing Page" + }, + "version": 1, + "name": "test_landingpage", + "description": "", + "owner": { + "id": 710420418, + "email": "joern.berkefeld@accenture.com", + "name": "Jörn Berkefeld", + "userId": "710420418" + }, + "createdDate": "2025-03-25T03:17:51.88-06:00", + "createdBy": { + "id": 710420418, + "email": "joern.berkefeld@accenture.com", + "name": "Jörn Berkefeld", + "userId": "710420418" + }, + "modifiedDate": "2025-03-25T03:17:52.187-06:00", + "modifiedBy": { + "id": 710420418, + "email": "joern.berkefeld@accenture.com", + "name": "Jörn Berkefeld", + "userId": "710420418" + }, + "enterpriseId": 1111111, + "memberId": 9999999, + "status": { + "id": 1, + "name": "Draft" + }, + "thumbnail": { + "thumbnailUrl": "/v1/assets/9465/thumbnail" + }, + "category": { + "id": 90888, + "name": "Test Folder", + "parentId": 89397 + }, + "content": "{\"url\":\"https://oss-test.accenture.com/test_landingpage\"}", + "meta": { + "thumbnailRefAssetId": 9466, + "cloudPages": {} + }, + "availableViews": [], + "modelVersion": 2 +} diff --git a/test/resources/9999999/asset/v1/content/assets/950143/delete-response.txt b/test/resources/9999999/asset/v1/content/assets/950143/delete-response.txt new file mode 100644 index 000000000..d86bac9de --- /dev/null +++ b/test/resources/9999999/asset/v1/content/assets/950143/delete-response.txt @@ -0,0 +1 @@ +OK diff --git a/test/resources/9999999/asset/v1/content/assets/950143/get-response.json b/test/resources/9999999/asset/v1/content/assets/950143/get-response.json new file mode 100644 index 000000000..99ced7d9b --- /dev/null +++ b/test/resources/9999999/asset/v1/content/assets/950143/get-response.json @@ -0,0 +1,97 @@ +{ + "id": 950143, + "customerKey": "testExisting_asset", + "objectID": "198ad191-59ae-44d1-9981-ffa71b076ad9", + "contentType": "text/html", + "assetType": { + "id": 205, + "name": "webpage", + "displayName": "Web Page" + }, + "version": 1, + "name": "testExisting_asset", + "owner": { + "id": 717319337, + "email": "joern.berkefeld@accenture.com", + "name": "Jörn Berkefeld", + "userId": "717319337" + }, + "createdDate": "2021-09-13T12:14:02.32-06:00", + "createdBy": { + "id": 717319337, + "email": "joern.berkefeld@accenture.com", + "name": "Jörn Berkefeld", + "userId": "717319337" + }, + "modifiedDate": "2023-08-02T07:10:29.553-06:00", + "modifiedBy": { + "id": 700304523, + "name": "SFMC DEVOPS app user", + "userId": "700304523" + }, + "enterpriseId": 111111, + "memberId": 999999, + "status": { + "id": 1, + "name": "Draft" + }, + "thumbnail": { + "thumbnailUrl": "/v1/assets/950143/thumbnail" + }, + "category": { + "id": 89397 + }, + "meta": { + "globalStyles": { + "isLocked": false, + "body": { + "max-width": "1280px", + "color": "#000000", + "font-family": "Arial", + "font-size": "12px", + "margin": "0px auto" + }, + "template": { + "background-color": "#FFFFFF", + "border": "none", + "box-sizing": "border-box", + "padding": "0px", + "width": "100%" + } + } + }, + "views": { + "html": { + "thumbnail": {}, + "content": "<!DOCTYPE html>\n<html>\n <head>\n <meta\n name=\"viewport\"\n content=\"width=device-width, initial-scale=1, maximum-scale=1, user-scalable=0\"\n />\n <meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\" />\n <style class=\"main_style\">\n .layout-canvas-g {\n background-color: #ffffff;\n border: none;\n box-sizing: border-box;\n padding: 0px;\n width: 100%;\n }\n .layout-canvas-g > .header,\n .layout-canvas-g > .section,\n .layout-canvas-g > .footer {\n position: relative;\n overflow: hidden;\n width: 100%;\n overflow-wrap: break-word;\n }\n .layout-canvas-g > .section {\n margin: 10px 0px;\n }\n .layout-canvas-g > .section > .columns {\n box-sizing: border-box;\n overflow-wrap: break-word;\n }\n body {\n color: #000000;\n font-family: Arial;\n font-size: 12px;\n margin: 0px auto;\n max-width: 1280px;\n }\n @media only screen and (max-width: 480px) {\n .mobile-hidden {\n display: none !important;\n }\n .responsive-td {\n width: 100% !important;\n display: block !important;\n padding: 0px !important;\n }\n }\n .layout-canvas-g > .section > .columns {\n width: 100%;\n }\n </style>\n </head>\n <body>\n <div class=\"layout layout-canvas-g\">\n <div class=\"section\">\n <div class=\"columns col1\">\n <div data-type=\"slot\" data-key=\"col1\"></div>\n </div>\n </div>\n </div>\n </body>\n</html>\n", + "slots": { + "col1": { + "content": "<div data-type=\"block\" data-key=\"bgbqbbx4we9\"></div>", + "design": "<p style=\"font-family:arial;color:#ccc;font-size:11px;text-align:center;vertical-align:middle;font-weight:bold;padding:10px;margin:0;border:#ccc dashed 1px;\">Drop blocks or content here</p>", + "blocks": { + "bgbqbbx4we9": { + "assetType": { + "id": 197, + "name": "htmlblock" + }, + "content": "<table cellpadding=\"0\" cellspacing=\"0\" width=\"100%\" role=\"presentation\" style=\"min-width: 100%; \" class=\"stylingblock-content-wrapper\"><tr><td class=\"stylingblock-content-wrapper camarker-inner\">\n%%[FOR @I=1 TO 1000 DO\n SET @a = CONCAT(IIF(MOD(@i, 3)==0, \"Fizz\", \"\"), IIF(MOD(@i,5)==0,\"Buzz\",\"\"), IIF(MOD(@i, 7)==0, \"Boing\", \"\"), IIF(MOD(@i,11)==0,\"Bang\",\"\"))\nOUTPUT(CONCAT(@a, IIF(LENGTH(@a)>0, \"\", @i), \"<br>\"))NEXT @i\n]%%\n</td></tr></table>", + "design": "<table cellpadding=\"0\" cellspacing=\"0\" width=\"100%\" role=\"presentation\" style=\"min-width: 100%; \" class=\"stylingblock-content-wrapper\"><tr><td class=\"stylingblock-content-wrapper camarker-inner\"><div class=\"default-design\"></div></td></tr></table>", + "meta": { + "wrapperStyles": { + "mobile": { + "visible": true + } + } + }, + "modelVersion": 2 + } + }, + "modelVersion": 2 + } + }, + "modelVersion": 2 + } + }, + "availableViews": ["html"], + "modelVersion": 2 +} diff --git a/test/resources/9999999/asset/v1/content/assets/get-response-customerKey=testExisting_asset.json b/test/resources/9999999/asset/v1/content/assets/get-response-customerKey=testExisting_asset.json new file mode 100644 index 000000000..2359f37b0 --- /dev/null +++ b/test/resources/9999999/asset/v1/content/assets/get-response-customerKey=testExisting_asset.json @@ -0,0 +1,105 @@ +{ + "count": 1, + "page": 1, + "pageSize": 50, + "links": {}, + "items": [ + { + "id": 950143, + "customerKey": "testExisting_asset", + "objectID": "198ad191-59ae-44d1-9981-ffa71b076ad9", + "contentType": "text/html", + "assetType": { + "id": 205, + "name": "webpage", + "displayName": "Web Page" + }, + "version": 1, + "name": "testExisting_asset", + "owner": { + "id": 717319337, + "email": "joern.berkefeld@accenture.com", + "name": "Jörn Berkefeld", + "userId": "717319337" + }, + "createdDate": "2021-09-13T12:14:02.32-06:00", + "createdBy": { + "id": 717319337, + "email": "joern.berkefeld@accenture.com", + "name": "Jörn Berkefeld", + "userId": "717319337" + }, + "modifiedDate": "2023-08-02T07:10:29.553-06:00", + "modifiedBy": { + "id": 700304523, + "name": "SFMC DEVOPS app user", + "userId": "700304523" + }, + "enterpriseId": 111111, + "memberId": 999999, + "status": { + "id": 1, + "name": "Draft" + }, + "thumbnail": { + "thumbnailUrl": "/v1/assets/950143/thumbnail" + }, + "category": { + "id": 89397 + }, + "meta": { + "globalStyles": { + "isLocked": false, + "body": { + "max-width": "1280px", + "color": "#000000", + "font-family": "Arial", + "font-size": "12px", + "margin": "0px auto" + }, + "template": { + "background-color": "#FFFFFF", + "border": "none", + "box-sizing": "border-box", + "padding": "0px", + "width": "100%" + } + } + }, + "views": { + "html": { + "thumbnail": {}, + "content": "<!DOCTYPE html>\n<html>\n <head>\n <meta\n name=\"viewport\"\n content=\"width=device-width, initial-scale=1, maximum-scale=1, user-scalable=0\"\n />\n <meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\" />\n <style class=\"main_style\">\n .layout-canvas-g {\n background-color: #ffffff;\n border: none;\n box-sizing: border-box;\n padding: 0px;\n width: 100%;\n }\n .layout-canvas-g > .header,\n .layout-canvas-g > .section,\n .layout-canvas-g > .footer {\n position: relative;\n overflow: hidden;\n width: 100%;\n overflow-wrap: break-word;\n }\n .layout-canvas-g > .section {\n margin: 10px 0px;\n }\n .layout-canvas-g > .section > .columns {\n box-sizing: border-box;\n overflow-wrap: break-word;\n }\n body {\n color: #000000;\n font-family: Arial;\n font-size: 12px;\n margin: 0px auto;\n max-width: 1280px;\n }\n @media only screen and (max-width: 480px) {\n .mobile-hidden {\n display: none !important;\n }\n .responsive-td {\n width: 100% !important;\n display: block !important;\n padding: 0px !important;\n }\n }\n .layout-canvas-g > .section > .columns {\n width: 100%;\n }\n </style>\n </head>\n <body>\n <div class=\"layout layout-canvas-g\">\n <div class=\"section\">\n <div class=\"columns col1\">\n <div data-type=\"slot\" data-key=\"col1\"></div>\n </div>\n </div>\n </div>\n </body>\n</html>\n", + "slots": { + "col1": { + "content": "<div data-type=\"block\" data-key=\"bgbqbbx4we9\"></div>", + "design": "<p style=\"font-family:arial;color:#ccc;font-size:11px;text-align:center;vertical-align:middle;font-weight:bold;padding:10px;margin:0;border:#ccc dashed 1px;\">Drop blocks or content here</p>", + "blocks": { + "bgbqbbx4we9": { + "assetType": { + "id": 197, + "name": "htmlblock" + }, + "content": "<table cellpadding=\"0\" cellspacing=\"0\" width=\"100%\" role=\"presentation\" style=\"min-width: 100%; \" class=\"stylingblock-content-wrapper\"><tr><td class=\"stylingblock-content-wrapper camarker-inner\">\n%%[FOR @I=1 TO 1000 DO\n SET @a = CONCAT(IIF(MOD(@i, 3)==0, \"Fizz\", \"\"), IIF(MOD(@i,5)==0,\"Buzz\",\"\"), IIF(MOD(@i, 7)==0, \"Boing\", \"\"), IIF(MOD(@i,11)==0,\"Bang\",\"\"))\nOUTPUT(CONCAT(@a, IIF(LENGTH(@a)>0, \"\", @i), \"<br>\"))NEXT @i\n]%%\n</td></tr></table>", + "design": "<table cellpadding=\"0\" cellspacing=\"0\" width=\"100%\" role=\"presentation\" style=\"min-width: 100%; \" class=\"stylingblock-content-wrapper\"><tr><td class=\"stylingblock-content-wrapper camarker-inner\"><div class=\"default-design\"></div></td></tr></table>", + "meta": { + "wrapperStyles": { + "mobile": { + "visible": true + } + } + }, + "modelVersion": 2 + } + }, + "modelVersion": 2 + } + }, + "modelVersion": 2 + } + }, + "availableViews": ["html"], + "modelVersion": 2 + } + ] +} diff --git a/test/resources/9999999/asset/v1/content/assets/post-response-key=testNew_assetMessage.json b/test/resources/9999999/asset/v1/content/assets/post-response-key=testNew_assetMessage.json new file mode 100644 index 000000000..b57ff7d10 --- /dev/null +++ b/test/resources/9999999/asset/v1/content/assets/post-response-key=testNew_assetMessage.json @@ -0,0 +1,441 @@ +{ + "id": 2454776, + "customerKey": "testNew_assetMessage", + "contentType": "application/vnd.etmc.email.Message; kind=template", + "assetType": { + "name": "templatebasedemail", + "displayName": "Template-Based Email" + }, + "fileProperties": { + "fileName": "testNew_assetMessage" + }, + "name": "testNew_assetMessage", + "owner": { + "email": "joern.berkefeld@accenture.com", + "name": "Jörn Berkefeld" + }, + "createdDate": "2022-11-08T09:59:30.727-06:00", + "createdBy": { + "email": "joern.berkefeld@accenture.com", + "name": "Jörn Berkefeld" + }, + "modifiedDate": "2024-08-07T06:12:40.75-06:00", + "modifiedBy": { + "name": "Jörn Berkefeld" + }, + "memberId": 9999999, + "status": { + "name": "Draft" + }, + "meta": { + "globalStyles": { + "isLocked": false, + "template": { + "background-color": "#FFFFFF", + "border-width": "0px", + "border-style": "solid" + }, + "body": { + "background-color": "#FFFFFF", + "font-family": "Arial,helvetica,sans-serif", + "font-size": "16px", + "color": "#000000", + "line-height": 1, + "padding": "0px", + "content-padding-top": "0px", + "content-padding-right": "0px", + "content-padding-bottom": "0px", + "content-padding-left": "0px" + }, + "h1": { + "font-family": "Arial,helvetica,sans-serif", + "font-size": "28px", + "color": "#808080", + "line-height": 1, + "font-weight": "bold", + "font-style": "normal" + }, + "h2": { + "font-family": "Arial,helvetica,sans-serif", + "font-size": "22px", + "color": "#808080", + "line-height": 1, + "font-weight": "bold", + "font-style": "normal" + }, + "h3": { + "font-family": "Arial,helvetica,sans-serif", + "font-size": "20px", + "color": "#808080", + "line-height": 1, + "font-weight": "bold", + "font-style": "normal" + }, + "links": { + "font-weight": "normal", + "color": "#808080", + "text-decoration": "none" + }, + "buttons": { + "font-family": "Arial,helvetica,sans-serif", + "font-size": "16px", + "color": "#FFFFFF", + "background-color": "#5D5D5D", + "border-radius": "3px", + "padding": "10px", + "border-color": "#5D5D5D", + "border-width": "1px", + "border-style": "solid" + }, + "mobile": { + "body": { + "padding": "0px", + "font-size": "16px", + "line-height": 1.5 + }, + "h1": { + "font-size": "22px", + "line-height": 1 + }, + "h2": { + "font-size": "20px", + "line-height": 1 + }, + "h3": { + "font-size": "18px", + "line-height": 1 + }, + "buttons": { + "font-family": "Arial,helvetica,sans-serif", + "font-size": "16px", + "color": "#FFFFFF", + "padding": "10px" + } + } + } + }, + "views": { + "subjectline": { + "contentType": "application/vnd.etmc.email.View; kind=subjectline", + "thumbnail": {}, + "content": "A note", + "availableViews": [], + "data": { + "email": { + "options": {} + } + }, + "modelVersion": 2 + }, + "preheader": { + "thumbnail": {}, + "availableViews": [], + "data": { + "email": { + "options": {} + } + }, + "modelVersion": 2 + }, + "text": { + "thumbnail": {}, + "availableViews": [], + "data": { + "email": { + "options": { + "generateFrom": "html" + } + } + }, + "generateFrom": "html", + "modelVersion": 2 + }, + "viewAsAWebPage": { + "thumbnail": {}, + "availableViews": [], + "data": { + "email": { + "options": {} + } + }, + "modelVersion": 2 + }, + "subscriptioncenter": { + "thumbnail": {}, + "availableViews": [], + "data": { + "email": { + "options": {} + } + }, + "modelVersion": 2 + }, + "forwardHTML": { + "thumbnail": {}, + "availableViews": [], + "data": { + "email": { + "options": {} + } + }, + "modelVersion": 2 + }, + "forwardText": { + "thumbnail": {}, + "availableViews": [], + "data": { + "email": { + "options": {} + } + }, + "modelVersion": 2 + }, + "html": { + "thumbnail": {}, + "availableViews": [], + "slots": { + "banner": { + "content": "<table cellpadding=\"0\" cellspacing=\"0\" width=\"100%\" role=\"presentation\" style=\"background-color: transparent; min-width: 100%; \" class=\"slot-styling\"><tr><td style=\"padding: 0px; \" class=\"slot-styling camarker-inner\"><div data-type=\"block\" data-key=\"ms2rjhckdsr\"></div><div data-type=\"block\" data-key=\"vlh4b2my8gp\"></div><div data-type=\"block\" data-key=\"x0ecuu93q1k\"></div><div data-type=\"block\" data-key=\"8uflrc8ao4r\"></div><div data-type=\"block\" data-key=\"1bd95vemqf4\"></div></td></tr></table>", + "design": "<table cellpadding=\"0\" cellspacing=\"0\" width=\"100%\" role=\"presentation\" style=\"background-color: transparent; min-width: 100%; \" class=\"slot-styling\"><tr><td style=\"padding: 0px; \" class=\"slot-styling camarker-inner\"><p style=\"font-family:Arial;color:#ccc;font-size:12px;text-align:center;vertical-align:middle;font-weight:bold;height:150px;display:flex;flex-direction:column;justify-content:center;padding:10px;margin:0;border: #cccccc dashed 1px;\">Drop blocks or content here</p></td></tr></table>", + "meta": { + "wrapperStyles": { + "mobile": { + "visible": true, + "columnOrder": "ltr" + }, + "styling": { + "background-color": "transparent", + "margin": "0px", + "padding": "0px" + } + } + }, + "availableViews": [], + "blocks": { + "vlh4b2my8gp": { + "assetType": { + "id": 196, + "name": "textblock" + }, + "name": "sample content block", + "design": "<table cellpadding=\"0\" cellspacing=\"0\" width=\"100%\" role=\"presentation\" style=\"background-color: transparent; min-width: 100%; \" class=\"stylingblock-content-wrapper\"><tr><td style=\"padding: 20px; \" class=\"stylingblock-content-wrapper camarker-inner\"><div class=\"default-design\" style=\"height:150px; overflow:hidden;\"><p class=\"textblock\" style=\"margin:0; padding:0; overflow:hidden; display:block;\">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Morbi vestibulum nunc feugiat porta consectetur. Sed vehicula vel ante suscipit sagittis. Ut metus metus, feugiat ut laoreet blandit, viverra non mi. Phasellus convallis, mauris ac vehicula posuere, ligula magna mattis ipsum, in sollicitudin nibh lacus eget sapien. Mauris ultricies laoreet ex, a viverra leo ornare eu. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Mauris commodo scelerisque arcu, id semper sem pharetra vel. Sed ut erat auctor lectus pretium blandit gravida vitae enim. Nullam eget ex et enim molestie porttitor. Duis vitae est fringilla, placerat nisi condimentum, tristique purus. Fusce lobortis mauris quis iaculis ultrices. In tempor ligula ac ex tempor rutrum. Pellentesque quis convallis mi.<br><br>Duis mattis, ex a hendrerit ullamcorper, eros massa consectetur elit, vel lobortis justo arcu ac mi magna, blandit sit amet eros id, dapibus cursus justo. Suspendisse mauris odio, aliquet ut ligula in, porta mollis risus. Ut ultrices lectus dolor, sed euismod nulla ultrices ac. Phasellus laoreet ultricies facilisis. Fusce imperdiet maximus ipsum vitae rutrum. Maecenas faucibus vestibulum lorem sit amet varius. Vivamus et ultricies ligula. Mauris semper scelerisque ante id fermentum. Curabitur non odio pellentesque, consectetur odio eu, commodo risus. Mauris egestas elit vel ipsum sagittis fermentum. Cras varius quam ac enim eleifend, eu porttitor odio finibus. Aenean quis finibus dolor. Nunc bibendum aliquam auctor.</p></div></td></tr></table>", + "meta": { + "wrapperStyles": { + "mobile": { + "visible": true, + "columnOrder": "ltr" + }, + "styling": { + "background-color": "transparent", + "margin": "0px", + "padding": "20px" + } + } + }, + "availableViews": [], + "data": { + "email": { + "options": {} + } + }, + "modelVersion": 2, + "id": 1322777, + "objectID": "26fdf503-eeed-49eb-b428-cb3ghbc2ba49" + }, + "ms2rjhckdsr": { + "assetType": { + "id": 199, + "name": "imageblock" + }, + "design": "<table cellpadding=\"0\" cellspacing=\"0\" width=\"100%\" role=\"presentation\" style=\"min-width: 100%; \" class=\"stylingblock-content-wrapper\"><tr><td class=\"stylingblock-content-wrapper camarker-inner\"><div class=\"default-design\"><div style=\"width:100%;height:150px;background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAABuoAAACWBAMAAADK78OEAAAAKlBMVEUFBwgFBwgFBwgFBwgFBwgFBwgFBwgFBwgFBwgFBwgFBwgFBwgFBwgFBwhamwL+AAAADXRSTlMwmGPLQ97yfrGki3G+5/n17AAACcpJREFUeF7s2kGL00AYh/FJNhLrKrSy4KlQZBEvhUrOhS6wy168CQiYi/QaWOl5QbwXehaEfoQF/BqCpqSC8P8uBpxjtFs6KTPx+X2E981DZkJMwAAAAAAAAAAAAAAAAAAAQHJujgpAVJr/FEB1yDJzVKA6SMYXoDqqA9WB6kB1MdU5BaqjOlAd1VEdqO6U6jBodkZ1LYmoDmpWmpZQ3YjqHKI6qqM6UB3VUR3VUR3VYZGpWZWtqK4NVIeh/mpCdQ5QHajOAar7MJAGz8xOSGdU54VobUI3VW1jdsK46Z6mfyl9rC4Jv7q+8U7STnXIyy5UF2cmdD0Pq3vYSnWIVHWgunga/q5PPKzuyayN6nAl9YOvLlmK6towvmujOkylMvTqfi5FdZYVj4wLw9VeXzBz1apdXzHxSFIVeHU9ieosK8319unMHGw62fdNd49d4Eq1fkNz4XSXOjrXXAwaHLO6lcvoatWrr+ZAxfdOVbfIbowPvqk2D7m6NHe06bEaHLO6icORWJvPI3OAWGWnqhuqbzxwaqcUbnVpLqprHIn17uyQ+8cPc1+9rJC1zVZUt+uAKa2Dre6iUFequ3xjnIhzZ8t6vMdYT/z9f8lKni/16dyXA6Y0D7E6G11XqkvyamZciNwt64G2Haou8uTRjfXHJtDqrgt1prpL6b1v1b2WRlTnftPWXZDVXUudqS4upO2NZ9XdSmuqc+2LrHmI1b1Uh6p7odovz6pbSh+pzrHf7N1BS9tgHMdxFisVx8Ayr0JIRXYRZA96zoTBLoJIwVMB3WCAFLzsKDjYVfAljN0F38BuuwpVTbWuv/cy1dk/jQ2J6dPmn+T3PduQNPlgkjxP6uCpXg7V1VEgdU4L9x3qUtcENhOaM2uQ8NlEuaO6afQ7zZ26Omyqe5Xxti7hoZ6vSV0FwFXCYdII1aa6+AnjX/Km7huKpK7awmMNTepeA7imOrs5kLo5U+egUOoO8L+Oq0KdLKlLdZHVzX3pTzABNzt1VFdFvz1F6qYABFQXcydglDcSNbJTR3UHkPZVqBNKSa40171lhLrwFqluSJUWJHTFYqLaVGetKiR0Rx1Wv2pjA+SoOk17+/eiJOpeNj9lCgO5WamjuhNIwLHlVypejLasOapLuNkp9jU2LaijOgtSVtSoO3u2OlRnJNPEQMlPMKVzqhuM6lrPdjTVIbpkszhCuSVVF7/NbjnVOQk+TnWSd5cfM9foBKG2PKqTQHWzuO+20Oocb7DFVOok9+VnVDlXR3VVY5r2jv4ZGaIb04faAkKd1+bzoG4qvNpUR3U2rk4vRhum25nMU/JauCKqc94iXFCjOglUtyFbP351CFc0dbIK4eOW6iSq+42H9lWoq9T6zRdTHdVRncx5PlShzkG/wC2qOqqjuiYe2tSmDnt61f3ySqWO6qrGrNpUV8FjV+rU4adadcBk1VGd4w00aXWvrA6uka/479jVOcYYhDN3HUfs8Bvfirq6MWuK1VFdiiMv3+pked3xq0NEK1F/07CibhmAHnVUR3Vy8hUoVNdxC6iO6qhONkehOlyPSd1l7XnzStWte5KvTp0jA+yoLsXsMVehOhzbUhdfZ06fuvBnbnxF6uSIOC+6Ou+dXXUy/3IuA3Wx9fyJqUPgqleHHT8DdVQH2FUna7WiUR02J6cOl3I/VZW69Oyozmm9/JKF6toTUSetKFeHbaoDkOa1KWlfu051VIdtReoA6Fb3CaHS/I4d1VEd3lNdUnWVJsLtUh3VJVGXlh3VLUEaZZwh1VEdflBdomYhpX76QnVUl5wd1VWOMKxG9urW+2u25edFHdV15qkuvo8YWsfNXN0G+rma1FGdfNvp2FFdK4pK5uqmZUfm5wyT6hDsU11cUKtuBk/18qCO6oRdQdQ5nueXTZ3c5rkdnzqqC7yHjuypQ+AWQ90b4LvM+iiHOkcWMC51VCdZVIdLtyDqnuqclkWdXHK2c6POPPan5OrQ84ulDu1cqqtJtaSP4M/y97xOTrHKrQ43fvbqqC7NHlnIrTrslV0dzn1V6qgOjYmqm8Kw3HGpix5SV18FgMCUQh12fFXqqC5wi6VOXsce/f9cjKEc6vBVlTqqw659df/Yu6OVBIIoDMAUUnSnBHQVyEIQQVAOEQHCFtB9EnQlRPUAvYBg0APso/gIAT2AruwKwXmXaFOPeFxm3XVHx/n/y5nBmXXO5wIrs+tVJz/g0Xl19LRg+prMkRl1UBf3tk+d/i91t+2k59IVddTS7BLDMaAO6ihcu7oPfvi5KnXao/uaSUfVGXXUKK4O6uQsVqrjhIXUaYo4gDr6XkZdpSZTt1jdgZomMKQO6oY+1FE3k7r0XajaqE4W3oUhdVBHLaijvkF1PGLgrDqoi3tm1UEd1EEd/SyjDuoqh6LvoZ5FnTeTM8fVQR19ZlMHdbw4ec16dU05bQnq5NNGfxPVQV3kL3jjc9dmdaGX5NxBdXL19ezqiPqG1EEdvSwomTdb1BUP1HGG6saMOqiL3+WRFKM86jjWqku7R8ZKqWB71XGGpauDOvl253tKEjmqTnMfX5U6qIM6+uIldnizbFMHdbxXG6wO6mTZtcdNXQvUQR3HXnVQx5M8a9RBHdRVvNn41qgLvXFO1qtOnu852gZ1UDc5tu+4DHU7c7zLVMd96ep2+QdAqFs2kfrPlQl1e/zt268O6jgOqONrqRZWxzGhrjNt86FuLi3vL6dQJ3qKqYM6ro0A6nQprg7qoG5fKW57VY3c6qAO6pRS11CnGyUHhu6pg7qoNk1OdZxBbnU1kXR1d94kJ0Ldbzt3j9JAEAZgGELAwmpAsJUFrQMDdinS24TUqaytPEcgF/AI3sUkIGnmLhIRN+usNib7kzzvEb6dhx1mYFIl6gaxbNlrdXm9VJfXorqU9Zu6PwdEXbXKD2F0tuqoo24Q0l7TK+qoo+74Z5gps3AkdZXbx8dYNqJu1yTsuqaOuiZ6o64c+oY66g4bddRtQwh9Vkcddauw6Ly6vAbVUUfduthbnZNQaZGp+3fUUUdd2apmyn1SRx111FFHHXXUUUcddcV3t9TlUUddC1FHHXXtRx111FFHHXXUzWIcN6OOOuqoK+unOurW5YNALagbnoc66qjLa03dXbPqqKOOuovUZXXUbcNX49NRR91LJ9VRl9eAumaWHXUPqR1126IoXs9RHXXUDeepK1FH3am3iZ/dpzNRRx11oi6POlFHHXXUUVfWZ3XPMcb045XKG+qoy2/NDqSOuvrPSx11NVFH3QGjjjrqqLt8oo66BtN7jPPU26ijTtRRJ+qoq93LzJZHUydRl2obnYQ6UUedRN0qhJBqm4awSBJ1HUyiTtIHMv/VI7tXCZsAAAAASUVORK5CYII=) repeat-x 0 0\"></div></div></td></tr></table>", + "meta": { + "wrapperStyles": { + "mobile": { + "visible": true + } + } + }, + "availableViews": [], + "data": { + "email": { + "options": {} + } + }, + "modelVersion": 2 + }, + "1bd95vemqf4": { + "assetType": { + "id": 195, + "name": "freeformblock", + "displayName": "Free Form Block" + }, + "fileProperties": { + "fileName": "Footer" + }, + "name": "Footer", + "owner": { + "id": 710265361, + "email": "joern.berkefeld@accenture.com", + "name": "Jörn Berkefeld", + "userId": "710265361" + }, + "createdDate": "2022-06-27T07:17:04Z", + "createdBy": { + "id": 710265361, + "email": "joern.berkefeld@accenture.com", + "name": "Jörn Berkefeld", + "userId": "710265361" + }, + "modifiedDate": "2022-06-27T07:19:07Z", + "modifiedBy": { + "id": 710265361, + "email": "joern.berkefeld@accenture.com", + "name": "Jörn Berkefeld", + "userId": "710265361" + }, + "enterpriseId": 510004860, + "memberId": 510006764, + "status": { + "id": 1, + "name": "Draft" + }, + "category": { + "id": 4795, + "name": "Content Builder", + "parentId": 0 + }, + "design": "<table cellpadding=\"0\" cellspacing=\"0\" width=\"100%\" role=\"presentation\" style=\"min-width: 100%; \" class=\"stylingblock-content-wrapper\"><tr><td class=\"stylingblock-content-wrapper camarker-inner\"><div class=\"default-design\" style=\"height:150px; overflow:hidden;\"><p class=\"textblock\" style=\"margin:0; padding:0; overflow:hidden;\"><span style=\"float:left; margin: 0 6px 6px 0; width:50%; height: 75px; overflow:hidden; background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAA2sAAABLCAMAAADZL+8JAAAAS1BMVEUBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQGt0wPNAAAAGHRSTlMw51fNi5ilsr9K83HZPWR+N/rhxmq4rESzSUQKAAAGxElEQVR4XuzYW46DMAxAUUMDacK7pcX7X+lMNX+IoUgF5Kj3rMBSdKPE8j0AAAAAAACAIGcAcDEwA6bsLscDrSFoLfaB1npaOwVorem/uDW03aKW1g4Qmi9uDVdd5OUAtBZoLWm0Zh+toYuDLhriSGu7y3NJmys0c6Osw9Ixh0L/5SZam6G1LW8eVHGhHa8rSnOtNcWUeGutvZH2bg1Npo/EW+td1CBJa0dzqRWynXP6Uq++IvFU1WreX7jqCm9qQ93cMtXkW6tkL+F5Kbu8lw+5u2wXZ5sza7pysnDI+iubteP1jUKsmMqoukNrIS7I5Sxjt1tpg74MtXftJ1fiI24f3g/6R2++t7lTN/Af/mHfbpeUBQEwDL8iaAACfvac/5G+W02xlqVtqGjcv9cZRa4R2MlWONVtz5qbWX6s4bEFXxD1NKJd6Wu1n0x/egoXivCkHZVAtf6UzXBJb9EaaQHswprxNaTe/hnKAboXazyI1S3BJVR2c9b0AdiJNQoArQ3JmgHaiX+ZK7jQ5jxaG8i6Uco2Zq1JAX/WWJpiIJV2i1ED0iIgax2QvLU0cpG9W7PFqXenGFxkU9Y6wKe1A56k/s2eewsVD8eaejqm0ZrBqTfvoYRL2etOUusaI+Var7suP+zHWoZbQn92BkCIL2sFAJgpd58I3JUkzTdYY9cmXZMOfqsoJiWjNS8xuFASD2tRH9Yadzr9uhwDyf1ZoweXQq8/vJqSfKm1QsoUT0qk9PgBH5+sMhBrDABUtDZlW0V/si8vbqhAP0X5V1ojeJneiDVCMn/W0qnn99rUuIsZ/uZJQ79FrNGkn/m7tfGRygTuE812rUVrAvBmzZY41SxxNpICr9dkTqFHawz96AzWXNkTPtFatKZxjoVgjeBWXaxtLVqL1ojWPq1RnEtnt0a0VrhL/1QMv56Ke7HGCen8WkOynLVoTdLf6YWtJRgs/2x4Szu3tWR8dpH+NseHtQOA7VqL1lL8Ltu2NeGePSxrAJ3HmsofI0Fao8x1DMyaZj/JXVuzhVdrbkToWtYSdatCv9x6sjZeprUmoVkTcJWsCMoacyMdorX+k5gP9nz+rEl3/eLWxuMLWHOlIVsDBLXBWKO0DtmabdGrpNHaSNFav8SEYg1AwNa4Aj5ZIkVr0RpQyWhttEbgMcVXt2ZwCa0Nx1q0ps2pEo8pHa29jmIwQVa2ZnFLhmAtWhu/h5rswprl3M5iLcVwbO3vmsK14zzWorWWnaq9WQNavgNrGqjzc1mxC2vT+VQb2a8Zda7m27Dm8mgN6I47sHaLbdBal7vMm2cj7UfWJBtIz2GNvfqxLTdnM3L31lCyYk1r0ZqAC8z/OeR/du5tWUEQCsBwIihCCNGu4f2fdI9UYi5T09Z44r/FaQrWd5HOCK31jjT7qTXJfRY+M4EQd2pt8HGbKmEE3Vq05nKzsLW8rPqVNQZW7wa+HtIv6J1aG3zcJqe8byBa07SOTLPm6ALWQGKutZt4dOnAobr3udynNZiVX1gjHJRt19o1eXWfbS0BFx3R2oCWhBzbmku/sFZ2rQ1bg8j4ktbgDXSOYC1agwk51lq0ZsBXE8UYazpr5D+RYFgr5Ft/460ZpdCtRWvwBsys/2vKd1vSWpr7LIK1E4VnM8YaHDmKYY2BXR5pzVqXaG3QrUVr7mbArzlPsRaabw0/aI1xzjvHTAhR7tVaqMC3Fq25HM4KOaC11H1uhdY4bw44A+vRWitJnqULWuPhln84k5VZi9Zg/daE9lkEayVvxDCtEVZleq0Z8kzNnyPxzKFbCycmTLTWTJOqbEPWYPOtmfzR2wUppjXt11SvtaI+JIQ5QrJmKA17dqckWgMd3JpyIGDtSilVC1vLqs5rttbaSYZoTdGQ2rC1S9bKbtdaUneZZi1UTLRWnNslH61J/upaM88enf7bt8NWB0EoAMN0bctjpy4VF/z/v/QyNqYDCcbBlex9vwqU4oMgGFNnPdeGfPpurGhNYkoatVauWWt5x1grz7hsbfc5YwPW0pLlB7L/7O9izemtX6xhrWZYe+7B/i1rW781ZS2oavyANaxhbXWZtb/upZisGTqttVR9a1jDWmoofLd9a1jDGtaCPluwlsIa1upntzZNU1VrWMMa1lLNWcPaqqrhIGtjwBrWDI3zPLt61trPZW/TTmoNa+HRYrB2fFiTe0Os0+a97/bvKkJMYW03rJkjrKn33n2JtUlEcmu9iNisEdYq1XmvDVu7FAYya4S1JRisVQlr9ugico2nC2tYo3asYe26lgZ+3rdG5B51sRDWNJYaDdaIsGaNCGtE9A9/OsOIx1k7gwAAAABJRU5ErkJggg==) repeat-x 0 0\"></span>In viverra et dui id fermentum. Nulla tortor libero, aliquam in dictum id, vestibulum nec lacus. Curabitur sit amet accumsan magna. Mauris mollis eu lorem sodales mattis. Mauris et iaculis odio. Suspendisse et metus maximus, dapibus lectus in, placerat est. Praesent sit amet lacinia ligula. Donec non magna dictum, feugiat arcu vel, volutpat augue. In hac habitasse platea dictumst. Nunc eleifend nulla elit, vel condimentum lectus dictum sit amet. Aliquam ante nulla, dapibus ut nisi vitae, convallis malesuada mauris. Duis mattis, ex a hendrerit ullamcorper, eros massa consectetur elit, vel lobortis justo arcu ac mi magna, blandit sit amet eros id, dapibus cursus justo. Suspendisse mauris odio, aliquet ut ligula in, porta mollis risus. Ut ultrices lectus dolor, sed euismod nulla ultrices ac. Phasellus laoreet ultricies facilisis. Fusce imperdiet maximus ipsum vitae rutrum. Maecenas faucibus vestibulum lorem sit amet varius. Vivamus et ultricies ligula. Mauris semper scelerisque ante id fermentum. Curabitur non odio pellentesque, consectetur odio eu, commodo risus. Mauris egestas elit vel ipsum sagittis fermentum. Cras varius quam ac enim eleifend, eu porttitor odio finibus. Aenean quis finibus dolor. Nunc bibendum aliquam auctor. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Morbi vestibulum nunc feugiat porta consectetur. Sed vehicula vel ante suscipit sagittis. Ut metus metus, feugiat ut laoreet blandit, viverra non mi. Phasellus convallis, mauris ac vehicula posuere, ligula magna mattis ipsum, in sollicitudin nibh lacus eget sapien.</p></div></td></tr></table>", + "meta": { + "wrapperStyles": { + "mobile": { + "visible": true + } + } + }, + "availableViews": [], + "data": { + "email": { + "options": {} + } + }, + "modelVersion": 2 + }, + "x0ecuu93q1k": { + "assetType": { + "id": 223, + "name": "referenceblock" + }, + "design": "<div class=\"default-design\"><div style=\"width:100%;height:150px;background-size:cover;background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAADawAAAEtCAIAAADRXFFBAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAALyhJREFUeNrs3ftvI+l+J2aOSF27JbWu7Z72nPEJdrOws5ss9hcj58R/vWEDQYLAhjdeZHfhcbeGYosiRfFWrHuFPZpty30btcRLFfk8IASKIt+q+r6UVMX61Pt+13r3rgYAAAAAAAAAAABQNY2rd1eqAAAAAAAAAAAAAFTOhhIAAAAAAAAAAAAAVSQECQAAAAAAAAAAAFSSECQAAAAAAAAAAABQSUKQAAAAAAAAAAAAQCUJQQIAAAAAAAAAAACVJAQJAAAAAAAAAAAAVJIQJAAAAAAAAAAAAFBJQpAAAAAAAAAAAABAJQlBAgAAAAAAAAAAAJUkBAkAAAAAAAAAAABUkhAkAAAAAAAAAAAAUElCkAAAAAAAAAAAAEAlCUECAAAAAAAAAAAAlSQECQAAAAAAAAAAAFSSECQAAAAAAAAAAABQSUKQAAAAAAAAAAAAQCUJQQIAAAAAAAAAAACVJAQJAAAAAAAAAAAAVJIQJAAAAAAAAAAAAFBJQpAAAAAAAAAAAABAJQlBAgAAAAAAAAAAAJUkBAkAAAAAAAAAAABUUkMJAAAAAADg4drt9ngSTe88290+Pz9XEAAAAIAlMhIkAAAAAAAAAAAAUElCkAAAAAAAAAAAAEAlCUECAAAAAAAAAAAAlSQECQAAAAAAAAAAAFRSo7Rr1mxexmn26eO///EH3QYAAAAAAAAAAAAYCRIAAAAAAAAAAACoJCFIAAAAAAAAAAAAoJKEIAEAAAAAAAAAAIBKEoIEAAAAAAAAAAAAKkkIEgAAAAAAAACYvSicKAIAMG9CkAAAAAAAAADA7MVxoggAwLwJQQIAAAAAAAAAs5fnmSIAAPMmBAkAAAAAAAAAzF5kJEgAYP6EIAEAAAAAAAAAAIBKEoIEAAAAAAAAAAAAKkkIEgAAAAAAAACYiyicKAIAMFdCkAAAAAAAAADAXMRxoggAwFwJQQIAAAAAAAAAAACV1FACAAAAmLlm8zJOM3X4yOnR4f7BgToAAAAAAACzYiRIAAAAAAAAAAAAoJKEIAEAAAAAAAAAAIBKEoIEAAAAAAAAAAAAKkkIEgAAAAAAAACYvaIo8jxTBwBgrhpKAAAAAAAAAADMXJpm0XeJOgAAc2UkSAAAAAAAAAAAAKCShCABAAAAAAAAAACAShKCBAAAAAAAAAAAACqpoQQAAADwFMF4lGX5Rw9meaEyn4qiqDYYfPTg3t5uvbGpOAAAAAAAwCMIQQIAAMCT9G4HcZqpw0MMg3B6++jB01pt/0AIEgAAAAAAeAzTYQMAAAAAAAAAAACVJAQJAAAAAAAAAMxFkqSKAADMlRAkAAAAAAAAAAAAUElCkAAAAAAAAAAAAEAlCUECAADwVFmaKAIAAAAAH8nyQhEAgHlrlGElfnpz8cQnP9vdPj8/150AAACLNxwMbm77P/7uB6UAAAAA4L4sz+sbdXUAAOaqoQQAAAA8WpYmN7f9vKi12+31uTit2byM00zvz0qn15/ePnx7enS4f3CgLAAAAAAAwEOYDhsAAIDH63Rv7iY1Gk+iYDxSEACAr+jf9qJwog4AAABQUcPBQBFKSAgSAACAxx/qB2H84dvOTV9NAAC+tOPUbF7e9EdxnKgGALBWksx8GgCsjsHQeBBlZDpsAAAAHqnXH97/NsvztZoUGwDgIYaDwWA4ilPn/gGANVUUagDAiojCyfQAf/p1e2dXNUpFCBIAAIDHaLfbWZ5/9GAQRg7+AQDuTPeLbnq3YZwqBQAAAKyAMAynX8fjwHmQshGCBAAA4JsF49F4En36eFHUOt3e69cO/gGAtSb+CAAAAKsnjOLp1yR1vF86QpAAAAB8s85N/0s/itOsc319enamSgDAGsrSpHvT++zlIgAAAEClRb9c7hi56LF8hCABAAD4Np3r608nwr5vNAn3TYoNAKyZu/hjEEZFoRgAAACwggf+dydHpl+n9+uNTTUpjw0lAAAA4OGicDKahF9/zt2k2GoFAKyPzvX1xeW78UQCEgAAAFZTEEw+3B+NRgpSKkaCBAAA4Bt0ur2HnNqP06x/2zt8caRiAMBqu+l2h+Mgl30EAPhEliZ3dyJzhsCyTX8Nb3q3Gxsb9Y2N7e3t/YMDNYFvNQn/ZYSIKE4UpFQWGoIcDgbz2nnKss82vre3a+hRAACAWelcX8dp9sAn9waj58+fOygDAFbYeBIpAgDAl3wYMSuOEyFIWJa7+GMYpx8eGQZhp9ff+K622Ziq7+7sbG1t+iWF35Qk6WfvUwYLDUFO/4bOqeXpH+sw/kzjp7Xa/oHzbQAAADOQpclvToR9X1HUrtqd779/pXQAwCoZDgZhZLwHAACg7D6NP96XF7UoSae3u4u7vvuutlmvb242GvX6zs723rPnCggfuT9IxMMHjGAxTIcNAADAg1y1O8U3zvMYJWmlJ8Vut9uGd1q8Tq//2asof//jD4oDwHLddLujIMzyXCngiaJwEq/Z5HH1+oYkAQCwyN2tr8QfP6so3oe67nJd/VFQ6/TqGxubjemtsb29bSJW+HSO4ukjZpYvDyFIAAAAflv/thc9anKHW5NiAwDVd9PtDsdBXqgEzOj4YjBct8uNthp1IUgAYAEeEX/8kizPszifNjUMwtq96bO3tzZ3dnZMn83a/XJF0aeP7KtLaQhBAsDqa7fbn9kJqNePT04UB4CHyNKkNxg97rV5Uet0b16+fKmMAEAV94L677Na4o8AAEDZzTD++Fn/avrs/vuPi7ca9UajvtlobG5uGg+PlRd/Mk5EnKTKUh5CkACw+j57Yf30sERlAHigR0yEfV8QxmaFAACqJUuT7k0vCKNC/BEAACi3eccfv+R/TJ8dT+93ev36xkajvtFo1Hd3dkyfzeqJ0/Q3H2GJhCABAAD4muFgED35csab276PvQCAShB/BAAAqmJZ8cfPH0zl+fT261CRvf5339U26/XNzcb21ubU3rPn+otK/659+inB9JFgPPLeLgkhSAAAAL4oS5Ob2/7T2zEpNgBQfnenD6MkFX8EAJitSRiaJATmcfxSkvjjZ00PrO6Givx1zrpO7/D53vHJib6jisbj4LOPh2EkBFkScwxBNpuXS9+8Xn84GI7uP3L04sCbDwAA4IE63Zt8RiGAIIxdEwkAlFP5Tx8CAFRRnmd3dwpXmYDjl1otzTLdR1V/7+L4mx5n8eYYgozT5f/x+mWs3X/9yEffAwAA8AXDwSAIZ3kA37np/04IEgAo2Q7PaDwWfwQAmLlgPOoNfh2xKAjjm27XCHAwE5dXHUWABYuT9JseZ/FMhw0AAMDnzWQi7PuyPG+32+fn52oLACzdcDAYDEdluJgfAGD19G97vcHo/viP/VGQpOnLly8VB4BqydLkS1NmTR+Pwsn2zq4qLZ0QJACsmptu9yGDyU+f02637z+yu7Ozf3CggADcmf6byOcwT9F4EpkUGwBYLvFHAIC5uul2+6Pg08eDMG61Wudnp/XGpioBUBWj0egrPw3DUAiyDIQgAWDVTMLoISdy8uJ9DOWjB4UgAbgTjEef/puYld7tQAgSAFiKm253OA7mcaUHAAAf9rg+m4C8E8Zps9V+/epcDhKAqgij+Os/PVSjEthQAgAAAD7SuenPr/E4zTrX14oMACzSTbf75u1FfyQBCQAw352uryQg72R5/vPlu2A8Ui4AKiGK00f/lIUxEiQAAAD/SrvdzvJ8rosYTcL9cGKGCABg3rI06d70JmEk+wgAMG8PSUDeme6btbu981rNbCEAlN/Xz5jM+3wKD2QkSAAAAP5FFE7mNxH2B0VR63R7qg0AzE+WJu12++Ly3XTfRgISAGDerq6uHpiAvFMUtatO76bbVToAymw4GMzkOcybECQAAAD/YmHZRJNiAwBzEoWTD/HHQvwRAGD+Wq1WEMaPeGF/FEz33BQQgNKahOFMnsO8mQ4bAACAX3Wur+M0W9jiRpPwKE3qjU2VBwBmIgonN73bME6VAgBgYVqt1lN2wMaTaNrCq1evVBKAEkqSdCbPYd6MBAkAAMB7UTgZTRZ6teL7aY/aHZUHAGayJ9NqtS6vOhKQAACL9MQE5J1pC28vmlmaqCcAZZNkvz1yxCJHl+BLjAQJAADAe51ub/HzRUZJ2r/tHb44Un8A4HGGg8FgOHK+Acrm63ObruFAKWmWfb0m5+fn3jZAtWRp0r6e2SUoWZ43W+3T48O9Z8/VFoCSCMajB543mT7Tv7DlemoIcjgYdHr9Cm3wdG0/u8Jbjfrr1997QwAAAOupf9tbVnSgNxg9f/7cpNgAwLcSf4QyG08iRbgvL9QEWClZmjRb7SzPZ9lmnre7vfNaTYgEgJIIgsnDn+n/13IZCRIAAGDdZWnSG4yWtfSiqLWvO69evdIRAMAD3XS7kzASfwQAWIp5JCDvvP+YqNs7CKPjkxN1BmDp4gePYR+v32j3ZSMECQAAsO6u2p3FT4R9Xxinw8Fg/+BAXwAAX3fT7Q7HQV6oBADAcswvAXmnKGr9UZDn+enZmWoDsFxJms78mczJhhIAAACss/5tLyrBFYo3t/0sTXQHAPCVnZY3by/enxGXgAQAWJJ5JyA/GAZhq9VScACWKAonD/8IYvrM6fMVbYmEIAEAANZXlia3y5sI+768qHW6N3oEAPiS0Xgi/ggAsETBePTz5bsFJCDvhHHabF66aBaAZRmPg7k+n9kSggQAAFhfne5NecIEQRgPBwOdAgAAAFA2wXjU7vYW/DlSnGbNVtvAWgAsxbfOcB3FsaItUUMJAACgDK6urtI0e0oLr19/r4x8k+FgEITlOia/ue3vHxzoGgAAAIDyuEtAFsu4kjbL81a7c35ytPfsuY4AYJGi+NtCkEmaK9oSCUECAEAppGkWPy0ECd8kS5Ob237Z1iovau12+/z8XAcBAAAAlMESE5B3pouersBRkhy+ONIdACxGliZZ/m2hxunzp6+qNzZVbylMhw0AALCOSjUR9n3jSRSMRzoIAAAAYOmGg8FyE5B3pitw0x/ddLt6BIDFGI1GC3sVM2EkSAAAgLUTjEdlmwj7vs5N/3cLmeFoWocs+9qlnFlmfNYSGQ4GX3/C3t6uq2wBAABgVm663f4oKM/6TFcmiuNXr17pGgDmLYqTR7wqjOJDtVsSIUgAAIC107npl3n1sjxfzKTYvduBaeir9L7t/cb79rRW2z8QggQAAIAZKFsC8k4Yp5eXrZfnpy6DZLX99OZCEWC5kiR9xKtSZxyW56EhyGbzcrXPDE237kv/RX7/4w/eKAAAwMpot9tZnpd8JceTKAon2zu7+gsAAABgwcqZgLwTJWmz1X796lwOEoD5eVxMzrALS2QkSAAAWBHtdntBRxH1+vHJiYJXVDAejSdRJVa10+29fi0ECQAAALBQ/dteaROQd7I8v7h89+r81AW0AMzDcDB4ymv3Dw7UcPGEIAEAYEUsLNm21airdnX1bgdVWdU4zTrX16dnZ3oNAAAAYGGiOCn/ShZFLY4TIUgA5mEShk95rRDkUmwoAQAAwJroXF9Xay6G0SSMwomOAwAAAAAAFiN9wpmU1IzYS2IkSAAA1lEwHmVZXqpVyvJCvzBXUTgZTcJqrXNRmBQbAAAAAABYnDhNl/JankIIEgCAddS7HcSuxGLNdLq9ooJR2+mvav+2d/jiSA8CAAAAAABzFYxHTzmZMn3ttIW9Z89VcsGEIAEAAFZf5SbCvq83GD1//rze2NSPAABQHldXVyZ6m6Fm8/IrP339+nslAgCABQjD6IktBMFECHLxhCABAABWXJYmlZsI+76iqF21O99//0pXAgBAeaRpZo6FGVJMAAAogyiOn9hCYkbsZdhQAgAAgNV21e5UcSLs+6Ik7d/2dCUAAAAAADA/cZIuvQUeQQgSAABglfVve9FKHG/3BqMsTXQoAAAAAAAwD1E4yZ88qMS0hWk7irlgpsMGAAC+TZxmP725+KaXnB4d7h8cKN0CtNvt8SRayU0ritrb5jtvLQAAAACg6oLxKMtydYCyCcNwJu2Mx8H2zq56LpIQJAAAAAAAAAAALEjvdhCnmTpA2YRRPJN2ktSM2IsmBAkAVFizeVndld/d2T4+OdGJAAAAAAAAAEsXxWmp2uHhHhqCfP36+88+vjJTrW016l/aRgCgtCp9kdxm5go/AAAAAAAAgOXL0iTLZzNP/bSdaWv1xqaqLsyGEgAAAAAAAAAAALC2gmBS2tb4TabDhser9Bys9xkGFQBgZRwe7O/u7NzdH43H4SpOuHB6dPjh/t7erk4HAAAAAACeaBKGs21t/+BAVRdGCBIer9JzsAIAsJK2d3ant3uH6ysYgvSpAQAAAAAAMFtJkpa2NX6T6bABAAAAAAAAAABYX7MdCs3AagsmBAkAAAAAAAAAAMCaCsajmbc5HAwUdmFMhw1UW7vdXtait7c2D18c6QIAAAAAAAAAgOoKgsnM24yiaF9lF0UIEqi28SRa4qKDSfjq1Su9AAAAAAAAAABQUXGSVqJNvsR02ACPF8Zps3mZpYlSAAAAAAAAAABUUZymlWiTLzESJMAT/2llP1++Ozs52nv2XDUAAAAAAAAA1tlNt5tm2def85tPABYpCidFMftmp21OW97e2VXhBRCCBHiqvKi1u72jJDl8caQaAPD5o8coqg0GHz24tbXpwA8AAAAAgFUyCaM4lXGEKhmPg/m17FzYYghBAsxAUdRu+qMoTs7Pz1UDAD41DMLp7aMHn+1unzvwAwAAAAAAYHmiOK5cy3xkQwkAZmU8iVqtVpYmSgEAAAAAAAAAUH5xklauZT5iJEj4jCicxPEa5diGn8xN+Zv29nbrjU1vlU+FcdpstV+eHRvQGAAAAAAA+Kyf3lxUZVV//+MP+gsAWGFZmuTFvBqftjxtX8BmAYQg4TP6g+F4Eq3P9nZ6/W99yWmttn/gb/QX/kHmeavdOT852nv2XDXg0Sr0ISAAAAAAAAAAVTQajebd/uGLI3WeN9NhA8xeUdSuOr2bblcpAAAAAAAAAADKKYziSrfPHSFIgHnpj4Krqyt1AAAAAAAAAAAooTTN5tp+FKeKvABCkABzFIRxs3mZpYlSAAAAAAAAAACUSjznEGSW54q8AEKQAHP/f9lstYPxSCkAAAAAAAAAAEpiOBiszFLWnBAkwNxled7u9vq3PaUAAAAAAAAAACiDSRiuzFLWXEMJABagKGo3/VGSpKdnZ6oB/I+d3ajZvFyHLd3Y+O787LTe2NTpAKynUl3mu39woEcAqKgonPQHw0e//PBgf3tnVxkBAAD4IEnSlVnKmhOCBFicYRAmrZYkEHAnL2pxmq3Jxl5cvnu+uyMIDsB66vT65VmZm9v+/rO945MT/QJA5cRxMp5Ej3757s6OECQAAAD3JVm2MktZc0KQAAsVxmmz1X796lwOElgrRfE+CB41L09PjpxzAoAlyotafxRMwuhg/7lRIQEAAACeYjgYfDrLbSrtBBURjEdFsYgFTZcyXdbes+dqPj9CkMBjjMbjT3fmeKAszy8u352fHPkPB6ybOM1a7c7ezvb5+blqAMBy/yl3ev3BcCQKCQAAAPBokzB8ymjlwHIFwWSRyxIRmSshSOAxwjit1VJ1eLSiqLW7vYMwMgkdsIZ/AMeT6O1F8/T40I4+ACzXXRRyNB4fH70wVDMAAAAAsFbyxYwDufBlrSchSIDlKH6ZhC5J05cvX6oGsG6yPL/q9PZG4+++++6hu631uuA4AMxDGKeXV52drYYoJAAAAMF4FEZJJVZ1NB6b3AAAuLOgEOTm5uYf//CXLw4Pn9hOkqR//Td/OxgM9RywIkeSYdy5vj49O1MKYD3/Bj78yVuNuooBwPyEcdpqd/Z2tk+Oj+qNTQUBAABYQ/3bXm8wqspIVdMj2bcXzdevzh3GAgAbi1nMTBKQtfdhysZf/fEPe3uGJQBWh0GPAQCAMpgemown0cXlu3a7naWJggAAAKyV6cHgTX9UrdNWWZ5PD2OD8Uj3AcCaW9BIkDNJQN7Z3Gzs7e4GweT+g7/709d/+sOfTu/8fPHz25+b+hUAAADgEe6ikJPLd/vP9o5PThQEAABg5WVpctXuREla0cPYq07vMIwcwwLAOmuswDb87k9f/6f/9B/v7nc6XZ0KAAAA8BR5UeuPguE4EIUEYMF+enOhCACwSMF4dN3t5RWft2x6DBvF8fnZqamxAWA9bVR9A+4nIKdSszUBAAAAzMJdFLLZvBwOBqoBAACwem663Xb1E5B3wjhtttpRONGtALCGqh2C/CgB+c9v3v7TT290KgAAAMCsxGnW6fVFIQEAAFbM1dVVfxQUxepsUZbnrXbH0SsArKEKT4f9UQIySdIgmPzP//bf3H2bpsm7q/b0EX0MAAAA8ER3UcjReHx89GJ7Z1dBAAAAqit7fzL9enqgt3qbVhS16dFrFEWnZ2c6GgDWR4VDkPcTkFObm42/+PN/d/+R//U/1P7xv/x///W//XfdDAAAAPB0YZxeXnV2thqikAAAABUVjEfXqzIF9pcMgzBptc7PTuuNTT0OAOtgY7U37y/+/N/9L3/x57oZAAAAYFbCOG21O+12O0sT1QAAAKiQm263veoJyA+Hrs1WOwpNHQkAa6HCIcgkSR/ytH/7b/6nvT0jEwAAAADMTFHUxpPo4vKdKCQAAEBVXF1d9UdBUazL9mZ53mp3hoOBrgeAlVfh6bD/+m/+9q/++IfNzV83IUnS6SODwXB6/+Bg//6P/uTl+T/99EZnAwAAAMzQXRRycvlu/9ne8cmJggAAAJRTlibvrq7jNFvD49ZOrx9F0enZmbcBAKywCo8EORgM//pv/vbDeJCbm42/+uMfDg72P/zowzMbjU09DQAAADAPeVHrj4I3by9uul3VAAAAKJtgPPr58t0aJiA/GAZhq9UyjwEArLCNSq/9pznIP3n58sOP9C4AAADAYtxFIZvNSxONAQAAlMdNt9vu9vJi3esQxmmz1Y7CibcEAO12u9m8nN4mYbSwhU6XdbfQ6dJ1wTxsVH0DPspBAgAAALAscZp1en1RSAAAgDK4urrqj4KiUIn3sjxvtTsOVwGo/fIx5vS2yIsEpsu6W6jiz0ljBbbhLgd5Nwbkzc2NTgUAAABYorso5HA0Pjl+sb2zqyAAAAALlqXJu6trSYuPFEVtergaRdHp2ZlqAKyt3Z2d8SRa4tJ1wTwsKAT5z2/e/tmPv5tVU53ux0nHwWBo/msAAABgtq6urlJnjB4rStLLq87OVuP4SBQSAABggYdj4eRdu2MK7C8ZBmF2dfXyl1GWAFhD+wcHnV5/iUvXBfOwoBDk3/39PwwGg0Zj84ntpGnyTz+90W0AAADAAqQmKHmyMH4fhXy2u31yfFR/8kdDAAAA/KY4TiQgf/N4XxEA1tlWo76UD36ny1X8OVncdNjCiwAAAADraTyJgst3ezuikAAAAADAkm1uNpYSgpwuV/HnZEMJAAAAAJi3ongfhby4fHfT7aoGAAAAALAsuzs7a7XcdSAECQAAAMCCFEWtPwrevL0QhQQAAAAAlmJvb3etlrsOjLEJAAAAwELlv0QhR0F4dLi/f3CgIAAA3yQYj3q3g6884fXr71UJAAC+pN7YrG9sZHm+0IVubEyXq/hzsqAQ5Obm5n/83/7D9OsT20mS5O/+/h+mX/UcAAAAQKVled7p9QfD0cH+c1FIAIBv2I/K8jjN1AEAAB5te6sRhPGCl6js87Og4v7xD3/54vBwJk09e7b3N3/7f8pBAgAArKd2uz2rptLMWUNYvjjNOr3+cDQ+OX6xvWM6GACAGWg2L+fR7OZm4/z8XHkBAFgBO9tbCw5BTpeo7POzoBDkrBKQd00dHux3ujc6DwAAYA2NJ5EiwOqJkvTyqrOz1Tg+EoUEAHiqOY0TOW327UXz9Phw79lzRQYAoNKeP39+0x8teInKPj+LHmYzCILROHjEC7e2NmeYpAQAAACgbML4fRTy2e72yfFRvbGpIAAAZZPl+VWntzcav3z5UjUAAKiuemNz47taXixocdNl+cBzrhYdgvznNxf/9b/990e88PTk+P/44/+uwwAqKgon/cFw5s1ub20evjhSXgAAWCXjSRRcvtvbEYUEACipBc8bCAAA87C12QjjdGHLUvC5Ul8AFiGOk3nMXDltM4xi1xwDAMCKKYpfo5AHz/aOT04UBAAAAGB9/PTmolTr8913tfOTo71n5jJeNfV6vVZLF7gs5mhjVTdsc9M4AQBrIQjjy8tWliZKAQAAK6Yoav1R8ObtxU23qxoAAAAALEVR1K46PZ9QQZmtZghyc3Pzj3/4S70LsCaiJG222sF4pBQAALB68l+ikG8vmsPBQDUAAAAAWIr+KOhcX6sDlFMlp8P+9//+L+L4ayN+PX+2N/Xh23dXV3oaYLVled7u9k6yfP/gQDUAAGAl9/k7vf5gODrYf263HwAAAIDFGwZh0mq9evVKKaBsKhmCfHF4+PAnt687g8GwbJsQjEdZlq/ne65e39h79tzvHjBzRVHr9PpRFJ2enakGAACspDjNprv9w9H45PjF9s6uggAAAACwSGGctlqt87PTemNTNaA8Gqu9ebf9/v/1f/8/JVyx3u0gTrP1fM9tNepCkMD8rOfFN+12+/63afbIfzFJkt5vqlGvH5+ceFMBAFA2UZJeXnV2thrHR6KQAAAAACxUGKfNVvv1q3M5SCiPSoYgb/v9r0+Hfefdu3cXP18mSaKbAdZtp/PtRXOtdjrHk2gm7cRpdj+jv9WoezsBAFDmPf/Lq86z3e2T4yOfOAMAAACwMFmeN1vtl2fHLtCFkqhkCPI//+d/7HRvdB4AX9npvLh8d35yZOhZAABYbeNJFFy+29sRhQQAAABgcbI8b7U7TklDSSw6BPlnP/5wevqYiTW3tnyKDbAgw8Gg0+tXfSuKotbu9g7CyITOAACw2qY7/3dRyINne/b/AQAAAFiMu1PSR0ly+OJINWC5Fh2C3PuFugOwmJ3O/ihIs+z8/Fw1AABgHfb/h+Ngf9WjkFmaBMFkrTp3/+DAOxwAAAAooaKo3fRHWZa7NBeWa0EhyH9+8/bPfvzdTJq67ff7g6GeA+CBxpPo8rL18vzU1HgAALDy8l+ikKMgPDrcX9XkXBBMVmDw/m8iBAkAAACUmaF5YOkWFIL8u7//hyRJDw+f+nllkiS/NJXoOQAeLkrSZqv98ux4e2d3JTfw2e723Z3xJHp6axvf1XZ33jfYqNe9eQAAqKIszzu9/mA4Oth/Lj8HAAAAwLyNJ1Hn+vr07EwpYCkWNx32//uP/0W5AViWLM9b7c7Ji8OVPAP64aKin95czGDnoF53lRIAACsgTrNOrz8cjU+OX6zqBVEAAAAAlEReFIoAy9JQAhYszbJ2u/2kd229fnxyopLAt5ruc3Z6/SRJ/A0BAID1ESXp5VVnZ6txfCQKCQAAAI/UbF7Gabb01dhq1F+//l53APARIUgWLS+eOlvrdLdGGYFH64+CKI5fvXqlFAAAsD7C+H0U8tnu9snxUb2xqSAAAAAAACtDCBKgekpyoVV1hXH69qL5+tW5c58AALBWxpMouHy3tyMKCQAA1XDT7U7CaFlLbzTqL1++1AsAAOUnBAnAOsry/OfLd2cnR3vPnqsGAACsj6L4NQr5fHfn9OxMQfjIT28uVn4bf//jDzoaAKiKNMuMCgEAwG/aUAIA1lNe1NrdXv+2pxQAALBuiqI2DMI3by9uul3VAAAAAACoNCNBArC+iqJ20x9FcXJ+fq4aAACwbvKi1h8FxycnSgHwCFE46Q+Gj3hho173txcAAACYISFIANbdeBK1Wq3zs9N6Y1M1AAAAAB4ijpPxJHrEC7caddUDAAAAZsh02ABQC+O02WpH4UQpAAAAAAAAAAAqRAgSAN7L8rzV7gTjkVIAAAAAAAAAAFSFECQA/Kooaled3k23qxQAAAAAAAAAAJXQUAIAuK8/CqI4fvXqlVIAAACsm9Ojw7s7vf4wy/OV2a76xsbR4b7+BQAAAGAlCUECwMfCOG02L//k5Vm9sakaAAAA62P/4ODuzmA4ylYnA1mrb3z3YdOooqurqzTNyrZWWV48+oXDweD9O7O+sffsuf4FAAAAnkgIEgA+I06zZqt9enzos3gAAABgudI0i8sXgny0LM87vf70zlaj7oMXWENROOkPhlVc892dHRcVAABAOQlBAsDnZXne7vaOkuTwxZFqAAAAAAA8XRwn40lU0ZUXglxbw8FgEoZf+unhwf72zq4qAQAskRAkAHxRUdRu+qMkSU/Pzsq/tnczST1dnGZZmpgKHAAAAAAApiZh+JXw7u7OjhAkAMByCUECwG8YBmHSap2fnZY8Fzgaj2fVVK93W4ncJwDAv9qH6Q8Hw9Fs20yyTGEBAADWU5pl7Xb7/bFhkqoGAECZCUECwG8L47TZar9+dV7aHGSWJtOVnFVrQRjrdACgcrI8z3JlAAAAYDbyovaQ2ds7vf709tkfnR4dmkUdAGABhCAB4EGyPL+4fHd+crT37HkJV6/Xu53txgbjUTm3lLWVZFmzeTnbBlUVAKAShoPBQ55Wr284igEAAACANSQECQAPVRS1q07vMIyOT07Ktm7jSTjbBvuDodOHlO0XME7FFgGAVfPAeN99URStW5W+NKzOR7YadUcxAAAAALCGhCAB4Nv0R0GSpi9fvizPKg0Hg7yYcZtRkmZpUtrpvwEAYDU8MN4HAAAAAMCXbCgBAHyrIIwvL1tZmpRkfUbj8czbLIpavz/Q1wAAAAAAAABAmRkJEgAeI0rSZqt9eny49NnWsjQJ43QeLY+C8PhEVwMAAAAAD5KlSRBMvv6cKIoUCgAAmC0hSAB4pCzP293eea223Bzk/MZrnG5gMB4tPeUJAAAAAFRCEEw6vb46AAAACyYECQCPVxS10ThYbkxwFITza7w/GApBAgAAAMByNZuX97/N8kJNAAAAPhCCBIAKC8ajLM/n136UpIoMAAAAAMsVp5kiAAAAfMmGEgBAdfUHw7m2XxS1m25XnQEAAAAAAACAchKCBICqytJkASM1TsJIqQEAAAAAAACAcjIdNgBUVb8/KIq5LyVOsyicbO/sKjgAAAAAAMC3ajYv4zQr7er9/scf9BEwWzfdbpo96e/e4cG+M9R8EyHIX2V5MRwMFrk4NQfgiUZBuJgF3fYHL+1iAgAAAABrbBJGzealOgAAPGTH6Ynh792dHSFIvokQ5K+yPO/0+upQkc6ae2I1yzJ1BkouGI+m/7wWtJMaxQoOAAAAAKyzvKiVeSA3AAB4tHa7PZ5E817K6dHh/sHBnBoXgqR6JFYBpoaj8cKWVRTvRyw/PjlRdgAAAAAAAACgVIQgAaCSFjw64ySM1BwAAAAAAFhJN93u/E6FJOYhBIA5E4IEgEoeihfFQpcYp1kUTrZ3dhUfAAAAAABYMWmWmfIeAKpLCBIAqmcp4zL2B8NzIUgAAKCs4jT76c2FOgAAAADAutlQAgColiicLOViRDNiAwAAAAAAAABlYyRIACijLE2CYPLZH43G46WsUl7UOtfX29vbn/3p/sGBXgMAAAAAAGB+srwYDgYPfPLW1ua2Wc4A1oMQJACUURBMOr1+2dZqGITT22d/JAQJAAAAAADAXGV5/vAzaM92t8+FIAHWg+mwAQAAAAAAAAAAgEoyEiQAAAAAAAAAzFin1y/hpE8AlEq73V69jUqzTM+yYI1m89K7FgAAKI9gPMqyfOmrsbW1uW2qFABgJSRZ9sTPgUuyFboSAACAFTOeRIrAnZ/eXKz2Bvb6w8FwNKfGG3HqkyMAAKBMh0C3gzIcpzzb3T4XggQAVkJR1HwODAAAAMASZXk+v1FQNtQXAAAAAAAAAAAAqCIhSAAAAAAAAAAAAKCShCABAAAAAAAAAACASmooAQCU0N7e7um9b0fjcRinpVrDna3G82fP9BQAAAAAAAAAsERCkABQRvXG5v7B5odvJ2FYq5UrBFmv1/cPDvQU8BRZlg0Hg888nhdlXr1l2dvbnf538LYBAAAAAACA+4QgAQCA5QjjNIz7Vu+BTmu1+/l4AACAD66urtI0m0lTuzvbxycnSgoAAECFCEECAAAAAABUWJpm8YxCkJtZpp4AAABUy4YSAAAAAAAAAAAAAFUkBAkAAAAAAAAAAABUkumwAQAAAAAAAACAOZqEUbN5qQ7APAhBAgAAAAAAAAAAc5QXtTjN1AGYByFIAAAAAAAA4Bv89OZCEQAAgJLYUAIAAAAAAAAAAACgiowECQAAAAAALFqWF8PBoIQrFoxHvdtBtYqZZGYVBAAAYH0JQQIAAAAAAIuW5Xmn1y/jimV5nMoUAgAAQGWYDhsAAAAAAAAAAACoJCFIAAAAAAAAAAAAoJKEIAEAAAAAAAAAAIBKEoIEAAAAAAAAAAAAKkkIEgAAAAAAAAAAAKgkIUgAAAAAAAAAAACgkhpKAAAAAAAAAMCn2u32EpeeJKkuAADgNwlBAgAAAAAAAPAZ40mkCAAAlJzpsAEAAAAAAAAAAIBKEoIEAAAAAAAAAAAAKkkIEgAAAAAAAAAAAKgkIUgAAAAAAAAAAACgkoQgAQAAAAAAAAAAgEpqKAEAAAAAAAAAwBpqt9sPeVqaZWoFQGkJQQIAAAAAAAAArKPxJFIEAKrOdNgAAAAAAAAAAABAJQlBAgAAAAAAAAAAAJUkBAkAAAAAAAAAAABUUkMJAAAAym80Hk/C8JtekiSpugGUVpYm7euOOgAAAAAAPJEQJAAAQAWEcVqrCTUCrIgsTZqtdpbnSgEAAAAA8ERCkAAAAACwOMF41O72ikIlAAAAAABmQAgSAAAAABbkptvtjwJ1AAAAAACYFSFIAAAAAFiEq6urIIzVAQAAAAC+otPrT2/qwMMJQQIAAADAfGVpctXuREmqFAAAAAAAsyUECbBkSZK22+1vekmaZeoGAABQFVE4ubq+yfJcKQAAAAAAZk4IEmDJ4jSb3tQBAABgJQXjUbvbKwqVAAAAAACYCyFIAAAAAJiLm263PwrUAaAMRuPxJAwf8szMNCwAAABQKUKQAAAAADB7rVYrjFN1AD7S6fWnN3VYvF/+JvuzDAAAACtICBIAAAAAZilLk3dX13FqIDEAAAAAgLkTggQAAABgfTWblzNvM82yvFBaAAAAAIBFEIIEAAAA4P9n745a2gbDMAwXKbgdqAg7HcP//6NERMEg25quNE2+N7XiiQiyupA1r70uelJaaPu0J4WbfMfL9RoBAAAAGC4ilnVtBzgIESQAAAAAAAAAAMC/a9rStAs7wEGcmAAAAAAAAAAAAADISAQJAAAAAAAAAAAApOQ4bAAAAAAAAAAAABhFRCzr2g7jEUECAAAAAAAAAADAKJq2NO3CDuNxHDYAAAAAAAAAAACQkitBAsDBXN/c5n3zq/Vm//d/9eO7rxsAAAAAAJiC6LdvziSNCLMAQF4iSAAAAAAAAADgWETfP/5yJikAfB6OwwYAAAAAAAAAAABSEkECAAAAAAAAAAAAKYkgAQAAAAAAAAAAgJREkAAAAAAAAHxAlC76rR0AAACYgrkJAAAAAAAA2NOyrn/+XmggAQAAmAgRJAAAAAAAAH8XpXuoHjddMQUAAADTIYIEAAAAAADg2brZ3N3dv/doF7F1AUgAAAAmRgQJAAAAAADAs347a0vYAQAAgEROTAAAAAAAAAAAAABkJIIEAAAAAAAAAAAAUhJBAgAAAAAAAAAAACnNTQAAAAAAAAAAwGfSdaWqqrFfws4AUyCCBID/ZPcva7XeHOdnv765fX332+XF2fm5nwQAAAAAAAAjaUvsbnYAOAaOwwYAAAAAAAAAAABSEkECAAAAAAAAAAAAKYkgAQAAAAAAAAAAgJREkAAAAAAAAAAAAEBKIkgAAAAAAAAAAAAgpbkJAGCIritVVe35THO9+LNarZvGDgAAAAAAAADAQCJIABikLbG72eFDmrbMZpJQAAAAAAAAAGAox2EDAAAAAAAAAAAAKYkgAQAAAAAAAAAAgJREkAAAAAAAAAAAAEBKIkgAAAAAAAAAAAAgJREkAAAAAAAAAAAAkJIIEgAAAAAAAAAAAEhp/vXLqRUAAAAAAAAAAACAdJ4EGAD0UiXBHYVPBAAAAABJRU5ErkJggg==)\"></div></div>", + "meta": { + "options": { + "id": 760, + "assetType": { + "id": 197, + "name": "htmlblock", + "displayName": "HTML Block" + } + } + }, + "availableViews": [], + "data": { + "email": { + "options": {} + } + }, + "modelVersion": 2 + }, + "8uflrc8ao4r": { + "assetType": { + "id": 223, + "name": "referenceblock" + }, + "design": "<div class=\"default-design\"><div style=\"width:100%;height:150px;background-size:cover;background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAADawAAAEtCAIAAADRXFFBAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAALyhJREFUeNrs3ftvI+l+J2aOSF27JbWu7Z72nPEJdrOws5ss9hcj58R/vWEDQYLAhjdeZHfhcbeGYosiRfFWrHuFPZpty30btcRLFfk8IASKIt+q+r6UVMX61Pt+13r3rgYAAAAAAAAAAABQNY2rd1eqAAAAAAAAAAAAAFTOhhIAAAAAAAAAAAAAVSQECQAAAAAAAAAAAFSSECQAAAAAAAAAAABQSUKQAAAAAAAAAAAAQCUJQQIAAAAAAAAAAACVJAQJAAAAAAAAAAAAVJIQJAAAAAAAAAAAAFBJQpAAAAAAAAAAAABAJQlBAgAAAAAAAAAAAJUkBAkAAAAAAAAAAABUkhAkAAAAAAAAAAAAUElCkAAAAAAAAAAAAEAlCUECAAAAAAAAAAAAlSQECQAAAAAAAAAAAFSSECQAAAAAAAAAAABQSUKQAAAAAAAAAAAAQCUJQQIAAAAAAAAAAACVJAQJAAAAAAAAAAAAVJIQJAAAAAAAAAAAAFBJQpAAAAAAAAAAAABAJQlBAgAAAAAAAAAAAJUkBAkAAAAAAAAAAABUUkMJAAAAAADg4drt9ngSTe88290+Pz9XEAAAAIAlMhIkAAAAAAAAAAAAUElCkAAAAAAAAAAAAEAlCUECAAAAAAAAAAAAlSQECQAAAAAAAAAAAFRSo7Rr1mxexmn26eO///EH3QYAAAAAAAAAAAAYCRIAAAAAAAAAAACoJCFIAAAAAAAAAAAAoJKEIAEAAAAAAAAAAIBKEoIEAAAAAAAAAAAAKkkIEgAAAAAAAACYvSicKAIAMG9CkAAAAAAAAADA7MVxoggAwLwJQQIAAAAAAAAAs5fnmSIAAPMmBAkAAAAAAAAAzF5kJEgAYP6EIAEAAAAAAAAAAIBKEoIEAAAAAAAAAAAAKkkIEgAAAAAAAACYiyicKAIAMFdCkAAAAAAAAADAXMRxoggAwFwJQQIAAAAAAAAAAACV1FACAAAAmLlm8zJOM3X4yOnR4f7BgToAAAAAAACzYiRIAAAAAAAAAAAAoJKEIAEAAAAAAAAAAIBKEoIEAAAAAAAAAAAAKkkIEgAAAAAAAACYvaIo8jxTBwBgrhpKAAAAAAAAAADMXJpm0XeJOgAAc2UkSAAAAAAAAAAAAKCShCABAAAAAAAAAACAShKCBAAAAAAAAAAAACqpoQQAAADwFMF4lGX5Rw9meaEyn4qiqDYYfPTg3t5uvbGpOAAAAAAAwCMIQQIAAMCT9G4HcZqpw0MMg3B6++jB01pt/0AIEgAAAAAAeAzTYQMAAAAAAAAAAACVJAQJAAAAAAAAAMxFkqSKAADMlRAkAAAAAAAAAAAAUElCkAAAAAAAAAAAAEAlCUECAADwVFmaKAIAAAAAH8nyQhEAgHlrlGElfnpz8cQnP9vdPj8/150AAACLNxwMbm77P/7uB6UAAAAA4L4sz+sbdXUAAOaqoQQAAAA8WpYmN7f9vKi12+31uTit2byM00zvz0qn15/ePnx7enS4f3CgLAAAAAAAwEOYDhsAAIDH63Rv7iY1Gk+iYDxSEACAr+jf9qJwog4AAABQUcPBQBFKSAgSAACAxx/qB2H84dvOTV9NAAC+tOPUbF7e9EdxnKgGALBWksx8GgCsjsHQeBBlZDpsAAAAHqnXH97/NsvztZoUGwDgIYaDwWA4ilPn/gGANVUUagDAiojCyfQAf/p1e2dXNUpFCBIAAIDHaLfbWZ5/9GAQRg7+AQDuTPeLbnq3YZwqBQAAAKyAMAynX8fjwHmQshGCBAAA4JsF49F4En36eFHUOt3e69cO/gGAtSb+CAAAAKsnjOLp1yR1vF86QpAAAAB8s85N/0s/itOsc319enamSgDAGsrSpHvT++zlIgAAAEClRb9c7hi56LF8hCABAAD4Np3r608nwr5vNAn3TYoNAKyZu/hjEEZFoRgAAACwggf+dydHpl+n9+uNTTUpjw0lAAAA4OGicDKahF9/zt2k2GoFAKyPzvX1xeW78UQCEgAAAFZTEEw+3B+NRgpSKkaCBAAA4Bt0ur2HnNqP06x/2zt8caRiAMBqu+l2h+Mgl30EAPhEliZ3dyJzhsCyTX8Nb3q3Gxsb9Y2N7e3t/YMDNYFvNQn/ZYSIKE4UpFQWGoIcDgbz2nnKss82vre3a+hRAACAWelcX8dp9sAn9waj58+fOygDAFbYeBIpAgDAl3wYMSuOEyFIWJa7+GMYpx8eGQZhp9ff+K622Ziq7+7sbG1t+iWF35Qk6WfvUwYLDUFO/4bOqeXpH+sw/kzjp7Xa/oHzbQAAADOQpclvToR9X1HUrtqd779/pXQAwCoZDgZhZLwHAACg7D6NP96XF7UoSae3u4u7vvuutlmvb242GvX6zs723rPnCggfuT9IxMMHjGAxTIcNAADAg1y1O8U3zvMYJWmlJ8Vut9uGd1q8Tq//2asof//jD4oDwHLddLujIMzyXCngiaJwEq/Z5HH1+oYkAQCwyN2tr8QfP6so3oe67nJd/VFQ6/TqGxubjemtsb29bSJW+HSO4ukjZpYvDyFIAAAAflv/thc9anKHW5NiAwDVd9PtDsdBXqgEzOj4YjBct8uNthp1IUgAYAEeEX/8kizPszifNjUMwtq96bO3tzZ3dnZMn83a/XJF0aeP7KtLaQhBAsDqa7fbn9kJqNePT04UB4CHyNKkNxg97rV5Uet0b16+fKmMAEAV94L677Na4o8AAEDZzTD++Fn/avrs/vuPi7ca9UajvtlobG5uGg+PlRd/Mk5EnKTKUh5CkACw+j57Yf30sERlAHigR0yEfV8QxmaFAACqJUuT7k0vCKNC/BEAACi3eccfv+R/TJ8dT+93ev36xkajvtFo1Hd3dkyfzeqJ0/Q3H2GJhCABAAD4muFgED35csab276PvQCAShB/BAAAqmJZ8cfPH0zl+fT261CRvf5339U26/XNzcb21ubU3rPn+otK/659+inB9JFgPPLeLgkhSAAAAL4oS5Ob2/7T2zEpNgBQfnenD6MkFX8EAJitSRiaJATmcfxSkvjjZ00PrO6Givx1zrpO7/D53vHJib6jisbj4LOPh2EkBFkScwxBNpuXS9+8Xn84GI7uP3L04sCbDwAA4IE63Zt8RiGAIIxdEwkAlFP5Tx8CAFRRnmd3dwpXmYDjl1otzTLdR1V/7+L4mx5n8eYYgozT5f/x+mWs3X/9yEffAwAA8AXDwSAIZ3kA37np/04IEgAo2Q7PaDwWfwQAmLlgPOoNfh2xKAjjm27XCHAwE5dXHUWABYuT9JseZ/FMhw0AAMDnzWQi7PuyPG+32+fn52oLACzdcDAYDEdluJgfAGD19G97vcHo/viP/VGQpOnLly8VB4BqydLkS1NmTR+Pwsn2zq4qLZ0QJACsmptu9yGDyU+f02637z+yu7Ozf3CggADcmf6byOcwT9F4EpkUGwBYLvFHAIC5uul2+6Pg08eDMG61Wudnp/XGpioBUBWj0egrPw3DUAiyDIQgAWDVTMLoISdy8uJ9DOWjB4UgAbgTjEef/puYld7tQAgSAFiKm253OA7mcaUHAAAf9rg+m4C8E8Zps9V+/epcDhKAqgij+Os/PVSjEthQAgAAAD7SuenPr/E4zTrX14oMACzSTbf75u1FfyQBCQAw352uryQg72R5/vPlu2A8Ui4AKiGK00f/lIUxEiQAAAD/SrvdzvJ8rosYTcL9cGKGCABg3rI06d70JmEk+wgAMG8PSUDeme6btbu981rNbCEAlN/Xz5jM+3wKD2QkSAAAAP5FFE7mNxH2B0VR63R7qg0AzE+WJu12++Ly3XTfRgISAGDerq6uHpiAvFMUtatO76bbVToAymw4GMzkOcybECQAAAD/YmHZRJNiAwBzEoWTD/HHQvwRAGD+Wq1WEMaPeGF/FEz33BQQgNKahOFMnsO8mQ4bAACAX3Wur+M0W9jiRpPwKE3qjU2VBwBmIgonN73bME6VAgBgYVqt1lN2wMaTaNrCq1evVBKAEkqSdCbPYd6MBAkAAMB7UTgZTRZ6teL7aY/aHZUHAGayJ9NqtS6vOhKQAACL9MQE5J1pC28vmlmaqCcAZZNkvz1yxCJHl+BLjAQJAADAe51ub/HzRUZJ2r/tHb44Un8A4HGGg8FgOHK+Acrm63ObruFAKWmWfb0m5+fn3jZAtWRp0r6e2SUoWZ43W+3T48O9Z8/VFoCSCMajB543mT7Tv7DlemoIcjgYdHr9Cm3wdG0/u8Jbjfrr1997QwAAAOupf9tbVnSgNxg9f/7cpNgAwLcSf4QyG08iRbgvL9QEWClZmjRb7SzPZ9lmnre7vfNaTYgEgJIIgsnDn+n/13IZCRIAAGDdZWnSG4yWtfSiqLWvO69evdIRAMAD3XS7kzASfwQAWIp5JCDvvP+YqNs7CKPjkxN1BmDp4gePYR+v32j3ZSMECQAAsO6u2p3FT4R9Xxinw8Fg/+BAXwAAX3fT7Q7HQV6oBADAcswvAXmnKGr9UZDn+enZmWoDsFxJms78mczJhhIAAACss/5tLyrBFYo3t/0sTXQHAPCVnZY3by/enxGXgAQAWJJ5JyA/GAZhq9VScACWKAonD/8IYvrM6fMVbYmEIAEAANZXlia3y5sI+768qHW6N3oEAPiS0Xgi/ggAsETBePTz5bsFJCDvhHHabF66aBaAZRmPg7k+n9kSggQAAFhfne5NecIEQRgPBwOdAgAAAFA2wXjU7vYW/DlSnGbNVtvAWgAsxbfOcB3FsaItUUMJAACgDK6urtI0e0oLr19/r4x8k+FgEITlOia/ue3vHxzoGgAAAIDyuEtAFsu4kjbL81a7c35ytPfsuY4AYJGi+NtCkEmaK9oSCUECAEAppGkWPy0ECd8kS5Ob237Z1iovau12+/z8XAcBAAAAlMESE5B3pouersBRkhy+ONIdACxGliZZ/m2hxunzp6+qNzZVbylMhw0AALCOSjUR9n3jSRSMRzoIAAAAYOmGg8FyE5B3pitw0x/ddLt6BIDFGI1GC3sVM2EkSAAAgLUTjEdlmwj7vs5N/3cLmeFoWocs+9qlnFlmfNYSGQ4GX3/C3t6uq2wBAABgVm663f4oKM/6TFcmiuNXr17pGgDmLYqTR7wqjOJDtVsSIUgAAIC107npl3n1sjxfzKTYvduBaeir9L7t/cb79rRW2z8QggQAAIAZKFsC8k4Yp5eXrZfnpy6DZLX99OZCEWC5kiR9xKtSZxyW56EhyGbzcrXPDE237kv/RX7/4w/eKAAAwMpot9tZnpd8JceTKAon2zu7+gsAAABgwcqZgLwTJWmz1X796lwOEoD5eVxMzrALS2QkSAAAWBHtdntBRxH1+vHJiYJXVDAejSdRJVa10+29fi0ECQAAALBQ/dteaROQd7I8v7h89+r81AW0AMzDcDB4ymv3Dw7UcPGEIAEAYEUsLNm21airdnX1bgdVWdU4zTrX16dnZ3oNAAAAYGGiOCn/ShZFLY4TIUgA5mEShk95rRDkUmwoAQAAwJroXF9Xay6G0SSMwomOAwAAAAAAFiN9wpmU1IzYS2IkSAAA1lEwHmVZXqpVyvJCvzBXUTgZTcJqrXNRmBQbAAAAAABYnDhNl/JankIIEgCAddS7HcSuxGLNdLq9ooJR2+mvav+2d/jiSA8CAAAAAABzFYxHTzmZMn3ttIW9Z89VcsGEIAEAAFZf5SbCvq83GD1//rze2NSPAABQHldXVyZ6m6Fm8/IrP339+nslAgCABQjD6IktBMFECHLxhCABAABWXJYmlZsI+76iqF21O99//0pXAgBAeaRpZo6FGVJMAAAogyiOn9hCYkbsZdhQAgAAgNV21e5UcSLs+6Ik7d/2dCUAAAAAADA/cZIuvQUeQQgSAABglfVve9FKHG/3BqMsTXQoAAAAAAAwD1E4yZ88qMS0hWk7irlgpsMGAAC+TZxmP725+KaXnB4d7h8cKN0CtNvt8SRayU0ritrb5jtvLQAAAACg6oLxKMtydYCyCcNwJu2Mx8H2zq56LpIQJAAAAAAAAAAALEjvdhCnmTpA2YRRPJN2ktSM2IsmBAkAVFizeVndld/d2T4+OdGJAAAAAAAAAEsXxWmp2uHhHhqCfP36+88+vjJTrW016l/aRgCgtCp9kdxm5go/AAAAAAAAgOXL0iTLZzNP/bSdaWv1xqaqLsyGEgAAAAAAAAAAALC2gmBS2tb4TabDhser9Bys9xkGFQBgZRwe7O/u7NzdH43H4SpOuHB6dPjh/t7erk4HAAAAAACeaBKGs21t/+BAVRdGCBIer9JzsAIAsJK2d3ant3uH6ysYgvSpAQAAAAAAMFtJkpa2NX6T6bABAAAAAAAAAABYX7MdCs3AagsmBAkAAAAAAAAAAMCaCsajmbc5HAwUdmFMhw1UW7vdXtait7c2D18c6QIAAAAAAAAAgOoKgsnM24yiaF9lF0UIEqi28SRa4qKDSfjq1Su9AAAAAAAAAABQUXGSVqJNvsR02ACPF8Zps3mZpYlSAAAAAAAAAABUUZymlWiTLzESJMAT/2llP1++Ozs52nv2XDUAAAAAAAAA1tlNt5tm2def85tPABYpCidFMftmp21OW97e2VXhBRCCBHiqvKi1u72jJDl8caQaAPD5o8coqg0GHz24tbXpwA8AAAAAgFUyCaM4lXGEKhmPg/m17FzYYghBAsxAUdRu+qMoTs7Pz1UDAD41DMLp7aMHn+1unzvwAwAAAAAAYHmiOK5cy3xkQwkAZmU8iVqtVpYmSgEAAAAAAAAAUH5xklauZT5iJEj4jCicxPEa5diGn8xN+Zv29nbrjU1vlU+FcdpstV+eHRvQGAAAAAAA+Kyf3lxUZVV//+MP+gsAWGFZmuTFvBqftjxtX8BmAYQg4TP6g+F4Eq3P9nZ6/W99yWmttn/gb/QX/kHmeavdOT852nv2XDXg0Sr0ISAAAAAAAAAAVTQajebd/uGLI3WeN9NhA8xeUdSuOr2bblcpAAAAAAAAAADKKYziSrfPHSFIgHnpj4Krqyt1AAAAAAAAAAAooTTN5tp+FKeKvABCkABzFIRxs3mZpYlSAAAAAAAAAACUSjznEGSW54q8AEKQAHP/f9lstYPxSCkAAAAAAAAAAEpiOBiszFLWnBAkwNxled7u9vq3PaUAAAAAAAAAACiDSRiuzFLWXEMJABagKGo3/VGSpKdnZ6oB/I+d3ajZvFyHLd3Y+O787LTe2NTpAKynUl3mu39woEcAqKgonPQHw0e//PBgf3tnVxkBAAD4IEnSlVnKmhOCBFicYRAmrZYkEHAnL2pxmq3Jxl5cvnu+uyMIDsB66vT65VmZm9v+/rO945MT/QJA5cRxMp5Ej3757s6OECQAAAD3JVm2MktZc0KQAAsVxmmz1X796lwOElgrRfE+CB41L09PjpxzAoAlyotafxRMwuhg/7lRIQEAAACeYjgYfDrLbSrtBBURjEdFsYgFTZcyXdbes+dqPj9CkMBjjMbjT3fmeKAszy8u352fHPkPB6ybOM1a7c7ezvb5+blqAMBy/yl3ev3BcCQKCQAAAPBokzB8ymjlwHIFwWSRyxIRmSshSOAxwjit1VJ1eLSiqLW7vYMwMgkdsIZ/AMeT6O1F8/T40I4+ACzXXRRyNB4fH70wVDMAAAAAsFbyxYwDufBlrSchSIDlKH6ZhC5J05cvX6oGsG6yPL/q9PZG4+++++6hu631uuA4AMxDGKeXV52drYYoJAAAAMF4FEZJJVZ1NB6b3AAAuLOgEOTm5uYf//CXLw4Pn9hOkqR//Td/OxgM9RywIkeSYdy5vj49O1MKYD3/Bj78yVuNuooBwPyEcdpqd/Z2tk+Oj+qNTQUBAABYQ/3bXm8wqspIVdMj2bcXzdevzh3GAgAbi1nMTBKQtfdhysZf/fEPe3uGJQBWh0GPAQCAMpgemown0cXlu3a7naWJggAAAKyV6cHgTX9UrdNWWZ5PD2OD8Uj3AcCaW9BIkDNJQN7Z3Gzs7e4GweT+g7/709d/+sOfTu/8fPHz25+b+hUAAADgEe6ikJPLd/vP9o5PThQEAABg5WVpctXuREla0cPYq07vMIwcwwLAOmuswDb87k9f/6f/9B/v7nc6XZ0KAAAA8BR5UeuPguE4EIUEYMF+enOhCACwSMF4dN3t5RWft2x6DBvF8fnZqamxAWA9bVR9A+4nIKdSszUBAAAAzMJdFLLZvBwOBqoBAACwem663Xb1E5B3wjhtttpRONGtALCGqh2C/CgB+c9v3v7TT290KgAAAMCsxGnW6fVFIQEAAFbM1dVVfxQUxepsUZbnrXbH0SsArKEKT4f9UQIySdIgmPzP//bf3H2bpsm7q/b0EX0MAAAA8ER3UcjReHx89GJ7Z1dBAAAAqit7fzL9enqgt3qbVhS16dFrFEWnZ2c6GgDWR4VDkPcTkFObm42/+PN/d/+R//U/1P7xv/x///W//XfdDAAAAPB0YZxeXnV2thqikAAAABUVjEfXqzIF9pcMgzBptc7PTuuNTT0OAOtgY7U37y/+/N/9L3/x57oZAAAAYFbCOG21O+12O0sT1QAAAKiQm263veoJyA+Hrs1WOwpNHQkAa6HCIcgkSR/ytH/7b/6nvT0jEwAAAADMTFHUxpPo4vKdKCQAAEBVXF1d9UdBUazL9mZ53mp3hoOBrgeAlVfh6bD/+m/+9q/++IfNzV83IUnS6SODwXB6/+Bg//6P/uTl+T/99EZnAwAAAMzQXRRycvlu/9ne8cmJggAAAJRTlibvrq7jNFvD49ZOrx9F0enZmbcBAKywCo8EORgM//pv/vbDeJCbm42/+uMfDg72P/zowzMbjU09DQAAADAPeVHrj4I3by9uul3VAAAAKJtgPPr58t0aJiA/GAZhq9UyjwEArLCNSq/9pznIP3n58sOP9C4AAADAYtxFIZvNSxONAQAAlMdNt9vu9vJi3esQxmmz1Y7CibcEAO12u9m8nN4mYbSwhU6XdbfQ6dJ1wTxsVH0DPspBAgAAALAscZp1en1RSAAAgDK4urrqj4KiUIn3sjxvtTsOVwGo/fIx5vS2yIsEpsu6W6jiz0ljBbbhLgd5Nwbkzc2NTgUAAABYorso5HA0Pjl+sb2zqyAAAAALlqXJu6trSYuPFEVtergaRdHp2ZlqAKyt3Z2d8SRa4tJ1wTwsKAT5z2/e/tmPv5tVU53ux0nHwWBo/msAAABgtq6urlJnjB4rStLLq87OVuP4SBQSAABggYdj4eRdu2MK7C8ZBmF2dfXyl1GWAFhD+wcHnV5/iUvXBfOwoBDk3/39PwwGg0Zj84ntpGnyTz+90W0AAADAAqQmKHmyMH4fhXy2u31yfFR/8kdDAAAA/KY4TiQgf/N4XxEA1tlWo76UD36ny1X8OVncdNjCiwAAAADraTyJgst3ezuikAAAAADAkm1uNpYSgpwuV/HnZEMJAAAAAJi3ongfhby4fHfT7aoGAAAAALAsuzs7a7XcdSAECQAAAMCCFEWtPwrevL0QhQQAAAAAlmJvb3etlrsOjLEJAAAAwELlv0QhR0F4dLi/f3CgIAAA3yQYj3q3g6884fXr71UJAAC+pN7YrG9sZHm+0IVubEyXq/hzsqAQ5Obm5n/83/7D9OsT20mS5O/+/h+mX/UcAAAAQKVled7p9QfD0cH+c1FIAIBv2I/K8jjN1AEAAB5te6sRhPGCl6js87Og4v7xD3/54vBwJk09e7b3N3/7f8pBAgAArKd2uz2rptLMWUNYvjjNOr3+cDQ+OX6xvWM6GACAGWg2L+fR7OZm4/z8XHkBAFgBO9tbCw5BTpeo7POzoBDkrBKQd00dHux3ujc6DwAAYA2NJ5EiwOqJkvTyqrOz1Tg+EoUEAHiqOY0TOW327UXz9Phw79lzRQYAoNKeP39+0x8teInKPj+LHmYzCILROHjEC7e2NmeYpAQAAACgbML4fRTy2e72yfFRvbGpIAAAZZPl+VWntzcav3z5UjUAAKiuemNz47taXixocdNl+cBzrhYdgvznNxf/9b/990e88PTk+P/44/+uwwAqKgon/cFw5s1ub20evjhSXgAAWCXjSRRcvtvbEYUEACipBc8bCAAA87C12QjjdGHLUvC5Ul8AFiGOk3nMXDltM4xi1xwDAMCKKYpfo5AHz/aOT04UBAAAAGB9/PTmolTr8913tfOTo71n5jJeNfV6vVZLF7gs5mhjVTdsc9M4AQBrIQjjy8tWliZKAQAAK6Yoav1R8ObtxU23qxoAAAAALEVR1K46PZ9QQZmtZghyc3Pzj3/4S70LsCaiJG222sF4pBQAALB68l+ikG8vmsPBQDUAAAAAWIr+KOhcX6sDlFMlp8P+9//+L+L4ayN+PX+2N/Xh23dXV3oaYLVled7u9k6yfP/gQDUAAGAl9/k7vf5gODrYf263HwAAAIDFGwZh0mq9evVKKaBsKhmCfHF4+PAnt687g8GwbJsQjEdZlq/ne65e39h79tzvHjBzRVHr9PpRFJ2enakGAACspDjNprv9w9H45PjF9s6uggAAAACwSGGctlqt87PTemNTNaA8Gqu9ebf9/v/1f/8/JVyx3u0gTrP1fM9tNepCkMD8rOfFN+12+/63afbIfzFJkt5vqlGvH5+ceFMBAFA2UZJeXnV2thrHR6KQAAAAACxUGKfNVvv1q3M5SCiPSoYgb/v9r0+Hfefdu3cXP18mSaKbAdZtp/PtRXOtdjrHk2gm7cRpdj+jv9WoezsBAFDmPf/Lq86z3e2T4yOfOAMAAACwMFmeN1vtl2fHLtCFkqhkCPI//+d/7HRvdB4AX9npvLh8d35yZOhZAABYbeNJFFy+29sRhQQAAABgcbI8b7U7TklDSSw6BPlnP/5wevqYiTW3tnyKDbAgw8Gg0+tXfSuKotbu9g7CyITOAACw2qY7/3dRyINne/b/AQAAAFiMu1PSR0ly+OJINWC5Fh2C3PuFugOwmJ3O/ihIs+z8/Fw1AABgHfb/h+Ngf9WjkFmaBMFkrTp3/+DAOxwAAAAooaKo3fRHWZa7NBeWa0EhyH9+8/bPfvzdTJq67ff7g6GeA+CBxpPo8rL18vzU1HgAALDy8l+ikKMgPDrcX9XkXBBMVmDw/m8iBAkAAACUmaF5YOkWFIL8u7//hyRJDw+f+nllkiS/NJXoOQAeLkrSZqv98ux4e2d3JTfw2e723Z3xJHp6axvf1XZ33jfYqNe9eQAAqKIszzu9/mA4Oth/Lj8HAAAAwLyNJ1Hn+vr07EwpYCkWNx32//uP/0W5AViWLM9b7c7Ji8OVPAP64aKin95czGDnoF53lRIAACsgTrNOrz8cjU+OX6zqBVEAAAAAlEReFIoAy9JQAhYszbJ2u/2kd229fnxyopLAt5ruc3Z6/SRJ/A0BAID1ESXp5VVnZ6txfCQKCQAAAI/UbF7Gabb01dhq1F+//l53APARIUgWLS+eOlvrdLdGGYFH64+CKI5fvXqlFAAAsD7C+H0U8tnu9snxUb2xqSAAAAAAACtDCBKgekpyoVV1hXH69qL5+tW5c58AALBWxpMouHy3tyMKCQAA1XDT7U7CaFlLbzTqL1++1AsAAOUnBAnAOsry/OfLd2cnR3vPnqsGAACsj6L4NQr5fHfn9OxMQfjIT28uVn4bf//jDzoaAKiKNMuMCgEAwG/aUAIA1lNe1NrdXv+2pxQAALBuiqI2DMI3by9uul3VAAAAAACoNCNBArC+iqJ20x9FcXJ+fq4aAACwbvKi1h8FxycnSgHwCFE46Q+Gj3hho173txcAAACYISFIANbdeBK1Wq3zs9N6Y1M1AAAAAB4ijpPxJHrEC7caddUDAAAAZsh02ABQC+O02WpH4UQpAAAAAAAAAAAqRAgSAN7L8rzV7gTjkVIAAAAAAAAAAFSFECQA/Kooaled3k23qxQAAAAAAAAAAJXQUAIAuK8/CqI4fvXqlVIAAACsm9Ojw7s7vf4wy/OV2a76xsbR4b7+BQAAAGAlCUECwMfCOG02L//k5Vm9sakaAAAA62P/4ODuzmA4ylYnA1mrb3z3YdOooqurqzTNyrZWWV48+oXDweD9O7O+sffsuf4FAAAAnkgIEgA+I06zZqt9enzos3gAAABgudI0i8sXgny0LM87vf70zlaj7oMXWENROOkPhlVc892dHRcVAABAOQlBAsDnZXne7vaOkuTwxZFqAAAAAAA8XRwn40lU0ZUXglxbw8FgEoZf+unhwf72zq4qAQAskRAkAHxRUdRu+qMkSU/Pzsq/tnczST1dnGZZmpgKHAAAAAAApiZh+JXw7u7OjhAkAMByCUECwG8YBmHSap2fnZY8Fzgaj2fVVK93W4ncJwDAv9qH6Q8Hw9Fs20yyTGEBAADWU5pl7Xb7/bFhkqoGAECZCUECwG8L47TZar9+dV7aHGSWJtOVnFVrQRjrdACgcrI8z3JlAAAAYDbyovaQ2ds7vf709tkfnR4dmkUdAGABhCAB4EGyPL+4fHd+crT37HkJV6/Xu53txgbjUTm3lLWVZFmzeTnbBlUVAKAShoPBQ55Wr284igEAAACANSQECQAPVRS1q07vMIyOT07Ktm7jSTjbBvuDodOHlO0XME7FFgGAVfPAeN99URStW5W+NKzOR7YadUcxAAAAALCGhCAB4Nv0R0GSpi9fvizPKg0Hg7yYcZtRkmZpUtrpvwEAYDU8MN4HAAAAAMCXbCgBAHyrIIwvL1tZmpRkfUbj8czbLIpavz/Q1wAAAAAAAABAmRkJEgAeI0rSZqt9eny49NnWsjQJ43QeLY+C8PhEVwMAAAAAD5KlSRBMvv6cKIoUCgAAmC0hSAB4pCzP293eea223Bzk/MZrnG5gMB4tPeUJAAAAAFRCEEw6vb46AAAACyYECQCPVxS10ThYbkxwFITza7w/GApBAgAAAMByNZuX97/N8kJNAAAAPhCCBIAKC8ajLM/n136UpIoMAAAAAMsVp5kiAAAAfMmGEgBAdfUHw7m2XxS1m25XnQEAAAAAAACAchKCBICqytJkASM1TsJIqQEAAAAAAACAcjIdNgBUVb8/KIq5LyVOsyicbO/sKjgAAAAAAMC3ajYv4zQr7er9/scf9BEwWzfdbpo96e/e4cG+M9R8EyHIX2V5MRwMFrk4NQfgiUZBuJgF3fYHL+1iAgAAAABrbBJGzealOgAAPGTH6Ynh792dHSFIvokQ5K+yPO/0+upQkc6ae2I1yzJ1BkouGI+m/7wWtJMaxQoOAAAAAKyzvKiVeSA3AAB4tHa7PZ5E817K6dHh/sHBnBoXgqR6JFYBpoaj8cKWVRTvRyw/PjlRdgAAAAAAAACgVIQgAaCSFjw64ySM1BwAAAAAAFhJN93u/E6FJOYhBIA5E4IEgEoeihfFQpcYp1kUTrZ3dhUfAAAAAABYMWmWmfIeAKpLCBIAqmcp4zL2B8NzIUgAAKCs4jT76c2FOgAAAADAutlQAgColiicLOViRDNiAwAAAAAAAABlYyRIACijLE2CYPLZH43G46WsUl7UOtfX29vbn/3p/sGBXgMAAAAAAGB+srwYDgYPfPLW1ua2Wc4A1oMQJACUURBMOr1+2dZqGITT22d/JAQJAAAAAADAXGV5/vAzaM92t8+FIAHWg+mwAQAAAAAAAAAAgEoyEiQAAAAAAAAAzFin1y/hpE8AlEq73V69jUqzTM+yYI1m89K7FgAAKI9gPMqyfOmrsbW1uW2qFABgJSRZ9sTPgUuyFboSAACAFTOeRIrAnZ/eXKz2Bvb6w8FwNKfGG3HqkyMAAKBMh0C3gzIcpzzb3T4XggQAVkJR1HwODAAAAMASZXk+v1FQNtQXAAAAAAAAAAAAqCIhSAAAAAAAAAAAAKCShCABAAAAAAAAAACASmooAQCU0N7e7um9b0fjcRinpVrDna3G82fP9BQAAAAAAAAAsERCkABQRvXG5v7B5odvJ2FYq5UrBFmv1/cPDvQU8BRZlg0Hg888nhdlXr1l2dvbnf538LYBAAAAAACA+4QgAQCA5QjjNIz7Vu+BTmu1+/l4AACAD66urtI0m0lTuzvbxycnSgoAAECFCEECAAAAAABUWJpm8YxCkJtZpp4AAABUy4YSAAAAAAAAAAAAAFUkBAkAAAAAAAAAAABUkumwAQAAAAAAAACAOZqEUbN5qQ7APAhBAgAAAAAAAAAAc5QXtTjN1AGYByFIAAAAAAAA4Bv89OZCEQAAgJLYUAIAAAAAAAAAAACgiowECQAAAAAALFqWF8PBoIQrFoxHvdtBtYqZZGYVBAAAYH0JQQIAAAAAAIuW5Xmn1y/jimV5nMoUAgAAQGWYDhsAAAAAAAAAAACoJCFIAAAAAAAAAAAAoJKEIAEAAAAAAAAAAIBKEoIEAAAAAAAAAAAAKkkIEgAAAAAAAAAAAKgkIUgAAAAAAAAAAACgkhpKAAAAAAAAAMCn2u32EpeeJKkuAADgNwlBAgAAAAAAAPAZ40mkCAAAlJzpsAEAAAAAAAAAAIBKEoIEAAAAAAAAAAAAKkkIEgAAAAAAAAAAAKgkIUgAAAAAAAAAAACgkoQgAQAAAAAAAAAAgEpqKAEAAAAAAAAAwBpqt9sPeVqaZWoFQGkJQQIAAAAAAAAArKPxJFIEAKrOdNgAAAAAAAAAAABAJQlBAgAAAAAAAAAAAJUkBAkAAAAAAAAAAABUUkMJAAAAym80Hk/C8JtekiSpugGUVpYm7euOOgAAAAAAPJEQJAAAQAWEcVqrCTUCrIgsTZqtdpbnSgEAAAAA8ERCkAAAAACwOMF41O72ikIlAAAAAABmQAgSAAAAABbkptvtjwJ1AAAAAACYFSFIAAAAAFiEq6urIIzVAQAAAAC+otPrT2/qwMMJQQIAAADAfGVpctXuREmqFAAAAAAAsyUECbBkSZK22+1vekmaZeoGAABQFVE4ubq+yfJcKQAAAAAAZk4IEmDJ4jSb3tQBAABgJQXjUbvbKwqVAAAAAACYCyFIAAAAAJiLm263PwrUAaAMRuPxJAwf8szMNCwAAABQKUKQAAAAADB7rVYrjFN1AD7S6fWnN3VYvF/+JvuzDAAAACtICBIAAAAAZilLk3dX13FqIDEAAAAAgLkTggQAAABgfTWblzNvM82yvFBaAAAAAIBFEIIEAAAA4P9n745a2gbDMAwXKbgdqAg7HcP//6NERMEg25quNE2+N7XiiQiyupA1r70uelJaaPu0J4WbfMfL9RoBAAAAGC4ilnVtBzgIESQAAAAAAAAAAMC/a9rStAs7wEGcmAAAAAAAAAAAAADISAQJAAAAAAAAAAAApOQ4bAAAAAAAAAAAABhFRCzr2g7jEUECAAAAAAAAAADAKJq2NO3CDuNxHDYAAAAAAAAAAACQkitBAsDBXN/c5n3zq/Vm//d/9eO7rxsAAAAAAJiC6LdvziSNCLMAQF4iSAAAAAAAAADgWETfP/5yJikAfB6OwwYAAAAAAAAAAABSEkECAAAAAAAAAAAAKYkgAQAAAAAAAAAAgJREkAAAAAAAAHxAlC76rR0AAACYgrkJAAAAAAAA2NOyrn/+XmggAQAAmAgRJAAAAAAAAH8XpXuoHjddMQUAAADTIYIEAAAAAADg2brZ3N3dv/doF7F1AUgAAAAmRgQJAAAAAADAs347a0vYAQAAgEROTAAAAAAAAAAAAABkJIIEAAAAAAAAAAAAUhJBAgAAAAAAAAAAACnNTQAAAAAAAAAAwGfSdaWqqrFfws4AUyCCBID/ZPcva7XeHOdnv765fX332+XF2fm5nwQAAAAAAAAjaUvsbnYAOAaOwwYAAAAAAAAAAABSEkECAAAAAAAAAAAAKYkgAQAAAAAAAAAAgJREkAAAAAAAAAAAAEBKIkgAAAAAAAAAAAAgpbkJAGCIritVVe35THO9+LNarZvGDgAAAAAAAADAQCJIABikLbG72eFDmrbMZpJQAAAAAAAAAGAox2EDAAAAAAAAAAAAKYkgAQAAAAAAAAAAgJREkAAAAAAAAAAAAEBKIkgAAAAAAAAAAAAgJREkAAAAAAAAAAAAkJIIEgAAAAAAAAAAAEhp/vXLqRUAAAAAAAAAAACAdJ4EGAD0UiXBHYVPBAAAAABJRU5ErkJggg==)\"></div></div>", + "meta": { + "options": { + "id": 761, + "assetType": { + "id": 197, + "name": "htmlblock", + "displayName": "HTML Block" + } + } + }, + "availableViews": [], + "data": { + "email": { + "options": {} + } + }, + "modelVersion": 2 + } + }, + "data": { + "email": { + "options": {} + } + }, + "modelVersion": 2 + } + }, + "template": { + "id": 0, + "assetType": { + "id": 214, + "name": "defaulttemplate" + }, + "name": "CONTENTTEMPLATES_BLANK_PAGE", + "meta": { + "contentHash": -765177524 + }, + "availableViews": [], + "slots": { + "banner": { + "locked": false, + "availableViews": [], + "data": { + "email": { + "options": {} + } + }, + "modelVersion": 2 + } + }, + "data": { + "email": { + "options": {} + } + }, + "modelVersion": 2 + }, + "data": { + "email": { + "options": {} + } + }, + "modelVersion": 2 + } + }, + "availableViews": [ + "subjectline", + "preheader", + "text", + "viewAsAWebPage", + "subscriptioncenter", + "forwardHTML", + "forwardText", + "html" + ], + "data": { + "email": { + "options": { + "characterEncoding": "utf-8" + } + } + }, + "modelVersion": 2, + "category": { + "id": 89397, + "name": "Content Builder", + "parentId": 0 + } +} diff --git a/test/resources/9999999/asset/v1/content/assets/post-response-key=testNew_asset_htmlblock.json b/test/resources/9999999/asset/v1/content/assets/post-response-key=testNew_asset_htmlblock.json new file mode 100644 index 000000000..bbcb17e0a --- /dev/null +++ b/test/resources/9999999/asset/v1/content/assets/post-response-key=testNew_asset_htmlblock.json @@ -0,0 +1,59 @@ +{ + "id": 1322777, + "customerKey": "testNew_asset_htmlblock", + "objectID": "26fdf503-eeed-49eb-b428-cb3ghbc2ba49", + "assetType": { + "id": 196, + "name": "textblock", + "displayName": "Text Block" + }, + "fileProperties": { + "fileName": "testNew_asset_htmlblock" + }, + "name": "testNew_asset_htmlblock", + "description": "bla bla", + "owner": { + "id": 700304523, + "email": "", + "name": "SFMC DEVOPS app user", + "userId": "700304523" + }, + "createdDate": "2024-05-07T05:08:46.927-06:00", + "createdBy": { + "id": 700304523, + "email": "", + "name": "SFMC DEVOPS app user", + "userId": "700304523" + }, + "modifiedDate": "2024-05-07T05:08:46.927-06:00", + "modifiedBy": { + "id": 700304523, + "email": "", + "name": "SFMC DEVOPS app user", + "userId": "700304523" + }, + "enterpriseId": 1111111, + "memberId": 9999999, + "status": { + "id": 1, + "name": "Draft" + }, + "thumbnail": { + "thumbnailUrl": "/v1/assets/1324776/thumbnail" + }, + "category": { + "id": 89397, + "name": "Content Builder", + "parentId": 0 + }, + "content": "<html></html>\n", + "meta": { + "wrapperStyles": { + "mobile": { + "visible": true + } + } + }, + "availableViews": [], + "modelVersion": 2 +} diff --git a/test/resources/9999999/asset/v1/content/assets/post-response-key=testNew_asset_template.json b/test/resources/9999999/asset/v1/content/assets/post-response-key=testNew_asset_template.json new file mode 100644 index 000000000..310e53e5a --- /dev/null +++ b/test/resources/9999999/asset/v1/content/assets/post-response-key=testNew_asset_template.json @@ -0,0 +1,147 @@ +{ + "id": 8973, + "customerKey": "testNew_asset_template", + "objectID": "a6aad42d-df00-4b5d-9780-b7adc2a3cfa4", + "assetType": { + "id": 4, + "name": "template", + "displayName": "Template" + }, + "fileProperties": { + "fileName": "testNew_asset_template" + }, + "name": "testNew_asset_template", + "owner": { + "id": 710420432, + "email": "", + "name": "IDE - joern.berkefeld app user", + "userId": "710420432" + }, + "createdDate": "2025-02-12T11:06:57.24-06:00", + "createdBy": { + "id": 710420432, + "email": "", + "name": "IDE - joern.berkefeld app user", + "userId": "710420432" + }, + "modifiedDate": "2025-02-12T11:06:57.24-06:00", + "modifiedBy": { + "id": 710420432, + "email": "", + "name": "IDE - joern.berkefeld app user", + "userId": "710420432" + }, + "enterpriseId": 1111111, + "memberId": 9999999, + "status": { + "id": 1, + "name": "Draft" + }, + "thumbnail": { + "thumbnailUrl": "/v1/assets/8973/thumbnail" + }, + "category": { + "id": 89397, + "name": "Content Builder", + "parentId": 0 + }, + "content": "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\" \"http://www.w3.org/TR/html4/loose.dtd\">\n<html>\n <head>\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\" />\n <meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\" />\n <style type=\"text/css\">\n ReadMsgBody{ width: 100%;}\n .ExternalClass {width: 100%;}\n .ExternalClass, .ExternalClass p, .ExternalClass span, .ExternalClass font, .ExternalClass td, .ExternalClass div {line-height: 100%;}\n body {-webkit-text-size-adjust:100%; -ms-text-size-adjust:100%;margin:0 !important;}\n p { margin: 1em 0;}\n table td { border-collapse: collapse;}\n img {outline:0;}\n a img {border:none;}\n @-ms-viewport{ width: device-width;}\n </style>\n <style type=\"text/css\">\n @media only screen and (max-width: 480px) {\n .container {width: 100% !important;}\n .footer { width:auto !important; margin-left:0; }\n .mobile-hidden { display:none !important; }\n .logo { display:block !important; padding:0 !important; }\n img { max-width:100% !important; height:auto !important; max-height:auto !important;}\n .header img{max-width:100% !important;height:auto !important; max-height:auto !important;}\n .photo img { width:100% !important; max-width:100% !important; height:auto !important;}\n .drop { display:block !important; width: 100% !important; float:left; clear:both;}\n .footerlogo { display:block !important; width: 100% !important; padding-top:15px; float:left; clear:both;}\n .nav4, .nav5, .nav6 { display: none !important; }\n .tableBlock {width:100% !important;}\n .responsive-td {width:100% !important; display:block !important; padding:0 !important; }\n .fluid, .fluid-centered {\n width: 100% !important;\n max-width: 100% !important;\n height: auto !important;\n margin-left: auto !important;\n margin-right: auto !important;\n }\n .fluid-centered {\n margin-left: auto !important;\n margin-right: auto !important;\n }\n /* MOBILE GLOBAL STYLES - DO NOT CHANGE */\n body { padding: 0px !important; font-size: 16px !important; line-height: 150% !important;}\n h1 { font-size: 22px !important; line-height: normal !important;}\n h2 { font-size: 20px !important; line-height: normal !important;}\n h3 { font-size: 18px !important; line-height: normal !important;}\n .buttonstyles {\n font-family:arial,helvetica,sans-serif !important;\n font-size: 16px !important;\n color: #FFFFFF !important;\n padding: 10px !important;\n }\n /* END OF MOBILE GLOBAL STYLES - DO NOT CHANGE */\n }\n @media only screen and (max-width: 640px) {\n .container { width:100% !important; }\n .mobile-hidden { display:none !important; }\n .logo { display:block !important; padding:0 !important; }\n .photo img { width:100% !important; height:auto !important;}\n .nav5, .nav6 { display: none !important;}\n .fluid, .fluid-centered {\n width: 100% !important;\n max-width: 100% !important;\n height: auto !important;\n margin-left: auto !important;\n margin-right: auto !important;\n }\n .fluid-centered {\n margin-left: auto !important;\n margin-right: auto !important;\n }\n }\n </style>\n <!--[if mso]>\n <style type=\"text/css\">\n /* Begin Outlook Font Fix */\n body, table, td {\n font-family: Arial, Helvetica, sans-serif ;\n font-size:16px;\n color:#000000;\n line-height:1;\n }\n /* End Outlook Font Fix */\n </style>\n <![endif]-->\n </head>\n <body bgcolor=\"#ffffff\" text=\"#000000\" style=\"background-color: #ffffff; color: #000000; padding: 0px; -webkit-text-size-adjust:none; font-size: 16px; font-family:arial,helvetica,sans-serif;\">\n <div style=\"font-size:0; line-height:0;\"><custom name=\"opencounter\" type=\"tracking\"><custom name=\"usermatch\" type=\"tracking\" /></div>\n <table width=\"100%\" border=\"0\" cellpadding=\"0\" cellspacing=\"0\" align=\"center\">\n <tr>\n <td align=\"center\" valign=\"top\">\n <custom type=\"header\"/>\n </td>\n </tr>\n <tr>\n <td align=\"center\">\n <table cellspacing=\"0\" cellpadding=\"0\" border=\"0\" width=\"600\" class=\"container\" align=\"center\">\n <tr>\n <td>\n <table class=\"tb_properties border_style\" style=\"background-color:#FFFFFF;\" cellspacing=\"0\" cellpadding=\"0\" bgcolor=\"#ffffff\" width=\"100%\">\n <tr>\n <td align=\"center\" valign=\"top\">\n <table align=\"left\" border=\"0\" cellpadding=\"0\" cellspacing=\"0\" width=\"100%\">\n <tr>\n <!-- added padding here -->\n <td class=\"content_padding\" style=\"\">\n <!-- end of comment -->\n <table border=\"0\" cellpadding=\"0\" cellspacing=\"0\" width=\"100%\">\n <tr> <!-- top slot -->\n <td align=\"center\" class=\"header\" valign=\"top\">\n <table align=\"left\" border=\"0\" cellpadding=\"0\" cellspacing=\"0\" width=\"100%\">\n <tbody>\n <tr>\n <td align=\"left\" valign=\"top\">\n <table cellspacing=\"0\" cellpadding=\"0\" style=\"width:100%\">\n <tbody>\n <tr>\n <td class=\"responsive-td\" valign=\"top\" style=\"width: 100%;\">\n <div data-type=\"slot\" data-key=\"banner\">\n\t\t\t\t\t\t\t\t\t\t\t\t </div>\n </td>\n </tr>\n </tbody>\n </table>\n </td>\n </tr>\n </tbody>\n </table>\n </td>\n </tr>\n </table>\n </td>\n </tr>\n </table>\n </td>\n </tr>\n </table>\n </td>\n </tr>\n </table>\n </td>\n </tr>\n <tr>\n <td valign=\"top\">\n <custom type=\"footer\" />\n </td>\n </tr>\n </table>\n </body>\n</html>\n", + "meta": { + "globalStyles": { + "isLocked": false, + "template": { + "background-color": "#FFFFFF", + "border-color": "", + "border-width": "0px", + "border-style": "solid" + }, + "body": { + "background-color": "#FFFFFF", + "font-family": "Arial,helvetica,sans-serif", + "font-size": "16px", + "color": "#000000", + "line-height": 1, + "margin": "0px", + "padding": "0px", + "content-padding-top": "0px", + "content-padding-right": "0px", + "content-padding-bottom": "0px", + "content-padding-left": "0px" + }, + "h1": { + "font-family": "Arial,helvetica,sans-serif", + "font-size": "28px", + "color": "#181818", + "line-height": 1, + "font-weight": "bold", + "font-style": "normal" + }, + "h2": { + "font-family": "Arial,helvetica,sans-serif", + "font-size": "22px", + "color": "#181818", + "line-height": 1, + "font-weight": "bold", + "font-style": "normal" + }, + "h3": { + "font-family": "Arial,helvetica,sans-serif", + "font-size": "20px", + "color": "#181818", + "line-height": 1, + "font-weight": "bold", + "font-style": "normal" + }, + "links": { + "font-weight": "normal", + "color": "#0176d3", + "text-decoration": "none" + }, + "buttons": { + "font-family": "Arial,helvetica,sans-serif", + "font-size": "16px", + "color": "#FFFFFF", + "background-color": "#5D5D5D", + "border-radius": "3px", + "padding": "10px", + "border-color": "#5D5D5D", + "border-width": "1px", + "border-style": "solid" + }, + "mobile": { + "body": { + "padding": "0px", + "font-size": "16px", + "line-height": 1.5 + }, + "h1": { + "font-size": "22px", + "line-height": 1 + }, + "h2": { + "font-size": "20px", + "line-height": 1 + }, + "h3": { + "font-size": "18px", + "line-height": 1 + }, + "buttons": { + "font-family": "Arial,helvetica,sans-serif", + "font-size": "16px", + "color": "#FFFFFF", + "padding": "10px" + } + } + } + }, + "availableViews": [], + "slots": { + "banner": { + "thumbnail": {}, + "design": "<p style=\"font-family:Arial;color:#ccc;font-size:12px;text-align:center;vertical-align:middle;font-weight:bold;height:150px;display:flex;flex-direction:column;justify-content:center;padding:10px;margin:0;border: #cccccc dashed 1px;\">Drop blocks or content here</p>", + "modelVersion": 2 + } + }, + "modelVersion": 2 +} diff --git a/test/resources/9999999/asset/v1/content/assets/post-response-key=testNew_asset_templatebasedemail.json b/test/resources/9999999/asset/v1/content/assets/post-response-key=testNew_asset_templatebasedemail.json new file mode 100644 index 000000000..b7f6a0514 --- /dev/null +++ b/test/resources/9999999/asset/v1/content/assets/post-response-key=testNew_asset_templatebasedemail.json @@ -0,0 +1,322 @@ +{ + "id": 8974, + "customerKey": "testNew_asset_templatebasedemail", + "objectID": "184d3a14-b983-429d-a723-36604d24022b", + "contentType": "application/vnd.etmc.email.Message; kind=template", + "assetType": { + "id": 207, + "name": "templatebasedemail", + "displayName": "Template-Based Email" + }, + "name": "testNew_asset_templatebasedemail", + "description": "", + "owner": { + "id": 710420432, + "email": "", + "name": "IDE - joern.berkefeld app user", + "userId": "710420432" + }, + "createdDate": "2025-02-12T11:06:57.63-06:00", + "createdBy": { + "id": 710420432, + "email": "", + "name": "IDE - joern.berkefeld app user", + "userId": "710420432" + }, + "modifiedDate": "2025-02-12T11:06:57.63-06:00", + "modifiedBy": { + "id": 710420432, + "email": "", + "name": "IDE - joern.berkefeld app user", + "userId": "710420432" + }, + "enterpriseId": 1111111, + "memberId": 9999999, + "status": { + "id": 1, + "name": "Draft" + }, + "thumbnail": { + "thumbnailUrl": "/v1/assets/8974/thumbnail" + }, + "category": { + "id": 89397, + "name": "Content Builder", + "parentId": 0 + }, + "meta": { + "globalStyles": { + "isLocked": false, + "template": { + "background-color": "#FFFFFF", + "border-color": "", + "border-width": "0px", + "border-style": "solid" + }, + "body": { + "background-color": "#FFFFFF", + "font-family": "Arial,helvetica,sans-serif", + "font-size": "16px", + "color": "#000000", + "line-height": 1, + "margin": "0px", + "padding": "0px", + "content-padding-top": "0px", + "content-padding-right": "0px", + "content-padding-bottom": "0px", + "content-padding-left": "0px" + }, + "h1": { + "font-family": "Arial,helvetica,sans-serif", + "font-size": "28px", + "color": "#181818", + "line-height": 1, + "font-weight": "bold", + "font-style": "normal" + }, + "h2": { + "font-family": "Arial,helvetica,sans-serif", + "font-size": "22px", + "color": "#181818", + "line-height": 1, + "font-weight": "bold", + "font-style": "normal" + }, + "h3": { + "font-family": "Arial,helvetica,sans-serif", + "font-size": "20px", + "color": "#181818", + "line-height": 1, + "font-weight": "bold", + "font-style": "normal" + }, + "links": { + "font-weight": "normal", + "color": "#0176d3", + "text-decoration": "none" + }, + "buttons": { + "font-family": "Arial,helvetica,sans-serif", + "font-size": "16px", + "color": "#FFFFFF", + "background-color": "#5D5D5D", + "border-radius": "3px", + "padding": "10px", + "border-color": "#5D5D5D", + "border-width": "1px", + "border-style": "solid" + }, + "mobile": { + "body": { + "padding": "0px", + "font-size": "16px", + "line-height": 1.5 + }, + "h1": { + "font-size": "22px", + "line-height": 1 + }, + "h2": { + "font-size": "20px", + "line-height": 1 + }, + "h3": { + "font-size": "18px", + "line-height": 1 + }, + "buttons": { + "font-family": "Arial,helvetica,sans-serif", + "font-size": "16px", + "color": "#FFFFFF", + "padding": "10px" + } + } + } + }, + "views": { + "subjectline": { + "contentType": "application/vnd.etmc.email.View; kind=subjectline", + "thumbnail": {}, + "content": "my subject", + "meta": {}, + "availableViews": [], + "data": { + "email": { + "options": { + "generateFrom": "" + } + } + }, + "modelVersion": 2 + }, + "preheader": { + "thumbnail": {}, + "availableViews": [], + "data": { + "email": { + "options": { + "generateFrom": "" + } + } + }, + "modelVersion": 2 + }, + "html": { + "thumbnail": {}, + "content": "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\" \"http://www.w3.org/TR/html4/loose.dtd\">\n<html>\n <head>\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\" />\n <meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\" />\n <style type=\"text/css\">\n ReadMsgBody{ width: 100%;}\n .ExternalClass {width: 100%;}\n .ExternalClass, .ExternalClass p, .ExternalClass span, .ExternalClass font, .ExternalClass td, .ExternalClass div {line-height: 100%;}\n body {-webkit-text-size-adjust:100%; -ms-text-size-adjust:100%;margin:0 !important;}\n p { margin: 1em 0;}\n table td { border-collapse: collapse;}\n img {outline:0;}\n a img {border:none;}\n @-ms-viewport{ width: device-width;}\n </style>\n <style type=\"text/css\">\n @media only screen and (max-width: 480px) {\n .container {width: 100% !important;}\n .footer { width:auto !important; margin-left:0; }\n .mobile-hidden { display:none !important; }\n .logo { display:block !important; padding:0 !important; }\n img { max-width:100% !important; height:auto !important; max-height:auto !important;}\n .header img{max-width:100% !important;height:auto !important; max-height:auto !important;}\n .photo img { width:100% !important; max-width:100% !important; height:auto !important;}\n .drop { display:block !important; width: 100% !important; float:left; clear:both;}\n .footerlogo { display:block !important; width: 100% !important; padding-top:15px; float:left; clear:both;}\n .nav4, .nav5, .nav6 { display: none !important; }\n .tableBlock {width:100% !important;}\n .responsive-td {width:100% !important; display:block !important; padding:0 !important; }\n .fluid, .fluid-centered {\n width: 100% !important;\n max-width: 100% !important;\n height: auto !important;\n margin-left: auto !important;\n margin-right: auto !important;\n }\n .fluid-centered {\n margin-left: auto !important;\n margin-right: auto !important;\n }\n /* MOBILE GLOBAL STYLES - DO NOT CHANGE */\n body { padding: 0px !important; font-size: 16px !important; line-height: 150% !important;}\n h1 { font-size: 22px !important; line-height: normal !important;}\n h2 { font-size: 20px !important; line-height: normal !important;}\n h3 { font-size: 18px !important; line-height: normal !important;}\n .buttonstyles {\n font-family:arial,helvetica,sans-serif !important;\n font-size: 16px !important;\n color: #FFFFFF !important;\n padding: 10px !important;\n }\n /* END OF MOBILE GLOBAL STYLES - DO NOT CHANGE */\n }\n @media only screen and (max-width: 640px) {\n .container { width:100% !important; }\n .mobile-hidden { display:none !important; }\n .logo { display:block !important; padding:0 !important; }\n .photo img { width:100% !important; height:auto !important;}\n .nav5, .nav6 { display: none !important;}\n .fluid, .fluid-centered {\n width: 100% !important;\n max-width: 100% !important;\n height: auto !important;\n margin-left: auto !important;\n margin-right: auto !important;\n }\n .fluid-centered {\n margin-left: auto !important;\n margin-right: auto !important;\n }\n }\n </style>\n <!--[if mso]>\n <style type=\"text/css\">\n /* Begin Outlook Font Fix */\n body, table, td {\n font-family: Arial, Helvetica, sans-serif ;\n font-size:16px;\n color:#000000;\n line-height:1;\n }\n /* End Outlook Font Fix */\n </style>\n <![endif]-->\n </head>\n <body bgcolor=\"#ffffff\" text=\"#000000\" style=\"background-color: #ffffff; color: #000000; padding: 0px; -webkit-text-size-adjust:none; font-size: 16px; font-family:arial,helvetica,sans-serif;\">\n <div style=\"font-size:0; line-height:0;\"><custom name=\"opencounter\" type=\"tracking\"><custom name=\"usermatch\" type=\"tracking\" /></div>\n <table width=\"100%\" border=\"0\" cellpadding=\"0\" cellspacing=\"0\" align=\"center\">\n <tr>\n <td align=\"center\" valign=\"top\">\n <custom type=\"header\"/>\n </td>\n </tr>\n <tr>\n <td align=\"center\">\n <table cellspacing=\"0\" cellpadding=\"0\" border=\"0\" width=\"600\" class=\"container\" align=\"center\">\n <tr>\n <td>\n <table class=\"tb_properties border_style\" style=\"background-color:#FFFFFF;\" cellspacing=\"0\" cellpadding=\"0\" bgcolor=\"#ffffff\" width=\"100%\">\n <tr>\n <td align=\"center\" valign=\"top\">\n <table align=\"left\" border=\"0\" cellpadding=\"0\" cellspacing=\"0\" width=\"100%\">\n <tr>\n <!-- added padding here -->\n <td class=\"content_padding\" style=\"\">\n <!-- end of comment -->\n <table border=\"0\" cellpadding=\"0\" cellspacing=\"0\" width=\"100%\">\n <tr> <!-- top slot -->\n <td align=\"center\" class=\"header\" valign=\"top\">\n <table align=\"left\" border=\"0\" cellpadding=\"0\" cellspacing=\"0\" width=\"100%\">\n <tbody>\n <tr>\n <td align=\"left\" valign=\"top\">\n <table cellspacing=\"0\" cellpadding=\"0\" style=\"width:100%\">\n <tbody>\n <tr>\n <td class=\"responsive-td\" valign=\"top\" style=\"width: 100%;\">\n <div data-type=\"slot\" data-key=\"banner\">\n\t\t\t\t\t\t\t\t\t\t\t\t </div>\n </td>\n </tr>\n </tbody>\n </table>\n </td>\n </tr>\n </tbody>\n </table>\n </td>\n </tr>\n </table>\n </td>\n </tr>\n </table>\n </td>\n </tr>\n </table>\n </td>\n </tr>\n </table>\n </td>\n </tr>\n <tr>\n <td valign=\"top\">\n <custom type=\"footer\" />\n </td>\n </tr>\n </table>\n </body>\n</html>\n", + "availableViews": [], + "slots": { + "banner": { + "design": "<p style=\"font-family:Arial;color:#ccc;font-size:12px;text-align:center;vertical-align:middle;font-weight:bold;height:150px;display:flex;flex-direction:column;justify-content:center;padding:10px;margin:0;border: #cccccc dashed 1px;\">Drop blocks or content here</p>", + "availableViews": [], + "blocks": {}, + "slots": {}, + "data": { + "email": { + "options": { + "generateFrom": "" + } + } + }, + "modelVersion": 2 + } + }, + "template": { + "id": 8973, + "assetType": { + "id": 4, + "name": "template", + "displayName": "Template" + }, + "name": "testNew_asset_template", + "content": "", + "meta": { + "contentHash": 1850388723 + }, + "availableViews": [], + "slots": { + "banner": { + "locked": false, + "availableViews": [], + "data": { + "email": { + "options": { + "generateFrom": "" + } + } + }, + "modelVersion": 2 + } + }, + "data": { + "email": { + "options": { + "generateFrom": null + } + } + }, + "modelVersion": 2 + }, + "data": { + "email": { + "options": { + "generateFrom": "" + } + } + }, + "modelVersion": 2 + }, + "text": { + "thumbnail": {}, + "availableViews": [], + "data": { + "email": { + "options": { + "generateFrom": "html" + } + } + }, + "generateFrom": "html", + "modelVersion": 2 + }, + "viewAsAWebPage": { + "thumbnail": {}, + "availableViews": [], + "data": { + "email": { + "options": { + "generateFrom": "" + } + } + }, + "modelVersion": 2 + }, + "subscriptioncenter": { + "thumbnail": {}, + "availableViews": [], + "data": { + "email": { + "options": { + "generateFrom": "" + } + } + }, + "modelVersion": 2 + }, + "forwardHTML": { + "thumbnail": {}, + "availableViews": [], + "data": { + "email": { + "options": { + "generateFrom": "" + } + } + }, + "modelVersion": 2 + }, + "forwardText": { + "thumbnail": {}, + "availableViews": [], + "data": { + "email": { + "options": { + "generateFrom": "" + } + } + }, + "modelVersion": 2 + } + }, + "availableViews": [ + "subjectline", + "preheader", + "html", + "text", + "viewAsAWebPage", + "subscriptioncenter", + "forwardHTML", + "forwardText" + ], + "data": { + "email": { + "options": { + "characterEncoding": "utf-8" + }, + "attributes": [], + "legacy": { + "legacyId": 2614, + "legacyKey": "testNew_asset_templatebasedemail", + "legacyType": "email", + "legacyCategoryId": 5330 + } + } + }, + "legacyData": { + "legacyId": 2614, + "legacyKey": "testNew_asset_templatebasedemail", + "legacyType": "email", + "legacyCategoryId": 5330 + }, + "modelVersion": 2 +} diff --git a/test/resources/9999999/asset/v1/content/assets/post-response-key=testNew_asset_withCBBK_notexisting.json b/test/resources/9999999/asset/v1/content/assets/post-response-key=testNew_asset_withCBBK_notexisting.json new file mode 100644 index 000000000..e56c139ef --- /dev/null +++ b/test/resources/9999999/asset/v1/content/assets/post-response-key=testNew_asset_withCBBK_notexisting.json @@ -0,0 +1,59 @@ +{ + "id": 1322777, + "customerKey": "testNew_asset_withCBBK_notexisting", + "objectID": "26fdf503-eeed-49eb-b428-cb3b4bc2ba49", + "assetType": { + "id": 196, + "name": "textblock", + "displayName": "Text Block" + }, + "fileProperties": { + "fileName": "testNew_asset_withCBBK_notexisting" + }, + "name": "testNew_asset_withCBBK_notexisting", + "description": "bla bla", + "owner": { + "id": 700304523, + "email": "", + "name": "SFMC DEVOPS app user", + "userId": "700304523" + }, + "createdDate": "2024-05-07T05:08:46.927-06:00", + "createdBy": { + "id": 700304523, + "email": "", + "name": "SFMC DEVOPS app user", + "userId": "700304523" + }, + "modifiedDate": "2024-05-07T05:08:46.927-06:00", + "modifiedBy": { + "id": 700304523, + "email": "", + "name": "SFMC DEVOPS app user", + "userId": "700304523" + }, + "enterpriseId": 1111111, + "memberId": 9999999, + "status": { + "id": 1, + "name": "Draft" + }, + "thumbnail": { + "thumbnailUrl": "/v1/assets/1324776/thumbnail" + }, + "category": { + "id": 89397, + "name": "Content Builder", + "parentId": 0 + }, + "content": "%%[\n ContentBlockByKey(\"testNew_asset_htmlblock\")\n]%%\n\n", + "meta": { + "wrapperStyles": { + "mobile": { + "visible": true + } + } + }, + "availableViews": [], + "modelVersion": 2 +} diff --git a/test/resources/9999999/asset/v1/content/assets/post-response-key=testNew_asset_withCBBK_preexisting.json b/test/resources/9999999/asset/v1/content/assets/post-response-key=testNew_asset_withCBBK_preexisting.json new file mode 100644 index 000000000..5b0a7501c --- /dev/null +++ b/test/resources/9999999/asset/v1/content/assets/post-response-key=testNew_asset_withCBBK_preexisting.json @@ -0,0 +1,59 @@ +{ + "id": 1322777, + "customerKey": "testNew_asset_withCBBK_preexisting", + "objectID": "26fdf503-eeed-49eb-b428-cb3b4bc2ba49", + "assetType": { + "id": 196, + "name": "textblock", + "displayName": "Text Block" + }, + "fileProperties": { + "fileName": "testNew_asset_withCBBK_preexisting" + }, + "name": "testNew_asset_withCBBK_preexisting", + "description": "bla bla", + "owner": { + "id": 700304523, + "email": "", + "name": "SFMC DEVOPS app user", + "userId": "700304523" + }, + "createdDate": "2024-05-07T05:08:46.927-06:00", + "createdBy": { + "id": 700304523, + "email": "", + "name": "SFMC DEVOPS app user", + "userId": "700304523" + }, + "modifiedDate": "2024-05-07T05:08:46.927-06:00", + "modifiedBy": { + "id": 700304523, + "email": "", + "name": "SFMC DEVOPS app user", + "userId": "700304523" + }, + "enterpriseId": 1111111, + "memberId": 9999999, + "status": { + "id": 1, + "name": "Draft" + }, + "thumbnail": { + "thumbnailUrl": "/v1/assets/1324776/thumbnail" + }, + "category": { + "id": 89397, + "name": "Content Builder", + "parentId": 0 + }, + "content": "%%[\n ContentBlockByKey(\"testExisting_asset_htmlblock\")\n]%%\n\n", + "meta": { + "wrapperStyles": { + "mobile": { + "visible": true + } + } + }, + "availableViews": [], + "modelVersion": 2 +} diff --git a/test/resources/9999999/asset/v1/content/assets/post-response-key=test_slash.json b/test/resources/9999999/asset/v1/content/assets/post-response-key=test_slash.json new file mode 100644 index 000000000..f877af15d --- /dev/null +++ b/test/resources/9999999/asset/v1/content/assets/post-response-key=test_slash.json @@ -0,0 +1,60 @@ +{ + "id": 16992, + "customerKey": "test_slash", + "objectID": "13f34d9c-f555-4fce-b862-26ff7f9fef7a", + "assetType": { + "id": 197, + "name": "htmlblock", + "displayName": "HTML Block" + }, + "fileProperties": { + "fileName": "test_slash" + }, + "name": "test_slash", + "owner": { + "id": 710420432, + "email": "", + "name": "IDE - joern.berkefeld app user", + "userId": "710420432" + }, + "createdDate": "2026-03-06T07:47:11.04-06:00", + "createdBy": { + "id": 710420432, + "email": "", + "name": "IDE - joern.berkefeld app user", + "userId": "710420432" + }, + "modifiedDate": "2026-03-06T07:47:11.04-06:00", + "modifiedBy": { + "id": 710420432, + "email": "", + "name": "IDE - joern.berkefeld app user", + "userId": "710420432" + }, + "enterpriseId": 1111111, + "memberId": 9999999, + "status": { + "id": 1, + "name": "Draft" + }, + "thumbnail": { + "thumbnailUrl": "/v1/assets/16992/thumbnail" + }, + "category": { + "id": 38491, + "name": "bla/blub", + "parentId": 89397 + }, + "content": "<table\n cellpadding=\"0\"\n cellspacing=\"0\"\n width=\"100%\"\n role=\"presentation\"\n style=\"min-width: 100%\"\n class=\"stylingblock-content-wrapper\"\n>\n <tr>\n <td class=\"stylingblock-content-wrapper camarker-inner\">test</td>\n </tr>\n</table>\n", + "design": "", + "meta": { + "wrapperStyles": { + "mobile": { + "visible": true + }, + "styling": {} + } + }, + "availableViews": [], + "modelVersion": 2 +} diff --git a/test/resources/9999999/asset/v1/content/assets/post-response.json b/test/resources/9999999/asset/v1/content/assets/post-response.json new file mode 100644 index 000000000..ae952b77d --- /dev/null +++ b/test/resources/9999999/asset/v1/content/assets/post-response.json @@ -0,0 +1,59 @@ +{ + "id": 1324776, + "customerKey": "testNew_asset-9999999", + "objectID": "26fdf503-eeed-49eb-b428-cb3b4bc2ba48", + "assetType": { + "id": 196, + "name": "textblock", + "displayName": "Text Block" + }, + "fileProperties": { + "fileName": "testNew_asset" + }, + "name": "testNew_asset", + "description": "bla bla", + "owner": { + "id": 700304523, + "email": "", + "name": "SFMC DEVOPS app user", + "userId": "700304523" + }, + "createdDate": "2024-05-07T05:08:46.927-06:00", + "createdBy": { + "id": 700304523, + "email": "", + "name": "SFMC DEVOPS app user", + "userId": "700304523" + }, + "modifiedDate": "2024-05-07T05:08:46.927-06:00", + "modifiedBy": { + "id": 700304523, + "email": "", + "name": "SFMC DEVOPS app user", + "userId": "700304523" + }, + "enterpriseId": 1111111, + "memberId": 9999999, + "status": { + "id": 1, + "name": "Draft" + }, + "thumbnail": { + "thumbnailUrl": "/v1/assets/1324776/thumbnail" + }, + "category": { + "id": 89397, + "name": "Content Builder", + "parentId": 0 + }, + "content": "<table\n cellpadding=\"0\"\n cellspacing=\"0\"\n width=\"100%\"\n role=\"presentation\"\n style=\"min-width: 100%\"\n class=\"stylingblock-content-wrapper\"\n>\n <tr>\n <td class=\"stylingblock-content-wrapper camarker-inner\">foobar</td>\n </tr>\n</table>\n", + "meta": { + "wrapperStyles": { + "mobile": { + "visible": true + } + } + }, + "availableViews": [], + "modelVersion": 2 +} diff --git a/test/resources/9999999/asset/v1/content/assets/query/+post-response-assetType.idIN3,195,196,197,198,199,200,201,202,203,210,211,212,213-slashfolder.json b/test/resources/9999999/asset/v1/content/assets/query/+post-response-assetType.idIN3,195,196,197,198,199,200,201,202,203,210,211,212,213-slashfolder.json new file mode 100644 index 000000000..17d4132ba --- /dev/null +++ b/test/resources/9999999/asset/v1/content/assets/query/+post-response-assetType.idIN3,195,196,197,198,199,200,201,202,203,210,211,212,213-slashfolder.json @@ -0,0 +1,198 @@ +{ + "count": 5, + "page": 1, + "pageSize": 50, + "links": {}, + "items": [ + { + "id": 16992, + "customerKey": "test_slash", + "assetType": { + "id": 197, + "name": "htmlblock", + "displayName": "HTML Block" + }, + "fileProperties": { + "fileName": "test_slash" + }, + "name": "test_slash", + "createdDate": "2026-03-06T07:47:11.04-06:00", + "createdBy": { + "id": 710420432, + "email": "", + "name": "IDE - joern.berkefeld app user", + "userId": "710420432" + }, + "modifiedDate": "2026-03-06T07:47:11.04-06:00", + "modifiedBy": { + "id": 710420432, + "email": "", + "name": "IDE - joern.berkefeld app user", + "userId": "710420432" + }, + "status": { + "id": 1, + "name": "Draft" + }, + "category": { + "id": 38491, + "name": "bla/blub", + "parentId": 89397 + }, + "availableViews": [], + "modelVersion": 2 + }, + { + "id": 1295064, + "customerKey": "testExisting_asset_htmlblock", + "assetType": { + "id": 197, + "name": "htmlblock", + "displayName": "HTML Block" + }, + "fileProperties": { + "fileName": "dont strip non ssjs content" + }, + "name": "dont strip non ssjs content", + "createdDate": "2024-01-08T08:26:58.277-06:00", + "createdBy": { + "id": 700301950, + "email": "joern.berkefeld@accenture.com", + "name": "J\u00f6rn Berkefeld (ASGR)", + "userId": "700301950" + }, + "modifiedDate": "2024-01-08T08:28:01.6-06:00", + "modifiedBy": { + "id": 700301950, + "email": "joern.berkefeld@accenture.com", + "name": "J\u00f6rn Berkefeld (ASGR)", + "userId": "700301950" + }, + "status": { + "id": 1, + "name": "Draft" + }, + "category": { + "id": 89397, + "name": "Content Builder", + "parentId": 0 + }, + "availableViews": [], + "modelVersion": 2 + }, + { + "id": 1295065, + "customerKey": "testExisting_htmlblock1", + "assetType": { + "id": 197, + "name": "htmlblock", + "displayName": "HTML Block" + }, + "fileProperties": { + "fileName": "testExisting_htmlblock1" + }, + "name": "testExisting_htmlblock1", + "createdDate": "2024-01-08T08:26:58.277-06:00", + "createdBy": { + "id": 700301950, + "email": "joern.berkefeld@accenture.com", + "name": "J\u00f6rn Berkefeld (ASGR)", + "userId": "700301950" + }, + "modifiedDate": "2024-01-08T08:28:01.6-06:00", + "modifiedBy": { + "id": 700301950, + "email": "joern.berkefeld@accenture.com", + "name": "J\u00f6rn Berkefeld (ASGR)", + "userId": "700301950" + }, + "status": { + "id": 1, + "name": "Draft" + }, + "category": { + "id": 89397, + "name": "Content Builder", + "parentId": 0 + }, + "availableViews": [], + "modelVersion": 2 + }, + { + "id": 1295066, + "customerKey": "testExisting_htmlblock2", + "assetType": { + "id": 197, + "name": "htmlblock", + "displayName": "HTML Block" + }, + "fileProperties": { + "fileName": "testExisting_htmlblock2" + }, + "name": "testExisting_htmlblock2", + "createdDate": "2024-01-08T08:26:58.277-06:00", + "createdBy": { + "id": 700301950, + "email": "joern.berkefeld@accenture.com", + "name": "J\u00f6rn Berkefeld (ASGR)", + "userId": "700301950" + }, + "modifiedDate": "2024-01-08T08:28:01.6-06:00", + "modifiedBy": { + "id": 700301950, + "email": "joern.berkefeld@accenture.com", + "name": "J\u00f6rn Berkefeld (ASGR)", + "userId": "700301950" + }, + "status": { + "id": 1, + "name": "Draft" + }, + "category": { + "id": 89397, + "name": "Content Builder", + "parentId": 0 + }, + "availableViews": [], + "modelVersion": 2 + }, + { + "id": 1295067, + "customerKey": "testExisting_htmlblock 3 spaces", + "assetType": { + "id": 197, + "name": "htmlblock", + "displayName": "HTML Block" + }, + "fileProperties": { + "fileName": "testExisting_htmlblock 3 spaces" + }, + "name": "testExisting_htmlblock 3 spaces", + "createdDate": "2024-01-08T08:26:58.277-06:00", + "createdBy": { + "id": 700301950, + "email": "joern.berkefeld@accenture.com", + "name": "J\u00f6rn Berkefeld (ASGR)", + "userId": "700301950" + }, + "modifiedDate": "2024-01-08T08:28:01.6-06:00", + "modifiedBy": { + "id": 700301950, + "email": "joern.berkefeld@accenture.com", + "name": "J\u00f6rn Berkefeld (ASGR)", + "userId": "700301950" + }, + "status": { + "id": 1, + "name": "Draft" + }, + "category": { + "id": 89397, + "name": "Content Builder", + "parentId": 0 + }, + "availableViews": [], + "modelVersion": 2 + } + ] +} diff --git a/test/resources/9999999/asset/v1/content/assets/query/post-response-assetType.idIN1,205,206,230,232.json b/test/resources/9999999/asset/v1/content/assets/query/post-response-assetType.idIN1,205,206,230,232.json new file mode 100644 index 000000000..f44c96b44 --- /dev/null +++ b/test/resources/9999999/asset/v1/content/assets/query/post-response-assetType.idIN1,205,206,230,232.json @@ -0,0 +1,129 @@ +{ + "count": 2, + "page": 1, + "pageSize": 50, + "links": {}, + "items": [ + { + "id": 1209971, + "customerKey": "mobileMessage_test", + "assetType": { "id": 230, "name": "jsonmessage", "displayName": "JSON Message" }, + "name": "mobileMessage_test", + "createdDate": "2022-12-07T02:49:36.857-06:00", + "createdBy": { + "id": 700301950, + "email": "joern.berkefeld@accenture.com", + "name": "J├Ârn Berkefeld (ASGR)", + "userId": "700301950" + }, + "modifiedDate": "2022-12-07T02:49:57.44-06:00", + "modifiedBy": { + "id": 700301950, + "email": "joern.berkefeld@accenture.com", + "name": "J├Ârn Berkefeld (ASGR)", + "userId": "700301950" + }, + "status": { "id": 1, "name": "Draft" }, + "category": { "id": 89397, "name": "Content Builder", "parentId": 0 }, + "availableViews": ["push"], + "modelVersion": 2 + }, + { + "id": 950143, + "customerKey": "testExisting_asset", + "objectID": "198ad191-59ae-44d1-9981-ffa71b076ad9", + "contentType": "text/html", + "assetType": { + "id": 205, + "name": "webpage", + "displayName": "Web Page" + }, + "version": 1, + "name": "testExisting_asset", + "owner": { + "id": 717319337, + "email": "joern.berkefeld@accenture.com", + "name": "Jörn Berkefeld", + "userId": "717319337" + }, + "createdDate": "2021-09-13T12:14:02.32-06:00", + "createdBy": { + "id": 717319337, + "email": "joern.berkefeld@accenture.com", + "name": "Jörn Berkefeld", + "userId": "717319337" + }, + "modifiedDate": "2023-08-02T07:10:29.553-06:00", + "modifiedBy": { + "id": 700304523, + "name": "SFMC DEVOPS app user", + "userId": "700304523" + }, + "enterpriseId": 111111, + "memberId": 999999, + "status": { + "id": 1, + "name": "Draft" + }, + "thumbnail": { + "thumbnailUrl": "/v1/assets/950143/thumbnail" + }, + "category": { + "id": 89397 + }, + "meta": { + "globalStyles": { + "isLocked": false, + "body": { + "max-width": "1280px", + "color": "#000000", + "font-family": "Arial", + "font-size": "12px", + "margin": "0px auto" + }, + "template": { + "background-color": "#FFFFFF", + "border": "none", + "box-sizing": "border-box", + "padding": "0px", + "width": "100%" + } + } + }, + "views": { + "html": { + "thumbnail": {}, + "content": "<!DOCTYPE html>\n<html>\n <head>\n <meta\n name=\"viewport\"\n content=\"width=device-width, initial-scale=1, maximum-scale=1, user-scalable=0\"\n />\n <meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\" />\n <style class=\"main_style\">\n .layout-canvas-g {\n background-color: #ffffff;\n border: none;\n box-sizing: border-box;\n padding: 0px;\n width: 100%;\n }\n .layout-canvas-g > .header,\n .layout-canvas-g > .section,\n .layout-canvas-g > .footer {\n position: relative;\n overflow: hidden;\n width: 100%;\n overflow-wrap: break-word;\n }\n .layout-canvas-g > .section {\n margin: 10px 0px;\n }\n .layout-canvas-g > .section > .columns {\n box-sizing: border-box;\n overflow-wrap: break-word;\n }\n body {\n color: #000000;\n font-family: Arial;\n font-size: 12px;\n margin: 0px auto;\n max-width: 1280px;\n }\n @media only screen and (max-width: 480px) {\n .mobile-hidden {\n display: none !important;\n }\n .responsive-td {\n width: 100% !important;\n display: block !important;\n padding: 0px !important;\n }\n }\n .layout-canvas-g > .section > .columns {\n width: 100%;\n }\n </style>\n </head>\n <body>\n <div class=\"layout layout-canvas-g\">\n <div class=\"section\">\n <div class=\"columns col1\">\n <div data-type=\"slot\" data-key=\"col1\"></div>\n </div>\n </div>\n </div>\n </body>\n</html>\n", + "slots": { + "col1": { + "content": "<div data-type=\"block\" data-key=\"bgbqbbx4we9\"></div>", + "design": "<p style=\"font-family:arial;color:#ccc;font-size:11px;text-align:center;vertical-align:middle;font-weight:bold;padding:10px;margin:0;border:#ccc dashed 1px;\">Drop blocks or content here</p>", + "blocks": { + "bgbqbbx4we9": { + "assetType": { + "id": 197, + "name": "htmlblock" + }, + "content": "<table cellpadding=\"0\" cellspacing=\"0\" width=\"100%\" role=\"presentation\" style=\"min-width: 100%; \" class=\"stylingblock-content-wrapper\"><tr><td class=\"stylingblock-content-wrapper camarker-inner\">\n%%[FOR @I=1 TO 1000 DO\n SET @a = CONCAT(IIF(MOD(@i, 3)==0, \"Fizz\", \"\"), IIF(MOD(@i,5)==0,\"Buzz\",\"\"), IIF(MOD(@i, 7)==0, \"Boing\", \"\"), IIF(MOD(@i,11)==0,\"Bang\",\"\"))\nOUTPUT(CONCAT(@a, IIF(LENGTH(@a)>0, \"\", @i), \"<br>\"))NEXT @i\n]%%\n</td></tr></table>", + "design": "<table cellpadding=\"0\" cellspacing=\"0\" width=\"100%\" role=\"presentation\" style=\"min-width: 100%; \" class=\"stylingblock-content-wrapper\"><tr><td class=\"stylingblock-content-wrapper camarker-inner\"><div class=\"default-design\"></div></td></tr></table>", + "meta": { + "wrapperStyles": { + "mobile": { + "visible": true + } + } + }, + "modelVersion": 2 + } + }, + "modelVersion": 2 + } + }, + "modelVersion": 2 + } + }, + "availableViews": ["html"], + "modelVersion": 2 + } + ] +} diff --git a/test/resources/9999999/asset/v1/content/assets/query/post-response-assetType.idIN1,3,14,15,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,205,206,210,211,212,213,215,216,217,218,219,220,221,222,223,224.json b/test/resources/9999999/asset/v1/content/assets/query/post-response-assetType.idIN1,3,14,15,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,205,206,210,211,212,213,215,216,217,218,219,220,221,222,223,224.json new file mode 100644 index 000000000..c5915d83b --- /dev/null +++ b/test/resources/9999999/asset/v1/content/assets/query/post-response-assetType.idIN1,3,14,15,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,205,206,210,211,212,213,215,216,217,218,219,220,221,222,223,224.json @@ -0,0 +1,257 @@ +{ + "count": 5, + "page": 1, + "pageSize": 50, + "links": {}, + "items": [ + { + "id": 1295064, + "customerKey": "testExisting_asset_htmlblock", + "assetType": { + "id": 197, + "name": "htmlblock", + "displayName": "HTML Block" + }, + "fileProperties": { + "fileName": "dont strip non ssjs content" + }, + "name": "dont strip non ssjs content", + "createdDate": "2024-01-08T08:26:58.277-06:00", + "createdBy": { + "id": 700301950, + "email": "joern.berkefeld@accenture.com", + "name": "Jörn Berkefeld (ASGR)", + "userId": "700301950" + }, + "modifiedDate": "2024-01-08T08:28:01.6-06:00", + "modifiedBy": { + "id": 700301950, + "email": "joern.berkefeld@accenture.com", + "name": "Jörn Berkefeld (ASGR)", + "userId": "700301950" + }, + "status": { + "id": 1, + "name": "Draft" + }, + "category": { + "id": 89397, + "name": "Content Builder", + "parentId": 0 + }, + "availableViews": [], + "modelVersion": 2 + }, + { + "id": 1295065, + "customerKey": "testExisting_htmlblock1", + "assetType": { + "id": 197, + "name": "htmlblock", + "displayName": "HTML Block" + }, + "fileProperties": { + "fileName": "testExisting_htmlblock1" + }, + "name": "testExisting_htmlblock1", + "createdDate": "2024-01-08T08:26:58.277-06:00", + "createdBy": { + "id": 700301950, + "email": "joern.berkefeld@accenture.com", + "name": "Jörn Berkefeld (ASGR)", + "userId": "700301950" + }, + "modifiedDate": "2024-01-08T08:28:01.6-06:00", + "modifiedBy": { + "id": 700301950, + "email": "joern.berkefeld@accenture.com", + "name": "Jörn Berkefeld (ASGR)", + "userId": "700301950" + }, + "status": { + "id": 1, + "name": "Draft" + }, + "category": { + "id": 89397, + "name": "Content Builder", + "parentId": 0 + }, + "availableViews": [], + "modelVersion": 2 + }, + { + "id": 1295066, + "customerKey": "testExisting_htmlblock2", + "assetType": { + "id": 197, + "name": "htmlblock", + "displayName": "HTML Block" + }, + "fileProperties": { + "fileName": "testExisting_htmlblock2" + }, + "name": "testExisting_htmlblock2", + "createdDate": "2024-01-08T08:26:58.277-06:00", + "createdBy": { + "id": 700301950, + "email": "joern.berkefeld@accenture.com", + "name": "Jörn Berkefeld (ASGR)", + "userId": "700301950" + }, + "modifiedDate": "2024-01-08T08:28:01.6-06:00", + "modifiedBy": { + "id": 700301950, + "email": "joern.berkefeld@accenture.com", + "name": "Jörn Berkefeld (ASGR)", + "userId": "700301950" + }, + "status": { + "id": 1, + "name": "Draft" + }, + "category": { + "id": 89397, + "name": "Content Builder", + "parentId": 0 + }, + "availableViews": [], + "modelVersion": 2 + }, + { + "id": 1295067, + "customerKey": "testExisting_htmlblock 3 spaces", + "assetType": { + "id": 197, + "name": "htmlblock", + "displayName": "HTML Block" + }, + "fileProperties": { + "fileName": "testExisting_htmlblock 3 spaces" + }, + "name": "testExisting_htmlblock 3 spaces", + "createdDate": "2024-01-08T08:26:58.277-06:00", + "createdBy": { + "id": 700301950, + "email": "joern.berkefeld@accenture.com", + "name": "Jörn Berkefeld (ASGR)", + "userId": "700301950" + }, + "modifiedDate": "2024-01-08T08:28:01.6-06:00", + "modifiedBy": { + "id": 700301950, + "email": "joern.berkefeld@accenture.com", + "name": "Jörn Berkefeld (ASGR)", + "userId": "700301950" + }, + "status": { + "id": 1, + "name": "Draft" + }, + "category": { + "id": 89397, + "name": "Content Builder", + "parentId": 0 + }, + "availableViews": [], + "modelVersion": 2 + }, + { + "id": 950143, + "customerKey": "testExisting_asset", + "objectID": "198ad191-59ae-44d1-9981-ffa71b076ad9", + "contentType": "text/html", + "assetType": { + "id": 205, + "name": "webpage", + "displayName": "Web Page" + }, + "version": 1, + "name": "testExisting_asset", + "owner": { + "id": 717319337, + "email": "joern.berkefeld@accenture.com", + "name": "Jörn Berkefeld", + "userId": "717319337" + }, + "createdDate": "2021-09-13T12:14:02.32-06:00", + "createdBy": { + "id": 717319337, + "email": "joern.berkefeld@accenture.com", + "name": "Jörn Berkefeld", + "userId": "717319337" + }, + "modifiedDate": "2023-08-02T07:10:29.553-06:00", + "modifiedBy": { + "id": 700304523, + "name": "SFMC DEVOPS app user", + "userId": "700304523" + }, + "enterpriseId": 111111, + "memberId": 999999, + "status": { + "id": 1, + "name": "Draft" + }, + "thumbnail": { + "thumbnailUrl": "/v1/assets/950143/thumbnail" + }, + "category": { + "id": 89397 + }, + "meta": { + "globalStyles": { + "isLocked": false, + "body": { + "max-width": "1280px", + "color": "#000000", + "font-family": "Arial", + "font-size": "12px", + "margin": "0px auto" + }, + "template": { + "background-color": "#FFFFFF", + "border": "none", + "box-sizing": "border-box", + "padding": "0px", + "width": "100%" + } + } + }, + "views": { + "html": { + "thumbnail": {}, + "content": "<!DOCTYPE html>\n<html>\n <head>\n <meta\n name=\"viewport\"\n content=\"width=device-width, initial-scale=1, maximum-scale=1, user-scalable=0\"\n />\n <meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\" />\n <style class=\"main_style\">\n .layout-canvas-g {\n background-color: #ffffff;\n border: none;\n box-sizing: border-box;\n padding: 0px;\n width: 100%;\n }\n .layout-canvas-g > .header,\n .layout-canvas-g > .section,\n .layout-canvas-g > .footer {\n position: relative;\n overflow: hidden;\n width: 100%;\n overflow-wrap: break-word;\n }\n .layout-canvas-g > .section {\n margin: 10px 0px;\n }\n .layout-canvas-g > .section > .columns {\n box-sizing: border-box;\n overflow-wrap: break-word;\n }\n body {\n color: #000000;\n font-family: Arial;\n font-size: 12px;\n margin: 0px auto;\n max-width: 1280px;\n }\n @media only screen and (max-width: 480px) {\n .mobile-hidden {\n display: none !important;\n }\n .responsive-td {\n width: 100% !important;\n display: block !important;\n padding: 0px !important;\n }\n }\n .layout-canvas-g > .section > .columns {\n width: 100%;\n }\n </style>\n </head>\n <body>\n <div class=\"layout layout-canvas-g\">\n <div class=\"section\">\n <div class=\"columns col1\">\n <div data-type=\"slot\" data-key=\"col1\"></div>\n </div>\n </div>\n </div>\n </body>\n</html>\n", + "slots": { + "col1": { + "content": "<div data-type=\"block\" data-key=\"bgbqbbx4we9\"></div>", + "design": "<p style=\"font-family:arial;color:#ccc;font-size:11px;text-align:center;vertical-align:middle;font-weight:bold;padding:10px;margin:0;border:#ccc dashed 1px;\">Drop blocks or content here</p>", + "blocks": { + "bgbqbbx4we9": { + "assetType": { + "id": 197, + "name": "htmlblock" + }, + "content": "<table cellpadding=\"0\" cellspacing=\"0\" width=\"100%\" role=\"presentation\" style=\"min-width: 100%; \" class=\"stylingblock-content-wrapper\"><tr><td class=\"stylingblock-content-wrapper camarker-inner\">\n%%[FOR @I=1 TO 1000 DO\n SET @a = CONCAT(IIF(MOD(@i, 3)==0, \"Fizz\", \"\"), IIF(MOD(@i,5)==0,\"Buzz\",\"\"), IIF(MOD(@i, 7)==0, \"Boing\", \"\"), IIF(MOD(@i,11)==0,\"Bang\",\"\"))\nOUTPUT(CONCAT(@a, IIF(LENGTH(@a)>0, \"\", @i), \"<br>\"))NEXT @i\n]%%\n</td></tr></table>", + "design": "<table cellpadding=\"0\" cellspacing=\"0\" width=\"100%\" role=\"presentation\" style=\"min-width: 100%; \" class=\"stylingblock-content-wrapper\"><tr><td class=\"stylingblock-content-wrapper camarker-inner\"><div class=\"default-design\"></div></td></tr></table>", + "meta": { + "wrapperStyles": { + "mobile": { + "visible": true + } + } + }, + "modelVersion": 2 + } + }, + "modelVersion": 2 + } + }, + "modelVersion": 2 + } + }, + "availableViews": ["html"], + "modelVersion": 2 + } + ] +} diff --git a/test/resources/9999999/asset/v1/content/assets/query/post-response-assetType.idIN1,3,4,14,15,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,205,206,210,211,212,213,214,215,216,217,218,219,220,221,222.json b/test/resources/9999999/asset/v1/content/assets/query/post-response-assetType.idIN1,3,4,14,15,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,205,206,210,211,212,213,214,215,216,217,218,219,220,221,222.json new file mode 100644 index 000000000..e3b53e848 --- /dev/null +++ b/test/resources/9999999/asset/v1/content/assets/query/post-response-assetType.idIN1,3,4,14,15,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,205,206,210,211,212,213,214,215,216,217,218,219,220,221,222.json @@ -0,0 +1,377 @@ +{ + "count": 9, + "page": 1, + "pageSize": 50, + "links": {}, + "items": [ + { + "id": 5286, + "customerKey": "testExisting_asset_template", + "assetType": { + "id": 4, + "name": "template", + "displayName": "Template" + }, + "name": " testExisting_asset_template", + "createdDate": "2024-04-22T03:33:08.253-06:00", + "createdBy": { + "id": 710411605, + "email": "joern.berkefeld@accenture.com", + "name": "Jörn Berkefeld", + "userId": "710411605" + }, + "modifiedDate": "2024-05-13T07:12:13.117-06:00", + "modifiedBy": { + "id": 710420432, + "name": "joern.berkefeld app user", + "userId": "710420432" + }, + "category": { + "id": 89397 + }, + "modelVersion": 2 + }, + { + "id": 1295064, + "customerKey": "testExisting_asset_htmlblock", + "assetType": { + "id": 197, + "name": "htmlblock", + "displayName": "HTML Block" + }, + "fileProperties": { + "fileName": "dont strip non ssjs content" + }, + "name": "dont strip non ssjs content", + "createdDate": "2024-01-08T08:26:58.277-06:00", + "createdBy": { + "id": 700301950, + "email": "joern.berkefeld@accenture.com", + "name": "Jörn Berkefeld (ASGR)", + "userId": "700301950" + }, + "modifiedDate": "2024-01-08T08:28:01.6-06:00", + "modifiedBy": { + "id": 700301950, + "email": "joern.berkefeld@accenture.com", + "name": "Jörn Berkefeld (ASGR)", + "userId": "700301950" + }, + "status": { + "id": 1, + "name": "Draft" + }, + "category": { + "id": 89397, + "name": "Content Builder", + "parentId": 0 + }, + "availableViews": [], + "modelVersion": 2 + }, + { + "id": 1295065, + "customerKey": "testExisting_htmlblock1", + "assetType": { + "id": 197, + "name": "htmlblock", + "displayName": "HTML Block" + }, + "fileProperties": { + "fileName": "testExisting_htmlblock1" + }, + "name": "testExisting_htmlblock1", + "createdDate": "2024-01-08T08:26:58.277-06:00", + "createdBy": { + "id": 700301950, + "email": "joern.berkefeld@accenture.com", + "name": "Jörn Berkefeld (ASGR)", + "userId": "700301950" + }, + "modifiedDate": "2024-01-08T08:28:01.6-06:00", + "modifiedBy": { + "id": 700301950, + "email": "joern.berkefeld@accenture.com", + "name": "Jörn Berkefeld (ASGR)", + "userId": "700301950" + }, + "status": { + "id": 1, + "name": "Draft" + }, + "category": { + "id": 89397, + "name": "Content Builder", + "parentId": 0 + }, + "availableViews": [], + "modelVersion": 2 + }, + { + "id": 1295066, + "customerKey": "testExisting_htmlblock2", + "assetType": { + "id": 197, + "name": "htmlblock", + "displayName": "HTML Block" + }, + "fileProperties": { + "fileName": "testExisting_htmlblock2" + }, + "name": "testExisting_htmlblock2", + "createdDate": "2024-01-08T08:26:58.277-06:00", + "createdBy": { + "id": 700301950, + "email": "joern.berkefeld@accenture.com", + "name": "Jörn Berkefeld (ASGR)", + "userId": "700301950" + }, + "modifiedDate": "2024-01-08T08:28:01.6-06:00", + "modifiedBy": { + "id": 700301950, + "email": "joern.berkefeld@accenture.com", + "name": "Jörn Berkefeld (ASGR)", + "userId": "700301950" + }, + "status": { + "id": 1, + "name": "Draft" + }, + "category": { + "id": 89397, + "name": "Content Builder", + "parentId": 0 + }, + "availableViews": [], + "modelVersion": 2 + }, + { + "id": 1295067, + "customerKey": "testExisting_htmlblock 3 spaces", + "assetType": { + "id": 197, + "name": "htmlblock", + "displayName": "HTML Block" + }, + "fileProperties": { + "fileName": "testExisting_htmlblock 3 spaces" + }, + "name": "testExisting_htmlblock 3 spaces", + "createdDate": "2024-01-08T08:26:58.277-06:00", + "createdBy": { + "id": 700301950, + "email": "joern.berkefeld@accenture.com", + "name": "Jörn Berkefeld (ASGR)", + "userId": "700301950" + }, + "modifiedDate": "2024-01-08T08:28:01.6-06:00", + "modifiedBy": { + "id": 700301950, + "email": "joern.berkefeld@accenture.com", + "name": "Jörn Berkefeld (ASGR)", + "userId": "700301950" + }, + "status": { + "id": 1, + "name": "Draft" + }, + "category": { + "id": 89397, + "name": "Content Builder", + "parentId": 0 + }, + "availableViews": [], + "modelVersion": 2 + }, + { + "id": 950143, + "customerKey": "testExisting_asset", + "objectID": "198ad191-59ae-44d1-9981-ffa71b076ad9", + "contentType": "text/html", + "assetType": { + "id": 205, + "name": "webpage", + "displayName": "Web Page" + }, + "version": 1, + "name": "testExisting_asset", + "owner": { + "id": 717319337, + "email": "joern.berkefeld@accenture.com", + "name": "Jörn Berkefeld", + "userId": "717319337" + }, + "createdDate": "2021-09-13T12:14:02.32-06:00", + "createdBy": { + "id": 717319337, + "email": "joern.berkefeld@accenture.com", + "name": "Jörn Berkefeld", + "userId": "717319337" + }, + "modifiedDate": "2023-08-02T07:10:29.553-06:00", + "modifiedBy": { + "id": 700304523, + "name": "SFMC DEVOPS app user", + "userId": "700304523" + }, + "enterpriseId": 111111, + "memberId": 999999, + "status": { + "id": 1, + "name": "Draft" + }, + "thumbnail": { + "thumbnailUrl": "/v1/assets/950143/thumbnail" + }, + "category": { + "id": 89397 + }, + "meta": { + "globalStyles": { + "isLocked": false, + "body": { + "max-width": "1280px", + "color": "#000000", + "font-family": "Arial", + "font-size": "12px", + "margin": "0px auto" + }, + "template": { + "background-color": "#FFFFFF", + "border": "none", + "box-sizing": "border-box", + "padding": "0px", + "width": "100%" + } + } + }, + "views": { + "html": { + "thumbnail": {}, + "content": "<!DOCTYPE html>\n<html>\n <head>\n <meta\n name=\"viewport\"\n content=\"width=device-width, initial-scale=1, maximum-scale=1, user-scalable=0\"\n />\n <meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\" />\n <style class=\"main_style\">\n .layout-canvas-g {\n background-color: #ffffff;\n border: none;\n box-sizing: border-box;\n padding: 0px;\n width: 100%;\n }\n .layout-canvas-g > .header,\n .layout-canvas-g > .section,\n .layout-canvas-g > .footer {\n position: relative;\n overflow: hidden;\n width: 100%;\n overflow-wrap: break-word;\n }\n .layout-canvas-g > .section {\n margin: 10px 0px;\n }\n .layout-canvas-g > .section > .columns {\n box-sizing: border-box;\n overflow-wrap: break-word;\n }\n body {\n color: #000000;\n font-family: Arial;\n font-size: 12px;\n margin: 0px auto;\n max-width: 1280px;\n }\n @media only screen and (max-width: 480px) {\n .mobile-hidden {\n display: none !important;\n }\n .responsive-td {\n width: 100% !important;\n display: block !important;\n padding: 0px !important;\n }\n }\n .layout-canvas-g > .section > .columns {\n width: 100%;\n }\n </style>\n </head>\n <body>\n <div class=\"layout layout-canvas-g\">\n <div class=\"section\">\n <div class=\"columns col1\">\n <div data-type=\"slot\" data-key=\"col1\"></div>\n </div>\n </div>\n </div>\n </body>\n</html>\n", + "slots": { + "col1": { + "content": "<div data-type=\"block\" data-key=\"bgbqbbx4we9\"></div>", + "design": "<p style=\"font-family:arial;color:#ccc;font-size:11px;text-align:center;vertical-align:middle;font-weight:bold;padding:10px;margin:0;border:#ccc dashed 1px;\">Drop blocks or content here</p>", + "blocks": { + "bgbqbbx4we9": { + "assetType": { + "id": 197, + "name": "htmlblock" + }, + "content": "<table cellpadding=\"0\" cellspacing=\"0\" width=\"100%\" role=\"presentation\" style=\"min-width: 100%; \" class=\"stylingblock-content-wrapper\"><tr><td class=\"stylingblock-content-wrapper camarker-inner\">\n%%[FOR @I=1 TO 1000 DO\n SET @a = CONCAT(IIF(MOD(@i, 3)==0, \"Fizz\", \"\"), IIF(MOD(@i,5)==0,\"Buzz\",\"\"), IIF(MOD(@i, 7)==0, \"Boing\", \"\"), IIF(MOD(@i,11)==0,\"Bang\",\"\"))\nOUTPUT(CONCAT(@a, IIF(LENGTH(@a)>0, \"\", @i), \"<br>\"))NEXT @i\n]%%\n</td></tr></table>", + "design": "<table cellpadding=\"0\" cellspacing=\"0\" width=\"100%\" role=\"presentation\" style=\"min-width: 100%; \" class=\"stylingblock-content-wrapper\"><tr><td class=\"stylingblock-content-wrapper camarker-inner\"><div class=\"default-design\"></div></td></tr></table>", + "meta": { + "wrapperStyles": { + "mobile": { + "visible": true + } + } + }, + "modelVersion": 2 + } + }, + "modelVersion": 2 + } + }, + "modelVersion": 2 + } + }, + "availableViews": ["html"], + "modelVersion": 2 + }, + { + "id": 9459, + "customerKey": "test_interactivecontent_content", + "objectID": "283dc273-84c0-44b6-979c-b9f2534b28a1", + "assetType": { + "id": 205, + "name": "webpage", + "displayName": "Web Page" + }, + "name": "test_interactivecontent", + "createdDate": "2025-03-25T03:02:47.323-06:00", + "createdBy": { + "id": 710420418, + "email": "joern.berkefeld@accenture.com", + "name": "Jörn Berkefeld", + "userId": "710420418" + }, + "modifiedDate": "2025-03-25T03:02:47.323-06:00", + "modifiedBy": { + "id": 710420418, + "email": "joern.berkefeld@accenture.com", + "name": "Jörn Berkefeld", + "userId": "710420418" + }, + "category": { + "id": 5328, + "name": "Content Builder", + "parentId": 0 + }, + "modelVersion": 2 + }, + { + "id": 9461, + "customerKey": "test_microsite_content", + "objectID": "8f32dff3-026b-4cd6-9096-d3ecb319f386", + "assetType": { + "id": 205, + "name": "webpage", + "displayName": "Web Page" + }, + "name": "test_microsite_content", + "createdDate": "2025-03-25T03:10:56.733-06:00", + "createdBy": { + "id": 710420418, + "email": "joern.berkefeld@accenture.com", + "name": "Jörn Berkefeld", + "userId": "710420418" + }, + "modifiedDate": "2025-03-25T03:10:56.733-06:00", + "modifiedBy": { + "id": 710420418, + "email": "joern.berkefeld@accenture.com", + "name": "Jörn Berkefeld", + "userId": "710420418" + }, + "category": { + "id": 5328, + "name": "Content Builder", + "parentId": 0 + }, + "modelVersion": 2 + }, + { + "id": 9466, + "customerKey": "test_landingpage_content", + "objectID": "95aa069b-5d48-41b9-a206-a623832cfc6d", + "assetType": { + "id": 205, + "name": "webpage", + "displayName": "Web Page" + }, + "name": "test_landingpage_content", + "createdDate": "2025-03-25T03:17:52.317-06:00", + "createdBy": { + "id": 710420418, + "email": "joern.berkefeld@accenture.com", + "name": "Jörn Berkefeld", + "userId": "710420418" + }, + "modifiedDate": "2025-03-25T03:17:52.317-06:00", + "modifiedBy": { + "id": 710420418, + "email": "joern.berkefeld@accenture.com", + "name": "Jörn Berkefeld", + "userId": "710420418" + }, + "category": { + "id": 5328, + "name": "Content Builder", + "parentId": 0 + }, + "modelVersion": 2 + } + ] +} diff --git a/test/resources/9999999/asset/v1/content/assets/query/post-response-assetType.idIN1,3,4,5,14,15,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,205,206,207,208,209,210,211,212,213,214,215,216,217,218.json b/test/resources/9999999/asset/v1/content/assets/query/post-response-assetType.idIN1,3,4,5,14,15,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,205,206,207,208,209,210,211,212,213,214,215,216,217,218.json new file mode 100644 index 000000000..0c80bd5e6 --- /dev/null +++ b/test/resources/9999999/asset/v1/content/assets/query/post-response-assetType.idIN1,3,4,5,14,15,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,205,206,207,208,209,210,211,212,213,214,215,216,217,218.json @@ -0,0 +1,460 @@ +{ + "count": 8, + "page": 1, + "pageSize": 50, + "links": {}, + "items": [ + { + "id": 1295064, + "customerKey": "testExisting_asset_htmlblock", + "assetType": { + "id": 197, + "name": "htmlblock", + "displayName": "HTML Block" + }, + "fileProperties": { + "fileName": "dont strip non ssjs content" + }, + "name": "dont strip non ssjs content", + "createdDate": "2024-01-08T08:26:58.277-06:00", + "createdBy": { + "id": 700301950, + "email": "joern.berkefeld@accenture.com", + "name": "Jörn Berkefeld (ASGR)", + "userId": "700301950" + }, + "modifiedDate": "2024-01-08T08:28:01.6-06:00", + "modifiedBy": { + "id": 700301950, + "email": "joern.berkefeld@accenture.com", + "name": "Jörn Berkefeld (ASGR)", + "userId": "700301950" + }, + "status": { + "id": 1, + "name": "Draft" + }, + "category": { + "id": 89397, + "name": "Content Builder", + "parentId": 0 + }, + "availableViews": [], + "modelVersion": 2 + }, + { + "id": 1295065, + "customerKey": "testExisting_htmlblock1", + "assetType": { + "id": 197, + "name": "htmlblock", + "displayName": "HTML Block" + }, + "fileProperties": { + "fileName": "testExisting_htmlblock1" + }, + "name": "testExisting_htmlblock1", + "createdDate": "2024-01-08T08:26:58.277-06:00", + "createdBy": { + "id": 700301950, + "email": "joern.berkefeld@accenture.com", + "name": "Jörn Berkefeld (ASGR)", + "userId": "700301950" + }, + "modifiedDate": "2024-01-08T08:28:01.6-06:00", + "modifiedBy": { + "id": 700301950, + "email": "joern.berkefeld@accenture.com", + "name": "Jörn Berkefeld (ASGR)", + "userId": "700301950" + }, + "status": { + "id": 1, + "name": "Draft" + }, + "category": { + "id": 89397, + "name": "Content Builder", + "parentId": 0 + }, + "availableViews": [], + "modelVersion": 2 + }, + { + "id": 1295066, + "customerKey": "testExisting_htmlblock2", + "assetType": { + "id": 197, + "name": "htmlblock", + "displayName": "HTML Block" + }, + "fileProperties": { + "fileName": "testExisting_htmlblock2" + }, + "name": "testExisting_htmlblock2", + "createdDate": "2024-01-08T08:26:58.277-06:00", + "createdBy": { + "id": 700301950, + "email": "joern.berkefeld@accenture.com", + "name": "Jörn Berkefeld (ASGR)", + "userId": "700301950" + }, + "modifiedDate": "2024-01-08T08:28:01.6-06:00", + "modifiedBy": { + "id": 700301950, + "email": "joern.berkefeld@accenture.com", + "name": "Jörn Berkefeld (ASGR)", + "userId": "700301950" + }, + "status": { + "id": 1, + "name": "Draft" + }, + "category": { + "id": 89397, + "name": "Content Builder", + "parentId": 0 + }, + "availableViews": [], + "modelVersion": 2 + }, + { + "id": 1295067, + "customerKey": "testExisting_htmlblock 3 spaces", + "assetType": { + "id": 197, + "name": "htmlblock", + "displayName": "HTML Block" + }, + "fileProperties": { + "fileName": "testExisting_htmlblock 3 spaces" + }, + "name": "testExisting_htmlblock 3 spaces", + "createdDate": "2024-01-08T08:26:58.277-06:00", + "createdBy": { + "id": 700301950, + "email": "joern.berkefeld@accenture.com", + "name": "Jörn Berkefeld (ASGR)", + "userId": "700301950" + }, + "modifiedDate": "2024-01-08T08:28:01.6-06:00", + "modifiedBy": { + "id": 700301950, + "email": "joern.berkefeld@accenture.com", + "name": "Jörn Berkefeld (ASGR)", + "userId": "700301950" + }, + "status": { + "id": 1, + "name": "Draft" + }, + "category": { + "id": 89397, + "name": "Content Builder", + "parentId": 0 + }, + "availableViews": [], + "modelVersion": 2 + }, + { + "id": 5286, + "customerKey": "testExisting_asset_template", + "assetType": { + "id": 4, + "name": "template", + "displayName": "Template" + }, + "name": " testExisting_asset_template", + "createdDate": "2024-04-22T03:33:08.253-06:00", + "createdBy": { + "id": 710411605, + "email": "joern.berkefeld@accenture.com", + "name": "Jörn Berkefeld", + "userId": "710411605" + }, + "modifiedDate": "2024-05-13T07:12:13.117-06:00", + "modifiedBy": { + "id": 710420432, + "name": "joern.berkefeld app user", + "userId": "710420432" + }, + "category": { + "id": 89397 + }, + "modelVersion": 2 + }, + { + "id": 5289, + "customerKey": "testExisting_asset_templatebasedemail", + "assetType": { + "id": 207, + "name": "templatebasedemail", + "displayName": "Template-Based Email" + }, + "name": " testExisting_asset_templatebasedemail", + "createdDate": "2024-04-22T06:36:03.117-06:00", + "createdBy": { + "id": 710369861, + "email": "joern.berkefeld@accenture.com", + "name": "Jörn Berkefeld", + "userId": "710369861" + }, + "modifiedDate": "2024-05-13T07:15:29.77-06:00", + "modifiedBy": { + "id": 710420432, + "name": "joern.berkefeld app user", + "userId": "710420432" + }, + "status": { + "id": 1, + "name": "Draft" + }, + "category": { + "id": 89397 + }, + "availableViews": [ + "subjectline", + "preheader", + "text", + "viewAsAWebPage", + "subscriptioncenter", + "forwardHTML", + "forwardText", + "html" + ], + "data": { + "email": { + "options": { + "characterEncoding": "utf-8" + }, + "legacy": { + "legacyId": 1643, + "legacyKey": "9b6edc22-d19a-429a-a705-da88c3a16543", + "legacyType": "email", + "legacyCategoryId": 10251 + } + } + }, + "legacyData": { + "legacyId": 1643, + "legacyKey": "9b6edc22-d19a-429a-a705-da88c3a16543", + "legacyType": "email", + "legacyCategoryId": 10251 + }, + "modelVersion": 2 + }, + { + "id": 808714, + "customerKey": "testExisting_asset_message", + "assetType": { "id": 208, "name": "htmlemail", "displayName": "HTML Email" }, + "name": "testExisting_asset_message", + "createdDate": "2021-01-31T14:11:01.423-06:00", + "createdBy": { + "id": 700304523, + "email": "", + "name": "SFMC DEVOPS app user", + "userId": "700304523" + }, + "modifiedDate": "2021-01-31T14:13:30-06:00", + "modifiedBy": { + "id": 700304523, + "name": "SFMC DEVOPS app user", + "userId": "700304523" + }, + "status": { "id": 1, "name": "Draft" }, + "category": { "id": 89397, "name": "Content Builder", "parentId": 0 }, + "availableViews": ["html", "text", "subjectline", "preheader"], + "data": { + "email": { + "options": { "characterEncoding": "us-ascii" }, + "legacy": { + "legacyId": 531213, + "legacyKey": "testExisting_asset_message", + "legacyType": "email", + "legacyCategoryId": 290835 + } + } + }, + "legacyData": { + "legacyId": 531213, + "legacyKey": "testExisting_asset_message", + "legacyType": "email", + "legacyCategoryId": 290835 + }, + "modelVersion": 2 + }, + { + "id": 950143, + "customerKey": "testExisting_asset", + "objectID": "198ad191-59ae-44d1-9981-ffa71b076ad9", + "contentType": "text/html", + "assetType": { + "id": 205, + "name": "webpage", + "displayName": "Web Page" + }, + "version": 1, + "name": "testExisting_asset", + "owner": { + "id": 717319337, + "email": "joern.berkefeld@accenture.com", + "name": "Jörn Berkefeld", + "userId": "717319337" + }, + "createdDate": "2021-09-13T12:14:02.32-06:00", + "createdBy": { + "id": 717319337, + "email": "joern.berkefeld@accenture.com", + "name": "Jörn Berkefeld", + "userId": "717319337" + }, + "modifiedDate": "2023-08-02T07:10:29.553-06:00", + "modifiedBy": { + "id": 700304523, + "name": "SFMC DEVOPS app user", + "userId": "700304523" + }, + "enterpriseId": 111111, + "memberId": 999999, + "status": { + "id": 1, + "name": "Draft" + }, + "thumbnail": { + "thumbnailUrl": "/v1/assets/950143/thumbnail" + }, + "category": { + "id": 89397 + }, + "meta": { + "globalStyles": { + "isLocked": false, + "body": { + "max-width": "1280px", + "color": "#000000", + "font-family": "Arial", + "font-size": "12px", + "margin": "0px auto" + }, + "template": { + "background-color": "#FFFFFF", + "border": "none", + "box-sizing": "border-box", + "padding": "0px", + "width": "100%" + } + } + }, + "views": { + "html": { + "thumbnail": {}, + "content": "<!DOCTYPE html>\n<html>\n <head>\n <meta\n name=\"viewport\"\n content=\"width=device-width, initial-scale=1, maximum-scale=1, user-scalable=0\"\n />\n <meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\" />\n <style class=\"main_style\">\n .layout-canvas-g {\n background-color: #ffffff;\n border: none;\n box-sizing: border-box;\n padding: 0px;\n width: 100%;\n }\n .layout-canvas-g > .header,\n .layout-canvas-g > .section,\n .layout-canvas-g > .footer {\n position: relative;\n overflow: hidden;\n width: 100%;\n overflow-wrap: break-word;\n }\n .layout-canvas-g > .section {\n margin: 10px 0px;\n }\n .layout-canvas-g > .section > .columns {\n box-sizing: border-box;\n overflow-wrap: break-word;\n }\n body {\n color: #000000;\n font-family: Arial;\n font-size: 12px;\n margin: 0px auto;\n max-width: 1280px;\n }\n @media only screen and (max-width: 480px) {\n .mobile-hidden {\n display: none !important;\n }\n .responsive-td {\n width: 100% !important;\n display: block !important;\n padding: 0px !important;\n }\n }\n .layout-canvas-g > .section > .columns {\n width: 100%;\n }\n </style>\n </head>\n <body>\n <div class=\"layout layout-canvas-g\">\n <div class=\"section\">\n <div class=\"columns col1\">\n <div data-type=\"slot\" data-key=\"col1\"></div>\n </div>\n </div>\n </div>\n </body>\n</html>\n", + "slots": { + "col1": { + "content": "<div data-type=\"block\" data-key=\"bgbqbbx4we9\"></div>", + "design": "<p style=\"font-family:arial;color:#ccc;font-size:11px;text-align:center;vertical-align:middle;font-weight:bold;padding:10px;margin:0;border:#ccc dashed 1px;\">Drop blocks or content here</p>", + "blocks": { + "bgbqbbx4we9": { + "assetType": { + "id": 197, + "name": "htmlblock" + }, + "content": "<table cellpadding=\"0\" cellspacing=\"0\" width=\"100%\" role=\"presentation\" style=\"min-width: 100%; \" class=\"stylingblock-content-wrapper\"><tr><td class=\"stylingblock-content-wrapper camarker-inner\">\n%%[FOR @I=1 TO 1000 DO\n SET @a = CONCAT(IIF(MOD(@i, 3)==0, \"Fizz\", \"\"), IIF(MOD(@i,5)==0,\"Buzz\",\"\"), IIF(MOD(@i, 7)==0, \"Boing\", \"\"), IIF(MOD(@i,11)==0,\"Bang\",\"\"))\nOUTPUT(CONCAT(@a, IIF(LENGTH(@a)>0, \"\", @i), \"<br>\"))NEXT @i\n]%%\n</td></tr></table>", + "design": "<table cellpadding=\"0\" cellspacing=\"0\" width=\"100%\" role=\"presentation\" style=\"min-width: 100%; \" class=\"stylingblock-content-wrapper\"><tr><td class=\"stylingblock-content-wrapper camarker-inner\"><div class=\"default-design\"></div></td></tr></table>", + "meta": { + "wrapperStyles": { + "mobile": { + "visible": true + } + } + }, + "modelVersion": 2 + } + }, + "modelVersion": 2 + } + }, + "modelVersion": 2 + } + }, + "availableViews": ["html"], + "modelVersion": 2 + }, + { + "id": 1295075, + "customerKey": "testExisting_htmlblock_matchName1", + "assetType": { + "id": 197, + "name": "htmlblock", + "displayName": "HTML Block" + }, + "fileProperties": { + "fileName": "testExisting_htmlblock_matchName" + }, + "name": "testExisting_htmlblock_matchName", + "createdDate": "2024-01-08T08:26:58.277-06:00", + "createdBy": { + "id": 700301950, + "email": "joern.berkefeld@accenture.com", + "name": "Jörn Berkefeld (ASGR)", + "userId": "700301950" + }, + "modifiedDate": "2024-01-08T08:28:01.6-06:00", + "modifiedBy": { + "id": 700301950, + "email": "joern.berkefeld@accenture.com", + "name": "Jörn Berkefeld (ASGR)", + "userId": "700301950" + }, + "status": { + "id": 1, + "name": "Draft" + }, + "category": { + "id": 89397, + "name": "Content Builder", + "parentId": 0 + }, + "availableViews": [], + "modelVersion": 2 + }, + { + "id": 1295076, + "customerKey": "testExisting_htmlblock_matchName2", + "assetType": { + "id": 197, + "name": "htmlblock", + "displayName": "HTML Block" + }, + "fileProperties": { + "fileName": "testExisting_htmlblock_matchName" + }, + "name": "testExisting_htmlblock_matchName", + "createdDate": "2024-01-08T08:26:58.277-06:00", + "createdBy": { + "id": 700301950, + "email": "joern.berkefeld@accenture.com", + "name": "Jörn Berkefeld (ASGR)", + "userId": "700301950" + }, + "modifiedDate": "2024-01-08T08:28:01.6-06:00", + "modifiedBy": { + "id": 700301950, + "email": "joern.berkefeld@accenture.com", + "name": "Jörn Berkefeld (ASGR)", + "userId": "700301950" + }, + "status": { + "id": 1, + "name": "Draft" + }, + "category": { + "id": 90888, + "name": "Test Folder", + "parentId": 89397 + }, + "availableViews": [], + "modelVersion": 2 + } + ] +} diff --git a/test/resources/9999999/asset/v1/content/assets/query/post-response-assetType.idIN1,5,205,206,207,208,209,230,232.json b/test/resources/9999999/asset/v1/content/assets/query/post-response-assetType.idIN1,5,205,206,207,208,209,230,232.json new file mode 100644 index 000000000..c60fff5b6 --- /dev/null +++ b/test/resources/9999999/asset/v1/content/assets/query/post-response-assetType.idIN1,5,205,206,207,208,209,230,232.json @@ -0,0 +1,229 @@ +{ + "count": 4, + "page": 1, + "pageSize": 50, + "links": {}, + "items": [ + { + "id": 1209971, + "customerKey": "mobileMessage_test", + "assetType": { "id": 230, "name": "jsonmessage", "displayName": "JSON Message" }, + "name": "mobileMessage_test", + "createdDate": "2022-12-07T02:49:36.857-06:00", + "createdBy": { + "id": 700301950, + "email": "joern.berkefeld@accenture.com", + "name": "J├Ârn Berkefeld (ASGR)", + "userId": "700301950" + }, + "modifiedDate": "2022-12-07T02:49:57.44-06:00", + "modifiedBy": { + "id": 700301950, + "email": "joern.berkefeld@accenture.com", + "name": "J├Ârn Berkefeld (ASGR)", + "userId": "700301950" + }, + "status": { "id": 1, "name": "Draft" }, + "category": { "id": 89397, "name": "Content Builder", "parentId": 0 }, + "availableViews": ["push"], + "modelVersion": 2 + }, + { + "id": 808714, + "customerKey": "testExisting_asset_message", + "assetType": { "id": 208, "name": "htmlemail", "displayName": "HTML Email" }, + "name": "testExisting_asset_message", + "createdDate": "2021-01-31T14:11:01.423-06:00", + "createdBy": { + "id": 700304523, + "email": "", + "name": "SFMC DEVOPS app user", + "userId": "700304523" + }, + "modifiedDate": "2021-01-31T14:13:30-06:00", + "modifiedBy": { + "id": 700304523, + "name": "SFMC DEVOPS app user", + "userId": "700304523" + }, + "status": { "id": 1, "name": "Draft" }, + "category": { "id": 89397, "name": "Content Builder", "parentId": 0 }, + "availableViews": ["html", "text", "subjectline", "preheader"], + "data": { + "email": { + "options": { "characterEncoding": "us-ascii" }, + "legacy": { + "legacyId": 531213, + "legacyKey": "testExisting_asset_message", + "legacyType": "email", + "legacyCategoryId": 290835 + } + } + }, + "legacyData": { + "legacyId": 531213, + "legacyKey": "testExisting_asset_message", + "legacyType": "email", + "legacyCategoryId": 290835 + }, + "modelVersion": 2 + }, + { + "id": 5289, + "customerKey": "testExisting_asset_templatebasedemail", + "assetType": { + "id": 207, + "name": "templatebasedemail", + "displayName": "Template-Based Email" + }, + "name": " testExisting_asset_templatebasedemail", + "createdDate": "2024-04-22T06:36:03.117-06:00", + "createdBy": { + "id": 710369861, + "email": "joern.berkefeld@accenture.com", + "name": "Jörn Berkefeld", + "userId": "710369861" + }, + "modifiedDate": "2024-05-13T07:15:29.77-06:00", + "modifiedBy": { + "id": 710420432, + "name": "joern.berkefeld app user", + "userId": "710420432" + }, + "status": { + "id": 1, + "name": "Draft" + }, + "category": { + "id": 89397 + }, + "availableViews": [ + "subjectline", + "preheader", + "text", + "viewAsAWebPage", + "subscriptioncenter", + "forwardHTML", + "forwardText", + "html" + ], + "data": { + "email": { + "options": { + "characterEncoding": "utf-8" + }, + "legacy": { + "legacyId": 1643, + "legacyKey": "9b6edc22-d19a-429a-a705-da88c3a16543", + "legacyType": "email", + "legacyCategoryId": 10251 + } + } + }, + "legacyData": { + "legacyId": 1643, + "legacyKey": "9b6edc22-d19a-429a-a705-da88c3a16543", + "legacyType": "email", + "legacyCategoryId": 10251 + }, + "modelVersion": 2 + }, + { + "id": 950143, + "customerKey": "testExisting_asset", + "objectID": "198ad191-59ae-44d1-9981-ffa71b076ad9", + "contentType": "text/html", + "assetType": { + "id": 205, + "name": "webpage", + "displayName": "Web Page" + }, + "version": 1, + "name": "testExisting_asset", + "owner": { + "id": 717319337, + "email": "joern.berkefeld@accenture.com", + "name": "Jörn Berkefeld", + "userId": "717319337" + }, + "createdDate": "2021-09-13T12:14:02.32-06:00", + "createdBy": { + "id": 717319337, + "email": "joern.berkefeld@accenture.com", + "name": "Jörn Berkefeld", + "userId": "717319337" + }, + "modifiedDate": "2023-08-02T07:10:29.553-06:00", + "modifiedBy": { + "id": 700304523, + "name": "SFMC DEVOPS app user", + "userId": "700304523" + }, + "enterpriseId": 111111, + "memberId": 999999, + "status": { + "id": 1, + "name": "Draft" + }, + "thumbnail": { + "thumbnailUrl": "/v1/assets/950143/thumbnail" + }, + "category": { + "id": 89397 + }, + "meta": { + "globalStyles": { + "isLocked": false, + "body": { + "max-width": "1280px", + "color": "#000000", + "font-family": "Arial", + "font-size": "12px", + "margin": "0px auto" + }, + "template": { + "background-color": "#FFFFFF", + "border": "none", + "box-sizing": "border-box", + "padding": "0px", + "width": "100%" + } + } + }, + "views": { + "html": { + "thumbnail": {}, + "content": "<!DOCTYPE html>\n<html>\n <head>\n <meta\n name=\"viewport\"\n content=\"width=device-width, initial-scale=1, maximum-scale=1, user-scalable=0\"\n />\n <meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\" />\n <style class=\"main_style\">\n .layout-canvas-g {\n background-color: #ffffff;\n border: none;\n box-sizing: border-box;\n padding: 0px;\n width: 100%;\n }\n .layout-canvas-g > .header,\n .layout-canvas-g > .section,\n .layout-canvas-g > .footer {\n position: relative;\n overflow: hidden;\n width: 100%;\n overflow-wrap: break-word;\n }\n .layout-canvas-g > .section {\n margin: 10px 0px;\n }\n .layout-canvas-g > .section > .columns {\n box-sizing: border-box;\n overflow-wrap: break-word;\n }\n body {\n color: #000000;\n font-family: Arial;\n font-size: 12px;\n margin: 0px auto;\n max-width: 1280px;\n }\n @media only screen and (max-width: 480px) {\n .mobile-hidden {\n display: none !important;\n }\n .responsive-td {\n width: 100% !important;\n display: block !important;\n padding: 0px !important;\n }\n }\n .layout-canvas-g > .section > .columns {\n width: 100%;\n }\n </style>\n </head>\n <body>\n <div class=\"layout layout-canvas-g\">\n <div class=\"section\">\n <div class=\"columns col1\">\n <div data-type=\"slot\" data-key=\"col1\"></div>\n </div>\n </div>\n </div>\n </body>\n</html>\n", + "slots": { + "col1": { + "content": "<div data-type=\"block\" data-key=\"bgbqbbx4we9\"></div>", + "design": "<p style=\"font-family:arial;color:#ccc;font-size:11px;text-align:center;vertical-align:middle;font-weight:bold;padding:10px;margin:0;border:#ccc dashed 1px;\">Drop blocks or content here</p>", + "blocks": { + "bgbqbbx4we9": { + "assetType": { + "id": 197, + "name": "htmlblock" + }, + "content": "<table cellpadding=\"0\" cellspacing=\"0\" width=\"100%\" role=\"presentation\" style=\"min-width: 100%; \" class=\"stylingblock-content-wrapper\"><tr><td class=\"stylingblock-content-wrapper camarker-inner\">\n%%[FOR @I=1 TO 1000 DO\n SET @a = CONCAT(IIF(MOD(@i, 3)==0, \"Fizz\", \"\"), IIF(MOD(@i,5)==0,\"Buzz\",\"\"), IIF(MOD(@i, 7)==0, \"Boing\", \"\"), IIF(MOD(@i,11)==0,\"Bang\",\"\"))\nOUTPUT(CONCAT(@a, IIF(LENGTH(@a)>0, \"\", @i), \"<br>\"))NEXT @i\n]%%\n</td></tr></table>", + "design": "<table cellpadding=\"0\" cellspacing=\"0\" width=\"100%\" role=\"presentation\" style=\"min-width: 100%; \" class=\"stylingblock-content-wrapper\"><tr><td class=\"stylingblock-content-wrapper camarker-inner\"><div class=\"default-design\"></div></td></tr></table>", + "meta": { + "wrapperStyles": { + "mobile": { + "visible": true + } + } + }, + "modelVersion": 2 + } + }, + "modelVersion": 2 + } + }, + "modelVersion": 2 + } + }, + "availableViews": ["html"], + "modelVersion": 2 + } + ] +} diff --git a/test/resources/9999999/asset/v1/content/assets/query/post-response-assetType.idIN14,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192.json b/test/resources/9999999/asset/v1/content/assets/query/post-response-assetType.idIN14,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192.json new file mode 100644 index 000000000..347c7bc35 --- /dev/null +++ b/test/resources/9999999/asset/v1/content/assets/query/post-response-assetType.idIN14,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192.json @@ -0,0 +1,7 @@ +{ + "count": 0, + "page": 1, + "pageSize": 50, + "links": {}, + "items": [] +} diff --git a/test/resources/9999999/asset/v1/content/assets/query/post-response-assetType.idIN15,193,194.json b/test/resources/9999999/asset/v1/content/assets/query/post-response-assetType.idIN15,193,194.json new file mode 100644 index 000000000..347c7bc35 --- /dev/null +++ b/test/resources/9999999/asset/v1/content/assets/query/post-response-assetType.idIN15,193,194.json @@ -0,0 +1,7 @@ +{ + "count": 0, + "page": 1, + "pageSize": 50, + "links": {}, + "items": [] +} diff --git a/test/resources/9999999/asset/v1/content/assets/query/post-response-assetType.idIN215,216,217,218,219,220,221,222,223,224,225,226,227,228.json b/test/resources/9999999/asset/v1/content/assets/query/post-response-assetType.idIN215,216,217,218,219,220,221,222,223,224,225,226,227,228.json new file mode 100644 index 000000000..347c7bc35 --- /dev/null +++ b/test/resources/9999999/asset/v1/content/assets/query/post-response-assetType.idIN215,216,217,218,219,220,221,222,223,224,225,226,227,228.json @@ -0,0 +1,7 @@ +{ + "count": 0, + "page": 1, + "pageSize": 50, + "links": {}, + "items": [] +} diff --git a/test/resources/9999999/asset/v1/content/assets/query/post-response-assetType.idIN219,220,221,222,223,224,225,226,227,228,230,232,240,241,242,243,244,245.json b/test/resources/9999999/asset/v1/content/assets/query/post-response-assetType.idIN219,220,221,222,223,224,225,226,227,228,230,232,240,241,242,243,244,245.json new file mode 100644 index 000000000..e67e7539a --- /dev/null +++ b/test/resources/9999999/asset/v1/content/assets/query/post-response-assetType.idIN219,220,221,222,223,224,225,226,227,228,230,232,240,241,242,243,244,245.json @@ -0,0 +1,168 @@ +{ + "count": 4, + "page": 1, + "pageSize": 50, + "links": {}, + "items": [ + { + "id": 1209971, + "customerKey": "mobileMessage_test", + "assetType": { "id": 230, "name": "jsonmessage", "displayName": "JSON Message" }, + "name": "mobileMessage_test", + "createdDate": "2022-12-07T02:49:36.857-06:00", + "createdBy": { + "id": 700301950, + "email": "joern.berkefeld@accenture.com", + "name": "J├Ârn Berkefeld (ASGR)", + "userId": "700301950" + }, + "modifiedDate": "2022-12-07T02:49:57.44-06:00", + "modifiedBy": { + "id": 700301950, + "email": "joern.berkefeld@accenture.com", + "name": "J├Ârn Berkefeld (ASGR)", + "userId": "700301950" + }, + "status": { "id": 1, "name": "Draft" }, + "category": { "id": 89397, "name": "Content Builder", "parentId": 0 }, + "availableViews": ["push"], + "modelVersion": 2 + }, + { + "id": 9463, + "customerKey": "test_coderesource_json", + "assetType": { + "id": 242, + "name": "jsoncoderesource", + "displayName": "JSON Code Resource" + }, + "name": "test_coderesource_json", + "createdDate": "2025-03-25T03:15:22.72-06:00", + "createdBy": { + "id": 710420418, + "email": "joern.berkefeld@accenture.com", + "name": "Jörn Berkefeld", + "userId": "710420418" + }, + "modifiedDate": "2025-03-25T03:16:40.913-06:00", + "modifiedBy": { + "id": 710420418, + "email": "joern.berkefeld@accenture.com", + "name": "Jörn Berkefeld", + "userId": "710420418" + }, + "status": { + "id": 1, + "name": "Draft" + }, + "category": { + "id": 27675, + "name": "mcdev", + "parentId": 23009 + }, + "content": "{\n\"test\": true\n}", + "meta": { + "cloudPages": { + "publishDate": "2025-03-25 03:16:40.913" + } + }, + "availableViews": [], + "data": { + "site": { + "content": "{\"url\":\"https://oss-test.accenture.com/test_coderesource_json\"}" + } + }, + "modelVersion": 2 + }, + { + "id": 9460, + "customerKey": "test_coderesource_xml", + "assetType": { + "id": 245, + "name": "xmlcoderesource", + "displayName": "XML Code Resource" + }, + "name": "test_coderesource_xml", + "createdDate": "2025-03-25T03:03:45.713-06:00", + "createdBy": { + "id": 710420418, + "email": "joern.berkefeld@accenture.com", + "name": "Jörn Berkefeld", + "userId": "710420418" + }, + "modifiedDate": "2025-03-25T03:04:06.48-06:00", + "modifiedBy": { + "id": 710420418, + "email": "joern.berkefeld@accenture.com", + "name": "Jörn Berkefeld", + "userId": "710420418" + }, + "status": { + "id": 1, + "name": "Draft" + }, + "category": { + "id": 27675, + "name": "mcdev", + "parentId": 23009 + }, + "content": "<xml>test</xml>", + "meta": { + "cloudPages": {} + }, + "availableViews": [], + "data": { + "site": { + "content": "{\"url\":\"https://oss-test.accenture.com/test_coderesource_xml\"}" + } + }, + "modelVersion": 2 + }, + { + "id": 9451, + "customerKey": "test_coderesource_js", + "assetType": { + "id": 240, + "name": "jscoderesource", + "displayName": "Javascript Code Resource" + }, + "name": "test_coderesource_js", + "createdDate": "2025-03-24T05:20:40.82-06:00", + "createdBy": { + "id": 710420418, + "email": "joern.berkefeld@accenture.com", + "name": "Jörn Berkefeld", + "userId": "710420418" + }, + "modifiedDate": "2025-03-25T03:03:20.603-06:00", + "modifiedBy": { + "id": 710420418, + "email": "joern.berkefeld@accenture.com", + "name": "Jörn Berkefeld", + "userId": "710420418" + }, + "status": { + "id": 1, + "name": "Draft" + }, + "category": { + "id": 27675, + "name": "mcdev", + "parentId": 23009 + }, + "content": "/* insert code here */\n", + "meta": { + "cloudPages": { + "publishDate": "2025-03-24 06:05:23.203" + } + }, + "availableViews": [], + "data": { + "site": { + "content": "{\"url\":\"https://oss-test.accenture.com/test_coderesource\"}" + } + }, + "modelVersion": 2 + } + ] +} diff --git a/test/resources/9999999/asset/v1/content/assets/query/post-response-assetType.idIN223,224,225,226,227,228,230,232.json b/test/resources/9999999/asset/v1/content/assets/query/post-response-assetType.idIN223,224,225,226,227,228,230,232.json new file mode 100644 index 000000000..eef3b5b61 --- /dev/null +++ b/test/resources/9999999/asset/v1/content/assets/query/post-response-assetType.idIN223,224,225,226,227,228,230,232.json @@ -0,0 +1,32 @@ +{ + "count": 1, + "page": 1, + "pageSize": 50, + "links": {}, + "items": [ + { + "id": 1209971, + "customerKey": "mobileMessage_test", + "assetType": { "id": 230, "name": "jsonmessage", "displayName": "JSON Message" }, + "name": "mobileMessage_test", + "createdDate": "2022-12-07T02:49:36.857-06:00", + "createdBy": { + "id": 700301950, + "email": "joern.berkefeld@accenture.com", + "name": "J├Ârn Berkefeld (ASGR)", + "userId": "700301950" + }, + "modifiedDate": "2022-12-07T02:49:57.44-06:00", + "modifiedBy": { + "id": 700301950, + "email": "joern.berkefeld@accenture.com", + "name": "J├Ârn Berkefeld (ASGR)", + "userId": "700301950" + }, + "status": { "id": 1, "name": "Draft" }, + "category": { "id": 89397, "name": "Content Builder", "parentId": 0 }, + "availableViews": ["push"], + "modelVersion": 2 + } + ] +} diff --git a/test/resources/9999999/asset/v1/content/assets/query/post-response-assetType.idIN225,226,227,228,230,232.json b/test/resources/9999999/asset/v1/content/assets/query/post-response-assetType.idIN225,226,227,228,230,232.json new file mode 100644 index 000000000..347c7bc35 --- /dev/null +++ b/test/resources/9999999/asset/v1/content/assets/query/post-response-assetType.idIN225,226,227,228,230,232.json @@ -0,0 +1,7 @@ +{ + "count": 0, + "page": 1, + "pageSize": 50, + "links": {}, + "items": [] +} diff --git a/test/resources/9999999/asset/v1/content/assets/query/post-response-assetType.idIN240,241,242,243,244,245.json b/test/resources/9999999/asset/v1/content/assets/query/post-response-assetType.idIN240,241,242,243,244,245.json new file mode 100644 index 000000000..9b5aad411 --- /dev/null +++ b/test/resources/9999999/asset/v1/content/assets/query/post-response-assetType.idIN240,241,242,243,244,245.json @@ -0,0 +1,144 @@ +{ + "count": 3, + "page": 1, + "pageSize": 50, + "links": {}, + "items": [ + { + "id": 9463, + "customerKey": "test_coderesource_json", + "assetType": { + "id": 242, + "name": "jsoncoderesource", + "displayName": "JSON Code Resource" + }, + "name": "test_coderesource_json", + "createdDate": "2025-03-25T03:15:22.72-06:00", + "createdBy": { + "id": 710420418, + "email": "joern.berkefeld@accenture.com", + "name": "Jörn Berkefeld", + "userId": "710420418" + }, + "modifiedDate": "2025-03-25T03:16:40.913-06:00", + "modifiedBy": { + "id": 710420418, + "email": "joern.berkefeld@accenture.com", + "name": "Jörn Berkefeld", + "userId": "710420418" + }, + "status": { + "id": 1, + "name": "Draft" + }, + "category": { + "id": 27675, + "name": "mcdev", + "parentId": 23009 + }, + "content": "{\n\"test\": true\n}", + "meta": { + "cloudPages": { + "publishDate": "2025-03-25 03:16:40.913" + } + }, + "availableViews": [], + "data": { + "site": { + "content": "{\"url\":\"https://oss-test.accenture.com/test_coderesource_json\"}" + } + }, + "modelVersion": 2 + }, + { + "id": 9460, + "customerKey": "test_coderesource_xml", + "assetType": { + "id": 245, + "name": "xmlcoderesource", + "displayName": "XML Code Resource" + }, + "name": "test_coderesource_xml", + "createdDate": "2025-03-25T03:03:45.713-06:00", + "createdBy": { + "id": 710420418, + "email": "joern.berkefeld@accenture.com", + "name": "Jörn Berkefeld", + "userId": "710420418" + }, + "modifiedDate": "2025-03-25T03:04:06.48-06:00", + "modifiedBy": { + "id": 710420418, + "email": "joern.berkefeld@accenture.com", + "name": "Jörn Berkefeld", + "userId": "710420418" + }, + "status": { + "id": 1, + "name": "Draft" + }, + "category": { + "id": 27675, + "name": "mcdev", + "parentId": 23009 + }, + "content": "<xml>test</xml>", + "meta": { + "cloudPages": {} + }, + "availableViews": [], + "data": { + "site": { + "content": "{\"url\":\"https://oss-test.accenture.com/test_coderesource_xml\"}" + } + }, + "modelVersion": 2 + }, + { + "id": 9451, + "customerKey": "test_coderesource_js", + "assetType": { + "id": 240, + "name": "jscoderesource", + "displayName": "Javascript Code Resource" + }, + "name": "test_coderesource_js", + "createdDate": "2025-03-24T05:20:40.82-06:00", + "createdBy": { + "id": 710420418, + "email": "joern.berkefeld@accenture.com", + "name": "Jörn Berkefeld", + "userId": "710420418" + }, + "modifiedDate": "2025-03-25T03:03:20.603-06:00", + "modifiedBy": { + "id": 710420418, + "email": "joern.berkefeld@accenture.com", + "name": "Jörn Berkefeld", + "userId": "710420418" + }, + "status": { + "id": 1, + "name": "Draft" + }, + "category": { + "id": 27675, + "name": "mcdev", + "parentId": 23009 + }, + "content": "/* insert code here */\n", + "meta": { + "cloudPages": { + "publishDate": "2025-03-24 06:05:23.203" + } + }, + "availableViews": [], + "data": { + "site": { + "content": "{\"url\":\"https://oss-test.accenture.com/test_coderesource\"}" + } + }, + "modelVersion": 2 + } + ] +} diff --git a/test/resources/9999999/asset/v1/content/assets/query/post-response-assetType.idIN246,247,248,249.json b/test/resources/9999999/asset/v1/content/assets/query/post-response-assetType.idIN246,247,248,249.json new file mode 100644 index 000000000..20f588bc0 --- /dev/null +++ b/test/resources/9999999/asset/v1/content/assets/query/post-response-assetType.idIN246,247,248,249.json @@ -0,0 +1,132 @@ +{ + "count": 4, + "page": 1, + "pageSize": 50, + "links": {}, + "items": [ + { + "id": 9465, + "customerKey": "test_landingpage", + "assetType": { + "id": 247, + "name": "landingpage", + "displayName": "Landing Page" + }, + "name": "test_landingpage", + "createdDate": "2025-03-25T03:17:51.88-06:00", + "createdBy": { + "id": 710420418, + "email": "joern.berkefeld@accenture.com", + "name": "Jörn Berkefeld", + "userId": "710420418" + }, + "modifiedDate": "2025-03-25T03:17:52.187-06:00", + "modifiedBy": { + "id": 710420418, + "email": "joern.berkefeld@accenture.com", + "name": "Jörn Berkefeld", + "userId": "710420418" + }, + "status": { + "id": 1, + "name": "Draft" + }, + "category": { + "id": 27675, + "name": "mcdev", + "parentId": 23009 + }, + "content": "{\"url\":\"https://oss-test.accenture.com/test_landingpage\"}", + "meta": { + "thumbnailRefAssetId": 9466, + "cloudPages": {} + }, + "availableViews": [], + "modelVersion": 2 + }, + { + "id": 9456, + "customerKey": "test_microsite", + "assetType": { + "id": 248, + "name": "microsite", + "displayName": "Microsite" + }, + "name": "test_microsite", + "createdDate": "2025-03-25T03:01:05.467-06:00", + "createdBy": { + "id": 710420418, + "email": "joern.berkefeld@accenture.com", + "name": "Jörn Berkefeld", + "userId": "710420418" + }, + "modifiedDate": "2025-03-25T03:12:51.85-06:00", + "modifiedBy": { + "id": 710420418, + "email": "joern.berkefeld@accenture.com", + "name": "Jörn Berkefeld", + "userId": "710420418" + }, + "status": { + "id": 1, + "name": "Draft" + }, + "category": { + "id": 27675, + "name": "mcdev", + "parentId": 23009 + }, + "content": "{\"url\":\"https://oss-test.accenture.com/test_microsite\"}", + "meta": { + "thumbnailRefAssetId": 9461, + "cloudPages": { + "publishDate": "2025-03-25 03:12:51.850" + } + }, + "availableViews": [], + "modelVersion": 2 + }, + { + "id": 9458, + "customerKey": "test_interactivecontent", + "assetType": { + "id": 249, + "name": "interactivecontent", + "displayName": "Interactive Email Page" + }, + "name": "test_interactivecontent", + "createdDate": "2025-03-25T03:02:46.823-06:00", + "createdBy": { + "id": 710420418, + "email": "joern.berkefeld@accenture.com", + "name": "Jörn Berkefeld", + "userId": "710420418" + }, + "modifiedDate": "2025-03-25T03:02:55.307-06:00", + "modifiedBy": { + "id": 710420418, + "email": "joern.berkefeld@accenture.com", + "name": "Jörn Berkefeld", + "userId": "710420418" + }, + "status": { + "id": 1, + "name": "Draft" + }, + "category": { + "id": 27675, + "name": "mcdev", + "parentId": 23009 + }, + "content": "{\"url\":\"https://oss-test.accenture.com/test_interactivecontent\"}", + "meta": { + "thumbnailRefAssetId": 9459, + "cloudPages": { + "publishDate": "2025-03-25 03:02:55.307" + } + }, + "availableViews": [], + "modelVersion": 2 + } + ] +} diff --git a/test/resources/9999999/asset/v1/content/assets/query/post-response-assetType.idIN3,195,196,197,198,199,200,201,202,203,210,211,212,213.json b/test/resources/9999999/asset/v1/content/assets/query/post-response-assetType.idIN3,195,196,197,198,199,200,201,202,203,210,211,212,213.json new file mode 100644 index 000000000..050f9c845 --- /dev/null +++ b/test/resources/9999999/asset/v1/content/assets/query/post-response-assetType.idIN3,195,196,197,198,199,200,201,202,203,210,211,212,213.json @@ -0,0 +1,160 @@ +{ + "count": 4, + "page": 1, + "pageSize": 50, + "links": {}, + "items": [ + { + "id": 1295064, + "customerKey": "testExisting_asset_htmlblock", + "assetType": { + "id": 197, + "name": "htmlblock", + "displayName": "HTML Block" + }, + "fileProperties": { + "fileName": "dont strip non ssjs content" + }, + "name": "dont strip non ssjs content", + "createdDate": "2024-01-08T08:26:58.277-06:00", + "createdBy": { + "id": 700301950, + "email": "joern.berkefeld@accenture.com", + "name": "Jörn Berkefeld (ASGR)", + "userId": "700301950" + }, + "modifiedDate": "2024-01-08T08:28:01.6-06:00", + "modifiedBy": { + "id": 700301950, + "email": "joern.berkefeld@accenture.com", + "name": "Jörn Berkefeld (ASGR)", + "userId": "700301950" + }, + "status": { + "id": 1, + "name": "Draft" + }, + "category": { + "id": 89397, + "name": "Content Builder", + "parentId": 0 + }, + "availableViews": [], + "modelVersion": 2 + }, + { + "id": 1295065, + "customerKey": "testExisting_htmlblock1", + "assetType": { + "id": 197, + "name": "htmlblock", + "displayName": "HTML Block" + }, + "fileProperties": { + "fileName": "testExisting_htmlblock1" + }, + "name": "testExisting_htmlblock1", + "createdDate": "2024-01-08T08:26:58.277-06:00", + "createdBy": { + "id": 700301950, + "email": "joern.berkefeld@accenture.com", + "name": "Jörn Berkefeld (ASGR)", + "userId": "700301950" + }, + "modifiedDate": "2024-01-08T08:28:01.6-06:00", + "modifiedBy": { + "id": 700301950, + "email": "joern.berkefeld@accenture.com", + "name": "Jörn Berkefeld (ASGR)", + "userId": "700301950" + }, + "status": { + "id": 1, + "name": "Draft" + }, + "category": { + "id": 89397, + "name": "Content Builder", + "parentId": 0 + }, + "availableViews": [], + "modelVersion": 2 + }, + { + "id": 1295066, + "customerKey": "testExisting_htmlblock2", + "assetType": { + "id": 197, + "name": "htmlblock", + "displayName": "HTML Block" + }, + "fileProperties": { + "fileName": "testExisting_htmlblock2" + }, + "name": "testExisting_htmlblock2", + "createdDate": "2024-01-08T08:26:58.277-06:00", + "createdBy": { + "id": 700301950, + "email": "joern.berkefeld@accenture.com", + "name": "Jörn Berkefeld (ASGR)", + "userId": "700301950" + }, + "modifiedDate": "2024-01-08T08:28:01.6-06:00", + "modifiedBy": { + "id": 700301950, + "email": "joern.berkefeld@accenture.com", + "name": "Jörn Berkefeld (ASGR)", + "userId": "700301950" + }, + "status": { + "id": 1, + "name": "Draft" + }, + "category": { + "id": 89397, + "name": "Content Builder", + "parentId": 0 + }, + "availableViews": [], + "modelVersion": 2 + }, + { + "id": 1295067, + "customerKey": "testExisting_htmlblock 3 spaces", + "assetType": { + "id": 197, + "name": "htmlblock", + "displayName": "HTML Block" + }, + "fileProperties": { + "fileName": "testExisting_htmlblock 3 spaces" + }, + "name": "testExisting_htmlblock 3 spaces", + "createdDate": "2024-01-08T08:26:58.277-06:00", + "createdBy": { + "id": 700301950, + "email": "joern.berkefeld@accenture.com", + "name": "Jörn Berkefeld (ASGR)", + "userId": "700301950" + }, + "modifiedDate": "2024-01-08T08:28:01.6-06:00", + "modifiedBy": { + "id": 700301950, + "email": "joern.berkefeld@accenture.com", + "name": "Jörn Berkefeld (ASGR)", + "userId": "700301950" + }, + "status": { + "id": 1, + "name": "Draft" + }, + "category": { + "id": 89397, + "name": "Content Builder", + "parentId": 0 + }, + "availableViews": [], + "modelVersion": 2 + } + ] +} diff --git a/test/resources/9999999/asset/v1/content/assets/query/post-response-assetType.idIN4,214.json b/test/resources/9999999/asset/v1/content/assets/query/post-response-assetType.idIN4,214.json new file mode 100644 index 000000000..a7ac464db --- /dev/null +++ b/test/resources/9999999/asset/v1/content/assets/query/post-response-assetType.idIN4,214.json @@ -0,0 +1,35 @@ +{ + "count": 1, + "page": 1, + "pageSize": 50, + "links": {}, + "items": [ + { + "id": 5286, + "customerKey": "testExisting_asset_template", + "assetType": { + "id": 4, + "name": "template", + "displayName": "Template" + }, + "name": " testExisting_asset_template", + "createdDate": "2024-04-22T03:33:08.253-06:00", + "createdBy": { + "id": 710411605, + "email": "joern.berkefeld@accenture.com", + "name": "Jörn Berkefeld", + "userId": "710411605" + }, + "modifiedDate": "2024-05-13T07:12:13.117-06:00", + "modifiedBy": { + "id": 710420432, + "name": "joern.berkefeld app user", + "userId": "710420432" + }, + "category": { + "id": 89397 + }, + "modelVersion": 2 + } + ] +} diff --git a/test/resources/9999999/asset/v1/content/assets/query/post-response-assetType.idIN5,207,208,209.json b/test/resources/9999999/asset/v1/content/assets/query/post-response-assetType.idIN5,207,208,209.json new file mode 100644 index 000000000..8e91e9419 --- /dev/null +++ b/test/resources/9999999/asset/v1/content/assets/query/post-response-assetType.idIN5,207,208,209.json @@ -0,0 +1,108 @@ +{ + "count": 3, + "page": 1, + "pageSize": 50, + "links": {}, + "items": [ + { + "id": 808714, + "customerKey": "testExisting_asset_message", + "assetType": { "id": 208, "name": "htmlemail", "displayName": "HTML Email" }, + "name": "testExisting_asset_message", + "createdDate": "2021-01-31T14:11:01.423-06:00", + "createdBy": { + "id": 700304523, + "email": "", + "name": "SFMC DEVOPS app user", + "userId": "700304523" + }, + "modifiedDate": "2021-01-31T14:13:30-06:00", + "modifiedBy": { + "id": 700304523, + "name": "SFMC DEVOPS app user", + "userId": "700304523" + }, + "status": { "id": 1, "name": "Draft" }, + "category": { "id": 89397, "name": "Content Builder", "parentId": 0 }, + "availableViews": ["html", "text", "subjectline", "preheader"], + "data": { + "email": { + "options": { "characterEncoding": "us-ascii" }, + "legacy": { + "legacyId": 531213, + "legacyKey": "testExisting_asset_message", + "legacyType": "email", + "legacyCategoryId": 290835 + } + } + }, + "legacyData": { + "legacyId": 531213, + "legacyKey": "testExisting_asset_message", + "legacyType": "email", + "legacyCategoryId": 290835 + }, + "modelVersion": 2 + }, + { + "id": 5289, + "customerKey": "testExisting_asset_templatebasedemail", + "assetType": { + "id": 207, + "name": "templatebasedemail", + "displayName": "Template-Based Email" + }, + "name": " testExisting_asset_templatebasedemail", + "createdDate": "2024-04-22T06:36:03.117-06:00", + "createdBy": { + "id": 710369861, + "email": "joern.berkefeld@accenture.com", + "name": "Jörn Berkefeld", + "userId": "710369861" + }, + "modifiedDate": "2024-05-13T07:15:29.77-06:00", + "modifiedBy": { + "id": 710420432, + "name": "joern.berkefeld app user", + "userId": "710420432" + }, + "status": { + "id": 1, + "name": "Draft" + }, + "category": { + "id": 89397 + }, + "availableViews": [ + "subjectline", + "preheader", + "text", + "viewAsAWebPage", + "subscriptioncenter", + "forwardHTML", + "forwardText", + "html" + ], + "data": { + "email": { + "options": { + "characterEncoding": "utf-8" + }, + "legacy": { + "legacyId": 1643, + "legacyKey": "9b6edc22-d19a-429a-a705-da88c3a16543", + "legacyType": "email", + "legacyCategoryId": 10251 + } + } + }, + "legacyData": { + "legacyId": 1643, + "legacyKey": "9b6edc22-d19a-429a-a705-da88c3a16543", + "legacyType": "email", + "legacyCategoryId": 10251 + }, + "modelVersion": 2 + } + ] +} diff --git a/test/resources/9999999/asset/v1/content/assets/query/post-response-customerKey=testExisting_asset_htmlblock.json b/test/resources/9999999/asset/v1/content/assets/query/post-response-customerKey=testExisting_asset_htmlblock.json new file mode 100644 index 000000000..4287fce79 --- /dev/null +++ b/test/resources/9999999/asset/v1/content/assets/query/post-response-customerKey=testExisting_asset_htmlblock.json @@ -0,0 +1,46 @@ +{ + "count": 3, + "page": 1, + "pageSize": 50, + "links": {}, + "items": [ + { + "id": 1295064, + "customerKey": "testExisting_asset_htmlblock", + "assetType": { + "id": 197, + "name": "htmlblock", + "displayName": "HTML Block" + }, + "fileProperties": { + "fileName": "dont strip non ssjs content" + }, + "name": "dont strip non ssjs content", + "createdDate": "2024-01-08T08:26:58.277-06:00", + "createdBy": { + "id": 700301950, + "email": "joern.berkefeld@accenture.com", + "name": "Jörn Berkefeld (ASGR)", + "userId": "700301950" + }, + "modifiedDate": "2024-01-08T08:28:01.6-06:00", + "modifiedBy": { + "id": 700301950, + "email": "joern.berkefeld@accenture.com", + "name": "Jörn Berkefeld (ASGR)", + "userId": "700301950" + }, + "status": { + "id": 1, + "name": "Draft" + }, + "category": { + "id": 89397, + "name": "Content Builder", + "parentId": 0 + }, + "availableViews": [], + "modelVersion": 2 + } + ] +} diff --git a/test/resources/9999999/asset/v1/content/categories/post-response.json b/test/resources/9999999/asset/v1/content/categories/post-response.json new file mode 100644 index 000000000..b26107950 --- /dev/null +++ b/test/resources/9999999/asset/v1/content/categories/post-response.json @@ -0,0 +1,9 @@ +{ + "id": 38491, + "description": "", + "enterpriseId": 1111111, + "memberId": 9999999, + "name": "bla/blub", + "parentId": 89397, + "categoryType": "asset" +} diff --git a/test/resources/9999999/attributeGroup/retrieve-expected.json b/test/resources/9999999/attributeGroup/retrieve-expected.json new file mode 100644 index 000000000..54b34dfc1 --- /dev/null +++ b/test/resources/9999999/attributeGroup/retrieve-expected.json @@ -0,0 +1,25 @@ +{ + "applicationKey": "com.exacttarget.mobileconnect", + "attributeCount": 37, + "attributeGroupIconKey": "Mobile", + "attributeGroupType": "Standard", + "r__attributeSet_key": ["MobileDemographics", "MobileSubscriptions"], + "canAddProperties": false, + "canAddRelationships": true, + "canChangeProperties": false, + "canModify": false, + "canRemove": false, + "definitionKey": "ETMobileConnect", + "definitionName": { + "value": "MobileConnect Data" + }, + "description": "", + "displayOrder": 4, + "isHidden": false, + "isOwner": true, + "isSystemDefined": true, + "requiredRelationships": [ + "4651de3f-31e2-e611-80cc-1402ec7222b4", + "4352de3f-31e2-e611-80cc-1402ec7222b4" + ] +} diff --git a/test/resources/9999999/attributeSet/retrieve-expected.json b/test/resources/9999999/attributeSet/retrieve-expected.json new file mode 100644 index 000000000..74ed7681d --- /dev/null +++ b/test/resources/9999999/attributeSet/retrieve-expected.json @@ -0,0 +1,143 @@ +{ + "attributeCount": 0, + "canAddValues": true, + "canChangeValues": true, + "canModify": true, + "canRemove": true, + "createDate": "2023-08-11T08:22:00", + "createdBy": 700301950, + "dataRetentionProperties": { + "isDeleteAtEndOfRetentionPeriod": false, + "isResetRetentionPeriodOnImport": false, + "isRowBasedRetention": true, + "periodLength": 6, + "periodUnitOfMeasure": 5 + }, + "definitionKey": "testExisting_dataExtensionShared", + "isCustomObjectBacked": true, + "isEvent": false, + "isHidden": false, + "isReadOnly": false, + "isRoot": false, + "isSendable": true, + "isShared": true, + "isSystemDefined": false, + "isTestaable": true, + "localizedDescription": { + "value": "Container for my test emails" + }, + "name": "testExisting_dataExtensionShared", + "parentID": "00000000-0000-0000-0000-000000000000", + "r__dataExtension_key": "testExisting_dataExtensionShared", + "r__folder_Path": "Shared Items/Shared Data Extensions", + "relationshipCount": 1, + "relationships": [ + { + "canModify": true, + "canRemove": true, + "isGroupToSetRelationship": true, + "isHidden": false, + "isSystemDefined": false, + "leftItem": { + "cardinality": "One", + "r__attributeGroup_key": "testExisting_attributeGroup", + "relationshipType": "AttributeGroup" + }, + "leftRelationshipIDs": [ + { + "type": "int16", + "value": "3" + } + ], + "leftRelationshipReferenceType": "CustomerData", + "relationshipAttributes": [ + { + "c__leftFullyQualifiedName": "Contact.Contact Key", + "c__rightFullyQualifiedName": "testExisting_dataExtensionShared.ContactKey" + } + ], + "relationshipID": "598b787a-5238-ee11-b85a-48df37d1de8a", + "rightItem": { + "cardinality": "One", + "r__attributeSet_key": "testExisting_dataExtensionShared", + "relationshipType": "AttributeSet" + } + } + ], + "sendAttributeStorageName": "ContactKey", + "sendContactKeyStorageName": "_SubscriberKey", + "setDefinitionKey": "testExisting_dataExtensionShared", + "storageLogicalType": "DataExtension", + "storageObjectIDs": ["5b8b787a-5238-ee11-b85a-48df37d1de8a"], + "valueDefinitions": [ + { + "dataType": "LongNumber", + "definitionKey": "CustomObjectKey", + "description": "", + "isHidden": true, + "isIdentityValue": true, + "isNullable": false, + "isPrimaryKey": false, + "isReadOnly": true, + "isSystemDefined": true, + "isUpdateable": true, + "name": "Custom Object Key" + }, + { + "dataType": "Text", + "definitionKey": "FirstName", + "description": "", + "isHidden": false, + "isIdentityValue": false, + "isNullable": true, + "isPrimaryKey": false, + "isReadOnly": false, + "isSystemDefined": false, + "isUpdateable": true, + "length": 50, + "name": "FirstName" + }, + { + "dataType": "Text", + "definitionKey": "LastName", + "description": "", + "isHidden": false, + "isIdentityValue": false, + "isNullable": true, + "isPrimaryKey": false, + "isReadOnly": false, + "isSystemDefined": false, + "isUpdateable": true, + "length": 55, + "name": "LastName" + }, + { + "dataType": "EmailAddress", + "definitionKey": "EmailAddress", + "description": "", + "isHidden": false, + "isIdentityValue": false, + "isNullable": false, + "isPrimaryKey": false, + "isReadOnly": false, + "isSystemDefined": false, + "isUpdateable": true, + "length": 254, + "name": "EmailAddress" + }, + { + "dataType": "Text", + "definitionKey": "ContactKey", + "description": "", + "isHidden": false, + "isIdentityValue": false, + "isNullable": false, + "isPrimaryKey": true, + "isReadOnly": false, + "isSystemDefined": false, + "isUpdateable": true, + "length": 50, + "name": "ContactKey" + } + ] +} diff --git a/test/resources/9999999/automation/build-expected.json b/test/resources/9999999/automation/build-expected.json new file mode 100644 index 000000000..0400aeb6c --- /dev/null +++ b/test/resources/9999999/automation/build-expected.json @@ -0,0 +1,61 @@ +{ + "description": "foobar", + "key": "testTemplated_automation", + "name": "testTemplated_automation", + "r__folder_Path": "my automations", + "schedule": { + "endDate": "2022-07-30T00:00:00", + "icalRecur": "FREQ=DAILY;COUNT=1;INTERVAL=1", + "startDate": "2022-07-30T00:00:00", + "timezoneName": "W. Europe Standard Time" + }, + "status": "PausedSchedule", + "steps": [ + { + "activities": [ + { + "r__key": "testTemplated_dataExtract", + "r__type": "dataExtract" + }, + { + "r__key": "testTemplated_emailSend", + "r__type": "emailSend" + }, + { + "r__key": "testTemplated_fileTransfer", + "r__type": "fileTransfer" + }, + { + "r__key": "testTemplated_importFile", + "r__type": "importFile" + }, + { + "r__key": "testTemplated_query", + "r__type": "query" + }, + { + "r__key": "testTemplated_script", + "r__type": "script" + }, + { + "r__key": "testTemplated_automation__s1.7", + "r__type": "verification" + } + ], + "name": "" + } + ], + "type": "scheduled", + "notifications": [ + { + "email": ["complete@test.accenture.com"], + "message": "", + "type": "Complete" + }, + { + "email": ["error@test.accenture.com"], + "message": "test", + "type": "Error" + } + ] +} diff --git a/test/resources/9999999/automation/clone-expected.json b/test/resources/9999999/automation/clone-expected.json new file mode 100644 index 000000000..064fdcc09 --- /dev/null +++ b/test/resources/9999999/automation/clone-expected.json @@ -0,0 +1,61 @@ +{ + "description": "bla bla", + "key": "testExisting_automation", + "name": "testExisting_automation", + "r__folder_Path": "my automations", + "schedule": { + "endDate": "2022-07-30T00:00:00", + "icalRecur": "FREQ=DAILY;COUNT=1;INTERVAL=1", + "startDate": "2022-07-30T00:00:00", + "timezoneName": "W. Europe Standard Time" + }, + "status": "PausedSchedule", + "steps": [ + { + "activities": [ + { + "r__key": "testExisting_dataExtract", + "r__type": "dataExtract" + }, + { + "r__key": "testExisting_emailSend", + "r__type": "emailSend" + }, + { + "r__key": "testExisting_fileTransfer", + "r__type": "fileTransfer" + }, + { + "r__key": "testExisting_importFile", + "r__type": "importFile" + }, + { + "r__key": "testExisting_query", + "r__type": "query" + }, + { + "r__key": "testExisting_script", + "r__type": "script" + }, + { + "r__key": "testExisting_automation__s1.7", + "r__type": "verification" + } + ], + "name": "" + } + ], + "type": "scheduled", + "notifications": [ + { + "email": ["complete@test.accenture.com"], + "message": "", + "type": "Complete" + }, + { + "email": ["error@test.accenture.com"], + "message": "test", + "type": "Error" + } + ] +} diff --git a/test/resources/9999999/automation/create-callout-expected.json b/test/resources/9999999/automation/create-callout-expected.json new file mode 100644 index 000000000..13f11e3a5 --- /dev/null +++ b/test/resources/9999999/automation/create-callout-expected.json @@ -0,0 +1,66 @@ +{ + "description": "created on deploy", + "key": "testNew_automation", + "name": "testNew_automation", + "status": "Scheduled", + "steps": [ + { + "activities": [ + { + "displayOrder": 1, + "activityObjectId": "56c5370a-f988-4f36-b0ee-0f876573f6d7", + "name": "testExisting_dataExtract", + "objectTypeId": 73 + }, + { + "displayOrder": 2, + "activityObjectId": "9b1c7bf9-4964-ed11-b849-48df37d1de8b", + "name": "testExisting_emailSend", + "objectTypeId": 42 + }, + { + "displayOrder": 3, + "activityObjectId": "72c328ac-f5b0-4e37-91d3-a775666f15a6", + "name": "testExisting_fileTransfer", + "objectTypeId": 53 + }, + { + "displayOrder": 4, + "activityObjectId": "9d16f42c-2260-ed11-b849-48df37d1de8b", + "name": "testExisting_importFile", + "objectTypeId": 43 + }, + { + "displayOrder": 5, + "activityObjectId": "549f0568-607c-4940-afef-437965094dat", + "name": "testExisting_query", + "objectTypeId": 300 + }, + { + "displayOrder": 6, + "activityObjectId": "39f6a488-20eb-4ba0-b0b9-023725b574e4", + "name": "testExisting_script", + "objectTypeId": 423 + }, + { + "displayOrder": 7, + "activityObjectId": "testNew_RANDOM_NEW_GUID", + "name": "testNew_automation__s1.7", + "objectTypeId": 1000 + } + ], + "annotation": "", + "stepNumber": 0 + } + ], + "categoryId": 290937, + "startSource": { + "schedule": { + "startDate": "2020-05-14T02:30:32.11", + "endDate": "2079-06-06T21:00:00", + "icalRecur": "FREQ=MINUTELY;UNTIL=20790607T050000;INTERVAL=5", + "timezoneId": 5 + }, + "typeId": 1 + } +} diff --git a/test/resources/9999999/automation/create-expected.json b/test/resources/9999999/automation/create-expected.json new file mode 100644 index 000000000..c6d42d801 --- /dev/null +++ b/test/resources/9999999/automation/create-expected.json @@ -0,0 +1,50 @@ +{ + "description": "created on deploy", + "key": "testNew_automation", + "name": "testNew_automation", + "r__folder_Path": "my automations", + "type": "scheduled", + "status": "PausedSchedule", + "schedule": { + "endDate": "2079-06-06T21:00:00-06:00", + "icalRecur": "FREQ=MINUTELY;UNTIL=20790607T050000;INTERVAL=5", + "startDate": "2020-05-13T18:30:32.11-06:00", + "timezoneName": "W. Europe Standard Time" + }, + "steps": [ + { + "activities": [ + { + "r__key": "testExisting_dataExtract", + "r__type": "dataExtract" + }, + { + "r__key": "testExisting_emailSend", + "r__type": "emailSend" + }, + { + "r__key": "testExisting_fileTransfer", + "r__type": "fileTransfer" + }, + { + "r__key": "testExisting_importFile", + "r__type": "importFile" + }, + { + "r__key": "testExisting_query", + "r__type": "query" + }, + { + "r__key": "testExisting_script", + "r__type": "script" + }, + { + "r__key": "testNew_automation__s1.7", + "r__type": "verification" + } + ], + "name": "" + } + ], + "createdDate": "2023-07-04T07:49:08.297" +} diff --git a/test/resources/9999999/automation/create-testNew_automation-expected.md b/test/resources/9999999/automation/create-testNew_automation-expected.md new file mode 100644 index 000000000..b9a9dc311 --- /dev/null +++ b/test/resources/9999999/automation/create-testNew_automation-expected.md @@ -0,0 +1,29 @@ +## testNew_automation + +**Description:** created on deploy + +**Folder:** my automations/ + +**Started by:** Schedule + +**Status:** PausedSchedule + +**Schedule:** + +* Start: 2020-05-13 18:30:32.11-06:00 +01:00 +* End: 2079-06-06 21:00:00-06:00 +01:00 +* Timezone: W. Europe Standard Time +* Recurrence: every 5 minutes until end date + +**Notifications:** _none_ + + +| Step 1<br>_<small>-</small>_ | +| --- | +| _1.1: dataExtract_<br>testExisting_dataExtract | +| _1.2: emailSend_<br>testExisting_emailSend | +| _1.3: fileTransfer_<br>testExisting_fileTransfer | +| _1.4: importFile_<br>testExisting_importFile | +| _1.5: query_<br>testExisting_query | +| _1.6: script_<br>testExisting_script | +| _1.7: verification_<br>testNew_automation__s1.7 | diff --git a/test/resources/9999999/automation/delete-response.xml b/test/resources/9999999/automation/delete-response.xml new file mode 100644 index 000000000..54cce0ebc --- /dev/null +++ b/test/resources/9999999/automation/delete-response.xml @@ -0,0 +1,40 @@ +<?xml version="1.0" encoding="utf-8"?> +<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:xsd="http://www.w3.org/2001/XMLSchema" + xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing" + xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" + xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"> + <soap:Header> + <wsa:Action>DeleteResponse</wsa:Action> + <wsa:MessageID>urn:uuid:cc45bb83-15a3-4a82-ba48-47ac4fb13000</wsa:MessageID> + <wsa:RelatesTo>urn:uuid:29986848-a0c3-4f3b-bf5a-91151f784449</wsa:RelatesTo> + <wsa:To>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</wsa:To> + <wsse:Security> + <wsu:Timestamp wsu:Id="Timestamp-4e8dad58-7a68-4653-8406-a172d1960c8a"> + <wsu:Created>2023-06-02T13:41:30Z</wsu:Created> + <wsu:Expires>2023-06-02T13:46:30Z</wsu:Expires> + </wsu:Timestamp> + </wsse:Security> + </soap:Header> + <soap:Body> + <DeleteResponse xmlns="http://exacttarget.com/wsdl/partnerAPI"> + <Results> + <StatusCode>OK</StatusCode> + <StatusMessage>Program deleted</StatusMessage> + <OrdinalID>0</OrdinalID> + <Object xsi:type="Automation"> + <PartnerKey xsi:nil="true" /> + <ObjectID>08afb0e2-b00a-4c88-ad2e-1f7f8788c560</ObjectID> + <CustomerKey>testExisting_automation</CustomerKey> + <IsPlatformObject>false</IsPlatformObject> + <Name /> + <Description /> + <IsActive>true</IsActive> + </Object> + </Results> + <RequestID>898702fc-a432-4176-8130-5d6dd5ad9ca6</RequestID> + <OverallStatus>OK</OverallStatus> + </DeleteResponse> + </soap:Body> +</soap:Envelope> \ No newline at end of file diff --git a/test/resources/9999999/automation/patch_fixKeys-pause-expected.json b/test/resources/9999999/automation/patch_fixKeys-pause-expected.json new file mode 100644 index 000000000..5c4da0379 --- /dev/null +++ b/test/resources/9999999/automation/patch_fixKeys-pause-expected.json @@ -0,0 +1,44 @@ +{ + "description": "testing fixKey on an a paused automation", + "key": "testExisting_automation_fixedKey_paused", + "name": "testExisting_automation_fixedKey_paused", + "r__folder_Path": "my automations", + "schedule": { + "endDate": "2022-07-30T00:00:00", + "icalRecur": "FREQ=DAILY;COUNT=1;INTERVAL=1", + "startDate": "2022-07-30T00:00:00", + "timezoneName": "W. Europe Standard Time" + }, + "status": "PausedSchedule", + "steps": [ + { + "activities": [ + { + "r__key": "testExisting_dataExtract", + "r__type": "dataExtract" + }, + { + "r__key": "testExisting_emailSend", + "r__type": "emailSend" + }, + { + "r__key": "testExisting_fileTransfer", + "r__type": "fileTransfer" + }, + { + "r__key": "testExisting_importFile", + "r__type": "importFile" + }, + { + "r__key": "testExisting_query", + "r__type": "query" + }, + { + "r__key": "testExisting_script", + "r__type": "script" + } + ] + } + ], + "type": "scheduled" +} diff --git a/test/resources/9999999/automation/patch_fixKeys-schedule-expected.json b/test/resources/9999999/automation/patch_fixKeys-schedule-expected.json new file mode 100644 index 000000000..e0c47993c --- /dev/null +++ b/test/resources/9999999/automation/patch_fixKeys-schedule-expected.json @@ -0,0 +1,44 @@ +{ + "description": "testing fixKey on an a scheduled automation", + "key": "testExisting_automation_fixedKey_scheduled", + "name": "testExisting_automation_fixedKey_scheduled", + "r__folder_Path": "my automations", + "schedule": { + "endDate": "2022-07-30T00:00:00", + "icalRecur": "FREQ=DAILY;COUNT=1;INTERVAL=1", + "startDate": "2022-07-30T00:00:00", + "timezoneName": "W. Europe Standard Time" + }, + "status": "Scheduled", + "steps": [ + { + "activities": [ + { + "r__key": "testExisting_dataExtract", + "r__type": "dataExtract" + }, + { + "r__key": "testExisting_emailSend", + "r__type": "emailSend" + }, + { + "r__key": "testExisting_fileTransfer", + "r__type": "fileTransfer" + }, + { + "r__key": "testExisting_importFile", + "r__type": "importFile" + }, + { + "r__key": "testExisting_query", + "r__type": "query" + }, + { + "r__key": "testExisting_script", + "r__type": "script" + } + ] + } + ], + "type": "scheduled" +} diff --git a/test/resources/9999999/automation/perform-08afb0e2-b00a-4c88-ad2e-1f7f8788c560-response.xml b/test/resources/9999999/automation/perform-08afb0e2-b00a-4c88-ad2e-1f7f8788c560-response.xml new file mode 100644 index 000000000..83ef8a75d --- /dev/null +++ b/test/resources/9999999/automation/perform-08afb0e2-b00a-4c88-ad2e-1f7f8788c560-response.xml @@ -0,0 +1,42 @@ +<?xml version="1.0" encoding="utf-8"?> +<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:xsd="http://www.w3.org/2001/XMLSchema" + xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing" + xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" + xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"> + <soap:Header> + <wsa:Action>PerformResponse</wsa:Action> + <wsa:MessageID>urn:uuid:cc45bb83-15a3-4a82-ba48-47ac4fb13000</wsa:MessageID> + <wsa:RelatesTo>urn:uuid:29986848-a0c3-4f3b-bf5a-91151f784449</wsa:RelatesTo> + <wsa:To>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</wsa:To> + <wsse:Security> + <wsu:Timestamp wsu:Id="Timestamp-4e8dad58-7a68-4653-8406-a172d1960c8a"> + <wsu:Created>2023-06-02T13:41:30Z</wsu:Created> + <wsu:Expires>2023-06-02T13:46:30Z</wsu:Expires> + </wsu:Timestamp> + </wsse:Security> + </soap:Header> + <soap:Body> + <PerformResponseMsg xmlns="http://exacttarget.com/wsdl/partnerAPI"> + <Results> + <Result> + <StatusCode>OK</StatusCode> + <StatusMessage>Performed Activity</StatusMessage> + <Object xsi:type="Automation"> + <PartnerKey xsi:nil="true" /> + <ObjectID>08afb0e2-b00a-4c88-ad2e-1f7f8788c560</ObjectID> + <CustomerKey>testExisting_automation</CustomerKey> + <IsPlatformObject>false</IsPlatformObject> + <Name /> + <Description /> + <IsActive>true</IsActive> + </Object> + </Result> + </Results> + <OverallStatus>OK</OverallStatus> + <OverallStatusMessage /> + <RequestID>898702fc-a432-4176-8130-5d6dd5ad9ca6</RequestID> + </PerformResponseMsg> + </soap:Body> +</soap:Envelope> diff --git a/test/resources/9999999/automation/perform-08afb0e2-b00a-4c88-fixKey_pause-response.xml b/test/resources/9999999/automation/perform-08afb0e2-b00a-4c88-fixKey_pause-response.xml new file mode 100644 index 000000000..d301c7cee --- /dev/null +++ b/test/resources/9999999/automation/perform-08afb0e2-b00a-4c88-fixKey_pause-response.xml @@ -0,0 +1,42 @@ +<?xml version="1.0" encoding="utf-8"?> +<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:xsd="http://www.w3.org/2001/XMLSchema" + xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing" + xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" + xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"> + <soap:Header> + <wsa:Action>PerformResponse</wsa:Action> + <wsa:MessageID>urn:uuid:cc45bb83-15a3-4a82-ba48-47ac4fb13000</wsa:MessageID> + <wsa:RelatesTo>urn:uuid:29986848-a0c3-4f3b-bf5a-91151f784449</wsa:RelatesTo> + <wsa:To>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</wsa:To> + <wsse:Security> + <wsu:Timestamp wsu:Id="Timestamp-4e8dad58-7a68-4653-8406-a172d1960c8a"> + <wsu:Created>2023-06-02T13:41:30Z</wsu:Created> + <wsu:Expires>2023-06-02T13:46:30Z</wsu:Expires> + </wsu:Timestamp> + </wsse:Security> + </soap:Header> + <soap:Body> + <PerformResponseMsg xmlns="http://exacttarget.com/wsdl/partnerAPI"> + <Results> + <Result> + <StatusCode>OK</StatusCode> + <StatusMessage>Performed Activity</StatusMessage> + <Object xsi:type="Automation"> + <PartnerKey xsi:nil="true" /> + <ObjectID>08afb0e2-b00a-4c88-fixKey_pause</ObjectID> + <CustomerKey>testExisting_automation_fixedKey_paused</CustomerKey> + <IsPlatformObject>false</IsPlatformObject> + <Name /> + <Description /> + <IsActive>true</IsActive> + </Object> + </Result> + </Results> + <OverallStatus>OK</OverallStatus> + <OverallStatusMessage /> + <RequestID>898702fc-a432-4176-8130-5d6dd5ad9ca6</RequestID> + </PerformResponseMsg> + </soap:Body> +</soap:Envelope> diff --git a/test/resources/9999999/automation/perform-08afb0e2-b00a-4c88-fixKey_schedule-response.xml b/test/resources/9999999/automation/perform-08afb0e2-b00a-4c88-fixKey_schedule-response.xml new file mode 100644 index 000000000..c1c9e7685 --- /dev/null +++ b/test/resources/9999999/automation/perform-08afb0e2-b00a-4c88-fixKey_schedule-response.xml @@ -0,0 +1,42 @@ +<?xml version="1.0" encoding="utf-8"?> +<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:xsd="http://www.w3.org/2001/XMLSchema" + xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing" + xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" + xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"> + <soap:Header> + <wsa:Action>PerformResponse</wsa:Action> + <wsa:MessageID>urn:uuid:cc45bb83-15a3-4a82-ba48-47ac4fb13000</wsa:MessageID> + <wsa:RelatesTo>urn:uuid:29986848-a0c3-4f3b-bf5a-91151f784449</wsa:RelatesTo> + <wsa:To>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</wsa:To> + <wsse:Security> + <wsu:Timestamp wsu:Id="Timestamp-4e8dad58-7a68-4653-8406-a172d1960c8a"> + <wsu:Created>2023-06-02T13:41:30Z</wsu:Created> + <wsu:Expires>2023-06-02T13:46:30Z</wsu:Expires> + </wsu:Timestamp> + </wsse:Security> + </soap:Header> + <soap:Body> + <PerformResponseMsg xmlns="http://exacttarget.com/wsdl/partnerAPI"> + <Results> + <Result> + <StatusCode>OK</StatusCode> + <StatusMessage>Performed Activity</StatusMessage> + <Object xsi:type="Automation"> + <PartnerKey xsi:nil="true" /> + <ObjectID>08afb0e2-b00a-4c88-fixKey_schedule</ObjectID> + <CustomerKey>testExisting_automation_fixedKey_scheduled</CustomerKey> + <IsPlatformObject>false</IsPlatformObject> + <Name /> + <Description /> + <IsActive>true</IsActive> + </Object> + </Result> + </Results> + <OverallStatus>OK</OverallStatus> + <OverallStatusMessage /> + <RequestID>898702fc-a432-4176-8130-5d6dd5ad9ca6</RequestID> + </PerformResponseMsg> + </soap:Body> +</soap:Envelope> diff --git a/test/resources/9999999/automation/perform-a8afb0e2-b00a-4c88-ad2e-1f7f8788c560-response.xml b/test/resources/9999999/automation/perform-a8afb0e2-b00a-4c88-ad2e-1f7f8788c560-response.xml new file mode 100644 index 000000000..597d3e3a8 --- /dev/null +++ b/test/resources/9999999/automation/perform-a8afb0e2-b00a-4c88-ad2e-1f7f8788c560-response.xml @@ -0,0 +1,42 @@ +<?xml version="1.0" encoding="utf-8"?> +<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:xsd="http://www.w3.org/2001/XMLSchema" + xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing" + xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" + xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"> + <soap:Header> + <wsa:Action>PerformResponse</wsa:Action> + <wsa:MessageID>urn:uuid:cc45bb83-15a3-4a82-ba48-47ac4fb13000</wsa:MessageID> + <wsa:RelatesTo>urn:uuid:29986848-a0c3-4f3b-bf5a-91151f784449</wsa:RelatesTo> + <wsa:To>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</wsa:To> + <wsse:Security> + <wsu:Timestamp wsu:Id="Timestamp-4e8dad58-7a68-4653-8406-a172d1960c8a"> + <wsu:Created>2023-06-02T13:41:30Z</wsu:Created> + <wsu:Expires>2023-06-02T13:46:30Z</wsu:Expires> + </wsu:Timestamp> + </wsse:Security> + </soap:Header> + <soap:Body> + <PerformResponseMsg xmlns="http://exacttarget.com/wsdl/partnerAPI"> + <Results> + <Result> + <StatusCode>OK</StatusCode> + <StatusMessage>Performed Activity</StatusMessage> + <Object xsi:type="Automation"> + <PartnerKey xsi:nil="true" /> + <ObjectID>a8afb0e2-b00a-4c88-ad2e-1f7f8788c560</ObjectID> + <CustomerKey>testNew_automation</CustomerKey> + <IsPlatformObject>false</IsPlatformObject> + <Name /> + <Description /> + <IsActive>true</IsActive> + </Object> + </Result> + </Results> + <OverallStatus>OK</OverallStatus> + <OverallStatusMessage /> + <RequestID>898702fc-a432-4176-8130-5d6dd5ad9ca6</RequestID> + </PerformResponseMsg> + </soap:Body> +</soap:Envelope> diff --git a/test/resources/9999999/automation/retrieve-expected.json b/test/resources/9999999/automation/retrieve-expected.json new file mode 100644 index 000000000..45283aaed --- /dev/null +++ b/test/resources/9999999/automation/retrieve-expected.json @@ -0,0 +1,67 @@ +{ + "description": "bla bla", + "key": "testExisting_automation", + "name": "testExisting_automation", + "r__folder_Path": "my automations", + "schedule": { + "endDate": "2022-07-30T00:00:00", + "icalRecur": "FREQ=DAILY;COUNT=1;INTERVAL=1", + "startDate": "2022-07-30T00:00:00", + "timezoneName": "W. Europe Standard Time" + }, + "status": "PausedSchedule", + "steps": [ + { + "activities": [ + { + "r__key": "testExisting_dataExtract", + "r__type": "dataExtract" + }, + { + "r__key": "testExisting_emailSend", + "r__type": "emailSend" + }, + { + "r__key": "testExisting_fileTransfer", + "r__type": "fileTransfer" + }, + { + "r__key": "testExisting_importFile", + "r__type": "importFile" + }, + { + "r__key": "testExisting_query", + "r__type": "query" + }, + { + "r__key": "testExisting_script", + "r__type": "script" + }, + { + "r__key": "testExisting_automation__s1.7", + "r__type": "verification" + } + ], + "name": "" + } + ], + "type": "scheduled", + "notifications": [ + { + "email": ["complete@test.accenture.com"], + "message": "", + "type": "Complete" + }, + { + "email": ["error@test.accenture.com"], + "message": "test", + "type": "Error" + } + ], + "createdDate": "2022-01-12T08:41:35.773Z", + "createdName": "Tom Tester", + "modifiedDate": "2024-11-04T17:42:13.143Z", + "modifiedName": "Jörn Berkefeld", + "pausedDate": "2025-03-14T15:21:57.62Z", + "pausedName": "Jörn Berkefeld" +} diff --git a/test/resources/9999999/automation/retrieve-testExisting_automation-expected.md b/test/resources/9999999/automation/retrieve-testExisting_automation-expected.md new file mode 100644 index 000000000..697134df1 --- /dev/null +++ b/test/resources/9999999/automation/retrieve-testExisting_automation-expected.md @@ -0,0 +1,31 @@ +## testExisting_automation + +**Description:** bla bla + +**Folder:** my automations/ + +**Started by:** Schedule + +**Status:** PausedSchedule + +**Schedule:** + +* Start: 2022-07-30 00:00:00 +01:00 +* End: 2022-07-30 00:00:00 +01:00 +* Timezone: W. Europe Standard Time +* Recurrence: run only once + +**Notifications:** + +* Complete: complete@test.accenture.com +* Error: error@test.accenture.com ("test") + +| Step 1<br>_<small>-</small>_ | +| --- | +| _1.1: dataExtract_<br>testExisting_dataExtract | +| _1.2: emailSend_<br>testExisting_emailSend | +| _1.3: fileTransfer_<br>testExisting_fileTransfer | +| _1.4: importFile_<br>testExisting_importFile | +| _1.5: query_<br>testExisting_query | +| _1.6: script_<br>testExisting_script | +| _1.7: verification_<br>testExisting_automation__s1.7 | diff --git a/test/resources/9999999/automation/retrieve-wait-expected.json b/test/resources/9999999/automation/retrieve-wait-expected.json new file mode 100644 index 000000000..74690557b --- /dev/null +++ b/test/resources/9999999/automation/retrieve-wait-expected.json @@ -0,0 +1,81 @@ +{ + "name": "testExisting_automation_wait", + "description": "", + "key": "testExisting_automation_wait", + "type": "unspecified", + "status": "Ready", + "schedule": {}, + "steps": [ + { + "name": "", + "activities": [ + { + "name": "1 Years", + "r__type": "wait" + } + ] + }, + { + "name": "", + "activities": [ + { + "name": "1 Months", + "r__type": "wait" + } + ] + }, + { + "name": "", + "activities": [ + { + "name": "1 Weeks", + "r__type": "wait" + } + ] + }, + { + "name": "", + "activities": [ + { + "name": "1 Days", + "r__type": "wait" + } + ] + }, + { + "name": "", + "activities": [ + { + "name": "1 Hours", + "r__type": "wait" + } + ] + }, + { + "name": "", + "activities": [ + { + "name": "1 Minutes", + "r__type": "wait" + } + ] + }, + { + "name": "", + "activities": [ + { + "name": "15:00", + "timeZone": "GMT Standard Time", + "r__type": "wait" + } + ] + } + ], + "r__folder_Path": "my automations", + "createdDate": "2024-11-04T17:30:12.973Z", + "createdName": "Jörn Berkefeld", + "modifiedDate": "2024-11-04T17:42:13.143Z", + "modifiedName": "Jörn Berkefeld", + "pausedDate": "2025-03-14T15:21:57.62Z", + "pausedName": "Jörn Berkefeld" +} diff --git a/test/resources/9999999/automation/retrieve-wait-expected.md b/test/resources/9999999/automation/retrieve-wait-expected.md new file mode 100644 index 000000000..816df020f --- /dev/null +++ b/test/resources/9999999/automation/retrieve-wait-expected.md @@ -0,0 +1,18 @@ +## testExisting_automation_wait + +**Description:** n/a + +**Folder:** my automations/ + +**Started by:** Not defined + +**Status:** Ready + +**Schedule:** Not defined + +**Notifications:** _none_ + + +| Step 1<br>_<small>-</small>_ | Step 2<br>_<small>-</small>_ | Step 3<br>_<small>-</small>_ | Step 4<br>_<small>-</small>_ | Step 5<br>_<small>-</small>_ | Step 6<br>_<small>-</small>_ | Step 7<br>_<small>-</small>_ | +| --- | --- | --- | --- | --- | --- | --- | +| _1.1: wait_<br>1 Years | _2.1: wait_<br>1 Months | _3.1: wait_<br>1 Weeks | _4.1: wait_<br>1 Days | _5.1: wait_<br>1 Hours | _6.1: wait_<br>1 Minutes | _7.1: wait_<br>15:00<br>GMT Standard Time | diff --git a/test/resources/9999999/automation/template-expected.json b/test/resources/9999999/automation/template-expected.json new file mode 100644 index 000000000..a12c48c23 --- /dev/null +++ b/test/resources/9999999/automation/template-expected.json @@ -0,0 +1,61 @@ +{ + "description": "{{{description}}}", + "key": "{{{prefix}}}automation", + "name": "{{{prefix}}}automation", + "r__folder_Path": "my automations", + "schedule": { + "endDate": "2022-07-30T00:00:00", + "icalRecur": "FREQ=DAILY;COUNT=1;INTERVAL=1", + "startDate": "2022-07-30T00:00:00", + "timezoneName": "W. Europe Standard Time" + }, + "status": "PausedSchedule", + "steps": [ + { + "activities": [ + { + "r__key": "{{{prefix}}}dataExtract", + "r__type": "dataExtract" + }, + { + "r__key": "{{{prefix}}}emailSend", + "r__type": "emailSend" + }, + { + "r__key": "{{{prefix}}}fileTransfer", + "r__type": "fileTransfer" + }, + { + "r__key": "{{{prefix}}}importFile", + "r__type": "importFile" + }, + { + "r__key": "{{{prefix}}}query", + "r__type": "query" + }, + { + "r__key": "{{{prefix}}}script", + "r__type": "script" + }, + { + "r__key": "{{{prefix}}}automation__s1.7", + "r__type": "verification" + } + ], + "name": "" + } + ], + "type": "scheduled", + "notifications": [ + { + "email": ["complete@test.accenture.com"], + "message": "", + "type": "Complete" + }, + { + "email": ["error@test.accenture.com"], + "message": "test", + "type": "Error" + } + ] +} diff --git a/test/resources/9999999/automation/update-callout-expected.json b/test/resources/9999999/automation/update-callout-expected.json new file mode 100644 index 000000000..0f4a1a957 --- /dev/null +++ b/test/resources/9999999/automation/update-callout-expected.json @@ -0,0 +1,68 @@ +{ + "description": "updated on deploy", + "key": "testExisting_automation", + "name": "testExisting_automation", + "status": "PausedSchedule", + "steps": [ + { + "activities": [ + { + "displayOrder": 1, + "activityObjectId": "56c5370a-f988-4f36-b0ee-0f876573f6d7", + "name": "testExisting_dataExtract", + "objectTypeId": 73 + }, + { + "displayOrder": 2, + "activityObjectId": "9b1c7bf9-4964-ed11-b849-48df37d1de8b", + "name": "testExisting_emailSend", + "objectTypeId": 42 + }, + { + "displayOrder": 3, + "activityObjectId": "72c328ac-f5b0-4e37-91d3-a775666f15a6", + "name": "testExisting_fileTransfer", + "objectTypeId": 53 + }, + { + "displayOrder": 4, + "activityObjectId": "9d16f42c-2260-ed11-b849-48df37d1de8b", + "name": "testExisting_importFile", + "objectTypeId": 43 + }, + { + "displayOrder": 5, + "activityObjectId": "549f0568-607c-4940-afef-437965094dat", + "name": "testExisting_query", + "objectTypeId": 300 + }, + { + "displayOrder": 6, + "activityObjectId": "39f6a488-20eb-4ba0-b0b9-023725b574e4", + "name": "testExisting_script", + "objectTypeId": 423 + } + ], + "annotation": "", + "stepNumber": 0 + } + ], + "notifications": [ + { + "email": ["error-updated@test.accenture.com"], + "message": "test updated", + "type": "Error" + } + ], + "categoryId": 290937, + "startSource": { + "schedule": { + "endDate": "2022-07-30T00:00:00", + "icalRecur": "FREQ=DAILY;COUNT=1;INTERVAL=1", + "startDate": "2022-07-30T00:00:00", + "timezoneId": 5 + }, + "typeId": 1 + }, + "id": "08afb0e2-b00a-4c88-ad2e-1f7f8788c560" +} diff --git a/test/resources/9999999/automation/update-expected.json b/test/resources/9999999/automation/update-expected.json new file mode 100644 index 000000000..45283aaed --- /dev/null +++ b/test/resources/9999999/automation/update-expected.json @@ -0,0 +1,67 @@ +{ + "description": "bla bla", + "key": "testExisting_automation", + "name": "testExisting_automation", + "r__folder_Path": "my automations", + "schedule": { + "endDate": "2022-07-30T00:00:00", + "icalRecur": "FREQ=DAILY;COUNT=1;INTERVAL=1", + "startDate": "2022-07-30T00:00:00", + "timezoneName": "W. Europe Standard Time" + }, + "status": "PausedSchedule", + "steps": [ + { + "activities": [ + { + "r__key": "testExisting_dataExtract", + "r__type": "dataExtract" + }, + { + "r__key": "testExisting_emailSend", + "r__type": "emailSend" + }, + { + "r__key": "testExisting_fileTransfer", + "r__type": "fileTransfer" + }, + { + "r__key": "testExisting_importFile", + "r__type": "importFile" + }, + { + "r__key": "testExisting_query", + "r__type": "query" + }, + { + "r__key": "testExisting_script", + "r__type": "script" + }, + { + "r__key": "testExisting_automation__s1.7", + "r__type": "verification" + } + ], + "name": "" + } + ], + "type": "scheduled", + "notifications": [ + { + "email": ["complete@test.accenture.com"], + "message": "", + "type": "Complete" + }, + { + "email": ["error@test.accenture.com"], + "message": "test", + "type": "Error" + } + ], + "createdDate": "2022-01-12T08:41:35.773Z", + "createdName": "Tom Tester", + "modifiedDate": "2024-11-04T17:42:13.143Z", + "modifiedName": "Jörn Berkefeld", + "pausedDate": "2025-03-14T15:21:57.62Z", + "pausedName": "Jörn Berkefeld" +} diff --git a/test/resources/9999999/automation/update-testExisting_automation-expected.md b/test/resources/9999999/automation/update-testExisting_automation-expected.md new file mode 100644 index 000000000..697134df1 --- /dev/null +++ b/test/resources/9999999/automation/update-testExisting_automation-expected.md @@ -0,0 +1,31 @@ +## testExisting_automation + +**Description:** bla bla + +**Folder:** my automations/ + +**Started by:** Schedule + +**Status:** PausedSchedule + +**Schedule:** + +* Start: 2022-07-30 00:00:00 +01:00 +* End: 2022-07-30 00:00:00 +01:00 +* Timezone: W. Europe Standard Time +* Recurrence: run only once + +**Notifications:** + +* Complete: complete@test.accenture.com +* Error: error@test.accenture.com ("test") + +| Step 1<br>_<small>-</small>_ | +| --- | +| _1.1: dataExtract_<br>testExisting_dataExtract | +| _1.2: emailSend_<br>testExisting_emailSend | +| _1.3: fileTransfer_<br>testExisting_fileTransfer | +| _1.4: importFile_<br>testExisting_importFile | +| _1.5: query_<br>testExisting_query | +| _1.6: script_<br>testExisting_script | +| _1.7: verification_<br>testExisting_automation__s1.7 | diff --git a/test/resources/9999999/automation/v1/automations/08afb0e2-b00a-4c88-ad2e-1f7f8788c560/get-response.json b/test/resources/9999999/automation/v1/automations/08afb0e2-b00a-4c88-ad2e-1f7f8788c560/get-response.json new file mode 100644 index 000000000..2cb5c1e27 --- /dev/null +++ b/test/resources/9999999/automation/v1/automations/08afb0e2-b00a-4c88-ad2e-1f7f8788c560/get-response.json @@ -0,0 +1,92 @@ +{ + "id": "08afb0e2-b00a-4c88-ad2e-1f7f8788c560", + "name": "testExisting_automation", + "description": "bla bla", + "key": "testExisting_automation", + "typeId": 1, + "type": "scheduled", + "statusId": 4, + "status": "PausedSchedule", + "categoryId": 290937, + "schedule": { + "id": "b393aa6c-a4a8-4c0f-a148-9250258a7339", + "typeId": 3, + "startDate": "2022-07-30T00:00:00", + "endDate": "2022-07-30T00:00:00", + "scheduledTime": "0001-01-01T07:00:00", + "rangeTypeId": 0, + "occurrences": 1, + "pattern": "<Pattern><PatternType>0</PatternType><DayInterval>1</DayInterval></Pattern>", + "icalRecur": "FREQ=DAILY;COUNT=1;INTERVAL=1", + "timezoneName": "W. Europe Standard Time", + "scheduleStatus": "paused", + "timezoneId": 5 + }, + "steps": [ + { + "id": "13fda077-0e82-4936-b936-a36b0997fc44", + "name": "", + "step": 1, + "activities": [ + { + "id": "d3774dc2-a271-4a44-8cbe-f630a6d6545e", + "name": "testExisting_emailSend", + "activityObjectId": "9b1c7bf9-4964-ed11-b849-48df37d1de8b", + "objectTypeId": 42, + "displayOrder": 2 + }, + { + "id": "8081a992-a27d-4a43-984a-d60114ea1025", + "name": "testExisting_dataExtract", + "activityObjectId": "56c5370a-f988-4f36-b0ee-0f876573f6d7", + "objectTypeId": 73, + "displayOrder": 1 + }, + { + "id": "2c77fc42-85eb-4611-98f9-223d29d89d72", + "name": "testExisting_fileTransfer", + "activityObjectId": "72c328ac-f5b0-4e37-91d3-a775666f15a6", + "objectTypeId": 53, + "displayOrder": 3 + }, + { + "id": "298b2794-28cb-4c70-b7ad-58b2c8cf48f7", + "name": "testExisting_importFile", + "activityObjectId": "9d16f42c-2260-ed11-b849-48df37d1de8b", + "objectTypeId": 43, + "displayOrder": 4, + "targetDataExtensions": [ + { + "id": "21711373-72c1-ec11-b83b-48df37d1deb7", + "name": "testExisting_dataExtension", + "key": "testExisting_dataExtension", + "description": "bla bla", + "rowCount": 0 + } + ] + }, + { + "id": "e3774dc2-a271-4a44-8cbe-f630a6d6545e", + "name": "testExisting_query_WRONG_NAME", + "activityObjectId": "549f0568-607c-4940-afef-437965094dat", + "objectTypeId": 300, + "displayOrder": 5 + }, + { + "id": "g3774dc2-a271-4a44-8cbe-f630a6d6545e", + "name": "testExisting_script", + "activityObjectId": "39f6a488-20eb-4ba0-b0b9-023725b574e4", + "objectTypeId": 423, + "displayOrder": 6 + }, + { + "id": "f3774dc2-a271-4a44-8cbe-f630a6d6545e", + "name": "testExisting_dataExtension", + "activityObjectId": "testExisting_39f6a488-20eb-4ba0-b0b9", + "objectTypeId": 1000, + "displayOrder": 7 + } + ] + } + ] +} diff --git a/test/resources/9999999/automation/v1/automations/08afb0e2-b00a-4c88-ad2e-1f7f8788c560/patch-response.json b/test/resources/9999999/automation/v1/automations/08afb0e2-b00a-4c88-ad2e-1f7f8788c560/patch-response.json new file mode 100644 index 000000000..1c0dc1b08 --- /dev/null +++ b/test/resources/9999999/automation/v1/automations/08afb0e2-b00a-4c88-ad2e-1f7f8788c560/patch-response.json @@ -0,0 +1,85 @@ +{ + "legacyId": "RkpOcE9qSVh2VUdnYTVJbWFfWW14dzoyNTow", + "name": "testExisting_automation", + "description": "updated on deploy", + "key": "testExisting_automation", + "typeId": 1, + "type": "scheduled", + "statusId": 4, + "status": "PausedSchedule", + "schedule": { + "id": "b393aa6c-a4a8-4c0f-a148-9250258a7339", + "typeId": 3, + "startDate": "2022-07-30T00:00:00", + "endDate": "2022-07-30T00:00:00", + "scheduledTime": "0001-01-01T07:00:00", + "rangeTypeId": 0, + "occurrences": 1, + "pattern": "<Pattern><PatternType>0</PatternType><DayInterval>1</DayInterval></Pattern>", + "icalRecur": "FREQ=DAILY;COUNT=1;INTERVAL=1", + "timezoneName": "W. Europe Standard Time", + "scheduleStatus": "paused", + "timezoneId": 5 + }, + "steps": [ + { + "activities": [ + { + "id": "8081a992-a27d-4a43-984a-d60114ea1025", + "name": "testExisting_dataExtract", + "activityObjectId": "56c5370a-f988-4f36-b0ee-0f876573f6d7", + "objectTypeId": 73, + "displayOrder": 1 + }, + { + "id": "d3774dc2-a271-4a44-8cbe-f630a6d6545e", + "name": "testExisting_emailSend", + "activityObjectId": "9b1c7bf9-4964-ed11-b849-48df37d1de8b", + "objectTypeId": 42, + "displayOrder": 2 + }, + { + "id": "2c77fc42-85eb-4611-98f9-223d29d89d72", + "name": "testExisting_fileTransfer", + "activityObjectId": "72c328ac-f5b0-4e37-91d3-a775666f15a6", + "objectTypeId": 53, + "displayOrder": 3 + }, + { + "id": "298b2794-28cb-4c70-b7ad-58b2c8cf48f7", + "name": "testExisting_importFile", + "activityObjectId": "9d16f42c-2260-ed11-b849-48df37d1de8b", + "objectTypeId": 43, + "displayOrder": 4, + "targetDataExtensions": [ + { + "id": "21711373-72c1-ec11-b83b-48df37d1deb7", + "name": "testExisting_dataExtension", + "key": "testExisting_dataExtension", + "description": "bla bla", + "rowCount": 0 + } + ] + }, + { + "id": "e3774dc2-a271-4a44-8cbe-f630a6d6545e", + "name": "testExisting_query_WRONG_NAME", + "activityObjectId": "549f0568-607c-4940-afef-437965094dat", + "objectTypeId": 300, + "displayOrder": 5 + }, + { + "id": "g3774dc2-a271-4a44-8cbe-f630a6d6545e", + "name": "testExisting_script", + "activityObjectId": "39f6a488-20eb-4ba0-b0b9-023725b574e4", + "objectTypeId": 423, + "displayOrder": 6 + } + ], + "annotation": "", + "stepNumber": 0 + } + ], + "categoryId": 290937, + "id": "08afb0e2-b00a-4c88-ad2e-1f7f8788c560" +} diff --git a/test/resources/9999999/automation/v1/automations/08afb0e2-b00a-4c88-ad2e-pause/get-response.json b/test/resources/9999999/automation/v1/automations/08afb0e2-b00a-4c88-ad2e-pause/get-response.json new file mode 100644 index 000000000..58ec6b51c --- /dev/null +++ b/test/resources/9999999/automation/v1/automations/08afb0e2-b00a-4c88-ad2e-pause/get-response.json @@ -0,0 +1,85 @@ +{ + "id": "08afb0e2-b00a-4c88-ad2e-pause", + "name": "testExisting_automation_pause", + "description": "bla bla", + "key": "testExisting_automation_pause", + "typeId": 1, + "type": "scheduled", + "statusId": 4, + "status": "Scheduled", + "categoryId": 290937, + "schedule": { + "id": "b393aa6c-a4a8-4c0f-a148-9250258a7339", + "typeId": 3, + "startDate": "2022-07-30T00:00:00", + "endDate": "2022-07-30T00:00:00", + "scheduledTime": "0001-01-01T07:00:00", + "rangeTypeId": 0, + "occurrences": 1, + "pattern": "<Pattern><PatternType>0</PatternType><DayInterval>1</DayInterval></Pattern>", + "icalRecur": "FREQ=DAILY;COUNT=1;INTERVAL=1", + "timezoneName": "W. Europe Standard Time", + "scheduleStatus": "scheduled", + "timezoneId": 5 + }, + "steps": [ + { + "id": "13fda077-0e82-4936-b936-a36b0997fc44", + "name": "", + "step": 1, + "activities": [ + { + "id": "8081a992-a27d-4a43-984a-d60114ea1025", + "name": "testExisting_dataExtract", + "activityObjectId": "56c5370a-f988-4f36-b0ee-0f876573f6d7", + "objectTypeId": 73, + "displayOrder": 1 + }, + { + "id": "d3774dc2-a271-4a44-8cbe-f630a6d6545e", + "name": "testExisting_emailSend", + "activityObjectId": "9b1c7bf9-4964-ed11-b849-48df37d1de8b", + "objectTypeId": 42, + "displayOrder": 2 + }, + { + "id": "2c77fc42-85eb-4611-98f9-223d29d89d72", + "name": "testExisting_fileTransfer", + "activityObjectId": "72c328ac-f5b0-4e37-91d3-a775666f15a6", + "objectTypeId": 53, + "displayOrder": 3 + }, + { + "id": "298b2794-28cb-4c70-b7ad-58b2c8cf48f7", + "name": "testExisting_importFile", + "activityObjectId": "9d16f42c-2260-ed11-b849-48df37d1de8b", + "objectTypeId": 43, + "displayOrder": 4, + "targetDataExtensions": [ + { + "id": "21711373-72c1-ec11-b83b-48df37d1deb7", + "name": "testExisting_dataExtension", + "key": "testExisting_dataExtension", + "description": "bla bla", + "rowCount": 0 + } + ] + }, + { + "id": "e3774dc2-a271-4a44-8cbe-f630a6d6545e", + "name": "testExisting_query_WRONG_NAME", + "activityObjectId": "549f0568-607c-4940-afef-437965094dat", + "objectTypeId": 300, + "displayOrder": 5 + }, + { + "id": "g3774dc2-a271-4a44-8cbe-f630a6d6545e", + "name": "testExisting_script", + "activityObjectId": "39f6a488-20eb-4ba0-b0b9-023725b574e4", + "objectTypeId": 423, + "displayOrder": 6 + } + ] + } + ] +} diff --git a/test/resources/9999999/automation/v1/automations/08afb0e2-b00a-4c88-ad2e-pause/patch-response.json b/test/resources/9999999/automation/v1/automations/08afb0e2-b00a-4c88-ad2e-pause/patch-response.json new file mode 100644 index 000000000..2454567e8 --- /dev/null +++ b/test/resources/9999999/automation/v1/automations/08afb0e2-b00a-4c88-ad2e-pause/patch-response.json @@ -0,0 +1,85 @@ +{ + "legacyId": "RkpOcE9qSVh2VUdnYTVJbWFfWW14dzoyNTow-PAUSED", + "name": "testExisting_automation_pause", + "description": "updated on deploy", + "key": "testExisting_automation_pause", + "typeId": 1, + "type": "scheduled", + "statusId": 4, + "status": "Scheduled", + "schedule": { + "id": "b393aa6c-a4a8-4c0f-a148-9250258a7339", + "typeId": 3, + "startDate": "2022-07-30T00:00:00", + "endDate": "2022-07-30T00:00:00", + "scheduledTime": "0001-01-01T07:00:00", + "rangeTypeId": 0, + "occurrences": 1, + "pattern": "<Pattern><PatternType>0</PatternType><DayInterval>1</DayInterval></Pattern>", + "icalRecur": "FREQ=DAILY;COUNT=1;INTERVAL=1", + "timezoneName": "W. Europe Standard Time", + "scheduleStatus": "scheduled", + "timezoneId": 5 + }, + "steps": [ + { + "activities": [ + { + "id": "8081a992-a27d-4a43-984a-d60114ea1025", + "name": "testExisting_dataExtract", + "activityObjectId": "56c5370a-f988-4f36-b0ee-0f876573f6d7", + "objectTypeId": 73, + "displayOrder": 1 + }, + { + "id": "d3774dc2-a271-4a44-8cbe-f630a6d6545e", + "name": "testExisting_emailSend", + "activityObjectId": "9b1c7bf9-4964-ed11-b849-48df37d1de8b", + "objectTypeId": 42, + "displayOrder": 2 + }, + { + "id": "2c77fc42-85eb-4611-98f9-223d29d89d72", + "name": "testExisting_fileTransfer", + "activityObjectId": "72c328ac-f5b0-4e37-91d3-a775666f15a6", + "objectTypeId": 53, + "displayOrder": 3 + }, + { + "id": "298b2794-28cb-4c70-b7ad-58b2c8cf48f7", + "name": "testExisting_importFile", + "activityObjectId": "9d16f42c-2260-ed11-b849-48df37d1de8b", + "objectTypeId": 43, + "displayOrder": 4, + "targetDataExtensions": [ + { + "id": "21711373-72c1-ec11-b83b-48df37d1deb7", + "name": "testExisting_dataExtension", + "key": "testExisting_dataExtension", + "description": "bla bla", + "rowCount": 0 + } + ] + }, + { + "id": "e3774dc2-a271-4a44-8cbe-f630a6d6545e", + "name": "testExisting_query_WRONG_NAME", + "activityObjectId": "549f0568-607c-4940-afef-437965094dat", + "objectTypeId": 300, + "displayOrder": 5 + }, + { + "id": "g3774dc2-a271-4a44-8cbe-f630a6d6545e", + "name": "testExisting_script", + "activityObjectId": "39f6a488-20eb-4ba0-b0b9-023725b574e4", + "objectTypeId": 423, + "displayOrder": 6 + } + ], + "annotation": "", + "stepNumber": 0 + } + ], + "categoryId": 290937, + "id": "08afb0e2-b00a-4c88-ad2e-1f7f8788c560" +} diff --git a/test/resources/9999999/automation/v1/automations/08afb0e2-b00a-4c88-fixKey_pause/get-response.json b/test/resources/9999999/automation/v1/automations/08afb0e2-b00a-4c88-fixKey_pause/get-response.json new file mode 100644 index 000000000..17e4c6c2e --- /dev/null +++ b/test/resources/9999999/automation/v1/automations/08afb0e2-b00a-4c88-fixKey_pause/get-response.json @@ -0,0 +1,85 @@ +{ + "id": "08afb0e2-b00a-4c88-fixKey_pause", + "name": "testExisting_automation_fixedKey_paused", + "description": "testing fixKey on an a paused automation", + "key": "testExisting_automation_fixKey_pause", + "typeId": 1, + "type": "scheduled", + "statusId": 4, + "status": "PausedSchedule", + "categoryId": 290937, + "schedule": { + "id": "b393aa6c-a4a8-4c0f-a148-9250258a7339", + "typeId": 3, + "startDate": "2022-07-30T00:00:00", + "endDate": "2022-07-30T00:00:00", + "scheduledTime": "0001-01-01T07:00:00", + "rangeTypeId": 0, + "occurrences": 1, + "pattern": "<Pattern><PatternType>0</PatternType><DayInterval>1</DayInterval></Pattern>", + "icalRecur": "FREQ=DAILY;COUNT=1;INTERVAL=1", + "timezoneName": "W. Europe Standard Time", + "scheduleStatus": "paused", + "timezoneId": 5 + }, + "steps": [ + { + "id": "13fda077-0e82-4936-b936-a36b0997fc44", + "name": "", + "step": 1, + "activities": [ + { + "id": "8081a992-a27d-4a43-984a-d60114ea1025", + "name": "testExisting_dataExtract", + "activityObjectId": "56c5370a-f988-4f36-b0ee-0f876573f6d7", + "objectTypeId": 73, + "displayOrder": 1 + }, + { + "id": "d3774dc2-a271-4a44-8cbe-f630a6d6545e", + "name": "testExisting_emailSend", + "activityObjectId": "9b1c7bf9-4964-ed11-b849-48df37d1de8b", + "objectTypeId": 42, + "displayOrder": 2 + }, + { + "id": "2c77fc42-85eb-4611-98f9-223d29d89d72", + "name": "testExisting_fileTransfer", + "activityObjectId": "72c328ac-f5b0-4e37-91d3-a775666f15a6", + "objectTypeId": 53, + "displayOrder": 3 + }, + { + "id": "298b2794-28cb-4c70-b7ad-58b2c8cf48f7", + "name": "testExisting_importFile", + "activityObjectId": "9d16f42c-2260-ed11-b849-48df37d1de8b", + "objectTypeId": 43, + "displayOrder": 4, + "targetDataExtensions": [ + { + "id": "21711373-72c1-ec11-b83b-48df37d1deb7", + "name": "testExisting_dataExtension", + "key": "testExisting_dataExtension", + "description": "bla bla", + "rowCount": 0 + } + ] + }, + { + "id": "e3774dc2-a271-4a44-8cbe-f630a6d6545e", + "name": "testExisting_query_WRONG_NAME", + "activityObjectId": "549f0568-607c-4940-afef-437965094dat", + "objectTypeId": 300, + "displayOrder": 5 + }, + { + "id": "g3774dc2-a271-4a44-8cbe-f630a6d6545e", + "name": "testExisting_script", + "activityObjectId": "39f6a488-20eb-4ba0-b0b9-023725b574e4", + "objectTypeId": 423, + "displayOrder": 6 + } + ] + } + ] +} diff --git a/test/resources/9999999/automation/v1/automations/08afb0e2-b00a-4c88-fixKey_pause/patch-response.json b/test/resources/9999999/automation/v1/automations/08afb0e2-b00a-4c88-fixKey_pause/patch-response.json new file mode 100644 index 000000000..111641f1e --- /dev/null +++ b/test/resources/9999999/automation/v1/automations/08afb0e2-b00a-4c88-fixKey_pause/patch-response.json @@ -0,0 +1,86 @@ +{ + "id": "08afb0e2-b00a-4c88-fixKey_pause", + "legacyId": "RkpOcE9qSVh2VUdnYTVJbWFfWW14dzoyNTow", + "name": "testExisting_automation_fixedKey_paused", + "description": "testing fixKey on an a paused automation", + "key": "testExisting_automation_fixedKey_paused", + "typeId": 1, + "type": "scheduled", + "statusId": 4, + "status": "PausedSchedule", + "categoryId": 290937, + "schedule": { + "id": "b393aa6c-a4a8-4c0f-a148-9250258a7339", + "typeId": 3, + "startDate": "2022-07-30T00:00:00", + "endDate": "2022-07-30T00:00:00", + "scheduledTime": "0001-01-01T07:00:00", + "rangeTypeId": 0, + "occurrences": 1, + "pattern": "<Pattern><PatternType>0</PatternType><DayInterval>1</DayInterval></Pattern>", + "icalRecur": "FREQ=DAILY;COUNT=1;INTERVAL=1", + "timezoneName": "W. Europe Standard Time", + "scheduleStatus": "paused", + "timezoneId": 5 + }, + "steps": [ + { + "id": "13fda077-0e82-4936-b936-a36b0997fc44", + "name": "", + "step": 1, + "activities": [ + { + "id": "8081a992-a27d-4a43-984a-d60114ea1025", + "name": "testExisting_dataExtract", + "activityObjectId": "56c5370a-f988-4f36-b0ee-0f876573f6d7", + "objectTypeId": 73, + "displayOrder": 1 + }, + { + "id": "d3774dc2-a271-4a44-8cbe-f630a6d6545e", + "name": "testExisting_emailSend", + "activityObjectId": "9b1c7bf9-4964-ed11-b849-48df37d1de8b", + "objectTypeId": 42, + "displayOrder": 2 + }, + { + "id": "2c77fc42-85eb-4611-98f9-223d29d89d72", + "name": "testExisting_fileTransfer", + "activityObjectId": "72c328ac-f5b0-4e37-91d3-a775666f15a6", + "objectTypeId": 53, + "displayOrder": 3 + }, + { + "id": "298b2794-28cb-4c70-b7ad-58b2c8cf48f7", + "name": "testExisting_importFile", + "activityObjectId": "9d16f42c-2260-ed11-b849-48df37d1de8b", + "objectTypeId": 43, + "displayOrder": 4, + "targetDataExtensions": [ + { + "id": "21711373-72c1-ec11-b83b-48df37d1deb7", + "name": "testExisting_dataExtension", + "key": "testExisting_dataExtension", + "description": "bla bla", + "rowCount": 0 + } + ] + }, + { + "id": "e3774dc2-a271-4a44-8cbe-f630a6d6545e", + "name": "testExisting_query_WRONG_NAME", + "activityObjectId": "549f0568-607c-4940-afef-437965094dat", + "objectTypeId": 300, + "displayOrder": 5 + }, + { + "id": "g3774dc2-a271-4a44-8cbe-f630a6d6545e", + "name": "testExisting_script", + "activityObjectId": "39f6a488-20eb-4ba0-b0b9-023725b574e4", + "objectTypeId": 423, + "displayOrder": 6 + } + ] + } + ] +} diff --git a/test/resources/9999999/automation/v1/automations/08afb0e2-b00a-4c88-fixKey_schedule/get-response.json b/test/resources/9999999/automation/v1/automations/08afb0e2-b00a-4c88-fixKey_schedule/get-response.json new file mode 100644 index 000000000..5f88c6f78 --- /dev/null +++ b/test/resources/9999999/automation/v1/automations/08afb0e2-b00a-4c88-fixKey_schedule/get-response.json @@ -0,0 +1,85 @@ +{ + "id": "08afb0e2-b00a-4c88-fixKey_schedule", + "name": "testExisting_automation_fixedKey_scheduled", + "description": "testing fixKey on an a scheduled automation", + "key": "testExisting_automation_fixKey_schedule", + "typeId": 1, + "type": "scheduled", + "statusId": 4, + "status": "Scheduled", + "categoryId": 290937, + "schedule": { + "id": "b393aa6c-a4a8-4c0f-a148-9250258a7339", + "typeId": 3, + "startDate": "2022-07-30T00:00:00", + "endDate": "2022-07-30T00:00:00", + "scheduledTime": "0001-01-01T07:00:00", + "rangeTypeId": 0, + "occurrences": 1, + "pattern": "<Pattern><PatternType>0</PatternType><DayInterval>1</DayInterval></Pattern>", + "icalRecur": "FREQ=DAILY;COUNT=1;INTERVAL=1", + "timezoneName": "W. Europe Standard Time", + "scheduleStatus": "paused", + "timezoneId": 5 + }, + "steps": [ + { + "id": "13fda077-0e82-4936-b936-a36b0997fc44", + "name": "", + "step": 1, + "activities": [ + { + "id": "8081a992-a27d-4a43-984a-d60114ea1025", + "name": "testExisting_dataExtract", + "activityObjectId": "56c5370a-f988-4f36-b0ee-0f876573f6d7", + "objectTypeId": 73, + "displayOrder": 1 + }, + { + "id": "d3774dc2-a271-4a44-8cbe-f630a6d6545e", + "name": "testExisting_emailSend", + "activityObjectId": "9b1c7bf9-4964-ed11-b849-48df37d1de8b", + "objectTypeId": 42, + "displayOrder": 2 + }, + { + "id": "2c77fc42-85eb-4611-98f9-223d29d89d72", + "name": "testExisting_fileTransfer", + "activityObjectId": "72c328ac-f5b0-4e37-91d3-a775666f15a6", + "objectTypeId": 53, + "displayOrder": 3 + }, + { + "id": "298b2794-28cb-4c70-b7ad-58b2c8cf48f7", + "name": "testExisting_importFile", + "activityObjectId": "9d16f42c-2260-ed11-b849-48df37d1de8b", + "objectTypeId": 43, + "displayOrder": 4, + "targetDataExtensions": [ + { + "id": "21711373-72c1-ec11-b83b-48df37d1deb7", + "name": "testExisting_dataExtension", + "key": "testExisting_dataExtension", + "description": "bla bla", + "rowCount": 0 + } + ] + }, + { + "id": "e3774dc2-a271-4a44-8cbe-f630a6d6545e", + "name": "testExisting_query_WRONG_NAME", + "activityObjectId": "549f0568-607c-4940-afef-437965094dat", + "objectTypeId": 300, + "displayOrder": 5 + }, + { + "id": "g3774dc2-a271-4a44-8cbe-f630a6d6545e", + "name": "testExisting_script", + "activityObjectId": "39f6a488-20eb-4ba0-b0b9-023725b574e4", + "objectTypeId": 423, + "displayOrder": 6 + } + ] + } + ] +} diff --git a/test/resources/9999999/automation/v1/automations/08afb0e2-b00a-4c88-fixKey_schedule/patch-response.json b/test/resources/9999999/automation/v1/automations/08afb0e2-b00a-4c88-fixKey_schedule/patch-response.json new file mode 100644 index 000000000..94fb59728 --- /dev/null +++ b/test/resources/9999999/automation/v1/automations/08afb0e2-b00a-4c88-fixKey_schedule/patch-response.json @@ -0,0 +1,86 @@ +{ + "id": "08afb0e2-b00a-4c88-fixKey_schedule", + "legacyId": "RkpOcE9qSVh2VUdnYTVJbWFfWW14dzoyNTow", + "name": "testExisting_automation_fixedKey_scheduled", + "description": "testing fixKey on an a scheduled automation", + "key": "testExisting_automation_fixedKey_scheduled", + "typeId": 1, + "type": "scheduled", + "statusId": 4, + "status": "Scheduled", + "categoryId": 290937, + "schedule": { + "id": "b393aa6c-a4a8-4c0f-a148-9250258a7339", + "typeId": 3, + "startDate": "2022-07-30T00:00:00", + "endDate": "2022-07-30T00:00:00", + "scheduledTime": "0001-01-01T07:00:00", + "rangeTypeId": 0, + "occurrences": 1, + "pattern": "<Pattern><PatternType>0</PatternType><DayInterval>1</DayInterval></Pattern>", + "icalRecur": "FREQ=DAILY;COUNT=1;INTERVAL=1", + "timezoneName": "W. Europe Standard Time", + "scheduleStatus": "paused", + "timezoneId": 5 + }, + "steps": [ + { + "id": "13fda077-0e82-4936-b936-a36b0997fc44", + "name": "", + "step": 1, + "activities": [ + { + "id": "8081a992-a27d-4a43-984a-d60114ea1025", + "name": "testExisting_dataExtract", + "activityObjectId": "56c5370a-f988-4f36-b0ee-0f876573f6d7", + "objectTypeId": 73, + "displayOrder": 1 + }, + { + "id": "d3774dc2-a271-4a44-8cbe-f630a6d6545e", + "name": "testExisting_emailSend", + "activityObjectId": "9b1c7bf9-4964-ed11-b849-48df37d1de8b", + "objectTypeId": 42, + "displayOrder": 2 + }, + { + "id": "2c77fc42-85eb-4611-98f9-223d29d89d72", + "name": "testExisting_fileTransfer", + "activityObjectId": "72c328ac-f5b0-4e37-91d3-a775666f15a6", + "objectTypeId": 53, + "displayOrder": 3 + }, + { + "id": "298b2794-28cb-4c70-b7ad-58b2c8cf48f7", + "name": "testExisting_importFile", + "activityObjectId": "9d16f42c-2260-ed11-b849-48df37d1de8b", + "objectTypeId": 43, + "displayOrder": 4, + "targetDataExtensions": [ + { + "id": "21711373-72c1-ec11-b83b-48df37d1deb7", + "name": "testExisting_dataExtension", + "key": "testExisting_dataExtension", + "description": "bla bla", + "rowCount": 0 + } + ] + }, + { + "id": "e3774dc2-a271-4a44-8cbe-f630a6d6545e", + "name": "testExisting_query_WRONG_NAME", + "activityObjectId": "549f0568-607c-4940-afef-437965094dat", + "objectTypeId": 300, + "displayOrder": 5 + }, + { + "id": "g3774dc2-a271-4a44-8cbe-f630a6d6545e", + "name": "testExisting_script", + "activityObjectId": "39f6a488-20eb-4ba0-b0b9-023725b574e4", + "objectTypeId": 423, + "displayOrder": 6 + } + ] + } + ] +} diff --git a/test/resources/9999999/automation/v1/automations/0fc2ac96-14ba-495a-8db9-3ddd4f8ac444-wait/get-response.json b/test/resources/9999999/automation/v1/automations/0fc2ac96-14ba-495a-8db9-3ddd4f8ac444-wait/get-response.json new file mode 100644 index 000000000..3d1d75e29 --- /dev/null +++ b/test/resources/9999999/automation/v1/automations/0fc2ac96-14ba-495a-8db9-3ddd4f8ac444-wait/get-response.json @@ -0,0 +1,114 @@ +{ + "id": "0fc2ac96-14ba-495a-8db9-3ddd4f8ac444-wait", + "name": "testExisting_automation_wait", + "description": "", + "key": "testExisting_automation_wait", + "typeId": 0, + "type": "unspecified", + "statusId": 2, + "status": "Ready", + "categoryId": 290937, + "schedule": { + "scheduleStatus": "none" + }, + "steps": [ + { + "id": "73acb9f6-3dd2-4a7e-a25b-7c3a03170957", + "name": "", + "step": 1, + "activities": [ + { + "id": "f8c0e577-278c-479f-b381-610569b0b52e", + "name": "1 Years", + "activityObjectId": "1bd41a92-2c57-463c-a1e6-6e1549e481a1", + "objectTypeId": 467, + "displayOrder": 1 + } + ] + }, + { + "id": "83fd8f6d-54bb-4b04-bc0d-dd62e16f452a", + "name": "", + "step": 2, + "activities": [ + { + "id": "d364faa9-06e3-4d38-9fbe-93986b1d541e", + "name": "1 Months", + "activityObjectId": "76f255e3-1603-4d8b-be59-32ac6fe61e15", + "objectTypeId": 467, + "displayOrder": 1 + } + ] + }, + { + "id": "935d4ac1-c65e-4ba6-adb4-a3c8e8dcb241", + "name": "", + "step": 3, + "activities": [ + { + "id": "5aaeb136-9b1b-4d1f-95f2-bdd8d522f018", + "name": "1 Weeks", + "activityObjectId": "85a405e4-e77b-4a2e-8d1b-9ad34244ac10", + "objectTypeId": 467, + "displayOrder": 1 + } + ] + }, + { + "id": "eb5871a6-1399-446c-a067-3a03d1a4367f", + "name": "", + "step": 4, + "activities": [ + { + "id": "002fbe34-10b0-4121-b19a-e9c073cbd700", + "name": "1 Days", + "activityObjectId": "562cf01a-6cca-4fd9-9d3c-f2649379a282", + "objectTypeId": 467, + "displayOrder": 1 + } + ] + }, + { + "id": "26c45a57-8761-4dac-91b4-c1c64d1a6741", + "name": "", + "step": 5, + "activities": [ + { + "id": "283a0acf-d5ed-4535-a2a7-383e2c8c51db", + "name": "1 Hours", + "activityObjectId": "2722bb7c-2ea2-4cf5-8891-96c5a4362a72", + "objectTypeId": 467, + "displayOrder": 1 + } + ] + }, + { + "id": "93065127-adcc-43cb-b040-ef63be2285ec", + "name": "", + "step": 6, + "activities": [ + { + "id": "167b101a-af09-4002-a14f-f537de266ce0", + "name": "1 Minutes", + "activityObjectId": "5d5f816b-b024-45a9-8ce9-726c6dd61bf4", + "objectTypeId": 467, + "displayOrder": 1 + } + ] + }, + { + "id": "0d8d1390-75be-427d-900b-0af5c906a01b", + "name": "", + "step": 7, + "activities": [ + { + "id": "6752906a-ce99-4bfe-b1d5-4db8eb4a24b0", + "name": "03:00 PM", + "activityObjectId": "1c9836b8-0242-4620-9421-21d36a0df751", + "objectTypeId": 467, + "displayOrder": 1 + } + ] + } + ] +} diff --git a/test/resources/9999999/automation/v1/automations/8f82c2a7-0bae-45a9-bdee-e631ab25c0d5/get-response.json b/test/resources/9999999/automation/v1/automations/8f82c2a7-0bae-45a9-bdee-e631ab25c0d5/get-response.json new file mode 100644 index 000000000..2aa165b19 --- /dev/null +++ b/test/resources/9999999/automation/v1/automations/8f82c2a7-0bae-45a9-bdee-e631ab25c0d5/get-response.json @@ -0,0 +1,44 @@ +{ + "id": "8f82c2a7-0bae-45a9-bdee-e631ab25c0d5", + "name": "testExisting_automation_event", + "description": "", + "key": "testExisting_automation_event", + "typeId": 1, + "type": "scheduled", + "statusId": 6, + "status": "Scheduled", + "categoryId": 290937, + "lastRunTime": "2024-11-08T03:15:20.27", + "lastRunInstanceId": "b2bc1d03-04ba-4a01-9e33-0c246f07dd36", + "schedule": { + "id": "064cf4ba-a5d0-420a-8a4f-26055a3550ba", + "typeId": 2, + "startDate": "2024-11-07T12:15:00", + "endDate": "2079-06-06T00:00:00", + "scheduledTime": "2024-11-08T11:15:00", + "rangeTypeId": 1, + "occurrences": 478403, + "pattern": "<Pattern><PatternType>0</PatternType><HourInterval>1</HourInterval></Pattern>", + "icalRecur": "FREQ=HOURLY;UNTIL=20790606T080000;INTERVAL=1", + "timezoneName": "W. Europe Standard Time", + "scheduleStatus": "active", + "timezoneId": 5 + }, + "steps": [ + { + "id": "83755b3f-5012-49b4-8112-0291c879b9d5", + "name": "", + "description": "", + "step": 1, + "activities": [ + { + "id": "39d74fe0-ced2-4e91-b23e-11218adc304c", + "name": "testExisting_event_automation", + "activityObjectId": "161b64a1-1867-4272-8c5c-4d7abe880702", + "objectTypeId": 952, + "displayOrder": 1 + } + ] + } + ] +} diff --git a/test/resources/9999999/automation/v1/automations/a8afb0e2-b00a-4c88-ad2e-1f7f8788c560/get-response.json b/test/resources/9999999/automation/v1/automations/a8afb0e2-b00a-4c88-ad2e-1f7f8788c560/get-response.json new file mode 100644 index 000000000..0f20856b9 --- /dev/null +++ b/test/resources/9999999/automation/v1/automations/a8afb0e2-b00a-4c88-ad2e-1f7f8788c560/get-response.json @@ -0,0 +1,85 @@ +{ + "id": "a8afb0e2-b00a-4c88-ad2e-1f7f8788c560", + "name": "testNew_automation", + "description": "created on deploy", + "key": "testNew_automation", + "typeId": 1, + "type": "scheduled", + "statusId": 4, + "status": "Scheduled", + "categoryId": 290937, + "schedule": { + "id": "b393aa6c-a4a8-4c0f-a148-9250258a7339", + "typeId": 3, + "startDate": "2022-07-30T00:00:00", + "endDate": "2022-07-30T00:00:00", + "scheduledTime": "0001-01-01T07:00:00", + "rangeTypeId": 0, + "occurrences": 1, + "pattern": "<Pattern><PatternType>0</PatternType><DayInterval>1</DayInterval></Pattern>", + "icalRecur": "FREQ=DAILY;COUNT=1;INTERVAL=1", + "timezoneName": "W. Europe Standard Time", + "scheduleStatus": "paused", + "timezoneId": 5 + }, + "steps": [ + { + "id": "13fda077-0e82-4936-b936-a36b0997fc44", + "name": "", + "step": 1, + "activities": [ + { + "id": "8081a992-a27d-4a43-984a-d60114ea1025", + "name": "testExisting_dataExtract", + "activityObjectId": "56c5370a-f988-4f36-b0ee-0f876573f6d7", + "objectTypeId": 73, + "displayOrder": 1 + }, + { + "id": "d3774dc2-a271-4a44-8cbe-f630a6d6545e", + "name": "testExisting_emailSend", + "activityObjectId": "9b1c7bf9-4964-ed11-b849-48df37d1de8b", + "objectTypeId": 42, + "displayOrder": 2 + }, + { + "id": "2c77fc42-85eb-4611-98f9-223d29d89d72", + "name": "testExisting_fileTransfer", + "activityObjectId": "72c328ac-f5b0-4e37-91d3-a775666f15a6", + "objectTypeId": 53, + "displayOrder": 3 + }, + { + "id": "298b2794-28cb-4c70-b7ad-58b2c8cf48f7", + "name": "testExisting_importFile", + "activityObjectId": "9d16f42c-2260-ed11-b849-48df37d1de8b", + "objectTypeId": 43, + "displayOrder": 4, + "targetDataExtensions": [ + { + "id": "21711373-72c1-ec11-b83b-48df37d1deb7", + "name": "testExisting_dataExtension", + "key": "testExisting_dataExtension", + "description": "bla bla", + "rowCount": 0 + } + ] + }, + { + "id": "e3774dc2-a271-4a44-8cbe-f630a6d6545e", + "name": "testExisting_query_WRONG_NAME", + "activityObjectId": "549f0568-607c-4940-afef-437965094dat", + "objectTypeId": 300, + "displayOrder": 5 + }, + { + "id": "g3774dc2-a271-4a44-8cbe-f630a6d6545e", + "name": "testExisting_script", + "activityObjectId": "39f6a488-20eb-4ba0-b0b9-023725b574e4", + "objectTypeId": 423, + "displayOrder": 6 + } + ] + } + ] +} diff --git a/test/resources/9999999/automation/v1/automations/post-response.json b/test/resources/9999999/automation/v1/automations/post-response.json new file mode 100644 index 000000000..bacde7613 --- /dev/null +++ b/test/resources/9999999/automation/v1/automations/post-response.json @@ -0,0 +1,93 @@ +{ + "id": "a8afb0e2-b00a-4c88-ad2e-1f7f8788c560", + "legacyId": "NewRkpOcE9qSVh2VUdnYTVJbWFfWW14dzoyNTow", + "name": "testNew_automation", + "description": "created on deploy", + "key": "testNew_automation", + "categoryId": 290937, + "statusId": 4, + "lastSavedDate": "2023-07-04T07:49:08.577", + "lastSavedByName": "SFMC DevTools app user", + "createdDate": "2023-07-04T07:49:08.297", + "createdByName": "SFMC DevTools app user", + "updateInProgress": false, + "startSource": { + "typeId": 1, + "schedule": { + "scheduleTypeId": 1, + "startDate": "2020-05-13T18:30:32.11-06:00", + "endDate": "2079-06-06T21:00:00-06:00", + "rangeTypeId": 1, + "occurrences": 6213054, + "icalRecur": "FREQ=MINUTELY;UNTIL=20790607T050000;INTERVAL=5", + "timezoneId": 5, + "statusId": 0 + } + }, + "steps": [ + { + "activities": [ + { + "id": "8081a992-a27d-4a43-984a-d60114ea1025", + "name": "testExisting_dataExtract", + "activityObjectId": "56c5370a-f988-4f36-b0ee-0f876573f6d7", + "objectTypeId": 73, + "displayOrder": 1 + }, + { + "id": "d3774dc2-a271-4a44-8cbe-f630a6d6545e", + "name": "testExisting_emailSend", + "activityObjectId": "9b1c7bf9-4964-ed11-b849-48df37d1de8b", + "objectTypeId": 42, + "displayOrder": 2 + }, + { + "id": "2c77fc42-85eb-4611-98f9-223d29d89d72", + "name": "testExisting_fileTransfer", + "activityObjectId": "72c328ac-f5b0-4e37-91d3-a775666f15a6", + "objectTypeId": 53, + "displayOrder": 3 + }, + { + "id": "298b2794-28cb-4c70-b7ad-58b2c8cf48f7", + "name": "testExisting_importFile", + "activityObjectId": "9d16f42c-2260-ed11-b849-48df37d1de8b", + "objectTypeId": 43, + "displayOrder": 4, + "targetDataExtensions": [ + { + "id": "21711373-72c1-ec11-b83b-48df37d1deb7", + "name": "testExisting_dataExtension", + "key": "testExisting_dataExtension", + "description": "bla bla", + "rowCount": 0 + } + ] + }, + { + "id": "e3774dc2-a271-4a44-8cbe-f630a6d6545e", + "name": "testExisting_query_WRONG_NAME", + "activityObjectId": "549f0568-607c-4940-afef-437965094dat", + "objectTypeId": 300, + "displayOrder": 5 + }, + { + "id": "g3774dc2-a271-4a44-8cbe-f630a6d6545e", + "name": "testExisting_script", + "activityObjectId": "39f6a488-20eb-4ba0-b0b9-023725b574e4", + "objectTypeId": 423, + "displayOrder": 6 + }, + { + "id": "f3774dc2-a271-4a44-8cbe-f630a6d6545e", + "name": "testExisting_dataExtension", + "activityObjectId": "testNew_RANDOM_NEW_GUID", + "objectTypeId": 1000, + "displayOrder": 7 + } + ], + "annotation": "", + "stepNumber": 0 + } + ] +} diff --git a/test/resources/9999999/automation/v1/dataextracts/56c5370a-f988-4f36-b0ee-0f876573f6d7/delete-response.txt b/test/resources/9999999/automation/v1/dataextracts/56c5370a-f988-4f36-b0ee-0f876573f6d7/delete-response.txt new file mode 100644 index 000000000..d86bac9de --- /dev/null +++ b/test/resources/9999999/automation/v1/dataextracts/56c5370a-f988-4f36-b0ee-0f876573f6d7/delete-response.txt @@ -0,0 +1 @@ +OK diff --git a/test/resources/9999999/automation/v1/dataextracts/56c5370a-f988-4f36-b0ee-0f876573f6d7/get-response.json b/test/resources/9999999/automation/v1/dataextracts/56c5370a-f988-4f36-b0ee-0f876573f6d7/get-response.json new file mode 100644 index 000000000..70564f615 --- /dev/null +++ b/test/resources/9999999/automation/v1/dataextracts/56c5370a-f988-4f36-b0ee-0f876573f6d7/get-response.json @@ -0,0 +1,38 @@ +{ + "dataExtractDefinitionId": "56c5370a-f988-4f36-b0ee-0f876573f6d7", + "name": "testExisting_dataExtract", + "key": "testExisting_dataExtract", + "description": "blabla", + "dataExtractTypeId": "bb94a04d-9632-4623-be47-daabc3f588a6", + "fileSpec": "testExisting-%%Year%%-%%Month%%-%%Day%%", + "createdBy": 700301950, + "modifiedBy": 700301950, + "intervalType": 0, + "dataFields": [ + { + "name": "ColumnDelimiter", + "type": "string", + "value": "," + }, + { + "name": "DECustomerKey", + "type": "string", + "value": "testExisting_dataExtension" + }, + { + "name": "HasColumnHeaders", + "type": "bool", + "value": "False" + }, + { + "name": "TextQualified", + "type": "bool", + "value": "False" + }, + { + "name": "UsesLineFeed", + "type": "bool", + "value": "False" + } + ] +} diff --git a/test/resources/9999999/automation/v1/dataextracts/56c5370a-f988-4f36-b0ee-0f876573f6d7/patch-response.json b/test/resources/9999999/automation/v1/dataextracts/56c5370a-f988-4f36-b0ee-0f876573f6d7/patch-response.json new file mode 100644 index 000000000..06f403a7d --- /dev/null +++ b/test/resources/9999999/automation/v1/dataextracts/56c5370a-f988-4f36-b0ee-0f876573f6d7/patch-response.json @@ -0,0 +1,38 @@ +{ + "dataExtractDefinitionId": "56c5370a-f988-4f36-b0ee-0f876573f6d7", + "name": "testExisting_dataExtract", + "key": "testExisting_dataExtract", + "description": "created via deploy", + "dataExtractTypeId": "bb94a04d-9632-4623-be47-daabc3f588a6", + "fileSpec": "testExisting-%%Year%%-%%Month%%-%%Day%%", + "createdBy": 700301950, + "modifiedBy": 700301950, + "intervalType": 0, + "dataFields": [ + { + "name": "ColumnDelimiter", + "type": "string", + "value": "," + }, + { + "name": "DECustomerKey", + "type": "string", + "value": "testExisting_dataExtension" + }, + { + "name": "HasColumnHeaders", + "type": "bool", + "value": "False" + }, + { + "name": "TextQualified", + "type": "bool", + "value": "False" + }, + { + "name": "UsesLineFeed", + "type": "bool", + "value": "False" + } + ] +} diff --git a/test/resources/9999999/automation/v1/dataextracts/get-response.json b/test/resources/9999999/automation/v1/dataextracts/get-response.json new file mode 100644 index 000000000..462a69793 --- /dev/null +++ b/test/resources/9999999/automation/v1/dataextracts/get-response.json @@ -0,0 +1,20 @@ +{ + "count": 1, + "page": 1, + "pageSize": 500, + "items": [ + { + "dataExtractDefinitionId": "56c5370a-f988-4f36-b0ee-0f876573f6d7", + "name": "testExisting_dataExtract", + "key": "testExisting_dataExtract", + "description": "bla bla", + "dataExtractTypeId": "bb94a04d-9632-4623-be47-daabc3f588a6", + "fileSpec": "testExisting-%%Year%%-%%Month%%-%%Day%%", + "createdDate": "2022-11-09T05:31:21.667", + "modifiedDate": "2022-11-17T07:13:36.9", + "createdBy": 700301950, + "modifiedBy": 700301950, + "intervalType": 0 + } + ] +} diff --git a/test/resources/9999999/automation/v1/dataextracts/post-response.json b/test/resources/9999999/automation/v1/dataextracts/post-response.json new file mode 100644 index 000000000..2122c1a82 --- /dev/null +++ b/test/resources/9999999/automation/v1/dataextracts/post-response.json @@ -0,0 +1,38 @@ +{ + "dataExtractDefinitionId": "56c5370a-f988-4f36-b0ee-0f876573f6d7", + "name": "testNew_dataExtract", + "key": "testNew_dataExtract", + "description": "blabla", + "dataExtractTypeId": "bb94a04d-9632-4623-be47-daabc3f588a6", + "fileSpec": "testNew-%%Year%%-%%Month%%-%%Day%%", + "createdBy": 700301950, + "modifiedBy": 700301950, + "intervalType": 0, + "dataFields": [ + { + "name": "ColumnDelimiter", + "type": "string", + "value": "," + }, + { + "name": "DECustomerKey", + "type": "string", + "value": "testExisting_dataExtension" + }, + { + "name": "HasColumnHeaders", + "type": "bool", + "value": "False" + }, + { + "name": "TextQualified", + "type": "bool", + "value": "False" + }, + { + "name": "UsesLineFeed", + "type": "bool", + "value": "False" + } + ] +} diff --git a/test/resources/9999999/automation/v1/dataextracttypes/get-response.json b/test/resources/9999999/automation/v1/dataextracttypes/get-response.json new file mode 100644 index 000000000..ee3cab786 --- /dev/null +++ b/test/resources/9999999/automation/v1/dataextracttypes/get-response.json @@ -0,0 +1,50 @@ +[ + { + "name": "Audit Trail Activity Log", + "extractId": "d804ddf9-feda-4495-8e7e-069a14f5d248" + }, + { + "name": "Zip", + "extractId": "9a487c7d-96bd-484c-ad80-0f0bcbb91ca7" + }, + { + "name": "Tracking Extract", + "extractId": "c7219016-a7f0-4c72-8657-1ec12c28a0db" + }, + { + "name": "Mobile Push Detail Extract Report", + "extractId": "e6647310-ac95-4f32-a639-2a6b145c83f1" + }, + { + "name": "UTF16 to ASCII Converter", + "extractId": "e7e14f95-b925-462d-b6b4-4a6b1dca7ca1" + }, + { + "name": "Contacts Without Channel Addresses", + "extractId": "f2500d28-b3cb-42b9-ad31-361123ec1222" + }, + { + "name": "Convert XML", + "extractId": "805dfb29-82cb-43dc-989b-53ef5d181920" + }, + { + "name": "GZip", + "extractId": "7e7d322a-88ca-499a-9fb3-90e72fcf00af" + }, + { + "name": "XmlToTextMapper", + "extractId": "cf2cd221-fc3c-4d9f-90b4-a4e879a51ab6" + }, + { + "name": "Enhanced FTP File Move and Copy", + "extractId": "90d90e0a-fd9a-4d35-b471-cde0d17c91d4" + }, + { + "name": "Data Extension Extract", + "extractId": "bb94a04d-9632-4623-be47-daabc3f588a6" + }, + { + "name": "Audit Trail Access Log", + "extractId": "382b94bd-bd1b-45e1-864f-eb824841885a" + } +] diff --git a/test/resources/9999999/automation/v1/dataverifications/post-response.json b/test/resources/9999999/automation/v1/dataverifications/post-response.json new file mode 100644 index 000000000..96d88a20e --- /dev/null +++ b/test/resources/9999999/automation/v1/dataverifications/post-response.json @@ -0,0 +1,12 @@ +{ + "dataVerificationDefinitionId": "testNew_RANDOM_NEW_GUID", + "targetObjectId": "21711373-72c1-ec11-b83b-48df37d1deb7", + "verificationType": "IsEqualTo", + "value1": 2, + "value2": 0, + "shouldStopOnFailure": false, + "shouldEmailOnFailure": false, + "notificationEmailAddress": "", + "notificationEmailMessage": "", + "createdBy": 700301950 +} diff --git a/test/resources/9999999/automation/v1/dataverifications/testExisting_39f6a488-20eb-4ba0-b0b9/delete-response.json b/test/resources/9999999/automation/v1/dataverifications/testExisting_39f6a488-20eb-4ba0-b0b9/delete-response.json new file mode 100644 index 000000000..e69de29bb diff --git a/test/resources/9999999/automation/v1/dataverifications/testExisting_39f6a488-20eb-4ba0-b0b9/get-response.json b/test/resources/9999999/automation/v1/dataverifications/testExisting_39f6a488-20eb-4ba0-b0b9/get-response.json new file mode 100644 index 000000000..6b6d4101e --- /dev/null +++ b/test/resources/9999999/automation/v1/dataverifications/testExisting_39f6a488-20eb-4ba0-b0b9/get-response.json @@ -0,0 +1,12 @@ +{ + "dataVerificationDefinitionId": "testExisting_39f6a488-20eb-4ba0-b0b9", + "targetObjectId": "21711373-72c1-ec11-b83b-48df37d1deb7", + "verificationType": "IsEqualTo", + "value1": 1, + "value2": 0, + "shouldStopOnFailure": true, + "shouldEmailOnFailure": false, + "notificationEmailAddress": "", + "notificationEmailMessage": "", + "createdBy": 700301950 +} diff --git a/test/resources/9999999/automation/v1/dataverifications/testExisting_39f6a488-20eb-4ba0-b0b9/patch-response.json b/test/resources/9999999/automation/v1/dataverifications/testExisting_39f6a488-20eb-4ba0-b0b9/patch-response.json new file mode 100644 index 000000000..5d7c8d336 --- /dev/null +++ b/test/resources/9999999/automation/v1/dataverifications/testExisting_39f6a488-20eb-4ba0-b0b9/patch-response.json @@ -0,0 +1,12 @@ +{ + "dataVerificationDefinitionId": "testExisting_39f6a488-20eb-4ba0-b0b9", + "targetObjectId": "21711373-72c1-ec11-b83b-48df37d1deb7", + "verificationType": "IsEqualTo", + "value1": 1, + "value2": 0, + "shouldStopOnFailure": true, + "shouldEmailOnFailure": true, + "notificationEmailAddress": "test@accenture.com", + "notificationEmailMessage": "", + "createdBy": 700301950 +} diff --git a/test/resources/9999999/automation/v1/filetransfers/72c328ac-f5b0-4e37-91d3-a775666f15a6/delete-response.json b/test/resources/9999999/automation/v1/filetransfers/72c328ac-f5b0-4e37-91d3-a775666f15a6/delete-response.json new file mode 100644 index 000000000..0967ef424 --- /dev/null +++ b/test/resources/9999999/automation/v1/filetransfers/72c328ac-f5b0-4e37-91d3-a775666f15a6/delete-response.json @@ -0,0 +1 @@ +{} diff --git a/test/resources/9999999/automation/v1/filetransfers/72c328ac-f5b0-4e37-91d3-a775666f15a6/get-response.json b/test/resources/9999999/automation/v1/filetransfers/72c328ac-f5b0-4e37-91d3-a775666f15a6/get-response.json new file mode 100644 index 000000000..4775efdce --- /dev/null +++ b/test/resources/9999999/automation/v1/filetransfers/72c328ac-f5b0-4e37-91d3-a775666f15a6/get-response.json @@ -0,0 +1,18 @@ +{ + "id": "72c328ac-f5b0-4e37-91d3-a775666f15a6", + "name": "testExisting_fileTransfer", + "description": "17.11.2022", + "customerKey": "testExisting_fileTransfer", + "fileSpec": "%%Year%%", + "isEncrypted": false, + "isCompressed": false, + "maxFileAge": 0, + "maxFileAgeScheduleOffset": 0, + "maxImportFrequency": 0, + "fileTransferLocationId": "41a5ded7-0d98-4910-a15f-d09e7ab0af24", + "isUpload": true, + "isPgp": false, + "isFileSpecLocalized": false, + "createdDate": "2022-11-09T05:31:56.477", + "modifiedDate": "2022-11-17T07:13:20.05" +} diff --git a/test/resources/9999999/automation/v1/filetransfers/72c328ac-f5b0-4e37-91d3-a775666f15a6/patch-response.json b/test/resources/9999999/automation/v1/filetransfers/72c328ac-f5b0-4e37-91d3-a775666f15a6/patch-response.json new file mode 100644 index 000000000..564cd62dc --- /dev/null +++ b/test/resources/9999999/automation/v1/filetransfers/72c328ac-f5b0-4e37-91d3-a775666f15a6/patch-response.json @@ -0,0 +1,18 @@ +{ + "id": "72c328ac-f5b0-4e37-91d3-a775666f15a6", + "name": "testExisting_fileTransfer", + "description": "17.11.2022", + "customerKey": "testExisting_fileTransfer", + "fileSpec": "%%Year%% updated via deploy", + "isEncrypted": false, + "isCompressed": false, + "maxFileAge": 0, + "maxFileAgeScheduleOffset": 0, + "maxImportFrequency": 0, + "fileTransferLocationId": "41a5ded7-0d98-4910-a15f-d09e7ab0af24", + "isUpload": true, + "isPgp": false, + "isFileSpecLocalized": false, + "createdDate": "2022-11-09T05:31:56.477", + "modifiedDate": "2022-11-17T07:13:20.05" +} diff --git a/test/resources/9999999/automation/v1/filetransfers/get-response.json b/test/resources/9999999/automation/v1/filetransfers/get-response.json new file mode 100644 index 000000000..1a925b687 --- /dev/null +++ b/test/resources/9999999/automation/v1/filetransfers/get-response.json @@ -0,0 +1,15 @@ +{ + "page": 1, + "pageSize": 500, + "count": 1, + "items": [ + { + "id": "72c328ac-f5b0-4e37-91d3-a775666f15a6", + "name": "testExisting_fileTransfer", + "description": "17.11.2022", + "customerKey": "testExisting_fileTransfer", + "createdDate": "2022-11-09T05:31:56.477", + "modifiedDate": "2022-11-17T07:13:20.05" + } + ] +} diff --git a/test/resources/9999999/automation/v1/filetransfers/post-response.json b/test/resources/9999999/automation/v1/filetransfers/post-response.json new file mode 100644 index 000000000..d26689236 --- /dev/null +++ b/test/resources/9999999/automation/v1/filetransfers/post-response.json @@ -0,0 +1,18 @@ +{ + "id": "72c328ac-f5b0-4e37-91d3-a775666f15a6", + "name": "testNew_fileTransfer", + "description": "17.11.2022", + "customerKey": "testNew_fileTransfer", + "fileSpec": "%%Year%% created on deploy", + "isEncrypted": false, + "isCompressed": false, + "maxFileAge": 0, + "maxFileAgeScheduleOffset": 0, + "maxImportFrequency": 0, + "fileTransferLocationId": "41a5ded7-0d98-4910-a15f-d09e7ab0af24", + "isUpload": true, + "isPgp": false, + "isFileSpecLocalized": false, + "createdDate": "2022-11-09T05:31:56.477", + "modifiedDate": "2022-11-17T07:13:20.05" +} diff --git a/test/resources/9999999/automation/v1/filters/a0f1a1bc-4ea1-44b3-8fe1-ce40ef35c1c0/patch-response.json b/test/resources/9999999/automation/v1/filters/a0f1a1bc-4ea1-44b3-8fe1-ce40ef35c1c0/patch-response.json new file mode 100644 index 000000000..2b23fe85e --- /dev/null +++ b/test/resources/9999999/automation/v1/filters/a0f1a1bc-4ea1-44b3-8fe1-ce40ef35c1c0/patch-response.json @@ -0,0 +1,18 @@ +{ + "categoryId": 37139, + "customerKey": "testNew_filter", + "description": "created via deploy", + "destinationObjectId": "21711373-72c1-ec11-b83b-exclusion", + "destinationTypeId": 2, + "filterActivityId": "a0f1a1bc-4ea1-44b3-8fe1-ce40ef35c1c0", + "filterDefinitionId": "10ef27dd-4be8-4bf6-970a-8acf8e281e55", + "name": "testNew_filter", + "sourceObjectId": "21711373-72c1-ec11-b83b-48df37d1deb7", + "sourceTypeId": 2, + "statusId": 1, + "resultDEName": "testExisting_dataExtension_exclusion", + "resultDEKey": "testExisting_dataExtension_exclusion", + "resultDEDescription": "", + "createdDate": "2026-02-02T07:34:49.203", + "modifiedDate": "2026-02-02T07:34:49.277" +} diff --git a/test/resources/9999999/automation/v1/filters/f018f237-f7ef-40b0-afc8-39ea2e5dcca4/delete-response.txt b/test/resources/9999999/automation/v1/filters/f018f237-f7ef-40b0-afc8-39ea2e5dcca4/delete-response.txt new file mode 100644 index 000000000..e69de29bb diff --git a/test/resources/9999999/automation/v1/filters/f018f237-f7ef-40b0-afc8-39ea2e5dcca4/get-response.json b/test/resources/9999999/automation/v1/filters/f018f237-f7ef-40b0-afc8-39ea2e5dcca4/get-response.json new file mode 100644 index 000000000..947e117f7 --- /dev/null +++ b/test/resources/9999999/automation/v1/filters/f018f237-f7ef-40b0-afc8-39ea2e5dcca4/get-response.json @@ -0,0 +1,15 @@ +{ + "categoryId": 37139, + "customerKey": "testExisting_filter", + "description": "blabla", + "destinationObjectId": "21711373-72c1-ec11-b83b-exclusion", + "destinationTypeId": 2, + "filterActivityId": "f018f237-f7ef-40b0-afc8-39ea2e5dcca4", + "filterDefinitionId": "10ef27dd-4be8-4bf6-970a-8acf8e281e55", + "name": "testExisting_filter", + "sourceObjectId": "21711373-72c1-ec11-b83b-48df37d1deb7", + "sourceTypeId": 2, + "statusId": 1, + "createdDate": "2025-12-01T17:53:39.163", + "modifiedDate": "2026-01-28T10:14:46.717" +} diff --git a/test/resources/9999999/automation/v1/filters/f018f237-f7ef-40b0-afc8-39ea2e5dcca4/patch-response.json b/test/resources/9999999/automation/v1/filters/f018f237-f7ef-40b0-afc8-39ea2e5dcca4/patch-response.json new file mode 100644 index 000000000..46057adfd --- /dev/null +++ b/test/resources/9999999/automation/v1/filters/f018f237-f7ef-40b0-afc8-39ea2e5dcca4/patch-response.json @@ -0,0 +1,15 @@ +{ + "categoryId": 5319, + "customerKey": "testExisting_filter", + "description": "updated on deploy", + "destinationObjectId": "21711373-72c1-ec11-b83b-exclusion", + "destinationTypeId": 2, + "filterActivityId": "f018f237-f7ef-40b0-afc8-39ea2e5dcca4", + "filterDefinitionId": "10ef27dd-4be8-4bf6-970a-8acf8e281e55", + "name": "testExisting_filter", + "sourceObjectId": "21711373-72c1-ec11-b83b-48df37d1deb7", + "sourceTypeId": 2, + "statusId": 1, + "createdDate": "2025-12-01T17:53:39.163", + "modifiedDate": "2026-01-28T10:14:46.717" +} diff --git a/test/resources/9999999/automation/v1/filters/get-response.json b/test/resources/9999999/automation/v1/filters/get-response.json new file mode 100644 index 000000000..7dbecb2ed --- /dev/null +++ b/test/resources/9999999/automation/v1/filters/get-response.json @@ -0,0 +1,22 @@ +{ + "count": 54, + "page": 1, + "pageSize": 500, + "items": [ + { + "categoryId": 37139, + "customerKey": "testExisting_filter", + "description": "blabla", + "destinationObjectId": "21711373-72c1-ec11-b83b-exclusion", + "destinationTypeId": 2, + "filterActivityId": "f018f237-f7ef-40b0-afc8-39ea2e5dcca4", + "filterDefinitionId": "10ef27dd-4be8-4bf6-970a-8acf8e281e55", + "name": "testExisting_filter", + "sourceObjectId": "21711373-72c1-ec11-b83b-48df37d1deb7", + "sourceTypeId": 2, + "statusId": 1, + "createdDate": "2025-12-01T17:53:39.163", + "modifiedDate": "2026-01-28T10:14:46.717" + } + ] +} diff --git a/test/resources/9999999/automation/v1/ftplocations/get-response.json b/test/resources/9999999/automation/v1/ftplocations/get-response.json new file mode 100644 index 000000000..2f1ceb7ab --- /dev/null +++ b/test/resources/9999999/automation/v1/ftplocations/get-response.json @@ -0,0 +1,43 @@ +{ + "page": 1, + "pageSize": 2, + "count": 5, + "items": [ + { + "name": "Salesforce Objects & Reports", + "id": "a4a0aff9-ddc5-4608-b0e1-40d0a5133d8f", + "locationTypeId": 4 + }, + { + "name": "ExactTarget Enhanced FTP", + "id": "41a5ded7-0d98-4910-a15f-d09e7ab0af24", + "locationTypeId": 0, + "relPath": "ExactTarget Enhanced FTP" + }, + { + "name": "testExisting_fileLocation_gcp_name", + "id": "5fc2cc79-b4fb-465d-bc09-7dacf8afebae", + "locationTypeId": 16, + "locationUrl": "GCP://some-bucket/Task/Activity" + }, + + { + "name": "testExisting_fileLocation_azure_name", + "id": "fff73b41-dced-4a2a-a6cf-430a46a18df6", + "locationTypeId": 15, + "locationUrl": "Azure://container-name/my/path" + }, + { + "name": "testExisting_fileLocation_aws_name", + "id": "62bb39b1-c84f-47b5-98a0-61e5d79b7f31", + "locationTypeId": 13, + "locationUrl": "S3://bucket-name/my/path" + }, + { + "name": "testExisting_fileLocation_exsftp_name", + "id": "335802a4-479d-4834-a491-fc5d2d068132", + "locationTypeId": 2, + "locationUrl": "sftp://test.com" + } + ] +} diff --git a/test/resources/9999999/automation/v1/imports/1ebf557b-372e-eb11-b81b-48df37d1dbd7/get-response.json b/test/resources/9999999/automation/v1/imports/1ebf557b-372e-eb11-b81b-48df37d1dbd7/get-response.json new file mode 100644 index 000000000..87a475ffb --- /dev/null +++ b/test/resources/9999999/automation/v1/imports/1ebf557b-372e-eb11-b81b-48df37d1dbd7/get-response.json @@ -0,0 +1,78 @@ +{ + "allowErrors": true, + "customerKey": "testExisting_importFileSMS", + "createdDate": "2022-11-24T03:29:01.05", + "modifiedDate": "2023-07-19T23:06:33.577", + "dateFormatLocale": "en-US", + "deleteFile": false, + "description": "Unsub for Keyword", + "destinationObjectId": "00000000-0000-0000-0000-000000000000", + "destinationId": 0, + "destinationObjectTypeId": 584, + "fieldMappings": [ + { + "sourceFieldName": "Locale", + "destinationFieldName": "_CountryCode" + }, + { + "sourceFieldName": "FirstName", + "destinationFieldName": "_FirstName" + }, + { + "sourceFieldName": "IsHonorDST", + "destinationFieldName": "_IsHonorDST" + }, + { + "sourceFieldName": "LastName", + "destinationFieldName": "_LastName" + }, + { + "sourceFieldName": "MobileNumber", + "destinationFieldName": "_MobileNumber" + }, + { + "sourceFieldName": "Status", + "destinationFieldName": "_Status" + }, + { + "sourceFieldName": "ContactKey", + "destinationFieldName": "_SubscriberKey" + }, + { + "sourceFieldName": "UTCoffset", + "destinationFieldName": "_UTCOffset" + }, + { + "sourceFieldName": "Action", + "destinationFieldName": "Action" + }, + { + "sourceFieldName": "ModifiedDate", + "destinationFieldName": "SalesforceModified" + }, + { + "sourceFieldName": "SFContactID", + "destinationFieldName": "SFContactID" + } + ], + "fieldMappingType": "ManualMap", + "fileNamingPattern": "_CustomObject", + "fileTransferLocationId": "41a5ded7-0d98-4910-a15f-d09e7ab0af24", + "fileTransferLocationName": "ExactTarget Enhanced FTP", + "fileType": "CSV", + "filter": "", + "hasColumnHeader": true, + "importDefinitionId": "1ebf557b-372e-eb11-b81b-48df37d1dbd7", + "isOrderedImport": false, + "isSequential": true, + "maxFileAgeHours": 0, + "maxImportFrequencyHours": 0, + "maxFileAgeScheduleOffsetHours": 0, + "name": "testExisting_importFileSMS", + "notificationEmailAddress": "joern.berkefeld@accenture.com", + "sendEmailNotification": true, + "standardQuotedStrings": false, + "subscriberImportTypeId": 255, + "updateTypeId": 0, + "fileTransferLocationTypeId": 0 +} diff --git a/test/resources/9999999/automation/v1/imports/9d16f42c-2260-ed11-b849-48df37d1de8b/delete-response.txt b/test/resources/9999999/automation/v1/imports/9d16f42c-2260-ed11-b849-48df37d1de8b/delete-response.txt new file mode 100644 index 000000000..e69de29bb diff --git a/test/resources/9999999/automation/v1/imports/9d16f42c-2260-ed11-b849-48df37d1de8b/get-response.json b/test/resources/9999999/automation/v1/imports/9d16f42c-2260-ed11-b849-48df37d1de8b/get-response.json new file mode 100644 index 000000000..9e443db63 --- /dev/null +++ b/test/resources/9999999/automation/v1/imports/9d16f42c-2260-ed11-b849-48df37d1de8b/get-response.json @@ -0,0 +1,35 @@ +{ + "allowErrors": true, + "customerKey": "testExisting_importFile", + "createdDate": "2022-11-09T05:32:30.533", + "modifiedDate": "2022-11-17T07:13:03.95", + "dateFormatLocale": "en-US", + "deleteFile": false, + "description": "17.11.2022", + "destinationObjectId": "21711373-72c1-ec11-b83b-48df37d1deb7", + "destinationId": 0, + "destinationObjectTypeId": 310, + "destinationName": "testExisting_dataExtension", + "encodingName": "utf-8", + "fieldMappings": [], + "fieldMappingType": "InferFromColumnHeadings", + "fileNamingPattern": "blabla", + "fileTransferLocationId": "41a5ded7-0d98-4910-a15f-d09e7ab0af24", + "fileTransferLocationName": "ExactTarget Enhanced FTP", + "fileType": "CSV", + "filter": "", + "hasColumnHeader": true, + "importDefinitionId": "9d16f42c-2260-ed11-b849-48df37d1de8b", + "isOrderedImport": true, + "isSequential": true, + "maxFileAgeHours": 0, + "maxImportFrequencyHours": 0, + "maxFileAgeScheduleOffsetHours": 0, + "name": "testExisting_importFile", + "sendEmailNotification": false, + "standardQuotedStrings": true, + "subscriberImportTypeId": 255, + "updateTypeId": 0, + "fileTransferLocationTypeId": 0, + "blankFileProcessingType": 2 +} diff --git a/test/resources/9999999/automation/v1/imports/9d16f42c-2260-ed11-b849-48df37d1de8b/patch-response.json b/test/resources/9999999/automation/v1/imports/9d16f42c-2260-ed11-b849-48df37d1de8b/patch-response.json new file mode 100644 index 000000000..be6e10946 --- /dev/null +++ b/test/resources/9999999/automation/v1/imports/9d16f42c-2260-ed11-b849-48df37d1de8b/patch-response.json @@ -0,0 +1,35 @@ +{ + "allowErrors": true, + "customerKey": "testExisting_importFile", + "createdDate": "2022-11-09T05:32:30.533", + "modifiedDate": "2023-07-18T09:11:26.19", + "dateFormatLocale": "en-US", + "deleteFile": false, + "description": "updated on deploy", + "destinationObjectId": "21711373-72c1-ec11-b83b-48df37d1deb7", + "destinationId": 0, + "destinationObjectTypeId": 310, + "destinationName": "testExisting_dataExtension", + "encodingName": "utf-8", + "fieldMappings": [], + "fieldMappingType": "InferFromColumnHeadings", + "fileNamingPattern": "blabla", + "fileTransferLocationId": "41a5ded7-0d98-4910-a15f-d09e7ab0af24", + "fileTransferLocationName": "ExactTarget Enhanced FTP", + "fileType": "CSV", + "filter": "", + "hasColumnHeader": true, + "importDefinitionId": "9d16f42c-2260-ed11-b849-48df37d1de8b", + "isOrderedImport": true, + "isSequential": true, + "maxFileAgeHours": 0, + "maxImportFrequencyHours": 0, + "maxFileAgeScheduleOffsetHours": 0, + "name": "testExisting_importFile", + "sendEmailNotification": false, + "standardQuotedStrings": true, + "subscriberImportTypeId": 255, + "updateTypeId": 0, + "fileTransferLocationTypeId": 0, + "blankFileProcessingType": 1 +} diff --git a/test/resources/9999999/automation/v1/imports/d2474efb-a449-ef11-b876-f40343c95928/get-response.json b/test/resources/9999999/automation/v1/imports/d2474efb-a449-ef11-b876-f40343c95928/get-response.json new file mode 100644 index 000000000..f88d4b83f --- /dev/null +++ b/test/resources/9999999/automation/v1/imports/d2474efb-a449-ef11-b876-f40343c95928/get-response.json @@ -0,0 +1,37 @@ +{ + "allowErrors": true, + "customerKey": "testExisting_importFileDataImport", + "createdDate": "2024-07-24T04:10:42.15", + "modifiedDate": "2024-07-24T04:10:42.15", + "dateFormatLocale": "en-US", + "deleteFile": false, + "destinationObjectId": "1c8064d5-6502-ef11-a5c8-5cba2c702db8", + "destinationId": 0, + "destinationObjectTypeId": 310, + "destinationName": "importFileTestB", + "encodingName": "utf-8", + "fieldMappings": [], + "fieldMappingType": "InferFromColumnHeadings", + "fileNamingPattern": "_CustomObject", + "fileSpec": "_CustomObject", + "fileTransferLocationId": "41a5ded7-0d98-4910-a15f-d09e7ab0af24", + "fileTransferLocationName": "ExactTarget Enhanced FTP", + "fileType": "CSV", + "filter": "", + "hasColumnHeader": true, + "importDefinitionId": "d2474efb-a449-ef11-b876-f40343c95928", + "isOrderedImport": true, + "isSequential": true, + "maxFileAgeHours": 0, + "maxImportFrequencyHours": 0, + "maxFileAgeScheduleOffsetHours": 0, + "name": "testExisting_importFileDataImport", + "sendEmailNotification": false, + "sourceCustomObjectId": "21711373-72c1-ec11-b83b-48df37d1deb7", + "sourceDataExtensionName": "testExisting_dataExtension", + "standardQuotedStrings": true, + "subscriberImportTypeId": 255, + "updateTypeId": 4, + "fileTransferLocationTypeId": 0, + "blankFileProcessingType": 0 +} diff --git a/test/resources/9999999/automation/v1/imports/get-response.json b/test/resources/9999999/automation/v1/imports/get-response.json new file mode 100644 index 000000000..1e44eb86d --- /dev/null +++ b/test/resources/9999999/automation/v1/imports/get-response.json @@ -0,0 +1,146 @@ +{ + "page": 1, + "pageSize": 500, + "count": 3, + "items": [ + { + "allowErrors": true, + "customerKey": "testExisting_importFile", + "createdDate": "2022-11-09T05:32:30.533", + "modifiedDate": "2022-11-17T07:13:03.95", + "dateFormatLocale": "en-US", + "deleteFile": false, + "description": "17.11.2022", + "destinationObjectId": "21711373-72c1-ec11-b83b-48df37d1deb7", + "destinationId": 0, + "destinationObjectTypeId": 310, + "fieldMappings": [], + "fieldMappingType": "InferFromColumnHeadings", + "fileNamingPattern": "blabla", + "fileTransferLocationId": "41a5ded7-0d98-4910-a15f-d09e7ab0af24", + "fileType": "CSV", + "filter": "", + "hasColumnHeader": true, + "importDefinitionId": "9d16f42c-2260-ed11-b849-48df37d1de8b", + "isOrderedImport": true, + "isSequential": true, + "maxFileAgeHours": 0, + "maxImportFrequencyHours": 0, + "maxFileAgeScheduleOffsetHours": 0, + "name": "testExisting_importFile", + "sendEmailNotification": false, + "standardQuotedStrings": true, + "subscriberImportTypeId": 255, + "updateTypeId": 0, + "fileTransferLocationTypeId": 0 + }, + { + "allowErrors": true, + "customerKey": "testExisting_importFileSMS", + "createdDate": "2022-11-24T03:29:01.05", + "modifiedDate": "2023-07-19T23:06:33.577", + "dateFormatLocale": "en-US", + "deleteFile": false, + "description": "Unsub for Keyword", + "destinationObjectId": "00000000-0000-0000-0000-000000000000", + "destinationId": 0, + "destinationObjectTypeId": 584, + "fieldMappings": [ + { + "sourceFieldName": "Locale", + "destinationFieldName": "_CountryCode" + }, + { + "sourceFieldName": "FirstName", + "destinationFieldName": "_FirstName" + }, + { + "sourceFieldName": "IsHonorDST", + "destinationFieldName": "_IsHonorDST" + }, + { + "sourceFieldName": "LastName", + "destinationFieldName": "_LastName" + }, + { + "sourceFieldName": "MobileNumber", + "destinationFieldName": "_MobileNumber" + }, + { + "sourceFieldName": "Status", + "destinationFieldName": "_Status" + }, + { + "sourceFieldName": "ContactKey", + "destinationFieldName": "_SubscriberKey" + }, + { + "sourceFieldName": "UTCoffset", + "destinationFieldName": "_UTCOffset" + }, + { + "sourceFieldName": "Action", + "destinationFieldName": "Action" + }, + { + "sourceFieldName": "ModifiedDate", + "destinationFieldName": "SalesforceModified" + }, + { + "sourceFieldName": "SFContactID", + "destinationFieldName": "SFContactID" + } + ], + "fieldMappingType": "ManualMap", + "fileNamingPattern": "_CustomObject", + "fileTransferLocationId": "41a5ded7-0d98-4910-a15f-d09e7ab0af24", + "fileType": "CSV", + "filter": "", + "hasColumnHeader": true, + "importDefinitionId": "1ebf557b-372e-eb11-b81b-48df37d1dbd7", + "isOrderedImport": false, + "isSequential": true, + "maxFileAgeHours": 0, + "maxImportFrequencyHours": 0, + "maxFileAgeScheduleOffsetHours": 0, + "name": "testExisting_importFileSMS", + "notificationEmailAddress": "joern.berkefeld@accenture.com", + "sendEmailNotification": true, + "standardQuotedStrings": false, + "subscriberImportTypeId": 255, + "updateTypeId": 0, + "fileTransferLocationTypeId": 0 + }, + { + "allowErrors": true, + "customerKey": "testExisting_importFileDataImport", + "createdDate": "2024-07-24T04:10:42.15", + "modifiedDate": "2024-07-24T04:10:42.15", + "dateFormatLocale": "en-US", + "deleteFile": false, + "destinationObjectId": "bf4f1d9b-a349-ef11-b876-f40343c95928", + "destinationId": 0, + "destinationObjectTypeId": 310, + "fieldMappings": [], + "fieldMappingType": "InferFromColumnHeadings", + "fileNamingPattern": "_CustomObject", + "fileSpec": "_CustomObject", + "fileTransferLocationId": "527eeab5-fd9e-4a2d-ad38-f3c856ea2031", + "fileType": "CSV", + "filter": "", + "hasColumnHeader": true, + "importDefinitionId": "d2474efb-a449-ef11-b876-f40343c95928", + "isOrderedImport": true, + "isSequential": true, + "maxFileAgeHours": 0, + "maxImportFrequencyHours": 0, + "maxFileAgeScheduleOffsetHours": 0, + "name": "testExisting_importFileDataImport", + "sendEmailNotification": false, + "standardQuotedStrings": true, + "subscriberImportTypeId": 255, + "updateTypeId": 4, + "fileTransferLocationTypeId": 0 + } + ] +} diff --git a/test/resources/9999999/automation/v1/imports/post-response.json b/test/resources/9999999/automation/v1/imports/post-response.json new file mode 100644 index 000000000..7f8ce56ec --- /dev/null +++ b/test/resources/9999999/automation/v1/imports/post-response.json @@ -0,0 +1,30 @@ +{ + "allowErrors": true, + "customerKey": "testNew_importFile", + "dateFormatLocale": "en-US", + "deleteFile": false, + "description": "created via deploy", + "fieldMappingType": "InferFromColumnHeadings", + "fieldMappings": [], + "fileNamingPattern": "blabla", + "fileTransferLocationTypeId": 0, + "fileType": "CSV", + "filter": "", + "hasColumnHeader": true, + "isOrderedImport": true, + "isSequential": true, + "maxFileAgeHours": 0, + "maxFileAgeScheduleOffsetHours": 0, + "maxImportFrequencyHours": 0, + "name": "testNew_importFile", + "sendEmailNotification": false, + "standardQuotedStrings": true, + "fileTransferLocationId": "41a5ded7-0d98-4910-a15f-d09e7ab0af24", + "destinationObjectId": "21711373-72c1-ec11-b83b-48df37d1deb7", + "destinationObjectTypeId": 310, + "subscriberImportTypeId": 255, + "updateTypeId": 0, + "createdDate": "2022-11-09T05:53:03.243", + "destinationId": 0, + "modifiedDate": "2023-07-18T09:11:26.19" +} diff --git a/test/resources/9999999/automation/v1/queries/549f0568-607c-4940-afef-437965094dae/actions/start/post-response.txt b/test/resources/9999999/automation/v1/queries/549f0568-607c-4940-afef-437965094dae/actions/start/post-response.txt new file mode 100644 index 000000000..a0aba9318 --- /dev/null +++ b/test/resources/9999999/automation/v1/queries/549f0568-607c-4940-afef-437965094dae/actions/start/post-response.txt @@ -0,0 +1 @@ +OK \ No newline at end of file diff --git a/test/resources/9999999/automation/v1/queries/549f0568-607c-4940-afef-437965094dat/actions/start/post-response.txt b/test/resources/9999999/automation/v1/queries/549f0568-607c-4940-afef-437965094dat/actions/start/post-response.txt new file mode 100644 index 000000000..a0aba9318 --- /dev/null +++ b/test/resources/9999999/automation/v1/queries/549f0568-607c-4940-afef-437965094dat/actions/start/post-response.txt @@ -0,0 +1 @@ +OK \ No newline at end of file diff --git a/test/resources/9999999/automation/v1/queries/549f0568-607c-4940-afef-437965094dat/delete-response.json b/test/resources/9999999/automation/v1/queries/549f0568-607c-4940-afef-437965094dat/delete-response.json new file mode 100644 index 000000000..11e42d082 --- /dev/null +++ b/test/resources/9999999/automation/v1/queries/549f0568-607c-4940-afef-437965094dat/delete-response.json @@ -0,0 +1 @@ +"OK" diff --git a/test/resources/9999999/automation/v1/queries/549f0568-607c-4940-afef-437965094dat/get-response.json b/test/resources/9999999/automation/v1/queries/549f0568-607c-4940-afef-437965094dat/get-response.json new file mode 100644 index 000000000..32aa90a8c --- /dev/null +++ b/test/resources/9999999/automation/v1/queries/549f0568-607c-4940-afef-437965094dat/get-response.json @@ -0,0 +1,17 @@ +{ + "queryDefinitionId": "549f0568-607c-4940-afef-437965094dat", + "name": "testExisting_query", + "key": "testExisting_query", + "description": "bla bla", + "queryText": "Select\n SubscriberKey as testField, Trim(last_name) AS name\nFrom\n _Subscribers\nwhere\n country in ('test')\n", + "targetName": "testExisting_dataExtension", + "targetKey": "testExisting_dataExtension", + "targetId": "21711373-72c1-ec11-b83b-48df37d1deb7", + "targetDescription": "", + "createdDate": "2022-04-26T15:21:16.453", + "modifiedDate": "2022-04-26T16:02:44.01", + "targetUpdateTypeId": 0, + "targetUpdateTypeName": "Overwrite", + "categoryId": 999, + "isFrozen": false +} diff --git a/test/resources/9999999/automation/v1/queries/549f0568-607c-4940-afef-437965094dat/patch-response.json b/test/resources/9999999/automation/v1/queries/549f0568-607c-4940-afef-437965094dat/patch-response.json new file mode 100644 index 000000000..6414f11dc --- /dev/null +++ b/test/resources/9999999/automation/v1/queries/549f0568-607c-4940-afef-437965094dat/patch-response.json @@ -0,0 +1,18 @@ +{ + "queryDefinitionId": "549f0568-607c-4940-afef-437965094dat", + "name": "testExisting_query", + "key": "testExisting_query", + "description": "updated on deploy", + "queryText": "SELECT\n SubscriberKey as testField\nFROM\n _Subscribers\nWHERE\n country IN ('test')\n", + "targetName": "testExisting_dataExtension", + "targetKey": "testExisting_dataExtension", + "targetId": "21711373-72c1-ec11-b83b-48df37d1deb7", + "targetDescription": "", + "createdDate": "2022-04-26T15:21:16.453", + "modifiedDate": "2022-04-26T16:04:15.88", + "targetUpdateTypeId": 0, + "targetUpdateTypeName": "Overwrite", + "validatedQueryText": "SET NOCOUNT ON; SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;\r\n\r\nINSERT INTO C518001158.[testDataExtension] ([testField])\r\nSELECT querydef.[testField]\r\nFROM (SELECT SubscriberKey as testField FROM C518001158._Subscribers ) AS querydef \r\nSELECT @rcInsert = @@ROWCOUNT;;\r\n", + "categoryId": 999, + "isFrozen": false +} diff --git a/test/resources/9999999/automation/v1/queries/549f0568-607c-4940-afef-437965094dat_fixKeys/get-response.json b/test/resources/9999999/automation/v1/queries/549f0568-607c-4940-afef-437965094dat_fixKeys/get-response.json new file mode 100644 index 000000000..5f481344a --- /dev/null +++ b/test/resources/9999999/automation/v1/queries/549f0568-607c-4940-afef-437965094dat_fixKeys/get-response.json @@ -0,0 +1,17 @@ +{ + "queryDefinitionId": "549f0568-607c-4940-afef-437965094dat_fixKeys", + "name": "testExisting_query_fixedKeys", + "key": "testExisting_query_fixKeys", + "description": "bla bla", + "queryText": "SELECT\n SubscriberKey as testField\nFROM\n _Subscribers\nWHERE\n country IN ('test')\n", + "targetName": "testExisting_dataExtension", + "targetKey": "testExisting_dataExtension", + "targetId": "21711373-72c1-ec11-b83b-48df37d1deb7", + "targetDescription": "", + "createdDate": "2022-04-26T15:21:16.453", + "modifiedDate": "2022-04-26T16:02:44.01", + "targetUpdateTypeId": 0, + "targetUpdateTypeName": "Overwrite", + "categoryId": 999, + "isFrozen": false +} diff --git a/test/resources/9999999/automation/v1/queries/549f0568-607c-4940-afef-437965094dat_fixKeys/patch-response.json b/test/resources/9999999/automation/v1/queries/549f0568-607c-4940-afef-437965094dat_fixKeys/patch-response.json new file mode 100644 index 000000000..599678503 --- /dev/null +++ b/test/resources/9999999/automation/v1/queries/549f0568-607c-4940-afef-437965094dat_fixKeys/patch-response.json @@ -0,0 +1,18 @@ +{ + "queryDefinitionId": "549f0568-607c-4940-afef-437965094dat_fixKeys", + "name": "testExisting_query_fixedKeys", + "key": "testExisting_query_fixedKeys", + "description": "updated on deploy", + "queryText": "SELECT\n SubscriberKey as testField\nFROM\n _Subscribers\nWHERE\n country IN ('test')\n", + "targetName": "testExisting_dataExtension", + "targetKey": "testExisting_dataExtension", + "targetId": "21711373-72c1-ec11-b83b-48df37d1deb7", + "targetDescription": "", + "createdDate": "2022-04-26T15:21:16.453", + "modifiedDate": "2022-04-26T16:04:15.88", + "targetUpdateTypeId": 0, + "targetUpdateTypeName": "Overwrite", + "validatedQueryText": "SET NOCOUNT ON; SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;\r\n\r\nINSERT INTO C518001158.[testDataExtension] ([testField])\r\nSELECT querydef.[testField]\r\nFROM (SELECT SubscriberKey as testField FROM C518001158._Subscribers ) AS querydef \r\nSELECT @rcInsert = @@ROWCOUNT;;\r\n", + "categoryId": 999, + "isFrozen": false +} diff --git a/test/resources/9999999/automation/v1/queries/549f0568-607c-4940-afef-437965094dat_fixKeysSuffix/get-response.json b/test/resources/9999999/automation/v1/queries/549f0568-607c-4940-afef-437965094dat_fixKeysSuffix/get-response.json new file mode 100644 index 000000000..32a65b117 --- /dev/null +++ b/test/resources/9999999/automation/v1/queries/549f0568-607c-4940-afef-437965094dat_fixKeysSuffix/get-response.json @@ -0,0 +1,17 @@ +{ + "queryDefinitionId": "549f0568-607c-4940-afef-437965094dat_fixKeysSuffix", + "name": "testExisting_query_fixedKeysSuffix", + "key": "testExisting_query_fixKeysSuffix", + "description": "bla bla", + "queryText": "Select\n SubscriberKey as testField, Trim(last_name) AS name\nfrom\n _Subscribers\nwhere\n country in ('test')\n", + "targetName": "testExisting_dataExtension", + "targetKey": "testExisting_dataExtension", + "targetId": "21711373-72c1-ec11-b83b-48df37d1deb7", + "targetDescription": "", + "createdDate": "2022-04-26T15:21:16.453", + "modifiedDate": "2022-04-26T16:02:44.01", + "targetUpdateTypeId": 0, + "targetUpdateTypeName": "Overwrite", + "categoryId": 999, + "isFrozen": false +} diff --git a/test/resources/9999999/automation/v1/queries/549f0568-607c-4940-afef-437965094dat_fixKeysSuffix/patch-response.json b/test/resources/9999999/automation/v1/queries/549f0568-607c-4940-afef-437965094dat_fixKeysSuffix/patch-response.json new file mode 100644 index 000000000..909157933 --- /dev/null +++ b/test/resources/9999999/automation/v1/queries/549f0568-607c-4940-afef-437965094dat_fixKeysSuffix/patch-response.json @@ -0,0 +1,18 @@ +{ + "queryDefinitionId": "549f0568-607c-4940-afef-437965094dat_fixKeys", + "name": "testExisting_query_fixedKeysSuffix", + "key": "testExisting_query_fixedKeysSuff_DEV", + "description": "updated on deploy", + "queryText": "SELECT\n SubscriberKey as testField\nFROM\n _Subscribers\nWHERE\n country IN ('test')\n", + "targetName": "testExisting_dataExtension", + "targetKey": "testExisting_dataExtension", + "targetId": "21711373-72c1-ec11-b83b-48df37d1deb7", + "targetDescription": "", + "createdDate": "2022-04-26T15:21:16.453", + "modifiedDate": "2022-04-26T16:04:15.88", + "targetUpdateTypeId": 0, + "targetUpdateTypeName": "Overwrite", + "validatedQueryText": "SET NOCOUNT ON; SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;\r\n\r\nINSERT INTO C518001158.[testDataExtension] ([testField])\r\nSELECT querydef.[testField]\r\nFROM (SELECT SubscriberKey as testField FROM C518001158._Subscribers ) AS querydef \r\nSELECT @rcInsert = @@ROWCOUNT;;\r\n", + "categoryId": 999, + "isFrozen": false +} diff --git a/test/resources/9999999/automation/v1/queries/abcde-607c-4940-afef-437965094dat/get-response.json b/test/resources/9999999/automation/v1/queries/abcde-607c-4940-afef-437965094dat/get-response.json new file mode 100644 index 000000000..9487f867d --- /dev/null +++ b/test/resources/9999999/automation/v1/queries/abcde-607c-4940-afef-437965094dat/get-response.json @@ -0,0 +1,17 @@ +{ + "queryDefinitionId": "abcde-607c-4940-afef-437965094dat", + "name": "testExisting_query2", + "key": "testExisting_query2", + "description": "bla bla", + "queryText": "Select\n SubscriberKey as testField, Trim(last_name) AS name\nfrom\n _Subscribers\nwhere\n country in ('test')\n", + "targetName": "testExisting_dataExtension", + "targetKey": "testExisting_dataExtension-WRONG", + "targetId": "21711373-72c1-ec11-b83b-48df37d1deb7", + "targetDescription": "", + "createdDate": "2022-04-26T15:21:16.453", + "modifiedDate": "2022-04-26T16:02:44.01", + "targetUpdateTypeId": 0, + "targetUpdateTypeName": "Overwrite", + "categoryId": 999, + "isFrozen": false +} diff --git a/test/resources/9999999/automation/v1/queries/get-response-Name=testExisting_query.json b/test/resources/9999999/automation/v1/queries/get-response-Name=testExisting_query.json new file mode 100644 index 000000000..6e61075f0 --- /dev/null +++ b/test/resources/9999999/automation/v1/queries/get-response-Name=testExisting_query.json @@ -0,0 +1,24 @@ +{ + "count": 1, + "page": 1, + "pageSize": 50, + "items": [ + { + "queryDefinitionId": "549f0568-607c-4940-afef-437965094dat", + "name": "testExisting_query", + "key": "testExisting_query", + "description": "bla bla", + "queryText": "Select\n SubscriberKey as testField, Trim(last_name) AS name\nFrom\n _Subscribers\nwhere\n country in ('test')\n", + "targetName": "testExisting_dataExtension", + "targetKey": "testExisting_dataExtension", + "targetId": "21711373-72c1-ec11-b83b-48df37d1deb7", + "targetDescription": "", + "createdDate": "2022-04-26T15:21:16.453", + "modifiedDate": "2022-04-26T16:02:44.01", + "targetUpdateTypeId": 0, + "targetUpdateTypeName": "Overwrite", + "categoryId": 999, + "isFrozen": false + } + ] +} diff --git a/test/resources/9999999/automation/v1/queries/get-response.json b/test/resources/9999999/automation/v1/queries/get-response.json new file mode 100644 index 000000000..ddfab04e6 --- /dev/null +++ b/test/resources/9999999/automation/v1/queries/get-response.json @@ -0,0 +1,75 @@ +{ + "count": 3, + "page": 1, + "pageSize": 50, + "items": [ + { + "queryDefinitionId": "549f0568-607c-4940-afef-437965094dat", + "name": "testExisting_query", + "key": "testExisting_query", + "description": "bla bla", + "queryText": "Select\n SubscriberKey as testField, Trim(last_name) AS name\nFrom\n _Subscribers\nwhere\n country in ('test')\n", + "targetName": "testExisting_dataExtension", + "targetKey": "testExisting_dataExtension", + "targetId": "21711373-72c1-ec11-b83b-48df37d1deb7", + "targetDescription": "", + "createdDate": "2022-04-26T15:21:16.453", + "modifiedDate": "2022-04-26T16:02:44.01", + "targetUpdateTypeId": 0, + "targetUpdateTypeName": "Overwrite", + "categoryId": 999, + "isFrozen": false + }, + { + "queryDefinitionId": "abcde-607c-4940-afef-437965094dat", + "name": "testExisting_query2", + "key": "testExisting_query2", + "description": "bla bla", + "queryText": "Select\n SubscriberKey as testField, Trim(last_name) AS name\nfrom\n _Subscribers\nwhere\n country in ('test')\n", + "targetName": "testExisting_dataExtension", + "targetKey": "testExisting_dataExtension-WRONG", + "targetId": "21711373-72c1-ec11-b83b-48df37d1deb7", + "targetDescription": "", + "createdDate": "2022-04-26T15:21:16.453", + "modifiedDate": "2022-04-26T16:02:44.01", + "targetUpdateTypeId": 0, + "targetUpdateTypeName": "Overwrite", + "categoryId": 999, + "isFrozen": false + }, + { + "queryDefinitionId": "549f0568-607c-4940-afef-437965094dat_fixKeys", + "name": "testExisting_query_fixedKeys", + "key": "testExisting_query_fixKeys", + "description": "bla bla", + "queryText": "Select\n SubscriberKey as testField, Trim(last_name) AS name\nfrom\n _Subscribers\nwhere\n country in ('test')\n", + "targetName": "testExisting_dataExtension", + "targetKey": "testExisting_dataExtension", + "targetId": "21711373-72c1-ec11-b83b-48df37d1deb7", + "targetDescription": "", + "createdDate": "2022-04-26T15:21:16.453", + "modifiedDate": "2022-04-26T16:02:44.01", + "targetUpdateTypeId": 0, + "targetUpdateTypeName": "Overwrite", + "categoryId": 999, + "isFrozen": false + }, + { + "queryDefinitionId": "549f0568-607c-4940-afef-437965094dat_fixKeysSuffix", + "name": "testExisting_query_fixedKeysSuffix", + "key": "testExisting_query_fixKeysSuffix", + "description": "bla bla", + "queryText": "Select\n SubscriberKey as testField, Trim(last_name) AS name\nfrom\n _Subscribers\nwhere\n country in ('test')\n", + "targetName": "testExisting_dataExtension", + "targetKey": "testExisting_dataExtension", + "targetId": "21711373-72c1-ec11-b83b-48df37d1deb7", + "targetDescription": "", + "createdDate": "2022-04-26T15:21:16.453", + "modifiedDate": "2022-04-26T16:02:44.01", + "targetUpdateTypeId": 0, + "targetUpdateTypeName": "Overwrite", + "categoryId": 999, + "isFrozen": false + } + ] +} diff --git a/test/resources/9999999/automation/v1/queries/post-response.json b/test/resources/9999999/automation/v1/queries/post-response.json new file mode 100644 index 000000000..e809ffc3a --- /dev/null +++ b/test/resources/9999999/automation/v1/queries/post-response.json @@ -0,0 +1,18 @@ +{ + "queryDefinitionId": "549f0568-607c-4940-afef-437965094dae", + "name": "testNew_query", + "key": "testNew_query", + "description": "created on deploy", + "queryText": "SELECT\n SubscriberKey as testField\nFROM\n _Subscribers\n", + "targetName": "testExisting_dataExtension", + "targetKey": "testExisting_dataExtension", + "targetId": "21711373-72c1-ec11-b83b-48df37d1deb7", + "targetDescription": "", + "createdDate": "2022-04-26T15:21:16.453", + "modifiedDate": "2022-04-26T16:04:15.88", + "targetUpdateTypeId": 0, + "targetUpdateTypeName": "Overwrite", + "validatedQueryText": "SET NOCOUNT ON; SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;\r\n\r\nINSERT INTO C518001158.[testDataExtension] ([testField])\r\nSELECT querydef.[testField]\r\nFROM (SELECT SubscriberKey as testField FROM C518001158._Subscribers ) AS querydef \r\nSELECT @rcInsert = @@ROWCOUNT;;\r\n", + "categoryId": 999, + "isFrozen": false +} diff --git a/test/resources/9999999/automation/v1/scripts/39f6a488-20eb-4ba0-b0b9-023725b574e4/delete-response.txt b/test/resources/9999999/automation/v1/scripts/39f6a488-20eb-4ba0-b0b9-023725b574e4/delete-response.txt new file mode 100644 index 000000000..d86bac9de --- /dev/null +++ b/test/resources/9999999/automation/v1/scripts/39f6a488-20eb-4ba0-b0b9-023725b574e4/delete-response.txt @@ -0,0 +1 @@ +OK diff --git a/test/resources/9999999/automation/v1/scripts/39f6a488-20eb-4ba0-b0b9-023725b574e4/get-response.json b/test/resources/9999999/automation/v1/scripts/39f6a488-20eb-4ba0-b0b9-023725b574e4/get-response.json new file mode 100644 index 000000000..bffec43f9 --- /dev/null +++ b/test/resources/9999999/automation/v1/scripts/39f6a488-20eb-4ba0-b0b9-023725b574e4/get-response.json @@ -0,0 +1,10 @@ +{ + "ssjsActivityId": "39f6a488-20eb-4ba0-b0b9-023725b574e4", + "name": "testExisting_script", + "key": "testExisting_script", + "description": "updated on deploy", + "script": "<script runat=\"server\">\n// dummy updated\n</script>", + "categoryId": 304, + "createdDate": "2022-10-20T00:41:26.163", + "modifiedDate": "2022-10-20T00:41:26.163" +} diff --git a/test/resources/9999999/automation/v1/scripts/39f6a488-20eb-4ba0-b0b9-023725b574e4/patch-response.json b/test/resources/9999999/automation/v1/scripts/39f6a488-20eb-4ba0-b0b9-023725b574e4/patch-response.json new file mode 100644 index 000000000..db52312e7 --- /dev/null +++ b/test/resources/9999999/automation/v1/scripts/39f6a488-20eb-4ba0-b0b9-023725b574e4/patch-response.json @@ -0,0 +1,10 @@ +{ + "ssjsActivityId": "39f6a488-20eb-4ba0-b0b9-023725b574e4", + "name": "testExisting_script", + "key": "testExisting_script", + "description": "updated on deploy", + "script": "<script runat=\"server\">\n// dummy updated\n</script>", + "categoryId": 304, + "createdDate": "0001-01-01T00:00:00", + "modifiedDate": "0001-01-01T00:00:00" +} diff --git a/test/resources/9999999/automation/v1/scripts/get-response-name=testExisting_script.json b/test/resources/9999999/automation/v1/scripts/get-response-name=testExisting_script.json new file mode 100644 index 000000000..b2aee3357 --- /dev/null +++ b/test/resources/9999999/automation/v1/scripts/get-response-name=testExisting_script.json @@ -0,0 +1,17 @@ +{ + "count": 1, + "page": 1, + "pageSize": 500, + "items": [ + { + "ssjsActivityId": "39f6a488-20eb-4ba0-b0b9-023725b574e4", + "name": "testExisting_script", + "key": "testExisting_script", + "description": "", + "script": " <script runat=\"server\">\n//dummy\n</script>", + "categoryId": 304, + "createdDate": "2022-10-20T00:41:26.163", + "modifiedDate": "2022-10-20T00:41:26.163" + } + ] +} diff --git a/test/resources/9999999/automation/v1/scripts/get-response.json b/test/resources/9999999/automation/v1/scripts/get-response.json new file mode 100644 index 000000000..b475db19a --- /dev/null +++ b/test/resources/9999999/automation/v1/scripts/get-response.json @@ -0,0 +1,57 @@ +{ + "count": 5, + "page": 1, + "pageSize": 500, + "items": [ + { + "ssjsActivityId": "39f6a488-20eb-4ba0-b0b9-023725b574e4", + "name": "testExisting_script", + "key": "testExisting_script", + "description": "", + "script": " <script runat=\"server\">\n//dummy\n</script>", + "categoryId": 304, + "createdDate": "2022-10-20T00:41:26.163", + "modifiedDate": "2022-10-20T00:41:26.163" + }, + { + "ssjsActivityId": "39f6a488-20eb-4ba0-b0b9-noScriptTag", + "name": "testExisting_script_noScriptTag", + "key": "testExisting_script_noScriptTag", + "description": "", + "script": "// no script tag\n", + "categoryId": 304, + "createdDate": "2022-10-20T00:41:26.163", + "modifiedDate": "2022-10-20T00:41:26.163" + }, + { + "ssjsActivityId": "39f6a488-20eb-4ba0-b0b9-ampscript", + "name": "testExisting_script_ampscript", + "key": "testExisting_script_ampscript", + "description": "", + "script": "line1 %%[ SET @test='bla bla' ]%% line2 %%= ContentBlockByName(\"Content Builder\\dont strip non ssjs content\") =%% still line2\nline3\n<script runat=\"server\">\nPlatform.Function.ContentBlockByName(\"Content Builder\\\\dont strip non ssjs content\"); Platform.Function.ContentBlockByKey(\"testExisting_htmlblock1\");</script>", + "categoryId": 304, + "createdDate": "2022-10-20T00:41:26.163", + "modifiedDate": "2022-10-20T00:41:26.163" + }, + { + "ssjsActivityId": "39f6a488-20eb-4ba0-b0b9-ampincluded", + "name": "testExisting_script_ampincluded", + "key": "testExisting_script_ampincluded", + "description": "", + "script": " <script runat=\"server\">line1 %%[ SET @test='bla bla' ]%% line2 %%= ContentBlockById(1295064) =%% still line2\nline3\n</script>\n<script runat=\"server\">\nPlatform.Function.ContentBlockById(1295064);</script>", + "categoryId": 304, + "createdDate": "2022-10-20T00:41:26.163", + "modifiedDate": "2022-10-20T00:41:26.163" + }, + { + "ssjsActivityId": "39f6a488-20eb-4ba0-b0b9-mixed", + "name": "testExisting_script_mixed", + "key": "testExisting_script_mixed", + "description": "", + "script": " <script runat=\"server\">//dummy\n</script>line1 %%[ SET @test='bla bla' ]%% line2 %%= ContentBlockByKey(\"testExisting_asset_htmlblock\") =%% still line2;\n collapsed to line2 because it's assumed HTML\n<script runat=\"server\">\nPlatform.Function.ContentBlockByKey(\"testExisting_asset_htmlblock\");</script>", + "categoryId": 304, + "createdDate": "2022-10-20T00:41:26.163", + "modifiedDate": "2022-10-20T00:41:26.163" + } + ] +} diff --git a/test/resources/9999999/automation/v1/scripts/post-response.json b/test/resources/9999999/automation/v1/scripts/post-response.json new file mode 100644 index 000000000..aeeb66322 --- /dev/null +++ b/test/resources/9999999/automation/v1/scripts/post-response.json @@ -0,0 +1,10 @@ +{ + "ssjsActivityId": "39f6a488-20eb-4ba0-b0b9-new", + "name": "testNew_script", + "key": "testNew_script", + "description": "created on deploy", + "script": "<script runat=\"server\">\n// dummy created\n</script>", + "categoryId": 304, + "createdDate": "2022-10-20T00:41:26.163", + "modifiedDate": "2022-10-20T00:41:26.163" +} diff --git a/test/resources/9999999/data/v1/customobjectdata/key/testExisting_dataExtension/rowset/get-response.json b/test/resources/9999999/data/v1/customobjectdata/key/testExisting_dataExtension/rowset/get-response.json new file mode 100644 index 000000000..3a3d7d4a6 --- /dev/null +++ b/test/resources/9999999/data/v1/customobjectdata/key/testExisting_dataExtension/rowset/get-response.json @@ -0,0 +1,13 @@ +{ + "links": { + "self": "/v1/customobjectdata/token/ea0a44dc-b679-4d7d-8b77-e5d3f106e854/rowset?$page=1" + }, + "requestToken": "ea0a44dc-b679-4d7d-8b77-e5d3f106e854", + "tokenExpireDateUtc": "2023-01-26T13:54:59.883", + "customObjectId": "30400c03-0ec4-ec11-b83c-48df37d1de8b", + "customObjectKey": "testExisting_dataExtension", + "pageSize": 1, + "page": 1, + "count": 0, + "top": 0 +} diff --git a/test/resources/9999999/data/v1/filetransferlocation/Salesforce%20Objects%20%26%20Reports/get-response.json b/test/resources/9999999/data/v1/filetransferlocation/Salesforce%20Objects%20%26%20Reports/get-response.json new file mode 100644 index 000000000..3d626395c --- /dev/null +++ b/test/resources/9999999/data/v1/filetransferlocation/Salesforce%20Objects%20%26%20Reports/get-response.json @@ -0,0 +1,4 @@ +{ + "requestId": "bfc409fb-2fd5-459a-81d6-525b20f6eed4", + "resultMessages": [] +} diff --git a/test/resources/9999999/data/v1/filetransferlocation/testExisting_fileLocation_aws/patch-response.json b/test/resources/9999999/data/v1/filetransferlocation/testExisting_fileLocation_aws/patch-response.json new file mode 100644 index 000000000..11717d342 --- /dev/null +++ b/test/resources/9999999/data/v1/filetransferlocation/testExisting_fileLocation_aws/patch-response.json @@ -0,0 +1,18 @@ +{ + "fileTransferLocation": { + "customerKey": "testExisting_fileLocation_aws", + "name": "testExisting_fileLocation_aws_name", + "description": "updated via deploy", + "locationType": "AmazonSimpleStorage", + "awsFileTransferLocation": { + "regionName": "eucentral1", + "transferAccelerationEnabled": false, + "accessKeyId": "key-id", + "relativePath": "my/path", + "bucketName": "bucket-name", + "authType": "AccessKey" + } + }, + "requestId": "ae8149ee-819e-40b7-b08f-cb59fdf88ddb", + "resultMessages": [] +} diff --git a/test/resources/9999999/data/v1/filetransferlocation/testExisting_fileLocation_azure/delete-response.json b/test/resources/9999999/data/v1/filetransferlocation/testExisting_fileLocation_azure/delete-response.json new file mode 100644 index 000000000..39eb458d0 --- /dev/null +++ b/test/resources/9999999/data/v1/filetransferlocation/testExisting_fileLocation_azure/delete-response.json @@ -0,0 +1,4 @@ +{ + "requestId": "dba273e4-6036-4c1d-99de-e08626e102d5", + "resultMessages": [] +} diff --git a/test/resources/9999999/data/v1/filetransferlocation/testExisting_fileLocation_azure/get-response.json b/test/resources/9999999/data/v1/filetransferlocation/testExisting_fileLocation_azure/get-response.json new file mode 100644 index 000000000..3251d0076 --- /dev/null +++ b/test/resources/9999999/data/v1/filetransferlocation/testExisting_fileLocation_azure/get-response.json @@ -0,0 +1,18 @@ +{ + "fileTransferLocation": { + "customerKey": "testExisting_fileLocation_azure", + "name": "testExisting_fileLocation_azure_name", + "description": "blabla", + "locationType": "AzureBlobStorage", + "azureFileTransferLocation": { + "storageAccountName": "accountname", + "tenantId": "my-id", + "accessKeyId": "client-id", + "relativePath": "my/path", + "bucketName": "container-name", + "authType": "AccessKey" + } + }, + "requestId": "d49c372e-9939-4b81-91d2-69a37a8bb036", + "resultMessages": [] +} diff --git a/test/resources/9999999/data/v1/filetransferlocation/testExisting_fileLocation_exsftp/patch-response.json b/test/resources/9999999/data/v1/filetransferlocation/testExisting_fileLocation_exsftp/patch-response.json new file mode 100644 index 000000000..f8e8afdab --- /dev/null +++ b/test/resources/9999999/data/v1/filetransferlocation/testExisting_fileLocation_exsftp/patch-response.json @@ -0,0 +1,16 @@ +{ + "fileTransferLocation": { + "customerKey": "testExisting_fileLocation_exsftp", + "name": "testExisting_fileLocation_exsftp_name", + "description": "updated via deploy", + "locationType": "ExternalSftp", + "sFtpFileTransferLocation": { + "portNumber": 22, + "userName": "abc", + "url": "sftp://test.com", + "authType": "Password" + } + }, + "requestId": "05ef7257-72e6-4774-87c7-1f99aa892534", + "resultMessages": [] +} diff --git a/test/resources/9999999/data/v1/filetransferlocations/get-response.json b/test/resources/9999999/data/v1/filetransferlocations/get-response.json new file mode 100644 index 000000000..c5a27e2a1 --- /dev/null +++ b/test/resources/9999999/data/v1/filetransferlocations/get-response.json @@ -0,0 +1,59 @@ +{ + "page": 1, + "pageSize": 50, + "count": 4, + "items": [ + { + "customerKey": "testExisting_fileLocation_gcp", + "name": "testExisting_fileLocation_gcp_name", + "description": "", + "locationType": "GcpBlobStorage", + "gcpFileTransferLocation": { + "relativePath": "Task/Activity", + "bucketName": "some-bucket" + } + }, + { + "customerKey": "testExisting_fileLocation_aws", + "name": "testExisting_fileLocation_aws_name", + "description": "", + "locationType": "AmazonSimpleStorage", + "awsFileTransferLocation": { + "regionName": "eucentral1", + "transferAccelerationEnabled": false, + "accessKeyId": "key-id", + "relativePath": "my/path", + "bucketName": "bucket-name", + "authType": "AccessKey" + } + }, + { + "customerKey": "testExisting_fileLocation_azure", + "name": "testExisting_fileLocation_azure_name", + "description": "blabla", + "locationType": "AzureBlobStorage", + "azureFileTransferLocation": { + "storageAccountName": "accountname", + "tenantId": "my-id", + "accessKeyId": "client-id", + "relativePath": "my/path", + "bucketName": "container-name", + "authType": "AccessKey" + } + }, + { + "customerKey": "testExisting_fileLocation_exsftp", + "name": "testExisting_fileLocation_exsftp_name", + "description": "blabla", + "locationType": "ExternalSftp", + "sFtpFileTransferLocation": { + "portNumber": 22, + "userName": "abc", + "url": "sftp://test.com", + "authType": "Password" + } + } + ], + "requestId": "3870c0e1-943c-4ae4-9cff-26736372dbe7", + "resultMessages": [] +} diff --git a/test/resources/9999999/dataExtension-deploy/testBlacklist_dataExtension.dataExtension-meta.json b/test/resources/9999999/dataExtension-deploy/testBlacklist_dataExtension.dataExtension-meta.json new file mode 100644 index 000000000..5e12a0974 --- /dev/null +++ b/test/resources/9999999/dataExtension-deploy/testBlacklist_dataExtension.dataExtension-meta.json @@ -0,0 +1,20 @@ +{ + "CustomerKey": "testBlacklist_dataExtension", + "Name": "testBlacklist_dataExtension", + "Description": "", + "IsSendable": false, + "IsTestable": false, + "Fields": [ + { + "Name": "testField", + "DefaultValue": "", + "MaxLength": 254, + "IsRequired": true, + "IsPrimaryKey": false, + "FieldType": "Text" + } + ], + "c__retentionPolicy": "none", + "r__folder_ContentType": "dataextension", + "r__folder_Path": "Data Extensions" +} diff --git a/test/resources/9999999/dataExtension/build-expected.json b/test/resources/9999999/dataExtension/build-expected.json new file mode 100644 index 000000000..d54b9bbf9 --- /dev/null +++ b/test/resources/9999999/dataExtension/build-expected.json @@ -0,0 +1,66 @@ +{ + "CustomerKey": "testTemplated_dataExtension", + "Name": "testTemplated_dataExtension", + "Description": "foobar", + "IsSendable": true, + "IsTestable": true, + "SendableDataExtensionField": { "Name": "ContactKey" }, + "SendableSubscriberField": { "Name": "Subscriber Key" }, + "DataRetentionPeriodLength": 6, + "ResetRetentionPeriodOnImport": false, + "Fields": [ + { + "Name": "FirstName", + "DefaultValue": "", + "MaxLength": 50, + "IsRequired": false, + "IsPrimaryKey": false, + "FieldType": "Text" + }, + { + "Name": "LastName", + "DefaultValue": "", + "MaxLength": 50, + "IsRequired": false, + "IsPrimaryKey": false, + "FieldType": "Text" + }, + { + "Name": "EmailAddress", + "DefaultValue": "", + "MaxLength": 254, + "IsRequired": true, + "IsPrimaryKey": false, + "FieldType": "EmailAddress" + }, + { + "Name": "ContactKey", + "DefaultValue": "", + "MaxLength": 50, + "IsRequired": true, + "IsPrimaryKey": true, + "FieldType": "Text" + }, + { + "Name": "decimalField", + "DefaultValue": "", + "MaxLength": 6, + "Scale": 3, + "IsPrimaryKey": false, + "IsRequired": true, + "FieldType": "Decimal" + }, + { + "Name": "numberField", + "DefaultValue": "", + "IsPrimaryKey": false, + "IsRequired": true, + "FieldType": "Number" + } + ], + "c__dataRetentionPeriodUnitOfMeasure": "Months", + "c__retainUntil": "2024-5-9", + "c__retentionPolicy": "allRecords", + "r__folder_ContentType": "dataextension", + "r__folder_Path": "Data Extensions" +} diff --git a/test/resources/9999999/dataExtension/create-expected.json b/test/resources/9999999/dataExtension/create-expected.json new file mode 100644 index 000000000..5701a0f7b --- /dev/null +++ b/test/resources/9999999/dataExtension/create-expected.json @@ -0,0 +1,20 @@ +{ + "CustomerKey": "testNew_dataExtension", + "Name": "testNew_dataExtension", + "Description": "", + "IsSendable": false, + "IsTestable": false, + "Fields": [ + { + "Name": "testField", + "DefaultValue": "", + "MaxLength": 254, + "IsRequired": true, + "IsPrimaryKey": false, + "FieldType": "Text" + } + ], + "c__retentionPolicy": "none", + "r__folder_ContentType": "dataextension", + "r__folder_Path": "Data Extensions" +} diff --git a/test/resources/9999999/dataExtension/create-response.xml b/test/resources/9999999/dataExtension/create-response.xml new file mode 100644 index 000000000..5f46a6023 --- /dev/null +++ b/test/resources/9999999/dataExtension/create-response.xml @@ -0,0 +1,59 @@ +<?xml version="1.0" encoding="utf-8"?> +<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:xsd="http://www.w3.org/2001/XMLSchema" + xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing" + xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" + xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"> + <soap:Header> + <wsa:Action>CreateResponse</wsa:Action> + <wsa:MessageID>urn:uuid:3a5f1edf-dacb-4d19-a0d3-4e0dcc9f507d</wsa:MessageID> + <wsa:RelatesTo>urn:uuid:fb395987-bf45-42d6-af73-f51816c7b73f</wsa:RelatesTo> + <wsa:To>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</wsa:To> + <wsse:Security> + <wsu:Timestamp wsu:Id="Timestamp-b5d88471-97ad-4070-a18f-4c148a52da96"> + <wsu:Created>2022-04-24T20:35:10Z</wsu:Created> + <wsu:Expires>2022-04-24T20:40:10Z</wsu:Expires> + </wsu:Timestamp> + </wsse:Security> + </soap:Header> + <soap:Body> + <CreateResponse xmlns="http://exacttarget.com/wsdl/partnerAPI"> + <Results> + <StatusCode>OK</StatusCode> + <StatusMessage>Data Extension created.</StatusMessage> + <OrdinalID>0</OrdinalID> + <NewID>0</NewID> + <NewObjectID>30400c03-0ec4-ec11-b83c-48df37d1de8a</NewObjectID> + <Object xsi:type="DataExtension"> + <PartnerKey xsi:nil="true" /> + <ObjectID>30400c03-0ec4-ec11-b83c-48df37d1de8a</ObjectID> + <CustomerKey>testNew_dataExtension</CustomerKey> + <Name>testNew_dataExtension</Name> + <Description /> + <IsSendable>false</IsSendable> + <IsTestable>false</IsTestable> + <RowBasedRetention>false</RowBasedRetention> + <ResetRetentionPeriodOnImport>false</ResetRetentionPeriodOnImport> + <DeleteAtEndOfRetentionPeriod>false</DeleteAtEndOfRetentionPeriod> + <RetainUntil /> + <Fields> + <Field> + <PartnerKey xsi:nil="true" /> + <ObjectID xsi:nil="true" /> + <Name>testField</Name> + <DefaultValue /> + <MaxLength>254</MaxLength> + <IsRequired>true</IsRequired> + <IsPrimaryKey>false</IsPrimaryKey> + <FieldType>Text</FieldType> + </Field> + </Fields> + <CategoryID>2</CategoryID> + </Object> + </Results> + <RequestID>c41aa55a-90e3-4021-9f82-103796aae6da</RequestID> + <OverallStatus>OK</OverallStatus> + </CreateResponse> + </soap:Body> +</soap:Envelope> \ No newline at end of file diff --git a/test/resources/9999999/dataExtension/delete-response.xml b/test/resources/9999999/dataExtension/delete-response.xml new file mode 100644 index 000000000..3c5d3b961 --- /dev/null +++ b/test/resources/9999999/dataExtension/delete-response.xml @@ -0,0 +1,42 @@ +<?xml version="1.0" encoding="utf-8"?> +<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:xsd="http://www.w3.org/2001/XMLSchema" + xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing" + xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" + xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"> + <soap:Header> + <wsa:Action>DeleteResponse</wsa:Action> + <wsa:MessageID>urn:uuid:cbcad7ed-d768-4dbd-b2b9-230cc05dca1b</wsa:MessageID> + <wsa:RelatesTo>urn:uuid:545315fb-1e5b-4b6b-a17a-da1fcac3524f</wsa:RelatesTo> + <wsa:To>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</wsa:To> + <wsse:Security> + <wsu:Timestamp wsu:Id="Timestamp-cd8b5c6b-0bc1-45e1-8df0-4c61bf120d0e"> + <wsu:Created>2023-08-11T12:34:31Z</wsu:Created> + <wsu:Expires>2023-08-11T12:39:31Z</wsu:Expires> + </wsu:Timestamp> + </wsse:Security> + </soap:Header> + <soap:Body> + <DeleteResponse xmlns="http://exacttarget.com/wsdl/partnerAPI"> + <Results> + <StatusCode>OK</StatusCode> + <StatusMessage>Data Extension deleted. / Data Extension Fields deleted</StatusMessage> + <OrdinalID>0</OrdinalID> + <Object xsi:type="DataExtension"> + <PartnerKey xsi:nil="true" /> + <ObjectID>21711373-72c1-ec11-b83b-48df37d1deb7</ObjectID> + <CustomerKey>testExisting_dataExtension</CustomerKey> + <!-- <Fields> + <Field> + <PartnerKey xsi:nil="true" /> + <ObjectID>d26f1b9c-fb30-4a91-9fe8-e2495cffbd74</ObjectID> + </Field> + </Fields> --> + </Object> + </Results> + <RequestID>5c0faaa8-81db-4530-8b47-c56432f68543</RequestID> + <OverallStatus>OK</OverallStatus> + </DeleteResponse> + </soap:Body> +</soap:Envelope> diff --git a/test/resources/9999999/dataExtension/retrieve-CustomerKey=testExisting_dataExtension-response.xml b/test/resources/9999999/dataExtension/retrieve-CustomerKey=testExisting_dataExtension-response.xml new file mode 100644 index 000000000..d2f4ace4a --- /dev/null +++ b/test/resources/9999999/dataExtension/retrieve-CustomerKey=testExisting_dataExtension-response.xml @@ -0,0 +1,52 @@ +<?xml version="1.0" encoding="utf-8"?> +<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:xsd="http://www.w3.org/2001/XMLSchema" + xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing" + xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" + xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"> + <soap:Header> + <wsa:Action>RetrieveResponse</wsa:Action> + <wsa:MessageID>urn:uuid:c198cc12-c34c-4d1d-90b0-5b785a342efc</wsa:MessageID> + <wsa:RelatesTo>urn:uuid:a0506b59-1847-4405-8231-6a15e26bbcc9</wsa:RelatesTo> + <wsa:To>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</wsa:To> + <wsse:Security> + <wsu:Timestamp wsu:Id="Timestamp-52fe9187-6f22-4701-bd57-d0eaa4aef215"> + <wsu:Created>2022-04-21T19:21:50Z</wsu:Created> + <wsu:Expires>2022-04-21T19:26:50Z</wsu:Expires> + </wsu:Timestamp> + </wsse:Security> + </soap:Header> + <soap:Body> + <RetrieveResponseMsg xmlns="http://exacttarget.com/wsdl/partnerAPI"> + <OverallStatus>OK</OverallStatus> + <RequestID>d175de6e-c8e4-4f5d-9c1d-ad64426ff4b7</RequestID> + <Results xsi:type="DataExtension"> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2022-04-21T06:56:27.927</CreatedDate> + <ModifiedDate>2022-04-21T06:56:27.927</ModifiedDate> + <ObjectID>21711373-72c1-ec11-b83b-48df37d1deb7</ObjectID> + <CustomerKey>testExisting_dataExtension</CustomerKey> + <Name>testExisting_dataExtension</Name> + <Description>bla bla</Description> + <IsSendable>true</IsSendable> + <IsTestable>true</IsTestable> + <SendableDataExtensionField> + <PartnerKey xsi:nil="true" /> + <ObjectID xsi:nil="true" /> + <Name>ContactKey</Name> + </SendableDataExtensionField> + <SendableSubscriberField> + <Name>_SubscriberKey</Name> + </SendableSubscriberField> + <DataRetentionPeriodLength>6</DataRetentionPeriodLength> + <DataRetentionPeriodUnitOfMeasure>5</DataRetentionPeriodUnitOfMeasure> + <RowBasedRetention>false</RowBasedRetention> + <ResetRetentionPeriodOnImport>false</ResetRetentionPeriodOnImport> + <DeleteAtEndOfRetentionPeriod>true</DeleteAtEndOfRetentionPeriod> + <RetainUntil>5/9/2024 12:00:00 AM</RetainUntil> + <CategoryID>2</CategoryID> + </Results> + </RetrieveResponseMsg> + </soap:Body> +</soap:Envelope> diff --git a/test/resources/9999999/dataExtension/retrieve-CustomerKey=testNew_event_withSchema-response.xml b/test/resources/9999999/dataExtension/retrieve-CustomerKey=testNew_event_withSchema-response.xml new file mode 100644 index 000000000..de023bf46 --- /dev/null +++ b/test/resources/9999999/dataExtension/retrieve-CustomerKey=testNew_event_withSchema-response.xml @@ -0,0 +1,50 @@ +<?xml version="1.0" encoding="utf-8"?> +<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:xsd="http://www.w3.org/2001/XMLSchema" + xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing" + xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" + xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"> + <soap:Header> + <wsa:Action>RetrieveResponse</wsa:Action> + <wsa:MessageID>urn:uuid:c198cc12-c34c-4d1d-90b0-5b785a342efc</wsa:MessageID> + <wsa:RelatesTo>urn:uuid:a0506b59-1847-4405-8231-6a15e26bbcc9</wsa:RelatesTo> + <wsa:To>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</wsa:To> + <wsse:Security> + <wsu:Timestamp wsu:Id="Timestamp-52fe9187-6f22-4701-bd57-d0eaa4aef215"> + <wsu:Created>2022-04-21T19:21:50Z</wsu:Created> + <wsu:Expires>2022-04-21T19:26:50Z</wsu:Expires> + </wsu:Timestamp> + </wsse:Security> + </soap:Header> + <soap:Body> + <RetrieveResponseMsg xmlns="http://exacttarget.com/wsdl/partnerAPI"> + <OverallStatus>OK</OverallStatus> + <RequestID>d175de6e-c8e4-4f5d-9c1d-ad64426ff4b7</RequestID> + <Results xsi:type="DataExtension"> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2024-07-05T08:01:54.803</CreatedDate> + <ModifiedDate>2024-07-05T08:01:58.923</ModifiedDate> + <ObjectID>4342972c-a43c-ef11-a5c8-5cba2c702db8</ObjectID> + <CustomerKey>testNew_event_withSchema</CustomerKey> + <Name>testNew_event_withSchema</Name> + <Description /> + <IsSendable>true</IsSendable> + <IsTestable>false</IsTestable> + <SendableDataExtensionField> + <PartnerKey xsi:nil="true" /> + <ObjectID xsi:nil="true" /> + <Name>ContactId</Name> + </SendableDataExtensionField> + <SendableSubscriberField> + <Name>_SubscriberKey</Name> + </SendableSubscriberField> + <RowBasedRetention>false</RowBasedRetention> + <ResetRetentionPeriodOnImport>false</ResetRetentionPeriodOnImport> + <DeleteAtEndOfRetentionPeriod>false</DeleteAtEndOfRetentionPeriod> + <RetainUntil /> + <CategoryID>2</CategoryID> + </Results> + </RetrieveResponseMsg> + </soap:Body> +</soap:Envelope> diff --git a/test/resources/9999999/dataExtension/retrieve-Name=testExisting_dataExtension-response.xml b/test/resources/9999999/dataExtension/retrieve-Name=testExisting_dataExtension-response.xml new file mode 100644 index 000000000..d2f4ace4a --- /dev/null +++ b/test/resources/9999999/dataExtension/retrieve-Name=testExisting_dataExtension-response.xml @@ -0,0 +1,52 @@ +<?xml version="1.0" encoding="utf-8"?> +<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:xsd="http://www.w3.org/2001/XMLSchema" + xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing" + xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" + xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"> + <soap:Header> + <wsa:Action>RetrieveResponse</wsa:Action> + <wsa:MessageID>urn:uuid:c198cc12-c34c-4d1d-90b0-5b785a342efc</wsa:MessageID> + <wsa:RelatesTo>urn:uuid:a0506b59-1847-4405-8231-6a15e26bbcc9</wsa:RelatesTo> + <wsa:To>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</wsa:To> + <wsse:Security> + <wsu:Timestamp wsu:Id="Timestamp-52fe9187-6f22-4701-bd57-d0eaa4aef215"> + <wsu:Created>2022-04-21T19:21:50Z</wsu:Created> + <wsu:Expires>2022-04-21T19:26:50Z</wsu:Expires> + </wsu:Timestamp> + </wsse:Security> + </soap:Header> + <soap:Body> + <RetrieveResponseMsg xmlns="http://exacttarget.com/wsdl/partnerAPI"> + <OverallStatus>OK</OverallStatus> + <RequestID>d175de6e-c8e4-4f5d-9c1d-ad64426ff4b7</RequestID> + <Results xsi:type="DataExtension"> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2022-04-21T06:56:27.927</CreatedDate> + <ModifiedDate>2022-04-21T06:56:27.927</ModifiedDate> + <ObjectID>21711373-72c1-ec11-b83b-48df37d1deb7</ObjectID> + <CustomerKey>testExisting_dataExtension</CustomerKey> + <Name>testExisting_dataExtension</Name> + <Description>bla bla</Description> + <IsSendable>true</IsSendable> + <IsTestable>true</IsTestable> + <SendableDataExtensionField> + <PartnerKey xsi:nil="true" /> + <ObjectID xsi:nil="true" /> + <Name>ContactKey</Name> + </SendableDataExtensionField> + <SendableSubscriberField> + <Name>_SubscriberKey</Name> + </SendableSubscriberField> + <DataRetentionPeriodLength>6</DataRetentionPeriodLength> + <DataRetentionPeriodUnitOfMeasure>5</DataRetentionPeriodUnitOfMeasure> + <RowBasedRetention>false</RowBasedRetention> + <ResetRetentionPeriodOnImport>false</ResetRetentionPeriodOnImport> + <DeleteAtEndOfRetentionPeriod>true</DeleteAtEndOfRetentionPeriod> + <RetainUntil>5/9/2024 12:00:00 AM</RetainUntil> + <CategoryID>2</CategoryID> + </Results> + </RetrieveResponseMsg> + </soap:Body> +</soap:Envelope> diff --git a/test/resources/9999999/dataExtension/retrieve-createdViaEvent-response.xml b/test/resources/9999999/dataExtension/retrieve-createdViaEvent-response.xml new file mode 100644 index 000000000..46c69fe82 --- /dev/null +++ b/test/resources/9999999/dataExtension/retrieve-createdViaEvent-response.xml @@ -0,0 +1,50 @@ +<?xml version="1.0" encoding="utf-8"?> +<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:xsd="http://www.w3.org/2001/XMLSchema" + xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing" + xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" + xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"> + <soap:Header> + <wsa:Action>RetrieveResponse</wsa:Action> + <wsa:MessageID>urn:uuid:c198cc12-c34c-4d1d-90b0-5b785a342efc</wsa:MessageID> + <wsa:RelatesTo>urn:uuid:a0506b59-1847-4405-8231-6a15e26bbcc9</wsa:RelatesTo> + <wsa:To>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</wsa:To> + <wsse:Security> + <wsu:Timestamp wsu:Id="Timestamp-52fe9187-6f22-4701-bd57-d0eaa4aef215"> + <wsu:Created>2022-04-21T19:21:50Z</wsu:Created> + <wsu:Expires>2022-04-21T19:26:50Z</wsu:Expires> + </wsu:Timestamp> + </wsse:Security> + </soap:Header> + <soap:Body> + <RetrieveResponseMsg xmlns="http://exacttarget.com/wsdl/partnerAPI"> + <OverallStatus>OK</OverallStatus> + <RequestID>d175de6e-c8e4-4f5d-9c1d-ad64426ff4b7</RequestID> + <Results xsi:type="DataExtension"> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2024-07-05T08:01:54.803</CreatedDate> + <ModifiedDate>2024-07-05T08:01:58.923</ModifiedDate> + <ObjectID>4342972c-a43c-ef11-a5c8-5cba2c702db8</ObjectID> + <CustomerKey>0A1730F7-D7E3-4F30-8279-575BDB38D24D</CustomerKey> + <Name>testNew_event_withSchema - 2024-07-08T014814443</Name> + <Description /> + <IsSendable>true</IsSendable> + <IsTestable>false</IsTestable> + <SendableDataExtensionField> + <PartnerKey xsi:nil="true" /> + <ObjectID xsi:nil="true" /> + <Name>ContactId</Name> + </SendableDataExtensionField> + <SendableSubscriberField> + <Name>_SubscriberKey</Name> + </SendableSubscriberField> + <RowBasedRetention>false</RowBasedRetention> + <ResetRetentionPeriodOnImport>false</ResetRetentionPeriodOnImport> + <DeleteAtEndOfRetentionPeriod>false</DeleteAtEndOfRetentionPeriod> + <RetainUntil /> + <CategoryID>2</CategoryID> + </Results> + </RetrieveResponseMsg> + </soap:Body> +</soap:Envelope> diff --git a/test/resources/9999999/dataExtension/retrieve-expected.json b/test/resources/9999999/dataExtension/retrieve-expected.json new file mode 100644 index 000000000..4049fe48d --- /dev/null +++ b/test/resources/9999999/dataExtension/retrieve-expected.json @@ -0,0 +1,66 @@ +{ + "CustomerKey": "testExisting_dataExtension", + "Name": "testExisting_dataExtension", + "Description": "bla bla", + "IsSendable": true, + "IsTestable": true, + "SendableDataExtensionField": { "Name": "ContactKey" }, + "SendableSubscriberField": { "Name": "Subscriber Key" }, + "DataRetentionPeriodLength": 6, + "ResetRetentionPeriodOnImport": false, + "Fields": [ + { + "Name": "FirstName", + "DefaultValue": "", + "MaxLength": 50, + "IsRequired": false, + "IsPrimaryKey": false, + "FieldType": "Text" + }, + { + "Name": "LastName", + "DefaultValue": "", + "MaxLength": 50, + "IsRequired": false, + "IsPrimaryKey": false, + "FieldType": "Text" + }, + { + "Name": "EmailAddress", + "DefaultValue": "", + "MaxLength": 254, + "IsRequired": true, + "IsPrimaryKey": false, + "FieldType": "EmailAddress" + }, + { + "Name": "ContactKey", + "DefaultValue": "", + "MaxLength": 50, + "IsRequired": true, + "IsPrimaryKey": true, + "FieldType": "Text" + }, + { + "Name": "decimalField", + "DefaultValue": "", + "MaxLength": 6, + "Scale": 3, + "IsPrimaryKey": false, + "IsRequired": true, + "FieldType": "Decimal" + }, + { + "Name": "numberField", + "DefaultValue": "", + "IsPrimaryKey": false, + "IsRequired": true, + "FieldType": "Number" + } + ], + "c__dataRetentionPeriodUnitOfMeasure": "Months", + "c__retainUntil": "2024-5-9", + "c__retentionPolicy": "allRecords", + "r__folder_ContentType": "dataextension", + "r__folder_Path": "Data Extensions" +} diff --git a/test/resources/9999999/dataExtension/retrieve-expected.md b/test/resources/9999999/dataExtension/retrieve-expected.md new file mode 100644 index 000000000..074c23786 --- /dev/null +++ b/test/resources/9999999/dataExtension/retrieve-expected.md @@ -0,0 +1,25 @@ +## testExisting_dataExtension + +**Description:** bla bla + +**Folder:** Data Extensions/ + +**Fields in table:** 6 + +**Sendable:** Yes (`ContactKey` to `Subscriber Key`) + +**Testable:** Yes + +**Retention Policy:** allRecords + +- **Retention Period:** 6 Months +- **Reset Retention Period on import:** no + +| Name | FieldType | MaxLength | IsPrimaryKey | IsNullable | DefaultValue | +| --- | --- | --- | --- | --- | --- | +| FirstName | Text | 50 | - | + | | +| LastName | Text | 50 | - | + | | +| EmailAddress | EmailAddress | 254 | - | - | | +| ContactKey | Text | 50 | + | - | | +| decimalField | Decimal | 6,3 | - | - | | +| numberField | Number | | - | - | | diff --git a/test/resources/9999999/dataExtension/retrieve-response.xml b/test/resources/9999999/dataExtension/retrieve-response.xml new file mode 100644 index 000000000..f02c14330 --- /dev/null +++ b/test/resources/9999999/dataExtension/retrieve-response.xml @@ -0,0 +1,224 @@ +<?xml version="1.0" encoding="utf-8"?> +<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:xsd="http://www.w3.org/2001/XMLSchema" + xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing" + xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" + xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"> + <soap:Header> + <wsa:Action>RetrieveResponse</wsa:Action> + <wsa:MessageID>urn:uuid:c198cc12-c34c-4d1d-90b0-5b785a342efc</wsa:MessageID> + <wsa:RelatesTo>urn:uuid:a0506b59-1847-4405-8231-6a15e26bbcc9</wsa:RelatesTo> + <wsa:To>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</wsa:To> + <wsse:Security> + <wsu:Timestamp wsu:Id="Timestamp-52fe9187-6f22-4701-bd57-d0eaa4aef215"> + <wsu:Created>2022-04-21T19:21:50Z</wsu:Created> + <wsu:Expires>2022-04-21T19:26:50Z</wsu:Expires> + </wsu:Timestamp> + </wsse:Security> + </soap:Header> + <soap:Body> + <RetrieveResponseMsg xmlns="http://exacttarget.com/wsdl/partnerAPI"> + <OverallStatus>OK</OverallStatus> + <RequestID>d175de6e-c8e4-4f5d-9c1d-ad64426ff4b7</RequestID> + <Results xsi:type="DataExtension"> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2022-04-21T06:56:27.927</CreatedDate> + <ModifiedDate>2022-04-21T06:56:27.927</ModifiedDate> + <ObjectID>21711373-72c1-ec11-b83b-48df37d1deb7</ObjectID> + <CustomerKey>testExisting_dataExtension</CustomerKey> + <Name>testExisting_dataExtension</Name> + <Description>bla bla</Description> + <IsSendable>true</IsSendable> + <IsTestable>true</IsTestable> + <SendableDataExtensionField> + <PartnerKey xsi:nil="true" /> + <ObjectID xsi:nil="true" /> + <Name>ContactKey</Name> + </SendableDataExtensionField> + <SendableSubscriberField> + <Name>_SubscriberKey</Name> + </SendableSubscriberField> + <DataRetentionPeriodLength>6</DataRetentionPeriodLength> + <DataRetentionPeriodUnitOfMeasure>5</DataRetentionPeriodUnitOfMeasure> + <RowBasedRetention>false</RowBasedRetention> + <ResetRetentionPeriodOnImport>false</ResetRetentionPeriodOnImport> + <DeleteAtEndOfRetentionPeriod>true</DeleteAtEndOfRetentionPeriod> + <RetainUntil>5/9/2024 12:00:00 AM</RetainUntil> + <CategoryID>2</CategoryID> + </Results> + <Results xsi:type="DataExtension"> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2022-04-21T06:56:27.927</CreatedDate> + <ModifiedDate>2022-04-21T06:56:27.927</ModifiedDate> + <ObjectID>21711373-72c1-ec11-b83b-exclusion</ObjectID> + <CustomerKey>testExisting_dataExtension_exclusion</CustomerKey> + <Name>testExisting_dataExtension_exclusion</Name> + <Description>bla bla</Description> + <IsSendable>true</IsSendable> + <IsTestable>true</IsTestable> + <SendableDataExtensionField> + <PartnerKey xsi:nil="true" /> + <ObjectID xsi:nil="true" /> + <Name>ContactKey</Name> + </SendableDataExtensionField> + <SendableSubscriberField> + <Name>_SubscriberKey</Name> + </SendableSubscriberField> + <DataRetentionPeriodLength>6</DataRetentionPeriodLength> + <DataRetentionPeriodUnitOfMeasure>5</DataRetentionPeriodUnitOfMeasure> + <RowBasedRetention>true</RowBasedRetention> + <ResetRetentionPeriodOnImport>false</ResetRetentionPeriodOnImport> + <DeleteAtEndOfRetentionPeriod>false</DeleteAtEndOfRetentionPeriod> + <RetainUntil /> + <CategoryID>2</CategoryID> + </Results> + <Results xsi:type="DataExtension"> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2024-04-24T12:15:55.853</CreatedDate> + <ModifiedDate>2024-04-24T12:15:55.853</ModifiedDate> + <ObjectID>5a7194ad-6602-ef11-a5c8-5cba2c702db8</ObjectID> + <CustomerKey>testExisting_DomainExclusion</CustomerKey> + <Name>testExisting_DomainExclusion</Name> + <Description>Domain Exclusion Data Extension Template</Description> + <IsSendable>false</IsSendable> + <IsTestable>false</IsTestable> + <Template> + <PartnerKey xsi:nil="true" /> + <ObjectID xsi:nil="true" /> + <CustomerKey>086D14D3-5057-462B-AF33-01CA8D1FE87A</CustomerKey> + </Template> + <RowBasedRetention>false</RowBasedRetention> + <ResetRetentionPeriodOnImport>false</ResetRetentionPeriodOnImport> + <DeleteAtEndOfRetentionPeriod>false</DeleteAtEndOfRetentionPeriod> + <RetainUntil /> + <CategoryID>2</CategoryID> + </Results> + <Results xsi:type="DataExtension"> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2024-04-24T12:09:53.527</CreatedDate> + <ModifiedDate>2024-04-24T12:09:53.527</ModifiedDate> + <ObjectID>1c8064d5-6502-ef11-a5c8-5cba2c702db8</ObjectID> + <CustomerKey>testExisting_journey_Quicksend</CustomerKey> + <Name>testExisting_journey_Quicksend</Name> + <Description /> + <IsSendable>true</IsSendable> + <IsTestable>false</IsTestable> + <SendableDataExtensionField> + <PartnerKey xsi:nil="true" /> + <ObjectID xsi:nil="true" /> + <Name>ContactId</Name> + </SendableDataExtensionField> + <SendableSubscriberField> + <Name>_SubscriberKey</Name> + </SendableSubscriberField> + <RowBasedRetention>false</RowBasedRetention> + <ResetRetentionPeriodOnImport>false</ResetRetentionPeriodOnImport> + <DeleteAtEndOfRetentionPeriod>false</DeleteAtEndOfRetentionPeriod> + <RetainUntil /> + <CategoryID>2</CategoryID> + </Results> + <Results xsi:type="DataExtension"> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2024-04-24T12:10:46.457</CreatedDate> + <ModifiedDate>2024-04-24T12:10:46.457</ModifiedDate> + <ObjectID>ed305df3-6502-ef11-a5c8-5cba2c702db8</ObjectID> + <CustomerKey>testExisting_journey_Multistep</CustomerKey> + <Name>testExisting_journey_Multistep</Name> + <Description /> + <IsSendable>true</IsSendable> + <IsTestable>false</IsTestable> + <SendableDataExtensionField> + <PartnerKey xsi:nil="true" /> + <ObjectID xsi:nil="true" /> + <Name>ContactId</Name> + </SendableDataExtensionField> + <SendableSubscriberField> + <Name>_SubscriberKey</Name> + </SendableSubscriberField> + <RowBasedRetention>false</RowBasedRetention> + <ResetRetentionPeriodOnImport>false</ResetRetentionPeriodOnImport> + <DeleteAtEndOfRetentionPeriod>false</DeleteAtEndOfRetentionPeriod> + <RetainUntil /> + <CategoryID>2</CategoryID> + </Results> + <Results xsi:type="DataExtension"> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2024-07-05T08:01:54.803</CreatedDate> + <ModifiedDate>2024-07-05T08:01:58.923</ModifiedDate> + <ObjectID>f2cc2b21-d73a-ef11-a5c8-5cba2c702db8</ObjectID> + <CustomerKey>testExisting_event - 2024-07-05T080154625</CustomerKey> + <Name>testExisting_event - 2024-07-05T080154625</Name> + <Description /> + <IsSendable>true</IsSendable> + <IsTestable>false</IsTestable> + <SendableDataExtensionField> + <PartnerKey xsi:nil="true" /> + <ObjectID xsi:nil="true" /> + <Name>ContactId</Name> + </SendableDataExtensionField> + <SendableSubscriberField> + <Name>_SubscriberKey</Name> + </SendableSubscriberField> + <RowBasedRetention>false</RowBasedRetention> + <ResetRetentionPeriodOnImport>false</ResetRetentionPeriodOnImport> + <DeleteAtEndOfRetentionPeriod>false</DeleteAtEndOfRetentionPeriod> + <RetainUntil /> + <CategoryID>2</CategoryID> + </Results> + <Results xsi:type="DataExtension"> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2024-07-05T08:01:54.803</CreatedDate> + <ModifiedDate>2024-07-05T08:01:58.923</ModifiedDate> + <ObjectID>4342972c-a43c-ef11-a5c8-5cba2c702db8</ObjectID> + <CustomerKey>testNew_event_withSchema - 2024-07-08T014814443</CustomerKey> + <Name>testNew_event_withSchema - 2024-07-08T014814443</Name> + <Description /> + <IsSendable>true</IsSendable> + <IsTestable>false</IsTestable> + <SendableDataExtensionField> + <PartnerKey xsi:nil="true" /> + <ObjectID xsi:nil="true" /> + <Name>ContactId</Name> + </SendableDataExtensionField> + <SendableSubscriberField> + <Name>_SubscriberKey</Name> + </SendableSubscriberField> + <RowBasedRetention>false</RowBasedRetention> + <ResetRetentionPeriodOnImport>false</ResetRetentionPeriodOnImport> + <DeleteAtEndOfRetentionPeriod>false</DeleteAtEndOfRetentionPeriod> + <RetainUntil /> + <CategoryID>2</CategoryID> + </Results> + <Results xsi:type="DataExtension"> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2024-08-21T09:54:28.807</CreatedDate> + <ModifiedDate>2024-08-21T09:54:28.807</ModifiedDate> + <ObjectID>3c3a54a5-d55f-ef11-b876-f40343c95928</ObjectID> + <CustomerKey>testExisting_temail_notPublished</CustomerKey> + <Name>testExisting_temail_notPublished</Name> + <Description>Triggered Send Source Data Extension Template</Description> + <IsSendable>true</IsSendable> + <IsTestable>false</IsTestable> + <SendableDataExtensionField> + <PartnerKey xsi:nil="true" /> + <ObjectID xsi:nil="true" /> + <Name>SubscriberKey</Name> + </SendableDataExtensionField> + <SendableSubscriberField> + <Name>_SubscriberKey</Name> + </SendableSubscriberField> + <Template> + <PartnerKey xsi:nil="true" /> + <ObjectID xsi:nil="true" /> + <CustomerKey>B6E8AE4C-3D93-49B1-B299-E0AE734213DD</CustomerKey> + </Template> + <RowBasedRetention>false</RowBasedRetention> + <ResetRetentionPeriodOnImport>false</ResetRetentionPeriodOnImport> + <DeleteAtEndOfRetentionPeriod>false</DeleteAtEndOfRetentionPeriod> + <RetainUntil /> + <CategoryID>2</CategoryID> + </Results> + </RetrieveResponseMsg> + </soap:Body> +</soap:Envelope> diff --git a/test/resources/9999999/dataExtension/retrieve_event_withSchema-expected.json b/test/resources/9999999/dataExtension/retrieve_event_withSchema-expected.json new file mode 100644 index 000000000..00350d1a1 --- /dev/null +++ b/test/resources/9999999/dataExtension/retrieve_event_withSchema-expected.json @@ -0,0 +1,219 @@ +{ + "CustomerKey": "testNew_event_withSchema", + "Name": "testNew_event_withSchema", + "Description": "", + "IsSendable": true, + "IsTestable": false, + "SendableDataExtensionField": { + "Name": "ContactId" + }, + "SendableSubscriberField": { + "Name": "Subscriber Key" + }, + "Fields": [ + { + "Name": "ContactId", + "DefaultValue": "", + "MaxLength": 18, + "IsRequired": true, + "IsPrimaryKey": true, + "FieldType": "Text" + }, + { + "Name": "Type", + "DefaultValue": "", + "MaxLength": 50, + "IsRequired": true, + "IsPrimaryKey": false, + "FieldType": "Text" + }, + { + "Name": "Status", + "DefaultValue": "", + "MaxLength": 50, + "IsRequired": true, + "IsPrimaryKey": true, + "FieldType": "Text" + }, + { + "Name": "Respondent", + "DefaultValue": "", + "MaxLength": 256, + "IsRequired": false, + "IsPrimaryKey": false, + "FieldType": "Text" + }, + { + "Name": "FirstName", + "DefaultValue": "", + "MaxLength": 256, + "IsRequired": false, + "IsPrimaryKey": false, + "FieldType": "Text" + }, + { + "Name": "LastName", + "DefaultValue": "", + "MaxLength": 256, + "IsRequired": false, + "IsPrimaryKey": false, + "FieldType": "Text" + }, + { + "Name": "PreferredLanguage", + "DefaultValue": "", + "MaxLength": 50, + "IsRequired": false, + "IsPrimaryKey": false, + "FieldType": "Text" + }, + { + "Name": "TouchPoint", + "DefaultValue": "", + "MaxLength": 256, + "IsRequired": false, + "IsPrimaryKey": false, + "FieldType": "Text" + }, + { + "Name": "Datestamp", + "DefaultValue": "GetDate()", + "IsRequired": false, + "IsPrimaryKey": false, + "FieldType": "Date" + }, + { + "Name": "StartDate", + "DefaultValue": "", + "IsRequired": false, + "IsPrimaryKey": false, + "FieldType": "Date" + }, + { + "Name": "EndDate", + "DefaultValue": "", + "IsRequired": false, + "IsPrimaryKey": false, + "FieldType": "Date" + }, + { + "Name": "BroadcastedNotificationDate", + "DefaultValue": "", + "IsRequired": false, + "IsPrimaryKey": false, + "FieldType": "Date" + }, + { + "Name": "FirstReminderDate", + "DefaultValue": "", + "IsRequired": false, + "IsPrimaryKey": false, + "FieldType": "Date" + }, + { + "Name": "SecondReminderDate", + "DefaultValue": "", + "IsRequired": false, + "IsPrimaryKey": false, + "FieldType": "Date" + }, + { + "Name": "Title", + "DefaultValue": "", + "MaxLength": 256, + "IsRequired": false, + "IsPrimaryKey": false, + "FieldType": "Text" + }, + { + "Name": "DisplayName", + "DefaultValue": "", + "MaxLength": 256, + "IsRequired": false, + "IsPrimaryKey": false, + "FieldType": "Text" + }, + { + "Name": "Text", + "DefaultValue": "", + "MaxLength": 256, + "IsRequired": false, + "IsPrimaryKey": false, + "FieldType": "Text" + }, + { + "Name": "Description", + "DefaultValue": "", + "MaxLength": 4000, + "IsRequired": false, + "IsPrimaryKey": false, + "FieldType": "Text" + }, + { + "Name": "Channel", + "DefaultValue": "", + "MaxLength": 256, + "IsRequired": false, + "IsPrimaryKey": false, + "FieldType": "Text" + }, + { + "Name": "FirstReminderChannel", + "DefaultValue": "", + "MaxLength": 256, + "IsRequired": false, + "IsPrimaryKey": false, + "FieldType": "Text" + }, + { + "Name": "SecondReminderChannel", + "DefaultValue": "", + "MaxLength": 256, + "IsRequired": false, + "IsPrimaryKey": false, + "FieldType": "Text" + }, + { + "Name": "Email", + "DefaultValue": "", + "MaxLength": 254, + "IsRequired": false, + "IsPrimaryKey": false, + "FieldType": "EmailAddress" + }, + { + "Name": "ArticleOrTaskID", + "DefaultValue": "", + "MaxLength": 18, + "IsRequired": true, + "IsPrimaryKey": true, + "FieldType": "Text" + }, + { + "Name": "Points", + "DefaultValue": "", + "IsRequired": false, + "IsPrimaryKey": false, + "FieldType": "Number" + }, + { + "Name": "TaskType", + "DefaultValue": "", + "MaxLength": 255, + "IsRequired": false, + "IsPrimaryKey": false, + "FieldType": "Text" + }, + { + "Name": "TaskArea", + "DefaultValue": "", + "MaxLength": 255, + "IsRequired": false, + "IsPrimaryKey": false, + "FieldType": "Text" + } + ], + "r__folder_ContentType": "dataextension", + "r__folder_Path": "Data Extensions", + "c__retentionPolicy": "none" +} diff --git a/test/resources/9999999/dataExtension/template-expected.json b/test/resources/9999999/dataExtension/template-expected.json new file mode 100644 index 000000000..439050ea5 --- /dev/null +++ b/test/resources/9999999/dataExtension/template-expected.json @@ -0,0 +1,66 @@ +{ + "CustomerKey": "{{{prefix}}}dataExtension", + "Name": "{{{prefix}}}dataExtension", + "Description": "{{{description}}}", + "IsSendable": true, + "IsTestable": true, + "SendableDataExtensionField": { "Name": "ContactKey" }, + "SendableSubscriberField": { "Name": "Subscriber Key" }, + "DataRetentionPeriodLength": 6, + "ResetRetentionPeriodOnImport": false, + "Fields": [ + { + "Name": "FirstName", + "DefaultValue": "", + "MaxLength": 50, + "IsRequired": false, + "IsPrimaryKey": false, + "FieldType": "Text" + }, + { + "Name": "LastName", + "DefaultValue": "", + "MaxLength": 50, + "IsRequired": false, + "IsPrimaryKey": false, + "FieldType": "Text" + }, + { + "Name": "EmailAddress", + "DefaultValue": "", + "MaxLength": 254, + "IsRequired": true, + "IsPrimaryKey": false, + "FieldType": "EmailAddress" + }, + { + "Name": "ContactKey", + "DefaultValue": "", + "MaxLength": 50, + "IsRequired": true, + "IsPrimaryKey": true, + "FieldType": "Text" + }, + { + "Name": "decimalField", + "DefaultValue": "", + "MaxLength": 6, + "Scale": 3, + "IsPrimaryKey": false, + "IsRequired": true, + "FieldType": "Decimal" + }, + { + "Name": "numberField", + "DefaultValue": "", + "IsPrimaryKey": false, + "IsRequired": true, + "FieldType": "Number" + } + ], + "c__dataRetentionPeriodUnitOfMeasure": "Months", + "c__retainUntil": "2024-5-9", + "c__retentionPolicy": "allRecords", + "r__folder_ContentType": "dataextension", + "r__folder_Path": "Data Extensions" +} diff --git a/test/resources/9999999/dataExtension/update-afterCreatedViaEvent-response.xml b/test/resources/9999999/dataExtension/update-afterCreatedViaEvent-response.xml new file mode 100644 index 000000000..f342e1357 --- /dev/null +++ b/test/resources/9999999/dataExtension/update-afterCreatedViaEvent-response.xml @@ -0,0 +1,55 @@ +<?xml version="1.0" encoding="utf-8"?> +<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:xsd="http://www.w3.org/2001/XMLSchema" + xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing" + xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" + xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"> + <soap:Header> + <wsa:Action>UpdateResponse</wsa:Action> + <wsa:MessageID>urn:uuid:994e213d-1125-450d-b187-32e3870147d1</wsa:MessageID> + <wsa:RelatesTo>urn:uuid:f1fc86ef-c0c8-4c17-a901-a15fc2631f76</wsa:RelatesTo> + <wsa:To>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</wsa:To> + <wsse:Security> + <wsu:Timestamp wsu:Id="Timestamp-88cf0bce-bf0f-4d5f-90a6-2897708181b5"> + <wsu:Created>2022-04-26T20:49:03Z</wsu:Created> + <wsu:Expires>2022-04-26T20:54:03Z</wsu:Expires> + </wsu:Timestamp> + </wsse:Security> + </soap:Header> + <soap:Body> + <UpdateResponse xmlns="http://exacttarget.com/wsdl/partnerAPI"> + <Results> + <StatusCode>OK</StatusCode> + <StatusMessage>Data Extension updated.</StatusMessage> + <OrdinalID>0</OrdinalID> + <Object xsi:type="DataExtension"> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2024-07-05T08:01:54.803</CreatedDate> + <ModifiedDate>2024-07-05T08:01:58.923</ModifiedDate> + <ObjectID>4342972c-a43c-ef11-a5c8-5cba2c702db8</ObjectID> + <CustomerKey>testNew_event_withSchema</CustomerKey> + <Name>testNew_event_withSchema</Name> + <Description /> + <IsSendable>true</IsSendable> + <IsTestable>false</IsTestable> + <SendableDataExtensionField> + <PartnerKey xsi:nil="true" /> + <ObjectID xsi:nil="true" /> + <Name>ContactId</Name> + </SendableDataExtensionField> + <SendableSubscriberField> + <Name>_SubscriberKey</Name> + </SendableSubscriberField> + <RowBasedRetention>false</RowBasedRetention> + <ResetRetentionPeriodOnImport>false</ResetRetentionPeriodOnImport> + <DeleteAtEndOfRetentionPeriod>false</DeleteAtEndOfRetentionPeriod> + <RetainUntil /> + <CategoryID>2</CategoryID> + + </Results> + <RequestID>dbfedcb6-a809-4101-b314-a7b920c9fb1e</RequestID> + <OverallStatus>OK</OverallStatus> + </UpdateResponse> + </soap:Body> + </soap:Envelope> diff --git a/test/resources/9999999/dataExtension/update-callout-afterCreatedViaEvent-expected.xml b/test/resources/9999999/dataExtension/update-callout-afterCreatedViaEvent-expected.xml new file mode 100644 index 000000000..9cd788954 --- /dev/null +++ b/test/resources/9999999/dataExtension/update-callout-afterCreatedViaEvent-expected.xml @@ -0,0 +1 @@ +<Envelope xmlns="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"><Body><UpdateRequest xmlns="http://exacttarget.com/wsdl/partnerAPI"><Objects xsi:type="DataExtension"><CreatedDate>2024-07-05T08:01:54.803</CreatedDate><ModifiedDate>2024-07-05T08:01:58.923</ModifiedDate><ObjectID>4342972c-a43c-ef11-a5c8-5cba2c702db8</ObjectID><CustomerKey>testNew_event_withSchema</CustomerKey><Name>testNew_event_withSchema</Name><Description></Description><IsSendable>true</IsSendable><IsTestable>false</IsTestable><SendableDataExtensionField><ObjectID></ObjectID><Name>ContactId</Name></SendableDataExtensionField><SendableSubscriberField><Name>_SubscriberKey</Name></SendableSubscriberField><RowBasedRetention>false</RowBasedRetention><ResetRetentionPeriodOnImport>false</ResetRetentionPeriodOnImport><DeleteAtEndOfRetentionPeriod>false</DeleteAtEndOfRetentionPeriod><RetainUntil></RetainUntil><CategoryID>2</CategoryID></Objects></UpdateRequest></Body><Header><fueloauth xmlns="http://exacttarget.com">9999999</fueloauth></Header></Envelope> \ No newline at end of file diff --git a/test/resources/9999999/dataExtension/update-expected.json b/test/resources/9999999/dataExtension/update-expected.json new file mode 100644 index 000000000..51b603741 --- /dev/null +++ b/test/resources/9999999/dataExtension/update-expected.json @@ -0,0 +1,72 @@ +{ + "CustomerKey": "testExisting_dataExtension", + "Name": "testExisting_dataExtension", + "Description": "Container for my test emails", + "IsSendable": false, + "IsTestable": false, + "DataRetentionPeriodLength": 6, + "ResetRetentionPeriodOnImport": false, + "Fields": [ + { + "Name": "FirstName", + "DefaultValue": "", + "MaxLength": 50, + "IsRequired": false, + "IsPrimaryKey": false, + "FieldType": "Text" + }, + { + "Name": "LastName", + "DefaultValue": "", + "MaxLength": 55, + "IsRequired": false, + "IsPrimaryKey": false, + "FieldType": "Text" + }, + { + "Name": "Email", + "DefaultValue": "", + "MaxLength": 254, + "IsRequired": true, + "IsPrimaryKey": false, + "FieldType": "EmailAddress" + }, + { + "Name": "ContactKey", + "DefaultValue": "", + "MaxLength": 50, + "IsRequired": true, + "IsPrimaryKey": true, + "FieldType": "Text" + }, + { + "Name": "decimalField", + "DefaultValue": "", + "MaxLength": 6, + "Scale": 3, + "IsPrimaryKey": false, + "IsRequired": true, + "FieldType": "Decimal" + }, + { + "Name": "numberField", + "DefaultValue": "", + "IsPrimaryKey": false, + "IsRequired": true, + "FieldType": "Number" + }, + { + "Name": "testField", + "DefaultValue": "", + "MaxLength": 254, + "IsRequired": false, + "IsPrimaryKey": false, + "FieldType": "Text" + } + ], + "c__dataRetentionPeriodUnitOfMeasure": "Months", + "c__retainUntil": "2024-5-9", + "c__retentionPolicy": "allRecords", + "r__folder_ContentType": "dataextension", + "r__folder_Path": "Data Extensions" +} diff --git a/test/resources/9999999/dataExtension/update-response.xml b/test/resources/9999999/dataExtension/update-response.xml new file mode 100644 index 000000000..f08b00787 --- /dev/null +++ b/test/resources/9999999/dataExtension/update-response.xml @@ -0,0 +1,59 @@ +<?xml version="1.0" encoding="utf-8"?> +<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:xsd="http://www.w3.org/2001/XMLSchema" + xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing" + xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" + xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"> + <soap:Header> + <wsa:Action>UpdateResponse</wsa:Action> + <wsa:MessageID>urn:uuid:994e213d-1125-450d-b187-32e3870147d1</wsa:MessageID> + <wsa:RelatesTo>urn:uuid:f1fc86ef-c0c8-4c17-a901-a15fc2631f76</wsa:RelatesTo> + <wsa:To>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</wsa:To> + <wsse:Security> + <wsu:Timestamp wsu:Id="Timestamp-88cf0bce-bf0f-4d5f-90a6-2897708181b5"> + <wsu:Created>2022-04-26T20:49:03Z</wsu:Created> + <wsu:Expires>2022-04-26T20:54:03Z</wsu:Expires> + </wsu:Timestamp> + </wsse:Security> + </soap:Header> + <soap:Body> + <UpdateResponse xmlns="http://exacttarget.com/wsdl/partnerAPI"> + <Results> + <StatusCode>OK</StatusCode> + <StatusMessage>Data Extension updated.</StatusMessage> + <OrdinalID>0</OrdinalID> + <Object xsi:type="DataExtension"> + <PartnerKey xsi:nil="true" /> + <ObjectID>30400c03-0ec4-ec11-b83c-48df37d1de8b</ObjectID> + <CustomerKey>testExisting_dataExtension</CustomerKey> + <Name>testExisting_dataExtension</Name> + <Description>Container for my test emails</Description> + <IsSendable>false</IsSendable> + <IsTestable>false</IsTestable> + <DataRetentionPeriodLength>6</DataRetentionPeriodLength> + <DataRetentionPeriodUnitOfMeasure>5</DataRetentionPeriodUnitOfMeasure> + <RowBasedRetention>false</RowBasedRetention> + <ResetRetentionPeriodOnImport>false</ResetRetentionPeriodOnImport> + <DeleteAtEndOfRetentionPeriod>true</DeleteAtEndOfRetentionPeriod> + <RetainUntil>5/9/2024 12:00:00 AM</RetainUntil> + <Fields> + <Field> + <PartnerKey xsi:nil="true" /> + <ObjectID xsi:nil="true" /> + <Name>testField</Name> + <DefaultValue /> + <MaxLength>254</MaxLength> + <IsRequired>true</IsRequired> + <IsPrimaryKey>false</IsPrimaryKey> + <FieldType>Text</FieldType> + </Field> + </Fields> + <CategoryID>2</CategoryID> + </Object> + </Results> + <RequestID>dbfedcb6-a809-4101-b314-a7b920c9fb1e</RequestID> + <OverallStatus>OK</OverallStatus> + </UpdateResponse> + </soap:Body> +</soap:Envelope> diff --git a/test/resources/9999999/dataExtensionField/retrieve-CustomerKey=[testExisting_dataExtension].[LastName]-response.xml b/test/resources/9999999/dataExtensionField/retrieve-CustomerKey=[testExisting_dataExtension].[LastName]-response.xml new file mode 100644 index 000000000..d040f9e3b --- /dev/null +++ b/test/resources/9999999/dataExtensionField/retrieve-CustomerKey=[testExisting_dataExtension].[LastName]-response.xml @@ -0,0 +1,44 @@ +<?xml version="1.0" encoding="utf-8"?> +<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:xsd="http://www.w3.org/2001/XMLSchema" + xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing" + xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" + xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"> + <soap:Header> + <wsa:Action>RetrieveResponse</wsa:Action> + <wsa:MessageID>urn:uuid:6d2f81c8-80ab-44d5-8664-206753e7ac8d</wsa:MessageID> + <wsa:RelatesTo>urn:uuid:a7354389-079e-4844-93b5-af6b7bf1d535</wsa:RelatesTo> + <wsa:To>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</wsa:To> + <wsse:Security> + <wsu:Timestamp wsu:Id="Timestamp-468a08b7-c8fd-44bf-a2c8-fd6063127ca6"> + <wsu:Created>2022-04-21T19:21:52Z</wsu:Created> + <wsu:Expires>2022-04-21T19:26:52Z</wsu:Expires> + </wsu:Timestamp> + </wsse:Security> + </soap:Header> + <soap:Body> + <RetrieveResponseMsg xmlns="http://exacttarget.com/wsdl/partnerAPI"> + <OverallStatus>OK</OverallStatus> + <RequestID>cfe51e71-6a2b-4cb4-aecd-3777076d63bc</RequestID> + <Results xsi:type="DataExtensionField"> + <PartnerKey xsi:nil="true" /> + <ObjectID>bea0e308-5d45-4181-a673-da9972a7c674</ObjectID> + <CustomerKey>[testExisting_dataExtension].[LastName]</CustomerKey> + <Name>LastName</Name> + <Scale>0</Scale> + <DefaultValue /> + <MaxLength>50</MaxLength> + <IsRequired>false</IsRequired> + <Ordinal>1</Ordinal> + <IsPrimaryKey>false</IsPrimaryKey> + <FieldType>Text</FieldType> + <DataExtension> + <PartnerKey xsi:nil="true" /> + <ObjectID xsi:nil="true" /> + <CustomerKey>testExisting_dataExtension</CustomerKey> + </DataExtension> + </Results> + </RetrieveResponseMsg> + </soap:Body> +</soap:Envelope> diff --git a/test/resources/9999999/dataExtensionField/retrieve-DataExtension.CustomerKey=testExisting_dataExtension-response.xml b/test/resources/9999999/dataExtensionField/retrieve-DataExtension.CustomerKey=testExisting_dataExtension-response.xml new file mode 100644 index 000000000..c927c2258 --- /dev/null +++ b/test/resources/9999999/dataExtensionField/retrieve-DataExtension.CustomerKey=testExisting_dataExtension-response.xml @@ -0,0 +1,133 @@ +<?xml version="1.0" encoding="utf-8"?> +<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:xsd="http://www.w3.org/2001/XMLSchema" + xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing" + xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" + xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"> + <soap:Header> + <wsa:Action>RetrieveResponse</wsa:Action> + <wsa:MessageID>urn:uuid:6d2f81c8-80ab-44d5-8664-206753e7ac8d</wsa:MessageID> + <wsa:RelatesTo>urn:uuid:a7354389-079e-4844-93b5-af6b7bf1d535</wsa:RelatesTo> + <wsa:To>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</wsa:To> + <wsse:Security> + <wsu:Timestamp wsu:Id="Timestamp-468a08b7-c8fd-44bf-a2c8-fd6063127ca6"> + <wsu:Created>2022-04-21T19:21:52Z</wsu:Created> + <wsu:Expires>2022-04-21T19:26:52Z</wsu:Expires> + </wsu:Timestamp> + </wsse:Security> + </soap:Header> + <soap:Body> + <RetrieveResponseMsg xmlns="http://exacttarget.com/wsdl/partnerAPI"> + <OverallStatus>OK</OverallStatus> + <RequestID>cfe51e71-6a2b-4cb4-aecd-3777076d63bc</RequestID> + <Results xsi:type="DataExtensionField"> + <PartnerKey xsi:nil="true" /> + <ObjectID>8018397d-880d-4f88-940e-3b4eca098a0c</ObjectID> + <CustomerKey>[testExisting_dataExtension].[ContactKey]</CustomerKey> + <Name>ContactKey</Name> + <Scale>0</Scale> + <DefaultValue /> + <MaxLength>50</MaxLength> + <IsRequired>true</IsRequired> + <Ordinal>3</Ordinal> + <IsPrimaryKey>true</IsPrimaryKey> + <FieldType>Text</FieldType> + <DataExtension> + <PartnerKey xsi:nil="true" /> + <ObjectID xsi:nil="true" /> + <CustomerKey>testExisting_dataExtension</CustomerKey> + </DataExtension> + </Results> + <Results xsi:type="DataExtensionField"> + <PartnerKey xsi:nil="true" /> + <ObjectID>bea0e308-5d45-4181-a673-da9972a7c674</ObjectID> + <CustomerKey>[testExisting_dataExtension].[LastName]</CustomerKey> + <Name>LastName</Name> + <Scale>0</Scale> + <DefaultValue /> + <MaxLength>50</MaxLength> + <IsRequired>false</IsRequired> + <Ordinal>1</Ordinal> + <IsPrimaryKey>false</IsPrimaryKey> + <FieldType>Text</FieldType> + <DataExtension> + <PartnerKey xsi:nil="true" /> + <ObjectID xsi:nil="true" /> + <CustomerKey>testExisting_dataExtension</CustomerKey> + </DataExtension> + </Results> + <Results xsi:type="DataExtensionField"> + <PartnerKey xsi:nil="true" /> + <ObjectID>2557b461-a699-4744-950d-e80a19afc2dc</ObjectID> + <CustomerKey>[testExisting_dataExtension].[EmailAddress]</CustomerKey> + <Name>EmailAddress</Name> + <Scale>0</Scale> + <DefaultValue /> + <MaxLength>254</MaxLength> + <IsRequired>true</IsRequired> + <Ordinal>2</Ordinal> + <IsPrimaryKey>false</IsPrimaryKey> + <FieldType>EmailAddress</FieldType> + <DataExtension> + <PartnerKey xsi:nil="true" /> + <ObjectID xsi:nil="true" /> + <CustomerKey>testExisting_dataExtension</CustomerKey> + </DataExtension> + </Results> + <Results xsi:type="DataExtensionField"> + <PartnerKey xsi:nil="true" /> + <ObjectID>42760528-a8c5-44dd-8c1d-ff34e5daee54</ObjectID> + <CustomerKey>[testExisting_dataExtension].[FirstName]</CustomerKey> + <Name>FirstName</Name> + <Scale>0</Scale> + <DefaultValue /> + <MaxLength>50</MaxLength> + <IsRequired>false</IsRequired> + <Ordinal>0</Ordinal> + <IsPrimaryKey>false</IsPrimaryKey> + <FieldType>Text</FieldType> + <DataExtension> + <PartnerKey xsi:nil="true" /> + <ObjectID xsi:nil="true" /> + <CustomerKey>testExisting_dataExtension</CustomerKey> + </DataExtension> + </Results> + <Results xsi:type="DataExtensionField"> + <PartnerKey xsi:nil="true" /> + <ObjectID>7b7ef009-4b85-455b-9bdf-b7bef93791d7</ObjectID> + <CustomerKey>[testExisting_dataExtension].[numberField]</CustomerKey> + <Name>numberField</Name> + <Scale>0</Scale> + <DefaultValue /> + <IsRequired>true</IsRequired> + <Ordinal>5</Ordinal> + <IsPrimaryKey>false</IsPrimaryKey> + <FieldType>Number</FieldType> + <DataExtension> + <PartnerKey xsi:nil="true" /> + <ObjectID xsi:nil="true" /> + <CustomerKey>testExisting_dataExtension</CustomerKey> + </DataExtension> + </Results> + <Results xsi:type="DataExtensionField"> + <PartnerKey xsi:nil="true" /> + <ObjectID>c5d553cc-2c2a-464d-953d-6901be040f20</ObjectID> + <CustomerKey>[testExisting_dataExtension].[decimalField]</CustomerKey> + <Name>decimalField</Name> + <Scale>3</Scale> + <DefaultValue /> + <MaxLength>6</MaxLength> + <IsRequired>true</IsRequired> + <Ordinal>4</Ordinal> + <IsPrimaryKey>false</IsPrimaryKey> + <FieldType>Decimal</FieldType> + <DataExtension> + <PartnerKey xsi:nil="true" /> + <ObjectID xsi:nil="true" /> + <CustomerKey>testExisting_dataExtension</CustomerKey> + </DataExtension> + </Results> + </RetrieveResponseMsg> + </soap:Body> +</soap:Envelope> diff --git a/test/resources/9999999/dataExtensionField/retrieve-DataExtension.CustomerKey=testNew_dataExtensionORDataExtension.CustomerKey=testExisting_dataExtension-response.xml b/test/resources/9999999/dataExtensionField/retrieve-DataExtension.CustomerKey=testNew_dataExtensionORDataExtension.CustomerKey=testExisting_dataExtension-response.xml new file mode 100644 index 000000000..8018e9949 --- /dev/null +++ b/test/resources/9999999/dataExtensionField/retrieve-DataExtension.CustomerKey=testNew_dataExtensionORDataExtension.CustomerKey=testExisting_dataExtension-response.xml @@ -0,0 +1,99 @@ +<!-- used by deploy to get existing fields for existing and new dataExtension --> +<?xml version="1.0" encoding="utf-8"?> +<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:xsd="http://www.w3.org/2001/XMLSchema" + xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing" + xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" + xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"> + <soap:Header> + <wsa:Action>RetrieveResponse</wsa:Action> + <wsa:MessageID>urn:uuid:6d2f81c8-80ab-44d5-8664-206753e7ac8d</wsa:MessageID> + <wsa:RelatesTo>urn:uuid:a7354389-079e-4844-93b5-af6b7bf1d535</wsa:RelatesTo> + <wsa:To>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</wsa:To> + <wsse:Security> + <wsu:Timestamp wsu:Id="Timestamp-468a08b7-c8fd-44bf-a2c8-fd6063127ca6"> + <wsu:Created>2022-04-21T19:21:52Z</wsu:Created> + <wsu:Expires>2022-04-21T19:26:52Z</wsu:Expires> + </wsu:Timestamp> + </wsse:Security> + </soap:Header> + <soap:Body> + <RetrieveResponseMsg xmlns="http://exacttarget.com/wsdl/partnerAPI"> + <OverallStatus>OK</OverallStatus> + <RequestID>cfe51e71-6a2b-4cb4-aecd-3777076d63bc</RequestID> + <Results xsi:type="DataExtensionField"> + <PartnerKey xsi:nil="true" /> + <ObjectID>8018397d-880d-4f88-940e-3b4eca098a0c</ObjectID> + <CustomerKey>[testExisting_dataExtension].[ContactKey]</CustomerKey> + <Name>ContactKey</Name> + <Scale>0</Scale> + <DefaultValue /> + <MaxLength>50</MaxLength> + <IsRequired>true</IsRequired> + <Ordinal>3</Ordinal> + <IsPrimaryKey>true</IsPrimaryKey> + <FieldType>Text</FieldType> + <DataExtension> + <PartnerKey xsi:nil="true" /> + <ObjectID xsi:nil="true" /> + <CustomerKey>testExisting_dataExtension</CustomerKey> + </DataExtension> + </Results> + <Results xsi:type="DataExtensionField"> + <PartnerKey xsi:nil="true" /> + <ObjectID>bea0e308-5d45-4181-a673-da9972a7c674</ObjectID> + <CustomerKey>[testExisting_dataExtension].[LastName]</CustomerKey> + <Name>LastName</Name> + <Scale>0</Scale> + <DefaultValue /> + <MaxLength>50</MaxLength> + <IsRequired>false</IsRequired> + <Ordinal>1</Ordinal> + <IsPrimaryKey>false</IsPrimaryKey> + <FieldType>Text</FieldType> + <DataExtension> + <PartnerKey xsi:nil="true" /> + <ObjectID xsi:nil="true" /> + <CustomerKey>testExisting_dataExtension</CustomerKey> + </DataExtension> + </Results> + <Results xsi:type="DataExtensionField"> + <PartnerKey xsi:nil="true" /> + <ObjectID>2557b461-a699-4744-950d-e80a19afc2dc</ObjectID> + <CustomerKey>[testExisting_dataExtension].[EmailAddress]</CustomerKey> + <Name>EmailAddress</Name> + <Scale>0</Scale> + <DefaultValue /> + <MaxLength>254</MaxLength> + <IsRequired>true</IsRequired> + <Ordinal>2</Ordinal> + <IsPrimaryKey>false</IsPrimaryKey> + <FieldType>EmailAddress</FieldType> + <DataExtension> + <PartnerKey xsi:nil="true" /> + <ObjectID xsi:nil="true" /> + <CustomerKey>testExisting_dataExtension</CustomerKey> + </DataExtension> + </Results> + <Results xsi:type="DataExtensionField"> + <PartnerKey xsi:nil="true" /> + <ObjectID>42760528-a8c5-44dd-8c1d-ff34e5daee54</ObjectID> + <CustomerKey>[testExisting_dataExtension].[FirstName]</CustomerKey> + <Name>FirstName</Name> + <Scale>0</Scale> + <DefaultValue /> + <MaxLength>50</MaxLength> + <IsRequired>false</IsRequired> + <Ordinal>0</Ordinal> + <IsPrimaryKey>false</IsPrimaryKey> + <FieldType>Text</FieldType> + <DataExtension> + <PartnerKey xsi:nil="true" /> + <ObjectID xsi:nil="true" /> + <CustomerKey>testExisting_dataExtension</CustomerKey> + </DataExtension> + </Results> + </RetrieveResponseMsg> + </soap:Body> +</soap:Envelope> \ No newline at end of file diff --git a/test/resources/9999999/dataExtensionField/retrieve-DataExtension.CustomerKey=testNew_event_withSchema-response.xml b/test/resources/9999999/dataExtensionField/retrieve-DataExtension.CustomerKey=testNew_event_withSchema-response.xml new file mode 100644 index 000000000..9f1ab63ce --- /dev/null +++ b/test/resources/9999999/dataExtensionField/retrieve-DataExtension.CustomerKey=testNew_event_withSchema-response.xml @@ -0,0 +1,461 @@ +<?xml version="1.0" encoding="utf-8"?> +<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:xsd="http://www.w3.org/2001/XMLSchema" + xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing" + xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" + xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"> + <soap:Header> + <wsa:Action>RetrieveResponse</wsa:Action> + <wsa:MessageID>urn:uuid:6d2f81c8-80ab-44d5-8664-206753e7ac8d</wsa:MessageID> + <wsa:RelatesTo>urn:uuid:a7354389-079e-4844-93b5-af6b7bf1d535</wsa:RelatesTo> + <wsa:To>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</wsa:To> + <wsse:Security> + <wsu:Timestamp wsu:Id="Timestamp-468a08b7-c8fd-44bf-a2c8-fd6063127ca6"> + <wsu:Created>2022-04-21T19:21:52Z</wsu:Created> + <wsu:Expires>2022-04-21T19:26:52Z</wsu:Expires> + </wsu:Timestamp> + </wsse:Security> + </soap:Header> + <soap:Body> + <RetrieveResponseMsg xmlns="http://exacttarget.com/wsdl/partnerAPI"> + <OverallStatus>OK</OverallStatus> + <RequestID>cfe51e71-6a2b-4cb4-aecd-3777076d63bc</RequestID> + <Results xsi:type="DataExtensionField"> + <PartnerKey xsi:nil="true" /> + <ObjectID>eb18160e-ec0f-46ca-b59a-1287dbeb7172</ObjectID> + <CustomerKey>[testNew_event_withSchema].[DisplayName]</CustomerKey> + <Name>DisplayName</Name> + <DefaultValue /> + <MaxLength>256</MaxLength> + <IsRequired>false</IsRequired> + <Ordinal>15</Ordinal> + <IsPrimaryKey>false</IsPrimaryKey> + <FieldType>Text</FieldType> + <DataExtension> + <PartnerKey xsi:nil="true" /> + <ObjectID xsi:nil="true" /> + <CustomerKey>testNew_event_withSchema</CustomerKey> + </DataExtension> + </Results> + <Results xsi:type="DataExtensionField"> + <PartnerKey xsi:nil="true" /> + <ObjectID>ae0a3a3e-e81a-4b13-9a70-12ff6903c901</ObjectID> + <CustomerKey>[testNew_event_withSchema].[PreferredLanguage]</CustomerKey> + <Name>PreferredLanguage</Name> + <DefaultValue /> + <MaxLength>50</MaxLength> + <IsRequired>false</IsRequired> + <Ordinal>6</Ordinal> + <IsPrimaryKey>false</IsPrimaryKey> + <FieldType>Text</FieldType> + <DataExtension> + <PartnerKey xsi:nil="true" /> + <ObjectID xsi:nil="true" /> + <CustomerKey>testNew_event_withSchema</CustomerKey> + </DataExtension> + </Results> + <Results xsi:type="DataExtensionField"> + <PartnerKey xsi:nil="true" /> + <ObjectID>3d39db8b-b561-4227-9051-1c201c79033e</ObjectID> + <CustomerKey>[testNew_event_withSchema].[FirstReminderDate]</CustomerKey> + <Name>FirstReminderDate</Name> + <DefaultValue /> + <IsRequired>false</IsRequired> + <Ordinal>12</Ordinal> + <IsPrimaryKey>false</IsPrimaryKey> + <FieldType>Date</FieldType> + <DataExtension> + <PartnerKey xsi:nil="true" /> + <ObjectID xsi:nil="true" /> + <CustomerKey>testNew_event_withSchema</CustomerKey> + </DataExtension> + </Results> + <Results xsi:type="DataExtensionField"> + <PartnerKey xsi:nil="true" /> + <ObjectID>4eadce50-f552-41e5-8318-2fd367f043b9</ObjectID> + <CustomerKey>[testNew_event_withSchema].[Description]</CustomerKey> + <Name>Description</Name> + <DefaultValue /> + <MaxLength>4000</MaxLength> + <IsRequired>false</IsRequired> + <Ordinal>17</Ordinal> + <IsPrimaryKey>false</IsPrimaryKey> + <FieldType>Text</FieldType> + <DataExtension> + <PartnerKey xsi:nil="true" /> + <ObjectID xsi:nil="true" /> + <CustomerKey>testNew_event_withSchema</CustomerKey> + </DataExtension> + </Results> + <Results xsi:type="DataExtensionField"> + <PartnerKey xsi:nil="true" /> + <ObjectID>d2826773-6965-4e78-9a05-3008ea45a104</ObjectID> + <CustomerKey>[testNew_event_withSchema].[EndDate]</CustomerKey> + <Name>EndDate</Name> + <DefaultValue /> + <IsRequired>false</IsRequired> + <Ordinal>10</Ordinal> + <IsPrimaryKey>false</IsPrimaryKey> + <FieldType>Date</FieldType> + <DataExtension> + <PartnerKey xsi:nil="true" /> + <ObjectID xsi:nil="true" /> + <CustomerKey>testNew_event_withSchema</CustomerKey> + </DataExtension> + </Results> + <Results xsi:type="DataExtensionField"> + <PartnerKey xsi:nil="true" /> + <ObjectID>3bb8fa91-5881-4ca1-ac09-30604ba0b9be</ObjectID> + <CustomerKey>[testNew_event_withSchema].[TaskArea]</CustomerKey> + <Name>TaskArea</Name> + <DefaultValue /> + <MaxLength>255</MaxLength> + <IsRequired>false</IsRequired> + <Ordinal>25</Ordinal> + <IsPrimaryKey>false</IsPrimaryKey> + <FieldType>Text</FieldType> + <DataExtension> + <PartnerKey xsi:nil="true" /> + <ObjectID xsi:nil="true" /> + <CustomerKey>testNew_event_withSchema</CustomerKey> + </DataExtension> + </Results> + <Results xsi:type="DataExtensionField"> + <PartnerKey xsi:nil="true" /> + <ObjectID>721b938f-67ab-4d82-bb1c-33add4ec1533</ObjectID> + <CustomerKey>[testNew_event_withSchema].[ContactId]</CustomerKey> + <Name>ContactId</Name> + <DefaultValue /> + <MaxLength>18</MaxLength> + <IsRequired>true</IsRequired> + <Ordinal>0</Ordinal> + <IsPrimaryKey>true</IsPrimaryKey> + <FieldType>Text</FieldType> + <DataExtension> + <PartnerKey xsi:nil="true" /> + <ObjectID xsi:nil="true" /> + <CustomerKey>testNew_event_withSchema</CustomerKey> + </DataExtension> + </Results> + <Results xsi:type="DataExtensionField"> + <PartnerKey xsi:nil="true" /> + <ObjectID>5ccee5f6-f282-4741-899d-400b05c57425</ObjectID> + <CustomerKey>[testNew_event_withSchema].[FirstName]</CustomerKey> + <Name>FirstName</Name> + <DefaultValue /> + <MaxLength>256</MaxLength> + <IsRequired>false</IsRequired> + <Ordinal>4</Ordinal> + <IsPrimaryKey>false</IsPrimaryKey> + <FieldType>Text</FieldType> + <DataExtension> + <PartnerKey xsi:nil="true" /> + <ObjectID xsi:nil="true" /> + <CustomerKey>testNew_event_withSchema</CustomerKey> + </DataExtension> + </Results> + <Results xsi:type="DataExtensionField"> + <PartnerKey xsi:nil="true" /> + <ObjectID>d0ec626c-7cba-492b-abd0-48484e0c18bb</ObjectID> + <CustomerKey>[testNew_event_withSchema].[Type]</CustomerKey> + <Name>Type</Name> + <DefaultValue /> + <MaxLength>50</MaxLength> + <IsRequired>true</IsRequired> + <Ordinal>1</Ordinal> + <IsPrimaryKey>false</IsPrimaryKey> + <FieldType>Text</FieldType> + <DataExtension> + <PartnerKey xsi:nil="true" /> + <ObjectID xsi:nil="true" /> + <CustomerKey>testNew_event_withSchema</CustomerKey> + </DataExtension> + </Results> + <Results xsi:type="DataExtensionField"> + <PartnerKey xsi:nil="true" /> + <ObjectID>0d49e8cf-cce9-4323-9b17-52f2366f9fc2</ObjectID> + <CustomerKey>[testNew_event_withSchema].[Datestamp]</CustomerKey> + <Name>Datestamp</Name> + <DefaultValue>GetDate()</DefaultValue> + <IsRequired>false</IsRequired> + <Ordinal>8</Ordinal> + <IsPrimaryKey>false</IsPrimaryKey> + <FieldType>Date</FieldType> + <DataExtension> + <PartnerKey xsi:nil="true" /> + <ObjectID xsi:nil="true" /> + <CustomerKey>testNew_event_withSchema</CustomerKey> + </DataExtension> + </Results> + <Results xsi:type="DataExtensionField"> + <PartnerKey xsi:nil="true" /> + <ObjectID>c44861f7-bac3-4b32-a5f8-744f67a66aaa</ObjectID> + <CustomerKey>[testNew_event_withSchema].[Email]</CustomerKey> + <Name>Email</Name> + <DefaultValue /> + <MaxLength>254</MaxLength> + <IsRequired>false</IsRequired> + <Ordinal>21</Ordinal> + <IsPrimaryKey>false</IsPrimaryKey> + <FieldType>EmailAddress</FieldType> + <DataExtension> + <PartnerKey xsi:nil="true" /> + <ObjectID xsi:nil="true" /> + <CustomerKey>testNew_event_withSchema</CustomerKey> + </DataExtension> + </Results> + <Results xsi:type="DataExtensionField"> + <PartnerKey xsi:nil="true" /> + <ObjectID>c78d6054-5ce0-4438-a7ad-76b375224033</ObjectID> + <CustomerKey>[testNew_event_withSchema].[Status]</CustomerKey> + <Name>Status</Name> + <DefaultValue /> + <MaxLength>50</MaxLength> + <IsRequired>true</IsRequired> + <Ordinal>2</Ordinal> + <IsPrimaryKey>true</IsPrimaryKey> + <FieldType>Text</FieldType> + <DataExtension> + <PartnerKey xsi:nil="true" /> + <ObjectID xsi:nil="true" /> + <CustomerKey>testNew_event_withSchema</CustomerKey> + </DataExtension> + </Results> + <Results xsi:type="DataExtensionField"> + <PartnerKey xsi:nil="true" /> + <ObjectID>541b063f-7c25-45b2-af53-7fdafbe0ee12</ObjectID> + <CustomerKey>[testNew_event_withSchema].[BroadcastedNotificationDate]</CustomerKey> + <Name>BroadcastedNotificationDate</Name> + <DefaultValue /> + <IsRequired>false</IsRequired> + <Ordinal>11</Ordinal> + <IsPrimaryKey>false</IsPrimaryKey> + <FieldType>Date</FieldType> + <DataExtension> + <PartnerKey xsi:nil="true" /> + <ObjectID xsi:nil="true" /> + <CustomerKey>testNew_event_withSchema</CustomerKey> + </DataExtension> + </Results> + <Results xsi:type="DataExtensionField"> + <PartnerKey xsi:nil="true" /> + <ObjectID>ff54519e-931b-432f-9083-861213fa9460</ObjectID> + <CustomerKey>[testNew_event_withSchema].[TouchPoint]</CustomerKey> + <Name>TouchPoint</Name> + <DefaultValue /> + <MaxLength>256</MaxLength> + <IsRequired>false</IsRequired> + <Ordinal>7</Ordinal> + <IsPrimaryKey>false</IsPrimaryKey> + <FieldType>Text</FieldType> + <DataExtension> + <PartnerKey xsi:nil="true" /> + <ObjectID xsi:nil="true" /> + <CustomerKey>testNew_event_withSchema</CustomerKey> + </DataExtension> + </Results> + <Results xsi:type="DataExtensionField"> + <PartnerKey xsi:nil="true" /> + <ObjectID>f0a58625-0b62-496f-bea9-9d2722e50864</ObjectID> + <CustomerKey>[testNew_event_withSchema].[Points]</CustomerKey> + <Name>Points</Name> + <DefaultValue /> + <IsRequired>false</IsRequired> + <Ordinal>23</Ordinal> + <IsPrimaryKey>false</IsPrimaryKey> + <FieldType>Number</FieldType> + <DataExtension> + <PartnerKey xsi:nil="true" /> + <ObjectID xsi:nil="true" /> + <CustomerKey>testNew_event_withSchema</CustomerKey> + </DataExtension> + </Results> + <Results xsi:type="DataExtensionField"> + <PartnerKey xsi:nil="true" /> + <ObjectID>43f69e09-9f47-477f-95b6-a9b9b8111f5e</ObjectID> + <CustomerKey>[testNew_event_withSchema].[Title]</CustomerKey> + <Name>Title</Name> + <DefaultValue /> + <MaxLength>256</MaxLength> + <IsRequired>false</IsRequired> + <Ordinal>14</Ordinal> + <IsPrimaryKey>false</IsPrimaryKey> + <FieldType>Text</FieldType> + <DataExtension> + <PartnerKey xsi:nil="true" /> + <ObjectID xsi:nil="true" /> + <CustomerKey>testNew_event_withSchema</CustomerKey> + </DataExtension> + </Results> + <Results xsi:type="DataExtensionField"> + <PartnerKey xsi:nil="true" /> + <ObjectID>e9cd8c9f-39b0-4c93-8fce-aa3f0ca0d310</ObjectID> + <CustomerKey>[testNew_event_withSchema].[SecondReminderDate]</CustomerKey> + <Name>SecondReminderDate</Name> + <DefaultValue /> + <IsRequired>false</IsRequired> + <Ordinal>13</Ordinal> + <IsPrimaryKey>false</IsPrimaryKey> + <FieldType>Date</FieldType> + <DataExtension> + <PartnerKey xsi:nil="true" /> + <ObjectID xsi:nil="true" /> + <CustomerKey>testNew_event_withSchema</CustomerKey> + </DataExtension> + </Results> + <Results xsi:type="DataExtensionField"> + <PartnerKey xsi:nil="true" /> + <ObjectID>403e68ee-f203-42e1-ac48-af18def0cccd</ObjectID> + <CustomerKey>[testNew_event_withSchema].[TaskType]</CustomerKey> + <Name>TaskType</Name> + <DefaultValue /> + <MaxLength>255</MaxLength> + <IsRequired>false</IsRequired> + <Ordinal>24</Ordinal> + <IsPrimaryKey>false</IsPrimaryKey> + <FieldType>Text</FieldType> + <DataExtension> + <PartnerKey xsi:nil="true" /> + <ObjectID xsi:nil="true" /> + <CustomerKey>testNew_event_withSchema</CustomerKey> + </DataExtension> + </Results> + <Results xsi:type="DataExtensionField"> + <PartnerKey xsi:nil="true" /> + <ObjectID>555ad728-f99a-4e13-a992-b70b1ffe36a2</ObjectID> + <CustomerKey>[testNew_event_withSchema].[Respondent]</CustomerKey> + <Name>Respondent</Name> + <DefaultValue /> + <MaxLength>256</MaxLength> + <IsRequired>false</IsRequired> + <Ordinal>3</Ordinal> + <IsPrimaryKey>false</IsPrimaryKey> + <FieldType>Text</FieldType> + <DataExtension> + <PartnerKey xsi:nil="true" /> + <ObjectID xsi:nil="true" /> + <CustomerKey>testNew_event_withSchema</CustomerKey> + </DataExtension> + </Results> + <Results xsi:type="DataExtensionField"> + <PartnerKey xsi:nil="true" /> + <ObjectID>95948e52-e8d0-4908-98a9-cc34cd84233e</ObjectID> + <CustomerKey>[testNew_event_withSchema].[LastName]</CustomerKey> + <Name>LastName</Name> + <DefaultValue /> + <MaxLength>256</MaxLength> + <IsRequired>false</IsRequired> + <Ordinal>5</Ordinal> + <IsPrimaryKey>false</IsPrimaryKey> + <FieldType>Text</FieldType> + <DataExtension> + <PartnerKey xsi:nil="true" /> + <ObjectID xsi:nil="true" /> + <CustomerKey>testNew_event_withSchema</CustomerKey> + </DataExtension> + </Results> + <Results xsi:type="DataExtensionField"> + <PartnerKey xsi:nil="true" /> + <ObjectID>7976b904-1ed5-46f0-a524-cd1a787bfb5e</ObjectID> + <CustomerKey>[testNew_event_withSchema].[FirstReminderChannel]</CustomerKey> + <Name>FirstReminderChannel</Name> + <DefaultValue /> + <MaxLength>256</MaxLength> + <IsRequired>false</IsRequired> + <Ordinal>19</Ordinal> + <IsPrimaryKey>false</IsPrimaryKey> + <FieldType>Text</FieldType> + <DataExtension> + <PartnerKey xsi:nil="true" /> + <ObjectID xsi:nil="true" /> + <CustomerKey>testNew_event_withSchema</CustomerKey> + </DataExtension> + </Results> + <Results xsi:type="DataExtensionField"> + <PartnerKey xsi:nil="true" /> + <ObjectID>ed225fdd-1aff-401d-906e-cd59b4d86fe2</ObjectID> + <CustomerKey>[testNew_event_withSchema].[SecondReminderChannel]</CustomerKey> + <Name>SecondReminderChannel</Name> + <DefaultValue /> + <MaxLength>256</MaxLength> + <IsRequired>false</IsRequired> + <Ordinal>20</Ordinal> + <IsPrimaryKey>false</IsPrimaryKey> + <FieldType>Text</FieldType> + <DataExtension> + <PartnerKey xsi:nil="true" /> + <ObjectID xsi:nil="true" /> + <CustomerKey>testNew_event_withSchema</CustomerKey> + </DataExtension> + </Results> + <Results xsi:type="DataExtensionField"> + <PartnerKey xsi:nil="true" /> + <ObjectID>30222d00-35c5-46e8-ab41-d3febd909eed</ObjectID> + <CustomerKey>[testNew_event_withSchema].[ArticleOrTaskID]</CustomerKey> + <Name>ArticleOrTaskID</Name> + <DefaultValue /> + <MaxLength>18</MaxLength> + <IsRequired>true</IsRequired> + <Ordinal>22</Ordinal> + <IsPrimaryKey>true</IsPrimaryKey> + <FieldType>Text</FieldType> + <DataExtension> + <PartnerKey xsi:nil="true" /> + <ObjectID xsi:nil="true" /> + <CustomerKey>testNew_event_withSchema</CustomerKey> + </DataExtension> + </Results> + <Results xsi:type="DataExtensionField"> + <PartnerKey xsi:nil="true" /> + <ObjectID>8c79306f-4f3a-4925-bd48-e6c6905c157c</ObjectID> + <CustomerKey>[testNew_event_withSchema].[StartDate]</CustomerKey> + <Name>StartDate</Name> + <DefaultValue /> + <IsRequired>false</IsRequired> + <Ordinal>9</Ordinal> + <IsPrimaryKey>false</IsPrimaryKey> + <FieldType>Date</FieldType> + <DataExtension> + <PartnerKey xsi:nil="true" /> + <ObjectID xsi:nil="true" /> + <CustomerKey>testNew_event_withSchema</CustomerKey> + </DataExtension> + </Results> + <Results xsi:type="DataExtensionField"> + <PartnerKey xsi:nil="true" /> + <ObjectID>1892b0ee-26ea-4280-8bca-e8cc5d3f9658</ObjectID> + <CustomerKey>[testNew_event_withSchema].[Channel]</CustomerKey> + <Name>Channel</Name> + <DefaultValue /> + <MaxLength>256</MaxLength> + <IsRequired>false</IsRequired> + <Ordinal>18</Ordinal> + <IsPrimaryKey>false</IsPrimaryKey> + <FieldType>Text</FieldType> + <DataExtension> + <PartnerKey xsi:nil="true" /> + <ObjectID xsi:nil="true" /> + <CustomerKey>testNew_event_withSchema</CustomerKey> + </DataExtension> + </Results> + <Results xsi:type="DataExtensionField"> + <PartnerKey xsi:nil="true" /> + <ObjectID>bf50095e-54ba-42c7-9baf-f91618738d85</ObjectID> + <CustomerKey>[testNew_event_withSchema].[Text]</CustomerKey> + <Name>Text</Name> + <DefaultValue /> + <MaxLength>256</MaxLength> + <IsRequired>false</IsRequired> + <Ordinal>16</Ordinal> + <IsPrimaryKey>false</IsPrimaryKey> + <FieldType>Text</FieldType> + <DataExtension> + <PartnerKey xsi:nil="true" /> + <ObjectID xsi:nil="true" /> + <CustomerKey>testNew_event_withSchema</CustomerKey> + </DataExtension> + </Results> + </RetrieveResponseMsg> + </soap:Body> +</soap:Envelope> diff --git a/test/resources/9999999/dataExtensionField/retrieve-DataExtension.CustomerKeyINtestExisting_dataExtension,testNew_dataExtension-response.xml b/test/resources/9999999/dataExtensionField/retrieve-DataExtension.CustomerKeyINtestExisting_dataExtension,testNew_dataExtension-response.xml new file mode 100644 index 000000000..c927c2258 --- /dev/null +++ b/test/resources/9999999/dataExtensionField/retrieve-DataExtension.CustomerKeyINtestExisting_dataExtension,testNew_dataExtension-response.xml @@ -0,0 +1,133 @@ +<?xml version="1.0" encoding="utf-8"?> +<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:xsd="http://www.w3.org/2001/XMLSchema" + xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing" + xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" + xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"> + <soap:Header> + <wsa:Action>RetrieveResponse</wsa:Action> + <wsa:MessageID>urn:uuid:6d2f81c8-80ab-44d5-8664-206753e7ac8d</wsa:MessageID> + <wsa:RelatesTo>urn:uuid:a7354389-079e-4844-93b5-af6b7bf1d535</wsa:RelatesTo> + <wsa:To>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</wsa:To> + <wsse:Security> + <wsu:Timestamp wsu:Id="Timestamp-468a08b7-c8fd-44bf-a2c8-fd6063127ca6"> + <wsu:Created>2022-04-21T19:21:52Z</wsu:Created> + <wsu:Expires>2022-04-21T19:26:52Z</wsu:Expires> + </wsu:Timestamp> + </wsse:Security> + </soap:Header> + <soap:Body> + <RetrieveResponseMsg xmlns="http://exacttarget.com/wsdl/partnerAPI"> + <OverallStatus>OK</OverallStatus> + <RequestID>cfe51e71-6a2b-4cb4-aecd-3777076d63bc</RequestID> + <Results xsi:type="DataExtensionField"> + <PartnerKey xsi:nil="true" /> + <ObjectID>8018397d-880d-4f88-940e-3b4eca098a0c</ObjectID> + <CustomerKey>[testExisting_dataExtension].[ContactKey]</CustomerKey> + <Name>ContactKey</Name> + <Scale>0</Scale> + <DefaultValue /> + <MaxLength>50</MaxLength> + <IsRequired>true</IsRequired> + <Ordinal>3</Ordinal> + <IsPrimaryKey>true</IsPrimaryKey> + <FieldType>Text</FieldType> + <DataExtension> + <PartnerKey xsi:nil="true" /> + <ObjectID xsi:nil="true" /> + <CustomerKey>testExisting_dataExtension</CustomerKey> + </DataExtension> + </Results> + <Results xsi:type="DataExtensionField"> + <PartnerKey xsi:nil="true" /> + <ObjectID>bea0e308-5d45-4181-a673-da9972a7c674</ObjectID> + <CustomerKey>[testExisting_dataExtension].[LastName]</CustomerKey> + <Name>LastName</Name> + <Scale>0</Scale> + <DefaultValue /> + <MaxLength>50</MaxLength> + <IsRequired>false</IsRequired> + <Ordinal>1</Ordinal> + <IsPrimaryKey>false</IsPrimaryKey> + <FieldType>Text</FieldType> + <DataExtension> + <PartnerKey xsi:nil="true" /> + <ObjectID xsi:nil="true" /> + <CustomerKey>testExisting_dataExtension</CustomerKey> + </DataExtension> + </Results> + <Results xsi:type="DataExtensionField"> + <PartnerKey xsi:nil="true" /> + <ObjectID>2557b461-a699-4744-950d-e80a19afc2dc</ObjectID> + <CustomerKey>[testExisting_dataExtension].[EmailAddress]</CustomerKey> + <Name>EmailAddress</Name> + <Scale>0</Scale> + <DefaultValue /> + <MaxLength>254</MaxLength> + <IsRequired>true</IsRequired> + <Ordinal>2</Ordinal> + <IsPrimaryKey>false</IsPrimaryKey> + <FieldType>EmailAddress</FieldType> + <DataExtension> + <PartnerKey xsi:nil="true" /> + <ObjectID xsi:nil="true" /> + <CustomerKey>testExisting_dataExtension</CustomerKey> + </DataExtension> + </Results> + <Results xsi:type="DataExtensionField"> + <PartnerKey xsi:nil="true" /> + <ObjectID>42760528-a8c5-44dd-8c1d-ff34e5daee54</ObjectID> + <CustomerKey>[testExisting_dataExtension].[FirstName]</CustomerKey> + <Name>FirstName</Name> + <Scale>0</Scale> + <DefaultValue /> + <MaxLength>50</MaxLength> + <IsRequired>false</IsRequired> + <Ordinal>0</Ordinal> + <IsPrimaryKey>false</IsPrimaryKey> + <FieldType>Text</FieldType> + <DataExtension> + <PartnerKey xsi:nil="true" /> + <ObjectID xsi:nil="true" /> + <CustomerKey>testExisting_dataExtension</CustomerKey> + </DataExtension> + </Results> + <Results xsi:type="DataExtensionField"> + <PartnerKey xsi:nil="true" /> + <ObjectID>7b7ef009-4b85-455b-9bdf-b7bef93791d7</ObjectID> + <CustomerKey>[testExisting_dataExtension].[numberField]</CustomerKey> + <Name>numberField</Name> + <Scale>0</Scale> + <DefaultValue /> + <IsRequired>true</IsRequired> + <Ordinal>5</Ordinal> + <IsPrimaryKey>false</IsPrimaryKey> + <FieldType>Number</FieldType> + <DataExtension> + <PartnerKey xsi:nil="true" /> + <ObjectID xsi:nil="true" /> + <CustomerKey>testExisting_dataExtension</CustomerKey> + </DataExtension> + </Results> + <Results xsi:type="DataExtensionField"> + <PartnerKey xsi:nil="true" /> + <ObjectID>c5d553cc-2c2a-464d-953d-6901be040f20</ObjectID> + <CustomerKey>[testExisting_dataExtension].[decimalField]</CustomerKey> + <Name>decimalField</Name> + <Scale>3</Scale> + <DefaultValue /> + <MaxLength>6</MaxLength> + <IsRequired>true</IsRequired> + <Ordinal>4</Ordinal> + <IsPrimaryKey>false</IsPrimaryKey> + <FieldType>Decimal</FieldType> + <DataExtension> + <PartnerKey xsi:nil="true" /> + <ObjectID xsi:nil="true" /> + <CustomerKey>testExisting_dataExtension</CustomerKey> + </DataExtension> + </Results> + </RetrieveResponseMsg> + </soap:Body> +</soap:Envelope> diff --git a/test/resources/9999999/dataExtensionField/retrieve-Name=FirstName-response.xml b/test/resources/9999999/dataExtensionField/retrieve-Name=FirstName-response.xml new file mode 100644 index 000000000..ff53ea3b2 --- /dev/null +++ b/test/resources/9999999/dataExtensionField/retrieve-Name=FirstName-response.xml @@ -0,0 +1,78 @@ +<?xml version="1.0" encoding="utf-8"?> +<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:xsd="http://www.w3.org/2001/XMLSchema" + xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing" + xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" + xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"> + <soap:Header> + <wsa:Action>RetrieveResponse</wsa:Action> + <wsa:MessageID>urn:uuid:6d2f81c8-80ab-44d5-8664-206753e7ac8d</wsa:MessageID> + <wsa:RelatesTo>urn:uuid:a7354389-079e-4844-93b5-af6b7bf1d535</wsa:RelatesTo> + <wsa:To>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</wsa:To> + <wsse:Security> + <wsu:Timestamp wsu:Id="Timestamp-468a08b7-c8fd-44bf-a2c8-fd6063127ca6"> + <wsu:Created>2022-04-21T19:21:52Z</wsu:Created> + <wsu:Expires>2022-04-21T19:26:52Z</wsu:Expires> + </wsu:Timestamp> + </wsse:Security> + </soap:Header> + <soap:Body> + <RetrieveResponseMsg xmlns="http://exacttarget.com/wsdl/partnerAPI"> + <OverallStatus>OK</OverallStatus> + <RequestID>cfe51e71-6a2b-4cb4-aecd-3777076d63bc</RequestID> + <Results xsi:type="DataExtensionField"> + <PartnerKey xsi:nil="true" /> + <ObjectID>42760528-a8c5-44dd-8c1d-ff34e5daee54</ObjectID> + <CustomerKey>[testExisting_dataExtension].[FirstName]</CustomerKey> + <Name>FirstName</Name> + <Scale>0</Scale> + <DefaultValue /> + <MaxLength>50</MaxLength> + <IsRequired>false</IsRequired> + <Ordinal>0</Ordinal> + <IsPrimaryKey>false</IsPrimaryKey> + <FieldType>Text</FieldType> + <DataExtension> + <PartnerKey xsi:nil="true" /> + <ObjectID xsi:nil="true" /> + <CustomerKey>testExisting_dataExtension</CustomerKey> + </DataExtension> + </Results> + <Results xsi:type="DataExtensionField"> + <PartnerKey xsi:nil="true" /> + <ObjectID>5ccee5f6-f282-4741-899d-400b05c57425</ObjectID> + <CustomerKey>[testExisting_event - 2024-07-05T080154625].[FirstName]</CustomerKey> + <Name>FirstName</Name> + <DefaultValue /> + <MaxLength>256</MaxLength> + <IsRequired>false</IsRequired> + <Ordinal>4</Ordinal> + <IsPrimaryKey>false</IsPrimaryKey> + <FieldType>Text</FieldType> + <DataExtension> + <PartnerKey xsi:nil="true" /> + <ObjectID xsi:nil="true" /> + <CustomerKey>testExisting_event - 2024-07-05T080154625</CustomerKey> + </DataExtension> + </Results> + <Results xsi:type="DataExtensionField"> + <PartnerKey xsi:nil="true" /> + <ObjectID>5ccee5f6-f282-4741-899d-400b05c57425</ObjectID> + <CustomerKey>[testNew_event_withSchema - 2024-07-08T014814443].[FirstName]</CustomerKey> + <Name>FirstName</Name> + <DefaultValue /> + <MaxLength>256</MaxLength> + <IsRequired>false</IsRequired> + <Ordinal>4</Ordinal> + <IsPrimaryKey>false</IsPrimaryKey> + <FieldType>Text</FieldType> + <DataExtension> + <PartnerKey xsi:nil="true" /> + <ObjectID xsi:nil="true" /> + <CustomerKey>testNew_event_withSchema - 2024-07-08T014814443</CustomerKey> + </DataExtension> + </Results> + </RetrieveResponseMsg> + </soap:Body> +</soap:Envelope> diff --git a/test/resources/9999999/dataExtensionField/retrieve-Name=LastName-response.xml b/test/resources/9999999/dataExtensionField/retrieve-Name=LastName-response.xml new file mode 100644 index 000000000..2725e1060 --- /dev/null +++ b/test/resources/9999999/dataExtensionField/retrieve-Name=LastName-response.xml @@ -0,0 +1,78 @@ +<?xml version="1.0" encoding="utf-8"?> +<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:xsd="http://www.w3.org/2001/XMLSchema" + xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing" + xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" + xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"> + <soap:Header> + <wsa:Action>RetrieveResponse</wsa:Action> + <wsa:MessageID>urn:uuid:6d2f81c8-80ab-44d5-8664-206753e7ac8d</wsa:MessageID> + <wsa:RelatesTo>urn:uuid:a7354389-079e-4844-93b5-af6b7bf1d535</wsa:RelatesTo> + <wsa:To>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</wsa:To> + <wsse:Security> + <wsu:Timestamp wsu:Id="Timestamp-468a08b7-c8fd-44bf-a2c8-fd6063127ca6"> + <wsu:Created>2022-04-21T19:21:52Z</wsu:Created> + <wsu:Expires>2022-04-21T19:26:52Z</wsu:Expires> + </wsu:Timestamp> + </wsse:Security> + </soap:Header> + <soap:Body> + <RetrieveResponseMsg xmlns="http://exacttarget.com/wsdl/partnerAPI"> + <OverallStatus>OK</OverallStatus> + <RequestID>cfe51e71-6a2b-4cb4-aecd-3777076d63bc</RequestID> + <Results xsi:type="DataExtensionField"> + <PartnerKey xsi:nil="true" /> + <ObjectID>bea0e308-5d45-4181-a673-da9972a7c674</ObjectID> + <CustomerKey>[testExisting_dataExtension].[LastName]</CustomerKey> + <Name>LastName</Name> + <Scale>0</Scale> + <DefaultValue /> + <MaxLength>50</MaxLength> + <IsRequired>false</IsRequired> + <Ordinal>1</Ordinal> + <IsPrimaryKey>false</IsPrimaryKey> + <FieldType>Text</FieldType> + <DataExtension> + <PartnerKey xsi:nil="true" /> + <ObjectID xsi:nil="true" /> + <CustomerKey>testExisting_dataExtension</CustomerKey> + </DataExtension> + </Results> + <Results xsi:type="DataExtensionField"> + <PartnerKey xsi:nil="true" /> + <ObjectID>95948e52-e8d0-4908-98a9-cc34cd84233e</ObjectID> + <CustomerKey>[testExisting_event - 2024-07-05T080154625].[LastName]</CustomerKey> + <Name>LastName</Name> + <DefaultValue /> + <MaxLength>256</MaxLength> + <IsRequired>false</IsRequired> + <Ordinal>5</Ordinal> + <IsPrimaryKey>false</IsPrimaryKey> + <FieldType>Text</FieldType> + <DataExtension> + <PartnerKey xsi:nil="true" /> + <ObjectID xsi:nil="true" /> + <CustomerKey>testExisting_event - 2024-07-05T080154625</CustomerKey> + </DataExtension> + </Results> + <Results xsi:type="DataExtensionField"> + <PartnerKey xsi:nil="true" /> + <ObjectID>95948e52-e8d0-4908-98a9-cc34cd84233e</ObjectID> + <CustomerKey>[testNew_event_withSchema - 2024-07-08T014814443].[LastName]</CustomerKey> + <Name>LastName</Name> + <DefaultValue /> + <MaxLength>256</MaxLength> + <IsRequired>false</IsRequired> + <Ordinal>5</Ordinal> + <IsPrimaryKey>false</IsPrimaryKey> + <FieldType>Text</FieldType> + <DataExtension> + <PartnerKey xsi:nil="true" /> + <ObjectID xsi:nil="true" /> + <CustomerKey>testNew_event_withSchema - 2024-07-08T014814443</CustomerKey> + </DataExtension> + </Results> + </RetrieveResponseMsg> + </soap:Body> +</soap:Envelope> diff --git a/test/resources/9999999/dataExtensionField/retrieve-response.xml b/test/resources/9999999/dataExtensionField/retrieve-response.xml new file mode 100644 index 000000000..f1a2268c3 --- /dev/null +++ b/test/resources/9999999/dataExtensionField/retrieve-response.xml @@ -0,0 +1,1075 @@ +<?xml version="1.0" encoding="utf-8"?> +<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:xsd="http://www.w3.org/2001/XMLSchema" + xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing" + xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" + xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"> + <soap:Header> + <wsa:Action>RetrieveResponse</wsa:Action> + <wsa:MessageID>urn:uuid:6d2f81c8-80ab-44d5-8664-206753e7ac8d</wsa:MessageID> + <wsa:RelatesTo>urn:uuid:a7354389-079e-4844-93b5-af6b7bf1d535</wsa:RelatesTo> + <wsa:To>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</wsa:To> + <wsse:Security> + <wsu:Timestamp wsu:Id="Timestamp-468a08b7-c8fd-44bf-a2c8-fd6063127ca6"> + <wsu:Created>2022-04-21T19:21:52Z</wsu:Created> + <wsu:Expires>2022-04-21T19:26:52Z</wsu:Expires> + </wsu:Timestamp> + </wsse:Security> + </soap:Header> + <soap:Body> + <RetrieveResponseMsg xmlns="http://exacttarget.com/wsdl/partnerAPI"> + <OverallStatus>OK</OverallStatus> + <RequestID>cfe51e71-6a2b-4cb4-aecd-3777076d63bc</RequestID> + <Results xsi:type="DataExtensionField"> + <PartnerKey xsi:nil="true" /> + <ObjectID>8018397d-880d-4f88-940e-3b4eca098a0c</ObjectID> + <CustomerKey>[testExisting_dataExtension].[ContactKey]</CustomerKey> + <Name>ContactKey</Name> + <Scale>0</Scale> + <DefaultValue /> + <MaxLength>50</MaxLength> + <IsRequired>true</IsRequired> + <Ordinal>3</Ordinal> + <IsPrimaryKey>true</IsPrimaryKey> + <FieldType>Text</FieldType> + <DataExtension> + <PartnerKey xsi:nil="true" /> + <ObjectID xsi:nil="true" /> + <CustomerKey>testExisting_dataExtension</CustomerKey> + </DataExtension> + </Results> + <Results xsi:type="DataExtensionField"> + <PartnerKey xsi:nil="true" /> + <ObjectID>bea0e308-5d45-4181-a673-da9972a7c674</ObjectID> + <CustomerKey>[testExisting_dataExtension].[LastName]</CustomerKey> + <Name>LastName</Name> + <Scale>0</Scale> + <DefaultValue /> + <MaxLength>50</MaxLength> + <IsRequired>false</IsRequired> + <Ordinal>1</Ordinal> + <IsPrimaryKey>false</IsPrimaryKey> + <FieldType>Text</FieldType> + <DataExtension> + <PartnerKey xsi:nil="true" /> + <ObjectID xsi:nil="true" /> + <CustomerKey>testExisting_dataExtension</CustomerKey> + </DataExtension> + </Results> + <Results xsi:type="DataExtensionField"> + <PartnerKey xsi:nil="true" /> + <ObjectID>2557b461-a699-4744-950d-e80a19afc2dc</ObjectID> + <CustomerKey>[testExisting_dataExtension].[EmailAddress]</CustomerKey> + <Name>EmailAddress</Name> + <Scale>0</Scale> + <DefaultValue /> + <MaxLength>254</MaxLength> + <IsRequired>true</IsRequired> + <Ordinal>2</Ordinal> + <IsPrimaryKey>false</IsPrimaryKey> + <FieldType>EmailAddress</FieldType> + <DataExtension> + <PartnerKey xsi:nil="true" /> + <ObjectID xsi:nil="true" /> + <CustomerKey>testExisting_dataExtension</CustomerKey> + </DataExtension> + </Results> + <Results xsi:type="DataExtensionField"> + <PartnerKey xsi:nil="true" /> + <ObjectID>42760528-a8c5-44dd-8c1d-ff34e5daee54</ObjectID> + <CustomerKey>[testExisting_dataExtension].[FirstName]</CustomerKey> + <Name>FirstName</Name> + <Scale>0</Scale> + <DefaultValue /> + <MaxLength>50</MaxLength> + <IsRequired>false</IsRequired> + <Ordinal>0</Ordinal> + <IsPrimaryKey>false</IsPrimaryKey> + <FieldType>Text</FieldType> + <DataExtension> + <PartnerKey xsi:nil="true" /> + <ObjectID xsi:nil="true" /> + <CustomerKey>testExisting_dataExtension</CustomerKey> + </DataExtension> + </Results> + <Results xsi:type="DataExtensionField"> + <PartnerKey xsi:nil="true" /> + <ObjectID>7b7ef009-4b85-455b-9bdf-b7bef93791d7</ObjectID> + <CustomerKey>[testExisting_dataExtension].[numberField]</CustomerKey> + <Name>numberField</Name> + <Scale>0</Scale> + <DefaultValue /> + <IsRequired>true</IsRequired> + <Ordinal>5</Ordinal> + <IsPrimaryKey>false</IsPrimaryKey> + <FieldType>Number</FieldType> + <DataExtension> + <PartnerKey xsi:nil="true" /> + <ObjectID xsi:nil="true" /> + <CustomerKey>testExisting_dataExtension</CustomerKey> + </DataExtension> + </Results> + <Results xsi:type="DataExtensionField"> + <PartnerKey xsi:nil="true" /> + <ObjectID>c5d553cc-2c2a-464d-953d-6901be040f20</ObjectID> + <CustomerKey>[testExisting_dataExtension].[decimalField]</CustomerKey> + <Name>decimalField</Name> + <Scale>3</Scale> + <DefaultValue /> + <MaxLength>6</MaxLength> + <IsRequired>true</IsRequired> + <Ordinal>4</Ordinal> + <IsPrimaryKey>false</IsPrimaryKey> + <FieldType>Decimal</FieldType> + <DataExtension> + <PartnerKey xsi:nil="true" /> + <ObjectID xsi:nil="true" /> + <CustomerKey>testExisting_dataExtension</CustomerKey> + </DataExtension> + </Results> + <Results xsi:type="DataExtensionField"> + <PartnerKey xsi:nil="true" /> + <ObjectID>78b6d411-a5a3-42ac-b9ef-4b5b31db861d</ObjectID> + <CustomerKey>[testExisting_journey_Multistep].[Email]</CustomerKey> + <Name>Email</Name> + <Scale>0</Scale> + <DefaultValue /> + <MaxLength>254</MaxLength> + <IsRequired>true</IsRequired> + <Ordinal>1</Ordinal> + <IsPrimaryKey>false</IsPrimaryKey> + <FieldType>EmailAddress</FieldType> + <DataExtension> + <PartnerKey xsi:nil="true" /> + <ObjectID xsi:nil="true" /> + <CustomerKey>testExisting_journey_Multistep</CustomerKey> + </DataExtension> + </Results> + <Results xsi:type="DataExtensionField"> + <PartnerKey xsi:nil="true" /> + <ObjectID>d38a445a-34b4-499d-9764-ce46cfc675a2</ObjectID> + <CustomerKey>[testExisting_journey_Multistep].[ContactId]</CustomerKey> + <Name>ContactId</Name> + <Scale>0</Scale> + <DefaultValue /> + <MaxLength>50</MaxLength> + <IsRequired>true</IsRequired> + <Ordinal>0</Ordinal> + <IsPrimaryKey>true</IsPrimaryKey> + <FieldType>Text</FieldType> + <DataExtension> + <PartnerKey xsi:nil="true" /> + <ObjectID xsi:nil="true" /> + <CustomerKey>testExisting_journey_Multistep</CustomerKey> + </DataExtension> + </Results> + <Results xsi:type="DataExtensionField"> + <PartnerKey xsi:nil="true" /> + <ObjectID>f8c11314-49fc-4e9b-8971-5d6a50705195</ObjectID> + <CustomerKey>[testExisting_journey_Quicksend].[ContactId]</CustomerKey> + <Name>ContactId</Name> + <Scale>0</Scale> + <DefaultValue /> + <MaxLength>50</MaxLength> + <IsRequired>true</IsRequired> + <Ordinal>0</Ordinal> + <IsPrimaryKey>true</IsPrimaryKey> + <FieldType>Text</FieldType> + <DataExtension> + <PartnerKey xsi:nil="true" /> + <ObjectID xsi:nil="true" /> + <CustomerKey>testExisting_journey_Quicksend</CustomerKey> + </DataExtension> + </Results> + <Results xsi:type="DataExtensionField"> + <PartnerKey xsi:nil="true" /> + <ObjectID>633ca953-b614-4715-8310-91cdadd085c6</ObjectID> + <CustomerKey>[testExisting_journey_Quicksend].[Email]</CustomerKey> + <Name>Email</Name> + <Scale>0</Scale> + <DefaultValue /> + <MaxLength>254</MaxLength> + <IsRequired>true</IsRequired> + <Ordinal>1</Ordinal> + <IsPrimaryKey>false</IsPrimaryKey> + <FieldType>EmailAddress</FieldType> + <DataExtension> + <PartnerKey xsi:nil="true" /> + <ObjectID xsi:nil="true" /> + <CustomerKey>testExisting_journey_Quicksend</CustomerKey> + </DataExtension> + </Results> + <Results xsi:type="DataExtensionField"> + <PartnerKey xsi:nil="true" /> + <ObjectID>eb18160e-ec0f-46ca-b59a-1287dbeb7172</ObjectID> + <CustomerKey>[testExisting_event - 2024-07-05T080154625].[DisplayName]</CustomerKey> + <Name>DisplayName</Name> + <DefaultValue /> + <MaxLength>256</MaxLength> + <IsRequired>false</IsRequired> + <Ordinal>15</Ordinal> + <IsPrimaryKey>false</IsPrimaryKey> + <FieldType>Text</FieldType> + <DataExtension> + <PartnerKey xsi:nil="true" /> + <ObjectID xsi:nil="true" /> + <CustomerKey>testExisting_event - 2024-07-05T080154625</CustomerKey> + </DataExtension> + </Results> + <Results xsi:type="DataExtensionField"> + <PartnerKey xsi:nil="true" /> + <ObjectID>ae0a3a3e-e81a-4b13-9a70-12ff6903c901</ObjectID> + <CustomerKey>[testExisting_event - 2024-07-05T080154625].[PreferredLanguage]</CustomerKey> + <Name>PreferredLanguage</Name> + <DefaultValue /> + <MaxLength>50</MaxLength> + <IsRequired>false</IsRequired> + <Ordinal>6</Ordinal> + <IsPrimaryKey>false</IsPrimaryKey> + <FieldType>Text</FieldType> + <DataExtension> + <PartnerKey xsi:nil="true" /> + <ObjectID xsi:nil="true" /> + <CustomerKey>testExisting_event - 2024-07-05T080154625</CustomerKey> + </DataExtension> + </Results> + <Results xsi:type="DataExtensionField"> + <PartnerKey xsi:nil="true" /> + <ObjectID>3d39db8b-b561-4227-9051-1c201c79033e</ObjectID> + <CustomerKey>[testExisting_event - 2024-07-05T080154625].[FirstReminderDate]</CustomerKey> + <Name>FirstReminderDate</Name> + <DefaultValue /> + <IsRequired>false</IsRequired> + <Ordinal>12</Ordinal> + <IsPrimaryKey>false</IsPrimaryKey> + <FieldType>Date</FieldType> + <DataExtension> + <PartnerKey xsi:nil="true" /> + <ObjectID xsi:nil="true" /> + <CustomerKey>testExisting_event - 2024-07-05T080154625</CustomerKey> + </DataExtension> + </Results> + <Results xsi:type="DataExtensionField"> + <PartnerKey xsi:nil="true" /> + <ObjectID>4eadce50-f552-41e5-8318-2fd367f043b9</ObjectID> + <CustomerKey>[testExisting_event - 2024-07-05T080154625].[Description]</CustomerKey> + <Name>Description</Name> + <DefaultValue /> + <MaxLength>4000</MaxLength> + <IsRequired>false</IsRequired> + <Ordinal>17</Ordinal> + <IsPrimaryKey>false</IsPrimaryKey> + <FieldType>Text</FieldType> + <DataExtension> + <PartnerKey xsi:nil="true" /> + <ObjectID xsi:nil="true" /> + <CustomerKey>testExisting_event - 2024-07-05T080154625</CustomerKey> + </DataExtension> + </Results> + <Results xsi:type="DataExtensionField"> + <PartnerKey xsi:nil="true" /> + <ObjectID>d2826773-6965-4e78-9a05-3008ea45a104</ObjectID> + <CustomerKey>[testExisting_event - 2024-07-05T080154625].[EndDate]</CustomerKey> + <Name>EndDate</Name> + <DefaultValue /> + <IsRequired>false</IsRequired> + <Ordinal>10</Ordinal> + <IsPrimaryKey>false</IsPrimaryKey> + <FieldType>Date</FieldType> + <DataExtension> + <PartnerKey xsi:nil="true" /> + <ObjectID xsi:nil="true" /> + <CustomerKey>testExisting_event - 2024-07-05T080154625</CustomerKey> + </DataExtension> + </Results> + <Results xsi:type="DataExtensionField"> + <PartnerKey xsi:nil="true" /> + <ObjectID>3bb8fa91-5881-4ca1-ac09-30604ba0b9be</ObjectID> + <CustomerKey>[testExisting_event - 2024-07-05T080154625].[TaskArea]</CustomerKey> + <Name>TaskArea</Name> + <DefaultValue /> + <MaxLength>255</MaxLength> + <IsRequired>false</IsRequired> + <Ordinal>25</Ordinal> + <IsPrimaryKey>false</IsPrimaryKey> + <FieldType>Text</FieldType> + <DataExtension> + <PartnerKey xsi:nil="true" /> + <ObjectID xsi:nil="true" /> + <CustomerKey>testExisting_event - 2024-07-05T080154625</CustomerKey> + </DataExtension> + </Results> + <Results xsi:type="DataExtensionField"> + <PartnerKey xsi:nil="true" /> + <ObjectID>721b938f-67ab-4d82-bb1c-33add4ec1533</ObjectID> + <CustomerKey>[testExisting_event - 2024-07-05T080154625].[ContactId]</CustomerKey> + <Name>ContactId</Name> + <DefaultValue /> + <MaxLength>18</MaxLength> + <IsRequired>true</IsRequired> + <Ordinal>0</Ordinal> + <IsPrimaryKey>true</IsPrimaryKey> + <FieldType>Text</FieldType> + <DataExtension> + <PartnerKey xsi:nil="true" /> + <ObjectID xsi:nil="true" /> + <CustomerKey>testExisting_event - 2024-07-05T080154625</CustomerKey> + </DataExtension> + </Results> + <Results xsi:type="DataExtensionField"> + <PartnerKey xsi:nil="true" /> + <ObjectID>5ccee5f6-f282-4741-899d-400b05c57425</ObjectID> + <CustomerKey>[testExisting_event - 2024-07-05T080154625].[FirstName]</CustomerKey> + <Name>FirstName</Name> + <DefaultValue /> + <MaxLength>256</MaxLength> + <IsRequired>false</IsRequired> + <Ordinal>4</Ordinal> + <IsPrimaryKey>false</IsPrimaryKey> + <FieldType>Text</FieldType> + <DataExtension> + <PartnerKey xsi:nil="true" /> + <ObjectID xsi:nil="true" /> + <CustomerKey>testExisting_event - 2024-07-05T080154625</CustomerKey> + </DataExtension> + </Results> + <Results xsi:type="DataExtensionField"> + <PartnerKey xsi:nil="true" /> + <ObjectID>d0ec626c-7cba-492b-abd0-48484e0c18bb</ObjectID> + <CustomerKey>[testExisting_event - 2024-07-05T080154625].[Type]</CustomerKey> + <Name>Type</Name> + <DefaultValue /> + <MaxLength>50</MaxLength> + <IsRequired>true</IsRequired> + <Ordinal>1</Ordinal> + <IsPrimaryKey>false</IsPrimaryKey> + <FieldType>Text</FieldType> + <DataExtension> + <PartnerKey xsi:nil="true" /> + <ObjectID xsi:nil="true" /> + <CustomerKey>testExisting_event - 2024-07-05T080154625</CustomerKey> + </DataExtension> + </Results> + <Results xsi:type="DataExtensionField"> + <PartnerKey xsi:nil="true" /> + <ObjectID>0d49e8cf-cce9-4323-9b17-52f2366f9fc2</ObjectID> + <CustomerKey>[testExisting_event - 2024-07-05T080154625].[Datestamp]</CustomerKey> + <Name>Datestamp</Name> + <DefaultValue>GetDate()</DefaultValue> + <IsRequired>false</IsRequired> + <Ordinal>8</Ordinal> + <IsPrimaryKey>false</IsPrimaryKey> + <FieldType>Date</FieldType> + <DataExtension> + <PartnerKey xsi:nil="true" /> + <ObjectID xsi:nil="true" /> + <CustomerKey>testExisting_event - 2024-07-05T080154625</CustomerKey> + </DataExtension> + </Results> + <Results xsi:type="DataExtensionField"> + <PartnerKey xsi:nil="true" /> + <ObjectID>c44861f7-bac3-4b32-a5f8-744f67a66aaa</ObjectID> + <CustomerKey>[testExisting_event - 2024-07-05T080154625].[Email]</CustomerKey> + <Name>Email</Name> + <DefaultValue /> + <MaxLength>254</MaxLength> + <IsRequired>false</IsRequired> + <Ordinal>21</Ordinal> + <IsPrimaryKey>false</IsPrimaryKey> + <FieldType>EmailAddress</FieldType> + <DataExtension> + <PartnerKey xsi:nil="true" /> + <ObjectID xsi:nil="true" /> + <CustomerKey>testExisting_event - 2024-07-05T080154625</CustomerKey> + </DataExtension> + </Results> + <Results xsi:type="DataExtensionField"> + <PartnerKey xsi:nil="true" /> + <ObjectID>c78d6054-5ce0-4438-a7ad-76b375224033</ObjectID> + <CustomerKey>[testExisting_event - 2024-07-05T080154625].[Status]</CustomerKey> + <Name>Status</Name> + <DefaultValue /> + <MaxLength>50</MaxLength> + <IsRequired>true</IsRequired> + <Ordinal>2</Ordinal> + <IsPrimaryKey>true</IsPrimaryKey> + <FieldType>Text</FieldType> + <DataExtension> + <PartnerKey xsi:nil="true" /> + <ObjectID xsi:nil="true" /> + <CustomerKey>testExisting_event - 2024-07-05T080154625</CustomerKey> + </DataExtension> + </Results> + <Results xsi:type="DataExtensionField"> + <PartnerKey xsi:nil="true" /> + <ObjectID>541b063f-7c25-45b2-af53-7fdafbe0ee12</ObjectID> + <CustomerKey>[testExisting_event - 2024-07-05T080154625].[BroadcastedNotificationDate]</CustomerKey> + <Name>BroadcastedNotificationDate</Name> + <DefaultValue /> + <IsRequired>false</IsRequired> + <Ordinal>11</Ordinal> + <IsPrimaryKey>false</IsPrimaryKey> + <FieldType>Date</FieldType> + <DataExtension> + <PartnerKey xsi:nil="true" /> + <ObjectID xsi:nil="true" /> + <CustomerKey>testExisting_event - 2024-07-05T080154625</CustomerKey> + </DataExtension> + </Results> + <Results xsi:type="DataExtensionField"> + <PartnerKey xsi:nil="true" /> + <ObjectID>ff54519e-931b-432f-9083-861213fa9460</ObjectID> + <CustomerKey>[testExisting_event - 2024-07-05T080154625].[TouchPoint]</CustomerKey> + <Name>TouchPoint</Name> + <DefaultValue /> + <MaxLength>256</MaxLength> + <IsRequired>false</IsRequired> + <Ordinal>7</Ordinal> + <IsPrimaryKey>false</IsPrimaryKey> + <FieldType>Text</FieldType> + <DataExtension> + <PartnerKey xsi:nil="true" /> + <ObjectID xsi:nil="true" /> + <CustomerKey>testExisting_event - 2024-07-05T080154625</CustomerKey> + </DataExtension> + </Results> + <Results xsi:type="DataExtensionField"> + <PartnerKey xsi:nil="true" /> + <ObjectID>f0a58625-0b62-496f-bea9-9d2722e50864</ObjectID> + <CustomerKey>[testExisting_event - 2024-07-05T080154625].[Points]</CustomerKey> + <Name>Points</Name> + <DefaultValue /> + <IsRequired>false</IsRequired> + <Ordinal>23</Ordinal> + <IsPrimaryKey>false</IsPrimaryKey> + <FieldType>Number</FieldType> + <DataExtension> + <PartnerKey xsi:nil="true" /> + <ObjectID xsi:nil="true" /> + <CustomerKey>testExisting_event - 2024-07-05T080154625</CustomerKey> + </DataExtension> + </Results> + <Results xsi:type="DataExtensionField"> + <PartnerKey xsi:nil="true" /> + <ObjectID>43f69e09-9f47-477f-95b6-a9b9b8111f5e</ObjectID> + <CustomerKey>[testExisting_event - 2024-07-05T080154625].[Title]</CustomerKey> + <Name>Title</Name> + <DefaultValue /> + <MaxLength>256</MaxLength> + <IsRequired>false</IsRequired> + <Ordinal>14</Ordinal> + <IsPrimaryKey>false</IsPrimaryKey> + <FieldType>Text</FieldType> + <DataExtension> + <PartnerKey xsi:nil="true" /> + <ObjectID xsi:nil="true" /> + <CustomerKey>testExisting_event - 2024-07-05T080154625</CustomerKey> + </DataExtension> + </Results> + <Results xsi:type="DataExtensionField"> + <PartnerKey xsi:nil="true" /> + <ObjectID>e9cd8c9f-39b0-4c93-8fce-aa3f0ca0d310</ObjectID> + <CustomerKey>[testExisting_event - 2024-07-05T080154625].[SecondReminderDate]</CustomerKey> + <Name>SecondReminderDate</Name> + <DefaultValue /> + <IsRequired>false</IsRequired> + <Ordinal>13</Ordinal> + <IsPrimaryKey>false</IsPrimaryKey> + <FieldType>Date</FieldType> + <DataExtension> + <PartnerKey xsi:nil="true" /> + <ObjectID xsi:nil="true" /> + <CustomerKey>testExisting_event - 2024-07-05T080154625</CustomerKey> + </DataExtension> + </Results> + <Results xsi:type="DataExtensionField"> + <PartnerKey xsi:nil="true" /> + <ObjectID>403e68ee-f203-42e1-ac48-af18def0cccd</ObjectID> + <CustomerKey>[testExisting_event - 2024-07-05T080154625].[TaskType]</CustomerKey> + <Name>TaskType</Name> + <DefaultValue /> + <MaxLength>255</MaxLength> + <IsRequired>false</IsRequired> + <Ordinal>24</Ordinal> + <IsPrimaryKey>false</IsPrimaryKey> + <FieldType>Text</FieldType> + <DataExtension> + <PartnerKey xsi:nil="true" /> + <ObjectID xsi:nil="true" /> + <CustomerKey>testExisting_event - 2024-07-05T080154625</CustomerKey> + </DataExtension> + </Results> + <Results xsi:type="DataExtensionField"> + <PartnerKey xsi:nil="true" /> + <ObjectID>555ad728-f99a-4e13-a992-b70b1ffe36a2</ObjectID> + <CustomerKey>[testExisting_event - 2024-07-05T080154625].[Respondent]</CustomerKey> + <Name>Respondent</Name> + <DefaultValue /> + <MaxLength>256</MaxLength> + <IsRequired>false</IsRequired> + <Ordinal>3</Ordinal> + <IsPrimaryKey>false</IsPrimaryKey> + <FieldType>Text</FieldType> + <DataExtension> + <PartnerKey xsi:nil="true" /> + <ObjectID xsi:nil="true" /> + <CustomerKey>testExisting_event - 2024-07-05T080154625</CustomerKey> + </DataExtension> + </Results> + <Results xsi:type="DataExtensionField"> + <PartnerKey xsi:nil="true" /> + <ObjectID>95948e52-e8d0-4908-98a9-cc34cd84233e</ObjectID> + <CustomerKey>[testExisting_event - 2024-07-05T080154625].[LastName]</CustomerKey> + <Name>LastName</Name> + <DefaultValue /> + <MaxLength>256</MaxLength> + <IsRequired>false</IsRequired> + <Ordinal>5</Ordinal> + <IsPrimaryKey>false</IsPrimaryKey> + <FieldType>Text</FieldType> + <DataExtension> + <PartnerKey xsi:nil="true" /> + <ObjectID xsi:nil="true" /> + <CustomerKey>testExisting_event - 2024-07-05T080154625</CustomerKey> + </DataExtension> + </Results> + <Results xsi:type="DataExtensionField"> + <PartnerKey xsi:nil="true" /> + <ObjectID>7976b904-1ed5-46f0-a524-cd1a787bfb5e</ObjectID> + <CustomerKey>[testExisting_event - 2024-07-05T080154625].[FirstReminderChannel]</CustomerKey> + <Name>FirstReminderChannel</Name> + <DefaultValue /> + <MaxLength>256</MaxLength> + <IsRequired>false</IsRequired> + <Ordinal>19</Ordinal> + <IsPrimaryKey>false</IsPrimaryKey> + <FieldType>Text</FieldType> + <DataExtension> + <PartnerKey xsi:nil="true" /> + <ObjectID xsi:nil="true" /> + <CustomerKey>testExisting_event - 2024-07-05T080154625</CustomerKey> + </DataExtension> + </Results> + <Results xsi:type="DataExtensionField"> + <PartnerKey xsi:nil="true" /> + <ObjectID>ed225fdd-1aff-401d-906e-cd59b4d86fe2</ObjectID> + <CustomerKey>[testExisting_event - 2024-07-05T080154625].[SecondReminderChannel]</CustomerKey> + <Name>SecondReminderChannel</Name> + <DefaultValue /> + <MaxLength>256</MaxLength> + <IsRequired>false</IsRequired> + <Ordinal>20</Ordinal> + <IsPrimaryKey>false</IsPrimaryKey> + <FieldType>Text</FieldType> + <DataExtension> + <PartnerKey xsi:nil="true" /> + <ObjectID xsi:nil="true" /> + <CustomerKey>testExisting_event - 2024-07-05T080154625</CustomerKey> + </DataExtension> + </Results> + <Results xsi:type="DataExtensionField"> + <PartnerKey xsi:nil="true" /> + <ObjectID>30222d00-35c5-46e8-ab41-d3febd909eed</ObjectID> + <CustomerKey>[testExisting_event - 2024-07-05T080154625].[ArticleOrTaskID]</CustomerKey> + <Name>ArticleOrTaskID</Name> + <DefaultValue /> + <MaxLength>18</MaxLength> + <IsRequired>true</IsRequired> + <Ordinal>22</Ordinal> + <IsPrimaryKey>true</IsPrimaryKey> + <FieldType>Text</FieldType> + <DataExtension> + <PartnerKey xsi:nil="true" /> + <ObjectID xsi:nil="true" /> + <CustomerKey>testExisting_event - 2024-07-05T080154625</CustomerKey> + </DataExtension> + </Results> + <Results xsi:type="DataExtensionField"> + <PartnerKey xsi:nil="true" /> + <ObjectID>8c79306f-4f3a-4925-bd48-e6c6905c157c</ObjectID> + <CustomerKey>[testExisting_event - 2024-07-05T080154625].[StartDate]</CustomerKey> + <Name>StartDate</Name> + <DefaultValue /> + <IsRequired>false</IsRequired> + <Ordinal>9</Ordinal> + <IsPrimaryKey>false</IsPrimaryKey> + <FieldType>Date</FieldType> + <DataExtension> + <PartnerKey xsi:nil="true" /> + <ObjectID xsi:nil="true" /> + <CustomerKey>testExisting_event - 2024-07-05T080154625</CustomerKey> + </DataExtension> + </Results> + <Results xsi:type="DataExtensionField"> + <PartnerKey xsi:nil="true" /> + <ObjectID>1892b0ee-26ea-4280-8bca-e8cc5d3f9658</ObjectID> + <CustomerKey>[testExisting_event - 2024-07-05T080154625].[Channel]</CustomerKey> + <Name>Channel</Name> + <DefaultValue /> + <MaxLength>256</MaxLength> + <IsRequired>false</IsRequired> + <Ordinal>18</Ordinal> + <IsPrimaryKey>false</IsPrimaryKey> + <FieldType>Text</FieldType> + <DataExtension> + <PartnerKey xsi:nil="true" /> + <ObjectID xsi:nil="true" /> + <CustomerKey>testExisting_event - 2024-07-05T080154625</CustomerKey> + </DataExtension> + </Results> + <Results xsi:type="DataExtensionField"> + <PartnerKey xsi:nil="true" /> + <ObjectID>bf50095e-54ba-42c7-9baf-f91618738d85</ObjectID> + <CustomerKey>[testExisting_event - 2024-07-05T080154625].[Text]</CustomerKey> + <Name>Text</Name> + <DefaultValue /> + <MaxLength>256</MaxLength> + <IsRequired>false</IsRequired> + <Ordinal>16</Ordinal> + <IsPrimaryKey>false</IsPrimaryKey> + <FieldType>Text</FieldType> + <DataExtension> + <PartnerKey xsi:nil="true" /> + <ObjectID xsi:nil="true" /> + <CustomerKey>testExisting_event - 2024-07-05T080154625</CustomerKey> + </DataExtension> + </Results> + <Results xsi:type="DataExtensionField"> + <PartnerKey xsi:nil="true" /> + <ObjectID>eb18160e-ec0f-46ca-b59a-1287dbeb7172</ObjectID> + <CustomerKey>[testNew_event_withSchema - 2024-07-08T014814443].[DisplayName]</CustomerKey> + <Name>DisplayName</Name> + <DefaultValue /> + <MaxLength>256</MaxLength> + <IsRequired>false</IsRequired> + <Ordinal>15</Ordinal> + <IsPrimaryKey>false</IsPrimaryKey> + <FieldType>Text</FieldType> + <DataExtension> + <PartnerKey xsi:nil="true" /> + <ObjectID xsi:nil="true" /> + <CustomerKey>testNew_event_withSchema - 2024-07-08T014814443</CustomerKey> + </DataExtension> + </Results> + <Results xsi:type="DataExtensionField"> + <PartnerKey xsi:nil="true" /> + <ObjectID>ae0a3a3e-e81a-4b13-9a70-12ff6903c901</ObjectID> + <CustomerKey>[testNew_event_withSchema - 2024-07-08T014814443].[PreferredLanguage]</CustomerKey> + <Name>PreferredLanguage</Name> + <DefaultValue /> + <MaxLength>50</MaxLength> + <IsRequired>false</IsRequired> + <Ordinal>6</Ordinal> + <IsPrimaryKey>false</IsPrimaryKey> + <FieldType>Text</FieldType> + <DataExtension> + <PartnerKey xsi:nil="true" /> + <ObjectID xsi:nil="true" /> + <CustomerKey>testNew_event_withSchema - 2024-07-08T014814443</CustomerKey> + </DataExtension> + </Results> + <Results xsi:type="DataExtensionField"> + <PartnerKey xsi:nil="true" /> + <ObjectID>3d39db8b-b561-4227-9051-1c201c79033e</ObjectID> + <CustomerKey>[testNew_event_withSchema - 2024-07-08T014814443].[FirstReminderDate]</CustomerKey> + <Name>FirstReminderDate</Name> + <DefaultValue /> + <IsRequired>false</IsRequired> + <Ordinal>12</Ordinal> + <IsPrimaryKey>false</IsPrimaryKey> + <FieldType>Date</FieldType> + <DataExtension> + <PartnerKey xsi:nil="true" /> + <ObjectID xsi:nil="true" /> + <CustomerKey>testNew_event_withSchema - 2024-07-08T014814443</CustomerKey> + </DataExtension> + </Results> + <Results xsi:type="DataExtensionField"> + <PartnerKey xsi:nil="true" /> + <ObjectID>4eadce50-f552-41e5-8318-2fd367f043b9</ObjectID> + <CustomerKey>[testNew_event_withSchema - 2024-07-08T014814443].[Description]</CustomerKey> + <Name>Description</Name> + <DefaultValue /> + <MaxLength>4000</MaxLength> + <IsRequired>false</IsRequired> + <Ordinal>17</Ordinal> + <IsPrimaryKey>false</IsPrimaryKey> + <FieldType>Text</FieldType> + <DataExtension> + <PartnerKey xsi:nil="true" /> + <ObjectID xsi:nil="true" /> + <CustomerKey>testNew_event_withSchema - 2024-07-08T014814443</CustomerKey> + </DataExtension> + </Results> + <Results xsi:type="DataExtensionField"> + <PartnerKey xsi:nil="true" /> + <ObjectID>d2826773-6965-4e78-9a05-3008ea45a104</ObjectID> + <CustomerKey>[testNew_event_withSchema - 2024-07-08T014814443].[EndDate]</CustomerKey> + <Name>EndDate</Name> + <DefaultValue /> + <IsRequired>false</IsRequired> + <Ordinal>10</Ordinal> + <IsPrimaryKey>false</IsPrimaryKey> + <FieldType>Date</FieldType> + <DataExtension> + <PartnerKey xsi:nil="true" /> + <ObjectID xsi:nil="true" /> + <CustomerKey>testNew_event_withSchema - 2024-07-08T014814443</CustomerKey> + </DataExtension> + </Results> + <Results xsi:type="DataExtensionField"> + <PartnerKey xsi:nil="true" /> + <ObjectID>3bb8fa91-5881-4ca1-ac09-30604ba0b9be</ObjectID> + <CustomerKey>[testNew_event_withSchema - 2024-07-08T014814443].[TaskArea]</CustomerKey> + <Name>TaskArea</Name> + <DefaultValue /> + <MaxLength>255</MaxLength> + <IsRequired>false</IsRequired> + <Ordinal>25</Ordinal> + <IsPrimaryKey>false</IsPrimaryKey> + <FieldType>Text</FieldType> + <DataExtension> + <PartnerKey xsi:nil="true" /> + <ObjectID xsi:nil="true" /> + <CustomerKey>testNew_event_withSchema - 2024-07-08T014814443</CustomerKey> + </DataExtension> + </Results> + <Results xsi:type="DataExtensionField"> + <PartnerKey xsi:nil="true" /> + <ObjectID>721b938f-67ab-4d82-bb1c-33add4ec1533</ObjectID> + <CustomerKey>[testNew_event_withSchema - 2024-07-08T014814443].[ContactId]</CustomerKey> + <Name>ContactId</Name> + <DefaultValue /> + <MaxLength>18</MaxLength> + <IsRequired>true</IsRequired> + <Ordinal>0</Ordinal> + <IsPrimaryKey>true</IsPrimaryKey> + <FieldType>Text</FieldType> + <DataExtension> + <PartnerKey xsi:nil="true" /> + <ObjectID xsi:nil="true" /> + <CustomerKey>testNew_event_withSchema - 2024-07-08T014814443</CustomerKey> + </DataExtension> + </Results> + <Results xsi:type="DataExtensionField"> + <PartnerKey xsi:nil="true" /> + <ObjectID>5ccee5f6-f282-4741-899d-400b05c57425</ObjectID> + <CustomerKey>[testNew_event_withSchema - 2024-07-08T014814443].[FirstName]</CustomerKey> + <Name>FirstName</Name> + <DefaultValue /> + <MaxLength>256</MaxLength> + <IsRequired>false</IsRequired> + <Ordinal>4</Ordinal> + <IsPrimaryKey>false</IsPrimaryKey> + <FieldType>Text</FieldType> + <DataExtension> + <PartnerKey xsi:nil="true" /> + <ObjectID xsi:nil="true" /> + <CustomerKey>testNew_event_withSchema - 2024-07-08T014814443</CustomerKey> + </DataExtension> + </Results> + <Results xsi:type="DataExtensionField"> + <PartnerKey xsi:nil="true" /> + <ObjectID>d0ec626c-7cba-492b-abd0-48484e0c18bb</ObjectID> + <CustomerKey>[testNew_event_withSchema - 2024-07-08T014814443].[Type]</CustomerKey> + <Name>Type</Name> + <DefaultValue /> + <MaxLength>50</MaxLength> + <IsRequired>true</IsRequired> + <Ordinal>1</Ordinal> + <IsPrimaryKey>false</IsPrimaryKey> + <FieldType>Text</FieldType> + <DataExtension> + <PartnerKey xsi:nil="true" /> + <ObjectID xsi:nil="true" /> + <CustomerKey>testNew_event_withSchema - 2024-07-08T014814443</CustomerKey> + </DataExtension> + </Results> + <Results xsi:type="DataExtensionField"> + <PartnerKey xsi:nil="true" /> + <ObjectID>0d49e8cf-cce9-4323-9b17-52f2366f9fc2</ObjectID> + <CustomerKey>[testNew_event_withSchema - 2024-07-08T014814443].[Datestamp]</CustomerKey> + <Name>Datestamp</Name> + <DefaultValue>GetDate()</DefaultValue> + <IsRequired>false</IsRequired> + <Ordinal>8</Ordinal> + <IsPrimaryKey>false</IsPrimaryKey> + <FieldType>Date</FieldType> + <DataExtension> + <PartnerKey xsi:nil="true" /> + <ObjectID xsi:nil="true" /> + <CustomerKey>testNew_event_withSchema - 2024-07-08T014814443</CustomerKey> + </DataExtension> + </Results> + <Results xsi:type="DataExtensionField"> + <PartnerKey xsi:nil="true" /> + <ObjectID>c44861f7-bac3-4b32-a5f8-744f67a66aaa</ObjectID> + <CustomerKey>[testNew_event_withSchema - 2024-07-08T014814443].[Email]</CustomerKey> + <Name>Email</Name> + <DefaultValue /> + <MaxLength>254</MaxLength> + <IsRequired>false</IsRequired> + <Ordinal>21</Ordinal> + <IsPrimaryKey>false</IsPrimaryKey> + <FieldType>EmailAddress</FieldType> + <DataExtension> + <PartnerKey xsi:nil="true" /> + <ObjectID xsi:nil="true" /> + <CustomerKey>testNew_event_withSchema - 2024-07-08T014814443</CustomerKey> + </DataExtension> + </Results> + <Results xsi:type="DataExtensionField"> + <PartnerKey xsi:nil="true" /> + <ObjectID>c78d6054-5ce0-4438-a7ad-76b375224033</ObjectID> + <CustomerKey>[testNew_event_withSchema - 2024-07-08T014814443].[Status]</CustomerKey> + <Name>Status</Name> + <DefaultValue /> + <MaxLength>50</MaxLength> + <IsRequired>true</IsRequired> + <Ordinal>2</Ordinal> + <IsPrimaryKey>true</IsPrimaryKey> + <FieldType>Text</FieldType> + <DataExtension> + <PartnerKey xsi:nil="true" /> + <ObjectID xsi:nil="true" /> + <CustomerKey>testNew_event_withSchema - 2024-07-08T014814443</CustomerKey> + </DataExtension> + </Results> + <Results xsi:type="DataExtensionField"> + <PartnerKey xsi:nil="true" /> + <ObjectID>541b063f-7c25-45b2-af53-7fdafbe0ee12</ObjectID> + <CustomerKey>[testNew_event_withSchema - 2024-07-08T014814443].[BroadcastedNotificationDate]</CustomerKey> + <Name>BroadcastedNotificationDate</Name> + <DefaultValue /> + <IsRequired>false</IsRequired> + <Ordinal>11</Ordinal> + <IsPrimaryKey>false</IsPrimaryKey> + <FieldType>Date</FieldType> + <DataExtension> + <PartnerKey xsi:nil="true" /> + <ObjectID xsi:nil="true" /> + <CustomerKey>testNew_event_withSchema - 2024-07-08T014814443</CustomerKey> + </DataExtension> + </Results> + <Results xsi:type="DataExtensionField"> + <PartnerKey xsi:nil="true" /> + <ObjectID>ff54519e-931b-432f-9083-861213fa9460</ObjectID> + <CustomerKey>[testNew_event_withSchema - 2024-07-08T014814443].[TouchPoint]</CustomerKey> + <Name>TouchPoint</Name> + <DefaultValue /> + <MaxLength>256</MaxLength> + <IsRequired>false</IsRequired> + <Ordinal>7</Ordinal> + <IsPrimaryKey>false</IsPrimaryKey> + <FieldType>Text</FieldType> + <DataExtension> + <PartnerKey xsi:nil="true" /> + <ObjectID xsi:nil="true" /> + <CustomerKey>testNew_event_withSchema - 2024-07-08T014814443</CustomerKey> + </DataExtension> + </Results> + <Results xsi:type="DataExtensionField"> + <PartnerKey xsi:nil="true" /> + <ObjectID>f0a58625-0b62-496f-bea9-9d2722e50864</ObjectID> + <CustomerKey>[testNew_event_withSchema - 2024-07-08T014814443].[Points]</CustomerKey> + <Name>Points</Name> + <DefaultValue /> + <IsRequired>false</IsRequired> + <Ordinal>23</Ordinal> + <IsPrimaryKey>false</IsPrimaryKey> + <FieldType>Number</FieldType> + <DataExtension> + <PartnerKey xsi:nil="true" /> + <ObjectID xsi:nil="true" /> + <CustomerKey>testNew_event_withSchema - 2024-07-08T014814443</CustomerKey> + </DataExtension> + </Results> + <Results xsi:type="DataExtensionField"> + <PartnerKey xsi:nil="true" /> + <ObjectID>43f69e09-9f47-477f-95b6-a9b9b8111f5e</ObjectID> + <CustomerKey>[testNew_event_withSchema - 2024-07-08T014814443].[Title]</CustomerKey> + <Name>Title</Name> + <DefaultValue /> + <MaxLength>256</MaxLength> + <IsRequired>false</IsRequired> + <Ordinal>14</Ordinal> + <IsPrimaryKey>false</IsPrimaryKey> + <FieldType>Text</FieldType> + <DataExtension> + <PartnerKey xsi:nil="true" /> + <ObjectID xsi:nil="true" /> + <CustomerKey>testNew_event_withSchema - 2024-07-08T014814443</CustomerKey> + </DataExtension> + </Results> + <Results xsi:type="DataExtensionField"> + <PartnerKey xsi:nil="true" /> + <ObjectID>e9cd8c9f-39b0-4c93-8fce-aa3f0ca0d310</ObjectID> + <CustomerKey>[testNew_event_withSchema - 2024-07-08T014814443].[SecondReminderDate]</CustomerKey> + <Name>SecondReminderDate</Name> + <DefaultValue /> + <IsRequired>false</IsRequired> + <Ordinal>13</Ordinal> + <IsPrimaryKey>false</IsPrimaryKey> + <FieldType>Date</FieldType> + <DataExtension> + <PartnerKey xsi:nil="true" /> + <ObjectID xsi:nil="true" /> + <CustomerKey>testNew_event_withSchema - 2024-07-08T014814443</CustomerKey> + </DataExtension> + </Results> + <Results xsi:type="DataExtensionField"> + <PartnerKey xsi:nil="true" /> + <ObjectID>403e68ee-f203-42e1-ac48-af18def0cccd</ObjectID> + <CustomerKey>[testNew_event_withSchema - 2024-07-08T014814443].[TaskType]</CustomerKey> + <Name>TaskType</Name> + <DefaultValue /> + <MaxLength>255</MaxLength> + <IsRequired>false</IsRequired> + <Ordinal>24</Ordinal> + <IsPrimaryKey>false</IsPrimaryKey> + <FieldType>Text</FieldType> + <DataExtension> + <PartnerKey xsi:nil="true" /> + <ObjectID xsi:nil="true" /> + <CustomerKey>testNew_event_withSchema - 2024-07-08T014814443</CustomerKey> + </DataExtension> + </Results> + <Results xsi:type="DataExtensionField"> + <PartnerKey xsi:nil="true" /> + <ObjectID>555ad728-f99a-4e13-a992-b70b1ffe36a2</ObjectID> + <CustomerKey>[testNew_event_withSchema - 2024-07-08T014814443].[Respondent]</CustomerKey> + <Name>Respondent</Name> + <DefaultValue /> + <MaxLength>256</MaxLength> + <IsRequired>false</IsRequired> + <Ordinal>3</Ordinal> + <IsPrimaryKey>false</IsPrimaryKey> + <FieldType>Text</FieldType> + <DataExtension> + <PartnerKey xsi:nil="true" /> + <ObjectID xsi:nil="true" /> + <CustomerKey>testNew_event_withSchema - 2024-07-08T014814443</CustomerKey> + </DataExtension> + </Results> + <Results xsi:type="DataExtensionField"> + <PartnerKey xsi:nil="true" /> + <ObjectID>95948e52-e8d0-4908-98a9-cc34cd84233e</ObjectID> + <CustomerKey>[testNew_event_withSchema - 2024-07-08T014814443].[LastName]</CustomerKey> + <Name>LastName</Name> + <DefaultValue /> + <MaxLength>256</MaxLength> + <IsRequired>false</IsRequired> + <Ordinal>5</Ordinal> + <IsPrimaryKey>false</IsPrimaryKey> + <FieldType>Text</FieldType> + <DataExtension> + <PartnerKey xsi:nil="true" /> + <ObjectID xsi:nil="true" /> + <CustomerKey>testNew_event_withSchema - 2024-07-08T014814443</CustomerKey> + </DataExtension> + </Results> + <Results xsi:type="DataExtensionField"> + <PartnerKey xsi:nil="true" /> + <ObjectID>7976b904-1ed5-46f0-a524-cd1a787bfb5e</ObjectID> + <CustomerKey>[testNew_event_withSchema - 2024-07-08T014814443].[FirstReminderChannel]</CustomerKey> + <Name>FirstReminderChannel</Name> + <DefaultValue /> + <MaxLength>256</MaxLength> + <IsRequired>false</IsRequired> + <Ordinal>19</Ordinal> + <IsPrimaryKey>false</IsPrimaryKey> + <FieldType>Text</FieldType> + <DataExtension> + <PartnerKey xsi:nil="true" /> + <ObjectID xsi:nil="true" /> + <CustomerKey>testNew_event_withSchema - 2024-07-08T014814443</CustomerKey> + </DataExtension> + </Results> + <Results xsi:type="DataExtensionField"> + <PartnerKey xsi:nil="true" /> + <ObjectID>ed225fdd-1aff-401d-906e-cd59b4d86fe2</ObjectID> + <CustomerKey>[testNew_event_withSchema - 2024-07-08T014814443].[SecondReminderChannel]</CustomerKey> + <Name>SecondReminderChannel</Name> + <DefaultValue /> + <MaxLength>256</MaxLength> + <IsRequired>false</IsRequired> + <Ordinal>20</Ordinal> + <IsPrimaryKey>false</IsPrimaryKey> + <FieldType>Text</FieldType> + <DataExtension> + <PartnerKey xsi:nil="true" /> + <ObjectID xsi:nil="true" /> + <CustomerKey>testNew_event_withSchema - 2024-07-08T014814443</CustomerKey> + </DataExtension> + </Results> + <Results xsi:type="DataExtensionField"> + <PartnerKey xsi:nil="true" /> + <ObjectID>30222d00-35c5-46e8-ab41-d3febd909eed</ObjectID> + <CustomerKey>[testNew_event_withSchema - 2024-07-08T014814443].[ArticleOrTaskID]</CustomerKey> + <Name>ArticleOrTaskID</Name> + <DefaultValue /> + <MaxLength>18</MaxLength> + <IsRequired>true</IsRequired> + <Ordinal>22</Ordinal> + <IsPrimaryKey>true</IsPrimaryKey> + <FieldType>Text</FieldType> + <DataExtension> + <PartnerKey xsi:nil="true" /> + <ObjectID xsi:nil="true" /> + <CustomerKey>testNew_event_withSchema - 2024-07-08T014814443</CustomerKey> + </DataExtension> + </Results> + <Results xsi:type="DataExtensionField"> + <PartnerKey xsi:nil="true" /> + <ObjectID>8c79306f-4f3a-4925-bd48-e6c6905c157c</ObjectID> + <CustomerKey>[testNew_event_withSchema - 2024-07-08T014814443].[StartDate]</CustomerKey> + <Name>StartDate</Name> + <DefaultValue /> + <IsRequired>false</IsRequired> + <Ordinal>9</Ordinal> + <IsPrimaryKey>false</IsPrimaryKey> + <FieldType>Date</FieldType> + <DataExtension> + <PartnerKey xsi:nil="true" /> + <ObjectID xsi:nil="true" /> + <CustomerKey>testNew_event_withSchema - 2024-07-08T014814443</CustomerKey> + </DataExtension> + </Results> + <Results xsi:type="DataExtensionField"> + <PartnerKey xsi:nil="true" /> + <ObjectID>1892b0ee-26ea-4280-8bca-e8cc5d3f9658</ObjectID> + <CustomerKey>[testNew_event_withSchema - 2024-07-08T014814443].[Channel]</CustomerKey> + <Name>Channel</Name> + <DefaultValue /> + <MaxLength>256</MaxLength> + <IsRequired>false</IsRequired> + <Ordinal>18</Ordinal> + <IsPrimaryKey>false</IsPrimaryKey> + <FieldType>Text</FieldType> + <DataExtension> + <PartnerKey xsi:nil="true" /> + <ObjectID xsi:nil="true" /> + <CustomerKey>testNew_event_withSchema - 2024-07-08T014814443</CustomerKey> + </DataExtension> + </Results> + <Results xsi:type="DataExtensionField"> + <PartnerKey xsi:nil="true" /> + <ObjectID>bf50095e-54ba-42c7-9baf-f91618738d85</ObjectID> + <CustomerKey>[testNew_event_withSchema - 2024-07-08T014814443].[Text]</CustomerKey> + <Name>Text</Name> + <DefaultValue /> + <MaxLength>256</MaxLength> + <IsRequired>false</IsRequired> + <Ordinal>16</Ordinal> + <IsPrimaryKey>false</IsPrimaryKey> + <FieldType>Text</FieldType> + <DataExtension> + <PartnerKey xsi:nil="true" /> + <ObjectID xsi:nil="true" /> + <CustomerKey>testNew_event_withSchema - 2024-07-08T014814443</CustomerKey> + </DataExtension> + </Results> + </RetrieveResponseMsg> + </soap:Body> +</soap:Envelope> diff --git a/test/resources/9999999/dataExtensionTemplate/retrieve-response.xml b/test/resources/9999999/dataExtensionTemplate/retrieve-response.xml new file mode 100644 index 000000000..31b41f0b5 --- /dev/null +++ b/test/resources/9999999/dataExtensionTemplate/retrieve-response.xml @@ -0,0 +1,303 @@ +<?xml version="1.0" encoding="utf-8"?> +<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing" xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"> + <soap:Header> + <wsa:Action>RetrieveResponse</wsa:Action> + <wsa:MessageID>urn:uuid:110bbc72-d639-4e67-ab93-68e081bcf3a0</wsa:MessageID> + <wsa:RelatesTo>urn:uuid:753eed05-f925-4113-8a98-e81ca69c96fd</wsa:RelatesTo> + <wsa:To>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</wsa:To> + <wsse:Security> + <wsu:Timestamp wsu:Id="Timestamp-a81724ab-b6f6-4825-82e8-ec523642075e"> + <wsu:Created>2022-04-21T19:21:49Z</wsu:Created> + <wsu:Expires>2022-04-21T19:26:49Z</wsu:Expires> + </wsu:Timestamp> + </wsse:Security> + </soap:Header> + <soap:Body> + <RetrieveResponseMsg xmlns="http://exacttarget.com/wsdl/partnerAPI"> + <OverallStatus>OK</OverallStatus> + <RequestID>82fd5f74-ad8c-49ad-958f-867d4a4b53b0</RequestID> + <Results xsi:type="DataExtensionTemplate"> + <PartnerKey xsi:nil="true" /> + <PartnerProperties> + <Name>IsSendable</Name> + <Value>False</Value> + </PartnerProperties> + <PartnerProperties> + <Name>IsTestable</Name> + <Value>False</Value> + </PartnerProperties> + <PartnerProperties> + <Name>SendableCustomObjectField</Name> + <Value /> + </PartnerProperties> + <PartnerProperties> + <Name>SendableSubscriberField</Name> + <Value /> + </PartnerProperties> + <PartnerProperties> + <Name>DataRetentionPeriodLength</Name> + <Value /> + </PartnerProperties> + <PartnerProperties> + <Name>DataRetentionPeriodUnitOfMeasure</Name> + <Value /> + </PartnerProperties> + <PartnerProperties> + <Name>RowBasedRetention</Name> + <Value>False</Value> + </PartnerProperties> + <PartnerProperties> + <Name>ResetRetentionPeriodOnImport</Name> + <Value>False</Value> + </PartnerProperties> + <PartnerProperties> + <Name>DeleteAtEndOfRetentionPeriod</Name> + <Value>False</Value> + </PartnerProperties> + <PartnerProperties> + <Name>RetainUntil</Name> + <Value /> + </PartnerProperties> + <ObjectID>cfd6fc95-d594-ea11-a2e6-1402ec938a35</ObjectID> + <CustomerKey>086D14D3-5057-462B-AF33-01CA8D1FE87A</CustomerKey> + <Name>DomainExclusion</Name> + <Description>Domain Exclusion Data Extension Template</Description> + </Results> + <Results xsi:type="DataExtensionTemplate"> + <PartnerKey xsi:nil="true" /> + <PartnerProperties> + <Name>IsSendable</Name> + <Value>True</Value> + </PartnerProperties> + <PartnerProperties> + <Name>IsTestable</Name> + <Value>False</Value> + </PartnerProperties> + <PartnerProperties> + <Name>SendableCustomObjectField</Name> + <Value>SubscriberKey</Value> + </PartnerProperties> + <PartnerProperties> + <Name>SendableSubscriberField</Name> + <Value>_SubscriberKey</Value> + </PartnerProperties> + <PartnerProperties> + <Name>DataRetentionPeriodLength</Name> + <Value /> + </PartnerProperties> + <PartnerProperties> + <Name>DataRetentionPeriodUnitOfMeasure</Name> + <Value /> + </PartnerProperties> + <PartnerProperties> + <Name>RowBasedRetention</Name> + <Value>False</Value> + </PartnerProperties> + <PartnerProperties> + <Name>ResetRetentionPeriodOnImport</Name> + <Value>False</Value> + </PartnerProperties> + <PartnerProperties> + <Name>DeleteAtEndOfRetentionPeriod</Name> + <Value>False</Value> + </PartnerProperties> + <PartnerProperties> + <Name>RetainUntil</Name> + <Value /> + </PartnerProperties> + <ObjectID>1fd7fc95-d594-ea11-a2e6-1402ec938a35</ObjectID> + <CustomerKey>B6E8AE4C-3D93-49B1-B299-E0AE734213DD</CustomerKey> + <Name>TriggeredSendDataExtension</Name> + <Description>Triggered Send Source Data Extension Template</Description> + </Results> + <Results xsi:type="DataExtensionTemplate"> + <PartnerKey xsi:nil="true" /> + <PartnerProperties> + <Name>IsSendable</Name> + <Value>True</Value> + </PartnerProperties> + <PartnerProperties> + <Name>IsTestable</Name> + <Value>False</Value> + </PartnerProperties> + <PartnerProperties> + <Name>SendableCustomObjectField</Name> + <Value>Email Address</Value> + </PartnerProperties> + <PartnerProperties> + <Name>SendableSubscriberField</Name> + <Value>_EmailAddress</Value> + </PartnerProperties> + <PartnerProperties> + <Name>DataRetentionPeriodLength</Name> + <Value /> + </PartnerProperties> + <PartnerProperties> + <Name>DataRetentionPeriodUnitOfMeasure</Name> + <Value /> + </PartnerProperties> + <PartnerProperties> + <Name>RowBasedRetention</Name> + <Value>False</Value> + </PartnerProperties> + <PartnerProperties> + <Name>ResetRetentionPeriodOnImport</Name> + <Value>False</Value> + </PartnerProperties> + <PartnerProperties> + <Name>DeleteAtEndOfRetentionPeriod</Name> + <Value>False</Value> + </PartnerProperties> + <PartnerProperties> + <Name>RetainUntil</Name> + <Value /> + </PartnerProperties> + <ObjectID>bb1df59b-d594-ea11-a2e6-1402ec938a35</ObjectID> + <CustomerKey>23471ECA-8710-4512-9296-040CA86FBD9E</CustomerKey> + <Name>CONTEXTUAL_SUPPRESSION_LISTS</Name> + <Description>Used to create new auto-suppression lists</Description> + </Results> + <Results xsi:type="DataExtensionTemplate"> + <PartnerKey xsi:nil="true" /> + <PartnerProperties> + <Name>IsSendable</Name> + <Value>True</Value> + </PartnerProperties> + <PartnerProperties> + <Name>IsTestable</Name> + <Value>False</Value> + </PartnerProperties> + <PartnerProperties> + <Name>SendableCustomObjectField</Name> + <Value>EmailAddress</Value> + </PartnerProperties> + <PartnerProperties> + <Name>SendableSubscriberField</Name> + <Value>_SubscriberKey</Value> + </PartnerProperties> + <PartnerProperties> + <Name>DataRetentionPeriodLength</Name> + <Value /> + </PartnerProperties> + <PartnerProperties> + <Name>DataRetentionPeriodUnitOfMeasure</Name> + <Value /> + </PartnerProperties> + <PartnerProperties> + <Name>RowBasedRetention</Name> + <Value>False</Value> + </PartnerProperties> + <PartnerProperties> + <Name>ResetRetentionPeriodOnImport</Name> + <Value>False</Value> + </PartnerProperties> + <PartnerProperties> + <Name>DeleteAtEndOfRetentionPeriod</Name> + <Value>False</Value> + </PartnerProperties> + <PartnerProperties> + <Name>RetainUntil</Name> + <Value /> + </PartnerProperties> + <ObjectID>e61df59b-d594-ea11-a2e6-1402ec938a35</ObjectID> + <CustomerKey>00A4369E-0B57-4EF2-BFFA-E3F23B4D1098</CustomerKey> + <Name>SocialPages Default Template Extension</Name> + <Description>Required for contacts. Used by Smart Capture for Social Pages.</Description> + </Results> + <Results xsi:type="DataExtensionTemplate"> + <PartnerKey xsi:nil="true" /> + <PartnerProperties> + <Name>IsSendable</Name> + <Value>True</Value> + </PartnerProperties> + <PartnerProperties> + <Name>IsTestable</Name> + <Value>False</Value> + </PartnerProperties> + <PartnerProperties> + <Name>SendableCustomObjectField</Name> + <Value>SubscriberKey</Value> + </PartnerProperties> + <PartnerProperties> + <Name>SendableSubscriberField</Name> + <Value>_SubscriberKey</Value> + </PartnerProperties> + <PartnerProperties> + <Name>DataRetentionPeriodLength</Name> + <Value>6</Value> + </PartnerProperties> + <PartnerProperties> + <Name>DataRetentionPeriodUnitOfMeasure</Name> + <Value>5</Value> + </PartnerProperties> + <PartnerProperties> + <Name>RowBasedRetention</Name> + <Value>False</Value> + </PartnerProperties> + <PartnerProperties> + <Name>ResetRetentionPeriodOnImport</Name> + <Value>False</Value> + </PartnerProperties> + <PartnerProperties> + <Name>DeleteAtEndOfRetentionPeriod</Name> + <Value>False</Value> + </PartnerProperties> + <PartnerProperties> + <Name>RetainUntil</Name> + <Value /> + </PartnerProperties> + <ObjectID>37d8c7f2-ad19-4084-8d18-4dda1dc36772</ObjectID> + <CustomerKey>DAE95D91-762C-4124-B082-0433165ADD30</CustomerKey> + <Name>AudienceBuilderResult</Name> + <Description>Used for creating audience builder result destinations.</Description> + </Results> + <Results xsi:type="DataExtensionTemplate"> + <PartnerKey xsi:nil="true" /> + <PartnerProperties> + <Name>IsSendable</Name> + <Value>True</Value> + </PartnerProperties> + <PartnerProperties> + <Name>IsTestable</Name> + <Value>False</Value> + </PartnerProperties> + <PartnerProperties> + <Name>SendableCustomObjectField</Name> + <Value>ContactKey</Value> + </PartnerProperties> + <PartnerProperties> + <Name>SendableSubscriberField</Name> + <Value>_SubscriberKey</Value> + </PartnerProperties> + <PartnerProperties> + <Name>DataRetentionPeriodLength</Name> + <Value /> + </PartnerProperties> + <PartnerProperties> + <Name>DataRetentionPeriodUnitOfMeasure</Name> + <Value>0</Value> + </PartnerProperties> + <PartnerProperties> + <Name>RowBasedRetention</Name> + <Value>False</Value> + </PartnerProperties> + <PartnerProperties> + <Name>ResetRetentionPeriodOnImport</Name> + <Value>False</Value> + </PartnerProperties> + <PartnerProperties> + <Name>DeleteAtEndOfRetentionPeriod</Name> + <Value>False</Value> + </PartnerProperties> + <PartnerProperties> + <Name>RetainUntil</Name> + <Value /> + </PartnerProperties> + <ObjectID>941cf36b-f927-4674-8468-c9a3bed7cae4</ObjectID> + <CustomerKey>BE1B7591-BFA6-473F-A6CE-0E458204865B</CustomerKey> + <Name>Event DE Template</Name> + <Description>Event Data Extension Template</Description> + </Results> + </RetrieveResponseMsg> + </soap:Body> +</soap:Envelope> \ No newline at end of file diff --git a/test/resources/9999999/dataExtract/build-expected.json b/test/resources/9999999/dataExtract/build-expected.json new file mode 100644 index 000000000..99ec29f0e --- /dev/null +++ b/test/resources/9999999/dataExtract/build-expected.json @@ -0,0 +1,35 @@ +{ + "dataFields": [ + { + "name": "ColumnDelimiter", + "type": "string", + "value": "," + }, + { + "name": "DECustomerKey", + "type": "string" + }, + { + "name": "HasColumnHeaders", + "type": "bool", + "value": "False" + }, + { + "name": "TextQualified", + "type": "bool", + "value": "False" + }, + { + "name": "UsesLineFeed", + "type": "bool", + "value": "False" + } + ], + "description": "blabla", + "fileSpec": "testExisting-%%Year%%-%%Month%%-%%Day%%", + "intervalType": 0, + "key": "testTemplated_dataExtract", + "name": "testTemplated_dataExtract", + "r__dataExtension_key": "testTemplated_dataExtension", + "r__dataExtractType_name": "Data Extension Extract" +} diff --git a/test/resources/9999999/dataExtract/get-expected.json b/test/resources/9999999/dataExtract/get-expected.json new file mode 100644 index 000000000..e7544bf9f --- /dev/null +++ b/test/resources/9999999/dataExtract/get-expected.json @@ -0,0 +1,39 @@ +{ + "createdBy": "Jörn Berkefeld", + "createdDate": "2022-11-09T05:31:21.667", + "dataFields": [ + { + "name": "ColumnDelimiter", + "type": "string", + "value": "," + }, + { + "name": "DECustomerKey", + "type": "string" + }, + { + "name": "HasColumnHeaders", + "type": "bool", + "value": "False" + }, + { + "name": "TextQualified", + "type": "bool", + "value": "False" + }, + { + "name": "UsesLineFeed", + "type": "bool", + "value": "False" + } + ], + "description": "blabla", + "fileSpec": "testExisting-%%Year%%-%%Month%%-%%Day%%", + "intervalType": 0, + "key": "testExisting_dataExtract", + "modifiedBy": "Jörn Berkefeld", + "modifiedDate": "2022-11-17T07:13:36.9", + "name": "testExisting_dataExtract", + "r__dataExtension_key": "testExisting_dataExtension", + "r__dataExtractType_name": "Data Extension Extract" +} diff --git a/test/resources/9999999/dataExtract/patch-expected.json b/test/resources/9999999/dataExtract/patch-expected.json new file mode 100644 index 000000000..e7544bf9f --- /dev/null +++ b/test/resources/9999999/dataExtract/patch-expected.json @@ -0,0 +1,39 @@ +{ + "createdBy": "Jörn Berkefeld", + "createdDate": "2022-11-09T05:31:21.667", + "dataFields": [ + { + "name": "ColumnDelimiter", + "type": "string", + "value": "," + }, + { + "name": "DECustomerKey", + "type": "string" + }, + { + "name": "HasColumnHeaders", + "type": "bool", + "value": "False" + }, + { + "name": "TextQualified", + "type": "bool", + "value": "False" + }, + { + "name": "UsesLineFeed", + "type": "bool", + "value": "False" + } + ], + "description": "blabla", + "fileSpec": "testExisting-%%Year%%-%%Month%%-%%Day%%", + "intervalType": 0, + "key": "testExisting_dataExtract", + "modifiedBy": "Jörn Berkefeld", + "modifiedDate": "2022-11-17T07:13:36.9", + "name": "testExisting_dataExtract", + "r__dataExtension_key": "testExisting_dataExtension", + "r__dataExtractType_name": "Data Extension Extract" +} diff --git a/test/resources/9999999/dataExtract/post-expected.json b/test/resources/9999999/dataExtract/post-expected.json new file mode 100644 index 000000000..1e1273879 --- /dev/null +++ b/test/resources/9999999/dataExtract/post-expected.json @@ -0,0 +1,37 @@ +{ + "createdBy": "Jörn Berkefeld", + "dataFields": [ + { + "name": "ColumnDelimiter", + "type": "string", + "value": "," + }, + { + "name": "DECustomerKey", + "type": "string" + }, + { + "name": "HasColumnHeaders", + "type": "bool", + "value": "False" + }, + { + "name": "TextQualified", + "type": "bool", + "value": "False" + }, + { + "name": "UsesLineFeed", + "type": "bool", + "value": "False" + } + ], + "description": "blabla", + "fileSpec": "testNew-%%Year%%-%%Month%%-%%Day%%", + "intervalType": 0, + "key": "testNew_dataExtract", + "modifiedBy": "Jörn Berkefeld", + "name": "testNew_dataExtract", + "r__dataExtension_key": "testExisting_dataExtension", + "r__dataExtractType_name": "Data Extension Extract" +} diff --git a/test/resources/9999999/dataExtract/template-expected.json b/test/resources/9999999/dataExtract/template-expected.json new file mode 100644 index 000000000..495971f68 --- /dev/null +++ b/test/resources/9999999/dataExtract/template-expected.json @@ -0,0 +1,35 @@ +{ + "dataFields": [ + { + "name": "ColumnDelimiter", + "type": "string", + "value": "," + }, + { + "name": "DECustomerKey", + "type": "string" + }, + { + "name": "HasColumnHeaders", + "type": "bool", + "value": "False" + }, + { + "name": "TextQualified", + "type": "bool", + "value": "False" + }, + { + "name": "UsesLineFeed", + "type": "bool", + "value": "False" + } + ], + "description": "blabla", + "fileSpec": "testExisting-%%Year%%-%%Month%%-%%Day%%", + "intervalType": 0, + "key": "{{{prefix}}}dataExtract", + "name": "{{{prefix}}}dataExtract", + "r__dataExtension_key": "{{{prefix}}}dataExtension", + "r__dataExtractType_name": "Data Extension Extract" +} diff --git a/test/resources/9999999/dataFilter/build-expected.json b/test/resources/9999999/dataFilter/build-expected.json new file mode 100644 index 000000000..1465ecf2b --- /dev/null +++ b/test/resources/9999999/dataFilter/build-expected.json @@ -0,0 +1,19 @@ +{ + "c__filterDefinition": { + "ConditionSet": { + "@_ConditionSetName": "Outer Grouping", + "@_Operator": "AND", + "Condition": { + "@_Operator": "Ends", + "Value": "_testTarget", + "r__dataExtensionField_name": "LastName" + } + } + }, + "description": "test", + "isSendable": true, + "key": "testTemplated_dataFilter", + "name": "testTemplated_dataFilter", + "r__folder_Path": "Data Filters", + "r__source_dataExtension_key": "testTemplated_dataExtension" +} diff --git a/test/resources/9999999/dataFilter/get-expected.json b/test/resources/9999999/dataFilter/get-expected.json new file mode 100644 index 000000000..656513024 --- /dev/null +++ b/test/resources/9999999/dataFilter/get-expected.json @@ -0,0 +1,23 @@ +{ + "createdByName": "Jörn Berkefeld", + "createdDate": "2025-12-01T16:54:09.813", + "lastUpdated": "2025-12-01T17:17:31.827", + "lastUpdatedByName": "Jörn Berkefeld", + "description": "test", + "key": "testExisting_dataFilter", + "name": "testExisting_dataFilter", + "isSendable": true, + "c__filterDefinition": { + "ConditionSet": { + "@_ConditionSetName": "Outer Grouping", + "@_Operator": "AND", + "Condition": { + "@_Operator": "Ends", + "Value": "_test", + "r__dataExtensionField_name": "LastName" + } + } + }, + "r__folder_Path": "Data Filters", + "r__source_dataExtension_key": "testExisting_dataExtension" +} diff --git a/test/resources/9999999/dataFilter/patch-expected.json b/test/resources/9999999/dataFilter/patch-expected.json new file mode 100644 index 000000000..16a51e2b1 --- /dev/null +++ b/test/resources/9999999/dataFilter/patch-expected.json @@ -0,0 +1,20 @@ +{ + "c__filterDefinition": { + "ConditionSet": { + "@_ConditionSetName": "Outer Grouping", + "@_Operator": "AND", + "Condition": { + "@_Operator": "Begins", + "Value": "testExisting_", + "r__dataExtensionField_name": "LastName" + } + } + }, + "createdDate": "2026-01-27T06:24:40.527", + "isSendable": true, + "key": "testExisting_dataFilter", + "lastUpdated": "2026-01-30T10:46:59.777", + "name": "testExisting_dataFilter", + "r__folder_Path": "Data Filters", + "r__source_dataExtension_key": "testExisting_dataExtension" +} diff --git a/test/resources/9999999/dataFilter/post-expected.json b/test/resources/9999999/dataFilter/post-expected.json new file mode 100644 index 000000000..0ff32f18e --- /dev/null +++ b/test/resources/9999999/dataFilter/post-expected.json @@ -0,0 +1,20 @@ +{ + "createdDate": "2026-01-30T11:04:06.883", + "lastUpdated": "2026-01-30T11:04:06.883", + "isSendable": false, + "key": "testNew_dataFilter", + "name": "testNew_dataFilter", + "c__filterDefinition": { + "ConditionSet": { + "@_ConditionSetName": "Outer Grouping", + "@_Operator": "AND", + "Condition": { + "@_Operator": "Ends", + "Value": "_test", + "r__dataExtensionField_name": "LastName" + } + } + }, + "r__folder_Path": "Data Filters", + "r__source_dataExtension_key": "testExisting_dataExtension" +} diff --git a/test/resources/9999999/dataFilter/template-expected.json b/test/resources/9999999/dataFilter/template-expected.json new file mode 100644 index 000000000..77725c0f0 --- /dev/null +++ b/test/resources/9999999/dataFilter/template-expected.json @@ -0,0 +1,19 @@ +{ + "c__filterDefinition": { + "ConditionSet": { + "@_ConditionSetName": "Outer Grouping", + "@_Operator": "AND", + "Condition": { + "@_Operator": "Ends", + "Value": "{{{suffix}}}", + "r__dataExtensionField_name": "LastName" + } + } + }, + "description": "test", + "isSendable": true, + "key": "{{{prefix}}}dataFilter", + "name": "{{{prefix}}}dataFilter", + "r__folder_Path": "Data Filters", + "r__source_dataExtension_key": "{{{prefix}}}dataExtension" +} diff --git a/test/resources/9999999/dataFolder/+retrieve-ContentTypeINasset,asset-shared,cloudpages-slashfolder-response.xml b/test/resources/9999999/dataFolder/+retrieve-ContentTypeINasset,asset-shared,cloudpages-slashfolder-response.xml new file mode 100644 index 000000000..d91fa68fb --- /dev/null +++ b/test/resources/9999999/dataFolder/+retrieve-ContentTypeINasset,asset-shared,cloudpages-slashfolder-response.xml @@ -0,0 +1,136 @@ +<?xml version="1.0" encoding="utf-8"?> +<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:xsd="http://www.w3.org/2001/XMLSchema" + xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing" + xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" + xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"> + <soap:Header> + <wsa:Action>RetrieveResponse</wsa:Action> + <wsa:MessageID>urn:uuid:00106553-ac00-4e72-b387-42325fe6f93d</wsa:MessageID> + <wsa:RelatesTo>urn:uuid:a1dd2a9d-b696-480e-9a1b-265f262a8997</wsa:RelatesTo> + <wsa:To>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</wsa:To> + <wsse:Security> + <wsu:Timestamp wsu:Id="Timestamp-d82724f8-afc2-4461-8e3e-190aeb6d9625"> + <wsu:Created>2024-01-08T14:30:39Z</wsu:Created> + <wsu:Expires>2024-01-08T14:35:39Z</wsu:Expires> + </wsu:Timestamp> + </wsse:Security> + </soap:Header> + <soap:Body> + <RetrieveResponseMsg xmlns="http://exacttarget.com/wsdl/partnerAPI"> + <OverallStatus>OK</OverallStatus> + <RequestID>6596087d-d12f-4c9d-9353-783fe01775a3</RequestID> + <Results xsi:type="DataFolder"> + <Client> + <ID>9999999</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2016-07-22T11:52:35.687</CreatedDate> + <ModifiedDate>2016-07-22T11:52:35.687</ModifiedDate> + <ID>89397</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey /> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>0</ID> + <ObjectID xsi:nil="true" /> + </ParentFolder> + <Name>Content Builder</Name> + <Description>The root folder for assets</Description> + <ContentType>asset</ContentType> + <IsActive>true</IsActive> + <IsEditable>false</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>9999999</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2016-07-29T12:13:07.7</CreatedDate> + <ModifiedDate>2021-12-16T02:56:14.68</ModifiedDate> + <ID>90888</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey /> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>89397</ID> + <ObjectID xsi:nil="true" /> + </ParentFolder> + <Name>Test Folder</Name> + <Description /> + <ContentType>asset</ContentType> + <IsActive>true</IsActive> + <IsEditable>true</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>9999999</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2026-03-06T07:47:11.04</CreatedDate> + <ModifiedDate>2026-03-06T07:47:11.04</ModifiedDate> + <ID>38491</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey /> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>89397</ID> + <ObjectID xsi:nil="true" /> + </ParentFolder> + <Name>bla/blub</Name> + <Description /> + <ContentType>asset</ContentType> + <IsActive>true</IsActive> + <IsEditable>true</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>9999999</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2024-02-16T10:12:15.9</CreatedDate> + <ModifiedDate>2024-02-16T10:12:15.9</ModifiedDate> + <ID>14914</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey /> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>0</ID> + <ObjectID xsi:nil="true" /> + </ParentFolder> + <Name>CloudPages</Name> + <Description>The root folder for CloudPages</Description> + <ContentType>cloudpages</ContentType> + <IsActive>true</IsActive> + <IsEditable>false</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>510007949</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2025-03-25T03:00:33.163</CreatedDate> + <ModifiedDate>2025-03-26T03:33:00.893</ModifiedDate> + <ID>27675</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>958bac7c-972b-4cac-aa8a-22a2b77b0fbc</CustomerKey> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>14914</ID> + <ObjectID xsi:nil="true" /> + </ParentFolder> + <Name>mcdev</Name> + <Description /> + <ContentType>cloudpages</ContentType> + <IsActive>true</IsActive> + <IsEditable>true</IsEditable> + <AllowChildren>false</AllowChildren> + </Results> + </RetrieveResponseMsg> + </soap:Body> +</soap:Envelope> diff --git a/test/resources/9999999/dataFolder/create-ContentType=asset,Name=testFolder_samePath,ParentFolderID=89397-response.xml b/test/resources/9999999/dataFolder/create-ContentType=asset,Name=testFolder_samePath,ParentFolderID=89397-response.xml new file mode 100644 index 000000000..9eb382160 --- /dev/null +++ b/test/resources/9999999/dataFolder/create-ContentType=asset,Name=testFolder_samePath,ParentFolderID=89397-response.xml @@ -0,0 +1,33 @@ +<?xml version="1.0" encoding="utf-8"?> +<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:xsd="http://www.w3.org/2001/XMLSchema" + xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing" + xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" + xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"> + <soap:Header> + <wsa:Action>CreateResponse</wsa:Action> + <wsa:MessageID>urn:uuid:50c68314-30a5-45d4-93aa-6dd1191190e3</wsa:MessageID> + <wsa:RelatesTo>urn:uuid:00b40ac8-d7e8-4e55-8b88-fcf3569684a9</wsa:RelatesTo> + <wsa:To>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</wsa:To> + <wsse:Security> + <wsu:Timestamp wsu:Id="Timestamp-26435e8f-90d6-4552-aabb-d5eefa3a4bed"> + <wsu:Created>2024-08-08T09:56:20Z</wsu:Created> + <wsu:Expires>2024-08-08T10:01:20Z</wsu:Expires> + </wsu:Timestamp> + </wsse:Security> + </soap:Header> + <soap:Body> + <CreateResponse xmlns="http://exacttarget.com/wsdl/partnerAPI"> + <Results> + <StatusCode>OK</StatusCode> + <StatusMessage>Folder created successfully.</StatusMessage> + <OrdinalID>0</OrdinalID> + <NewID>88888</NewID> + <NewObjectID>a890243b-a4e1-4010-85e4-db6d6ae84502</NewObjectID> + </Results> + <RequestID>6b408e0b-ecbe-4b8e-9019-6376f6eeb0e2</RequestID> + <OverallStatus>OK</OverallStatus> + </CreateResponse> + </soap:Body> +</soap:Envelope> diff --git a/test/resources/9999999/dataFolder/create-ContentType=dataextension,Name=my,ParentFolderID=2-response.xml b/test/resources/9999999/dataFolder/create-ContentType=dataextension,Name=my,ParentFolderID=2-response.xml new file mode 100644 index 000000000..390672484 --- /dev/null +++ b/test/resources/9999999/dataFolder/create-ContentType=dataextension,Name=my,ParentFolderID=2-response.xml @@ -0,0 +1,33 @@ +<?xml version="1.0" encoding="utf-8"?> +<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:xsd="http://www.w3.org/2001/XMLSchema" + xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing" + xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" + xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"> + <soap:Header> + <wsa:Action>CreateResponse</wsa:Action> + <wsa:MessageID>urn:uuid:50c68314-30a5-45d4-93aa-6dd1191190e2</wsa:MessageID> + <wsa:RelatesTo>urn:uuid:00b40ac8-d7e8-4e55-8b88-fcf3569684a8</wsa:RelatesTo> + <wsa:To>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</wsa:To> + <wsse:Security> + <wsu:Timestamp wsu:Id="Timestamp-26435e8f-90d6-4552-aabb-d5eefa3a4bec"> + <wsu:Created>2024-08-08T09:56:20Z</wsu:Created> + <wsu:Expires>2024-08-08T10:01:20Z</wsu:Expires> + </wsu:Timestamp> + </wsse:Security> + </soap:Header> + <soap:Body> + <CreateResponse xmlns="http://exacttarget.com/wsdl/partnerAPI"> + <Results> + <StatusCode>OK</StatusCode> + <StatusMessage>Folder created successfully.</StatusMessage> + <OrdinalID>0</OrdinalID> + <NewID>862001</NewID> + <NewObjectID>d890243b-a4e1-4010-85e4-db6d6ae84501</NewObjectID> + </Results> + <RequestID>5b408e0b-ecbe-4b8e-9019-6376f6eeb0e1</RequestID> + <OverallStatus>OK</OverallStatus> + </CreateResponse> + </soap:Body> +</soap:Envelope> diff --git a/test/resources/9999999/dataFolder/create-ContentType=dataextension,Name=path,ParentFolderID=862002-response.xml b/test/resources/9999999/dataFolder/create-ContentType=dataextension,Name=path,ParentFolderID=862002-response.xml new file mode 100644 index 000000000..381ac39c7 --- /dev/null +++ b/test/resources/9999999/dataFolder/create-ContentType=dataextension,Name=path,ParentFolderID=862002-response.xml @@ -0,0 +1,33 @@ +<?xml version="1.0" encoding="utf-8"?> +<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:xsd="http://www.w3.org/2001/XMLSchema" + xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing" + xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" + xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"> + <soap:Header> + <wsa:Action>CreateResponse</wsa:Action> + <wsa:MessageID>urn:uuid:50c68314-30a5-45d4-93aa-6dd1191190e2</wsa:MessageID> + <wsa:RelatesTo>urn:uuid:00b40ac8-d7e8-4e55-8b88-fcf3569684a8</wsa:RelatesTo> + <wsa:To>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</wsa:To> + <wsse:Security> + <wsu:Timestamp wsu:Id="Timestamp-26435e8f-90d6-4552-aabb-d5eefa3a4bec"> + <wsu:Created>2024-08-08T09:56:20Z</wsu:Created> + <wsu:Expires>2024-08-08T10:01:20Z</wsu:Expires> + </wsu:Timestamp> + </wsse:Security> + </soap:Header> + <soap:Body> + <CreateResponse xmlns="http://exacttarget.com/wsdl/partnerAPI"> + <Results> + <StatusCode>OK</StatusCode> + <StatusMessage>Folder created successfully.</StatusMessage> + <OrdinalID>0</OrdinalID> + <NewID>862003</NewID> + <NewObjectID>d890243b-a4e1-4010-85e4-db6d6ae84503</NewObjectID> + </Results> + <RequestID>5b408e0b-ecbe-4b8e-9019-6376f6eeb0e1</RequestID> + <OverallStatus>OK</OverallStatus> + </CreateResponse> + </soap:Body> +</soap:Envelope> diff --git a/test/resources/9999999/dataFolder/create-ContentType=dataextension,Name=sub,ParentFolderID=862001-response.xml b/test/resources/9999999/dataFolder/create-ContentType=dataextension,Name=sub,ParentFolderID=862001-response.xml new file mode 100644 index 000000000..fee3bf6e0 --- /dev/null +++ b/test/resources/9999999/dataFolder/create-ContentType=dataextension,Name=sub,ParentFolderID=862001-response.xml @@ -0,0 +1,33 @@ +<?xml version="1.0" encoding="utf-8"?> +<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:xsd="http://www.w3.org/2001/XMLSchema" + xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing" + xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" + xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"> + <soap:Header> + <wsa:Action>CreateResponse</wsa:Action> + <wsa:MessageID>urn:uuid:50c68314-30a5-45d4-93aa-6dd1191190e2</wsa:MessageID> + <wsa:RelatesTo>urn:uuid:00b40ac8-d7e8-4e55-8b88-fcf3569684a8</wsa:RelatesTo> + <wsa:To>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</wsa:To> + <wsse:Security> + <wsu:Timestamp wsu:Id="Timestamp-26435e8f-90d6-4552-aabb-d5eefa3a4bec"> + <wsu:Created>2024-08-08T09:56:20Z</wsu:Created> + <wsu:Expires>2024-08-08T10:01:20Z</wsu:Expires> + </wsu:Timestamp> + </wsse:Security> + </soap:Header> + <soap:Body> + <CreateResponse xmlns="http://exacttarget.com/wsdl/partnerAPI"> + <Results> + <StatusCode>OK</StatusCode> + <StatusMessage>Folder created successfully.</StatusMessage> + <OrdinalID>0</OrdinalID> + <NewID>862002</NewID> + <NewObjectID>d890243b-a4e1-4010-85e4-db6d6ae84502</NewObjectID> + </Results> + <RequestID>5b408e0b-ecbe-4b8e-9019-6376f6eeb0e1</RequestID> + <OverallStatus>OK</OverallStatus> + </CreateResponse> + </soap:Body> +</soap:Envelope> diff --git a/test/resources/9999999/dataFolder/create-ContentType=dataextension,Name=subpath,ParentFolderID=862003-response.xml b/test/resources/9999999/dataFolder/create-ContentType=dataextension,Name=subpath,ParentFolderID=862003-response.xml new file mode 100644 index 000000000..35345e14d --- /dev/null +++ b/test/resources/9999999/dataFolder/create-ContentType=dataextension,Name=subpath,ParentFolderID=862003-response.xml @@ -0,0 +1,33 @@ +<?xml version="1.0" encoding="utf-8"?> +<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:xsd="http://www.w3.org/2001/XMLSchema" + xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing" + xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" + xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"> + <soap:Header> + <wsa:Action>CreateResponse</wsa:Action> + <wsa:MessageID>urn:uuid:50c68314-30a5-45d4-93aa-6dd1191190e2</wsa:MessageID> + <wsa:RelatesTo>urn:uuid:00b40ac8-d7e8-4e55-8b88-fcf3569684a8</wsa:RelatesTo> + <wsa:To>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</wsa:To> + <wsse:Security> + <wsu:Timestamp wsu:Id="Timestamp-26435e8f-90d6-4552-aabb-d5eefa3a4bec"> + <wsu:Created>2024-08-08T09:56:20Z</wsu:Created> + <wsu:Expires>2024-08-08T10:01:20Z</wsu:Expires> + </wsu:Timestamp> + </wsse:Security> + </soap:Header> + <soap:Body> + <CreateResponse xmlns="http://exacttarget.com/wsdl/partnerAPI"> + <Results> + <StatusCode>OK</StatusCode> + <StatusMessage>Folder created successfully.</StatusMessage> + <OrdinalID>0</OrdinalID> + <NewID>862004</NewID> + <NewObjectID>d890243b-a4e1-4010-85e4-db6d6ae84504</NewObjectID> + </Results> + <RequestID>5b408e0b-ecbe-4b8e-9019-6376f6eeb0e1</RequestID> + <OverallStatus>OK</OverallStatus> + </CreateResponse> + </soap:Body> +</soap:Envelope> diff --git a/test/resources/9999999/dataFolder/create-response.xml b/test/resources/9999999/dataFolder/create-response.xml new file mode 100644 index 000000000..ebbd01616 --- /dev/null +++ b/test/resources/9999999/dataFolder/create-response.xml @@ -0,0 +1,33 @@ +<?xml version="1.0" encoding="utf-8"?> +<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:xsd="http://www.w3.org/2001/XMLSchema" + xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing" + xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" + xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"> + <soap:Header> + <wsa:Action>CreateResponse</wsa:Action> + <wsa:MessageID>urn:uuid:50c68314-30a5-45d4-93aa-6dd1191190e3</wsa:MessageID> + <wsa:RelatesTo>urn:uuid:00b40ac8-d7e8-4e55-8b88-fcf3569684a9</wsa:RelatesTo> + <wsa:To>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</wsa:To> + <wsse:Security> + <wsu:Timestamp wsu:Id="Timestamp-26435e8f-90d6-4552-aabb-d5eefa3a4bed"> + <wsu:Created>2024-08-08T09:56:20Z</wsu:Created> + <wsu:Expires>2024-08-08T10:01:20Z</wsu:Expires> + </wsu:Timestamp> + </wsse:Security> + </soap:Header> + <soap:Body> + <CreateResponse xmlns="http://exacttarget.com/wsdl/partnerAPI"> + <Results> + <StatusCode>OK</StatusCode> + <StatusMessage>Folder created successfully.</StatusMessage> + <OrdinalID>0</OrdinalID> + <NewID>862099</NewID> + <NewObjectID>d890243b-a4e1-4010-85e4-db6d6ae84502</NewObjectID> + </Results> + <RequestID>5b408e0b-ecbe-4b8e-9019-6376f6eeb0e2</RequestID> + <OverallStatus>OK</OverallStatus> + </CreateResponse> + </soap:Body> +</soap:Envelope> diff --git a/test/resources/9999999/dataFolder/retrieve-ContentType=asset-shared-QAA-response.xml b/test/resources/9999999/dataFolder/retrieve-ContentType=asset-shared-QAA-response.xml new file mode 100644 index 000000000..e40e8bbdb --- /dev/null +++ b/test/resources/9999999/dataFolder/retrieve-ContentType=asset-shared-QAA-response.xml @@ -0,0 +1,70 @@ +<?xml version="1.0" encoding="utf-8"?> +<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:xsd="http://www.w3.org/2001/XMLSchema" + xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing" + xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" + xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"> + <soap:Header> + <wsa:Action>RetrieveResponse</wsa:Action> + <wsa:MessageID>urn:uuid:ece12788-5617-4bf7-97b6-d2ee6fefa7c5</wsa:MessageID> + <wsa:RelatesTo>urn:uuid:260afb64-4686-421e-bc94-46386dd6e28d</wsa:RelatesTo> + <wsa:To>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</wsa:To> + <wsse:Security> + <wsu:Timestamp wsu:Id="Timestamp-c6787260-1486-411c-b1e4-1a561aa1efd8"> + <wsu:Created>2024-07-22T09:14:36Z</wsu:Created> + <wsu:Expires>2024-07-22T09:19:36Z</wsu:Expires> + </wsu:Timestamp> + </wsse:Security> + </soap:Header> + <soap:Body> + <RetrieveResponseMsg xmlns="http://exacttarget.com/wsdl/partnerAPI"> + <OverallStatus>OK</OverallStatus> + <RequestID>0df23b67-2645-4b4f-87e1-f3eb6b818dde</RequestID> + <Results xsi:type="DataFolder"> + <Client> + <ID>1111111</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2021-06-21T11:55:12.743</CreatedDate> + <ModifiedDate>2021-06-21T11:55:12.743</ModifiedDate> + <ID>4707</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey /> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>0</ID> + <ObjectID xsi:nil="true" /> + </ParentFolder> + <Name>Content Builder</Name> + <Description>The root folder for assets</Description> + <ContentType>asset</ContentType> + <IsActive>true</IsActive> + <IsEditable>false</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>1111111</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2021-06-21T11:55:13.34</CreatedDate> + <ModifiedDate>2021-06-21T11:55:13.34</ModifiedDate> + <ID>4710</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey /> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>0</ID> + <ObjectID xsi:nil="true" /> + </ParentFolder> + <Name>Shared Content</Name> + <Description>The root shared folder for assets</Description> + <ContentType>asset-shared</ContentType> + <IsActive>true</IsActive> + <IsEditable>false</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + </RetrieveResponseMsg> + </soap:Body> +</soap:Envelope> diff --git a/test/resources/9999999/dataFolder/retrieve-ContentType=asset-shared-response.xml b/test/resources/9999999/dataFolder/retrieve-ContentType=asset-shared-response.xml new file mode 100644 index 000000000..e40e8bbdb --- /dev/null +++ b/test/resources/9999999/dataFolder/retrieve-ContentType=asset-shared-response.xml @@ -0,0 +1,70 @@ +<?xml version="1.0" encoding="utf-8"?> +<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:xsd="http://www.w3.org/2001/XMLSchema" + xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing" + xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" + xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"> + <soap:Header> + <wsa:Action>RetrieveResponse</wsa:Action> + <wsa:MessageID>urn:uuid:ece12788-5617-4bf7-97b6-d2ee6fefa7c5</wsa:MessageID> + <wsa:RelatesTo>urn:uuid:260afb64-4686-421e-bc94-46386dd6e28d</wsa:RelatesTo> + <wsa:To>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</wsa:To> + <wsse:Security> + <wsu:Timestamp wsu:Id="Timestamp-c6787260-1486-411c-b1e4-1a561aa1efd8"> + <wsu:Created>2024-07-22T09:14:36Z</wsu:Created> + <wsu:Expires>2024-07-22T09:19:36Z</wsu:Expires> + </wsu:Timestamp> + </wsse:Security> + </soap:Header> + <soap:Body> + <RetrieveResponseMsg xmlns="http://exacttarget.com/wsdl/partnerAPI"> + <OverallStatus>OK</OverallStatus> + <RequestID>0df23b67-2645-4b4f-87e1-f3eb6b818dde</RequestID> + <Results xsi:type="DataFolder"> + <Client> + <ID>1111111</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2021-06-21T11:55:12.743</CreatedDate> + <ModifiedDate>2021-06-21T11:55:12.743</ModifiedDate> + <ID>4707</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey /> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>0</ID> + <ObjectID xsi:nil="true" /> + </ParentFolder> + <Name>Content Builder</Name> + <Description>The root folder for assets</Description> + <ContentType>asset</ContentType> + <IsActive>true</IsActive> + <IsEditable>false</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>1111111</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2021-06-21T11:55:13.34</CreatedDate> + <ModifiedDate>2021-06-21T11:55:13.34</ModifiedDate> + <ID>4710</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey /> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>0</ID> + <ObjectID xsi:nil="true" /> + </ParentFolder> + <Name>Shared Content</Name> + <Description>The root shared folder for assets</Description> + <ContentType>asset-shared</ContentType> + <IsActive>true</IsActive> + <IsEditable>false</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + </RetrieveResponseMsg> + </soap:Body> +</soap:Envelope> diff --git a/test/resources/9999999/dataFolder/retrieve-ContentType=automations-response.xml b/test/resources/9999999/dataFolder/retrieve-ContentType=automations-response.xml new file mode 100644 index 000000000..995659991 --- /dev/null +++ b/test/resources/9999999/dataFolder/retrieve-ContentType=automations-response.xml @@ -0,0 +1,48 @@ +<?xml version="1.0" encoding="utf-8"?> +<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:xsd="http://www.w3.org/2001/XMLSchema" + xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing" + xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" + xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"> + <soap:Header> + <wsa:Action>RetrieveResponse</wsa:Action> + <wsa:MessageID>urn:uuid:f36f3303-3b5a-4641-8109-b26447634d91</wsa:MessageID> + <wsa:RelatesTo>urn:uuid:33983968-28c4-4379-bb5f-f80ae32eb988</wsa:RelatesTo> + <wsa:To>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</wsa:To> + <wsse:Security> + <wsu:Timestamp wsu:Id="Timestamp-32ecc81b-6020-473c-9e99-4b5338921220"> + <wsu:Created>2022-04-19T20:03:41Z</wsu:Created> + <wsu:Expires>2022-04-19T20:08:41Z</wsu:Expires> + </wsu:Timestamp> + </wsse:Security> + </soap:Header> + <soap:Body> + <RetrieveResponseMsg xmlns="http://exacttarget.com/wsdl/partnerAPI"> + <OverallStatus>OK</OverallStatus> + <RequestID>02cd5ccb-8f84-4651-826f-71169eeecf05</RequestID> + <Results xsi:type="DataFolder"> + <Client> + <ID>9999999</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2019-10-25T05:35:17.337</CreatedDate> + <ModifiedDate>2019-10-25T05:35:17.337</ModifiedDate> + <ID>290937</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey /> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>0</ID> + <ObjectID xsi:nil="true" /> + </ParentFolder> + <Name>my automations</Name> + <Description /> + <ContentType>automations</ContentType> + <IsActive>true</IsActive> + <IsEditable>true</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + </RetrieveResponseMsg> + </soap:Body> +</soap:Envelope> diff --git a/test/resources/9999999/dataFolder/retrieve-ContentType=journey-response.xml b/test/resources/9999999/dataFolder/retrieve-ContentType=journey-response.xml new file mode 100644 index 000000000..f0aac0fcd --- /dev/null +++ b/test/resources/9999999/dataFolder/retrieve-ContentType=journey-response.xml @@ -0,0 +1,48 @@ +<?xml version="1.0" encoding="utf-8"?> +<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:xsd="http://www.w3.org/2001/XMLSchema" + xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing" + xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" + xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"> + <soap:Header> + <wsa:Action>RetrieveResponse</wsa:Action> + <wsa:MessageID>urn:uuid:dc2be79b-a2b9-4775-90f9-92f7298129e4</wsa:MessageID> + <wsa:RelatesTo>urn:uuid:e6015b6f-c9d3-4649-aed8-ea66f1a1dbe8</wsa:RelatesTo> + <wsa:To>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</wsa:To> + <wsse:Security> + <wsu:Timestamp wsu:Id="Timestamp-89a3ca99-8f71-4361-959c-6fd89384ed9e"> + <wsu:Created>2024-07-22T11:05:21Z</wsu:Created> + <wsu:Expires>2024-07-22T11:10:21Z</wsu:Expires> + </wsu:Timestamp> + </wsse:Security> + </soap:Header> + <soap:Body> + <RetrieveResponseMsg xmlns="http://exacttarget.com/wsdl/partnerAPI"> + <OverallStatus>OK</OverallStatus> + <RequestID>37bbe40c-a525-4f43-b907-0cc83fe7a020</RequestID> + <Results xsi:type="DataFolder"> + <Client> + <ID>9999999</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2017-02-16T01:59:32.323</CreatedDate> + <ModifiedDate>2017-02-16T01:59:32.323</ModifiedDate> + <ID>6298</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>journey_default</CustomerKey> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>0</ID> + <ObjectID xsi:nil="true" /> + </ParentFolder> + <Name>my journeys</Name> + <Description>The root folder for Journeys</Description> + <ContentType>journey</ContentType> + <IsActive>true</IsActive> + <IsEditable>false</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + </RetrieveResponseMsg> + </soap:Body> +</soap:Envelope> diff --git a/test/resources/9999999/dataFolder/retrieve-ContentType=queryactivity-response.xml b/test/resources/9999999/dataFolder/retrieve-ContentType=queryactivity-response.xml new file mode 100644 index 000000000..668f47112 --- /dev/null +++ b/test/resources/9999999/dataFolder/retrieve-ContentType=queryactivity-response.xml @@ -0,0 +1,48 @@ +<?xml version="1.0" encoding="utf-8"?> +<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:xsd="http://www.w3.org/2001/XMLSchema" + xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing" + xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" + xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"> + <soap:Header> + <wsa:Action>RetrieveResponse</wsa:Action> + <wsa:MessageID>urn:uuid:f36f3303-3b5a-4641-8109-b26447634d91</wsa:MessageID> + <wsa:RelatesTo>urn:uuid:33983968-28c4-4379-bb5f-f80ae32eb988</wsa:RelatesTo> + <wsa:To>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</wsa:To> + <wsse:Security> + <wsu:Timestamp wsu:Id="Timestamp-32ecc81b-6020-473c-9e99-4b5338921220"> + <wsu:Created>2022-04-19T20:03:41Z</wsu:Created> + <wsu:Expires>2022-04-19T20:08:41Z</wsu:Expires> + </wsu:Timestamp> + </wsse:Security> + </soap:Header> + <soap:Body> + <RetrieveResponseMsg xmlns="http://exacttarget.com/wsdl/partnerAPI"> + <OverallStatus>OK</OverallStatus> + <RequestID>02cd5ccb-8f84-4651-826f-71169eeecf05</RequestID> + <Results xsi:type="DataFolder"> + <Client> + <ID>9999999</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2016-07-22T11:52:20.407</CreatedDate> + <ModifiedDate>2016-07-22T11:52:20.407</ModifiedDate> + <ID>999</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>queryactivity_default</CustomerKey> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>0</ID> + <ObjectID xsi:nil="true" /> + </ParentFolder> + <Name>Query</Name> + <Description /> + <ContentType>queryactivity</ContentType> + <IsActive>true</IsActive> + <IsEditable>false</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + </RetrieveResponseMsg> + </soap:Body> +</soap:Envelope> diff --git a/test/resources/9999999/dataFolder/retrieve-ContentType=ssjsactivity-response.xml b/test/resources/9999999/dataFolder/retrieve-ContentType=ssjsactivity-response.xml new file mode 100644 index 000000000..65f4ad08a --- /dev/null +++ b/test/resources/9999999/dataFolder/retrieve-ContentType=ssjsactivity-response.xml @@ -0,0 +1,48 @@ +<?xml version="1.0" encoding="utf-8"?> +<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:xsd="http://www.w3.org/2001/XMLSchema" + xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing" + xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" + xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"> + <soap:Header> + <wsa:Action>RetrieveResponse</wsa:Action> + <wsa:MessageID>urn:uuid:f36f3303-3b5a-4641-8109-b26447634d91</wsa:MessageID> + <wsa:RelatesTo>urn:uuid:33983968-28c4-4379-bb5f-f80ae32eb988</wsa:RelatesTo> + <wsa:To>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</wsa:To> + <wsse:Security> + <wsu:Timestamp wsu:Id="Timestamp-32ecc81b-6020-473c-9e99-4b5338921220"> + <wsu:Created>2022-04-19T20:03:41Z</wsu:Created> + <wsu:Expires>2022-04-19T20:08:41Z</wsu:Expires> + </wsu:Timestamp> + </wsse:Security> + </soap:Header> + <soap:Body> + <RetrieveResponseMsg xmlns="http://exacttarget.com/wsdl/partnerAPI"> + <OverallStatus>OK</OverallStatus> + <RequestID>02cd5ccb-8f84-4651-826f-71169eeecf05</RequestID> + <Results xsi:type="DataFolder"> + <Client> + <ID>9999999</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2017-01-24T06:32:42.353</CreatedDate> + <ModifiedDate>2017-01-24T06:32:42.353</ModifiedDate> + <ID>304</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>SSJSActivity_default</CustomerKey> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>0</ID> + <ObjectID xsi:nil="true" /> + </ParentFolder> + <Name>Scripts</Name> + <Description /> + <ContentType>SSJSActivity</ContentType> + <IsActive>true</IsActive> + <IsEditable>false</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + </RetrieveResponseMsg> + </soap:Body> +</soap:Envelope> diff --git a/test/resources/9999999/dataFolder/retrieve-ContentType=userinitiatedsends-response.xml b/test/resources/9999999/dataFolder/retrieve-ContentType=userinitiatedsends-response.xml new file mode 100644 index 000000000..b2b920e20 --- /dev/null +++ b/test/resources/9999999/dataFolder/retrieve-ContentType=userinitiatedsends-response.xml @@ -0,0 +1,48 @@ +<?xml version="1.0" encoding="utf-8"?> +<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:xsd="http://www.w3.org/2001/XMLSchema" + xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing" + xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" + xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"> + <soap:Header> + <wsa:Action>RetrieveResponse</wsa:Action> + <wsa:MessageID>urn:uuid:1512750f-32c9-4e70-adfe-6863acb037b4</wsa:MessageID> + <wsa:RelatesTo>urn:uuid:58a10fa7-12d7-4221-9d70-028add22d7be</wsa:RelatesTo> + <wsa:To>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</wsa:To> + <wsse:Security> + <wsu:Timestamp wsu:Id="Timestamp-fb923341-9f26-4ee2-8893-28bbf44ef6bb"> + <wsu:Created>2024-04-16T16:38:36Z</wsu:Created> + <wsu:Expires>2024-04-16T16:43:36Z</wsu:Expires> + </wsu:Timestamp> + </wsse:Security> + </soap:Header> + <soap:Body> + <RetrieveResponseMsg xmlns="http://exacttarget.com/wsdl/partnerAPI"> + <OverallStatus>OK</OverallStatus> + <RequestID>f0fec0a3-586b-4da9-95d3-ed47245d395c</RequestID> + <Results xsi:type="DataFolder"> + <Client> + <ID>9999999</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2021-06-21T11:54:58.023</CreatedDate> + <ModifiedDate>2021-06-21T11:54:58.023</ModifiedDate> + <ID>4691</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>userinitiatedsends_default</CustomerKey> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>0</ID> + <ObjectID xsi:nil="true" /> + </ParentFolder> + <Name>User-Initiated</Name> + <Description /> + <ContentType>userinitiatedsends</ContentType> + <IsActive>true</IsActive> + <IsEditable>false</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + </RetrieveResponseMsg> + </soap:Body> +</soap:Envelope> diff --git a/test/resources/9999999/dataFolder/retrieve-ContentTypeINasset,asset-sha,automatio,cloudpage,dataexten,filteract,filterdef,hidden,journey,list,mysubs,publicati,queryacti,salesforc,shared_da,shared_da,shared_sa,ssjsactiv,synchroni,useriniti-response.xml b/test/resources/9999999/dataFolder/retrieve-ContentTypeINasset,asset-sha,automatio,cloudpage,dataexten,filteract,filterdef,hidden,journey,list,mysubs,publicati,queryacti,salesforc,shared_da,shared_da,shared_sa,ssjsactiv,synchroni,useriniti-response.xml new file mode 100644 index 000000000..8e463721b --- /dev/null +++ b/test/resources/9999999/dataFolder/retrieve-ContentTypeINasset,asset-sha,automatio,cloudpage,dataexten,filteract,filterdef,hidden,journey,list,mysubs,publicati,queryacti,salesforc,shared_da,shared_da,shared_sa,ssjsactiv,synchroni,useriniti-response.xml @@ -0,0 +1,765 @@ +<?xml version="1.0" encoding="utf-8"?> +<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:xsd="http://www.w3.org/2001/XMLSchema" + xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing" + xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" + xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"> + <soap:Header> + <wsa:Action>RetrieveResponse</wsa:Action> + <wsa:MessageID>urn:uuid:f36f3303-3b5a-4641-8109-b26447634d91</wsa:MessageID> + <wsa:RelatesTo>urn:uuid:33983968-28c4-4379-bb5f-f80ae32eb988</wsa:RelatesTo> + <wsa:To>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</wsa:To> + <wsse:Security> + <wsu:Timestamp wsu:Id="Timestamp-32ecc81b-6020-473c-9e99-4b5338921220"> + <wsu:Created>2022-04-19T20:03:41Z</wsu:Created> + <wsu:Expires>2022-04-19T20:08:41Z</wsu:Expires> + </wsu:Timestamp> + </wsse:Security> + </soap:Header> + <soap:Body> + <RetrieveResponseMsg xmlns="http://exacttarget.com/wsdl/partnerAPI"> + <OverallStatus>OK</OverallStatus> + <RequestID>02cd5ccb-8f84-4651-826f-71169eeecf05</RequestID> + <Results xsi:type="DataFolder"> + <Client> + <ID>9999999</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2016-07-22T11:52:19.6</CreatedDate> + <ModifiedDate>2016-07-22T11:52:19.6</ModifiedDate> + <ID>2</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>dataextension_default</CustomerKey> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>0</ID> + <ObjectID xsi:nil="true" /> + </ParentFolder> + <Name>Data Extensions</Name> + <Description /> + <ContentType>dataextension</ContentType> + <IsActive>true</IsActive> + <IsEditable>false</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>9999999</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2016-07-22T11:52:20.407</CreatedDate> + <ModifiedDate>2016-07-22T11:52:20.407</ModifiedDate> + <ID>999</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>queryactivity_default</CustomerKey> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>0</ID> + <ObjectID xsi:nil="true" /> + </ParentFolder> + <Name>Query</Name> + <Description /> + <ContentType>queryactivity</ContentType> + <IsActive>true</IsActive> + <IsEditable>false</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>9999999</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2017-02-16T01:59:27.18</CreatedDate> + <ModifiedDate>2017-02-16T01:59:27.18</ModifiedDate> + <ID>412</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>mysubs_default</CustomerKey> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>0</ID> + <ObjectID xsi:nil="true" /> + </ParentFolder> + <Name>my subscribers</Name> + <Description /> + <ContentType>mysubs</ContentType> + <IsActive>true</IsActive> + <IsEditable>false</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>9999999</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2017-02-16T01:59:27.177</CreatedDate> + <ModifiedDate>2017-02-16T01:59:27.177</ModifiedDate> + <ID>404</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>list_default</CustomerKey> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>0</ID> + <ObjectID xsi:nil="true" /> + </ParentFolder> + <Name>my lists</Name> + <Description /> + <ContentType>list</ContentType> + <IsActive>true</IsActive> + <IsEditable>false</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>9999999</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2017-02-16T01:59:34.023</CreatedDate> + <ModifiedDate>2017-02-16T01:59:34.023</ModifiedDate> + <ID>424</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>publication_default</CustomerKey> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>0</ID> + <ObjectID xsi:nil="true" /> + </ParentFolder> + <Name>Publication Lists</Name> + <Description /> + <ContentType>publication</ContentType> + <IsActive>true</IsActive> + <IsEditable>false</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>9999999</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2017-02-16T01:59:32.323</CreatedDate> + <ModifiedDate>2017-02-16T01:59:32.323</ModifiedDate> + <ID>419</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>suppression_list_default</CustomerKey> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>0</ID> + <ObjectID xsi:nil="true" /> + </ParentFolder> + <Name>Suppression Lists</Name> + <Description /> + <ContentType>suppression_list</ContentType> + <IsActive>true</IsActive> + <IsEditable>false</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>9999999</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2017-02-16T01:59:32.323</CreatedDate> + <ModifiedDate>2017-02-16T01:59:32.323</ModifiedDate> + <ID>6298</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>journey_default</CustomerKey> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>0</ID> + <ObjectID xsi:nil="true" /> + </ParentFolder> + <Name>my journeys</Name> + <Description>The root folder for Journeys</Description> + <ContentType>journey</ContentType> + <IsActive>true</IsActive> + <IsEditable>false</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>9999999</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2019-10-25T05:35:17.337</CreatedDate> + <ModifiedDate>2019-10-25T05:35:17.337</ModifiedDate> + <ID>290937</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey /> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>0</ID> + <ObjectID xsi:nil="true" /> + </ParentFolder> + <Name>my automations</Name> + <Description /> + <ContentType>automations</ContentType> + <IsActive>true</IsActive> + <IsEditable>true</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>9999999</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2017-02-08T10:19:37.123</CreatedDate> + <ModifiedDate>2017-02-08T10:19:37.123</ModifiedDate> + <ID>386</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey /> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>2</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>dataextension_default</CustomerKey> + </ParentFolder> + <Name>Einstein</Name> + <Description /> + <ContentType>dataextension</ContentType> + <IsActive>true</IsActive> + <IsEditable>true</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>9999999</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2016-07-22T11:52:35.687</CreatedDate> + <ModifiedDate>2016-07-22T11:52:35.687</ModifiedDate> + <ID>89397</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey /> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>0</ID> + <ObjectID xsi:nil="true" /> + </ParentFolder> + <Name>Content Builder</Name> + <Description>The root folder for assets</Description> + <ContentType>asset</ContentType> + <IsActive>true</IsActive> + <IsEditable>false</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>9999999</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2016-07-29T12:13:07.7</CreatedDate> + <ModifiedDate>2021-12-16T02:56:14.68</ModifiedDate> + <ID>90888</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey /> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>89397</ID> + <ObjectID xsi:nil="true" /> + </ParentFolder> + <Name>Test Folder</Name> + <Description /> + <ContentType>asset</ContentType> + <IsActive>true</IsActive> + <IsEditable>true</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>9999999</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2016-07-22T11:52:19.28</CreatedDate> + <ModifiedDate>2016-07-22T11:52:19.28</ModifiedDate> + <ID>89348</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>triggered_send_default</CustomerKey> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>0</ID> + <ObjectID xsi:nil="true" /> + </ParentFolder> + <Name>Triggered Sends</Name> + <Description /> + <ContentType>triggered_send</ContentType> + <IsActive>true</IsActive> + <IsEditable>false</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>9999999</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2016-07-22T11:52:34.983</CreatedDate> + <ModifiedDate>2016-07-22T11:52:34.983</ModifiedDate> + <ID>89396</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>triggered_send_journeybuilder</CustomerKey> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>0</ID> + <ObjectID xsi:nil="true" /> + </ParentFolder> + <Name>Journey Builder Sends</Name> + <Description /> + <ContentType>triggered_send_journeybuilder</ContentType> + <IsActive>true</IsActive> + <IsEditable>false</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>9999999</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2016-07-29T12:13:27.28</CreatedDate> + <ModifiedDate>2016-07-29T12:13:27.28</ModifiedDate> + <ID>90889</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>HiddenCategory_default</CustomerKey> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>0</ID> + <ObjectID xsi:nil="true" /> + </ParentFolder> + <Name>HiddenCategory</Name> + <Description>Hidden folder to store Hidden items</Description> + <ContentType>Hidden</ContentType> + <IsActive>true</IsActive> + <IsEditable>false</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>9999999</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2016-08-25T10:04:09.12</CreatedDate> + <ModifiedDate>2016-08-25T10:04:09.12</ModifiedDate> + <ID>94030</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey /> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>89396</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>triggered_send_journeybuilder</CustomerKey> + </ParentFolder> + <Name>Satisfaction Score Survey</Name> + <Description /> + <ContentType>triggered_send_journeybuilder</ContentType> + <IsActive>true</IsActive> + <IsEditable>true</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>9999999</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2016-08-25T10:04:09.133</CreatedDate> + <ModifiedDate>2016-08-25T10:04:09.133</ModifiedDate> + <ID>94031</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey /> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>94030</ID> + <ObjectID xsi:nil="true" /> + </ParentFolder> + <Name>Version 1</Name> + <Description /> + <ContentType>triggered_send_journeybuilder</ContentType> + <IsActive>true</IsActive> + <IsEditable>true</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>9999999</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2021-06-09T10:17:06.27</CreatedDate> + <ModifiedDate>2021-06-09T10:17:06.27</ModifiedDate> + <ID>664654</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>6aa28490-6577-4cb2-8eac-fd5e4f983cae</CustomerKey> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>317169</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>HiddenJourneyBuilderTriggeredSends_d</CustomerKey> + </ParentFolder> + <Name>6aa28490-6577-4cb2-8eac-fd5e4f983cae_V9</Name> + <Description>triggered_send folder to store triggered_send items</Description> + <ContentType>triggered_send</ContentType> + <IsActive>true</IsActive> + <IsEditable>true</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>9999999</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2022-07-31T19:55:31.657</CreatedDate> + <ModifiedDate>2022-07-31T19:55:31.657</ModifiedDate> + <ID>742869</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>77211381-9967-4472-bd12-f58d4d5952a1</CustomerKey> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>317169</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>HiddenJourneyBuilderTriggeredSends_d</CustomerKey> + </ParentFolder> + <Name>77211381-9967-4472-bd12-f58d4d5952a1_V1</Name> + <Description>triggered_send folder to store triggered_send items</Description> + <ContentType>triggered_send</ContentType> + <IsActive>true</IsActive> + <IsEditable>true</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>9999999</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2022-07-31T19:56:51.297</CreatedDate> + <ModifiedDate>2022-07-31T19:56:51.297</ModifiedDate> + <ID>742871</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>HiddenJourneyBuilderSimulationTrigge</CustomerKey> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>90889</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>HiddenCategory_default</CustomerKey> + </ParentFolder> + <Name>HiddenJourneyBuilderSimulationTriggeredSends</Name> + <Description>triggered_send_journeybuilder folder to store triggered_send_journeybuilder items</Description> + <ContentType>triggered_send_journeybuilder</ContentType> + <IsActive>true</IsActive> + <IsEditable>true</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>9999999</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2023-03-08T10:26:55.787</CreatedDate> + <ModifiedDate>2023-03-08T10:26:55.787</ModifiedDate> + <ID>771879</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>8c24f428-4da8-4df6-97a7-beba5166c3c7</CustomerKey> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>317169</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>HiddenJourneyBuilderTriggeredSends_d</CustomerKey> + </ParentFolder> + <Name>8c24f428-4da8-4df6-97a7-beba5166c3c7_V1</Name> + <Description>triggered_send folder to store triggered_send items</Description> + <ContentType>triggered_send</ContentType> + <IsActive>true</IsActive> + <IsEditable>true</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>9999999</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2023-04-10T15:46:09.947</CreatedDate> + <ModifiedDate>2023-04-10T15:46:09.947</ModifiedDate> + <ID>776623</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>0a85b483-4208-4377-87fb-25794f5df244</CustomerKey> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>317169</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>HiddenJourneyBuilderTriggeredSends_d</CustomerKey> + </ParentFolder> + <Name>0a85b483-4208-4377-87fb-25794f5df244_V1</Name> + <Description>triggered_send folder to store triggered_send items</Description> + <ContentType>triggered_send</ContentType> + <IsActive>true</IsActive> + <IsEditable>true</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>9999999</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2020-03-06T07:57:37.633</CreatedDate> + <ModifiedDate>2020-03-06T07:57:37.633</ModifiedDate> + <ID>317169</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>HiddenJourneyBuilderTriggeredSends_d</CustomerKey> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>90889</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>HiddenCategory_default</CustomerKey> + </ParentFolder> + <Name>HiddenJourneyBuilderTriggeredSends</Name> + <Description>triggered_send folder to store triggered_send items</Description> + <ContentType>triggered_send</ContentType> + <IsActive>true</IsActive> + <IsEditable>true</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>9999999</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2024-02-16T10:12:15.9</CreatedDate> + <ModifiedDate>2024-02-16T10:12:15.9</ModifiedDate> + <ID>14914</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey /> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>0</ID> + <ObjectID xsi:nil="true" /> + </ParentFolder> + <Name>CloudPages</Name> + <Description>The root folder for CloudPages</Description> + <ContentType>cloudpages</ContentType> + <IsActive>true</IsActive> + <IsEditable>false</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>510007949</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2025-03-25T03:00:33.163</CreatedDate> + <ModifiedDate>2025-03-26T03:33:00.893</ModifiedDate> + <ID>27675</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>958bac7c-972b-4cac-aa8a-22a2b77b0fbc</CustomerKey> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>14914</ID> + <ObjectID xsi:nil="true" /> + </ParentFolder> + <Name>mcdev</Name> + <Description /> + <ContentType>cloudpages</ContentType> + <IsActive>true</IsActive> + <IsEditable>true</IsEditable> + <AllowChildren>false</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>9999999</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2022-06-21T09:34:31.84</CreatedDate> + <ModifiedDate>2022-06-21T09:34:31.84</ModifiedDate> + <ID>5319</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>filteractivity_default</CustomerKey> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>0</ID> + <ObjectID xsi:nil="true" /> + </ParentFolder> + <Name>Filter</Name> + <Description /> + <ContentType>filteractivity</ContentType> + <IsActive>true</IsActive> + <IsEditable>false</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>9999999</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2022-06-21T09:34:39.98</CreatedDate> + <ModifiedDate>2022-06-21T09:34:39.98</ModifiedDate> + <ID>90889</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>HiddenCategory_default</CustomerKey> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>0</ID> + <ObjectID xsi:nil="true" /> + </ParentFolder> + <Name>HiddenCategory</Name> + <Description>Hidden folder to store Hidden items</Description> + <ContentType>Hidden</ContentType> + <IsActive>true</IsActive> + <IsEditable>false</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>9999999</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2023-02-03T07:22:55.39</CreatedDate> + <ModifiedDate>2023-02-03T07:22:55.39</ModifiedDate> + <ID>8504</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>SystemHiddenFilterActivities_default</CustomerKey> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>90889</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>HiddenCategory_default</CustomerKey> + </ParentFolder> + <Name>SystemHiddenFilterActivities</Name> + <Description>filteractivity folder to store filteractivity items</Description> + <ContentType>filteractivity</ContentType> + <IsActive>true</IsActive> + <IsEditable>true</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>9999999</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2023-02-03T07:22:55.39</CreatedDate> + <ModifiedDate>2023-02-03T07:22:55.39</ModifiedDate> + <ID>8505</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>SystemHiddenFilterActivitiesForGE_de</CustomerKey> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>8504</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>SystemHiddenFilterActivities_default</CustomerKey> + </ParentFolder> + <Name>SystemHiddenFilterActivitiesForGE</Name> + <Description>filteractivity folder to store filteractivity items</Description> + <ContentType>filteractivity</ContentType> + <IsActive>true</IsActive> + <IsEditable>true</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>9999999</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2026-01-27T06:57:18.513</CreatedDate> + <ModifiedDate>2026-01-27T06:57:18.513</ModifiedDate> + <ID>37139</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey /> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>5319</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>filteractivity_default</CustomerKey> + </ParentFolder> + <Name>filterSubfolder</Name> + <Description>doesnt have a CustomerKey for some reason</Description> + <ContentType>filteractivity</ContentType> + <IsActive>true</IsActive> + <IsEditable>true</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>9999999</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2022-06-21T09:34:31.823</CreatedDate> + <ModifiedDate>2022-06-21T09:34:31.823</ModifiedDate> + <ID>5318</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>filterdefinition_default</CustomerKey> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>0</ID> + <ObjectID xsi:nil="true" /> + </ParentFolder> + <Name>Data Filters</Name> + <Description /> + <ContentType>filterdefinition</ContentType> + <IsActive>true</IsActive> + <IsEditable>false</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>9999999</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2022-06-21T09:34:39.98</CreatedDate> + <ModifiedDate>2022-06-21T09:34:39.98</ModifiedDate> + <ID>90889</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>HiddenCategory_default</CustomerKey> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>0</ID> + <ObjectID xsi:nil="true" /> + </ParentFolder> + <Name>HiddenCategory</Name> + <Description>Hidden folder to store Hidden items</Description> + <ContentType>Hidden</ContentType> + <IsActive>true</IsActive> + <IsEditable>false</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>9999999</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2023-02-03T07:22:55.39</CreatedDate> + <ModifiedDate>2023-02-03T07:22:55.39</ModifiedDate> + <ID>8502</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>SystemHiddenDataFilters_default</CustomerKey> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>90889</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>HiddenCategory_default</CustomerKey> + </ParentFolder> + <Name>SystemHiddenDataFilters</Name> + <Description>filterdefinition folder to store filterdefinition items</Description> + <ContentType>filterdefinition</ContentType> + <IsActive>true</IsActive> + <IsEditable>true</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>9999999</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2023-02-03T07:22:55.39</CreatedDate> + <ModifiedDate>2023-02-03T07:22:55.39</ModifiedDate> + <ID>8503</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>SystemHiddenDataFiltersForGE_default</CustomerKey> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>8502</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>SystemHiddenDataFilters_default</CustomerKey> + </ParentFolder> + <Name>SystemHiddenDataFiltersForGE</Name> + <Description>filterdefinition folder to store filterdefinition items</Description> + <ContentType>filterdefinition</ContentType> + <IsActive>true</IsActive> + <IsEditable>true</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + </RetrieveResponseMsg> + </soap:Body> +</soap:Envelope> diff --git a/test/resources/9999999/dataFolder/retrieve-ContentTypeINasset,asset-sha,automatio,cloudpage,dataexten,hidden,journey,list,mysubs,publicati,queryacti,salesforc,shared_da,shared_da,shared_sa,ssjsactiv,synchroni,triggered,triggered,useriniti-response.xml b/test/resources/9999999/dataFolder/retrieve-ContentTypeINasset,asset-sha,automatio,cloudpage,dataexten,hidden,journey,list,mysubs,publicati,queryacti,salesforc,shared_da,shared_da,shared_sa,ssjsactiv,synchroni,triggered,triggered,useriniti-response.xml new file mode 100644 index 000000000..21d37d825 --- /dev/null +++ b/test/resources/9999999/dataFolder/retrieve-ContentTypeINasset,asset-sha,automatio,cloudpage,dataexten,hidden,journey,list,mysubs,publicati,queryacti,salesforc,shared_da,shared_da,shared_sa,ssjsactiv,synchroni,triggered,triggered,useriniti-response.xml @@ -0,0 +1,562 @@ +<?xml version="1.0" encoding="utf-8"?> +<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:xsd="http://www.w3.org/2001/XMLSchema" + xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing" + xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" + xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"> + <soap:Header> + <wsa:Action>RetrieveResponse</wsa:Action> + <wsa:MessageID>urn:uuid:f36f3303-3b5a-4641-8109-b26447634d91</wsa:MessageID> + <wsa:RelatesTo>urn:uuid:33983968-28c4-4379-bb5f-f80ae32eb988</wsa:RelatesTo> + <wsa:To>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</wsa:To> + <wsse:Security> + <wsu:Timestamp wsu:Id="Timestamp-32ecc81b-6020-473c-9e99-4b5338921220"> + <wsu:Created>2022-04-19T20:03:41Z</wsu:Created> + <wsu:Expires>2022-04-19T20:08:41Z</wsu:Expires> + </wsu:Timestamp> + </wsse:Security> + </soap:Header> + <soap:Body> + <RetrieveResponseMsg xmlns="http://exacttarget.com/wsdl/partnerAPI"> + <OverallStatus>OK</OverallStatus> + <RequestID>02cd5ccb-8f84-4651-826f-71169eeecf05</RequestID> + <Results xsi:type="DataFolder"> + <Client> + <ID>9999999</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2016-07-22T11:52:19.6</CreatedDate> + <ModifiedDate>2016-07-22T11:52:19.6</ModifiedDate> + <ID>2</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>dataextension_default</CustomerKey> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>0</ID> + <ObjectID xsi:nil="true" /> + </ParentFolder> + <Name>Data Extensions</Name> + <Description /> + <ContentType>dataextension</ContentType> + <IsActive>true</IsActive> + <IsEditable>false</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>9999999</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2016-07-22T11:52:20.407</CreatedDate> + <ModifiedDate>2016-07-22T11:52:20.407</ModifiedDate> + <ID>999</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>queryactivity_default</CustomerKey> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>0</ID> + <ObjectID xsi:nil="true" /> + </ParentFolder> + <Name>Query</Name> + <Description /> + <ContentType>queryactivity</ContentType> + <IsActive>true</IsActive> + <IsEditable>false</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>9999999</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2017-02-16T01:59:27.18</CreatedDate> + <ModifiedDate>2017-02-16T01:59:27.18</ModifiedDate> + <ID>412</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>mysubs_default</CustomerKey> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>0</ID> + <ObjectID xsi:nil="true" /> + </ParentFolder> + <Name>my subscribers</Name> + <Description /> + <ContentType>mysubs</ContentType> + <IsActive>true</IsActive> + <IsEditable>false</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>9999999</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2017-02-16T01:59:27.177</CreatedDate> + <ModifiedDate>2017-02-16T01:59:27.177</ModifiedDate> + <ID>404</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>list_default</CustomerKey> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>0</ID> + <ObjectID xsi:nil="true" /> + </ParentFolder> + <Name>my lists</Name> + <Description /> + <ContentType>list</ContentType> + <IsActive>true</IsActive> + <IsEditable>false</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>9999999</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2017-02-16T01:59:34.023</CreatedDate> + <ModifiedDate>2017-02-16T01:59:34.023</ModifiedDate> + <ID>424</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>publication_default</CustomerKey> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>0</ID> + <ObjectID xsi:nil="true" /> + </ParentFolder> + <Name>Publication Lists</Name> + <Description /> + <ContentType>publication</ContentType> + <IsActive>true</IsActive> + <IsEditable>false</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>9999999</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2017-02-16T01:59:32.323</CreatedDate> + <ModifiedDate>2017-02-16T01:59:32.323</ModifiedDate> + <ID>419</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>suppression_list_default</CustomerKey> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>0</ID> + <ObjectID xsi:nil="true" /> + </ParentFolder> + <Name>Suppression Lists</Name> + <Description /> + <ContentType>suppression_list</ContentType> + <IsActive>true</IsActive> + <IsEditable>false</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>9999999</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2017-02-16T01:59:32.323</CreatedDate> + <ModifiedDate>2017-02-16T01:59:32.323</ModifiedDate> + <ID>6298</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>journey_default</CustomerKey> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>0</ID> + <ObjectID xsi:nil="true" /> + </ParentFolder> + <Name>my journeys</Name> + <Description>The root folder for Journeys</Description> + <ContentType>journey</ContentType> + <IsActive>true</IsActive> + <IsEditable>false</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>9999999</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2019-10-25T05:35:17.337</CreatedDate> + <ModifiedDate>2019-10-25T05:35:17.337</ModifiedDate> + <ID>290937</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey /> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>0</ID> + <ObjectID xsi:nil="true" /> + </ParentFolder> + <Name>my automations</Name> + <Description /> + <ContentType>automations</ContentType> + <IsActive>true</IsActive> + <IsEditable>true</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>9999999</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2017-02-08T10:19:37.123</CreatedDate> + <ModifiedDate>2017-02-08T10:19:37.123</ModifiedDate> + <ID>386</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey /> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>2</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>dataextension_default</CustomerKey> + </ParentFolder> + <Name>Einstein</Name> + <Description /> + <ContentType>dataextension</ContentType> + <IsActive>true</IsActive> + <IsEditable>true</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>9999999</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2016-07-22T11:52:35.687</CreatedDate> + <ModifiedDate>2016-07-22T11:52:35.687</ModifiedDate> + <ID>89397</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey /> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>0</ID> + <ObjectID xsi:nil="true" /> + </ParentFolder> + <Name>Content Builder</Name> + <Description>The root folder for assets</Description> + <ContentType>asset</ContentType> + <IsActive>true</IsActive> + <IsEditable>false</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>9999999</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2016-07-29T12:13:07.7</CreatedDate> + <ModifiedDate>2021-12-16T02:56:14.68</ModifiedDate> + <ID>90888</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey /> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>89397</ID> + <ObjectID xsi:nil="true" /> + </ParentFolder> + <Name>Test Folder</Name> + <Description /> + <ContentType>asset</ContentType> + <IsActive>true</IsActive> + <IsEditable>true</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>9999999</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2016-07-22T11:52:19.28</CreatedDate> + <ModifiedDate>2016-07-22T11:52:19.28</ModifiedDate> + <ID>89348</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>triggered_send_default</CustomerKey> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>0</ID> + <ObjectID xsi:nil="true" /> + </ParentFolder> + <Name>Triggered Sends</Name> + <Description /> + <ContentType>triggered_send</ContentType> + <IsActive>true</IsActive> + <IsEditable>false</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>9999999</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2016-07-22T11:52:34.983</CreatedDate> + <ModifiedDate>2016-07-22T11:52:34.983</ModifiedDate> + <ID>89396</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>triggered_send_journeybuilder</CustomerKey> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>0</ID> + <ObjectID xsi:nil="true" /> + </ParentFolder> + <Name>Journey Builder Sends</Name> + <Description /> + <ContentType>triggered_send_journeybuilder</ContentType> + <IsActive>true</IsActive> + <IsEditable>false</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>9999999</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2016-07-29T12:13:27.28</CreatedDate> + <ModifiedDate>2016-07-29T12:13:27.28</ModifiedDate> + <ID>90889</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>HiddenCategory_default</CustomerKey> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>0</ID> + <ObjectID xsi:nil="true" /> + </ParentFolder> + <Name>HiddenCategory</Name> + <Description>Hidden folder to store Hidden items</Description> + <ContentType>Hidden</ContentType> + <IsActive>true</IsActive> + <IsEditable>false</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>9999999</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2016-08-25T10:04:09.12</CreatedDate> + <ModifiedDate>2016-08-25T10:04:09.12</ModifiedDate> + <ID>94030</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey /> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>89396</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>triggered_send_journeybuilder</CustomerKey> + </ParentFolder> + <Name>Satisfaction Score Survey</Name> + <Description /> + <ContentType>triggered_send_journeybuilder</ContentType> + <IsActive>true</IsActive> + <IsEditable>true</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>9999999</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2016-08-25T10:04:09.133</CreatedDate> + <ModifiedDate>2016-08-25T10:04:09.133</ModifiedDate> + <ID>94031</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey /> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>94030</ID> + <ObjectID xsi:nil="true" /> + </ParentFolder> + <Name>Version 1</Name> + <Description /> + <ContentType>triggered_send_journeybuilder</ContentType> + <IsActive>true</IsActive> + <IsEditable>true</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>9999999</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2021-06-09T10:17:06.27</CreatedDate> + <ModifiedDate>2021-06-09T10:17:06.27</ModifiedDate> + <ID>664654</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>6aa28490-6577-4cb2-8eac-fd5e4f983cae</CustomerKey> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>317169</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>HiddenJourneyBuilderTriggeredSends_d</CustomerKey> + </ParentFolder> + <Name>6aa28490-6577-4cb2-8eac-fd5e4f983cae_V9</Name> + <Description>triggered_send folder to store triggered_send items</Description> + <ContentType>triggered_send</ContentType> + <IsActive>true</IsActive> + <IsEditable>true</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>9999999</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2022-07-31T19:55:31.657</CreatedDate> + <ModifiedDate>2022-07-31T19:55:31.657</ModifiedDate> + <ID>742869</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>77211381-9967-4472-bd12-f58d4d5952a1</CustomerKey> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>317169</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>HiddenJourneyBuilderTriggeredSends_d</CustomerKey> + </ParentFolder> + <Name>77211381-9967-4472-bd12-f58d4d5952a1_V1</Name> + <Description>triggered_send folder to store triggered_send items</Description> + <ContentType>triggered_send</ContentType> + <IsActive>true</IsActive> + <IsEditable>true</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>9999999</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2022-07-31T19:56:51.297</CreatedDate> + <ModifiedDate>2022-07-31T19:56:51.297</ModifiedDate> + <ID>742871</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>HiddenJourneyBuilderSimulationTrigge</CustomerKey> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>90889</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>HiddenCategory_default</CustomerKey> + </ParentFolder> + <Name>HiddenJourneyBuilderSimulationTriggeredSends</Name> + <Description>triggered_send_journeybuilder folder to store triggered_send_journeybuilder items</Description> + <ContentType>triggered_send_journeybuilder</ContentType> + <IsActive>true</IsActive> + <IsEditable>true</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>9999999</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2023-03-08T10:26:55.787</CreatedDate> + <ModifiedDate>2023-03-08T10:26:55.787</ModifiedDate> + <ID>771879</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>8c24f428-4da8-4df6-97a7-beba5166c3c7</CustomerKey> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>317169</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>HiddenJourneyBuilderTriggeredSends_d</CustomerKey> + </ParentFolder> + <Name>8c24f428-4da8-4df6-97a7-beba5166c3c7_V1</Name> + <Description>triggered_send folder to store triggered_send items</Description> + <ContentType>triggered_send</ContentType> + <IsActive>true</IsActive> + <IsEditable>true</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>9999999</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2023-04-10T15:46:09.947</CreatedDate> + <ModifiedDate>2023-04-10T15:46:09.947</ModifiedDate> + <ID>776623</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>0a85b483-4208-4377-87fb-25794f5df244</CustomerKey> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>317169</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>HiddenJourneyBuilderTriggeredSends_d</CustomerKey> + </ParentFolder> + <Name>0a85b483-4208-4377-87fb-25794f5df244_V1</Name> + <Description>triggered_send folder to store triggered_send items</Description> + <ContentType>triggered_send</ContentType> + <IsActive>true</IsActive> + <IsEditable>true</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>9999999</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2020-03-06T07:57:37.633</CreatedDate> + <ModifiedDate>2020-03-06T07:57:37.633</ModifiedDate> + <ID>317169</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>HiddenJourneyBuilderTriggeredSends_d</CustomerKey> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>90889</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>HiddenCategory_default</CustomerKey> + </ParentFolder> + <Name>HiddenJourneyBuilderTriggeredSends</Name> + <Description>triggered_send folder to store triggered_send items</Description> + <ContentType>triggered_send</ContentType> + <IsActive>true</IsActive> + <IsEditable>true</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>9999999</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2024-02-16T10:12:15.9</CreatedDate> + <ModifiedDate>2024-02-16T10:12:15.9</ModifiedDate> + <ID>14914</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey /> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>0</ID> + <ObjectID xsi:nil="true" /> + </ParentFolder> + <Name>CloudPages</Name> + <Description>The root folder for CloudPages</Description> + <ContentType>cloudpages</ContentType> + <IsActive>true</IsActive> + <IsEditable>false</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>510007949</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2025-03-25T03:00:33.163</CreatedDate> + <ModifiedDate>2025-03-26T03:33:00.893</ModifiedDate> + <ID>27675</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>958bac7c-972b-4cac-aa8a-22a2b77b0fbc</CustomerKey> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>14914</ID> + <ObjectID xsi:nil="true" /> + </ParentFolder> + <Name>mcdev</Name> + <Description /> + <ContentType>cloudpages</ContentType> + <IsActive>true</IsActive> + <IsEditable>true</IsEditable> + <AllowChildren>false</AllowChildren> + </Results> + </RetrieveResponseMsg> + </soap:Body> +</soap:Envelope> diff --git a/test/resources/9999999/dataFolder/retrieve-ContentTypeINasset,asset-sha,automatio,cloudpage,dataexten,hidden,journey,list,mysubs,publicati,queryacti,salesforc,shared_da,shared_da,shared_sa,ssjsactiv,synchroni,useriniti-response.xml b/test/resources/9999999/dataFolder/retrieve-ContentTypeINasset,asset-sha,automatio,cloudpage,dataexten,hidden,journey,list,mysubs,publicati,queryacti,salesforc,shared_da,shared_da,shared_sa,ssjsactiv,synchroni,useriniti-response.xml new file mode 100644 index 000000000..a12116901 --- /dev/null +++ b/test/resources/9999999/dataFolder/retrieve-ContentTypeINasset,asset-sha,automatio,cloudpage,dataexten,hidden,journey,list,mysubs,publicati,queryacti,salesforc,shared_da,shared_da,shared_sa,ssjsactiv,synchroni,useriniti-response.xml @@ -0,0 +1,335 @@ +<?xml version="1.0" encoding="utf-8"?> +<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:xsd="http://www.w3.org/2001/XMLSchema" + xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing" + xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" + xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"> + <soap:Header> + <wsa:Action>RetrieveResponse</wsa:Action> + <wsa:MessageID>urn:uuid:f36f3303-3b5a-4641-8109-b26447634d91</wsa:MessageID> + <wsa:RelatesTo>urn:uuid:33983968-28c4-4379-bb5f-f80ae32eb988</wsa:RelatesTo> + <wsa:To>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</wsa:To> + <wsse:Security> + <wsu:Timestamp wsu:Id="Timestamp-32ecc81b-6020-473c-9e99-4b5338921220"> + <wsu:Created>2022-04-19T20:03:41Z</wsu:Created> + <wsu:Expires>2022-04-19T20:08:41Z</wsu:Expires> + </wsu:Timestamp> + </wsse:Security> + </soap:Header> + <soap:Body> + <RetrieveResponseMsg xmlns="http://exacttarget.com/wsdl/partnerAPI"> + <OverallStatus>OK</OverallStatus> + <RequestID>02cd5ccb-8f84-4651-826f-71169eeecf05</RequestID> + <Results xsi:type="DataFolder"> + <Client> + <ID>9999999</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2016-07-22T11:52:19.6</CreatedDate> + <ModifiedDate>2016-07-22T11:52:19.6</ModifiedDate> + <ID>2</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>dataextension_default</CustomerKey> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>0</ID> + <ObjectID xsi:nil="true" /> + </ParentFolder> + <Name>Data Extensions</Name> + <Description /> + <ContentType>dataextension</ContentType> + <IsActive>true</IsActive> + <IsEditable>false</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>9999999</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2016-07-22T11:52:20.407</CreatedDate> + <ModifiedDate>2016-07-22T11:52:20.407</ModifiedDate> + <ID>999</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>queryactivity_default</CustomerKey> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>0</ID> + <ObjectID xsi:nil="true" /> + </ParentFolder> + <Name>Query</Name> + <Description /> + <ContentType>queryactivity</ContentType> + <IsActive>true</IsActive> + <IsEditable>false</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>9999999</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2017-02-16T01:59:27.18</CreatedDate> + <ModifiedDate>2017-02-16T01:59:27.18</ModifiedDate> + <ID>412</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>mysubs_default</CustomerKey> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>0</ID> + <ObjectID xsi:nil="true" /> + </ParentFolder> + <Name>my subscribers</Name> + <Description /> + <ContentType>mysubs</ContentType> + <IsActive>true</IsActive> + <IsEditable>false</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>9999999</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2017-02-16T01:59:27.177</CreatedDate> + <ModifiedDate>2017-02-16T01:59:27.177</ModifiedDate> + <ID>404</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>list_default</CustomerKey> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>0</ID> + <ObjectID xsi:nil="true" /> + </ParentFolder> + <Name>my lists</Name> + <Description /> + <ContentType>list</ContentType> + <IsActive>true</IsActive> + <IsEditable>false</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>9999999</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2017-02-16T01:59:34.023</CreatedDate> + <ModifiedDate>2017-02-16T01:59:34.023</ModifiedDate> + <ID>424</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>publication_default</CustomerKey> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>0</ID> + <ObjectID xsi:nil="true" /> + </ParentFolder> + <Name>Publication Lists</Name> + <Description /> + <ContentType>publication</ContentType> + <IsActive>true</IsActive> + <IsEditable>false</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>9999999</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2017-02-16T01:59:32.323</CreatedDate> + <ModifiedDate>2017-02-16T01:59:32.323</ModifiedDate> + <ID>419</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>suppression_list_default</CustomerKey> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>0</ID> + <ObjectID xsi:nil="true" /> + </ParentFolder> + <Name>Suppression Lists</Name> + <Description /> + <ContentType>suppression_list</ContentType> + <IsActive>true</IsActive> + <IsEditable>false</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>9999999</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2017-02-16T01:59:32.323</CreatedDate> + <ModifiedDate>2017-02-16T01:59:32.323</ModifiedDate> + <ID>6298</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>journey_default</CustomerKey> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>0</ID> + <ObjectID xsi:nil="true" /> + </ParentFolder> + <Name>my journeys</Name> + <Description>The root folder for Journeys</Description> + <ContentType>journey</ContentType> + <IsActive>true</IsActive> + <IsEditable>false</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>9999999</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2019-10-25T05:35:17.337</CreatedDate> + <ModifiedDate>2019-10-25T05:35:17.337</ModifiedDate> + <ID>290937</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey /> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>0</ID> + <ObjectID xsi:nil="true" /> + </ParentFolder> + <Name>my automations</Name> + <Description /> + <ContentType>automations</ContentType> + <IsActive>true</IsActive> + <IsEditable>true</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>9999999</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2017-02-08T10:19:37.123</CreatedDate> + <ModifiedDate>2017-02-08T10:19:37.123</ModifiedDate> + <ID>386</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey /> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>2</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>dataextension_default</CustomerKey> + </ParentFolder> + <Name>Einstein</Name> + <Description /> + <ContentType>dataextension</ContentType> + <IsActive>true</IsActive> + <IsEditable>true</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>9999999</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2016-07-22T11:52:35.687</CreatedDate> + <ModifiedDate>2016-07-22T11:52:35.687</ModifiedDate> + <ID>89397</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey /> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>0</ID> + <ObjectID xsi:nil="true" /> + </ParentFolder> + <Name>Content Builder</Name> + <Description>The root folder for assets</Description> + <ContentType>asset</ContentType> + <IsActive>true</IsActive> + <IsEditable>false</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>9999999</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2016-07-29T12:13:07.7</CreatedDate> + <ModifiedDate>2021-12-16T02:56:14.68</ModifiedDate> + <ID>90888</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey /> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>89397</ID> + <ObjectID xsi:nil="true" /> + </ParentFolder> + <Name>Test Folder</Name> + <Description /> + <ContentType>asset</ContentType> + <IsActive>true</IsActive> + <IsEditable>true</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>9999999</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2016-07-29T12:13:27.28</CreatedDate> + <ModifiedDate>2016-07-29T12:13:27.28</ModifiedDate> + <ID>90889</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>HiddenCategory_default</CustomerKey> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>0</ID> + <ObjectID xsi:nil="true" /> + </ParentFolder> + <Name>HiddenCategory</Name> + <Description>Hidden folder to store Hidden items</Description> + <ContentType>Hidden</ContentType> + <IsActive>true</IsActive> + <IsEditable>false</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>9999999</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2024-02-16T10:12:15.9</CreatedDate> + <ModifiedDate>2024-02-16T10:12:15.9</ModifiedDate> + <ID>14914</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey /> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>0</ID> + <ObjectID xsi:nil="true" /> + </ParentFolder> + <Name>CloudPages</Name> + <Description>The root folder for CloudPages</Description> + <ContentType>cloudpages</ContentType> + <IsActive>true</IsActive> + <IsEditable>false</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>510007949</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2025-03-25T03:00:33.163</CreatedDate> + <ModifiedDate>2025-03-26T03:33:00.893</ModifiedDate> + <ID>27675</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>958bac7c-972b-4cac-aa8a-22a2b77b0fbc</CustomerKey> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>14914</ID> + <ObjectID xsi:nil="true" /> + </ParentFolder> + <Name>mcdev</Name> + <Description /> + <ContentType>cloudpages</ContentType> + <IsActive>true</IsActive> + <IsEditable>true</IsEditable> + <AllowChildren>false</AllowChildren> + </Results> + </RetrieveResponseMsg> + </soap:Body> +</soap:Envelope> diff --git a/test/resources/9999999/dataFolder/retrieve-ContentTypeINasset,asset-sha,dataexten,salesforc,shared_da,shared_da,shared_sa,synchroni,automatio,useriniti,journey,mysubs,list,publicati,queryacti,ssjsactiv,triggered,triggered-response.xml b/test/resources/9999999/dataFolder/retrieve-ContentTypeINasset,asset-sha,dataexten,salesforc,shared_da,shared_da,shared_sa,synchroni,automatio,useriniti,journey,mysubs,list,publicati,queryacti,ssjsactiv,triggered,triggered-response.xml new file mode 100644 index 000000000..5b28f9747 --- /dev/null +++ b/test/resources/9999999/dataFolder/retrieve-ContentTypeINasset,asset-sha,dataexten,salesforc,shared_da,shared_da,shared_sa,synchroni,automatio,useriniti,journey,mysubs,list,publicati,queryacti,ssjsactiv,triggered,triggered-response.xml @@ -0,0 +1,519 @@ +<?xml version="1.0" encoding="utf-8"?> +<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:xsd="http://www.w3.org/2001/XMLSchema" + xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing" + xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" + xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"> + <soap:Header> + <wsa:Action>RetrieveResponse</wsa:Action> + <wsa:MessageID>urn:uuid:f36f3303-3b5a-4641-8109-b26447634d91</wsa:MessageID> + <wsa:RelatesTo>urn:uuid:33983968-28c4-4379-bb5f-f80ae32eb988</wsa:RelatesTo> + <wsa:To>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</wsa:To> + <wsse:Security> + <wsu:Timestamp wsu:Id="Timestamp-32ecc81b-6020-473c-9e99-4b5338921220"> + <wsu:Created>2022-04-19T20:03:41Z</wsu:Created> + <wsu:Expires>2022-04-19T20:08:41Z</wsu:Expires> + </wsu:Timestamp> + </wsse:Security> + </soap:Header> + <soap:Body> + <RetrieveResponseMsg xmlns="http://exacttarget.com/wsdl/partnerAPI"> + <OverallStatus>OK</OverallStatus> + <RequestID>02cd5ccb-8f84-4651-826f-71169eeecf05</RequestID> + <Results xsi:type="DataFolder"> + <Client> + <ID>9999999</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2016-07-22T11:52:19.6</CreatedDate> + <ModifiedDate>2016-07-22T11:52:19.6</ModifiedDate> + <ID>2</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>dataextension_default</CustomerKey> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>0</ID> + <ObjectID xsi:nil="true" /> + </ParentFolder> + <Name>Data Extensions</Name> + <Description /> + <ContentType>dataextension</ContentType> + <IsActive>true</IsActive> + <IsEditable>false</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>9999999</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2016-07-22T11:52:20.407</CreatedDate> + <ModifiedDate>2016-07-22T11:52:20.407</ModifiedDate> + <ID>999</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>queryactivity_default</CustomerKey> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>0</ID> + <ObjectID xsi:nil="true" /> + </ParentFolder> + <Name>Query</Name> + <Description /> + <ContentType>queryactivity</ContentType> + <IsActive>true</IsActive> + <IsEditable>false</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>9999999</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2017-02-16T01:59:27.18</CreatedDate> + <ModifiedDate>2017-02-16T01:59:27.18</ModifiedDate> + <ID>412</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>mysubs_default</CustomerKey> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>0</ID> + <ObjectID xsi:nil="true" /> + </ParentFolder> + <Name>my subscribers</Name> + <Description /> + <ContentType>mysubs</ContentType> + <IsActive>true</IsActive> + <IsEditable>false</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>9999999</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2017-02-16T01:59:27.177</CreatedDate> + <ModifiedDate>2017-02-16T01:59:27.177</ModifiedDate> + <ID>404</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>list_default</CustomerKey> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>0</ID> + <ObjectID xsi:nil="true" /> + </ParentFolder> + <Name>my lists</Name> + <Description /> + <ContentType>list</ContentType> + <IsActive>true</IsActive> + <IsEditable>false</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>9999999</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2017-02-16T01:59:34.023</CreatedDate> + <ModifiedDate>2017-02-16T01:59:34.023</ModifiedDate> + <ID>424</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>publication_default</CustomerKey> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>0</ID> + <ObjectID xsi:nil="true" /> + </ParentFolder> + <Name>Publication Lists</Name> + <Description /> + <ContentType>publication</ContentType> + <IsActive>true</IsActive> + <IsEditable>false</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>9999999</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2017-02-16T01:59:32.323</CreatedDate> + <ModifiedDate>2017-02-16T01:59:32.323</ModifiedDate> + <ID>419</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>suppression_list_default</CustomerKey> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>0</ID> + <ObjectID xsi:nil="true" /> + </ParentFolder> + <Name>Suppression Lists</Name> + <Description /> + <ContentType>suppression_list</ContentType> + <IsActive>true</IsActive> + <IsEditable>false</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>9999999</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2017-02-16T01:59:32.323</CreatedDate> + <ModifiedDate>2017-02-16T01:59:32.323</ModifiedDate> + <ID>6298</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>journey_default</CustomerKey> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>0</ID> + <ObjectID xsi:nil="true" /> + </ParentFolder> + <Name>my journeys</Name> + <Description>The root folder for Journeys</Description> + <ContentType>journey</ContentType> + <IsActive>true</IsActive> + <IsEditable>false</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>9999999</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2019-10-25T05:35:17.337</CreatedDate> + <ModifiedDate>2019-10-25T05:35:17.337</ModifiedDate> + <ID>290937</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey /> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>0</ID> + <ObjectID xsi:nil="true" /> + </ParentFolder> + <Name>my automations</Name> + <Description /> + <ContentType>automations</ContentType> + <IsActive>true</IsActive> + <IsEditable>true</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>9999999</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2017-02-08T10:19:37.123</CreatedDate> + <ModifiedDate>2017-02-08T10:19:37.123</ModifiedDate> + <ID>386</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey /> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>2</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>dataextension_default</CustomerKey> + </ParentFolder> + <Name>Einstein</Name> + <Description /> + <ContentType>dataextension</ContentType> + <IsActive>true</IsActive> + <IsEditable>true</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>9999999</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2016-07-22T11:52:35.687</CreatedDate> + <ModifiedDate>2016-07-22T11:52:35.687</ModifiedDate> + <ID>89397</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey /> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>0</ID> + <ObjectID xsi:nil="true" /> + </ParentFolder> + <Name>Content Builder</Name> + <Description>The root folder for assets</Description> + <ContentType>asset</ContentType> + <IsActive>true</IsActive> + <IsEditable>false</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>9999999</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2016-07-29T12:13:07.7</CreatedDate> + <ModifiedDate>2021-12-16T02:56:14.68</ModifiedDate> + <ID>90888</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey /> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>89397</ID> + <ObjectID xsi:nil="true" /> + </ParentFolder> + <Name>Test Folder</Name> + <Description /> + <ContentType>asset</ContentType> + <IsActive>true</IsActive> + <IsEditable>true</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>9999999</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2016-07-22T11:52:19.28</CreatedDate> + <ModifiedDate>2016-07-22T11:52:19.28</ModifiedDate> + <ID>89348</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>triggered_send_default</CustomerKey> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>0</ID> + <ObjectID xsi:nil="true" /> + </ParentFolder> + <Name>Triggered Sends</Name> + <Description /> + <ContentType>triggered_send</ContentType> + <IsActive>true</IsActive> + <IsEditable>false</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>9999999</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2016-07-22T11:52:34.983</CreatedDate> + <ModifiedDate>2016-07-22T11:52:34.983</ModifiedDate> + <ID>89396</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>triggered_send_journeybuilder</CustomerKey> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>0</ID> + <ObjectID xsi:nil="true" /> + </ParentFolder> + <Name>Journey Builder Sends</Name> + <Description /> + <ContentType>triggered_send_journeybuilder</ContentType> + <IsActive>true</IsActive> + <IsEditable>false</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>9999999</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2016-07-29T12:13:27.28</CreatedDate> + <ModifiedDate>2016-07-29T12:13:27.28</ModifiedDate> + <ID>90889</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>HiddenCategory_default</CustomerKey> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>0</ID> + <ObjectID xsi:nil="true" /> + </ParentFolder> + <Name>HiddenCategory</Name> + <Description>Hidden folder to store Hidden items</Description> + <ContentType>Hidden</ContentType> + <IsActive>true</IsActive> + <IsEditable>false</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>9999999</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2016-08-25T10:04:09.12</CreatedDate> + <ModifiedDate>2016-08-25T10:04:09.12</ModifiedDate> + <ID>94030</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey /> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>89396</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>triggered_send_journeybuilder</CustomerKey> + </ParentFolder> + <Name>Satisfaction Score Survey</Name> + <Description /> + <ContentType>triggered_send_journeybuilder</ContentType> + <IsActive>true</IsActive> + <IsEditable>true</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>9999999</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2016-08-25T10:04:09.133</CreatedDate> + <ModifiedDate>2016-08-25T10:04:09.133</ModifiedDate> + <ID>94031</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey /> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>94030</ID> + <ObjectID xsi:nil="true" /> + </ParentFolder> + <Name>Version 1</Name> + <Description /> + <ContentType>triggered_send_journeybuilder</ContentType> + <IsActive>true</IsActive> + <IsEditable>true</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>9999999</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2021-06-09T10:17:06.27</CreatedDate> + <ModifiedDate>2021-06-09T10:17:06.27</ModifiedDate> + <ID>664654</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>6aa28490-6577-4cb2-8eac-fd5e4f983cae</CustomerKey> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>317169</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>HiddenJourneyBuilderTriggeredSends_d</CustomerKey> + </ParentFolder> + <Name>6aa28490-6577-4cb2-8eac-fd5e4f983cae_V9</Name> + <Description>triggered_send folder to store triggered_send items</Description> + <ContentType>triggered_send</ContentType> + <IsActive>true</IsActive> + <IsEditable>true</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>9999999</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2022-07-31T19:55:31.657</CreatedDate> + <ModifiedDate>2022-07-31T19:55:31.657</ModifiedDate> + <ID>742869</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>77211381-9967-4472-bd12-f58d4d5952a1</CustomerKey> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>317169</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>HiddenJourneyBuilderTriggeredSends_d</CustomerKey> + </ParentFolder> + <Name>77211381-9967-4472-bd12-f58d4d5952a1_V1</Name> + <Description>triggered_send folder to store triggered_send items</Description> + <ContentType>triggered_send</ContentType> + <IsActive>true</IsActive> + <IsEditable>true</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>9999999</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2022-07-31T19:56:51.297</CreatedDate> + <ModifiedDate>2022-07-31T19:56:51.297</ModifiedDate> + <ID>742871</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>HiddenJourneyBuilderSimulationTrigge</CustomerKey> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>90889</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>HiddenCategory_default</CustomerKey> + </ParentFolder> + <Name>HiddenJourneyBuilderSimulationTriggeredSends</Name> + <Description>triggered_send_journeybuilder folder to store triggered_send_journeybuilder items</Description> + <ContentType>triggered_send_journeybuilder</ContentType> + <IsActive>true</IsActive> + <IsEditable>true</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>9999999</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2023-03-08T10:26:55.787</CreatedDate> + <ModifiedDate>2023-03-08T10:26:55.787</ModifiedDate> + <ID>771879</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>8c24f428-4da8-4df6-97a7-beba5166c3c7</CustomerKey> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>317169</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>HiddenJourneyBuilderTriggeredSends_d</CustomerKey> + </ParentFolder> + <Name>8c24f428-4da8-4df6-97a7-beba5166c3c7_V1</Name> + <Description>triggered_send folder to store triggered_send items</Description> + <ContentType>triggered_send</ContentType> + <IsActive>true</IsActive> + <IsEditable>true</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>9999999</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2023-04-10T15:46:09.947</CreatedDate> + <ModifiedDate>2023-04-10T15:46:09.947</ModifiedDate> + <ID>776623</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>0a85b483-4208-4377-87fb-25794f5df244</CustomerKey> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>317169</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>HiddenJourneyBuilderTriggeredSends_d</CustomerKey> + </ParentFolder> + <Name>0a85b483-4208-4377-87fb-25794f5df244_V1</Name> + <Description>triggered_send folder to store triggered_send items</Description> + <ContentType>triggered_send</ContentType> + <IsActive>true</IsActive> + <IsEditable>true</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>9999999</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2020-03-06T07:57:37.633</CreatedDate> + <ModifiedDate>2020-03-06T07:57:37.633</ModifiedDate> + <ID>317169</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>HiddenJourneyBuilderTriggeredSends_d</CustomerKey> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>90889</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>HiddenCategory_default</CustomerKey> + </ParentFolder> + <Name>HiddenJourneyBuilderTriggeredSends</Name> + <Description>triggered_send folder to store triggered_send items</Description> + <ContentType>triggered_send</ContentType> + <IsActive>true</IsActive> + <IsEditable>true</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + + </RetrieveResponseMsg> + </soap:Body> +</soap:Envelope> diff --git a/test/resources/9999999/dataFolder/retrieve-ContentTypeINasset,asset-shared,cloudpages,dataextension,hidden,salesforcedataextension,shared_data,shared_dataextension,shared_salesforcedataextension,synchronizeddataextension-response.xml b/test/resources/9999999/dataFolder/retrieve-ContentTypeINasset,asset-shared,cloudpages,dataextension,hidden,salesforcedataextension,shared_data,shared_dataextension,shared_salesforcedataextension,synchronizeddataextension-response.xml new file mode 100644 index 000000000..a9d1f5207 --- /dev/null +++ b/test/resources/9999999/dataFolder/retrieve-ContentTypeINasset,asset-shared,cloudpages,dataextension,hidden,salesforcedataextension,shared_data,shared_dataextension,shared_salesforcedataextension,synchronizeddataextension-response.xml @@ -0,0 +1,181 @@ +<?xml version="1.0" encoding="utf-8"?> +<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:xsd="http://www.w3.org/2001/XMLSchema" + xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing" + xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" + xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"> + <soap:Header> + <wsa:Action>RetrieveResponse</wsa:Action> + <wsa:MessageID>urn:uuid:f36f3303-3b5a-4641-8109-b26447634d91</wsa:MessageID> + <wsa:RelatesTo>urn:uuid:33983968-28c4-4379-bb5f-f80ae32eb988</wsa:RelatesTo> + <wsa:To>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</wsa:To> + <wsse:Security> + <wsu:Timestamp wsu:Id="Timestamp-32ecc81b-6020-473c-9e99-4b5338921220"> + <wsu:Created>2022-04-19T20:03:41Z</wsu:Created> + <wsu:Expires>2022-04-19T20:08:41Z</wsu:Expires> + </wsu:Timestamp> + </wsse:Security> + </soap:Header> + <soap:Body> + <RetrieveResponseMsg xmlns="http://exacttarget.com/wsdl/partnerAPI"> + <OverallStatus>OK</OverallStatus> + <RequestID>02cd5ccb-8f84-4651-826f-71169eeecf05</RequestID> + <Results xsi:type="DataFolder"> + <Client> + <ID>9999999</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2016-07-22T11:52:19.6</CreatedDate> + <ModifiedDate>2016-07-22T11:52:19.6</ModifiedDate> + <ID>2</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>dataextension_default</CustomerKey> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>0</ID> + <ObjectID xsi:nil="true" /> + </ParentFolder> + <Name>Data Extensions</Name> + <Description /> + <ContentType>dataextension</ContentType> + <IsActive>true</IsActive> + <IsEditable>false</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>9999999</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2017-02-08T10:19:37.123</CreatedDate> + <ModifiedDate>2017-02-08T10:19:37.123</ModifiedDate> + <ID>386</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey /> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>2</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>dataextension_default</CustomerKey> + </ParentFolder> + <Name>Einstein</Name> + <Description /> + <ContentType>dataextension</ContentType> + <IsActive>true</IsActive> + <IsEditable>true</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>9999999</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2016-07-22T11:52:35.687</CreatedDate> + <ModifiedDate>2016-07-22T11:52:35.687</ModifiedDate> + <ID>89397</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey /> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>0</ID> + <ObjectID xsi:nil="true" /> + </ParentFolder> + <Name>Content Builder</Name> + <Description>The root folder for assets</Description> + <ContentType>asset</ContentType> + <IsActive>true</IsActive> + <IsEditable>false</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>9999999</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2016-07-29T12:13:07.7</CreatedDate> + <ModifiedDate>2021-12-16T02:56:14.68</ModifiedDate> + <ID>90888</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey /> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>89397</ID> + <ObjectID xsi:nil="true" /> + </ParentFolder> + <Name>Test Folder</Name> + <Description /> + <ContentType>asset</ContentType> + <IsActive>true</IsActive> + <IsEditable>true</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>9999999</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2016-07-29T12:13:27.28</CreatedDate> + <ModifiedDate>2016-07-29T12:13:27.28</ModifiedDate> + <ID>90889</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>HiddenCategory_default</CustomerKey> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>0</ID> + <ObjectID xsi:nil="true" /> + </ParentFolder> + <Name>HiddenCategory</Name> + <Description>Hidden folder to store Hidden items</Description> + <ContentType>Hidden</ContentType> + <IsActive>true</IsActive> + <IsEditable>false</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>9999999</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2024-02-16T10:12:15.9</CreatedDate> + <ModifiedDate>2024-02-16T10:12:15.9</ModifiedDate> + <ID>14914</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey /> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>0</ID> + <ObjectID xsi:nil="true" /> + </ParentFolder> + <Name>CloudPages</Name> + <Description>The root folder for CloudPages</Description> + <ContentType>cloudpages</ContentType> + <IsActive>true</IsActive> + <IsEditable>false</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>510007949</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2025-03-25T03:00:33.163</CreatedDate> + <ModifiedDate>2025-03-26T03:33:00.893</ModifiedDate> + <ID>27675</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>958bac7c-972b-4cac-aa8a-22a2b77b0fbc</CustomerKey> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>14914</ID> + <ObjectID xsi:nil="true" /> + </ParentFolder> + <Name>mcdev</Name> + <Description /> + <ContentType>cloudpages</ContentType> + <IsActive>true</IsActive> + <IsEditable>true</IsEditable> + <AllowChildren>false</AllowChildren> + </Results> + </RetrieveResponseMsg> + </soap:Body> +</soap:Envelope> diff --git a/test/resources/9999999/dataFolder/retrieve-ContentTypeINasset,asset-shared,cloudpages,journey-response.xml b/test/resources/9999999/dataFolder/retrieve-ContentTypeINasset,asset-shared,cloudpages,journey-response.xml new file mode 100644 index 000000000..f7748dd7a --- /dev/null +++ b/test/resources/9999999/dataFolder/retrieve-ContentTypeINasset,asset-shared,cloudpages,journey-response.xml @@ -0,0 +1,136 @@ +<?xml version="1.0" encoding="utf-8"?> +<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:xsd="http://www.w3.org/2001/XMLSchema" + xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing" + xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" + xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"> + <soap:Header> + <wsa:Action>RetrieveResponse</wsa:Action> + <wsa:MessageID>urn:uuid:dc2be79b-a2b9-4775-90f9-92f7298129e4</wsa:MessageID> + <wsa:RelatesTo>urn:uuid:e6015b6f-c9d3-4649-aed8-ea66f1a1dbe8</wsa:RelatesTo> + <wsa:To>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</wsa:To> + <wsse:Security> + <wsu:Timestamp wsu:Id="Timestamp-89a3ca99-8f71-4361-959c-6fd89384ed9e"> + <wsu:Created>2024-07-22T11:05:21Z</wsu:Created> + <wsu:Expires>2024-07-22T11:10:21Z</wsu:Expires> + </wsu:Timestamp> + </wsse:Security> + </soap:Header> + <soap:Body> + <RetrieveResponseMsg xmlns="http://exacttarget.com/wsdl/partnerAPI"> + <OverallStatus>OK</OverallStatus> + <RequestID>37bbe40c-a525-4f43-b907-0cc83fe7a020</RequestID> + <Results xsi:type="DataFolder"> + <Client> + <ID>9999999</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2017-02-16T01:59:32.323</CreatedDate> + <ModifiedDate>2017-02-16T01:59:32.323</ModifiedDate> + <ID>6298</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>journey_default</CustomerKey> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>0</ID> + <ObjectID xsi:nil="true" /> + </ParentFolder> + <Name>my journeys</Name> + <Description>The root folder for Journeys</Description> + <ContentType>journey</ContentType> + <IsActive>true</IsActive> + <IsEditable>false</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>1111111</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2021-06-21T11:55:12.743</CreatedDate> + <ModifiedDate>2021-06-21T11:55:12.743</ModifiedDate> + <ID>4707</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey /> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>0</ID> + <ObjectID xsi:nil="true" /> + </ParentFolder> + <Name>Content Builder</Name> + <Description>The root folder for assets</Description> + <ContentType>asset</ContentType> + <IsActive>true</IsActive> + <IsEditable>false</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>1111111</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2021-06-21T11:55:13.34</CreatedDate> + <ModifiedDate>2021-06-21T11:55:13.34</ModifiedDate> + <ID>4710</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey /> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>0</ID> + <ObjectID xsi:nil="true" /> + </ParentFolder> + <Name>Shared Content</Name> + <Description>The root shared folder for assets</Description> + <ContentType>asset-shared</ContentType> + <IsActive>true</IsActive> + <IsEditable>false</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>9999999</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2024-02-16T10:12:15.9</CreatedDate> + <ModifiedDate>2024-02-16T10:12:15.9</ModifiedDate> + <ID>14914</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey /> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>0</ID> + <ObjectID xsi:nil="true" /> + </ParentFolder> + <Name>CloudPages</Name> + <Description>The root folder for CloudPages</Description> + <ContentType>cloudpages</ContentType> + <IsActive>true</IsActive> + <IsEditable>false</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>510007949</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2025-03-25T03:00:33.163</CreatedDate> + <ModifiedDate>2025-03-26T03:33:00.893</ModifiedDate> + <ID>27675</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>958bac7c-972b-4cac-aa8a-22a2b77b0fbc</CustomerKey> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>14914</ID> + <ObjectID xsi:nil="true" /> + </ParentFolder> + <Name>mcdev</Name> + <Description /> + <ContentType>cloudpages</ContentType> + <IsActive>true</IsActive> + <IsEditable>true</IsEditable> + <AllowChildren>false</AllowChildren> + </Results> + </RetrieveResponseMsg> + </soap:Body> +</soap:Envelope> diff --git a/test/resources/9999999/dataFolder/retrieve-ContentTypeINasset,asset-shared,cloudpages,ssjsactivity-response.xml b/test/resources/9999999/dataFolder/retrieve-ContentTypeINasset,asset-shared,cloudpages,ssjsactivity-response.xml new file mode 100644 index 000000000..42944643e --- /dev/null +++ b/test/resources/9999999/dataFolder/retrieve-ContentTypeINasset,asset-shared,cloudpages,ssjsactivity-response.xml @@ -0,0 +1,136 @@ +<?xml version="1.0" encoding="utf-8"?> +<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:xsd="http://www.w3.org/2001/XMLSchema" + xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing" + xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" + xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"> + <soap:Header> + <wsa:Action>RetrieveResponse</wsa:Action> + <wsa:MessageID>urn:uuid:00106553-ac00-4e72-b387-42325fe6f93d</wsa:MessageID> + <wsa:RelatesTo>urn:uuid:a1dd2a9d-b696-480e-9a1b-265f262a8997</wsa:RelatesTo> + <wsa:To>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</wsa:To> + <wsse:Security> + <wsu:Timestamp wsu:Id="Timestamp-d82724f8-afc2-4461-8e3e-190aeb6d9625"> + <wsu:Created>2024-01-08T14:30:39Z</wsu:Created> + <wsu:Expires>2024-01-08T14:35:39Z</wsu:Expires> + </wsu:Timestamp> + </wsse:Security> + </soap:Header> + <soap:Body> + <RetrieveResponseMsg xmlns="http://exacttarget.com/wsdl/partnerAPI"> + <OverallStatus>OK</OverallStatus> + <RequestID>6596087d-d12f-4c9d-9353-783fe01775a3</RequestID> + <Results xsi:type="DataFolder"> + <Client> + <ID>9999999</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2016-07-22T11:52:35.687</CreatedDate> + <ModifiedDate>2016-07-22T11:52:35.687</ModifiedDate> + <ID>89397</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey /> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>0</ID> + <ObjectID xsi:nil="true" /> + </ParentFolder> + <Name>Content Builder</Name> + <Description>The root folder for assets</Description> + <ContentType>asset</ContentType> + <IsActive>true</IsActive> + <IsEditable>false</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>9999999</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2016-07-29T12:13:07.7</CreatedDate> + <ModifiedDate>2021-12-16T02:56:14.68</ModifiedDate> + <ID>90888</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey /> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>89397</ID> + <ObjectID xsi:nil="true" /> + </ParentFolder> + <Name>Test Folder</Name> + <Description /> + <ContentType>asset</ContentType> + <IsActive>true</IsActive> + <IsEditable>true</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>9999999</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2017-01-24T06:32:42.353</CreatedDate> + <ModifiedDate>2017-01-24T06:32:42.353</ModifiedDate> + <ID>304</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>SSJSActivity_default</CustomerKey> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>0</ID> + <ObjectID xsi:nil="true" /> + </ParentFolder> + <Name>Scripts</Name> + <Description /> + <ContentType>SSJSActivity</ContentType> + <IsActive>true</IsActive> + <IsEditable>false</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>9999999</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2024-02-16T10:12:15.9</CreatedDate> + <ModifiedDate>2024-02-16T10:12:15.9</ModifiedDate> + <ID>14914</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey /> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>0</ID> + <ObjectID xsi:nil="true" /> + </ParentFolder> + <Name>CloudPages</Name> + <Description>The root folder for CloudPages</Description> + <ContentType>cloudpages</ContentType> + <IsActive>true</IsActive> + <IsEditable>false</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>510007949</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2025-03-25T03:00:33.163</CreatedDate> + <ModifiedDate>2025-03-26T03:33:00.893</ModifiedDate> + <ID>27675</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>958bac7c-972b-4cac-aa8a-22a2b77b0fbc</CustomerKey> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>14914</ID> + <ObjectID xsi:nil="true" /> + </ParentFolder> + <Name>mcdev</Name> + <Description /> + <ContentType>cloudpages</ContentType> + <IsActive>true</IsActive> + <IsEditable>true</IsEditable> + <AllowChildren>false</AllowChildren> + </Results> + </RetrieveResponseMsg> + </soap:Body> +</soap:Envelope> diff --git a/test/resources/9999999/dataFolder/retrieve-ContentTypeINasset,asset-shared,cloudpages-response.xml b/test/resources/9999999/dataFolder/retrieve-ContentTypeINasset,asset-shared,cloudpages-response.xml new file mode 100644 index 000000000..ece8d2967 --- /dev/null +++ b/test/resources/9999999/dataFolder/retrieve-ContentTypeINasset,asset-shared,cloudpages-response.xml @@ -0,0 +1,114 @@ +<?xml version="1.0" encoding="utf-8"?> +<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:xsd="http://www.w3.org/2001/XMLSchema" + xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing" + xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" + xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"> + <soap:Header> + <wsa:Action>RetrieveResponse</wsa:Action> + <wsa:MessageID>urn:uuid:00106553-ac00-4e72-b387-42325fe6f93d</wsa:MessageID> + <wsa:RelatesTo>urn:uuid:a1dd2a9d-b696-480e-9a1b-265f262a8997</wsa:RelatesTo> + <wsa:To>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</wsa:To> + <wsse:Security> + <wsu:Timestamp wsu:Id="Timestamp-d82724f8-afc2-4461-8e3e-190aeb6d9625"> + <wsu:Created>2024-01-08T14:30:39Z</wsu:Created> + <wsu:Expires>2024-01-08T14:35:39Z</wsu:Expires> + </wsu:Timestamp> + </wsse:Security> + </soap:Header> + <soap:Body> + <RetrieveResponseMsg xmlns="http://exacttarget.com/wsdl/partnerAPI"> + <OverallStatus>OK</OverallStatus> + <RequestID>6596087d-d12f-4c9d-9353-783fe01775a3</RequestID> + <Results xsi:type="DataFolder"> + <Client> + <ID>9999999</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2016-07-22T11:52:35.687</CreatedDate> + <ModifiedDate>2016-07-22T11:52:35.687</ModifiedDate> + <ID>89397</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey /> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>0</ID> + <ObjectID xsi:nil="true" /> + </ParentFolder> + <Name>Content Builder</Name> + <Description>The root folder for assets</Description> + <ContentType>asset</ContentType> + <IsActive>true</IsActive> + <IsEditable>false</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>9999999</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2016-07-29T12:13:07.7</CreatedDate> + <ModifiedDate>2021-12-16T02:56:14.68</ModifiedDate> + <ID>90888</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey /> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>89397</ID> + <ObjectID xsi:nil="true" /> + </ParentFolder> + <Name>Test Folder</Name> + <Description /> + <ContentType>asset</ContentType> + <IsActive>true</IsActive> + <IsEditable>true</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>9999999</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2024-02-16T10:12:15.9</CreatedDate> + <ModifiedDate>2024-02-16T10:12:15.9</ModifiedDate> + <ID>14914</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey /> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>0</ID> + <ObjectID xsi:nil="true" /> + </ParentFolder> + <Name>CloudPages</Name> + <Description>The root folder for CloudPages</Description> + <ContentType>cloudpages</ContentType> + <IsActive>true</IsActive> + <IsEditable>false</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>510007949</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2025-03-25T03:00:33.163</CreatedDate> + <ModifiedDate>2025-03-26T03:33:00.893</ModifiedDate> + <ID>27675</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>958bac7c-972b-4cac-aa8a-22a2b77b0fbc</CustomerKey> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>14914</ID> + <ObjectID xsi:nil="true" /> + </ParentFolder> + <Name>mcdev</Name> + <Description /> + <ContentType>cloudpages</ContentType> + <IsActive>true</IsActive> + <IsEditable>true</IsEditable> + <AllowChildren>false</AllowChildren> + </Results> + </RetrieveResponseMsg> + </soap:Body> +</soap:Envelope> diff --git a/test/resources/9999999/dataFolder/retrieve-ContentTypeINasset,asset-shared,shared_data,shared_dataextension,shared_salesforcedataextension,synchronizeddataextension-QAA-response.xml b/test/resources/9999999/dataFolder/retrieve-ContentTypeINasset,asset-shared,shared_data,shared_dataextension,shared_salesforcedataextension,synchronizeddataextension-QAA-response.xml new file mode 100644 index 000000000..4f040825c --- /dev/null +++ b/test/resources/9999999/dataFolder/retrieve-ContentTypeINasset,asset-shared,shared_data,shared_dataextension,shared_salesforcedataextension,synchronizeddataextension-QAA-response.xml @@ -0,0 +1,115 @@ +<?xml version="1.0" encoding="utf-8"?> +<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:xsd="http://www.w3.org/2001/XMLSchema" + xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing" + xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" + xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"> + <soap:Header> + <wsa:Action>RetrieveResponse</wsa:Action> + <wsa:MessageID>urn:uuid:ece12788-5617-4bf7-97b6-d2ee6fefa7c5</wsa:MessageID> + <wsa:RelatesTo>urn:uuid:260afb64-4686-421e-bc94-46386dd6e28d</wsa:RelatesTo> + <wsa:To>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</wsa:To> + <wsse:Security> + <wsu:Timestamp wsu:Id="Timestamp-c6787260-1486-411c-b1e4-1a561aa1efd8"> + <wsu:Created>2024-07-22T09:14:36Z</wsu:Created> + <wsu:Expires>2024-07-22T09:19:36Z</wsu:Expires> + </wsu:Timestamp> + </wsse:Security> + </soap:Header> + <soap:Body> + <RetrieveResponseMsg xmlns="http://exacttarget.com/wsdl/partnerAPI"> + <OverallStatus>OK</OverallStatus> + <RequestID>0df23b67-2645-4b4f-87e1-f3eb6b818dde</RequestID> + <Results xsi:type="DataFolder"> + <Client> + <ID>1111111</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2021-06-21T11:55:12.743</CreatedDate> + <ModifiedDate>2021-06-21T11:55:12.743</ModifiedDate> + <ID>4707</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey /> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>0</ID> + <ObjectID xsi:nil="true" /> + </ParentFolder> + <Name>Content Builder</Name> + <Description>The root folder for assets</Description> + <ContentType>asset</ContentType> + <IsActive>true</IsActive> + <IsEditable>false</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>1111111</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2021-06-21T11:55:13.34</CreatedDate> + <ModifiedDate>2021-06-21T11:55:13.34</ModifiedDate> + <ID>4710</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey /> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>0</ID> + <ObjectID xsi:nil="true" /> + </ParentFolder> + <Name>Shared Content</Name> + <Description>The root shared folder for assets</Description> + <ContentType>asset-shared</ContentType> + <IsActive>true</IsActive> + <IsEditable>false</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>1111111</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2016-07-22T11:52:19.603</CreatedDate> + <ModifiedDate>2016-07-22T11:52:19.603</ModifiedDate> + <ID>89356</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>shared_dataextension_default</CustomerKey> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>89344</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>shared_data_default</CustomerKey> + </ParentFolder> + <Name>Shared Data Extensions</Name> + <Description /> + <ContentType>shared_dataextension</ContentType> + <IsActive>true</IsActive> + <IsEditable>false</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>1111111</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2016-07-22T11:52:18.73</CreatedDate> + <ModifiedDate>2016-07-22T11:52:19.603</ModifiedDate> + <ID>89344</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>shared_data_default</CustomerKey> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>0</ID> + <ObjectID xsi:nil="true" /> + </ParentFolder> + <Name>Shared Items</Name> + <Description /> + <ContentType>shared_data</ContentType> + <IsActive>true</IsActive> + <IsEditable>false</IsEditable> + <AllowChildren>false</AllowChildren> + </Results> + </RetrieveResponseMsg> + </soap:Body> +</soap:Envelope> diff --git a/test/resources/9999999/dataFolder/retrieve-ContentTypeINasset,asset-shared-QAA-response.xml b/test/resources/9999999/dataFolder/retrieve-ContentTypeINasset,asset-shared-QAA-response.xml new file mode 100644 index 000000000..e40e8bbdb --- /dev/null +++ b/test/resources/9999999/dataFolder/retrieve-ContentTypeINasset,asset-shared-QAA-response.xml @@ -0,0 +1,70 @@ +<?xml version="1.0" encoding="utf-8"?> +<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:xsd="http://www.w3.org/2001/XMLSchema" + xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing" + xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" + xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"> + <soap:Header> + <wsa:Action>RetrieveResponse</wsa:Action> + <wsa:MessageID>urn:uuid:ece12788-5617-4bf7-97b6-d2ee6fefa7c5</wsa:MessageID> + <wsa:RelatesTo>urn:uuid:260afb64-4686-421e-bc94-46386dd6e28d</wsa:RelatesTo> + <wsa:To>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</wsa:To> + <wsse:Security> + <wsu:Timestamp wsu:Id="Timestamp-c6787260-1486-411c-b1e4-1a561aa1efd8"> + <wsu:Created>2024-07-22T09:14:36Z</wsu:Created> + <wsu:Expires>2024-07-22T09:19:36Z</wsu:Expires> + </wsu:Timestamp> + </wsse:Security> + </soap:Header> + <soap:Body> + <RetrieveResponseMsg xmlns="http://exacttarget.com/wsdl/partnerAPI"> + <OverallStatus>OK</OverallStatus> + <RequestID>0df23b67-2645-4b4f-87e1-f3eb6b818dde</RequestID> + <Results xsi:type="DataFolder"> + <Client> + <ID>1111111</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2021-06-21T11:55:12.743</CreatedDate> + <ModifiedDate>2021-06-21T11:55:12.743</ModifiedDate> + <ID>4707</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey /> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>0</ID> + <ObjectID xsi:nil="true" /> + </ParentFolder> + <Name>Content Builder</Name> + <Description>The root folder for assets</Description> + <ContentType>asset</ContentType> + <IsActive>true</IsActive> + <IsEditable>false</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>1111111</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2021-06-21T11:55:13.34</CreatedDate> + <ModifiedDate>2021-06-21T11:55:13.34</ModifiedDate> + <ID>4710</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey /> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>0</ID> + <ObjectID xsi:nil="true" /> + </ParentFolder> + <Name>Shared Content</Name> + <Description>The root shared folder for assets</Description> + <ContentType>asset-shared</ContentType> + <IsActive>true</IsActive> + <IsEditable>false</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + </RetrieveResponseMsg> + </soap:Body> +</soap:Envelope> diff --git a/test/resources/9999999/dataFolder/retrieve-ContentTypeINasset,asset-shared-response.xml b/test/resources/9999999/dataFolder/retrieve-ContentTypeINasset,asset-shared-response.xml new file mode 100644 index 000000000..4898884ba --- /dev/null +++ b/test/resources/9999999/dataFolder/retrieve-ContentTypeINasset,asset-shared-response.xml @@ -0,0 +1,70 @@ +<?xml version="1.0" encoding="utf-8"?> +<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:xsd="http://www.w3.org/2001/XMLSchema" + xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing" + xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" + xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"> + <soap:Header> + <wsa:Action>RetrieveResponse</wsa:Action> + <wsa:MessageID>urn:uuid:00106553-ac00-4e72-b387-42325fe6f93d</wsa:MessageID> + <wsa:RelatesTo>urn:uuid:a1dd2a9d-b696-480e-9a1b-265f262a8997</wsa:RelatesTo> + <wsa:To>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</wsa:To> + <wsse:Security> + <wsu:Timestamp wsu:Id="Timestamp-d82724f8-afc2-4461-8e3e-190aeb6d9625"> + <wsu:Created>2024-01-08T14:30:39Z</wsu:Created> + <wsu:Expires>2024-01-08T14:35:39Z</wsu:Expires> + </wsu:Timestamp> + </wsse:Security> + </soap:Header> + <soap:Body> + <RetrieveResponseMsg xmlns="http://exacttarget.com/wsdl/partnerAPI"> + <OverallStatus>OK</OverallStatus> + <RequestID>6596087d-d12f-4c9d-9353-783fe01775a3</RequestID> + <Results xsi:type="DataFolder"> + <Client> + <ID>9999999</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2016-07-22T11:52:35.687</CreatedDate> + <ModifiedDate>2016-07-22T11:52:35.687</ModifiedDate> + <ID>89397</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey /> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>0</ID> + <ObjectID xsi:nil="true" /> + </ParentFolder> + <Name>Content Builder</Name> + <Description>The root folder for assets</Description> + <ContentType>asset</ContentType> + <IsActive>true</IsActive> + <IsEditable>false</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>9999999</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2016-07-29T12:13:07.7</CreatedDate> + <ModifiedDate>2021-12-16T02:56:14.68</ModifiedDate> + <ID>90888</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey /> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>89397</ID> + <ObjectID xsi:nil="true" /> + </ParentFolder> + <Name>Test Folder</Name> + <Description /> + <ContentType>asset</ContentType> + <IsActive>true</IsActive> + <IsEditable>true</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + </RetrieveResponseMsg> + </soap:Body> +</soap:Envelope> diff --git a/test/resources/9999999/dataFolder/retrieve-ContentTypeINasset-shared,shared_data,shared_dataextension,shared_salesforcedataextension,synchronizeddataextension-QAA-response.xml b/test/resources/9999999/dataFolder/retrieve-ContentTypeINasset-shared,shared_data,shared_dataextension,shared_salesforcedataextension,synchronizeddataextension-QAA-response.xml new file mode 100644 index 000000000..2fff35d18 --- /dev/null +++ b/test/resources/9999999/dataFolder/retrieve-ContentTypeINasset-shared,shared_data,shared_dataextension,shared_salesforcedataextension,synchronizeddataextension-QAA-response.xml @@ -0,0 +1,431 @@ +<?xml version="1.0" encoding="utf-8"?> +<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:xsd="http://www.w3.org/2001/XMLSchema" + xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing" + xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" + xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"> + <soap:Header> + <wsa:Action>RetrieveResponse</wsa:Action> + <wsa:MessageID>urn:uuid:4d209b2f-d7ce-4e6e-916c-c8642d368866</wsa:MessageID> + <wsa:RelatesTo>urn:uuid:a850f043-1422-4d16-8443-702dd2f9f13a</wsa:RelatesTo> + <wsa:To>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</wsa:To> + <wsse:Security> + <wsu:Timestamp wsu:Id="Timestamp-5da63531-caa7-4ead-9f10-a33d9bf66745"> + <wsu:Created>2023-08-11T13:15:46Z</wsu:Created> + <wsu:Expires>2023-08-11T13:20:46Z</wsu:Expires> + </wsu:Timestamp> + </wsse:Security> + </soap:Header> + <soap:Body> + <RetrieveResponseMsg xmlns="http://exacttarget.com/wsdl/partnerAPI"> + <OverallStatus>OK</OverallStatus> + <RequestID>ba1b0c59-78c4-4608-8423-35dda2248d4d</RequestID> + <Results xsi:type="DataFolder"> + <Client> + <ID>1111111</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2016-07-22T11:52:18.73</CreatedDate> + <ModifiedDate>2016-07-22T11:52:19.603</ModifiedDate> + <ID>89344</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>shared_data_default</CustomerKey> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>0</ID> + <ObjectID xsi:nil="true" /> + </ParentFolder> + <Name>Shared Items</Name> + <Description /> + <ContentType>shared_data</ContentType> + <IsActive>true</IsActive> + <IsEditable>false</IsEditable> + <AllowChildren>false</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>1111111</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2016-07-22T11:52:19.6</CreatedDate> + <ModifiedDate>2016-07-22T11:52:19.6</ModifiedDate> + <ID>89355</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>dataextension_default</CustomerKey> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>0</ID> + <ObjectID xsi:nil="true" /> + </ParentFolder> + <Name>Data Extensions</Name> + <Description /> + <ContentType>dataextension</ContentType> + <IsActive>true</IsActive> + <IsEditable>false</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>1111111</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2016-07-22T11:52:19.603</CreatedDate> + <ModifiedDate>2016-07-22T11:52:19.603</ModifiedDate> + <ID>89356</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>shared_dataextension_default</CustomerKey> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>89344</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>shared_data_default</CustomerKey> + </ParentFolder> + <Name>Shared Data Extensions</Name> + <Description /> + <ContentType>shared_dataextension</ContentType> + <IsActive>true</IsActive> + <IsEditable>false</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>1111111</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2016-07-29T12:13:27.28</CreatedDate> + <ModifiedDate>2016-07-29T12:13:27.28</ModifiedDate> + <ID>90889</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>HiddenCategory_default</CustomerKey> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>0</ID> + <ObjectID xsi:nil="true" /> + </ParentFolder> + <Name>HiddenCategory</Name> + <Description>Hidden folder to store Hidden items</Description> + <ContentType>Hidden</ContentType> + <IsActive>true</IsActive> + <IsEditable>false</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>1111111</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2016-08-23T09:22:27.54</CreatedDate> + <ModifiedDate>2016-08-23T09:22:27.54</ModifiedDate> + <ID>93698</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>salesforcedataextension_default</CustomerKey> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>0</ID> + <ObjectID xsi:nil="true" /> + </ParentFolder> + <Name>Salesforce Data Extensions</Name> + <Description /> + <ContentType>salesforcedataextension</ContentType> + <IsActive>true</IsActive> + <IsEditable>false</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>1111111</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2016-08-23T09:22:27.55</CreatedDate> + <ModifiedDate>2016-08-23T09:22:27.55</ModifiedDate> + <ID>93699</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>shared_salesforcedataextension_defau</CustomerKey> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>89344</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>shared_data_default</CustomerKey> + </ParentFolder> + <Name>Shared Salesforce Data Extensions</Name> + <Description /> + <ContentType>shared_salesforcedataextension</ContentType> + <IsActive>true</IsActive> + <IsEditable>false</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>1111111</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2020-01-27T10:50:46.573</CreatedDate> + <ModifiedDate>2020-01-27T10:50:46.573</ModifiedDate> + <ID>309082</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey /> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>89355</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>dataextension_default</CustomerKey> + </ParentFolder> + <Name>QueryStudioResults</Name> + <Description /> + <ContentType>dataextension</ContentType> + <IsActive>true</IsActive> + <IsEditable>true</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>1111111</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2020-04-17T08:14:19.763</CreatedDate> + <ModifiedDate>2020-04-17T08:14:19.763</ModifiedDate> + <ID>587750</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey /> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>89356</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>shared_dataextension_default</CustomerKey> + </ParentFolder> + <Name>catalyst target 1</Name> + <Description /> + <ContentType>shared_dataextension</ContentType> + <IsActive>true</IsActive> + <IsEditable>true</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>1111111</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2020-07-09T02:30:12.38</CreatedDate> + <ModifiedDate>2021-12-16T03:43:30.753</ModifiedDate> + <ID>605618</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>dataextension_default</CustomerKey> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>89355</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>dataextension_default</CustomerKey> + </ParentFolder> + <Name>Audiences</Name> + <Description /> + <ContentType>dataextension</ContentType> + <IsActive>true</IsActive> + <IsEditable>true</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>1111111</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2020-12-25T06:11:40.107</CreatedDate> + <ModifiedDate>2021-12-23T10:51:24.393</ModifiedDate> + <ID>633441</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey /> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>89355</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>dataextension_default</CustomerKey> + </ParentFolder> + <Name>System DEs</Name> + <Description /> + <ContentType>dataextension</ContentType> + <IsActive>true</IsActive> + <IsEditable>true</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>1111111</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2021-01-30T11:54:36.11</CreatedDate> + <ModifiedDate>2021-01-30T11:54:36.11</ModifiedDate> + <ID>638814</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>0b72bf27-0678-484d-ac0b-a8762b9bec33</CustomerKey> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>89356</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>shared_dataextension_default</CustomerKey> + </ParentFolder> + <Name>Customer 360 Segments</Name> + <Description>All Customer 360 segments will be grouped here. Each sub-folder relates to an activation profile name.</Description> + <ContentType>shared_dataextension</ContentType> + <IsActive>true</IsActive> + <IsEditable>false</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>1111111</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2021-01-30T11:56:38.77</CreatedDate> + <ModifiedDate>2021-01-30T11:56:38.77</ModifiedDate> + <ID>638815</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>cedd206d-178e-41cb-8965-ce255975b046</CustomerKey> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>638814</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>0b72bf27-0678-484d-ac0b-a8762b9bec33</CustomerKey> + </ParentFolder> + <Name>FirstAudience360 Segment</Name> + <Description /> + <ContentType>shared_dataextension</ContentType> + <IsActive>true</IsActive> + <IsEditable>false</IsEditable> + <AllowChildren>false</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>1111111</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2021-02-07T10:44:01.413</CreatedDate> + <ModifiedDate>2021-12-16T03:43:33.38</ModifiedDate> + <ID>639967</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey /> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>89355</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>dataextension_default</CustomerKey> + </ParentFolder> + <Name>TestAudiences</Name> + <Description /> + <ContentType>dataextension</ContentType> + <IsActive>true</IsActive> + <IsEditable>true</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>1111111</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2021-08-04T15:17:18.533</CreatedDate> + <ModifiedDate>2021-08-04T15:17:18.567</ModifiedDate> + <ID>675203</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>A19F7E38-7369-497E-826F-D551F17FB0B4</CustomerKey> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>0</ID> + <ObjectID xsi:nil="true" /> + </ParentFolder> + <Name>Synchronized Data Extensions</Name> + <Description /> + <ContentType>synchronizeddataextension</ContentType> + <IsActive>true</IsActive> + <IsEditable>false</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>1111111</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2021-10-03T05:01:37.23</CreatedDate> + <ModifiedDate>2021-10-03T05:01:37.37</ModifiedDate> + <ID>688352</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>B80AE306-55BC-4C2E-A79F-8CCA486F0BA0</CustomerKey> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>0</ID> + <ObjectID xsi:nil="true" /> + </ParentFolder> + <Name>Synchronized Data Extensions</Name> + <Description /> + <ContentType>synchronizeddataextension</ContentType> + <IsActive>true</IsActive> + <IsEditable>false</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>1111111</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2022-10-26T09:48:38.293</CreatedDate> + <ModifiedDate>2022-10-26T09:48:38.31</ModifiedDate> + <ID>757145</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>0ACB800B-AA8B-4F0F-9642-4907592C919C</CustomerKey> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>0</ID> + <ObjectID xsi:nil="true" /> + </ParentFolder> + <Name>Synchronized Data Extensions</Name> + <Description /> + <ContentType>synchronizeddataextension</ContentType> + <IsActive>true</IsActive> + <IsEditable>false</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>1111111</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2021-06-21T11:55:12.743</CreatedDate> + <ModifiedDate>2021-06-21T11:55:12.743</ModifiedDate> + <ID>4707</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey /> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>0</ID> + <ObjectID xsi:nil="true" /> + </ParentFolder> + <Name>Content Builder</Name> + <Description>The root folder for assets</Description> + <ContentType>asset</ContentType> + <IsActive>true</IsActive> + <IsEditable>false</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>1111111</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2021-06-21T11:55:13.34</CreatedDate> + <ModifiedDate>2021-06-21T11:55:13.34</ModifiedDate> + <ID>4710</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey /> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>0</ID> + <ObjectID xsi:nil="true" /> + </ParentFolder> + <Name>Shared Content</Name> + <Description>The root shared folder for assets</Description> + <ContentType>asset-shared</ContentType> + <IsActive>true</IsActive> + <IsEditable>false</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + </RetrieveResponseMsg> + </soap:Body> +</soap:Envelope> diff --git a/test/resources/9999999/dataFolder/retrieve-ContentTypeINautomations,queryactivity-response.xml b/test/resources/9999999/dataFolder/retrieve-ContentTypeINautomations,queryactivity-response.xml new file mode 100644 index 000000000..f41293234 --- /dev/null +++ b/test/resources/9999999/dataFolder/retrieve-ContentTypeINautomations,queryactivity-response.xml @@ -0,0 +1,70 @@ +<?xml version="1.0" encoding="utf-8"?> +<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:xsd="http://www.w3.org/2001/XMLSchema" + xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing" + xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" + xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"> + <soap:Header> + <wsa:Action>RetrieveResponse</wsa:Action> + <wsa:MessageID>urn:uuid:f36f3303-3b5a-4641-8109-b26447634d91</wsa:MessageID> + <wsa:RelatesTo>urn:uuid:33983968-28c4-4379-bb5f-f80ae32eb988</wsa:RelatesTo> + <wsa:To>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</wsa:To> + <wsse:Security> + <wsu:Timestamp wsu:Id="Timestamp-32ecc81b-6020-473c-9e99-4b5338921220"> + <wsu:Created>2022-04-19T20:03:41Z</wsu:Created> + <wsu:Expires>2022-04-19T20:08:41Z</wsu:Expires> + </wsu:Timestamp> + </wsse:Security> + </soap:Header> + <soap:Body> + <RetrieveResponseMsg xmlns="http://exacttarget.com/wsdl/partnerAPI"> + <OverallStatus>OK</OverallStatus> + <RequestID>02cd5ccb-8f84-4651-826f-71169eeecf05</RequestID> + <Results xsi:type="DataFolder"> + <Client> + <ID>9999999</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2019-10-25T05:35:17.337</CreatedDate> + <ModifiedDate>2019-10-25T05:35:17.337</ModifiedDate> + <ID>290937</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey /> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>0</ID> + <ObjectID xsi:nil="true" /> + </ParentFolder> + <Name>my automations</Name> + <Description /> + <ContentType>automations</ContentType> + <IsActive>true</IsActive> + <IsEditable>true</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>9999999</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2016-07-22T11:52:20.407</CreatedDate> + <ModifiedDate>2016-07-22T11:52:20.407</ModifiedDate> + <ID>999</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>queryactivity_default</CustomerKey> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>0</ID> + <ObjectID xsi:nil="true" /> + </ParentFolder> + <Name>Query</Name> + <Description /> + <ContentType>queryactivity</ContentType> + <IsActive>true</IsActive> + <IsEditable>false</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + </RetrieveResponseMsg> + </soap:Body> +</soap:Envelope> diff --git a/test/resources/9999999/dataFolder/retrieve-ContentTypeINcontextual_suppression_list,hidden,list,mysubs,publication,suppression_list,triggered_send,triggered_send_journeybuilder-response.xml b/test/resources/9999999/dataFolder/retrieve-ContentTypeINcontextual_suppression_list,hidden,list,mysubs,publication,suppression_list,triggered_send,triggered_send_journeybuilder-response.xml new file mode 100644 index 000000000..1c91178f2 --- /dev/null +++ b/test/resources/9999999/dataFolder/retrieve-ContentTypeINcontextual_suppression_list,hidden,list,mysubs,publication,suppression_list,triggered_send,triggered_send_journeybuilder-response.xml @@ -0,0 +1,385 @@ +<?xml version="1.0" encoding="utf-8"?> +<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:xsd="http://www.w3.org/2001/XMLSchema" + xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing" + xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" + xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"> + <soap:Header> + <wsa:Action>RetrieveResponse</wsa:Action> + <wsa:MessageID>urn:uuid:f36f3303-3b5a-4641-8109-b26447634d91</wsa:MessageID> + <wsa:RelatesTo>urn:uuid:33983968-28c4-4379-bb5f-f80ae32eb988</wsa:RelatesTo> + <wsa:To>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</wsa:To> + <wsse:Security> + <wsu:Timestamp wsu:Id="Timestamp-32ecc81b-6020-473c-9e99-4b5338921220"> + <wsu:Created>2022-04-19T20:03:41Z</wsu:Created> + <wsu:Expires>2022-04-19T20:08:41Z</wsu:Expires> + </wsu:Timestamp> + </wsse:Security> + </soap:Header> + <soap:Body> + <RetrieveResponseMsg xmlns="http://exacttarget.com/wsdl/partnerAPI"> + <OverallStatus>OK</OverallStatus> + <RequestID>02cd5ccb-8f84-4651-826f-71169eeecf05</RequestID> + <Results xsi:type="DataFolder"> + <Client> + <ID>9999999</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2016-07-29T12:13:27.28</CreatedDate> + <ModifiedDate>2016-07-29T12:13:27.28</ModifiedDate> + <ID>90889</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>HiddenCategory_default</CustomerKey> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>0</ID> + <ObjectID xsi:nil="true" /> + </ParentFolder> + <Name>HiddenCategory</Name> + <Description>Hidden folder to store Hidden items</Description> + <ContentType>Hidden</ContentType> + <IsActive>true</IsActive> + <IsEditable>false</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>9999999</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2017-02-16T01:59:32.323</CreatedDate> + <ModifiedDate>2017-02-16T01:59:32.323</ModifiedDate> + <ID>419</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>suppression_list_default</CustomerKey> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>0</ID> + <ObjectID xsi:nil="true" /> + </ParentFolder> + <Name>Suppression Lists</Name> + <Description /> + <ContentType>suppression_list</ContentType> + <IsActive>true</IsActive> + <IsEditable>false</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>9999999</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2017-02-16T01:59:27.177</CreatedDate> + <ModifiedDate>2017-02-16T01:59:27.177</ModifiedDate> + <ID>404</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>list_default</CustomerKey> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>0</ID> + <ObjectID xsi:nil="true" /> + </ParentFolder> + <Name>my lists</Name> + <Description /> + <ContentType>list</ContentType> + <IsActive>true</IsActive> + <IsEditable>false</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>9999999</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2017-02-16T01:59:32.323</CreatedDate> + <ModifiedDate>2017-02-16T01:59:32.323</ModifiedDate> + <ID>419</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>suppression_list_default</CustomerKey> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>0</ID> + <ObjectID xsi:nil="true" /> + </ParentFolder> + <Name>Suppression Lists</Name> + <Description /> + <ContentType>suppression_list</ContentType> + <IsActive>true</IsActive> + <IsEditable>false</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>9999999</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2017-02-16T01:59:27.18</CreatedDate> + <ModifiedDate>2017-02-16T01:59:27.18</ModifiedDate> + <ID>412</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>mysubs_default</CustomerKey> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>0</ID> + <ObjectID xsi:nil="true" /> + </ParentFolder> + <Name>my subscribers</Name> + <Description /> + <ContentType>mysubs</ContentType> + <IsActive>true</IsActive> + <IsEditable>false</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>9999999</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2017-02-16T01:59:34.023</CreatedDate> + <ModifiedDate>2017-02-16T01:59:34.023</ModifiedDate> + <ID>424</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>publication_default</CustomerKey> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>0</ID> + <ObjectID xsi:nil="true" /> + </ParentFolder> + <Name>Publication Lists</Name> + <Description /> + <ContentType>publication</ContentType> + <IsActive>true</IsActive> + <IsEditable>false</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>9999999</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2016-07-22T11:52:19.28</CreatedDate> + <ModifiedDate>2016-07-22T11:52:19.28</ModifiedDate> + <ID>89348</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>triggered_send_default</CustomerKey> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>0</ID> + <ObjectID xsi:nil="true" /> + </ParentFolder> + <Name>Triggered Sends</Name> + <Description /> + <ContentType>triggered_send</ContentType> + <IsActive>true</IsActive> + <IsEditable>false</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>9999999</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2016-07-22T11:52:34.983</CreatedDate> + <ModifiedDate>2016-07-22T11:52:34.983</ModifiedDate> + <ID>89396</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>triggered_send_journeybuilder</CustomerKey> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>0</ID> + <ObjectID xsi:nil="true" /> + </ParentFolder> + <Name>Journey Builder Sends</Name> + <Description /> + <ContentType>triggered_send_journeybuilder</ContentType> + <IsActive>true</IsActive> + <IsEditable>false</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>9999999</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2016-08-25T10:04:09.12</CreatedDate> + <ModifiedDate>2016-08-25T10:04:09.12</ModifiedDate> + <ID>94030</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey /> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>89396</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>triggered_send_journeybuilder</CustomerKey> + </ParentFolder> + <Name>Satisfaction Score Survey</Name> + <Description /> + <ContentType>triggered_send_journeybuilder</ContentType> + <IsActive>true</IsActive> + <IsEditable>true</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>9999999</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2016-08-25T10:04:09.133</CreatedDate> + <ModifiedDate>2016-08-25T10:04:09.133</ModifiedDate> + <ID>94031</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey /> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>94030</ID> + <ObjectID xsi:nil="true" /> + </ParentFolder> + <Name>Version 1</Name> + <Description /> + <ContentType>triggered_send_journeybuilder</ContentType> + <IsActive>true</IsActive> + <IsEditable>true</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>9999999</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2021-06-09T10:17:06.27</CreatedDate> + <ModifiedDate>2021-06-09T10:17:06.27</ModifiedDate> + <ID>664654</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>6aa28490-6577-4cb2-8eac-fd5e4f983cae</CustomerKey> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>317169</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>HiddenJourneyBuilderTriggeredSends_d</CustomerKey> + </ParentFolder> + <Name>6aa28490-6577-4cb2-8eac-fd5e4f983cae_V9</Name> + <Description>triggered_send folder to store triggered_send items</Description> + <ContentType>triggered_send</ContentType> + <IsActive>true</IsActive> + <IsEditable>true</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>9999999</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2022-07-31T19:55:31.657</CreatedDate> + <ModifiedDate>2022-07-31T19:55:31.657</ModifiedDate> + <ID>742869</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>77211381-9967-4472-bd12-f58d4d5952a1</CustomerKey> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>317169</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>HiddenJourneyBuilderTriggeredSends_d</CustomerKey> + </ParentFolder> + <Name>77211381-9967-4472-bd12-f58d4d5952a1_V1</Name> + <Description>triggered_send folder to store triggered_send items</Description> + <ContentType>triggered_send</ContentType> + <IsActive>true</IsActive> + <IsEditable>true</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>9999999</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2022-07-31T19:56:51.297</CreatedDate> + <ModifiedDate>2022-07-31T19:56:51.297</ModifiedDate> + <ID>742871</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>HiddenJourneyBuilderSimulationTrigge</CustomerKey> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>90889</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>HiddenCategory_default</CustomerKey> + </ParentFolder> + <Name>HiddenJourneyBuilderSimulationTriggeredSends</Name> + <Description>triggered_send_journeybuilder folder to store triggered_send_journeybuilder items</Description> + <ContentType>triggered_send_journeybuilder</ContentType> + <IsActive>true</IsActive> + <IsEditable>true</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>9999999</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2023-03-08T10:26:55.787</CreatedDate> + <ModifiedDate>2023-03-08T10:26:55.787</ModifiedDate> + <ID>771879</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>8c24f428-4da8-4df6-97a7-beba5166c3c7</CustomerKey> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>317169</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>HiddenJourneyBuilderTriggeredSends_d</CustomerKey> + </ParentFolder> + <Name>8c24f428-4da8-4df6-97a7-beba5166c3c7_V1</Name> + <Description>triggered_send folder to store triggered_send items</Description> + <ContentType>triggered_send</ContentType> + <IsActive>true</IsActive> + <IsEditable>true</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>9999999</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2023-04-10T15:46:09.947</CreatedDate> + <ModifiedDate>2023-04-10T15:46:09.947</ModifiedDate> + <ID>776623</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>0a85b483-4208-4377-87fb-25794f5df244</CustomerKey> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>317169</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>HiddenJourneyBuilderTriggeredSends_d</CustomerKey> + </ParentFolder> + <Name>0a85b483-4208-4377-87fb-25794f5df244_V1</Name> + <Description>triggered_send folder to store triggered_send items</Description> + <ContentType>triggered_send</ContentType> + <IsActive>true</IsActive> + <IsEditable>true</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>9999999</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2020-03-06T07:57:37.633</CreatedDate> + <ModifiedDate>2020-03-06T07:57:37.633</ModifiedDate> + <ID>317169</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>HiddenJourneyBuilderTriggeredSends_d</CustomerKey> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>90889</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>HiddenCategory_default</CustomerKey> + </ParentFolder> + <Name>HiddenJourneyBuilderTriggeredSends</Name> + <Description>triggered_send folder to store triggered_send items</Description> + <ContentType>triggered_send</ContentType> + <IsActive>true</IsActive> + <IsEditable>true</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + </RetrieveResponseMsg> + </soap:Body> +</soap:Envelope> diff --git a/test/resources/9999999/dataFolder/retrieve-ContentTypeINcontextual_suppression_list,list,mysubs,publication,suppression_list-response.xml b/test/resources/9999999/dataFolder/retrieve-ContentTypeINcontextual_suppression_list,list,mysubs,publication,suppression_list-response.xml new file mode 100644 index 000000000..306c34f4f --- /dev/null +++ b/test/resources/9999999/dataFolder/retrieve-ContentTypeINcontextual_suppression_list,list,mysubs,publication,suppression_list-response.xml @@ -0,0 +1,136 @@ +<?xml version="1.0" encoding="utf-8"?> +<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:xsd="http://www.w3.org/2001/XMLSchema" + xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing" + xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" + xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"> + <soap:Header> + <wsa:Action>RetrieveResponse</wsa:Action> + <wsa:MessageID>urn:uuid:016c1c21-3227-4e9c-9497-33b0c15d971b</wsa:MessageID> + <wsa:RelatesTo>urn:uuid:f559d162-26ae-4a2c-8bfe-0abaa0be36aa</wsa:RelatesTo> + <wsa:To>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</wsa:To> + <wsse:Security> + <wsu:Timestamp wsu:Id="Timestamp-9215e989-d752-4c92-914c-5d254c377f41"> + <wsu:Created>2023-08-08T12:49:25Z</wsu:Created> + <wsu:Expires>2023-08-08T12:54:25Z</wsu:Expires> + </wsu:Timestamp> + </wsse:Security> + </soap:Header> + <soap:Body> + <RetrieveResponseMsg xmlns="http://exacttarget.com/wsdl/partnerAPI"> + <OverallStatus>OK</OverallStatus> + <RequestID>01c5259b-174e-4c70-9fa7-f5cd984b28c6</RequestID> + <Results xsi:type="DataFolder"> + <Client> + <ID>9999999</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2017-02-16T01:59:27.177</CreatedDate> + <ModifiedDate>2017-02-16T01:59:27.177</ModifiedDate> + <ID>404</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>list_default</CustomerKey> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>0</ID> + <ObjectID xsi:nil="true" /> + </ParentFolder> + <Name>my lists</Name> + <Description /> + <ContentType>list</ContentType> + <IsActive>true</IsActive> + <IsEditable>false</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>9999999</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2016-07-22T11:52:17.55</CreatedDate> + <ModifiedDate>2016-07-22T11:52:17.55</ModifiedDate> + <ID>89332</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>mysubs_default</CustomerKey> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>0</ID> + <ObjectID xsi:nil="true" /> + </ParentFolder> + <Name>my subscribers</Name> + <Description /> + <ContentType>mysubs</ContentType> + <IsActive>true</IsActive> + <IsEditable>false</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>9999999</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2017-02-16T01:59:32.323</CreatedDate> + <ModifiedDate>2017-02-16T01:59:32.323</ModifiedDate> + <ID>419</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>suppression_list_default</CustomerKey> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>0</ID> + <ObjectID xsi:nil="true" /> + </ParentFolder> + <Name>Suppression Lists</Name> + <Description /> + <ContentType>suppression_list</ContentType> + <IsActive>true</IsActive> + <IsEditable>false</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>9999999</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2017-02-16T01:59:34.023</CreatedDate> + <ModifiedDate>2017-02-16T01:59:34.023</ModifiedDate> + <ID>424</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>publication_default</CustomerKey> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>0</ID> + <ObjectID xsi:nil="true" /> + </ParentFolder> + <Name>Publication Lists</Name> + <Description /> + <ContentType>publication</ContentType> + <IsActive>true</IsActive> + <IsEditable>false</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>9999999</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2016-07-22T11:52:24.417</CreatedDate> + <ModifiedDate>2016-07-22T11:52:24.417</ModifiedDate> + <ID>89373</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>contextual_suppression_list_default</CustomerKey> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>0</ID> + <ObjectID xsi:nil="true" /> + </ParentFolder> + <Name>Auto-Suppression Configuration</Name> + <Description /> + <ContentType>contextual_suppression_list</ContentType> + <IsActive>true</IsActive> + <IsEditable>false</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + </RetrieveResponseMsg> + </soap:Body> +</soap:Envelope> diff --git a/test/resources/9999999/dataFolder/retrieve-ContentTypeINdataextension,hidden,queryactivity,salesforcedataextension,shared_data,shared_dataextension,shared_salesforcedataextension,synchronizeddataextension-response.xml b/test/resources/9999999/dataFolder/retrieve-ContentTypeINdataextension,hidden,queryactivity,salesforcedataextension,shared_data,shared_dataextension,shared_salesforcedataextension,synchronizeddataextension-response.xml new file mode 100644 index 000000000..1545eab80 --- /dev/null +++ b/test/resources/9999999/dataFolder/retrieve-ContentTypeINdataextension,hidden,queryactivity,salesforcedataextension,shared_data,shared_dataextension,shared_salesforcedataextension,synchronizeddataextension-response.xml @@ -0,0 +1,138 @@ +<?xml version="1.0" encoding="utf-8"?> +<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:xsd="http://www.w3.org/2001/XMLSchema" + xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing" + xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" + xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"> + <soap:Header> + <wsa:Action>RetrieveResponse</wsa:Action> + <wsa:MessageID>urn:uuid:f36f3303-3b5a-4641-8109-b26447634d91</wsa:MessageID> + <wsa:RelatesTo>urn:uuid:33983968-28c4-4379-bb5f-f80ae32eb988</wsa:RelatesTo> + <wsa:To>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</wsa:To> + <wsse:Security> + <wsu:Timestamp wsu:Id="Timestamp-32ecc81b-6020-473c-9e99-4b5338921220"> + <wsu:Created>2022-04-19T20:03:41Z</wsu:Created> + <wsu:Expires>2022-04-19T20:08:41Z</wsu:Expires> + </wsu:Timestamp> + </wsse:Security> + </soap:Header> + <soap:Body> + <RetrieveResponseMsg xmlns="http://exacttarget.com/wsdl/partnerAPI"> + <OverallStatus>OK</OverallStatus> + <RequestID>02cd5ccb-8f84-4651-826f-71169eeecf05</RequestID> + <Results xsi:type="DataFolder"> + <Client> + <ID>9999999</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2016-07-22T11:52:19.6</CreatedDate> + <ModifiedDate>2016-07-22T11:52:19.6</ModifiedDate> + <ID>2</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>dataextension_default</CustomerKey> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>0</ID> + <ObjectID xsi:nil="true" /> + </ParentFolder> + <Name>Data Extensions</Name> + <Description /> + <ContentType>dataextension</ContentType> + <IsActive>true</IsActive> + <IsEditable>false</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>9999999</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2017-02-08T10:19:37.123</CreatedDate> + <ModifiedDate>2017-02-08T10:19:37.123</ModifiedDate> + <ID>386</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey /> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>2</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>dataextension_default</CustomerKey> + </ParentFolder> + <Name>Einstein</Name> + <Description /> + <ContentType>dataextension</ContentType> + <IsActive>true</IsActive> + <IsEditable>true</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>1111111</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2016-07-22T11:52:19.603</CreatedDate> + <ModifiedDate>2016-07-22T11:52:19.603</ModifiedDate> + <ID>89356</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>shared_dataextension_default</CustomerKey> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>89344</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>shared_data_default</CustomerKey> + </ParentFolder> + <Name>Shared Data Extensions</Name> + <Description /> + <ContentType>shared_dataextension</ContentType> + <IsActive>true</IsActive> + <IsEditable>false</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>1111111</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2016-07-22T11:52:18.73</CreatedDate> + <ModifiedDate>2016-07-22T11:52:19.603</ModifiedDate> + <ID>89344</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>shared_data_default</CustomerKey> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>0</ID> + <ObjectID xsi:nil="true" /> + </ParentFolder> + <Name>Shared Items</Name> + <Description /> + <ContentType>shared_data</ContentType> + <IsActive>true</IsActive> + <IsEditable>false</IsEditable> + <AllowChildren>false</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>9999999</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2016-07-22T11:52:20.407</CreatedDate> + <ModifiedDate>2016-07-22T11:52:20.407</ModifiedDate> + <ID>999</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>queryactivity_default</CustomerKey> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>0</ID> + <ObjectID xsi:nil="true" /> + </ParentFolder> + <Name>Query</Name> + <Description /> + <ContentType>queryactivity</ContentType> + <IsActive>true</IsActive> + <IsEditable>false</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + </RetrieveResponseMsg> + </soap:Body> +</soap:Envelope> diff --git a/test/resources/9999999/dataFolder/retrieve-ContentTypeINdataextension,hidden,salesforcedataextension,shared_data,shared_dataextension,shared_salesforcedataextension,synchronizeddataextension-response.xml b/test/resources/9999999/dataFolder/retrieve-ContentTypeINdataextension,hidden,salesforcedataextension,shared_data,shared_dataextension,shared_salesforcedataextension,synchronizeddataextension-response.xml new file mode 100644 index 000000000..d51b42687 --- /dev/null +++ b/test/resources/9999999/dataFolder/retrieve-ContentTypeINdataextension,hidden,salesforcedataextension,shared_data,shared_dataextension,shared_salesforcedataextension,synchronizeddataextension-response.xml @@ -0,0 +1,117 @@ +<?xml version="1.0" encoding="utf-8"?> +<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:xsd="http://www.w3.org/2001/XMLSchema" + xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing" + xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" + xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"> + <soap:Header> + <wsa:Action>RetrieveResponse</wsa:Action> + <wsa:MessageID>urn:uuid:f36f3303-3b5a-4641-8109-b26447634d91</wsa:MessageID> + <wsa:RelatesTo>urn:uuid:33983968-28c4-4379-bb5f-f80ae32eb988</wsa:RelatesTo> + <wsa:To>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</wsa:To> + <wsse:Security> + <wsu:Timestamp wsu:Id="Timestamp-32ecc81b-6020-473c-9e99-4b5338921220"> + <wsu:Created>2022-04-19T20:03:41Z</wsu:Created> + <wsu:Expires>2022-04-19T20:08:41Z</wsu:Expires> + </wsu:Timestamp> + </wsse:Security> + </soap:Header> + <soap:Body> + <RetrieveResponseMsg xmlns="http://exacttarget.com/wsdl/partnerAPI"> + <OverallStatus>OK</OverallStatus> + <RequestID>02cd5ccb-8f84-4651-826f-71169eeecf05</RequestID> + <Results xsi:type="DataFolder"> + <Client> + <ID>9999999</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2016-07-22T11:52:19.6</CreatedDate> + <ModifiedDate>2016-07-22T11:52:19.6</ModifiedDate> + <ID>2</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>dataextension_default</CustomerKey> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>0</ID> + <ObjectID xsi:nil="true" /> + </ParentFolder> + <Name>Data Extensions</Name> + <Description /> + <ContentType>dataextension</ContentType> + <IsActive>true</IsActive> + <IsEditable>false</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>9999999</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2017-02-08T10:19:37.123</CreatedDate> + <ModifiedDate>2017-02-08T10:19:37.123</ModifiedDate> + <ID>386</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey /> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>2</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>dataextension_default</CustomerKey> + </ParentFolder> + <Name>Einstein</Name> + <Description /> + <ContentType>dataextension</ContentType> + <IsActive>true</IsActive> + <IsEditable>true</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>1111111</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2016-07-22T11:52:19.603</CreatedDate> + <ModifiedDate>2016-07-22T11:52:19.603</ModifiedDate> + <ID>89356</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>shared_dataextension_default</CustomerKey> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>89344</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>shared_data_default</CustomerKey> + </ParentFolder> + <Name>Shared Data Extensions</Name> + <Description /> + <ContentType>shared_dataextension</ContentType> + <IsActive>true</IsActive> + <IsEditable>false</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>1111111</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2016-07-22T11:52:18.73</CreatedDate> + <ModifiedDate>2016-07-22T11:52:19.603</ModifiedDate> + <ID>89344</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>shared_data_default</CustomerKey> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>0</ID> + <ObjectID xsi:nil="true" /> + </ParentFolder> + <Name>Shared Items</Name> + <Description /> + <ContentType>shared_data</ContentType> + <IsActive>true</IsActive> + <IsEditable>false</IsEditable> + <AllowChildren>false</AllowChildren> + </Results> + + </RetrieveResponseMsg> + </soap:Body> +</soap:Envelope> diff --git a/test/resources/9999999/dataFolder/retrieve-ContentTypeINdataextension,salesforcedataextension,shared_data,shared_dataextension,shared_salesforcedataextension,synchronizeddataextension-QAA-response.xml b/test/resources/9999999/dataFolder/retrieve-ContentTypeINdataextension,salesforcedataextension,shared_data,shared_dataextension,shared_salesforcedataextension,synchronizeddataextension-QAA-response.xml new file mode 100644 index 000000000..d51b42687 --- /dev/null +++ b/test/resources/9999999/dataFolder/retrieve-ContentTypeINdataextension,salesforcedataextension,shared_data,shared_dataextension,shared_salesforcedataextension,synchronizeddataextension-QAA-response.xml @@ -0,0 +1,117 @@ +<?xml version="1.0" encoding="utf-8"?> +<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:xsd="http://www.w3.org/2001/XMLSchema" + xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing" + xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" + xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"> + <soap:Header> + <wsa:Action>RetrieveResponse</wsa:Action> + <wsa:MessageID>urn:uuid:f36f3303-3b5a-4641-8109-b26447634d91</wsa:MessageID> + <wsa:RelatesTo>urn:uuid:33983968-28c4-4379-bb5f-f80ae32eb988</wsa:RelatesTo> + <wsa:To>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</wsa:To> + <wsse:Security> + <wsu:Timestamp wsu:Id="Timestamp-32ecc81b-6020-473c-9e99-4b5338921220"> + <wsu:Created>2022-04-19T20:03:41Z</wsu:Created> + <wsu:Expires>2022-04-19T20:08:41Z</wsu:Expires> + </wsu:Timestamp> + </wsse:Security> + </soap:Header> + <soap:Body> + <RetrieveResponseMsg xmlns="http://exacttarget.com/wsdl/partnerAPI"> + <OverallStatus>OK</OverallStatus> + <RequestID>02cd5ccb-8f84-4651-826f-71169eeecf05</RequestID> + <Results xsi:type="DataFolder"> + <Client> + <ID>9999999</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2016-07-22T11:52:19.6</CreatedDate> + <ModifiedDate>2016-07-22T11:52:19.6</ModifiedDate> + <ID>2</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>dataextension_default</CustomerKey> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>0</ID> + <ObjectID xsi:nil="true" /> + </ParentFolder> + <Name>Data Extensions</Name> + <Description /> + <ContentType>dataextension</ContentType> + <IsActive>true</IsActive> + <IsEditable>false</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>9999999</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2017-02-08T10:19:37.123</CreatedDate> + <ModifiedDate>2017-02-08T10:19:37.123</ModifiedDate> + <ID>386</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey /> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>2</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>dataextension_default</CustomerKey> + </ParentFolder> + <Name>Einstein</Name> + <Description /> + <ContentType>dataextension</ContentType> + <IsActive>true</IsActive> + <IsEditable>true</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>1111111</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2016-07-22T11:52:19.603</CreatedDate> + <ModifiedDate>2016-07-22T11:52:19.603</ModifiedDate> + <ID>89356</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>shared_dataextension_default</CustomerKey> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>89344</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>shared_data_default</CustomerKey> + </ParentFolder> + <Name>Shared Data Extensions</Name> + <Description /> + <ContentType>shared_dataextension</ContentType> + <IsActive>true</IsActive> + <IsEditable>false</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>1111111</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2016-07-22T11:52:18.73</CreatedDate> + <ModifiedDate>2016-07-22T11:52:19.603</ModifiedDate> + <ID>89344</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>shared_data_default</CustomerKey> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>0</ID> + <ObjectID xsi:nil="true" /> + </ParentFolder> + <Name>Shared Items</Name> + <Description /> + <ContentType>shared_data</ContentType> + <IsActive>true</IsActive> + <IsEditable>false</IsEditable> + <AllowChildren>false</AllowChildren> + </Results> + + </RetrieveResponseMsg> + </soap:Body> +</soap:Envelope> diff --git a/test/resources/9999999/dataFolder/retrieve-ContentTypeINfilteractivity,hidden-response.xml b/test/resources/9999999/dataFolder/retrieve-ContentTypeINfilteractivity,hidden-response.xml new file mode 100644 index 000000000..cf6e29988 --- /dev/null +++ b/test/resources/9999999/dataFolder/retrieve-ContentTypeINfilteractivity,hidden-response.xml @@ -0,0 +1,139 @@ +<?xml version="1.0" encoding="utf-8"?> +<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:xsd="http://www.w3.org/2001/XMLSchema" + xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing" + xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" + xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"> + <soap:Header> + <wsa:Action>RetrieveResponse</wsa:Action> + <wsa:MessageID>urn:uuid:75cc7360-d424-486e-b122-b5b491b697bc</wsa:MessageID> + <wsa:RelatesTo>urn:uuid:5f907880-a5dd-431e-8fe3-65cd04806e06</wsa:RelatesTo> + <wsa:To>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</wsa:To> + <wsse:Security> + <wsu:Timestamp wsu:Id="Timestamp-4c68bf94-5cbc-4cb7-a7bb-12cde6ec88e6"> + <wsu:Created>2026-02-02T08:57:49Z</wsu:Created> + <wsu:Expires>2026-02-02T09:02:49Z</wsu:Expires> + </wsu:Timestamp> + </wsse:Security> + </soap:Header> + <soap:Body> + <RetrieveResponseMsg xmlns="http://exacttarget.com/wsdl/partnerAPI"> + <OverallStatus>OK</OverallStatus> + <RequestID>0af64064-a1f2-4247-87d1-cd838f224360</RequestID> + <Results xsi:type="DataFolder"> + <Client> + <ID>9999999</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2022-06-21T09:34:31.84</CreatedDate> + <ModifiedDate>2022-06-21T09:34:31.84</ModifiedDate> + <ID>5319</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>filteractivity_default</CustomerKey> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>0</ID> + <ObjectID xsi:nil="true" /> + </ParentFolder> + <Name>Filter</Name> + <Description /> + <ContentType>filteractivity</ContentType> + <IsActive>true</IsActive> + <IsEditable>false</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>9999999</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2022-06-21T09:34:39.98</CreatedDate> + <ModifiedDate>2022-06-21T09:34:39.98</ModifiedDate> + <ID>90889</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>HiddenCategory_default</CustomerKey> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>0</ID> + <ObjectID xsi:nil="true" /> + </ParentFolder> + <Name>HiddenCategory</Name> + <Description>Hidden folder to store Hidden items</Description> + <ContentType>Hidden</ContentType> + <IsActive>true</IsActive> + <IsEditable>false</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>9999999</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2023-02-03T07:22:55.39</CreatedDate> + <ModifiedDate>2023-02-03T07:22:55.39</ModifiedDate> + <ID>8504</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>SystemHiddenFilterActivities_default</CustomerKey> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>90889</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>HiddenCategory_default</CustomerKey> + </ParentFolder> + <Name>SystemHiddenFilterActivities</Name> + <Description>filteractivity folder to store filteractivity items</Description> + <ContentType>filteractivity</ContentType> + <IsActive>true</IsActive> + <IsEditable>true</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>9999999</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2023-02-03T07:22:55.39</CreatedDate> + <ModifiedDate>2023-02-03T07:22:55.39</ModifiedDate> + <ID>8505</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>SystemHiddenFilterActivitiesForGE_de</CustomerKey> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>8504</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>SystemHiddenFilterActivities_default</CustomerKey> + </ParentFolder> + <Name>SystemHiddenFilterActivitiesForGE</Name> + <Description>filteractivity folder to store filteractivity items</Description> + <ContentType>filteractivity</ContentType> + <IsActive>true</IsActive> + <IsEditable>true</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>9999999</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2026-01-27T06:57:18.513</CreatedDate> + <ModifiedDate>2026-01-27T06:57:18.513</ModifiedDate> + <ID>37139</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey /> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>5319</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>filteractivity_default</CustomerKey> + </ParentFolder> + <Name>filterSubfolder</Name> + <Description>doesnt have a CustomerKey for some reason</Description> + <ContentType>filteractivity</ContentType> + <IsActive>true</IsActive> + <IsEditable>true</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + </RetrieveResponseMsg> + </soap:Body> +</soap:Envelope> diff --git a/test/resources/9999999/dataFolder/retrieve-ContentTypeINfilterdefinition,hidden-response.xml b/test/resources/9999999/dataFolder/retrieve-ContentTypeINfilterdefinition,hidden-response.xml new file mode 100644 index 000000000..f30878524 --- /dev/null +++ b/test/resources/9999999/dataFolder/retrieve-ContentTypeINfilterdefinition,hidden-response.xml @@ -0,0 +1,116 @@ +<?xml version="1.0" encoding="utf-8"?> +<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:xsd="http://www.w3.org/2001/XMLSchema" + xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing" + xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" + xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"> + <soap:Header> + <wsa:Action>RetrieveResponse</wsa:Action> + <wsa:MessageID>urn:uuid:08aa605a-0837-4c4a-9725-028e93720e77</wsa:MessageID> + <wsa:RelatesTo>urn:uuid:2da02491-3144-43ab-8ac4-349824d29db2</wsa:RelatesTo> + <wsa:To>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</wsa:To> + <wsse:Security> + <wsu:Timestamp wsu:Id="Timestamp-48ea9660-d7b7-4709-acff-f868467729bb"> + <wsu:Created>2026-01-30T11:58:58Z</wsu:Created> + <wsu:Expires>2026-01-30T12:03:58Z</wsu:Expires> + </wsu:Timestamp> + </wsse:Security> + </soap:Header> + <soap:Body> + <RetrieveResponseMsg xmlns="http://exacttarget.com/wsdl/partnerAPI"> + <OverallStatus>OK</OverallStatus> + <RequestID>8da38b8d-30d2-4c4a-a81e-e564915e7312</RequestID> + <Results xsi:type="DataFolder"> + <Client> + <ID>9999999</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2022-06-21T09:34:31.823</CreatedDate> + <ModifiedDate>2022-06-21T09:34:31.823</ModifiedDate> + <ID>5318</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>filterdefinition_default</CustomerKey> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>0</ID> + <ObjectID xsi:nil="true" /> + </ParentFolder> + <Name>Data Filters</Name> + <Description /> + <ContentType>filterdefinition</ContentType> + <IsActive>true</IsActive> + <IsEditable>false</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>9999999</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2022-06-21T09:34:39.98</CreatedDate> + <ModifiedDate>2022-06-21T09:34:39.98</ModifiedDate> + <ID>90889</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>HiddenCategory_default</CustomerKey> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>0</ID> + <ObjectID xsi:nil="true" /> + </ParentFolder> + <Name>HiddenCategory</Name> + <Description>Hidden folder to store Hidden items</Description> + <ContentType>Hidden</ContentType> + <IsActive>true</IsActive> + <IsEditable>false</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>9999999</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2023-02-03T07:22:55.39</CreatedDate> + <ModifiedDate>2023-02-03T07:22:55.39</ModifiedDate> + <ID>8502</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>SystemHiddenDataFilters_default</CustomerKey> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>90889</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>HiddenCategory_default</CustomerKey> + </ParentFolder> + <Name>SystemHiddenDataFilters</Name> + <Description>filterdefinition folder to store filterdefinition items</Description> + <ContentType>filterdefinition</ContentType> + <IsActive>true</IsActive> + <IsEditable>true</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>9999999</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2023-02-03T07:22:55.39</CreatedDate> + <ModifiedDate>2023-02-03T07:22:55.39</ModifiedDate> + <ID>8503</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>SystemHiddenDataFiltersForGE_default</CustomerKey> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>8502</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>SystemHiddenDataFilters_default</CustomerKey> + </ParentFolder> + <Name>SystemHiddenDataFiltersForGE</Name> + <Description>filterdefinition folder to store filterdefinition items</Description> + <ContentType>filterdefinition</ContentType> + <IsActive>true</IsActive> + <IsEditable>true</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + </RetrieveResponseMsg> + </soap:Body> +</soap:Envelope> diff --git a/test/resources/9999999/dataFolder/retrieve-ContentTypeINhidden,shared_data,shared_dataextension,shared_salesforcedataextension,synchronizeddataextension-response.xml b/test/resources/9999999/dataFolder/retrieve-ContentTypeINhidden,shared_data,shared_dataextension,shared_salesforcedataextension,synchronizeddataextension-response.xml new file mode 100644 index 000000000..c2d90ad4d --- /dev/null +++ b/test/resources/9999999/dataFolder/retrieve-ContentTypeINhidden,shared_data,shared_dataextension,shared_salesforcedataextension,synchronizeddataextension-response.xml @@ -0,0 +1,46 @@ +<?xml version="1.0" encoding="utf-8"?> +<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:xsd="http://www.w3.org/2001/XMLSchema" + xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing" + xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" + xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"> + <soap:Header> + <wsa:Action>RetrieveResponse</wsa:Action> + <wsa:MessageID>urn:uuid:f36f3303-3b5a-4641-8109-b26447634d91</wsa:MessageID> + <wsa:RelatesTo>urn:uuid:33983968-28c4-4379-bb5f-f80ae32eb988</wsa:RelatesTo> + <wsa:To>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</wsa:To> + <wsse:Security> + <wsu:Timestamp wsu:Id="Timestamp-32ecc81b-6020-473c-9e99-4b5338921220"> + <wsu:Created>2022-04-19T20:03:41Z</wsu:Created> + <wsu:Expires>2022-04-19T20:08:41Z</wsu:Expires> + </wsu:Timestamp> + </wsse:Security> + </soap:Header> + <soap:Body> + <RetrieveResponseMsg xmlns="http://exacttarget.com/wsdl/partnerAPI"> + <Results xsi:type="DataFolder"> + <Client> + <ID>9999999</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2016-07-29T12:13:27.28</CreatedDate> + <ModifiedDate>2016-07-29T12:13:27.28</ModifiedDate> + <ID>90889</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>HiddenCategory_default</CustomerKey> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>0</ID> + <ObjectID xsi:nil="true" /> + </ParentFolder> + <Name>HiddenCategory</Name> + <Description>Hidden folder to store Hidden items</Description> + <ContentType>Hidden</ContentType> + <IsActive>true</IsActive> + <IsEditable>false</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + </RetrieveResponseMsg> + </soap:Body> +</soap:Envelope> diff --git a/test/resources/9999999/dataFolder/retrieve-ContentTypeINhidden,triggered_send,triggered_send_journeybuilder-response.xml b/test/resources/9999999/dataFolder/retrieve-ContentTypeINhidden,triggered_send,triggered_send_journeybuilder-response.xml new file mode 100644 index 000000000..9bbdc78be --- /dev/null +++ b/test/resources/9999999/dataFolder/retrieve-ContentTypeINhidden,triggered_send,triggered_send_journeybuilder-response.xml @@ -0,0 +1,276 @@ +<?xml version="1.0" encoding="utf-8"?> +<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:xsd="http://www.w3.org/2001/XMLSchema" + xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing" + xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" + xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"> + <soap:Header> + <wsa:Action>RetrieveResponse</wsa:Action> + <wsa:MessageID>urn:uuid:d626d883-8ca4-4cd1-b4ea-cb399015e275</wsa:MessageID> + <wsa:RelatesTo>urn:uuid:b1d23385-97c0-4bc8-b0fe-b54e3310ae6b</wsa:RelatesTo> + <wsa:To>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</wsa:To> + <wsse:Security> + <wsu:Timestamp wsu:Id="Timestamp-a9582e47-b23f-4956-85b1-fe0b7fa73cf2"> + <wsu:Created>2023-08-08T12:49:16Z</wsu:Created> + <wsu:Expires>2023-08-08T12:54:16Z</wsu:Expires> + </wsu:Timestamp> + </wsse:Security> + </soap:Header> + <soap:Body> + <RetrieveResponseMsg xmlns="http://exacttarget.com/wsdl/partnerAPI"> + <OverallStatus>OK</OverallStatus> + <RequestID>6e8873dd-03e2-47b6-823a-fb8681d93d78</RequestID> + <Results xsi:type="DataFolder"> + <Client> + <ID>9999999</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2016-07-22T11:52:19.28</CreatedDate> + <ModifiedDate>2016-07-22T11:52:19.28</ModifiedDate> + <ID>89348</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>triggered_send_default</CustomerKey> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>0</ID> + <ObjectID xsi:nil="true" /> + </ParentFolder> + <Name>Triggered Sends</Name> + <Description /> + <ContentType>triggered_send</ContentType> + <IsActive>true</IsActive> + <IsEditable>false</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>9999999</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2016-07-22T11:52:34.983</CreatedDate> + <ModifiedDate>2016-07-22T11:52:34.983</ModifiedDate> + <ID>89396</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>triggered_send_journeybuilder</CustomerKey> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>0</ID> + <ObjectID xsi:nil="true" /> + </ParentFolder> + <Name>Journey Builder Sends</Name> + <Description /> + <ContentType>triggered_send_journeybuilder</ContentType> + <IsActive>true</IsActive> + <IsEditable>false</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>9999999</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2016-07-29T12:13:27.28</CreatedDate> + <ModifiedDate>2016-07-29T12:13:27.28</ModifiedDate> + <ID>90889</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>HiddenCategory_default</CustomerKey> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>0</ID> + <ObjectID xsi:nil="true" /> + </ParentFolder> + <Name>HiddenCategory</Name> + <Description>Hidden folder to store Hidden items</Description> + <ContentType>Hidden</ContentType> + <IsActive>true</IsActive> + <IsEditable>false</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>9999999</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2016-08-25T10:04:09.12</CreatedDate> + <ModifiedDate>2016-08-25T10:04:09.12</ModifiedDate> + <ID>94030</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey /> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>89396</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>triggered_send_journeybuilder</CustomerKey> + </ParentFolder> + <Name>Satisfaction Score Survey</Name> + <Description /> + <ContentType>triggered_send_journeybuilder</ContentType> + <IsActive>true</IsActive> + <IsEditable>true</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>9999999</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2016-08-25T10:04:09.133</CreatedDate> + <ModifiedDate>2016-08-25T10:04:09.133</ModifiedDate> + <ID>94031</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey /> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>94030</ID> + <ObjectID xsi:nil="true" /> + </ParentFolder> + <Name>Version 1</Name> + <Description /> + <ContentType>triggered_send_journeybuilder</ContentType> + <IsActive>true</IsActive> + <IsEditable>true</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>9999999</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2021-06-09T10:17:06.27</CreatedDate> + <ModifiedDate>2021-06-09T10:17:06.27</ModifiedDate> + <ID>664654</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>6aa28490-6577-4cb2-8eac-fd5e4f983cae</CustomerKey> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>317169</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>HiddenJourneyBuilderTriggeredSends_d</CustomerKey> + </ParentFolder> + <Name>6aa28490-6577-4cb2-8eac-fd5e4f983cae_V9</Name> + <Description>triggered_send folder to store triggered_send items</Description> + <ContentType>triggered_send</ContentType> + <IsActive>true</IsActive> + <IsEditable>true</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>9999999</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2022-07-31T19:55:31.657</CreatedDate> + <ModifiedDate>2022-07-31T19:55:31.657</ModifiedDate> + <ID>742869</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>77211381-9967-4472-bd12-f58d4d5952a1</CustomerKey> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>317169</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>HiddenJourneyBuilderTriggeredSends_d</CustomerKey> + </ParentFolder> + <Name>77211381-9967-4472-bd12-f58d4d5952a1_V1</Name> + <Description>triggered_send folder to store triggered_send items</Description> + <ContentType>triggered_send</ContentType> + <IsActive>true</IsActive> + <IsEditable>true</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>9999999</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2022-07-31T19:56:51.297</CreatedDate> + <ModifiedDate>2022-07-31T19:56:51.297</ModifiedDate> + <ID>742871</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>HiddenJourneyBuilderSimulationTrigge</CustomerKey> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>90889</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>HiddenCategory_default</CustomerKey> + </ParentFolder> + <Name>HiddenJourneyBuilderSimulationTriggeredSends</Name> + <Description>triggered_send_journeybuilder folder to store triggered_send_journeybuilder items</Description> + <ContentType>triggered_send_journeybuilder</ContentType> + <IsActive>true</IsActive> + <IsEditable>true</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>9999999</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2023-03-08T10:26:55.787</CreatedDate> + <ModifiedDate>2023-03-08T10:26:55.787</ModifiedDate> + <ID>771879</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>8c24f428-4da8-4df6-97a7-beba5166c3c7</CustomerKey> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>317169</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>HiddenJourneyBuilderTriggeredSends_d</CustomerKey> + </ParentFolder> + <Name>8c24f428-4da8-4df6-97a7-beba5166c3c7_V1</Name> + <Description>triggered_send folder to store triggered_send items</Description> + <ContentType>triggered_send</ContentType> + <IsActive>true</IsActive> + <IsEditable>true</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>9999999</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2023-04-10T15:46:09.947</CreatedDate> + <ModifiedDate>2023-04-10T15:46:09.947</ModifiedDate> + <ID>776623</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>0a85b483-4208-4377-87fb-25794f5df244</CustomerKey> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>317169</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>HiddenJourneyBuilderTriggeredSends_d</CustomerKey> + </ParentFolder> + <Name>0a85b483-4208-4377-87fb-25794f5df244_V1</Name> + <Description>triggered_send folder to store triggered_send items</Description> + <ContentType>triggered_send</ContentType> + <IsActive>true</IsActive> + <IsEditable>true</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>9999999</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2020-03-06T07:57:37.633</CreatedDate> + <ModifiedDate>2020-03-06T07:57:37.633</ModifiedDate> + <ID>317169</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>HiddenJourneyBuilderTriggeredSends_d</CustomerKey> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>90889</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>HiddenCategory_default</CustomerKey> + </ParentFolder> + <Name>HiddenJourneyBuilderTriggeredSends</Name> + <Description>triggered_send folder to store triggered_send items</Description> + <ContentType>triggered_send</ContentType> + <IsActive>true</IsActive> + <IsEditable>true</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + + </RetrieveResponseMsg> + </soap:Body> +</soap:Envelope> diff --git a/test/resources/9999999/dataFolder/retrieve-ContentTypeINshared_data,shared_dataextension,shared_salesforcedataextension,synchronizeddataextension-QAA-response.xml b/test/resources/9999999/dataFolder/retrieve-ContentTypeINshared_data,shared_dataextension,shared_salesforcedataextension,synchronizeddataextension-QAA-response.xml new file mode 100644 index 000000000..ffa795de7 --- /dev/null +++ b/test/resources/9999999/dataFolder/retrieve-ContentTypeINshared_data,shared_dataextension,shared_salesforcedataextension,synchronizeddataextension-QAA-response.xml @@ -0,0 +1,251 @@ +<?xml version="1.0" encoding="utf-8"?> +<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:xsd="http://www.w3.org/2001/XMLSchema" + xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing" + xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" + xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"> + <soap:Header> + <wsa:Action>RetrieveResponse</wsa:Action> + <wsa:MessageID>urn:uuid:4d209b2f-d7ce-4e6e-916c-c8642d368866</wsa:MessageID> + <wsa:RelatesTo>urn:uuid:a850f043-1422-4d16-8443-702dd2f9f13a</wsa:RelatesTo> + <wsa:To>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</wsa:To> + <wsse:Security> + <wsu:Timestamp wsu:Id="Timestamp-5da63531-caa7-4ead-9f10-a33d9bf66745"> + <wsu:Created>2023-08-11T13:15:46Z</wsu:Created> + <wsu:Expires>2023-08-11T13:20:46Z</wsu:Expires> + </wsu:Timestamp> + </wsse:Security> + </soap:Header> + <soap:Body> + <RetrieveResponseMsg xmlns="http://exacttarget.com/wsdl/partnerAPI"> + <OverallStatus>OK</OverallStatus> + <RequestID>ba1b0c59-78c4-4608-8423-35dda2248d4d</RequestID> + <Results xsi:type="DataFolder"> + <Client> + <ID>1111111</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2016-07-22T11:52:18.73</CreatedDate> + <ModifiedDate>2016-07-22T11:52:19.603</ModifiedDate> + <ID>89344</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>shared_data_default</CustomerKey> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>0</ID> + <ObjectID xsi:nil="true" /> + </ParentFolder> + <Name>Shared Items</Name> + <Description /> + <ContentType>shared_data</ContentType> + <IsActive>true</IsActive> + <IsEditable>false</IsEditable> + <AllowChildren>false</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>1111111</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2016-07-22T11:52:19.603</CreatedDate> + <ModifiedDate>2016-07-22T11:52:19.603</ModifiedDate> + <ID>89356</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>shared_dataextension_default</CustomerKey> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>89344</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>shared_data_default</CustomerKey> + </ParentFolder> + <Name>Shared Data Extensions</Name> + <Description /> + <ContentType>shared_dataextension</ContentType> + <IsActive>true</IsActive> + <IsEditable>false</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>1111111</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2016-07-29T12:13:27.28</CreatedDate> + <ModifiedDate>2016-07-29T12:13:27.28</ModifiedDate> + <ID>90889</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>HiddenCategory_default</CustomerKey> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>0</ID> + <ObjectID xsi:nil="true" /> + </ParentFolder> + <Name>HiddenCategory</Name> + <Description>Hidden folder to store Hidden items</Description> + <ContentType>Hidden</ContentType> + <IsActive>true</IsActive> + <IsEditable>false</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>1111111</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2016-08-23T09:22:27.55</CreatedDate> + <ModifiedDate>2016-08-23T09:22:27.55</ModifiedDate> + <ID>93699</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>shared_salesforcedataextension_defau</CustomerKey> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>89344</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>shared_data_default</CustomerKey> + </ParentFolder> + <Name>Shared Salesforce Data Extensions</Name> + <Description /> + <ContentType>shared_salesforcedataextension</ContentType> + <IsActive>true</IsActive> + <IsEditable>false</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>1111111</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2020-04-17T08:14:19.763</CreatedDate> + <ModifiedDate>2020-04-17T08:14:19.763</ModifiedDate> + <ID>587750</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey /> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>89356</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>shared_dataextension_default</CustomerKey> + </ParentFolder> + <Name>catalyst target 1</Name> + <Description /> + <ContentType>shared_dataextension</ContentType> + <IsActive>true</IsActive> + <IsEditable>true</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>1111111</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2021-01-30T11:54:36.11</CreatedDate> + <ModifiedDate>2021-01-30T11:54:36.11</ModifiedDate> + <ID>638814</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>0b72bf27-0678-484d-ac0b-a8762b9bec33</CustomerKey> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>89356</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>shared_dataextension_default</CustomerKey> + </ParentFolder> + <Name>Customer 360 Segments</Name> + <Description>All Customer 360 segments will be grouped here. Each sub-folder relates to an activation profile name.</Description> + <ContentType>shared_dataextension</ContentType> + <IsActive>true</IsActive> + <IsEditable>false</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>1111111</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2021-01-30T11:56:38.77</CreatedDate> + <ModifiedDate>2021-01-30T11:56:38.77</ModifiedDate> + <ID>638815</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>cedd206d-178e-41cb-8965-ce255975b046</CustomerKey> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>638814</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>0b72bf27-0678-484d-ac0b-a8762b9bec33</CustomerKey> + </ParentFolder> + <Name>FirstAudience360 Segment</Name> + <Description /> + <ContentType>shared_dataextension</ContentType> + <IsActive>true</IsActive> + <IsEditable>false</IsEditable> + <AllowChildren>false</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>1111111</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2021-08-04T15:17:18.533</CreatedDate> + <ModifiedDate>2021-08-04T15:17:18.567</ModifiedDate> + <ID>675203</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>A19F7E38-7369-497E-826F-D551F17FB0B4</CustomerKey> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>0</ID> + <ObjectID xsi:nil="true" /> + </ParentFolder> + <Name>Synchronized Data Extensions</Name> + <Description /> + <ContentType>synchronizeddataextension</ContentType> + <IsActive>true</IsActive> + <IsEditable>false</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>1111111</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2021-10-03T05:01:37.23</CreatedDate> + <ModifiedDate>2021-10-03T05:01:37.37</ModifiedDate> + <ID>688352</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>B80AE306-55BC-4C2E-A79F-8CCA486F0BA0</CustomerKey> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>0</ID> + <ObjectID xsi:nil="true" /> + </ParentFolder> + <Name>Synchronized Data Extensions</Name> + <Description /> + <ContentType>synchronizeddataextension</ContentType> + <IsActive>true</IsActive> + <IsEditable>false</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>1111111</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2022-10-26T09:48:38.293</CreatedDate> + <ModifiedDate>2022-10-26T09:48:38.31</ModifiedDate> + <ID>757145</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>0ACB800B-AA8B-4F0F-9642-4907592C919C</CustomerKey> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>0</ID> + <ObjectID xsi:nil="true" /> + </ParentFolder> + <Name>Synchronized Data Extensions</Name> + <Description /> + <ContentType>synchronizeddataextension</ContentType> + <IsActive>true</IsActive> + <IsEditable>false</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + </RetrieveResponseMsg> + </soap:Body> +</soap:Envelope> diff --git a/test/resources/9999999/dataFolder/retrieve-QAA-response.xml b/test/resources/9999999/dataFolder/retrieve-QAA-response.xml new file mode 100644 index 000000000..41bb03f59 --- /dev/null +++ b/test/resources/9999999/dataFolder/retrieve-QAA-response.xml @@ -0,0 +1,387 @@ +<?xml version="1.0" encoding="utf-8"?> +<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:xsd="http://www.w3.org/2001/XMLSchema" + xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing" + xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" + xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"> + <soap:Header> + <wsa:Action>RetrieveResponse</wsa:Action> + <wsa:MessageID>urn:uuid:4d209b2f-d7ce-4e6e-916c-c8642d368866</wsa:MessageID> + <wsa:RelatesTo>urn:uuid:a850f043-1422-4d16-8443-702dd2f9f13a</wsa:RelatesTo> + <wsa:To>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</wsa:To> + <wsse:Security> + <wsu:Timestamp wsu:Id="Timestamp-5da63531-caa7-4ead-9f10-a33d9bf66745"> + <wsu:Created>2023-08-11T13:15:46Z</wsu:Created> + <wsu:Expires>2023-08-11T13:20:46Z</wsu:Expires> + </wsu:Timestamp> + </wsse:Security> + </soap:Header> + <soap:Body> + <RetrieveResponseMsg xmlns="http://exacttarget.com/wsdl/partnerAPI"> + <OverallStatus>OK</OverallStatus> + <RequestID>ba1b0c59-78c4-4608-8423-35dda2248d4d</RequestID> + <Results xsi:type="DataFolder"> + <Client> + <ID>1111111</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2016-07-22T11:52:18.73</CreatedDate> + <ModifiedDate>2016-07-22T11:52:19.603</ModifiedDate> + <ID>89344</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>shared_data_default</CustomerKey> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>0</ID> + <ObjectID xsi:nil="true" /> + </ParentFolder> + <Name>Shared Items</Name> + <Description /> + <ContentType>shared_data</ContentType> + <IsActive>true</IsActive> + <IsEditable>false</IsEditable> + <AllowChildren>false</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>1111111</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2016-07-22T11:52:19.6</CreatedDate> + <ModifiedDate>2016-07-22T11:52:19.6</ModifiedDate> + <ID>89355</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>dataextension_default</CustomerKey> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>0</ID> + <ObjectID xsi:nil="true" /> + </ParentFolder> + <Name>Data Extensions</Name> + <Description /> + <ContentType>dataextension</ContentType> + <IsActive>true</IsActive> + <IsEditable>false</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>1111111</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2016-07-22T11:52:19.603</CreatedDate> + <ModifiedDate>2016-07-22T11:52:19.603</ModifiedDate> + <ID>89356</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>shared_dataextension_default</CustomerKey> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>89344</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>shared_data_default</CustomerKey> + </ParentFolder> + <Name>Shared Data Extensions</Name> + <Description /> + <ContentType>shared_dataextension</ContentType> + <IsActive>true</IsActive> + <IsEditable>false</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>1111111</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2016-07-29T12:13:27.28</CreatedDate> + <ModifiedDate>2016-07-29T12:13:27.28</ModifiedDate> + <ID>90889</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>HiddenCategory_default</CustomerKey> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>0</ID> + <ObjectID xsi:nil="true" /> + </ParentFolder> + <Name>HiddenCategory</Name> + <Description>Hidden folder to store Hidden items</Description> + <ContentType>Hidden</ContentType> + <IsActive>true</IsActive> + <IsEditable>false</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>1111111</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2016-08-23T09:22:27.54</CreatedDate> + <ModifiedDate>2016-08-23T09:22:27.54</ModifiedDate> + <ID>93698</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>salesforcedataextension_default</CustomerKey> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>0</ID> + <ObjectID xsi:nil="true" /> + </ParentFolder> + <Name>Salesforce Data Extensions</Name> + <Description /> + <ContentType>salesforcedataextension</ContentType> + <IsActive>true</IsActive> + <IsEditable>false</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>1111111</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2016-08-23T09:22:27.55</CreatedDate> + <ModifiedDate>2016-08-23T09:22:27.55</ModifiedDate> + <ID>93699</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>shared_salesforcedataextension_defau</CustomerKey> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>89344</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>shared_data_default</CustomerKey> + </ParentFolder> + <Name>Shared Salesforce Data Extensions</Name> + <Description /> + <ContentType>shared_salesforcedataextension</ContentType> + <IsActive>true</IsActive> + <IsEditable>false</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>1111111</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2020-01-27T10:50:46.573</CreatedDate> + <ModifiedDate>2020-01-27T10:50:46.573</ModifiedDate> + <ID>309082</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey /> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>89355</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>dataextension_default</CustomerKey> + </ParentFolder> + <Name>QueryStudioResults</Name> + <Description /> + <ContentType>dataextension</ContentType> + <IsActive>true</IsActive> + <IsEditable>true</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>1111111</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2020-04-17T08:14:19.763</CreatedDate> + <ModifiedDate>2020-04-17T08:14:19.763</ModifiedDate> + <ID>587750</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey /> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>89356</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>shared_dataextension_default</CustomerKey> + </ParentFolder> + <Name>catalyst target 1</Name> + <Description /> + <ContentType>shared_dataextension</ContentType> + <IsActive>true</IsActive> + <IsEditable>true</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>1111111</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2020-07-09T02:30:12.38</CreatedDate> + <ModifiedDate>2021-12-16T03:43:30.753</ModifiedDate> + <ID>605618</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>dataextension_default</CustomerKey> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>89355</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>dataextension_default</CustomerKey> + </ParentFolder> + <Name>Audiences</Name> + <Description /> + <ContentType>dataextension</ContentType> + <IsActive>true</IsActive> + <IsEditable>true</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>1111111</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2020-12-25T06:11:40.107</CreatedDate> + <ModifiedDate>2021-12-23T10:51:24.393</ModifiedDate> + <ID>633441</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey /> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>89355</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>dataextension_default</CustomerKey> + </ParentFolder> + <Name>System DEs</Name> + <Description /> + <ContentType>dataextension</ContentType> + <IsActive>true</IsActive> + <IsEditable>true</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>1111111</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2021-01-30T11:54:36.11</CreatedDate> + <ModifiedDate>2021-01-30T11:54:36.11</ModifiedDate> + <ID>638814</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>0b72bf27-0678-484d-ac0b-a8762b9bec33</CustomerKey> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>89356</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>shared_dataextension_default</CustomerKey> + </ParentFolder> + <Name>Customer 360 Segments</Name> + <Description>All Customer 360 segments will be grouped here. Each sub-folder relates to an activation profile name.</Description> + <ContentType>shared_dataextension</ContentType> + <IsActive>true</IsActive> + <IsEditable>false</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>1111111</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2021-01-30T11:56:38.77</CreatedDate> + <ModifiedDate>2021-01-30T11:56:38.77</ModifiedDate> + <ID>638815</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>cedd206d-178e-41cb-8965-ce255975b046</CustomerKey> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>638814</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>0b72bf27-0678-484d-ac0b-a8762b9bec33</CustomerKey> + </ParentFolder> + <Name>FirstAudience360 Segment</Name> + <Description /> + <ContentType>shared_dataextension</ContentType> + <IsActive>true</IsActive> + <IsEditable>false</IsEditable> + <AllowChildren>false</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>1111111</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2021-02-07T10:44:01.413</CreatedDate> + <ModifiedDate>2021-12-16T03:43:33.38</ModifiedDate> + <ID>639967</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey /> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>89355</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>dataextension_default</CustomerKey> + </ParentFolder> + <Name>TestAudiences</Name> + <Description /> + <ContentType>dataextension</ContentType> + <IsActive>true</IsActive> + <IsEditable>true</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>1111111</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2021-08-04T15:17:18.533</CreatedDate> + <ModifiedDate>2021-08-04T15:17:18.567</ModifiedDate> + <ID>675203</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>A19F7E38-7369-497E-826F-D551F17FB0B4</CustomerKey> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>0</ID> + <ObjectID xsi:nil="true" /> + </ParentFolder> + <Name>Synchronized Data Extensions</Name> + <Description /> + <ContentType>synchronizeddataextension</ContentType> + <IsActive>true</IsActive> + <IsEditable>false</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>1111111</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2021-10-03T05:01:37.23</CreatedDate> + <ModifiedDate>2021-10-03T05:01:37.37</ModifiedDate> + <ID>688352</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>B80AE306-55BC-4C2E-A79F-8CCA486F0BA0</CustomerKey> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>0</ID> + <ObjectID xsi:nil="true" /> + </ParentFolder> + <Name>Synchronized Data Extensions</Name> + <Description /> + <ContentType>synchronizeddataextension</ContentType> + <IsActive>true</IsActive> + <IsEditable>false</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>1111111</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2022-10-26T09:48:38.293</CreatedDate> + <ModifiedDate>2022-10-26T09:48:38.31</ModifiedDate> + <ID>757145</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>0ACB800B-AA8B-4F0F-9642-4907592C919C</CustomerKey> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>0</ID> + <ObjectID xsi:nil="true" /> + </ParentFolder> + <Name>Synchronized Data Extensions</Name> + <Description /> + <ContentType>synchronizeddataextension</ContentType> + <IsActive>true</IsActive> + <IsEditable>false</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + </RetrieveResponseMsg> + </soap:Body> +</soap:Envelope> diff --git a/test/resources/9999999/dataFolder/retrieve-response.xml b/test/resources/9999999/dataFolder/retrieve-response.xml new file mode 100644 index 000000000..8837c53ca --- /dev/null +++ b/test/resources/9999999/dataFolder/retrieve-response.xml @@ -0,0 +1,542 @@ +<?xml version="1.0" encoding="utf-8"?> +<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:xsd="http://www.w3.org/2001/XMLSchema" + xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing" + xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" + xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"> + <soap:Header> + <wsa:Action>RetrieveResponse</wsa:Action> + <wsa:MessageID>urn:uuid:f36f3303-3b5a-4641-8109-b26447634d91</wsa:MessageID> + <wsa:RelatesTo>urn:uuid:33983968-28c4-4379-bb5f-f80ae32eb988</wsa:RelatesTo> + <wsa:To>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</wsa:To> + <wsse:Security> + <wsu:Timestamp wsu:Id="Timestamp-32ecc81b-6020-473c-9e99-4b5338921220"> + <wsu:Created>2022-04-19T20:03:41Z</wsu:Created> + <wsu:Expires>2022-04-19T20:08:41Z</wsu:Expires> + </wsu:Timestamp> + </wsse:Security> + </soap:Header> + <soap:Body> + <RetrieveResponseMsg xmlns="http://exacttarget.com/wsdl/partnerAPI"> + <OverallStatus>OK</OverallStatus> + <RequestID>02cd5ccb-8f84-4651-826f-71169eeecf05</RequestID> + <Results xsi:type="DataFolder"> + <Client> + <ID>9999999</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2016-07-22T11:52:19.6</CreatedDate> + <ModifiedDate>2016-07-22T11:52:19.6</ModifiedDate> + <ID>2</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>dataextension_default</CustomerKey> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>0</ID> + <ObjectID xsi:nil="true" /> + </ParentFolder> + <Name>Data Extensions</Name> + <Description /> + <ContentType>dataextension</ContentType> + <IsActive>true</IsActive> + <IsEditable>false</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>9999999</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2016-07-22T11:52:20.407</CreatedDate> + <ModifiedDate>2016-07-22T11:52:20.407</ModifiedDate> + <ID>999</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>queryactivity_default</CustomerKey> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>0</ID> + <ObjectID xsi:nil="true" /> + </ParentFolder> + <Name>Query</Name> + <Description /> + <ContentType>queryactivity</ContentType> + <IsActive>true</IsActive> + <IsEditable>false</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>9999999</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2017-02-16T01:59:27.18</CreatedDate> + <ModifiedDate>2017-02-16T01:59:27.18</ModifiedDate> + <ID>412</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>mysubs_default</CustomerKey> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>0</ID> + <ObjectID xsi:nil="true" /> + </ParentFolder> + <Name>my subscribers</Name> + <Description /> + <ContentType>mysubs</ContentType> + <IsActive>true</IsActive> + <IsEditable>false</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>9999999</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2017-02-16T01:59:27.177</CreatedDate> + <ModifiedDate>2017-02-16T01:59:27.177</ModifiedDate> + <ID>404</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>list_default</CustomerKey> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>0</ID> + <ObjectID xsi:nil="true" /> + </ParentFolder> + <Name>my lists</Name> + <Description /> + <ContentType>list</ContentType> + <IsActive>true</IsActive> + <IsEditable>false</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>9999999</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2017-02-16T01:59:34.023</CreatedDate> + <ModifiedDate>2017-02-16T01:59:34.023</ModifiedDate> + <ID>424</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>publication_default</CustomerKey> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>0</ID> + <ObjectID xsi:nil="true" /> + </ParentFolder> + <Name>Publication Lists</Name> + <Description /> + <ContentType>publication</ContentType> + <IsActive>true</IsActive> + <IsEditable>false</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>9999999</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2017-02-16T01:59:32.323</CreatedDate> + <ModifiedDate>2017-02-16T01:59:32.323</ModifiedDate> + <ID>419</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>suppression_list_default</CustomerKey> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>0</ID> + <ObjectID xsi:nil="true" /> + </ParentFolder> + <Name>Suppression Lists</Name> + <Description /> + <ContentType>suppression_list</ContentType> + <IsActive>true</IsActive> + <IsEditable>false</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>9999999</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2017-02-16T01:59:32.323</CreatedDate> + <ModifiedDate>2017-02-16T01:59:32.323</ModifiedDate> + <ID>6298</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>journey_default</CustomerKey> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>0</ID> + <ObjectID xsi:nil="true" /> + </ParentFolder> + <Name>my journeys</Name> + <Description>The root folder for Journeys</Description> + <ContentType>journey</ContentType> + <IsActive>true</IsActive> + <IsEditable>false</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>9999999</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2019-10-25T05:35:17.337</CreatedDate> + <ModifiedDate>2019-10-25T05:35:17.337</ModifiedDate> + <ID>290937</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey /> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>0</ID> + <ObjectID xsi:nil="true" /> + </ParentFolder> + <Name>my automations</Name> + <Description /> + <ContentType>automations</ContentType> + <IsActive>true</IsActive> + <IsEditable>true</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>9999999</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2017-02-08T10:19:37.123</CreatedDate> + <ModifiedDate>2017-02-08T10:19:37.123</ModifiedDate> + <ID>386</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey /> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>2</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>dataextension_default</CustomerKey> + </ParentFolder> + <Name>Einstein</Name> + <Description /> + <ContentType>dataextension</ContentType> + <IsActive>true</IsActive> + <IsEditable>true</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>9999999</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2017-02-08T10:19:37.123</CreatedDate> + <ModifiedDate>2017-02-08T10:19:37.123</ModifiedDate> + <ID>66666</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey /> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>2</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>dataextension_default</CustomerKey> + </ParentFolder> + <Name>testExisting_FOLDER</Name> + <Description /> + <ContentType>dataextension</ContentType> + <IsActive>true</IsActive> + <IsEditable>true</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>9999999</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2016-07-22T11:52:35.687</CreatedDate> + <ModifiedDate>2016-07-22T11:52:35.687</ModifiedDate> + <ID>89397</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey /> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>0</ID> + <ObjectID xsi:nil="true" /> + </ParentFolder> + <Name>Content Builder</Name> + <Description>The root folder for assets</Description> + <ContentType>asset</ContentType> + <IsActive>true</IsActive> + <IsEditable>false</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>9999999</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2016-07-29T12:13:07.7</CreatedDate> + <ModifiedDate>2021-12-16T02:56:14.68</ModifiedDate> + <ID>90888</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey /> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>89397</ID> + <ObjectID xsi:nil="true" /> + </ParentFolder> + <Name>Test Folder</Name> + <Description /> + <ContentType>asset</ContentType> + <IsActive>true</IsActive> + <IsEditable>true</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>9999999</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2016-07-22T11:52:19.28</CreatedDate> + <ModifiedDate>2016-07-22T11:52:19.28</ModifiedDate> + <ID>89348</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>triggered_send_default</CustomerKey> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>0</ID> + <ObjectID xsi:nil="true" /> + </ParentFolder> + <Name>Triggered Sends</Name> + <Description /> + <ContentType>triggered_send</ContentType> + <IsActive>true</IsActive> + <IsEditable>false</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>9999999</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2016-07-22T11:52:34.983</CreatedDate> + <ModifiedDate>2016-07-22T11:52:34.983</ModifiedDate> + <ID>89396</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>triggered_send_journeybuilder</CustomerKey> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>0</ID> + <ObjectID xsi:nil="true" /> + </ParentFolder> + <Name>Journey Builder Sends</Name> + <Description /> + <ContentType>triggered_send_journeybuilder</ContentType> + <IsActive>true</IsActive> + <IsEditable>false</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>9999999</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2016-07-29T12:13:27.28</CreatedDate> + <ModifiedDate>2016-07-29T12:13:27.28</ModifiedDate> + <ID>90889</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>HiddenCategory_default</CustomerKey> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>0</ID> + <ObjectID xsi:nil="true" /> + </ParentFolder> + <Name>HiddenCategory</Name> + <Description>Hidden folder to store Hidden items</Description> + <ContentType>Hidden</ContentType> + <IsActive>true</IsActive> + <IsEditable>false</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>9999999</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2016-08-25T10:04:09.12</CreatedDate> + <ModifiedDate>2016-08-25T10:04:09.12</ModifiedDate> + <ID>94030</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey /> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>89396</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>triggered_send_journeybuilder</CustomerKey> + </ParentFolder> + <Name>Satisfaction Score Survey</Name> + <Description /> + <ContentType>triggered_send_journeybuilder</ContentType> + <IsActive>true</IsActive> + <IsEditable>true</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>9999999</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2016-08-25T10:04:09.133</CreatedDate> + <ModifiedDate>2016-08-25T10:04:09.133</ModifiedDate> + <ID>94031</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey /> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>94030</ID> + <ObjectID xsi:nil="true" /> + </ParentFolder> + <Name>Version 1</Name> + <Description /> + <ContentType>triggered_send_journeybuilder</ContentType> + <IsActive>true</IsActive> + <IsEditable>true</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>9999999</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2021-06-09T10:17:06.27</CreatedDate> + <ModifiedDate>2021-06-09T10:17:06.27</ModifiedDate> + <ID>664654</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>6aa28490-6577-4cb2-8eac-fd5e4f983cae</CustomerKey> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>317169</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>HiddenJourneyBuilderTriggeredSends_d</CustomerKey> + </ParentFolder> + <Name>6aa28490-6577-4cb2-8eac-fd5e4f983cae_V9</Name> + <Description>triggered_send folder to store triggered_send items</Description> + <ContentType>triggered_send</ContentType> + <IsActive>true</IsActive> + <IsEditable>true</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>9999999</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2022-07-31T19:55:31.657</CreatedDate> + <ModifiedDate>2022-07-31T19:55:31.657</ModifiedDate> + <ID>742869</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>77211381-9967-4472-bd12-f58d4d5952a1</CustomerKey> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>317169</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>HiddenJourneyBuilderTriggeredSends_d</CustomerKey> + </ParentFolder> + <Name>77211381-9967-4472-bd12-f58d4d5952a1_V1</Name> + <Description>triggered_send folder to store triggered_send items</Description> + <ContentType>triggered_send</ContentType> + <IsActive>true</IsActive> + <IsEditable>true</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>9999999</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2022-07-31T19:56:51.297</CreatedDate> + <ModifiedDate>2022-07-31T19:56:51.297</ModifiedDate> + <ID>742871</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>HiddenJourneyBuilderSimulationTrigge</CustomerKey> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>90889</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>HiddenCategory_default</CustomerKey> + </ParentFolder> + <Name>HiddenJourneyBuilderSimulationTriggeredSends</Name> + <Description>triggered_send_journeybuilder folder to store triggered_send_journeybuilder items</Description> + <ContentType>triggered_send_journeybuilder</ContentType> + <IsActive>true</IsActive> + <IsEditable>true</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>9999999</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2023-03-08T10:26:55.787</CreatedDate> + <ModifiedDate>2023-03-08T10:26:55.787</ModifiedDate> + <ID>771879</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>8c24f428-4da8-4df6-97a7-beba5166c3c7</CustomerKey> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>317169</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>HiddenJourneyBuilderTriggeredSends_d</CustomerKey> + </ParentFolder> + <Name>8c24f428-4da8-4df6-97a7-beba5166c3c7_V1</Name> + <Description>triggered_send folder to store triggered_send items</Description> + <ContentType>triggered_send</ContentType> + <IsActive>true</IsActive> + <IsEditable>true</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>9999999</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2023-04-10T15:46:09.947</CreatedDate> + <ModifiedDate>2023-04-10T15:46:09.947</ModifiedDate> + <ID>776623</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>0a85b483-4208-4377-87fb-25794f5df244</CustomerKey> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>317169</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>HiddenJourneyBuilderTriggeredSends_d</CustomerKey> + </ParentFolder> + <Name>0a85b483-4208-4377-87fb-25794f5df244_V1</Name> + <Description>triggered_send folder to store triggered_send items</Description> + <ContentType>triggered_send</ContentType> + <IsActive>true</IsActive> + <IsEditable>true</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>9999999</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2020-03-06T07:57:37.633</CreatedDate> + <ModifiedDate>2020-03-06T07:57:37.633</ModifiedDate> + <ID>317169</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>HiddenJourneyBuilderTriggeredSends_d</CustomerKey> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>90889</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>HiddenCategory_default</CustomerKey> + </ParentFolder> + <Name>HiddenJourneyBuilderTriggeredSends</Name> + <Description>triggered_send folder to store triggered_send items</Description> + <ContentType>triggered_send</ContentType> + <IsActive>true</IsActive> + <IsEditable>true</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + + </RetrieveResponseMsg> + </soap:Body> +</soap:Envelope> diff --git a/test/resources/9999999/dataFolder/retrieve-samePathOtherBU-response.xml b/test/resources/9999999/dataFolder/retrieve-samePathOtherBU-response.xml new file mode 100644 index 000000000..feda90112 --- /dev/null +++ b/test/resources/9999999/dataFolder/retrieve-samePathOtherBU-response.xml @@ -0,0 +1,564 @@ +<?xml version="1.0" encoding="utf-8"?> +<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:xsd="http://www.w3.org/2001/XMLSchema" + xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing" + xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" + xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"> + <soap:Header> + <wsa:Action>RetrieveResponse</wsa:Action> + <wsa:MessageID>urn:uuid:f36f3303-3b5a-4641-8109-b26447634d91</wsa:MessageID> + <wsa:RelatesTo>urn:uuid:33983968-28c4-4379-bb5f-f80ae32eb988</wsa:RelatesTo> + <wsa:To>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</wsa:To> + <wsse:Security> + <wsu:Timestamp wsu:Id="Timestamp-32ecc81b-6020-473c-9e99-4b5338921220"> + <wsu:Created>2022-04-19T20:03:41Z</wsu:Created> + <wsu:Expires>2022-04-19T20:08:41Z</wsu:Expires> + </wsu:Timestamp> + </wsse:Security> + </soap:Header> + <soap:Body> + <RetrieveResponseMsg xmlns="http://exacttarget.com/wsdl/partnerAPI"> + <OverallStatus>OK</OverallStatus> + <RequestID>02cd5ccb-8f84-4651-826f-71169eeecf05</RequestID> + <Results xsi:type="DataFolder"> + <Client> + <ID>9999999</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2016-07-22T11:52:19.6</CreatedDate> + <ModifiedDate>2016-07-22T11:52:19.6</ModifiedDate> + <ID>2</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>dataextension_default</CustomerKey> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>0</ID> + <ObjectID xsi:nil="true" /> + </ParentFolder> + <Name>Data Extensions</Name> + <Description /> + <ContentType>dataextension</ContentType> + <IsActive>true</IsActive> + <IsEditable>false</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>9999999</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2016-07-22T11:52:20.407</CreatedDate> + <ModifiedDate>2016-07-22T11:52:20.407</ModifiedDate> + <ID>999</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>queryactivity_default</CustomerKey> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>0</ID> + <ObjectID xsi:nil="true" /> + </ParentFolder> + <Name>Query</Name> + <Description /> + <ContentType>queryactivity</ContentType> + <IsActive>true</IsActive> + <IsEditable>false</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>9999999</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2017-02-16T01:59:27.18</CreatedDate> + <ModifiedDate>2017-02-16T01:59:27.18</ModifiedDate> + <ID>412</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>mysubs_default</CustomerKey> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>0</ID> + <ObjectID xsi:nil="true" /> + </ParentFolder> + <Name>my subscribers</Name> + <Description /> + <ContentType>mysubs</ContentType> + <IsActive>true</IsActive> + <IsEditable>false</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>9999999</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2017-02-16T01:59:27.177</CreatedDate> + <ModifiedDate>2017-02-16T01:59:27.177</ModifiedDate> + <ID>404</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>list_default</CustomerKey> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>0</ID> + <ObjectID xsi:nil="true" /> + </ParentFolder> + <Name>my lists</Name> + <Description /> + <ContentType>list</ContentType> + <IsActive>true</IsActive> + <IsEditable>false</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>9999999</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2017-02-16T01:59:34.023</CreatedDate> + <ModifiedDate>2017-02-16T01:59:34.023</ModifiedDate> + <ID>424</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>publication_default</CustomerKey> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>0</ID> + <ObjectID xsi:nil="true" /> + </ParentFolder> + <Name>Publication Lists</Name> + <Description /> + <ContentType>publication</ContentType> + <IsActive>true</IsActive> + <IsEditable>false</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>9999999</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2017-02-16T01:59:32.323</CreatedDate> + <ModifiedDate>2017-02-16T01:59:32.323</ModifiedDate> + <ID>419</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>suppression_list_default</CustomerKey> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>0</ID> + <ObjectID xsi:nil="true" /> + </ParentFolder> + <Name>Suppression Lists</Name> + <Description /> + <ContentType>suppression_list</ContentType> + <IsActive>true</IsActive> + <IsEditable>false</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>9999999</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2017-02-16T01:59:32.323</CreatedDate> + <ModifiedDate>2017-02-16T01:59:32.323</ModifiedDate> + <ID>6298</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>journey_default</CustomerKey> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>0</ID> + <ObjectID xsi:nil="true" /> + </ParentFolder> + <Name>my journeys</Name> + <Description>The root folder for Journeys</Description> + <ContentType>journey</ContentType> + <IsActive>true</IsActive> + <IsEditable>false</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>9999999</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2019-10-25T05:35:17.337</CreatedDate> + <ModifiedDate>2019-10-25T05:35:17.337</ModifiedDate> + <ID>290937</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey /> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>0</ID> + <ObjectID xsi:nil="true" /> + </ParentFolder> + <Name>my automations</Name> + <Description /> + <ContentType>automations</ContentType> + <IsActive>true</IsActive> + <IsEditable>true</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>9999999</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2017-02-08T10:19:37.123</CreatedDate> + <ModifiedDate>2017-02-08T10:19:37.123</ModifiedDate> + <ID>386</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey /> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>2</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>dataextension_default</CustomerKey> + </ParentFolder> + <Name>Einstein</Name> + <Description /> + <ContentType>dataextension</ContentType> + <IsActive>true</IsActive> + <IsEditable>true</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>9999999</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2017-02-08T10:19:37.123</CreatedDate> + <ModifiedDate>2017-02-08T10:19:37.123</ModifiedDate> + <ID>66666</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey /> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>2</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>dataextension_default</CustomerKey> + </ParentFolder> + <Name>testExisting_FOLDER</Name> + <Description /> + <ContentType>dataextension</ContentType> + <IsActive>true</IsActive> + <IsEditable>true</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>9999999</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2016-07-22T11:52:35.687</CreatedDate> + <ModifiedDate>2016-07-22T11:52:35.687</ModifiedDate> + <ID>89397</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey /> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>0</ID> + <ObjectID xsi:nil="true" /> + </ParentFolder> + <Name>Content Builder</Name> + <Description>The root folder for assets</Description> + <ContentType>asset</ContentType> + <IsActive>true</IsActive> + <IsEditable>false</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>9999999</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2016-07-29T12:13:07.7</CreatedDate> + <ModifiedDate>2021-12-16T02:56:14.68</ModifiedDate> + <ID>90888</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey /> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>89397</ID> + <ObjectID xsi:nil="true" /> + </ParentFolder> + <Name>Test Folder</Name> + <Description /> + <ContentType>asset</ContentType> + <IsActive>true</IsActive> + <IsEditable>true</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>9999999</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2016-07-22T11:52:19.28</CreatedDate> + <ModifiedDate>2016-07-22T11:52:19.28</ModifiedDate> + <ID>89348</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>triggered_send_default</CustomerKey> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>0</ID> + <ObjectID xsi:nil="true" /> + </ParentFolder> + <Name>Triggered Sends</Name> + <Description /> + <ContentType>triggered_send</ContentType> + <IsActive>true</IsActive> + <IsEditable>false</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>9999999</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2016-07-22T11:52:34.983</CreatedDate> + <ModifiedDate>2016-07-22T11:52:34.983</ModifiedDate> + <ID>89396</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>triggered_send_journeybuilder</CustomerKey> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>0</ID> + <ObjectID xsi:nil="true" /> + </ParentFolder> + <Name>Journey Builder Sends</Name> + <Description /> + <ContentType>triggered_send_journeybuilder</ContentType> + <IsActive>true</IsActive> + <IsEditable>false</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>9999999</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2016-07-29T12:13:27.28</CreatedDate> + <ModifiedDate>2016-07-29T12:13:27.28</ModifiedDate> + <ID>90889</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>HiddenCategory_default</CustomerKey> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>0</ID> + <ObjectID xsi:nil="true" /> + </ParentFolder> + <Name>HiddenCategory</Name> + <Description>Hidden folder to store Hidden items</Description> + <ContentType>Hidden</ContentType> + <IsActive>true</IsActive> + <IsEditable>false</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>9999999</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2016-08-25T10:04:09.12</CreatedDate> + <ModifiedDate>2016-08-25T10:04:09.12</ModifiedDate> + <ID>94030</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey /> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>89396</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>triggered_send_journeybuilder</CustomerKey> + </ParentFolder> + <Name>Satisfaction Score Survey</Name> + <Description /> + <ContentType>triggered_send_journeybuilder</ContentType> + <IsActive>true</IsActive> + <IsEditable>true</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>9999999</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2016-08-25T10:04:09.133</CreatedDate> + <ModifiedDate>2016-08-25T10:04:09.133</ModifiedDate> + <ID>94031</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey /> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>94030</ID> + <ObjectID xsi:nil="true" /> + </ParentFolder> + <Name>Version 1</Name> + <Description /> + <ContentType>triggered_send_journeybuilder</ContentType> + <IsActive>true</IsActive> + <IsEditable>true</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>9999999</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2021-06-09T10:17:06.27</CreatedDate> + <ModifiedDate>2021-06-09T10:17:06.27</ModifiedDate> + <ID>664654</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>6aa28490-6577-4cb2-8eac-fd5e4f983cae</CustomerKey> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>317169</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>HiddenJourneyBuilderTriggeredSends_d</CustomerKey> + </ParentFolder> + <Name>6aa28490-6577-4cb2-8eac-fd5e4f983cae_V9</Name> + <Description>triggered_send folder to store triggered_send items</Description> + <ContentType>triggered_send</ContentType> + <IsActive>true</IsActive> + <IsEditable>true</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>9999999</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2022-07-31T19:55:31.657</CreatedDate> + <ModifiedDate>2022-07-31T19:55:31.657</ModifiedDate> + <ID>742869</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>77211381-9967-4472-bd12-f58d4d5952a1</CustomerKey> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>317169</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>HiddenJourneyBuilderTriggeredSends_d</CustomerKey> + </ParentFolder> + <Name>77211381-9967-4472-bd12-f58d4d5952a1_V1</Name> + <Description>triggered_send folder to store triggered_send items</Description> + <ContentType>triggered_send</ContentType> + <IsActive>true</IsActive> + <IsEditable>true</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>9999999</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2022-07-31T19:56:51.297</CreatedDate> + <ModifiedDate>2022-07-31T19:56:51.297</ModifiedDate> + <ID>742871</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>HiddenJourneyBuilderSimulationTrigge</CustomerKey> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>90889</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>HiddenCategory_default</CustomerKey> + </ParentFolder> + <Name>HiddenJourneyBuilderSimulationTriggeredSends</Name> + <Description>triggered_send_journeybuilder folder to store triggered_send_journeybuilder items</Description> + <ContentType>triggered_send_journeybuilder</ContentType> + <IsActive>true</IsActive> + <IsEditable>true</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>9999999</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2023-03-08T10:26:55.787</CreatedDate> + <ModifiedDate>2023-03-08T10:26:55.787</ModifiedDate> + <ID>771879</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>8c24f428-4da8-4df6-97a7-beba5166c3c7</CustomerKey> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>317169</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>HiddenJourneyBuilderTriggeredSends_d</CustomerKey> + </ParentFolder> + <Name>8c24f428-4da8-4df6-97a7-beba5166c3c7_V1</Name> + <Description>triggered_send folder to store triggered_send items</Description> + <ContentType>triggered_send</ContentType> + <IsActive>true</IsActive> + <IsEditable>true</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>9999999</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2023-04-10T15:46:09.947</CreatedDate> + <ModifiedDate>2023-04-10T15:46:09.947</ModifiedDate> + <ID>776623</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>0a85b483-4208-4377-87fb-25794f5df244</CustomerKey> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>317169</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>HiddenJourneyBuilderTriggeredSends_d</CustomerKey> + </ParentFolder> + <Name>0a85b483-4208-4377-87fb-25794f5df244_V1</Name> + <Description>triggered_send folder to store triggered_send items</Description> + <ContentType>triggered_send</ContentType> + <IsActive>true</IsActive> + <IsEditable>true</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + <Results xsi:type="DataFolder"> + <Client> + <ID>9999999</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2020-03-06T07:57:37.633</CreatedDate> + <ModifiedDate>2020-03-06T07:57:37.633</ModifiedDate> + <ID>317169</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>HiddenJourneyBuilderTriggeredSends_d</CustomerKey> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>90889</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>HiddenCategory_default</CustomerKey> + </ParentFolder> + <Name>HiddenJourneyBuilderTriggeredSends</Name> + <Description>triggered_send folder to store triggered_send items</Description> + <ContentType>triggered_send</ContentType> + <IsActive>true</IsActive> + <IsEditable>true</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + + <Results xsi:type="DataFolder"> + <Client> + <ID>1111111</ID> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2022-01-01T00:00:00.0</CreatedDate> + <ModifiedDate>2022-01-01T00:00:00.0</ModifiedDate> + <ID>77777</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey /> + <ParentFolder> + <PartnerKey xsi:nil="true" /> + <ID>89397</ID> + <ObjectID xsi:nil="true" /> + </ParentFolder> + <Name>testFolder_samePath</Name> + <Description /> + <ContentType>asset</ContentType> + <IsActive>true</IsActive> + <IsEditable>true</IsEditable> + <AllowChildren>true</AllowChildren> + </Results> + </RetrieveResponseMsg> + </soap:Body> +</soap:Envelope> diff --git a/test/resources/9999999/dataFolder/update-response.xml b/test/resources/9999999/dataFolder/update-response.xml new file mode 100644 index 000000000..7173f7491 --- /dev/null +++ b/test/resources/9999999/dataFolder/update-response.xml @@ -0,0 +1,31 @@ +<?xml version="1.0" encoding="utf-8"?> +<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:xsd="http://www.w3.org/2001/XMLSchema" + xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing" + xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" + xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"> + <soap:Header> + <wsa:Action>UpdateResponse</wsa:Action> + <wsa:MessageID>urn:uuid:be177208-5317-4cf6-ac91-ca6ee3cf2e9c</wsa:MessageID> + <wsa:RelatesTo>urn:uuid:860092b1-f5d0-4e26-bac6-e6176e1a24e3</wsa:RelatesTo> + <wsa:To>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</wsa:To> + <wsse:Security> + <wsu:Timestamp wsu:Id="Timestamp-31f5e02a-c01e-4460-9652-c34da0c5eaa4"> + <wsu:Created>2025-04-23T11:22:29Z</wsu:Created> + <wsu:Expires>2025-04-23T11:27:29Z</wsu:Expires> + </wsu:Timestamp> + </wsse:Security> + </soap:Header> + <soap:Body> + <UpdateResponse xmlns="http://exacttarget.com/wsdl/partnerAPI"> + <Results> + <StatusCode>OK</StatusCode> + <StatusMessage>Folder updated successfully.</StatusMessage> + <OrdinalID>0</OrdinalID> + </Results> + <RequestID>b7ffdc43-dd86-41ef-979d-ab3d4badcb07</RequestID> + <OverallStatus>OK</OverallStatus> + </UpdateResponse> + </soap:Body> +</soap:Envelope> diff --git a/test/resources/9999999/deliveryProfile/get-expected.json b/test/resources/9999999/deliveryProfile/get-expected.json new file mode 100644 index 000000000..d36d9bdf9 --- /dev/null +++ b/test/resources/9999999/deliveryProfile/get-expected.json @@ -0,0 +1,7 @@ +{ + "key": "Default", + "createdDate": "2021-06-21T17:55:00Z", + "lastUpdated": "2021-06-21T17:55:00Z", + "name": "Default", + "description": "Account defaults" +} diff --git a/test/resources/9999999/domainVerification/create-expected.json b/test/resources/9999999/domainVerification/create-expected.json new file mode 100644 index 000000000..dc388b326 --- /dev/null +++ b/test/resources/9999999/domainVerification/create-expected.json @@ -0,0 +1,3 @@ +{ + "domain": "joern.berkefeld.New@accenture.com" +} diff --git a/test/resources/9999999/domainVerification/get-sap-expected.json b/test/resources/9999999/domainVerification/get-sap-expected.json new file mode 100644 index 000000000..f132e6426 --- /dev/null +++ b/test/resources/9999999/domainVerification/get-sap-expected.json @@ -0,0 +1,6 @@ +{ + "domain": "mcdev.accenture.com", + "domainType": "SAP", + "isSendable": true, + "status": "Verified" +} diff --git a/test/resources/9999999/domainVerification/update-expected.json b/test/resources/9999999/domainVerification/update-expected.json new file mode 100644 index 000000000..8cd03c47a --- /dev/null +++ b/test/resources/9999999/domainVerification/update-expected.json @@ -0,0 +1,6 @@ +{ + "domain": "joern.berkefeld@accenture.com", + "domainType": "UserDomain", + "isSendable": true, + "status": "Verified" +} diff --git a/test/resources/9999999/email/retrieve-response.xml b/test/resources/9999999/email/retrieve-response.xml new file mode 100644 index 000000000..dedb7ab8c --- /dev/null +++ b/test/resources/9999999/email/retrieve-response.xml @@ -0,0 +1,203 @@ +<?xml version="1.0" encoding="utf-8"?> +<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:xsd="http://www.w3.org/2001/XMLSchema" + xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing" + xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" + xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"> + <soap:Header> + <wsa:Action>RetrieveResponse</wsa:Action> + <wsa:MessageID>urn:uuid:bda830a5-f8a8-4555-a0f0-9b3cdae02f9f</wsa:MessageID> + <wsa:RelatesTo>urn:uuid:afa5fcc9-c276-4f3d-9796-6b31a2b55721</wsa:RelatesTo> + <wsa:To>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</wsa:To> + <wsse:Security> + <wsu:Timestamp wsu:Id="Timestamp-1332843c-2deb-4570-822f-502889ddd5c9"> + <wsu:Created>2023-08-08T12:49:19Z</wsu:Created> + <wsu:Expires>2023-08-08T12:54:19Z</wsu:Expires> + </wsu:Timestamp> + </wsse:Security> + </soap:Header> + <soap:Body> + <RetrieveResponseMsg xmlns="http://exacttarget.com/wsdl/partnerAPI"> + <OverallStatus>OK</OverallStatus> + <RequestID>e25a4055-f1b6-4fcd-a771-76bcb1cff6a9</RequestID> + <Results xsi:type="Email"> + <PartnerKey /> + <CreatedDate>2020-08-13T10:16:59</CreatedDate> + <ModifiedDate>2020-11-09T13:33:30.15</ModifiedDate> + <ID>483943</ID> + <ObjectID xsi:nil="true" /> + <CustomerKey>255f0e7c-cd37-452b-ba59-cd802359f199</CustomerKey> + <Name>Sporting Goods for September</Name> + <Folder>my emails</Folder> + <CategoryID>283575</CategoryID> + <HTMLBody><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> +<html> +<head> +<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=0" /> +<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> +<style type="text/css"> +ReadMsgBody{ width: 100%;} +.ExternalClass {width: 100%;} +.ExternalClass, .ExternalClass p, .ExternalClass span, .ExternalClass font, .ExternalClass td, .ExternalClass div {line-height: 100%;} +body {-webkit-text-size-adjust:100%; -ms-text-size-adjust:100%;margin:0 !important; padding:0 !important;} +p { margin: 1em 0;} +table td { border-collapse: collapse;} +img {outline:0;} +a img {border:none;} +p {margin: 1em 0;} +@-ms-viewport{ width: device-width;} +@media only screen and (max-width: 480px) { +body[yahoo] .container { width:100% !important; } +body[yahoo] .footer { width:auto !important; margin-left:0; } +body[yahoo] .content-padding{ padding:4px !important; } +body[yahoo] .mobile-hidden { display:none !important; } +body[yahoo] .logo { display:block !important; padding:0 !important; } +body[yahoo] img { width:auto !important; max-width:308px !important; height:auto !important; max-height:auto !important;} +body[yahoo] .header img { width:auto !important; max-width:316px !important; height:auto !important; max-height:auto !important;} +body[yahoo] .photo img { width:100% !important; max-width:100% !important; height:auto !important;} +body[yahoo] .drop { display:block !important; width: 100% !important; float:left; clear:both;} +body[yahoo] .footerlogo { display:block !important; width: 100% !important; padding-top:15px; float:left; clear:both;} +body[yahoo] .nav4, body[yahoo] .nav5, body[yahoo] .nav6 { display: none !important; } +} +@media only screen and (max-width: 640px) { +body[yahoo] .container { width:100% !important; } +body[yahoo] .mobile-hidden { display:none !important; } +body[yahoo] .logo { display:block !important; padding:0 !important; } +body[yahoo] .photo img { width:100% !important; height:auto !important;} +body[yahoo] .nav5, body[yahoo] .nav6 { display: none !important;} +} +</style> +</head> +<body bgcolor="#ffffff" text="#000000" style="background-color: #FFFFFF; color: #000000; margin: 0px; padding:0px; -webkit-text-size-adjust:none;" yahoo="fix"> + <table width="100%" border="0" cellpadding="0" cellspacing="0" align="center"> + <tr> + <td align="center" valign="top"><custom type="header" name="header"></td> + </tr> + <tr> + <td align="center"> + <table cellspacing="0" cellpadding="0" border="0" width="600" class="container" align="center"> + <tr> + <td> + <table cellspacing="0" cellpadding="0" border="1" bordercolor="#000000" bgcolor="#ffffff" width="100%"> + <tr> + <td align="center" class="header" valign="top"></td> + </tr> + <tr> + <td align="center" valign="top"><table cellspacing="0" cellpadding="0" border="0" width="100%" align="left"> + <tr> + <td class="content-padding" style="padding:10px;"> + <table cellspacing="0" cellpadding="0" border="0" width="100%"> + <tr> + <td class="drop" valign="top" width="33%" align="left"> + <custom type="content" name="left"> + </td> + <td class="drop" valign="top" width="2%" height="10"><img alt="" src="https://image.s7.sfmc-content.com/lib/ffcf14/m/1/spacer.gif" height="10" width="10" style="display: block;"/></td> + <td class="drop" valign="top" width="65%"> + <table border="0" cellpadding="0" cellspacing="0" width="100%"> + <tr> + <td align="left" valign="top"> + <custom type="content" name="right1"> + </td> + </tr> + <tr> + <td align="left" valign="top" style="padding-top: 10px;"> + <custom type="content" name="right2"> + </td> + </tr> + </table> + </td> + </tr> + <tr> + <td align="left" colspan="3" valign="top" class="drop" style="padding-top:10px;"> + <custom type="content" name="bottom"> + </td> + </tr> + </table> + </td> + </tr> +</table></td> + </tr> + </table> + </td> + </tr> + </table> + </td> + </tr> + <tr> + <td valign="top"><custom type="footer" name="footer"></td> + </tr> + </table> + <custom name="opencounter" type="tracking"> +</body> +</html></HTMLBody> + <TextBody /> + <ContentAreas> + <PartnerKey xsi:nil="true" /> + <ID>934961</ID> + <ObjectID>5E999EA7-97D8-4910-91B3-ED29B16567DA</ObjectID> + <CustomerKey>36D85559-5345-41CB-9E8E-A6B7675E4A6F</CustomerKey> + <Key>left</Key> + <Content><table width="100%" bgcolor="" border="0" bordercolor="" cellpadding="0" cellspacing="0"><tr><td style="font-family:Arial;font-size:13px;">%%First Name%%</td></tr></table></Content> + <IsBlank>false</IsBlank> + <CategoryID>0</CategoryID> + <Name /> + <IsDynamicContent>false</IsDynamicContent> + <IsSurvey>false</IsSurvey> + <IsLocked>false</IsLocked> + </ContentAreas> + <ContentAreas> + <PartnerKey xsi:nil="true" /> + <ID>934962</ID> + <ObjectID>9FA2FEE0-8439-4475-B990-BBC95CB30E31</ObjectID> + <CustomerKey>68DC9A04-6662-4A23-912A-4A349A1EF040</CustomerKey> + <Key>right1</Key> + <Content><table width="100%" bgcolor="" border="0" bordercolor="" cellpadding="0" cellspacing="0"><tr><td style="font-family:Arial;font-size:13px;">%%Last Name%%</td></tr></table></Content> + <IsBlank>false</IsBlank> + <CategoryID>0</CategoryID> + <Name /> + <IsDynamicContent>false</IsDynamicContent> + <IsSurvey>false</IsSurvey> + <IsLocked>false</IsLocked> + </ContentAreas> + <ContentAreas> + <PartnerKey xsi:nil="true" /> + <ID>934963</ID> + <ObjectID>5CE10FC0-CE06-40CC-8BE4-14583E2D02B3</ObjectID> + <CustomerKey>AB7920D1-AE37-4137-9BB9-77B746D4A66C</CustomerKey> + <Key>right2</Key> + <Content><table width="100%" bgcolor="" border="0" bordercolor="" cellpadding="0" cellspacing="0"><tr><td style="font-family:Arial;font-size:13px;">%%emailname_%%</td></tr></table></Content> + <IsBlank>false</IsBlank> + <CategoryID>0</CategoryID> + <Name /> + <IsDynamicContent>false</IsDynamicContent> + <IsSurvey>false</IsSurvey> + <IsLocked>false</IsLocked> + </ContentAreas> + <ContentAreas> + <PartnerKey xsi:nil="true" /> + <ID>934964</ID> + <ObjectID>AF6501E0-8367-4121-9142-ADAFD632FBE7</ObjectID> + <CustomerKey>84B63EB0-E248-42D4-B6A6-716C18D2718D</CustomerKey> + <Key>bottom</Key> + <Content><table width="100%" bgcolor="" border="0" bordercolor="" cellpadding="0" cellspacing="0"><tr><td style="font-family:Arial;font-size:13px;">%%emailaddr%%</td></tr></table></Content> + <IsBlank>false</IsBlank> + <CategoryID>0</CategoryID> + <Name /> + <IsDynamicContent>false</IsDynamicContent> + <IsSurvey>false</IsSurvey> + <IsLocked>false</IsLocked> + </ContentAreas> + <Subject>Sporting Goods for September</Subject> + <IsActive>true</IsActive> + <IsHTMLPaste>false</IsHTMLPaste> + <Status>New</Status> + <EmailType>Normal</EmailType> + <CharacterSet>utf-8</CharacterSet> + <HasDynamicSubjectLine>false</HasDynamicSubjectLine> + <ContentCheckStatus>Not Checked</ContentCheckStatus> + <PreHeader /> + </Results> + </RetrieveResponseMsg> + </soap:Body> +</soap:Envelope> diff --git a/test/resources/9999999/email/v1/category/post-response-parentCatId=290937,name=my,catType=automations.json b/test/resources/9999999/email/v1/category/post-response-parentCatId=290937,name=my,catType=automations.json new file mode 100644 index 000000000..71ab441f2 --- /dev/null +++ b/test/resources/9999999/email/v1/category/post-response-parentCatId=290937,name=my,catType=automations.json @@ -0,0 +1,7 @@ +{ + "categoryId": 862100, + "parentCatId": 290937, + "objectId": "07d346ff-c0b2-4f1b-9ca0-bddd156d3950", + "catType": "automations", + "name": "my" +} diff --git a/test/resources/9999999/email/v1/category/post-response-parentCatId=862100,name=sub,catType=automations.json b/test/resources/9999999/email/v1/category/post-response-parentCatId=862100,name=sub,catType=automations.json new file mode 100644 index 000000000..036c1bf70 --- /dev/null +++ b/test/resources/9999999/email/v1/category/post-response-parentCatId=862100,name=sub,catType=automations.json @@ -0,0 +1,7 @@ +{ + "categoryId": 862101, + "parentCatId": 862100, + "objectId": "07d346ff-c0b2-4f1b-9ca0-bddd156d3951", + "catType": "automations", + "name": "sub" +} diff --git a/test/resources/9999999/email/v1/category/post-response-parentCatId=862101,name=path,catType=automations.json b/test/resources/9999999/email/v1/category/post-response-parentCatId=862101,name=path,catType=automations.json new file mode 100644 index 000000000..4f9d32863 --- /dev/null +++ b/test/resources/9999999/email/v1/category/post-response-parentCatId=862101,name=path,catType=automations.json @@ -0,0 +1,7 @@ +{ + "categoryId": 862102, + "parentCatId": 862101, + "objectId": "07d346ff-c0b2-4f1b-9ca0-bddd156d3952", + "catType": "automations", + "name": "path" +} diff --git a/test/resources/9999999/email/v1/category/post-response-parentCatId=862102,name=subpath,catType=automations.json b/test/resources/9999999/email/v1/category/post-response-parentCatId=862102,name=subpath,catType=automations.json new file mode 100644 index 000000000..29ca84932 --- /dev/null +++ b/test/resources/9999999/email/v1/category/post-response-parentCatId=862102,name=subpath,catType=automations.json @@ -0,0 +1,7 @@ +{ + "categoryId": 862103, + "parentCatId": 862102, + "objectId": "07d346ff-c0b2-4f1b-9ca0-bddd156d3953", + "catType": "automations", + "name": "subpath" +} diff --git a/test/resources/9999999/email/v1/filters/filterdefinition/10ef27dd-4be8-4bf6-970a-8acf8e281e55/delete-response.txt b/test/resources/9999999/email/v1/filters/filterdefinition/10ef27dd-4be8-4bf6-970a-8acf8e281e55/delete-response.txt new file mode 100644 index 000000000..4fcfe2e08 --- /dev/null +++ b/test/resources/9999999/email/v1/filters/filterdefinition/10ef27dd-4be8-4bf6-970a-8acf8e281e55/delete-response.txt @@ -0,0 +1 @@ +10ef27dd-4be8-4bf6-970a-8acf8e281e55 \ No newline at end of file diff --git a/test/resources/9999999/email/v1/filters/filterdefinition/10ef27dd-4be8-4bf6-970a-8acf8e281e55/get-response.json b/test/resources/9999999/email/v1/filters/filterdefinition/10ef27dd-4be8-4bf6-970a-8acf8e281e55/get-response.json new file mode 100644 index 000000000..027039fa4 --- /dev/null +++ b/test/resources/9999999/email/v1/filters/filterdefinition/10ef27dd-4be8-4bf6-970a-8acf8e281e55/get-response.json @@ -0,0 +1,19 @@ +{ + "id": "10ef27dd-4be8-4bf6-970a-8acf8e281e55", + "key": "testExisting_dataFilter", + "createdDate": "2025-12-01T16:54:09.813", + "createdBy": 700301950, + "createdByName": "Jörn Berkefeld", + "lastUpdated": "2025-12-01T17:17:31.827", + "lastUpdatedBy": 700301950, + "lastUpdatedByName": "Jörn Berkefeld", + "name": "testExisting_dataFilter", + "description": "test", + "categoryId": 5318, + "filterDefinitionXml": "<FilterDefinition Source=\"DataExtension\" SourceID=\"21711373-72c1-ec11-b83b-48df37d1deb7\"><ConditionSet Operator=\"AND\" ConditionSetName=\"Outer Grouping\"><Condition ID=\"bea0e308-5d45-4181-a673-da9972a7c674\" Operator=\"Ends\"><Value><![CDATA[_test]]></Value></Condition></ConditionSet></FilterDefinition>", + "derivedFromObjectId": "21711373-72c1-ec11-b83b-48df37d1deb7", + "derivedFromType": 2, + "isSendable": true, + "derivedFromObjectTypeName": "DataExtension", + "derivedFromObjectName": "testExisting_dataExtension" +} diff --git a/test/resources/9999999/email/v1/filters/filterdefinition/10ef27dd-4be8-4bf6-970a-8acf8e281e55/patch-response.json b/test/resources/9999999/email/v1/filters/filterdefinition/10ef27dd-4be8-4bf6-970a-8acf8e281e55/patch-response.json new file mode 100644 index 000000000..27c905003 --- /dev/null +++ b/test/resources/9999999/email/v1/filters/filterdefinition/10ef27dd-4be8-4bf6-970a-8acf8e281e55/patch-response.json @@ -0,0 +1,15 @@ +{ + "id": "10ef27dd-4be8-4bf6-970a-8acf8e281e55", + "key": "testExisting_dataFilter", + "owner": 700301950, + "createdDate": "2026-01-27T06:24:40.527", + "createdBy": 700301950, + "lastUpdated": "2026-01-30T10:46:59.777", + "lastUpdatedBy": 700301950, + "name": "testExisting_dataFilter", + "categoryId": 5318, + "filterDefinitionXml": "<FilterDefinition Source=\"DataExtension\" SourceID=\"21711373-72c1-ec11-b83b-48df37d1deb7\"><ConditionSet Operator=\"AND\" ConditionSetName=\"Outer Grouping\"><Condition ID=\"bea0e308-5d45-4181-a673-da9972a7c674\" Operator=\"Begins\"><Value><![CDATA[testExisting_]]></Value></Condition></ConditionSet></FilterDefinition>", + "derivedFromObjectId": "21711373-72c1-ec11-b83b-48df37d1deb7", + "derivedFromType": 2, + "isSendable": true +} diff --git a/test/resources/9999999/email/v1/filters/filterdefinition/category/5318/get-response.json b/test/resources/9999999/email/v1/filters/filterdefinition/category/5318/get-response.json new file mode 100644 index 000000000..84a0d122b --- /dev/null +++ b/test/resources/9999999/email/v1/filters/filterdefinition/category/5318/get-response.json @@ -0,0 +1,27 @@ +{ + "count": 1, + "page": 1, + "pageSize": 100, + "links": {}, + "items": [ + { + "id": "10ef27dd-4be8-4bf6-970a-8acf8e281e55", + "key": "testExisting_dataFilter", + "createdDate": "2025-12-01T16:54:09.813", + "createdBy": 700301950, + "createdByName": "Jörn Berkefeld", + "lastUpdated": "2025-12-01T17:17:31.827", + "lastUpdatedBy": 700301950, + "lastUpdatedByName": "Jörn Berkefeld", + "name": "testExisting_dataFilter", + "description": "test", + "categoryId": 5318, + "filterDefinitionXml": "<FilterDefinition Source=\"DataExtension\" SourceID=\"21711373-72c1-ec11-b83b-48df37d1deb7\"><ConditionSet Operator=\"AND\" ConditionSetName=\"Outer Grouping\"><Condition ID=\"bea0e308-5d45-4181-a673-da9972a7c674\" Operator=\"Ends\"><Value><![CDATA[_test]]></Value></Condition></ConditionSet></FilterDefinition>", + "derivedFromObjectId": "21711373-72c1-ec11-b83b-48df37d1deb7", + "derivedFromType": 2, + "isSendable": true, + "derivedFromObjectTypeName": "DataExtension", + "derivedFromObjectName": "MCV_Talent_flat" + } + ] +} diff --git a/test/resources/9999999/email/v1/filters/filterdefinition/category/8502/get-response.json b/test/resources/9999999/email/v1/filters/filterdefinition/category/8502/get-response.json new file mode 100644 index 000000000..d97642e38 --- /dev/null +++ b/test/resources/9999999/email/v1/filters/filterdefinition/category/8502/get-response.json @@ -0,0 +1,7 @@ +{ + "count": 0, + "page": 1, + "pageSize": 100, + "links": {}, + "items": [] +} diff --git a/test/resources/9999999/email/v1/filters/filterdefinition/category/8503/get-response.json b/test/resources/9999999/email/v1/filters/filterdefinition/category/8503/get-response.json new file mode 100644 index 000000000..d97642e38 --- /dev/null +++ b/test/resources/9999999/email/v1/filters/filterdefinition/category/8503/get-response.json @@ -0,0 +1,7 @@ +{ + "count": 0, + "page": 1, + "pageSize": 100, + "links": {}, + "items": [] +} diff --git a/test/resources/9999999/email/v1/filters/filterdefinition/post-response.json b/test/resources/9999999/email/v1/filters/filterdefinition/post-response.json new file mode 100644 index 000000000..c55947cb4 --- /dev/null +++ b/test/resources/9999999/email/v1/filters/filterdefinition/post-response.json @@ -0,0 +1,15 @@ +{ + "id": "4c92630e-e3e8-4940-a93d-99da02123e93", + "key": "testNew_dataFilter", + "owner": 700301950, + "createdDate": "2026-01-30T11:04:06.883", + "createdBy": 700301950, + "lastUpdated": "2026-01-30T11:04:06.883", + "lastUpdatedBy": 700301950, + "name": "testNew_dataFilter", + "categoryId": 5318, + "filterDefinitionXml": "<FilterDefinition Source=\"DataExtension\" SourceID=\"21711373-72c1-ec11-b83b-48df37d1deb7\"><ConditionSet Operator=\"AND\" ConditionSetName=\"Outer Grouping\"><Condition ID=\"bea0e308-5d45-4181-a673-da9972a7c674\" Operator=\"Ends\"><Value><![CDATA[_test]]></Value></Condition></ConditionSet></FilterDefinition>", + "derivedFromObjectId": "21711373-72c1-ec11-b83b-48df37d1deb7", + "derivedFromType": 2, + "isSendable": false +} diff --git a/test/resources/9999999/emailSend/build-expected.json b/test/resources/9999999/emailSend/build-expected.json new file mode 100644 index 000000000..2b50e8fb3 --- /dev/null +++ b/test/resources/9999999/emailSend/build-expected.json @@ -0,0 +1,43 @@ +{ + "Additional": "", + "AutoBccEmail": "", + "BccEmail": "", + "CCEmail": "", + "CreatedDate": "2022-11-14T12:27:29.963", + "CustomerKey": "testTemplated_emailSend", + "DeduplicateByEmail": false, + "Description": "some description", + "DynamicEmailSubject": "someSubject", + "EmailSubject": "someSubject", + "ExclusionFilter": "Domain(emailaddr) != \"accenture.com\"", + "IsMultipart": true, + "IsSendLogging": false, + "IsWrapped": true, + "ModifiedDate": "2022-11-14T12:27:29.963", + "Name": "testTemplated_emailSend", + "SendDefinitionList": [ + { + "DataSourceTypeID": "CustomObject", + "IsTestObject": false, + "Name": "", + "SendDefinitionListType": "ExclusionList", + "r__dataExtension_key": "testTemplated_dataExtension_exclusion" + }, + { + "DataSourceTypeID": "CustomObject", + "IsTestObject": false, + "Name": "", + "SendDefinitionListType": "SourceList", + "r__dataExtension_key": "testTemplated_dataExtension", + "r__list_PathName": "Publication Lists/Demo Publication List" + } + ], + "SuppressTracking": false, + "TestEmailAddr": "", + "r__asset_key": "testTemplated_asset_message", + "r__asset_name_readOnly": "testTemplated_asset_message", + "r__deliveryProfile_key": "Default", + "r__folder_Path": "User-Initiated", + "r__sendClassification_key": "testTemplated_sendClassification", + "r__senderProfile_key": "testTemplated_senderProfile" +} diff --git a/test/resources/9999999/emailSend/get-expected.json b/test/resources/9999999/emailSend/get-expected.json new file mode 100644 index 000000000..1f1747a76 --- /dev/null +++ b/test/resources/9999999/emailSend/get-expected.json @@ -0,0 +1,43 @@ +{ + "Additional": "", + "AutoBccEmail": "", + "BccEmail": "", + "CCEmail": "", + "CreatedDate": "2022-11-14T12:27:29.963", + "CustomerKey": "testExisting_emailSend", + "DeduplicateByEmail": false, + "Description": "some description", + "DynamicEmailSubject": "someSubject", + "EmailSubject": "someSubject", + "ExclusionFilter": "Domain(emailaddr) != \"accenture.com\"", + "IsMultipart": true, + "IsSendLogging": false, + "IsWrapped": true, + "ModifiedDate": "2022-11-14T12:27:29.963", + "Name": "testExisting_emailSend", + "SendDefinitionList": [ + { + "SendDefinitionListType": "ExclusionList", + "DataSourceTypeID": "CustomObject", + "IsTestObject": false, + "Name": "", + "r__dataExtension_key": "testExisting_dataExtension_exclusion" + }, + { + "SendDefinitionListType": "SourceList", + "DataSourceTypeID": "CustomObject", + "IsTestObject": false, + "Name": "", + "r__dataExtension_key": "testExisting_dataExtension", + "r__list_PathName": "Publication Lists/Demo Publication List" + } + ], + "SuppressTracking": false, + "TestEmailAddr": "", + "r__asset_key": "testExisting_asset_message", + "r__asset_name_readOnly": "testExisting_asset_message", + "r__deliveryProfile_key": "Default", + "r__folder_Path": "User-Initiated", + "r__sendClassification_key": "testExisting_sendClassification", + "r__senderProfile_key": "testExisting_senderProfile" +} diff --git a/test/resources/9999999/emailSend/patch-expected.json b/test/resources/9999999/emailSend/patch-expected.json new file mode 100644 index 000000000..e5dc97113 --- /dev/null +++ b/test/resources/9999999/emailSend/patch-expected.json @@ -0,0 +1,41 @@ +{ + "Additional": "", + "AutoBccEmail": "", + "BccEmail": "", + "CCEmail": "", + "CustomerKey": "testExisting_emailSend", + "DeduplicateByEmail": false, + "Description": "updated on deploy", + "DynamicEmailSubject": "someSubject", + "EmailSubject": "someSubject", + "ExclusionFilter": "", + "IsMultipart": true, + "IsSendLogging": false, + "IsWrapped": true, + "Name": "testExisting_emailSend", + "SendDefinitionList": [ + { + "SendDefinitionListType": "ExclusionList", + "DataSourceTypeID": "CustomObject", + "IsTestObject": false, + "Name": "", + "r__dataExtension_key": "testExisting_dataExtension_exclusion" + }, + { + "SendDefinitionListType": "SourceList", + "DataSourceTypeID": "CustomObject", + "IsTestObject": false, + "Name": "", + "r__dataExtension_key": "testExisting_dataExtension", + "r__list_PathName": "Publication Lists/Demo Publication List" + } + ], + "SuppressTracking": false, + "TestEmailAddr": "", + "r__asset_key": "testExisting_asset_message", + "r__asset_name_readOnly": "testExisting_asset_message", + "r__deliveryProfile_key": "Default", + "r__folder_Path": "User-Initiated", + "r__sendClassification_key": "testExisting_sendClassification", + "r__senderProfile_key": "testExisting_senderProfile" +} diff --git a/test/resources/9999999/emailSend/post-expected.json b/test/resources/9999999/emailSend/post-expected.json new file mode 100644 index 000000000..50f81b547 --- /dev/null +++ b/test/resources/9999999/emailSend/post-expected.json @@ -0,0 +1,41 @@ +{ + "Additional": "", + "AutoBccEmail": "", + "BccEmail": "", + "CCEmail": "", + "CustomerKey": "testNew_emailSend", + "DeduplicateByEmail": false, + "Description": "created on deploy", + "DynamicEmailSubject": "testExisting_asset_email", + "EmailSubject": "testExisting_asset_email", + "ExclusionFilter": "", + "IsMultipart": true, + "IsSendLogging": false, + "IsWrapped": true, + "Name": "testNew_emailSend", + "SendDefinitionList": [ + { + "SendDefinitionListType": "ExclusionList", + "DataSourceTypeID": "CustomObject", + "IsTestObject": false, + "Name": "", + "r__dataExtension_key": "testExisting_dataExtension_exclusion" + }, + { + "SendDefinitionListType": "SourceList", + "DataSourceTypeID": "CustomObject", + "IsTestObject": false, + "Name": "", + "r__dataExtension_key": "testExisting_dataExtension", + "r__list_PathName": "Publication Lists/Demo Publication List" + } + ], + "SuppressTracking": false, + "TestEmailAddr": "", + "r__asset_key": "testExisting_asset_message", + "r__asset_name_readOnly": "testExisting_asset_message", + "r__deliveryProfile_key": "Default", + "r__folder_Path": "User-Initiated", + "r__sendClassification_key": "testExisting_sendClassification", + "r__senderProfile_key": "testExisting_senderProfile" +} diff --git a/test/resources/9999999/emailSend/template-expected.json b/test/resources/9999999/emailSend/template-expected.json new file mode 100644 index 000000000..f6aaa794d --- /dev/null +++ b/test/resources/9999999/emailSend/template-expected.json @@ -0,0 +1,43 @@ +{ + "Additional": "", + "AutoBccEmail": "", + "BccEmail": "", + "CCEmail": "", + "CreatedDate": "2022-11-14T12:27:29.963", + "CustomerKey": "{{{prefix}}}emailSend", + "DeduplicateByEmail": false, + "Description": "some description", + "DynamicEmailSubject": "someSubject", + "EmailSubject": "someSubject", + "ExclusionFilter": "Domain(emailaddr) != \"accenture.com\"", + "IsMultipart": true, + "IsSendLogging": false, + "IsWrapped": true, + "ModifiedDate": "2022-11-14T12:27:29.963", + "Name": "{{{prefix}}}emailSend", + "SendDefinitionList": [ + { + "DataSourceTypeID": "CustomObject", + "IsTestObject": false, + "Name": "", + "SendDefinitionListType": "ExclusionList", + "r__dataExtension_key": "{{{prefix}}}dataExtension_exclusion" + }, + { + "DataSourceTypeID": "CustomObject", + "IsTestObject": false, + "Name": "", + "SendDefinitionListType": "SourceList", + "r__dataExtension_key": "{{{prefix}}}dataExtension", + "r__list_PathName": "Publication Lists/Demo Publication List" + } + ], + "SuppressTracking": false, + "TestEmailAddr": "", + "r__asset_key": "{{{prefix}}}asset_message", + "r__asset_name_readOnly": "{{{prefix}}}asset_message", + "r__deliveryProfile_key": "Default", + "r__folder_Path": "User-Initiated", + "r__sendClassification_key": "{{{prefix}}}sendClassification", + "r__senderProfile_key": "{{{prefix}}}senderProfile" +} diff --git a/test/resources/9999999/emailSendDefinition/create-response.xml b/test/resources/9999999/emailSendDefinition/create-response.xml new file mode 100644 index 000000000..974b6ca59 --- /dev/null +++ b/test/resources/9999999/emailSendDefinition/create-response.xml @@ -0,0 +1,98 @@ +<?xml version="1.0" encoding="utf-8"?> +<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:xsd="http://www.w3.org/2001/XMLSchema" + xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing" + xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" + xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"> + <soap:Header> + <wsa:Action>CreateResponse</wsa:Action> + <wsa:MessageID>urn:uuid:a717abcf-ef43-42a9-af53-69d95f93cf4a</wsa:MessageID> + <wsa:RelatesTo>urn:uuid:38efc94c-5fea-43e3-8689-fd26ec03d091</wsa:RelatesTo> + <wsa:To>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</wsa:To> + <wsse:Security> + <wsu:Timestamp wsu:Id="Timestamp-2552d265-3c7a-4593-ba69-15566a731880"> + <wsu:Created>2024-04-17T12:57:44Z</wsu:Created> + <wsu:Expires>2024-04-17T13:02:44Z</wsu:Expires> + </wsu:Timestamp> + </wsse:Security> + </soap:Header> + <soap:Body> + <CreateResponse xmlns="http://exacttarget.com/wsdl/partnerAPI"> + <Results> + <StatusCode>OK</StatusCode> + <StatusMessage>EmailSendDefinition created</StatusMessage> + <OrdinalID>0</OrdinalID> + <NewID>0</NewID> + <NewObjectID>ce281713-bafc-ee11-a5c8-5cba2c6fc270</NewObjectID> + <Object xsi:type="EmailSendDefinition"> + <PartnerKey xsi:nil="true" /> + <ObjectID>ce281713-bafc-ee11-a5c8-5cba2c6fc270</ObjectID> + <CustomerKey>testNew_emailSend</CustomerKey> + <IsPlatformObject>false</IsPlatformObject> + <Name>testNew_emailSend</Name> + <Description>created on deploy</Description> + <CategoryID>4691</CategoryID> + <SendClassification> + <PartnerKey xsi:nil="true" /> + <ObjectID xsi:nil="true" /> + <CustomerKey>testExisting_sendClassification</CustomerKey> + </SendClassification> + <SenderProfile> + <PartnerKey xsi:nil="true" /> + <ObjectID xsi:nil="true" /> + <CustomerKey>testExisting_senderProfile</CustomerKey> + </SenderProfile> + <DeliveryProfile> + <PartnerKey xsi:nil="true" /> + <ObjectID xsi:nil="true" /> + <CustomerKey>Default</CustomerKey> + </DeliveryProfile> + <SuppressTracking>false</SuppressTracking> + <IsSendLogging>false</IsSendLogging> + <SendDefinitionList> + <PartnerKey xsi:nil="true" /> + <ObjectID xsi:nil="true" /> + <SendDefinitionListType>ExclusionList</SendDefinitionListType> + <CustomObjectID>21711373-72c1-ec11-b83b-exclusion</CustomObjectID> + <DataSourceTypeID>CustomObject</DataSourceTypeID> + <IsTestObject>false</IsTestObject> + <Name /> + </SendDefinitionList> + <SendDefinitionList> + <PartnerKey xsi:nil="true" /> + <ObjectID xsi:nil="true" /> + <List> + <PartnerKey xsi:nil="true" /> + <ID>114</ID> + <ObjectID xsi:nil="true" /> + </List> + <SendDefinitionListType>SourceList</SendDefinitionListType> + <CustomObjectID>21711373-72c1-ec11-b83b-48df37d1deb7</CustomObjectID> + <DataSourceTypeID>CustomObject</DataSourceTypeID> + <IsTestObject>false</IsTestObject> + <Name /> + </SendDefinitionList> + <Email> + <PartnerKey xsi:nil="true" /> + <ID>531213</ID> + <ObjectID xsi:nil="true" /> + </Email> + <BccEmail /> + <AutoBccEmail /> + <TestEmailAddr /> + <EmailSubject>testExisting_asset_email</EmailSubject> + <DynamicEmailSubject>testExisting_asset_email</DynamicEmailSubject> + <IsMultipart>true</IsMultipart> + <IsWrapped>true</IsWrapped> + <DeduplicateByEmail>false</DeduplicateByEmail> + <ExclusionFilter /> + <Additional /> + <CCEmail /> + </Object> + </Results> + <RequestID>8a548392-c00a-4909-97d3-85b5a9305d35</RequestID> + <OverallStatus>OK</OverallStatus> + </CreateResponse> + </soap:Body> +</soap:Envelope> diff --git a/test/resources/9999999/emailSendDefinition/delete-response.xml b/test/resources/9999999/emailSendDefinition/delete-response.xml new file mode 100644 index 000000000..224c1e5a3 --- /dev/null +++ b/test/resources/9999999/emailSendDefinition/delete-response.xml @@ -0,0 +1,36 @@ +<?xml version="1.0" encoding="utf-8"?> +<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:xsd="http://www.w3.org/2001/XMLSchema" + xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing" + xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" + xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"> + <soap:Header> + <wsa:Action>DeleteResponse</wsa:Action> + <wsa:MessageID>urn:uuid:b9803c4e-4d42-44c3-87fe-3b216ee29eb4</wsa:MessageID> + <wsa:RelatesTo>urn:uuid:7b32fd02-7791-4e57-9a18-50936e575c9a</wsa:RelatesTo> + <wsa:To>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</wsa:To> + <wsse:Security> + <wsu:Timestamp wsu:Id="Timestamp-b119a5cf-5dcd-440a-8ed5-c96a134727b1"> + <wsu:Created>2024-04-17T13:26:48Z</wsu:Created> + <wsu:Expires>2024-04-17T13:31:48Z</wsu:Expires> + </wsu:Timestamp> + </wsse:Security> + </soap:Header> + <soap:Body> + <DeleteResponse xmlns="http://exacttarget.com/wsdl/partnerAPI"> + <Results> + <StatusCode>OK</StatusCode> + <StatusMessage>EmailSendDefinition deleted</StatusMessage> + <OrdinalID>0</OrdinalID> + <Object xsi:type="EmailSendDefinition"> + <PartnerKey xsi:nil="true" /> + <ObjectID>748400fc-b3fc-ee11-a5c8-5cba2c6fc270</ObjectID> + <CustomerKey>testExisting_emailSend</CustomerKey> + </Object> + </Results> + <RequestID>02ef6a83-36cc-402e-901e-c24d49cc0e3c</RequestID> + <OverallStatus>OK</OverallStatus> + </DeleteResponse> + </soap:Body> +</soap:Envelope> diff --git a/test/resources/9999999/emailSendDefinition/retrieve-IsPlatformObject=falseANDDescriptionnotEqualsSFSendDefinition-response.xml b/test/resources/9999999/emailSendDefinition/retrieve-IsPlatformObject=falseANDDescriptionnotEqualsSFSendDefinition-response.xml new file mode 100644 index 000000000..010771305 --- /dev/null +++ b/test/resources/9999999/emailSendDefinition/retrieve-IsPlatformObject=falseANDDescriptionnotEqualsSFSendDefinition-response.xml @@ -0,0 +1,95 @@ +<?xml version="1.0" encoding="utf-8"?> +<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:xsd="http://www.w3.org/2001/XMLSchema" + xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing" + xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" + xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"> + <soap:Header> + <wsa:Action>RetrieveResponse</wsa:Action> + <wsa:MessageID>urn:uuid:e0ba7da7-7e82-42db-a166-42a488ac375b</wsa:MessageID> + <wsa:RelatesTo>urn:uuid:17a3f405-6bd8-4b30-9230-44fea1749b96</wsa:RelatesTo> + <wsa:To>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</wsa:To> + <wsse:Security> + <wsu:Timestamp wsu:Id="Timestamp-96902d78-e86f-4361-855e-c37e2e3b4b58"> + <wsu:Created>2023-06-01T12:04:17Z</wsu:Created> + <wsu:Expires>2023-06-01T12:09:17Z</wsu:Expires> + </wsu:Timestamp> + </wsse:Security> + </soap:Header> + <soap:Body> + <RetrieveResponseMsg xmlns="http://exacttarget.com/wsdl/partnerAPI"> + <OverallStatus>OK</OverallStatus> + <RequestID>687d0584-acbe-4bac-bfc2-4c41b73b5a32</RequestID> + <Results xsi:type="EmailSendDefinition"> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2022-11-14T12:27:29.963</CreatedDate> + <ModifiedDate>2022-11-14T12:27:29.963</ModifiedDate> + <ObjectID>9b1c7bf9-4964-ed11-b849-48df37d1de8b</ObjectID> + <CustomerKey>testExisting_emailSend</CustomerKey> + <IsPlatformObject>false</IsPlatformObject> + <Name>testExisting_emailSend</Name> + <Description>some description</Description> + <CategoryID>4691</CategoryID> + <SendClassification> + <PartnerKey xsi:nil="true" /> + <ObjectID xsi:nil="true" /> + <CustomerKey>testExisting_sendClassification</CustomerKey> + </SendClassification> + <SenderProfile> + <PartnerKey xsi:nil="true" /> + <ObjectID xsi:nil="true" /> + <CustomerKey>testExisting_senderProfile</CustomerKey> + </SenderProfile> + <DeliveryProfile> + <PartnerKey xsi:nil="true" /> + <ObjectID xsi:nil="true" /> + <CustomerKey>Default</CustomerKey> + </DeliveryProfile> + <SuppressTracking>false</SuppressTracking> + <IsSendLogging>false</IsSendLogging> + <SendDefinitionList> + <PartnerKey xsi:nil="true" /> + <ObjectID>9d1c7bf9-4964-ed11-b849-48df37d1de8c</ObjectID> + <SendDefinitionListType>ExclusionList</SendDefinitionListType> + <CustomObjectID>21711373-72c1-ec11-b83b-exclusion</CustomObjectID> + <DataSourceTypeID>CustomObject</DataSourceTypeID> + <IsTestObject>false</IsTestObject> + <SalesForceObjectID /> + <Name /> + </SendDefinitionList> + <SendDefinitionList> + <PartnerKey xsi:nil="true" /> + <ObjectID>9d1c7bf9-4964-ed11-b849-48df37d1de8b</ObjectID> + <List> + <PartnerKey xsi:nil="true" /> + <ID>114</ID> + <ObjectID xsi:nil="true" /> + </List> + <SendDefinitionListType>SourceList</SendDefinitionListType> + <CustomObjectID>21711373-72c1-ec11-b83b-48df37d1deb7</CustomObjectID> + <DataSourceTypeID>CustomObject</DataSourceTypeID> + <IsTestObject>false</IsTestObject> + <SalesForceObjectID /> + <Name /> + </SendDefinitionList> + <Email> + <PartnerKey xsi:nil="true" /> + <ID>531213</ID> + <ObjectID xsi:nil="true" /> + </Email> + <BccEmail /> + <AutoBccEmail /> + <TestEmailAddr /> + <EmailSubject>someSubject</EmailSubject> + <DynamicEmailSubject>someSubject</DynamicEmailSubject> + <IsMultipart>true</IsMultipart> + <IsWrapped>true</IsWrapped> + <DeduplicateByEmail>false</DeduplicateByEmail> + <ExclusionFilter>Domain(emailaddr) != "accenture.com"</ExclusionFilter> + <Additional /> + <CCEmail /> + </Results> + </RetrieveResponseMsg> + </soap:Body> +</soap:Envelope> diff --git a/test/resources/9999999/emailSendDefinition/update-response.xml b/test/resources/9999999/emailSendDefinition/update-response.xml new file mode 100644 index 000000000..75bb1a8f0 --- /dev/null +++ b/test/resources/9999999/emailSendDefinition/update-response.xml @@ -0,0 +1,97 @@ +<?xml version="1.0" encoding="utf-8"?> +<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:xsd="http://www.w3.org/2001/XMLSchema" + xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing" + xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" + xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"> + <soap:Header> + <wsa:Action>UpdateResponse</wsa:Action> + <wsa:MessageID>urn:uuid:166b4a28-09e8-444b-ac08-91a7fb32af13</wsa:MessageID> + <wsa:RelatesTo>urn:uuid:95dd02cf-53a5-4bd7-acaf-4c0609f81912</wsa:RelatesTo> + <wsa:To>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</wsa:To> + <wsse:Security> + <wsu:Timestamp wsu:Id="Timestamp-0706d339-c346-4fa4-940d-565ca79a3f3f"> + <wsu:Created>2024-04-17T12:55:18Z</wsu:Created> + <wsu:Expires>2024-04-17T13:00:18Z</wsu:Expires> + </wsu:Timestamp> + </wsse:Security> + </soap:Header> + <soap:Body> + <UpdateResponse xmlns="http://exacttarget.com/wsdl/partnerAPI"> + <Results> + <StatusCode>OK</StatusCode> + <StatusMessage>EmailSendDefinition updated</StatusMessage> + <OrdinalID>0</OrdinalID> + <Object xsi:type="EmailSendDefinition"> + <PartnerKey xsi:nil="true" /> + <ObjectID>748400fc-b3fc-ee11-a5c8-5cba2c6fc270</ObjectID> + <CustomerKey>testExisting_emailSend</CustomerKey> + <IsPlatformObject>false</IsPlatformObject> + <Name>testExisting_emailSend</Name> + <Description>updated on deploy</Description> + <CategoryID>4691</CategoryID> + <SendClassification> + <PartnerKey xsi:nil="true" /> + <ObjectID xsi:nil="true" /> + <CustomerKey>testExisting_sendClassification</CustomerKey> + </SendClassification> + <SenderProfile> + <PartnerKey xsi:nil="true" /> + <ObjectID xsi:nil="true" /> + <CustomerKey>testExisting_senderProfile</CustomerKey> + </SenderProfile> + <DeliveryProfile> + <PartnerKey xsi:nil="true" /> + <ObjectID xsi:nil="true" /> + <CustomerKey>Default</CustomerKey> + </DeliveryProfile> + <SuppressTracking>false</SuppressTracking> + <IsSendLogging>false</IsSendLogging> + <SendDefinitionList> + <PartnerKey xsi:nil="true" /> + <ObjectID xsi:nil="true" /> + <SendDefinitionListType>ExclusionList</SendDefinitionListType> + <CustomObjectID>21711373-72c1-ec11-b83b-exclusion</CustomObjectID> + <DataSourceTypeID>CustomObject</DataSourceTypeID> + <IsTestObject>false</IsTestObject> + <Name /> + </SendDefinitionList> + <SendDefinitionList> + <PartnerKey xsi:nil="true" /> + <ObjectID xsi:nil="true" /> + <List> + <PartnerKey xsi:nil="true" /> + <ID>114</ID> + <ObjectID xsi:nil="true" /> + </List> + <SendDefinitionListType>SourceList</SendDefinitionListType> + <CustomObjectID>21711373-72c1-ec11-b83b-48df37d1deb7</CustomObjectID> + <DataSourceTypeID>CustomObject</DataSourceTypeID> + <IsTestObject>false</IsTestObject> + <Name /> + </SendDefinitionList> + <Email> + <PartnerKey xsi:nil="true" /> + <ID>531213</ID> + <ObjectID xsi:nil="true" /> + <Subject>testExisting_asset_email</Subject> + </Email> + <BccEmail /> + <AutoBccEmail /> + <TestEmailAddr /> + <EmailSubject>someSubject</EmailSubject> + <DynamicEmailSubject>someSubject</DynamicEmailSubject> + <IsMultipart>true</IsMultipart> + <IsWrapped>true</IsWrapped> + <DeduplicateByEmail>false</DeduplicateByEmail> + <ExclusionFilter /> + <Additional /> + <CCEmail /> + </Object> + </Results> + <RequestID>d961a829-bcbc-4f74-bbf3-66c3f391d471</RequestID> + <OverallStatus>OK</OverallStatus> + </UpdateResponse> + </soap:Body> +</soap:Envelope> diff --git a/test/resources/9999999/event-deploy/testNew_event_badExtension.bad-type-extension.json b/test/resources/9999999/event-deploy/testNew_event_badExtension.bad-type-extension.json new file mode 100644 index 000000000..1aac996b6 --- /dev/null +++ b/test/resources/9999999/event-deploy/testNew_event_badExtension.bad-type-extension.json @@ -0,0 +1,200 @@ +{ + "type": "APIEvent", + "name": "testNew_event_badExtension", + "description": "updated on deploy", + "mode": "Production", + "eventDefinitionKey": "testNew_event_badExtension", + "schema": { + "fields": [ + { + "name": "ContactId", + "dataType": "Text", + "maxLength": 18, + "isNullable": false, + "isPrimaryKey": true + }, + { + "name": "Type", + "dataType": "Text", + "maxLength": "50", + "isNullable": false, + "isPrimaryKey": false + }, + { + "name": "Status", + "dataType": "Text", + "maxLength": "50", + "isNullable": false, + "isPrimaryKey": true + }, + { + "name": "Respondent", + "dataType": "Text", + "maxLength": "256", + "isNullable": true, + "isPrimaryKey": false + }, + { + "name": "FirstName", + "dataType": "Text", + "maxLength": "256", + "isNullable": true, + "isPrimaryKey": false + }, + { + "name": "LastName", + "dataType": "Text", + "maxLength": "256", + "isNullable": true, + "isPrimaryKey": false + }, + { + "name": "PreferredLanguage", + "dataType": "Text", + "maxLength": "50", + "isNullable": true, + "isPrimaryKey": false + }, + { + "name": "TouchPoint", + "dataType": "Text", + "maxLength": "256", + "isNullable": true, + "isPrimaryKey": false + }, + { + "name": "Datestamp", + "dataType": "Date", + "defaultValue": "GetDate()", + "isNullable": true, + "isPrimaryKey": false + }, + { + "name": "StartDate", + "dataType": "Date", + "isNullable": true, + "defaultValue": "", + "isPrimaryKey": false + }, + { + "name": "EndDate", + "dataType": "Date", + "isNullable": true, + "isPrimaryKey": false + }, + { + "name": "BroadcastedNotificationDate", + "dataType": "Date", + "isNullable": true, + "defaultValue": "", + "isPrimaryKey": false + }, + { + "name": "FirstReminderDate", + "dataType": "Date", + "isNullable": true, + "isPrimaryKey": false + }, + { + "name": "SecondReminderDate", + "dataType": "Date", + "isNullable": true, + "isPrimaryKey": false + }, + { + "name": "Title", + "dataType": "Text", + "maxLength": "256", + "isNullable": true, + "isPrimaryKey": false + }, + { + "name": "DisplayName", + "dataType": "Text", + "maxLength": "256", + "isNullable": true, + "isPrimaryKey": false + }, + { + "name": "Text", + "dataType": "Text", + "maxLength": "256", + "isNullable": true, + "isPrimaryKey": false + }, + { + "name": "Description", + "dataType": "Text", + "maxLength": "4000", + "isNullable": true, + "isPrimaryKey": false + }, + { + "name": "Channel", + "dataType": "Text", + "maxLength": "256", + "isNullable": true, + "isPrimaryKey": false + }, + { + "name": "FirstReminderChannel", + "dataType": "Text", + "maxLength": "256", + "isNullable": true, + "isPrimaryKey": false + }, + { + "name": "SecondReminderChannel", + "dataType": "Text", + "maxLength": "256", + "isNullable": true, + "isPrimaryKey": false + }, + { + "name": "Email", + "dataType": "Email", + "maxLength": "", + "isNullable": true, + "isPrimaryKey": false + }, + { + "name": "ArticleOrTaskID", + "dataType": "Text", + "maxLength": "18", + "isNullable": false, + "isPrimaryKey": true + }, + { + "name": "Points", + "dataType": "Number", + "maxLength": "", + "isNullable": true, + "isPrimaryKey": false + }, + { + "name": "TaskType", + "dataType": "Text", + "maxLength": "255", + "isNullable": true, + "isPrimaryKey": false + }, + { + "name": "TaskArea", + "dataType": "Text", + "maxLength": "255", + "isNullable": true, + "isPrimaryKey": false + }, + { + "name": "AddedField", + "dataType": "Text", + "maxLength": "255", + "isNullable": true, + "isPrimaryKey": false + } + ], + "sendableCustomObjectField": "ContactId", + "sendableSubscriberField": "_SubscriberKey" + }, + "isVisibleInPicker": true +} diff --git a/test/resources/9999999/event-deploy/testNew_event_badName_bad.event-meta.json b/test/resources/9999999/event-deploy/testNew_event_badName_bad.event-meta.json new file mode 100644 index 000000000..3806c2917 --- /dev/null +++ b/test/resources/9999999/event-deploy/testNew_event_badName_bad.event-meta.json @@ -0,0 +1,200 @@ +{ + "type": "APIEvent", + "name": "testNew_event_badName", + "description": "updated on deploy", + "mode": "Production", + "eventDefinitionKey": "testNew_event_badName", + "schema": { + "fields": [ + { + "name": "ContactId", + "dataType": "Text", + "maxLength": 18, + "isNullable": false, + "isPrimaryKey": true + }, + { + "name": "Type", + "dataType": "Text", + "maxLength": "50", + "isNullable": false, + "isPrimaryKey": false + }, + { + "name": "Status", + "dataType": "Text", + "maxLength": "50", + "isNullable": false, + "isPrimaryKey": true + }, + { + "name": "Respondent", + "dataType": "Text", + "maxLength": "256", + "isNullable": true, + "isPrimaryKey": false + }, + { + "name": "FirstName", + "dataType": "Text", + "maxLength": "256", + "isNullable": true, + "isPrimaryKey": false + }, + { + "name": "LastName", + "dataType": "Text", + "maxLength": "256", + "isNullable": true, + "isPrimaryKey": false + }, + { + "name": "PreferredLanguage", + "dataType": "Text", + "maxLength": "50", + "isNullable": true, + "isPrimaryKey": false + }, + { + "name": "TouchPoint", + "dataType": "Text", + "maxLength": "256", + "isNullable": true, + "isPrimaryKey": false + }, + { + "name": "Datestamp", + "dataType": "Date", + "defaultValue": "GetDate()", + "isNullable": true, + "isPrimaryKey": false + }, + { + "name": "StartDate", + "dataType": "Date", + "isNullable": true, + "defaultValue": "", + "isPrimaryKey": false + }, + { + "name": "EndDate", + "dataType": "Date", + "isNullable": true, + "isPrimaryKey": false + }, + { + "name": "BroadcastedNotificationDate", + "dataType": "Date", + "isNullable": true, + "defaultValue": "", + "isPrimaryKey": false + }, + { + "name": "FirstReminderDate", + "dataType": "Date", + "isNullable": true, + "isPrimaryKey": false + }, + { + "name": "SecondReminderDate", + "dataType": "Date", + "isNullable": true, + "isPrimaryKey": false + }, + { + "name": "Title", + "dataType": "Text", + "maxLength": "256", + "isNullable": true, + "isPrimaryKey": false + }, + { + "name": "DisplayName", + "dataType": "Text", + "maxLength": "256", + "isNullable": true, + "isPrimaryKey": false + }, + { + "name": "Text", + "dataType": "Text", + "maxLength": "256", + "isNullable": true, + "isPrimaryKey": false + }, + { + "name": "Description", + "dataType": "Text", + "maxLength": "4000", + "isNullable": true, + "isPrimaryKey": false + }, + { + "name": "Channel", + "dataType": "Text", + "maxLength": "256", + "isNullable": true, + "isPrimaryKey": false + }, + { + "name": "FirstReminderChannel", + "dataType": "Text", + "maxLength": "256", + "isNullable": true, + "isPrimaryKey": false + }, + { + "name": "SecondReminderChannel", + "dataType": "Text", + "maxLength": "256", + "isNullable": true, + "isPrimaryKey": false + }, + { + "name": "Email", + "dataType": "Email", + "maxLength": "", + "isNullable": true, + "isPrimaryKey": false + }, + { + "name": "ArticleOrTaskID", + "dataType": "Text", + "maxLength": "18", + "isNullable": false, + "isPrimaryKey": true + }, + { + "name": "Points", + "dataType": "Number", + "maxLength": "", + "isNullable": true, + "isPrimaryKey": false + }, + { + "name": "TaskType", + "dataType": "Text", + "maxLength": "255", + "isNullable": true, + "isPrimaryKey": false + }, + { + "name": "TaskArea", + "dataType": "Text", + "maxLength": "255", + "isNullable": true, + "isPrimaryKey": false + }, + { + "name": "AddedField", + "dataType": "Text", + "maxLength": "255", + "isNullable": true, + "isPrimaryKey": false + } + ], + "sendableCustomObjectField": "ContactId", + "sendableSubscriberField": "_SubscriberKey" + }, + "isVisibleInPicker": true +} diff --git a/test/resources/9999999/event/build-expected.json b/test/resources/9999999/event/build-expected.json new file mode 100644 index 000000000..9fb64be7f --- /dev/null +++ b/test/resources/9999999/event/build-expected.json @@ -0,0 +1,226 @@ +{ + "type": "APIEvent", + "name": "testTemplated_event", + "description": "", + "eventDefinitionKey": "testTemplated_event", + "schema": { + "fields": [ + { + "name": "ContactId", + "dataType": "Text", + "maxLength": "18", + "isNullable": false, + "isPrimaryKey": true, + "isDevicePreference": false + }, + { + "name": "Type", + "dataType": "Text", + "maxLength": "50", + "isNullable": false, + "isPrimaryKey": false, + "isDevicePreference": false + }, + { + "name": "Status", + "dataType": "Text", + "maxLength": "50", + "isNullable": false, + "isPrimaryKey": true, + "isDevicePreference": false + }, + { + "name": "Respondent", + "dataType": "Text", + "maxLength": "256", + "isNullable": true, + "isPrimaryKey": false, + "isDevicePreference": false + }, + { + "name": "FirstName", + "dataType": "Text", + "maxLength": "256", + "isNullable": true, + "isPrimaryKey": false, + "isDevicePreference": false + }, + { + "name": "LastName", + "dataType": "Text", + "maxLength": "256", + "isNullable": true, + "isPrimaryKey": false, + "isDevicePreference": false + }, + { + "name": "PreferredLanguage", + "dataType": "Text", + "maxLength": "50", + "isNullable": true, + "isPrimaryKey": false, + "isDevicePreference": false + }, + { + "name": "TouchPoint", + "dataType": "Text", + "maxLength": "256", + "isNullable": true, + "isPrimaryKey": false, + "isDevicePreference": false + }, + { + "name": "Datestamp", + "dataType": "Date", + "isNullable": true, + "defaultValue": "GetDate()", + "isPrimaryKey": false, + "isDevicePreference": false + }, + { + "name": "StartDate", + "dataType": "Date", + "isNullable": true, + "defaultValue": "", + "isPrimaryKey": false, + "isDevicePreference": false + }, + { + "name": "EndDate", + "dataType": "Date", + "isNullable": true, + "isPrimaryKey": false, + "isDevicePreference": false + }, + { + "name": "BroadcastedNotificationDate", + "dataType": "Date", + "isNullable": true, + "defaultValue": "", + "isPrimaryKey": false, + "isDevicePreference": false + }, + { + "name": "FirstReminderDate", + "dataType": "Date", + "isNullable": true, + "isPrimaryKey": false, + "isDevicePreference": false + }, + { + "name": "SecondReminderDate", + "dataType": "Date", + "isNullable": true, + "isPrimaryKey": false, + "isDevicePreference": false + }, + { + "name": "Title", + "dataType": "Text", + "maxLength": "256", + "isNullable": true, + "isPrimaryKey": false, + "isDevicePreference": false + }, + { + "name": "DisplayName", + "dataType": "Text", + "maxLength": "256", + "isNullable": true, + "isPrimaryKey": false, + "isDevicePreference": false + }, + { + "name": "Text", + "dataType": "Text", + "maxLength": "256", + "isNullable": true, + "isPrimaryKey": false, + "isDevicePreference": false + }, + { + "name": "Description", + "dataType": "Text", + "maxLength": "4000", + "isNullable": true, + "isPrimaryKey": false, + "isDevicePreference": false + }, + { + "name": "Channel", + "dataType": "Text", + "maxLength": "256", + "isNullable": true, + "isPrimaryKey": false, + "isDevicePreference": false + }, + { + "name": "FirstReminderChannel", + "dataType": "Text", + "maxLength": "256", + "isNullable": true, + "isPrimaryKey": false, + "isDevicePreference": false + }, + { + "name": "SecondReminderChannel", + "dataType": "Text", + "maxLength": "256", + "isNullable": true, + "isPrimaryKey": false, + "isDevicePreference": false + }, + { + "name": "Email", + "dataType": "Email", + "maxLength": "", + "isNullable": true, + "isPrimaryKey": false, + "isDevicePreference": false + }, + { + "name": "ArticleOrTaskID", + "dataType": "Text", + "maxLength": "18", + "isNullable": false, + "isPrimaryKey": true, + "isDevicePreference": false + }, + { + "name": "Points", + "dataType": "Number", + "maxLength": "", + "isNullable": true, + "isPrimaryKey": false, + "isDevicePreference": false + }, + { + "name": "TaskType", + "dataType": "Text", + "maxLength": "255", + "isNullable": true, + "isPrimaryKey": false, + "isDevicePreference": false + }, + { + "name": "TaskArea", + "dataType": "Text", + "maxLength": "255", + "isNullable": true, + "isPrimaryKey": false, + "isDevicePreference": false + } + ], + "sendableCustomObjectField": "ContactId", + "sendableSubscriberField": "_SubscriberKey" + }, + "sourceApplicationExtensionId": "00000000-0000-0000-0000-000000000000", + "filterDefinitionTemplate": "", + "iconUrl": "", + "arguments": { "serializedObjectType": 11, "criteria": "" }, + "metaData": { "scheduleState": "No Schedule" }, + "isVisibleInPicker": true, + "category": "Event", + "disableDEDataLogging": false, + "r__dataExtension_key": "testTemplated_event - 2024-07-05T080154625" +} diff --git a/test/resources/9999999/event/get-automation-expected.json b/test/resources/9999999/event/get-automation-expected.json new file mode 100644 index 000000000..bdb133ce0 --- /dev/null +++ b/test/resources/9999999/event/get-automation-expected.json @@ -0,0 +1,41 @@ +{ + "type": "AutomationAudience", + "name": "testExisting_event_automation", + "description": "", + "createdDate": "2024-11-07T04:58:46.51", + "createdBy": "Jörn Berkefeld", + "modifiedDate": "2024-11-07T04:58:46.51", + "modifiedBy": "Jörn Berkefeld", + "eventDefinitionKey": "testExisting_event_automation", + "sourceApplicationExtensionId": "97e942ee-6914-4d3d-9e52-37ecb71f79ed", + "filterDefinitionTemplate": "", + "iconUrl": "/images/icon-data-extension.svg", + "arguments": { + "serializedObjectType": 9, + "useHighWatermark": true, + "resetHighWatermark": false, + "criteria": "" + }, + "configurationArguments": {}, + "metaData": { + "criteriaDescription": "", + "scheduleFlowMode": "automation" + }, + "schedule": { + "startDateTime": "2024-11-07T12:15:00", + "endDateTime": "2079-06-06T00:00:00", + "timeZone": "W. Europe Standard Time", + "occurrences": 478403, + "endType": "EndDate", + "frequency": "Hourly", + "recurrencePattern": "Interval", + "interval": 1 + }, + "interactionCount": 1, + "isVisibleInPicker": false, + "category": "Audience", + "publishedInteractionCount": 1, + "disableDEDataLogging": false, + "r__automation_key": "testExisting_automation_event", + "r__dataExtension_key": "testExisting_dataExtension" +} diff --git a/test/resources/9999999/event/get-expected.json b/test/resources/9999999/event/get-expected.json new file mode 100644 index 000000000..2573fbd19 --- /dev/null +++ b/test/resources/9999999/event/get-expected.json @@ -0,0 +1,232 @@ +{ + "type": "APIEvent", + "name": "testExisting_event", + "description": "", + "createdDate": "2024-07-05T06:12:24.227", + "createdBy": "Jörn Berkefeld", + "modifiedDate": "2024-07-05T08:01:55.4", + "modifiedBy": "Jörn Berkefeld", + "eventDefinitionKey": "testExisting_event", + "schema": { + "fields": [ + { + "name": "ContactId", + "dataType": "Text", + "maxLength": "18", + "isNullable": false, + "isPrimaryKey": true, + "isDevicePreference": false + }, + { + "name": "Type", + "dataType": "Text", + "maxLength": "50", + "isNullable": false, + "isPrimaryKey": false, + "isDevicePreference": false + }, + { + "name": "Status", + "dataType": "Text", + "maxLength": "50", + "isNullable": false, + "isPrimaryKey": true, + "isDevicePreference": false + }, + { + "name": "Respondent", + "dataType": "Text", + "maxLength": "256", + "isNullable": true, + "isPrimaryKey": false, + "isDevicePreference": false + }, + { + "name": "FirstName", + "dataType": "Text", + "maxLength": "256", + "isNullable": true, + "isPrimaryKey": false, + "isDevicePreference": false + }, + { + "name": "LastName", + "dataType": "Text", + "maxLength": "256", + "isNullable": true, + "isPrimaryKey": false, + "isDevicePreference": false + }, + { + "name": "PreferredLanguage", + "dataType": "Text", + "maxLength": "50", + "isNullable": true, + "isPrimaryKey": false, + "isDevicePreference": false + }, + { + "name": "TouchPoint", + "dataType": "Text", + "maxLength": "256", + "isNullable": true, + "isPrimaryKey": false, + "isDevicePreference": false + }, + { + "name": "Datestamp", + "dataType": "Date", + "isNullable": true, + "defaultValue": "GetDate()", + "isPrimaryKey": false, + "isDevicePreference": false + }, + { + "name": "StartDate", + "dataType": "Date", + "isNullable": true, + "defaultValue": "", + "isPrimaryKey": false, + "isDevicePreference": false + }, + { + "name": "EndDate", + "dataType": "Date", + "isNullable": true, + "isPrimaryKey": false, + "isDevicePreference": false + }, + { + "name": "BroadcastedNotificationDate", + "dataType": "Date", + "isNullable": true, + "defaultValue": "", + "isPrimaryKey": false, + "isDevicePreference": false + }, + { + "name": "FirstReminderDate", + "dataType": "Date", + "isNullable": true, + "isPrimaryKey": false, + "isDevicePreference": false + }, + { + "name": "SecondReminderDate", + "dataType": "Date", + "isNullable": true, + "isPrimaryKey": false, + "isDevicePreference": false + }, + { + "name": "Title", + "dataType": "Text", + "maxLength": "256", + "isNullable": true, + "isPrimaryKey": false, + "isDevicePreference": false + }, + { + "name": "DisplayName", + "dataType": "Text", + "maxLength": "256", + "isNullable": true, + "isPrimaryKey": false, + "isDevicePreference": false + }, + { + "name": "Text", + "dataType": "Text", + "maxLength": "256", + "isNullable": true, + "isPrimaryKey": false, + "isDevicePreference": false + }, + { + "name": "Description", + "dataType": "Text", + "maxLength": "4000", + "isNullable": true, + "isPrimaryKey": false, + "isDevicePreference": false + }, + { + "name": "Channel", + "dataType": "Text", + "maxLength": "256", + "isNullable": true, + "isPrimaryKey": false, + "isDevicePreference": false + }, + { + "name": "FirstReminderChannel", + "dataType": "Text", + "maxLength": "256", + "isNullable": true, + "isPrimaryKey": false, + "isDevicePreference": false + }, + { + "name": "SecondReminderChannel", + "dataType": "Text", + "maxLength": "256", + "isNullable": true, + "isPrimaryKey": false, + "isDevicePreference": false + }, + { + "name": "Email", + "dataType": "Email", + "maxLength": "", + "isNullable": true, + "isPrimaryKey": false, + "isDevicePreference": false + }, + { + "name": "ArticleOrTaskID", + "dataType": "Text", + "maxLength": "18", + "isNullable": false, + "isPrimaryKey": true, + "isDevicePreference": false + }, + { + "name": "Points", + "dataType": "Number", + "maxLength": "", + "isNullable": true, + "isPrimaryKey": false, + "isDevicePreference": false + }, + { + "name": "TaskType", + "dataType": "Text", + "maxLength": "255", + "isNullable": true, + "isPrimaryKey": false, + "isDevicePreference": false + }, + { + "name": "TaskArea", + "dataType": "Text", + "maxLength": "255", + "isNullable": true, + "isPrimaryKey": false, + "isDevicePreference": false + } + ], + "sendableCustomObjectField": "ContactId", + "sendableSubscriberField": "_SubscriberKey" + }, + "sourceApplicationExtensionId": "00000000-0000-0000-0000-000000000000", + "filterDefinitionTemplate": "", + "iconUrl": "", + "arguments": { "serializedObjectType": 11, "criteria": "" }, + "metaData": { "scheduleState": "No Schedule" }, + "interactionCount": 0, + "isVisibleInPicker": true, + "category": "Event", + "publishedInteractionCount": 0, + "disableDEDataLogging": false, + "r__dataExtension_key": "testExisting_event - 2024-07-05T080154625" +} diff --git a/test/resources/9999999/event/get-published-expected.json b/test/resources/9999999/event/get-published-expected.json new file mode 100644 index 000000000..74a0c3a4e --- /dev/null +++ b/test/resources/9999999/event/get-published-expected.json @@ -0,0 +1,28 @@ +{ + "type": "EmailAudience", + "name": "testExisting_journey_Multistep", + "description": "", + "createdDate": "2024-05-04T05:54:44.95", + "createdBy": "Jörn Berkefeld", + "modifiedDate": "2024-05-04T05:54:44.95", + "modifiedBy": "Jörn Berkefeld", + "eventDefinitionKey": "DEAudience-2e3c73b6-48cc-2ec0-5522-48636e1a236e", + "sourceApplicationExtensionId": "97e942ee-6914-4d3d-9e52-37ecb71f79ed", + "filterDefinitionTemplate": "", + "iconUrl": "/images/icon-data-extension.svg", + "configurationArguments": {}, + "arguments": { + "serializedObjectType": 3, + "criteria": "" + }, + "metaData": { + "criteriaDescription": "", + "scheduleState": "No Schedule" + }, + "interactionCount": 1, + "isVisibleInPicker": false, + "category": "Audience", + "publishedInteractionCount": 0, + "disableDEDataLogging": false, + "r__dataExtension_key": "testExisting_journey_Multistep" +} diff --git a/test/resources/9999999/event/post_withExistingDE-callout-expected.json b/test/resources/9999999/event/post_withExistingDE-callout-expected.json new file mode 100644 index 000000000..78d84c474 --- /dev/null +++ b/test/resources/9999999/event/post_withExistingDE-callout-expected.json @@ -0,0 +1,231 @@ +{ + "type": "APIEvent", + "name": "testNew_event_withExistingDE", + "description": "created on deploy", + "eventDefinitionKey": "testNew_event_withExistingDE", + "schema": { + "fields": [ + { + "dataType": "Text", + "isDevicePreference": false, + "isNullable": false, + "isPrimaryKey": true, + "maxLength": "18", + "name": "ContactId" + }, + { + "dataType": "Text", + "isDevicePreference": false, + "isNullable": false, + "isPrimaryKey": false, + "maxLength": "50", + "name": "Type" + }, + { + "dataType": "Text", + "isDevicePreference": false, + "isNullable": false, + "isPrimaryKey": true, + "maxLength": "50", + "name": "Status" + }, + { + "dataType": "Text", + "isDevicePreference": false, + "isNullable": true, + "isPrimaryKey": false, + "maxLength": "256", + "name": "Respondent" + }, + { + "dataType": "Text", + "isDevicePreference": false, + "isNullable": true, + "isPrimaryKey": false, + "maxLength": "256", + "name": "FirstName" + }, + { + "dataType": "Text", + "isDevicePreference": false, + "isNullable": true, + "isPrimaryKey": false, + "maxLength": "256", + "name": "LastName" + }, + { + "dataType": "Text", + "isDevicePreference": false, + "isNullable": true, + "isPrimaryKey": false, + "maxLength": "50", + "name": "PreferredLanguage" + }, + { + "dataType": "Text", + "isDevicePreference": false, + "isNullable": true, + "isPrimaryKey": false, + "maxLength": "256", + "name": "TouchPoint" + }, + { + "dataType": "Date", + "defaultValue": "GetDate()", + "isDevicePreference": false, + "isNullable": true, + "isPrimaryKey": false, + "name": "Datestamp" + }, + { + "dataType": "Date", + "defaultValue": "", + "isDevicePreference": false, + "isNullable": true, + "isPrimaryKey": false, + "name": "StartDate" + }, + { + "dataType": "Date", + "isDevicePreference": false, + "isNullable": true, + "isPrimaryKey": false, + "name": "EndDate" + }, + { + "dataType": "Date", + "defaultValue": "", + "isDevicePreference": false, + "isNullable": true, + "isPrimaryKey": false, + "name": "BroadcastedNotificationDate" + }, + { + "dataType": "Date", + "isDevicePreference": false, + "isNullable": true, + "isPrimaryKey": false, + "name": "FirstReminderDate" + }, + { + "dataType": "Date", + "isDevicePreference": false, + "isNullable": true, + "isPrimaryKey": false, + "name": "SecondReminderDate" + }, + { + "dataType": "Text", + "isDevicePreference": false, + "isNullable": true, + "isPrimaryKey": false, + "maxLength": "256", + "name": "Title" + }, + { + "dataType": "Text", + "isDevicePreference": false, + "isNullable": true, + "isPrimaryKey": false, + "maxLength": "256", + "name": "DisplayName" + }, + { + "dataType": "Text", + "isDevicePreference": false, + "isNullable": true, + "isPrimaryKey": false, + "maxLength": "256", + "name": "Text" + }, + { + "dataType": "Text", + "isDevicePreference": false, + "isNullable": true, + "isPrimaryKey": false, + "maxLength": "4000", + "name": "Description" + }, + { + "dataType": "Text", + "isDevicePreference": false, + "isNullable": true, + "isPrimaryKey": false, + "maxLength": "256", + "name": "Channel" + }, + { + "dataType": "Text", + "isDevicePreference": false, + "isNullable": true, + "isPrimaryKey": false, + "maxLength": "256", + "name": "FirstReminderChannel" + }, + { + "dataType": "Text", + "isDevicePreference": false, + "isNullable": true, + "isPrimaryKey": false, + "maxLength": "256", + "name": "SecondReminderChannel" + }, + { + "dataType": "Email", + "isDevicePreference": false, + "isNullable": true, + "isPrimaryKey": false, + "maxLength": "", + "name": "Email" + }, + { + "dataType": "Text", + "isDevicePreference": false, + "isNullable": false, + "isPrimaryKey": true, + "maxLength": "18", + "name": "ArticleOrTaskID" + }, + { + "dataType": "Number", + "isDevicePreference": false, + "isNullable": true, + "isPrimaryKey": false, + "maxLength": "", + "name": "Points" + }, + { + "dataType": "Text", + "isDevicePreference": false, + "isNullable": true, + "isPrimaryKey": false, + "maxLength": "255", + "name": "TaskType" + }, + { + "dataType": "Text", + "isDevicePreference": false, + "isNullable": true, + "isPrimaryKey": false, + "maxLength": "255", + "name": "TaskArea" + } + ], + "sendableCustomObjectField": "ContactId", + "sendableSubscriberField": "_SubscriberKey" + }, + "entrySourceGroupConfigUrl": "jb:///data/entry/api-event/entrysourcegroupconfig.json", + "iconUrl": "/images/icon_journeyBuilder-event-api-blue.svg", + "sourceApplicationExtensionId": "7db1f972-f8b7-49b6-91b5-fa218e13953d", + "filterDefinitionId": "00000000-0000-0000-0000-000000000000", + "arguments": { + "serializedObjectType": 11, + "eventDefinitionKey": "testNew_event_withExistingDE" + }, + "metaData": {}, + "isVisibleInPicker": true, + "category": "Event", + "automationId": "00000000-0000-0000-0000-000000000000", + "mode": "Production", + "dataExtensionId": "f2cc2b21-d73a-ef11-a5c8-5cba2c702db8" +} diff --git a/test/resources/9999999/event/post_withExistingDE-expected.json b/test/resources/9999999/event/post_withExistingDE-expected.json new file mode 100644 index 000000000..d49cc2483 --- /dev/null +++ b/test/resources/9999999/event/post_withExistingDE-expected.json @@ -0,0 +1,21 @@ +{ + "type": "APIEvent", + "name": "testNew_event_withExistingDE", + "description": "created on deploy", + "createdDate": "0001-01-01T00:00:00", + "createdBy": 0, + "modifiedDate": "0001-01-01T00:00:00", + "modifiedBy": 0, + "eventDefinitionKey": "testNew_event_withExistingDE", + "iconUrl": "/images/icon_journeyBuilder-event-api-blue.svg", + "sourceApplicationExtensionId": "7db1f972-f8b7-49b6-91b5-fa218e13953d", + "arguments": { + "serializedObjectType": 11 + }, + "metaData": {}, + "interactionCount": 0, + "isVisibleInPicker": true, + "category": "Event", + "publishedInteractionCount": 0, + "r__dataExtension_key": "testExisting_event - 2024-07-05T080154625" +} diff --git a/test/resources/9999999/event/post_withSchema-callout-expected.json b/test/resources/9999999/event/post_withSchema-callout-expected.json new file mode 100644 index 000000000..aefd382d4 --- /dev/null +++ b/test/resources/9999999/event/post_withSchema-callout-expected.json @@ -0,0 +1,202 @@ +{ + "type": "APIEvent", + "name": "testNew_event_withSchema", + "description": "created on deploy", + "mode": "Production", + "automationId": "00000000-0000-0000-0000-000000000000", + "filterDefinitionId": "00000000-0000-0000-0000-000000000000", + "eventDefinitionKey": "testNew_event_withSchema", + "sourceApplicationExtensionId": "7db1f972-f8b7-49b6-91b5-fa218e13953d", + "entrySourceGroupConfigUrl": "jb:///data/entry/api-event/entrysourcegroupconfig.json", + "iconUrl": "/images/icon_journeyBuilder-event-api-blue.svg", + "schema": { + "fields": [ + { + "name": "ContactId", + "dataType": "Text", + "maxLength": 18, + "isNullable": false, + "isPrimaryKey": true + }, + { + "name": "Type", + "dataType": "Text", + "maxLength": "50", + "isNullable": false, + "isPrimaryKey": false + }, + { + "name": "Status", + "dataType": "Text", + "maxLength": "50", + "isNullable": false, + "isPrimaryKey": true + }, + { + "name": "Respondent", + "dataType": "Text", + "maxLength": "256", + "isNullable": true, + "isPrimaryKey": false + }, + { + "name": "FirstName", + "dataType": "Text", + "maxLength": "256", + "isNullable": true, + "isPrimaryKey": false + }, + { + "name": "LastName", + "dataType": "Text", + "maxLength": "256", + "isNullable": true, + "isPrimaryKey": false + }, + { + "name": "PreferredLanguage", + "dataType": "Text", + "maxLength": "50", + "isNullable": true, + "isPrimaryKey": false + }, + { + "name": "TouchPoint", + "dataType": "Text", + "maxLength": "256", + "isNullable": true, + "isPrimaryKey": false + }, + { + "name": "Datestamp", + "dataType": "Date", + "defaultValue": "GetDate()", + "isNullable": true, + "isPrimaryKey": false + }, + { + "name": "StartDate", + "dataType": "Date", + "isNullable": true, + "defaultValue": "", + "isPrimaryKey": false + }, + { + "name": "EndDate", + "dataType": "Date", + "isNullable": true, + "isPrimaryKey": false + }, + { + "name": "BroadcastedNotificationDate", + "dataType": "Date", + "isNullable": true, + "defaultValue": "", + "isPrimaryKey": false + }, + { + "name": "FirstReminderDate", + "dataType": "Date", + "isNullable": true, + "isPrimaryKey": false + }, + { + "name": "SecondReminderDate", + "dataType": "Date", + "isNullable": true, + "isPrimaryKey": false + }, + { + "name": "Title", + "dataType": "Text", + "maxLength": "256", + "isNullable": true, + "isPrimaryKey": false + }, + { + "name": "DisplayName", + "dataType": "Text", + "maxLength": "256", + "isNullable": true, + "isPrimaryKey": false + }, + { + "name": "Text", + "dataType": "Text", + "maxLength": "256", + "isNullable": true, + "isPrimaryKey": false + }, + { + "name": "Description", + "dataType": "Text", + "maxLength": "4000", + "isNullable": true, + "isPrimaryKey": false + }, + { + "name": "Channel", + "dataType": "Text", + "maxLength": "256", + "isNullable": true, + "isPrimaryKey": false + }, + { + "name": "FirstReminderChannel", + "dataType": "Text", + "maxLength": "256", + "isNullable": true, + "isPrimaryKey": false + }, + { + "name": "SecondReminderChannel", + "dataType": "Text", + "maxLength": "256", + "isNullable": true, + "isPrimaryKey": false + }, + { + "name": "Email", + "dataType": "Email", + "maxLength": "", + "isNullable": true, + "isPrimaryKey": false + }, + { + "name": "ArticleOrTaskID", + "dataType": "Text", + "maxLength": "18", + "isNullable": false, + "isPrimaryKey": true + }, + { + "name": "Points", + "dataType": "Number", + "maxLength": "", + "isNullable": true, + "isPrimaryKey": false + }, + { + "name": "TaskType", + "dataType": "Text", + "maxLength": "255", + "isNullable": true, + "isPrimaryKey": false + }, + { + "name": "TaskArea", + "dataType": "Text", + "maxLength": "255", + "isNullable": true, + "isPrimaryKey": false + } + ], + "sendableCustomObjectField": "ContactId", + "sendableSubscriberField": "_SubscriberKey" + }, + "isVisibleInPicker": true, + "arguments": { + "automationId": "00000000-0000-0000-0000-000000000000", + "eventDefinitionKey": "testNew_event_withSchema" + } +} diff --git a/test/resources/9999999/event/post_withSchema-expected.json b/test/resources/9999999/event/post_withSchema-expected.json new file mode 100644 index 000000000..b8585305f --- /dev/null +++ b/test/resources/9999999/event/post_withSchema-expected.json @@ -0,0 +1,232 @@ +{ + "type": "APIEvent", + "name": "testNew_event_withSchema", + "description": "created on deploy", + "createdDate": "0001-01-01T00:00:00", + "createdBy": 0, + "modifiedDate": "0001-01-01T00:00:00", + "modifiedBy": 0, + "eventDefinitionKey": "testNew_event_withSchema", + "iconUrl": "/images/icon_journeyBuilder-event-api-blue.svg", + "sourceApplicationExtensionId": "7db1f972-f8b7-49b6-91b5-fa218e13953d", + "schema": { + "fields": [ + { + "name": "ContactId", + "dataType": "Text", + "maxLength": "18", + "isNullable": false, + "isPrimaryKey": true, + "isDevicePreference": false + }, + { + "name": "Type", + "dataType": "Text", + "maxLength": "50", + "isNullable": false, + "isPrimaryKey": false, + "isDevicePreference": false + }, + { + "name": "Status", + "dataType": "Text", + "maxLength": "50", + "isNullable": false, + "isPrimaryKey": true, + "isDevicePreference": false + }, + { + "name": "Respondent", + "dataType": "Text", + "maxLength": "256", + "isNullable": true, + "isPrimaryKey": false, + "isDevicePreference": false + }, + { + "name": "FirstName", + "dataType": "Text", + "maxLength": "256", + "isNullable": true, + "isPrimaryKey": false, + "isDevicePreference": false + }, + { + "name": "LastName", + "dataType": "Text", + "maxLength": "256", + "isNullable": true, + "isPrimaryKey": false, + "isDevicePreference": false + }, + { + "name": "PreferredLanguage", + "dataType": "Text", + "maxLength": "50", + "isNullable": true, + "isPrimaryKey": false, + "isDevicePreference": false + }, + { + "name": "TouchPoint", + "dataType": "Text", + "maxLength": "256", + "isNullable": true, + "isPrimaryKey": false, + "isDevicePreference": false + }, + { + "name": "Datestamp", + "dataType": "Date", + "isNullable": true, + "defaultValue": "GetDate()", + "isPrimaryKey": false, + "isDevicePreference": false + }, + { + "name": "StartDate", + "dataType": "Date", + "isNullable": true, + "defaultValue": "", + "isPrimaryKey": false, + "isDevicePreference": false + }, + { + "name": "EndDate", + "dataType": "Date", + "isNullable": true, + "isPrimaryKey": false, + "isDevicePreference": false + }, + { + "name": "BroadcastedNotificationDate", + "dataType": "Date", + "isNullable": true, + "defaultValue": "", + "isPrimaryKey": false, + "isDevicePreference": false + }, + { + "name": "FirstReminderDate", + "dataType": "Date", + "isNullable": true, + "isPrimaryKey": false, + "isDevicePreference": false + }, + { + "name": "SecondReminderDate", + "dataType": "Date", + "isNullable": true, + "isPrimaryKey": false, + "isDevicePreference": false + }, + { + "name": "Title", + "dataType": "Text", + "maxLength": "256", + "isNullable": true, + "isPrimaryKey": false, + "isDevicePreference": false + }, + { + "name": "DisplayName", + "dataType": "Text", + "maxLength": "256", + "isNullable": true, + "isPrimaryKey": false, + "isDevicePreference": false + }, + { + "name": "Text", + "dataType": "Text", + "maxLength": "256", + "isNullable": true, + "isPrimaryKey": false, + "isDevicePreference": false + }, + { + "name": "Description", + "dataType": "Text", + "maxLength": "4000", + "isNullable": true, + "isPrimaryKey": false, + "isDevicePreference": false + }, + { + "name": "Channel", + "dataType": "Text", + "maxLength": "256", + "isNullable": true, + "isPrimaryKey": false, + "isDevicePreference": false + }, + { + "name": "FirstReminderChannel", + "dataType": "Text", + "maxLength": "256", + "isNullable": true, + "isPrimaryKey": false, + "isDevicePreference": false + }, + { + "name": "SecondReminderChannel", + "dataType": "Text", + "maxLength": "256", + "isNullable": true, + "isPrimaryKey": false, + "isDevicePreference": false + }, + { + "name": "Email", + "dataType": "Email", + "maxLength": "", + "isNullable": true, + "isPrimaryKey": false, + "isDevicePreference": false + }, + { + "name": "ArticleOrTaskID", + "dataType": "Text", + "maxLength": "18", + "isNullable": false, + "isPrimaryKey": true, + "isDevicePreference": false + }, + { + "name": "Points", + "dataType": "Number", + "maxLength": "", + "isNullable": true, + "isPrimaryKey": false, + "isDevicePreference": false + }, + { + "name": "TaskType", + "dataType": "Text", + "maxLength": "255", + "isNullable": true, + "isPrimaryKey": false, + "isDevicePreference": false + }, + { + "name": "TaskArea", + "dataType": "Text", + "maxLength": "255", + "isNullable": true, + "isPrimaryKey": false, + "isDevicePreference": false + } + ], + "sendableCustomObjectField": "ContactId", + "sendableSubscriberField": "_SubscriberKey" + }, + "arguments": { + "serializedObjectType": 11 + }, + "metaData": {}, + "interactionCount": 0, + "isVisibleInPicker": true, + "category": "Event", + "publishedInteractionCount": 0, + "r__dataExtension_key": "testNew_event_withSchema" +} diff --git a/test/resources/9999999/event/put-callout-expected.json b/test/resources/9999999/event/put-callout-expected.json new file mode 100644 index 000000000..c4a570f2b --- /dev/null +++ b/test/resources/9999999/event/put-callout-expected.json @@ -0,0 +1,207 @@ +{ + "type": "APIEvent", + "name": "testExisting_event", + "description": "updated on deploy", + "mode": "Production", + "eventDefinitionKey": "testExisting_event", + "entrySourceGroupConfigUrl": "jb:///data/entry/api-event/entrysourcegroupconfig.json", + "automationId": "00000000-0000-0000-0000-000000000000", + "filterDefinitionId": "00000000-0000-0000-0000-000000000000", + "iconUrl": "/images/icon_journeyBuilder-event-api-blue.svg", + "schema": { + "fields": [ + { + "name": "ContactId", + "dataType": "Text", + "maxLength": "18", + "isNullable": false, + "isPrimaryKey": true + }, + { + "name": "Type", + "dataType": "Text", + "maxLength": "50", + "isNullable": false, + "isPrimaryKey": false + }, + { + "name": "Status", + "dataType": "Text", + "maxLength": "50", + "isNullable": false, + "isPrimaryKey": true + }, + { + "name": "Respondent", + "dataType": "Text", + "maxLength": "256", + "isNullable": true, + "isPrimaryKey": false + }, + { + "name": "FirstName", + "dataType": "Text", + "maxLength": "256", + "isNullable": true, + "isPrimaryKey": false + }, + { + "name": "LastName", + "dataType": "Text", + "maxLength": "256", + "isNullable": true, + "isPrimaryKey": false + }, + { + "name": "PreferredLanguage", + "dataType": "Text", + "maxLength": "50", + "isNullable": true, + "isPrimaryKey": false + }, + { + "name": "TouchPoint", + "dataType": "Text", + "maxLength": "256", + "isNullable": true, + "isPrimaryKey": false + }, + { + "name": "Datestamp", + "dataType": "Date", + "defaultValue": "GetDate()", + "isNullable": true, + "isPrimaryKey": false + }, + { + "name": "StartDate", + "dataType": "Date", + "isNullable": true, + "defaultValue": "", + "isPrimaryKey": false + }, + { + "name": "EndDate", + "dataType": "Date", + "isNullable": true, + "isPrimaryKey": false + }, + { + "name": "BroadcastedNotificationDate", + "dataType": "Date", + "isNullable": true, + "defaultValue": "", + "isPrimaryKey": false + }, + { + "name": "FirstReminderDate", + "dataType": "Date", + "isNullable": true, + "isPrimaryKey": false + }, + { + "name": "SecondReminderDate", + "dataType": "Date", + "isNullable": true, + "isPrimaryKey": false + }, + { + "name": "Title", + "dataType": "Text", + "maxLength": "256", + "isNullable": true, + "isPrimaryKey": false + }, + { + "name": "DisplayName", + "dataType": "Text", + "maxLength": "256", + "isNullable": true, + "isPrimaryKey": false + }, + { + "name": "Text", + "dataType": "Text", + "maxLength": "256", + "isNullable": true, + "isPrimaryKey": false + }, + { + "name": "Description", + "dataType": "Text", + "maxLength": "4000", + "isNullable": true, + "isPrimaryKey": false + }, + { + "name": "Channel", + "dataType": "Text", + "maxLength": "256", + "isNullable": true, + "isPrimaryKey": false + }, + { + "name": "FirstReminderChannel", + "dataType": "Text", + "maxLength": "256", + "isNullable": true, + "isPrimaryKey": false + }, + { + "name": "SecondReminderChannel", + "dataType": "Text", + "maxLength": "256", + "isNullable": true, + "isPrimaryKey": false + }, + { + "name": "Email", + "dataType": "Email", + "maxLength": "", + "isNullable": true, + "isPrimaryKey": false + }, + { + "name": "ArticleOrTaskID", + "dataType": "Text", + "maxLength": "18", + "isNullable": false, + "isPrimaryKey": true + }, + { + "name": "Points", + "dataType": "Number", + "maxLength": "", + "isNullable": true, + "isPrimaryKey": false + }, + { + "name": "TaskType", + "dataType": "Text", + "maxLength": "255", + "isNullable": true, + "isPrimaryKey": false + }, + { + "name": "TaskArea", + "dataType": "Text", + "maxLength": "255", + "isNullable": true, + "isPrimaryKey": false + } + ], + "sendableCustomObjectField": "ContactId", + "sendableSubscriberField": "_SubscriberKey", + "id": "f2cc2b21-d73a-ef11-a5c8-5cba2c702db8", + "name": "testExisting_event - 2024-07-05T080154625" + }, + "isVisibleInPicker": false, + "arguments": { + "automationId": "00000000-0000-0000-0000-000000000000", + "eventDefinitionKey": "testExisting_event", + "dataExtensionId": "f2cc2b21-d73a-ef11-a5c8-5cba2c702db8" + }, + "isPlatformObject": false, + "id": "d8d57832-ce9c-4bf6-8c24-3044ece5dffd", + "dataExtensionId": "f2cc2b21-d73a-ef11-a5c8-5cba2c702db8" +} diff --git a/test/resources/9999999/event/put-expected.json b/test/resources/9999999/event/put-expected.json new file mode 100644 index 000000000..2573fbd19 --- /dev/null +++ b/test/resources/9999999/event/put-expected.json @@ -0,0 +1,232 @@ +{ + "type": "APIEvent", + "name": "testExisting_event", + "description": "", + "createdDate": "2024-07-05T06:12:24.227", + "createdBy": "Jörn Berkefeld", + "modifiedDate": "2024-07-05T08:01:55.4", + "modifiedBy": "Jörn Berkefeld", + "eventDefinitionKey": "testExisting_event", + "schema": { + "fields": [ + { + "name": "ContactId", + "dataType": "Text", + "maxLength": "18", + "isNullable": false, + "isPrimaryKey": true, + "isDevicePreference": false + }, + { + "name": "Type", + "dataType": "Text", + "maxLength": "50", + "isNullable": false, + "isPrimaryKey": false, + "isDevicePreference": false + }, + { + "name": "Status", + "dataType": "Text", + "maxLength": "50", + "isNullable": false, + "isPrimaryKey": true, + "isDevicePreference": false + }, + { + "name": "Respondent", + "dataType": "Text", + "maxLength": "256", + "isNullable": true, + "isPrimaryKey": false, + "isDevicePreference": false + }, + { + "name": "FirstName", + "dataType": "Text", + "maxLength": "256", + "isNullable": true, + "isPrimaryKey": false, + "isDevicePreference": false + }, + { + "name": "LastName", + "dataType": "Text", + "maxLength": "256", + "isNullable": true, + "isPrimaryKey": false, + "isDevicePreference": false + }, + { + "name": "PreferredLanguage", + "dataType": "Text", + "maxLength": "50", + "isNullable": true, + "isPrimaryKey": false, + "isDevicePreference": false + }, + { + "name": "TouchPoint", + "dataType": "Text", + "maxLength": "256", + "isNullable": true, + "isPrimaryKey": false, + "isDevicePreference": false + }, + { + "name": "Datestamp", + "dataType": "Date", + "isNullable": true, + "defaultValue": "GetDate()", + "isPrimaryKey": false, + "isDevicePreference": false + }, + { + "name": "StartDate", + "dataType": "Date", + "isNullable": true, + "defaultValue": "", + "isPrimaryKey": false, + "isDevicePreference": false + }, + { + "name": "EndDate", + "dataType": "Date", + "isNullable": true, + "isPrimaryKey": false, + "isDevicePreference": false + }, + { + "name": "BroadcastedNotificationDate", + "dataType": "Date", + "isNullable": true, + "defaultValue": "", + "isPrimaryKey": false, + "isDevicePreference": false + }, + { + "name": "FirstReminderDate", + "dataType": "Date", + "isNullable": true, + "isPrimaryKey": false, + "isDevicePreference": false + }, + { + "name": "SecondReminderDate", + "dataType": "Date", + "isNullable": true, + "isPrimaryKey": false, + "isDevicePreference": false + }, + { + "name": "Title", + "dataType": "Text", + "maxLength": "256", + "isNullable": true, + "isPrimaryKey": false, + "isDevicePreference": false + }, + { + "name": "DisplayName", + "dataType": "Text", + "maxLength": "256", + "isNullable": true, + "isPrimaryKey": false, + "isDevicePreference": false + }, + { + "name": "Text", + "dataType": "Text", + "maxLength": "256", + "isNullable": true, + "isPrimaryKey": false, + "isDevicePreference": false + }, + { + "name": "Description", + "dataType": "Text", + "maxLength": "4000", + "isNullable": true, + "isPrimaryKey": false, + "isDevicePreference": false + }, + { + "name": "Channel", + "dataType": "Text", + "maxLength": "256", + "isNullable": true, + "isPrimaryKey": false, + "isDevicePreference": false + }, + { + "name": "FirstReminderChannel", + "dataType": "Text", + "maxLength": "256", + "isNullable": true, + "isPrimaryKey": false, + "isDevicePreference": false + }, + { + "name": "SecondReminderChannel", + "dataType": "Text", + "maxLength": "256", + "isNullable": true, + "isPrimaryKey": false, + "isDevicePreference": false + }, + { + "name": "Email", + "dataType": "Email", + "maxLength": "", + "isNullable": true, + "isPrimaryKey": false, + "isDevicePreference": false + }, + { + "name": "ArticleOrTaskID", + "dataType": "Text", + "maxLength": "18", + "isNullable": false, + "isPrimaryKey": true, + "isDevicePreference": false + }, + { + "name": "Points", + "dataType": "Number", + "maxLength": "", + "isNullable": true, + "isPrimaryKey": false, + "isDevicePreference": false + }, + { + "name": "TaskType", + "dataType": "Text", + "maxLength": "255", + "isNullable": true, + "isPrimaryKey": false, + "isDevicePreference": false + }, + { + "name": "TaskArea", + "dataType": "Text", + "maxLength": "255", + "isNullable": true, + "isPrimaryKey": false, + "isDevicePreference": false + } + ], + "sendableCustomObjectField": "ContactId", + "sendableSubscriberField": "_SubscriberKey" + }, + "sourceApplicationExtensionId": "00000000-0000-0000-0000-000000000000", + "filterDefinitionTemplate": "", + "iconUrl": "", + "arguments": { "serializedObjectType": 11, "criteria": "" }, + "metaData": { "scheduleState": "No Schedule" }, + "interactionCount": 0, + "isVisibleInPicker": true, + "category": "Event", + "publishedInteractionCount": 0, + "disableDEDataLogging": false, + "r__dataExtension_key": "testExisting_event - 2024-07-05T080154625" +} diff --git a/test/resources/9999999/event/template-expected.json b/test/resources/9999999/event/template-expected.json new file mode 100644 index 000000000..ca2f69df6 --- /dev/null +++ b/test/resources/9999999/event/template-expected.json @@ -0,0 +1,226 @@ +{ + "type": "APIEvent", + "name": "{{{prefix}}}event", + "description": "", + "eventDefinitionKey": "{{{prefix}}}event", + "schema": { + "fields": [ + { + "name": "ContactId", + "dataType": "Text", + "maxLength": "18", + "isNullable": false, + "isPrimaryKey": true, + "isDevicePreference": false + }, + { + "name": "Type", + "dataType": "Text", + "maxLength": "50", + "isNullable": false, + "isPrimaryKey": false, + "isDevicePreference": false + }, + { + "name": "Status", + "dataType": "Text", + "maxLength": "50", + "isNullable": false, + "isPrimaryKey": true, + "isDevicePreference": false + }, + { + "name": "Respondent", + "dataType": "Text", + "maxLength": "256", + "isNullable": true, + "isPrimaryKey": false, + "isDevicePreference": false + }, + { + "name": "FirstName", + "dataType": "Text", + "maxLength": "256", + "isNullable": true, + "isPrimaryKey": false, + "isDevicePreference": false + }, + { + "name": "LastName", + "dataType": "Text", + "maxLength": "256", + "isNullable": true, + "isPrimaryKey": false, + "isDevicePreference": false + }, + { + "name": "PreferredLanguage", + "dataType": "Text", + "maxLength": "50", + "isNullable": true, + "isPrimaryKey": false, + "isDevicePreference": false + }, + { + "name": "TouchPoint", + "dataType": "Text", + "maxLength": "256", + "isNullable": true, + "isPrimaryKey": false, + "isDevicePreference": false + }, + { + "name": "Datestamp", + "dataType": "Date", + "isNullable": true, + "defaultValue": "GetDate()", + "isPrimaryKey": false, + "isDevicePreference": false + }, + { + "name": "StartDate", + "dataType": "Date", + "isNullable": true, + "defaultValue": "", + "isPrimaryKey": false, + "isDevicePreference": false + }, + { + "name": "EndDate", + "dataType": "Date", + "isNullable": true, + "isPrimaryKey": false, + "isDevicePreference": false + }, + { + "name": "BroadcastedNotificationDate", + "dataType": "Date", + "isNullable": true, + "defaultValue": "", + "isPrimaryKey": false, + "isDevicePreference": false + }, + { + "name": "FirstReminderDate", + "dataType": "Date", + "isNullable": true, + "isPrimaryKey": false, + "isDevicePreference": false + }, + { + "name": "SecondReminderDate", + "dataType": "Date", + "isNullable": true, + "isPrimaryKey": false, + "isDevicePreference": false + }, + { + "name": "Title", + "dataType": "Text", + "maxLength": "256", + "isNullable": true, + "isPrimaryKey": false, + "isDevicePreference": false + }, + { + "name": "DisplayName", + "dataType": "Text", + "maxLength": "256", + "isNullable": true, + "isPrimaryKey": false, + "isDevicePreference": false + }, + { + "name": "Text", + "dataType": "Text", + "maxLength": "256", + "isNullable": true, + "isPrimaryKey": false, + "isDevicePreference": false + }, + { + "name": "Description", + "dataType": "Text", + "maxLength": "4000", + "isNullable": true, + "isPrimaryKey": false, + "isDevicePreference": false + }, + { + "name": "Channel", + "dataType": "Text", + "maxLength": "256", + "isNullable": true, + "isPrimaryKey": false, + "isDevicePreference": false + }, + { + "name": "FirstReminderChannel", + "dataType": "Text", + "maxLength": "256", + "isNullable": true, + "isPrimaryKey": false, + "isDevicePreference": false + }, + { + "name": "SecondReminderChannel", + "dataType": "Text", + "maxLength": "256", + "isNullable": true, + "isPrimaryKey": false, + "isDevicePreference": false + }, + { + "name": "Email", + "dataType": "Email", + "maxLength": "", + "isNullable": true, + "isPrimaryKey": false, + "isDevicePreference": false + }, + { + "name": "ArticleOrTaskID", + "dataType": "Text", + "maxLength": "18", + "isNullable": false, + "isPrimaryKey": true, + "isDevicePreference": false + }, + { + "name": "Points", + "dataType": "Number", + "maxLength": "", + "isNullable": true, + "isPrimaryKey": false, + "isDevicePreference": false + }, + { + "name": "TaskType", + "dataType": "Text", + "maxLength": "255", + "isNullable": true, + "isPrimaryKey": false, + "isDevicePreference": false + }, + { + "name": "TaskArea", + "dataType": "Text", + "maxLength": "255", + "isNullable": true, + "isPrimaryKey": false, + "isDevicePreference": false + } + ], + "sendableCustomObjectField": "ContactId", + "sendableSubscriberField": "_SubscriberKey" + }, + "sourceApplicationExtensionId": "00000000-0000-0000-0000-000000000000", + "filterDefinitionTemplate": "", + "iconUrl": "", + "arguments": { "serializedObjectType": 11, "criteria": "" }, + "metaData": { "scheduleState": "No Schedule" }, + "isVisibleInPicker": true, + "category": "Event", + "disableDEDataLogging": false, + "r__dataExtension_key": "{{{prefix}}}event - 2024-07-05T080154625" +} diff --git a/test/resources/9999999/eventDefinition/get-expected.json b/test/resources/9999999/eventDefinition/get-expected.json new file mode 100644 index 000000000..c40d583d2 --- /dev/null +++ b/test/resources/9999999/eventDefinition/get-expected.json @@ -0,0 +1,34 @@ +{ + "type": "APIEvent", + "name": "TestContact_Event", + "description": "", + "createdDate": "2018-08-03T07:55:27.38", + "createdBy": 7586085, + "modifiedDate": "2018-08-03T08:22:03.76", + "modifiedBy": 7586085, + "mode": "Production", + "eventDefinitionKey": "APIEvent-60130566-e2fe-eb29-4140-15c27093a80b", + "dataExtensionName": "Contact_Data", + "sourceApplicationExtensionId": "7db1f972-f8b7-49b6-91b5-fa218e13953d", + "filterDefinitionTemplate": "", + "iconUrl": "/events/images/icon_journeyBuilder-event-api-blue.svg", + "arguments": { + "serializedObjectType": 11, + "eventDefinitionKey": "APIEvent-60130566-e2fe-eb29-4140-15c27093a80b", + "dataExtensionId": "C25D5A59-5EBC-40C9-8D27-149831881D89", + "automationId": "00000000-0000-0000-0000-000000000000", + "criteria": "", + "useHighWatermark": false + }, + "metaData": { + "scheduleState": "No Schedule", + "criteriaDescription": "" + }, + "interactionCount": 1, + "isVisibleInPicker": true, + "isPlatformObject": false, + "category": "Event", + "publishedInteractionCount": 1, + "automationId": "00000000-0000-0000-0000-000000000000", + "disableDEDataLogging": false +} diff --git a/test/resources/9999999/fileLocation/build-expected.json b/test/resources/9999999/fileLocation/build-expected.json new file mode 100644 index 000000000..2105d1e50 --- /dev/null +++ b/test/resources/9999999/fileLocation/build-expected.json @@ -0,0 +1,14 @@ +{ + "customerKey": "testTemplated_fileLocation_azure", + "description": "blabla", + "name": "testTemplated_fileLocation_azure_name", + "azureFileTransferLocation": { + "accessKeyId": "client-id", + "authType": "AccessKey", + "bucketName": "container-name", + "relativePath": "my/path", + "storageAccountName": "accountname", + "tenantId": "my-id" + }, + "c__locationType": "Azure Blob Storage" +} diff --git a/test/resources/9999999/fileLocation/get-aws-expected.json b/test/resources/9999999/fileLocation/get-aws-expected.json new file mode 100644 index 000000000..21d3f283b --- /dev/null +++ b/test/resources/9999999/fileLocation/get-aws-expected.json @@ -0,0 +1,14 @@ +{ + "customerKey": "testExisting_fileLocation_aws", + "name": "testExisting_fileLocation_aws_name", + "description": "", + "awsFileTransferLocation": { + "accessKeyId": "key-id", + "authType": "AccessKey", + "bucketName": "bucket-name", + "regionName": "eucentral1", + "relativePath": "my/path", + "transferAccelerationEnabled": false + }, + "c__locationType": "Amazon Simple Storage Service" +} diff --git a/test/resources/9999999/fileLocation/get-azure-expected.json b/test/resources/9999999/fileLocation/get-azure-expected.json new file mode 100644 index 000000000..e3487985d --- /dev/null +++ b/test/resources/9999999/fileLocation/get-azure-expected.json @@ -0,0 +1,14 @@ +{ + "customerKey": "testExisting_fileLocation_azure", + "name": "testExisting_fileLocation_azure_name", + "description": "blabla", + "azureFileTransferLocation": { + "accessKeyId": "client-id", + "authType": "AccessKey", + "bucketName": "container-name", + "relativePath": "my/path", + "storageAccountName": "accountname", + "tenantId": "my-id" + }, + "c__locationType": "Azure Blob Storage" +} diff --git a/test/resources/9999999/fileLocation/get-eftp-expected.json b/test/resources/9999999/fileLocation/get-eftp-expected.json new file mode 100644 index 000000000..46f9cc109 --- /dev/null +++ b/test/resources/9999999/fileLocation/get-eftp-expected.json @@ -0,0 +1,5 @@ +{ + "customerKey": "ExactTarget Enhanced FTP", + "name": "ExactTarget Enhanced FTP", + "c__locationType": "Enhanced FTP Site Import Directory" +} diff --git a/test/resources/9999999/fileLocation/get-exsftp-expected.json b/test/resources/9999999/fileLocation/get-exsftp-expected.json new file mode 100644 index 000000000..d19f6d00c --- /dev/null +++ b/test/resources/9999999/fileLocation/get-exsftp-expected.json @@ -0,0 +1,12 @@ +{ + "customerKey": "testExisting_fileLocation_exsftp", + "name": "testExisting_fileLocation_exsftp_name", + "description": "blabla", + "sFtpFileTransferLocation": { + "authType": "Password", + "portNumber": 22, + "url": "sftp://test.com", + "userName": "abc" + }, + "c__locationType": "External SFTP Site" +} diff --git a/test/resources/9999999/fileLocation/get-gcp-expected.json b/test/resources/9999999/fileLocation/get-gcp-expected.json new file mode 100644 index 000000000..813f8c8ee --- /dev/null +++ b/test/resources/9999999/fileLocation/get-gcp-expected.json @@ -0,0 +1,10 @@ +{ + "customerKey": "testExisting_fileLocation_gcp", + "name": "testExisting_fileLocation_gcp_name", + "description": "", + "gcpFileTransferLocation": { + "bucketName": "some-bucket", + "relativePath": "Task/Activity" + }, + "c__locationType": "Google Cloud Storage" +} diff --git a/test/resources/9999999/fileLocation/get-sor-expected.json b/test/resources/9999999/fileLocation/get-sor-expected.json new file mode 100644 index 000000000..48ce4e132 --- /dev/null +++ b/test/resources/9999999/fileLocation/get-sor-expected.json @@ -0,0 +1,5 @@ +{ + "customerKey": "Salesforce Objects & Reports", + "name": "Salesforce Objects & Reports", + "c__locationType": "Salesforce Objects and Reports" +} diff --git a/test/resources/9999999/fileLocation/patch-aws-expected.json b/test/resources/9999999/fileLocation/patch-aws-expected.json new file mode 100644 index 000000000..94d9b2ccb --- /dev/null +++ b/test/resources/9999999/fileLocation/patch-aws-expected.json @@ -0,0 +1,14 @@ +{ + "customerKey": "testExisting_fileLocation_aws", + "description": "updated via deploy", + "name": "testExisting_fileLocation_aws_name", + "awsFileTransferLocation": { + "accessKeyId": "key-id", + "authType": "AccessKey", + "bucketName": "bucket-name", + "regionName": "eucentral1", + "relativePath": "my/path", + "transferAccelerationEnabled": false + }, + "c__locationType": "Amazon Simple Storage Service" +} diff --git a/test/resources/9999999/fileLocation/patch-exsftp-expected.json b/test/resources/9999999/fileLocation/patch-exsftp-expected.json new file mode 100644 index 000000000..b8ef8926a --- /dev/null +++ b/test/resources/9999999/fileLocation/patch-exsftp-expected.json @@ -0,0 +1,12 @@ +{ + "customerKey": "testExisting_fileLocation_exsftp", + "name": "testExisting_fileLocation_exsftp_name", + "description": "updated via deploy", + "sFtpFileTransferLocation": { + "authType": "Password", + "portNumber": 22, + "url": "sftp://test.com", + "userName": "abc" + }, + "c__locationType": "External SFTP Site" +} diff --git a/test/resources/9999999/fileLocation/template-expected.json b/test/resources/9999999/fileLocation/template-expected.json new file mode 100644 index 000000000..848ce5734 --- /dev/null +++ b/test/resources/9999999/fileLocation/template-expected.json @@ -0,0 +1,14 @@ +{ + "customerKey": "{{{prefix}}}fileLocation_azure", + "description": "blabla", + "name": "{{{prefix}}}fileLocation_azure_name", + "azureFileTransferLocation": { + "accessKeyId": "client-id", + "authType": "AccessKey", + "bucketName": "container-name", + "relativePath": "my/path", + "storageAccountName": "accountname", + "tenantId": "my-id" + }, + "c__locationType": "Azure Blob Storage" +} diff --git a/test/resources/9999999/fileTransfer/build-expected.json b/test/resources/9999999/fileTransfer/build-expected.json new file mode 100644 index 000000000..b2c3e837c --- /dev/null +++ b/test/resources/9999999/fileTransfer/build-expected.json @@ -0,0 +1,15 @@ +{ + "customerKey": "testTemplated_fileTransfer", + "description": "17.11.2022", + "fileSpec": "%%Year%%", + "isCompressed": false, + "isEncrypted": false, + "isFileSpecLocalized": false, + "isPgp": false, + "isUpload": true, + "maxFileAge": 0, + "maxFileAgeScheduleOffset": 0, + "maxImportFrequency": 0, + "name": "testTemplated_fileTransfer", + "r__fileLocation_name": "ExactTarget Enhanced FTP" +} diff --git a/test/resources/9999999/fileTransfer/get-expected.json b/test/resources/9999999/fileTransfer/get-expected.json new file mode 100644 index 000000000..c33af7903 --- /dev/null +++ b/test/resources/9999999/fileTransfer/get-expected.json @@ -0,0 +1,17 @@ +{ + "createdDate": "2022-11-09T05:31:56.477", + "customerKey": "testExisting_fileTransfer", + "description": "17.11.2022", + "fileSpec": "%%Year%%", + "isCompressed": false, + "isEncrypted": false, + "isFileSpecLocalized": false, + "isPgp": false, + "isUpload": true, + "maxFileAge": 0, + "maxFileAgeScheduleOffset": 0, + "maxImportFrequency": 0, + "modifiedDate": "2022-11-17T07:13:20.05", + "name": "testExisting_fileTransfer", + "r__fileLocation_name": "ExactTarget Enhanced FTP" +} diff --git a/test/resources/9999999/fileTransfer/patch-expected.json b/test/resources/9999999/fileTransfer/patch-expected.json new file mode 100644 index 000000000..0c460f792 --- /dev/null +++ b/test/resources/9999999/fileTransfer/patch-expected.json @@ -0,0 +1,17 @@ +{ + "createdDate": "2022-11-09T05:31:56.477", + "customerKey": "testExisting_fileTransfer", + "description": "17.11.2022", + "fileSpec": "%%Year%% updated via deploy", + "isCompressed": false, + "isEncrypted": false, + "isFileSpecLocalized": false, + "isPgp": false, + "isUpload": true, + "maxFileAge": 0, + "maxFileAgeScheduleOffset": 0, + "maxImportFrequency": 0, + "modifiedDate": "2022-11-17T07:13:20.05", + "name": "testExisting_fileTransfer", + "r__fileLocation_name": "ExactTarget Enhanced FTP" +} diff --git a/test/resources/9999999/fileTransfer/post-expected.json b/test/resources/9999999/fileTransfer/post-expected.json new file mode 100644 index 000000000..30de51868 --- /dev/null +++ b/test/resources/9999999/fileTransfer/post-expected.json @@ -0,0 +1,17 @@ +{ + "createdDate": "2022-11-09T05:31:56.477", + "customerKey": "testNew_fileTransfer", + "description": "17.11.2022", + "fileSpec": "%%Year%% created on deploy", + "isCompressed": false, + "isEncrypted": false, + "isFileSpecLocalized": false, + "isPgp": false, + "isUpload": true, + "maxFileAge": 0, + "maxFileAgeScheduleOffset": 0, + "maxImportFrequency": 0, + "modifiedDate": "2022-11-17T07:13:20.05", + "name": "testNew_fileTransfer", + "r__fileLocation_name": "ExactTarget Enhanced FTP" +} diff --git a/test/resources/9999999/fileTransfer/template-expected.json b/test/resources/9999999/fileTransfer/template-expected.json new file mode 100644 index 000000000..407519655 --- /dev/null +++ b/test/resources/9999999/fileTransfer/template-expected.json @@ -0,0 +1,15 @@ +{ + "customerKey": "{{{prefix}}}fileTransfer", + "description": "17.11.2022", + "fileSpec": "%%Year%%", + "isCompressed": false, + "isEncrypted": false, + "isFileSpecLocalized": false, + "isPgp": false, + "isUpload": true, + "maxFileAge": 0, + "maxFileAgeScheduleOffset": 0, + "maxImportFrequency": 0, + "name": "{{{prefix}}}fileTransfer", + "r__fileLocation_name": "ExactTarget Enhanced FTP" +} diff --git a/test/resources/9999999/filter/build-expected.json b/test/resources/9999999/filter/build-expected.json new file mode 100644 index 000000000..3c1f08c39 --- /dev/null +++ b/test/resources/9999999/filter/build-expected.json @@ -0,0 +1,10 @@ +{ + "customerKey": "testTemplated_filter", + "name": "testTemplated_filter", + "description": "blabla", + "statusId": 1, + "r__dataFilter_key": "testTemplated_dataFilter", + "r__destination_dataExtension_key": "testTemplated_dataExtension_exclusion", + "r__source_dataExtension_key": "testTemplated_dataExtension", + "r__folder_Path": "Filter/filterSubfolder" +} diff --git a/test/resources/9999999/filter/get-expected.json b/test/resources/9999999/filter/get-expected.json new file mode 100644 index 000000000..985be311c --- /dev/null +++ b/test/resources/9999999/filter/get-expected.json @@ -0,0 +1,11 @@ +{ + "customerKey": "testExisting_filter", + "name": "testExisting_filter", + "description": "blabla", + "modifiedDate": "2026-01-28T10:14:46.717", + "statusId": 1, + "r__dataFilter_key": "testExisting_dataFilter", + "r__destination_dataExtension_key": "testExisting_dataExtension_exclusion", + "r__source_dataExtension_key": "testExisting_dataExtension", + "r__folder_Path": "Filter/filterSubfolder" +} diff --git a/test/resources/9999999/filter/patch-expected.json b/test/resources/9999999/filter/patch-expected.json new file mode 100644 index 000000000..cd64bdef9 --- /dev/null +++ b/test/resources/9999999/filter/patch-expected.json @@ -0,0 +1,11 @@ +{ + "customerKey": "testExisting_filter", + "name": "testExisting_filter", + "description": "updated on deploy", + "modifiedDate": "2026-01-28T10:14:46.717", + "statusId": 1, + "r__dataFilter_key": "testExisting_dataFilter", + "r__destination_dataExtension_key": "testExisting_dataExtension_exclusion", + "r__source_dataExtension_key": "testExisting_dataExtension", + "r__folder_Path": "Filter" +} diff --git a/test/resources/9999999/filter/post-expected.json b/test/resources/9999999/filter/post-expected.json new file mode 100644 index 000000000..15c3ef5d5 --- /dev/null +++ b/test/resources/9999999/filter/post-expected.json @@ -0,0 +1,11 @@ +{ + "customerKey": "testNew_filter", + "name": "testNew_filter", + "description": "created via deploy", + "modifiedDate": "2026-02-02T07:34:49.277", + "statusId": 1, + "r__dataFilter_key": "testExisting_dataFilter", + "r__destination_dataExtension_key": "testExisting_dataExtension_exclusion", + "r__source_dataExtension_key": "testExisting_dataExtension", + "r__folder_Path": "Filter/filterSubfolder" +} diff --git a/test/resources/9999999/filter/template-expected.json b/test/resources/9999999/filter/template-expected.json new file mode 100644 index 000000000..8fdf89eb1 --- /dev/null +++ b/test/resources/9999999/filter/template-expected.json @@ -0,0 +1,10 @@ +{ + "customerKey": "{{{prefix}}}filter", + "name": "{{{prefix}}}filter", + "description": "blabla", + "statusId": 1, + "r__dataFilter_key": "{{{prefix}}}dataFilter", + "r__destination_dataExtension_key": "{{{prefix}}}dataExtension_exclusion", + "r__source_dataExtension_key": "{{{prefix}}}dataExtension", + "r__folder_Path": "Filter/filterSubfolder" +} diff --git a/test/resources/9999999/filterActivity/create-response.xml b/test/resources/9999999/filterActivity/create-response.xml new file mode 100644 index 000000000..5bd250bc7 --- /dev/null +++ b/test/resources/9999999/filterActivity/create-response.xml @@ -0,0 +1,46 @@ +<?xml version="1.0" encoding="utf-8"?> +<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:xsd="http://www.w3.org/2001/XMLSchema" + xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing" + xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" + xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"> + <soap:Header> + <wsa:Action>CreateResponse</wsa:Action> + <wsa:MessageID>urn:uuid:d5e6c2a7-842c-49c4-9486-5f62c19a3bb3</wsa:MessageID> + <wsa:RelatesTo>urn:uuid:25aedc29-eff1-40d2-bb67-c0e12af440c1</wsa:RelatesTo> + <wsa:To>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</wsa:To> + <wsse:Security> + <wsu:Timestamp wsu:Id="Timestamp-2b9eda1c-baa1-4ee7-b79f-8ce8d79f7f8a"> + <wsu:Created>2026-02-02T13:15:41Z</wsu:Created> + <wsu:Expires>2026-02-02T13:20:41Z</wsu:Expires> + </wsu:Timestamp> + </wsse:Security> + </soap:Header> + <soap:Body> + <CreateResponse xmlns="http://exacttarget.com/wsdl/partnerAPI"> + <Results> + <StatusCode>OK</StatusCode> + <StatusMessage>FilterActivity Created</StatusMessage> + <OrdinalID>0</OrdinalID> + <NewID>0</NewID> + <NewObjectID>a0f1a1bc-4ea1-44b3-8fe1-ce40ef35c1c0</NewObjectID> + <Object xsi:type="FilterActivity"> + <PartnerKey xsi:nil="true" /> + <ObjectID xsi:nil="true" /> + <CustomerKey>testNew_filter</CustomerKey> + <Name>testNew_filter</Name> + <Description /> + <FilterActivityID>a0f1a1bc-4ea1-44b3-8fe1-ce40ef35c1c0</FilterActivityID> + <FilterDefinitionID>10ef27dd-4be8-4bf6-970a-8acf8e281e55</FilterDefinitionID> + <DestinationObjectID>21711373-72c1-ec11-b83b-exclusion</DestinationObjectID> + <DestinationTypeID>2</DestinationTypeID> + <SourceObjectID>21711373-72c1-ec11-b83b-48df37d1deb7</SourceObjectID> + <SourceTypeID>2</SourceTypeID> + </Object> + </Results> + <RequestID>1391248a-ec47-4941-9e84-8272d4d23f8a</RequestID> + <OverallStatus>OK</OverallStatus> + </CreateResponse> + </soap:Body> +</soap:Envelope> diff --git a/test/resources/9999999/filterActivity/retrieve-CustomerKey=testExisting_filter-response.xml b/test/resources/9999999/filterActivity/retrieve-CustomerKey=testExisting_filter-response.xml new file mode 100644 index 000000000..7d6d292d0 --- /dev/null +++ b/test/resources/9999999/filterActivity/retrieve-CustomerKey=testExisting_filter-response.xml @@ -0,0 +1,30 @@ +<?xml version="1.0" encoding="utf-8"?> +<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:xsd="http://www.w3.org/2001/XMLSchema" + xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing" + xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" + xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"> + <soap:Header> + <wsa:Action>RetrieveResponse</wsa:Action> + <wsa:MessageID>urn:uuid:37985d19-539c-4205-bb97-26d8fb24f474</wsa:MessageID> + <wsa:RelatesTo>urn:uuid:2ccf52c3-4f84-4e4f-93e0-0b657d8eabe0</wsa:RelatesTo> + <wsa:To>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</wsa:To> + <wsse:Security> + <wsu:Timestamp wsu:Id="Timestamp-acf74abc-5790-458b-9632-c1f74a7aa0c3"> + <wsu:Created>2026-02-02T10:48:38Z</wsu:Created> + <wsu:Expires>2026-02-02T10:53:38Z</wsu:Expires> + </wsu:Timestamp> + </wsse:Security> + </soap:Header> + <soap:Body> + <RetrieveResponseMsg xmlns="http://exacttarget.com/wsdl/partnerAPI"> + <OverallStatus>OK</OverallStatus> + <RequestID>a60e3780-8b90-40ae-ade4-68b8732e756a</RequestID> + <Results xsi:type="FilterActivity"> + <PartnerKey xsi:nil="true" /> + <ObjectID>f018f237-f7ef-40b0-afc8-39ea2e5dcca4</ObjectID> + </Results> + </RetrieveResponseMsg> + </soap:Body> +</soap:Envelope> diff --git a/test/resources/9999999/filterDefinition/retrieve-CustomerKey=testExisting_dataFilter-response.xml b/test/resources/9999999/filterDefinition/retrieve-CustomerKey=testExisting_dataFilter-response.xml new file mode 100644 index 000000000..72f6492fb --- /dev/null +++ b/test/resources/9999999/filterDefinition/retrieve-CustomerKey=testExisting_dataFilter-response.xml @@ -0,0 +1,30 @@ +<?xml version="1.0" encoding="utf-8"?> +<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:xsd="http://www.w3.org/2001/XMLSchema" + xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing" + xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" + xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"> + <soap:Header> + <wsa:Action>RetrieveResponse</wsa:Action> + <wsa:MessageID>urn:uuid:ab5dec96-be6e-4900-b0a8-4cd958182307</wsa:MessageID> + <wsa:RelatesTo>urn:uuid:4ddb474a-4449-43da-b7f4-a7c2e34b66d9</wsa:RelatesTo> + <wsa:To>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</wsa:To> + <wsse:Security> + <wsu:Timestamp wsu:Id="Timestamp-6d8a8fea-bf2a-4be2-8265-63f395ddf550"> + <wsu:Created>2026-01-30T15:50:29Z</wsu:Created> + <wsu:Expires>2026-01-30T15:55:29Z</wsu:Expires> + </wsu:Timestamp> + </wsse:Security> + </soap:Header> + <soap:Body> + <RetrieveResponseMsg xmlns="http://exacttarget.com/wsdl/partnerAPI"> + <OverallStatus>OK</OverallStatus> + <RequestID>5b3f20f1-e615-445f-9bd3-ece1d239aa0f</RequestID> + <Results xsi:type="FilterDefinition"> + <PartnerKey xsi:nil="true" /> + <ObjectID>10ef27dd-4be8-4bf6-970a-8acf8e281e55</ObjectID> + </Results> + </RetrieveResponseMsg> + </soap:Body> +</soap:Envelope> diff --git a/test/resources/9999999/folder-deploy-samepath/Content Builder/testFolder_samePath.folder-meta.json b/test/resources/9999999/folder-deploy-samepath/Content Builder/testFolder_samePath.folder-meta.json new file mode 100644 index 000000000..876cd1479 --- /dev/null +++ b/test/resources/9999999/folder-deploy-samepath/Content Builder/testFolder_samePath.folder-meta.json @@ -0,0 +1,9 @@ +{ + "Name": "testFolder_samePath", + "Description": "", + "ContentType": "asset", + "IsActive": true, + "IsEditable": true, + "AllowChildren": true, + "_generated": true +} diff --git a/test/resources/9999999/folder-deploy-slash/Content Builder/Headers%2FFolders.folder-meta.json b/test/resources/9999999/folder-deploy-slash/Content Builder/Headers%2FFolders.folder-meta.json new file mode 100644 index 000000000..1e7d61b70 --- /dev/null +++ b/test/resources/9999999/folder-deploy-slash/Content Builder/Headers%2FFolders.folder-meta.json @@ -0,0 +1,9 @@ +{ + "Name": "Headers/Folders", + "Description": "", + "ContentType": "asset", + "IsActive": true, + "IsEditable": true, + "AllowChildren": true, + "_generated": true +} diff --git a/test/resources/9999999/folder-deploy/Data Extensions/my.folder-meta.json b/test/resources/9999999/folder-deploy/Data Extensions/my.folder-meta.json new file mode 100644 index 000000000..bd0f8ce9e --- /dev/null +++ b/test/resources/9999999/folder-deploy/Data Extensions/my.folder-meta.json @@ -0,0 +1,9 @@ +{ + "Name": "my", + "Description": "", + "ContentType": "dataextension", + "IsActive": true, + "IsEditable": true, + "AllowChildren": true, + "_generated": true +} diff --git a/test/resources/9999999/folder-deploy/Data Extensions/my/sub.folder-meta.json b/test/resources/9999999/folder-deploy/Data Extensions/my/sub.folder-meta.json new file mode 100644 index 000000000..f9b5e2158 --- /dev/null +++ b/test/resources/9999999/folder-deploy/Data Extensions/my/sub.folder-meta.json @@ -0,0 +1,9 @@ +{ + "Name": "sub", + "Description": "", + "ContentType": "dataextension", + "IsActive": true, + "IsEditable": true, + "AllowChildren": true, + "_generated": true +} diff --git a/test/resources/9999999/folder-deploy/Data Extensions/my/sub/path.folder-meta.json b/test/resources/9999999/folder-deploy/Data Extensions/my/sub/path.folder-meta.json new file mode 100644 index 000000000..67f7522bc --- /dev/null +++ b/test/resources/9999999/folder-deploy/Data Extensions/my/sub/path.folder-meta.json @@ -0,0 +1,9 @@ +{ + "Name": "path", + "Description": "", + "ContentType": "dataextension", + "IsActive": true, + "IsEditable": true, + "AllowChildren": true, + "_generated": true +} diff --git a/test/resources/9999999/folder-deploy/Data Extensions/my/sub/path/subpath.folder-meta.json b/test/resources/9999999/folder-deploy/Data Extensions/my/sub/path/subpath.folder-meta.json new file mode 100644 index 000000000..7df73ec7f --- /dev/null +++ b/test/resources/9999999/folder-deploy/Data Extensions/my/sub/path/subpath.folder-meta.json @@ -0,0 +1,9 @@ +{ + "Name": "subpath", + "Description": "", + "ContentType": "dataextension", + "IsActive": true, + "IsEditable": true, + "AllowChildren": true, + "_generated": true +} diff --git a/test/resources/9999999/folder-deploy/Data Extensions/testExisting_folder.folder-meta.json b/test/resources/9999999/folder-deploy/Data Extensions/testExisting_folder.folder-meta.json new file mode 100644 index 000000000..fd0015d48 --- /dev/null +++ b/test/resources/9999999/folder-deploy/Data Extensions/testExisting_folder.folder-meta.json @@ -0,0 +1,9 @@ +{ + "Name": "testExisting_folder", + "Description": "", + "ContentType": "dataextension", + "IsActive": true, + "IsEditable": true, + "AllowChildren": true, + "_generated": true +} diff --git a/test/resources/9999999/folder-deploy/my automations/my.folder-meta.json b/test/resources/9999999/folder-deploy/my automations/my.folder-meta.json new file mode 100644 index 000000000..d8bd77d74 --- /dev/null +++ b/test/resources/9999999/folder-deploy/my automations/my.folder-meta.json @@ -0,0 +1,9 @@ +{ + "Name": "my", + "Description": "", + "ContentType": "automations", + "IsActive": true, + "IsEditable": true, + "AllowChildren": true, + "_generated": true +} diff --git a/test/resources/9999999/folder-deploy/my automations/my/sub.folder-meta.json b/test/resources/9999999/folder-deploy/my automations/my/sub.folder-meta.json new file mode 100644 index 000000000..026135fd1 --- /dev/null +++ b/test/resources/9999999/folder-deploy/my automations/my/sub.folder-meta.json @@ -0,0 +1,9 @@ +{ + "Name": "sub", + "Description": "", + "ContentType": "automations", + "IsActive": true, + "IsEditable": true, + "AllowChildren": true, + "_generated": true +} diff --git a/test/resources/9999999/folder-deploy/my automations/my/sub/path.folder-meta.json b/test/resources/9999999/folder-deploy/my automations/my/sub/path.folder-meta.json new file mode 100644 index 000000000..b84eb16b3 --- /dev/null +++ b/test/resources/9999999/folder-deploy/my automations/my/sub/path.folder-meta.json @@ -0,0 +1,9 @@ +{ + "Name": "path", + "Description": "", + "ContentType": "automations", + "IsActive": true, + "IsEditable": true, + "AllowChildren": true, + "_generated": true +} diff --git a/test/resources/9999999/folder-deploy/my automations/my/sub/path/subpath.folder-meta.json b/test/resources/9999999/folder-deploy/my automations/my/sub/path/subpath.folder-meta.json new file mode 100644 index 000000000..afa38386c --- /dev/null +++ b/test/resources/9999999/folder-deploy/my automations/my/sub/path/subpath.folder-meta.json @@ -0,0 +1,9 @@ +{ + "Name": "subpath", + "Description": "", + "ContentType": "automations", + "IsActive": true, + "IsEditable": true, + "AllowChildren": true, + "_generated": true +} diff --git a/test/resources/9999999/hub/v1/contacts/schema/attributeGroups/get-response.json b/test/resources/9999999/hub/v1/contacts/schema/attributeGroups/get-response.json new file mode 100644 index 000000000..e0dbcb015 --- /dev/null +++ b/test/resources/9999999/hub/v1/contacts/schema/attributeGroups/get-response.json @@ -0,0 +1,628 @@ +{ + "attributeGroupDefinitions": [ + { + "mID": 1111111, + "objectState": "Created", + "attributeSetIdentifiers": [ + { + "definitionID": "1051de3f-31e2-e611-80cc-1402ec7222b4", + "definitionName": { + "value": "Email Addresses" + }, + "definitionKey": "EmailAddresses", + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "namespace": "" + }, + { + "definitionID": "9093dc39-31e2-e611-80cc-1402ec7222b4", + "definitionName": { + "value": "Contact" + }, + "definitionKey": "Contact", + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "namespace": "" + } + ], + "isOwner": true, + "isPrimary": false, + "isSystemDefined": true, + "isHidden": false, + "canAddProperties": false, + "canAddRelationships": false, + "containsSchemaAttributes": true, + "canRemove": false, + "canChangeProperties": false, + "displayOrder": 0, + "requiredRelationships": [ + "0e51de3f-31e2-e611-80cc-1402ec7222b4", + "1451de3f-31e2-e611-80cc-1402ec7222b4", + "9893dc39-31e2-e611-80cc-1402ec7222b4" + ], + "applicationID": "ce703ed3-e01f-4f5f-900d-76a95b363e29", + "canModify": false, + "applicationKey": "com.exacttarget.contacts", + "attributeGroupIconKey": "People", + "fullyQualifiedName": "System Data", + "attributeGroupType": "Standard", + "localizedDescription": {}, + "attributeCount": 7, + "definitionID": "8f93dc39-31e2-e611-80cc-1402ec7222b4", + "definitionName": { + "value": "System Data" + }, + "definitionKey": "ETSystem", + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "namespace": "" + }, + { + "mID": 1111111, + "objectState": "Created", + "attributeSetIdentifiers": [ + { + "definitionID": "c9e9847d-696d-eb11-b81e-48df37d1df5a", + "definitionName": { + "value": "Chat Message Demographics" + }, + "definitionKey": "ChatMessageDemographics", + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "namespace": "" + }, + { + "definitionID": "f2e9847d-696d-eb11-b81e-48df37d1df5a", + "definitionName": { + "value": "Chat Message Subscriptions" + }, + "definitionKey": "ChatMessageSubscriptions", + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "namespace": "" + } + ], + "isOwner": true, + "isPrimary": false, + "isSystemDefined": true, + "isHidden": false, + "canAddProperties": true, + "canAddRelationships": true, + "containsSchemaAttributes": false, + "canRemove": false, + "canChangeProperties": true, + "displayOrder": 1, + "requiredRelationships": [ + "9a42dcad-ae72-4cde-9937-193e17485ad6", + "04ea847d-696d-eb11-b81e-48df37d1df5a" + ], + "canModify": true, + "fullyQualifiedName": "Chat Message Data", + "attributeGroupType": "Standard", + "localizedDescription": {}, + "attributeCount": 37, + "definitionID": "cae9847d-696d-eb11-b81e-48df37d1df5a", + "definitionName": { + "value": "Chat Message Data" + }, + "definitionKey": "ETChatMessage", + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "namespace": "" + }, + { + "mID": 1111111, + "objectState": "Created", + "attributeSetIdentifiers": [ + { + "definitionID": "b151de3f-31e2-e611-80cc-1402ec7222b4", + "definitionName": { + "value": "Email Demographics" + }, + "definitionKey": "EmailDemographics", + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "namespace": "" + } + ], + "isOwner": true, + "isPrimary": false, + "isSystemDefined": true, + "isHidden": false, + "canAddProperties": false, + "canAddRelationships": true, + "containsSchemaAttributes": false, + "canRemove": false, + "canChangeProperties": false, + "displayOrder": 2, + "requiredRelationships": ["b751de3f-31e2-e611-80cc-1402ec7222b4"], + "applicationID": "b2ca1f50-3cc4-4fd7-a3a3-88bf09fb59fa", + "canModify": false, + "applicationKey": "com.exacttarget.email", + "attributeGroupIconKey": "Email", + "fullyQualifiedName": "Email Data", + "attributeGroupType": "Standard", + "localizedDescription": {}, + "attributeCount": 16, + "definitionID": "b451de3f-31e2-e611-80cc-1402ec7222b4", + "definitionName": { + "value": "Email Data" + }, + "definitionKey": "ETEmail", + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "namespace": "" + }, + { + "mID": 1111111, + "objectState": "Created", + "attributeSetIdentifiers": [ + { + "definitionID": "7a86d247-3045-ea11-a2e0-1402ec94ec41", + "definitionName": { + "value": "GroupConnect LINE Addresses" + }, + "definitionKey": "GroupConnectLineAddress", + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "namespace": "" + }, + { + "definitionID": "a151de3f-31e2-e611-80cc-1402ec7222b4", + "definitionName": { + "value": "GroupConnect LINE Demographics" + }, + "definitionKey": "GroupConnectLineDemographics", + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "namespace": "" + }, + { + "definitionID": "e551de3f-31e2-e611-80cc-1402ec7222b4", + "definitionName": { + "value": "GroupConnect LINE Subscriptions" + }, + "definitionKey": "GroupConnectLineSubscriptions", + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "namespace": "" + } + ], + "isOwner": true, + "isPrimary": false, + "isSystemDefined": true, + "isHidden": false, + "canAddProperties": false, + "canAddRelationships": true, + "containsSchemaAttributes": false, + "canRemove": false, + "canChangeProperties": false, + "displayOrder": 3, + "requiredRelationships": [ + "8686d247-3045-ea11-a2e0-1402ec94ec41", + "a686d247-3045-ea11-a2e0-1402ec94ec41", + "9386d247-3045-ea11-a2e0-1402ec94ec41" + ], + "applicationID": "4e9519db-ad21-483a-a3fc-8ab4557eded1", + "canModify": false, + "applicationKey": "com.exacttarget.GroupConnect", + "attributeGroupIconKey": "Mobile", + "fullyQualifiedName": "GroupConnect LINE Data", + "attributeGroupType": "Standard", + "localizedDescription": {}, + "attributeCount": 23, + "definitionID": "ab51de3f-31e2-e611-80cc-1402ec7222b4", + "definitionName": { + "value": "GroupConnect LINE Data" + }, + "definitionKey": "ETGroupConnectLine", + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "namespace": "" + }, + { + "mID": 1111111, + "objectState": "Created", + "attributeSetIdentifiers": [ + { + "definitionID": "2b51de3f-31e2-e611-80cc-1402ec7222b4", + "definitionName": { + "value": "MobileConnect Demographics" + }, + "definitionKey": "MobileDemographics", + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "namespace": "" + }, + { + "definitionID": "3152de3f-31e2-e611-80cc-1402ec7222b4", + "definitionName": { + "value": "MobileConnect Subscriptions" + }, + "definitionKey": "MobileSubscriptions", + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "namespace": "" + } + ], + "isOwner": true, + "isPrimary": false, + "isSystemDefined": true, + "isHidden": false, + "canAddProperties": false, + "canAddRelationships": true, + "containsSchemaAttributes": false, + "canRemove": false, + "canChangeProperties": false, + "displayOrder": 4, + "requiredRelationships": [ + "4651de3f-31e2-e611-80cc-1402ec7222b4", + "4352de3f-31e2-e611-80cc-1402ec7222b4" + ], + "applicationID": "e25893f9-08f3-480f-8def-7f8ab0583611", + "canModify": false, + "applicationKey": "com.exacttarget.mobileconnect", + "attributeGroupIconKey": "Mobile", + "fullyQualifiedName": "MobileConnect Data", + "attributeGroupType": "Standard", + "localizedDescription": {}, + "attributeCount": 37, + "definitionID": "4351de3f-31e2-e611-80cc-1402ec7222b4", + "definitionName": { + "value": "MobileConnect Data" + }, + "definitionKey": "ETMobileConnect", + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "namespace": "" + }, + { + "mID": 1111111, + "objectState": "Created", + "attributeSetIdentifiers": [ + { + "definitionID": "6d51de3f-31e2-e611-80cc-1402ec7222b4", + "definitionName": { + "value": "MobilePush Demographics" + }, + "definitionKey": "PushDemographics", + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "namespace": "" + }, + { + "definitionID": "b352de3f-31e2-e611-80cc-1402ec7222b4", + "definitionName": { + "value": "MobilePush Subscriptions" + }, + "definitionKey": "PushSubscriptions", + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "namespace": "" + }, + { + "definitionID": "c652de3f-31e2-e611-80cc-1402ec7222b4", + "definitionName": { + "value": "MobilePush Tags" + }, + "definitionKey": "PushTags", + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "namespace": "" + } + ], + "isOwner": true, + "isPrimary": false, + "isSystemDefined": true, + "isHidden": false, + "canAddProperties": false, + "canAddRelationships": true, + "containsSchemaAttributes": false, + "canRemove": false, + "canChangeProperties": false, + "displayOrder": 5, + "requiredRelationships": [ + "9651de3f-31e2-e611-80cc-1402ec7222b4", + "d052de3f-31e2-e611-80cc-1402ec7222b4", + "bc52de3f-31e2-e611-80cc-1402ec7222b4" + ], + "applicationID": "2051892d-5de2-4ecf-98af-8ca9a40d2c9c", + "canModify": false, + "applicationKey": "com.exacttarget.mobilepush", + "attributeGroupIconKey": "Mobile", + "fullyQualifiedName": "MobilePush Data", + "attributeGroupType": "Standard", + "localizedDescription": {}, + "attributeCount": 65, + "definitionID": "9351de3f-31e2-e611-80cc-1402ec7222b4", + "definitionName": { + "value": "MobilePush Data" + }, + "definitionKey": "ETMobilePush", + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "namespace": "" + }, + { + "mID": 1111111, + "objectState": "Created", + "attributeSetIdentifiers": [ + { + "definitionID": "0b86d645-31e2-e611-80cc-1402ec7222b4", + "definitionName": { + "value": "Predictive Intelligence Product Sessions" + }, + "definitionKey": "PredictiveIntelProductSessions", + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "namespace": "" + }, + { + "definitionID": "1e86d645-31e2-e611-80cc-1402ec7222b4", + "definitionName": { + "value": "Predictive Intelligence Content Views" + }, + "definitionKey": "PredictiveIntelContentViews", + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "namespace": "" + }, + { + "definitionID": "2e86d645-31e2-e611-80cc-1402ec7222b4", + "definitionName": { + "value": "Predictive Intelligence Content" + }, + "definitionKey": "PredictiveIntelContent", + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "namespace": "" + }, + { + "definitionID": "3e86d645-31e2-e611-80cc-1402ec7222b4", + "definitionName": { + "value": "Predictive Intelligence Content Attributes" + }, + "definitionKey": "PredictiveIntelContentAttribs", + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "namespace": "" + }, + { + "definitionID": "5286d645-31e2-e611-80cc-1402ec7222b4", + "definitionName": { + "value": "Predictive Intelligence AbandonedCartEvents" + }, + "definitionKey": "PredictiveIntelAbandonedCartEvents", + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "namespace": "" + }, + { + "definitionID": "6586d645-31e2-e611-80cc-1402ec7222b4", + "definitionName": { + "value": "Predictive Intelligence AbandonedCartItems" + }, + "definitionKey": "PredictiveIntelAbandonedCartItems", + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "namespace": "" + }, + { + "definitionID": "7586d645-31e2-e611-80cc-1402ec7222b4", + "definitionName": { + "value": "Predictive Intelligence Session Ends" + }, + "definitionKey": "PredictiveIntelSessionEnds", + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "namespace": "" + }, + { + "definitionID": "8574266c-c416-ec11-b839-48df37d1dc79", + "definitionName": { + "value": "Einstein MC Predictive Scores" + }, + "definitionKey": "EinsteinMCPredictiveScores", + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "namespace": "" + }, + { + "definitionID": "a185d645-31e2-e611-80cc-1402ec7222b4", + "definitionName": { + "value": "Predictive Scores" + }, + "definitionKey": "PredictiveIntelScores", + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "namespace": "" + }, + { + "definitionID": "b285d645-31e2-e611-80cc-1402ec7222b4", + "definitionName": { + "value": "Predictive Intelligence Product Views" + }, + "definitionKey": "PredictiveIntelProductViews", + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "namespace": "" + }, + { + "definitionID": "c485d645-31e2-e611-80cc-1402ec7222b4", + "definitionName": { + "value": "Predictive Intelligence Products" + }, + "definitionKey": "PredictiveIntelProducts", + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "namespace": "" + }, + { + "definitionID": "d685d645-31e2-e611-80cc-1402ec7222b4", + "definitionName": { + "value": "Predictive Intelligence Product Attributes" + }, + "definitionKey": "PredictiveIntelProductAttribs", + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "namespace": "" + }, + { + "definitionID": "ee85d645-31e2-e611-80cc-1402ec7222b4", + "definitionName": { + "value": "Predictive Intelligence Product Purchases" + }, + "definitionKey": "PredictiveIntelProductPurchases", + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "namespace": "" + }, + { + "definitionID": "f452de3f-31e2-e611-80cc-1402ec7222b4", + "definitionName": { + "value": "Predictive Intelligence Profiles" + }, + "definitionKey": "PredictiveIntelProfiles", + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "namespace": "" + } + ], + "isOwner": true, + "isPrimary": false, + "isSystemDefined": true, + "isHidden": false, + "canAddProperties": true, + "canAddRelationships": false, + "containsSchemaAttributes": false, + "canRemove": false, + "canChangeProperties": true, + "displayOrder": 7, + "requiredRelationships": [ + "1586d645-31e2-e611-80cc-1402ec7222b4", + "2686d645-31e2-e611-80cc-1402ec7222b4", + "3586d645-31e2-e611-80cc-1402ec7222b4", + "4686d645-31e2-e611-80cc-1402ec7222b4", + "5d86d645-31e2-e611-80cc-1402ec7222b4", + "6c86d645-31e2-e611-80cc-1402ec7222b4", + "7887d645-31e2-e611-80cc-1402ec7222b4", + "7d86d645-31e2-e611-80cc-1402ec7222b4", + "c80f6472-c416-ec11-b839-48df37d1dc79", + "a985d645-31e2-e611-80cc-1402ec7222b4", + "ba85d645-31e2-e611-80cc-1402ec7222b4", + "cd85d645-31e2-e611-80cc-1402ec7222b4", + "0086d645-31e2-e611-80cc-1402ec7222b4", + "de85d645-31e2-e611-80cc-1402ec7222b4", + "fd85d645-31e2-e611-80cc-1402ec7222b4", + "9885d645-31e2-e611-80cc-1402ec7222b4" + ], + "applicationID": "aed181bc-d7b7-465e-a3dd-9cdfb13943e2", + "canModify": false, + "applicationKey": "com.sfmc-einstein.Einstein Engagement Scoring", + "attributeGroupIconKey": "PredictiveIntel", + "fullyQualifiedName": "Predictive Intelligence Data", + "attributeGroupType": "Standard", + "description": "Attribute Group for Einstein Engagement Scoring", + "localizedDescription": { + "resourceSetKey": "ContactsMeta.SystemAttributeGroupDescriptions", + "resourceValueKey": "ATTR_GROUP_DESC_ETPredictiveIntel", + "value": "Attribute Group for Einstein Engagement Scoring" + }, + "attributeCount": 112, + "definitionID": "e152de3f-31e2-e611-80cc-1402ec7222b4", + "definitionName": { + "value": "Predictive Intelligence Data" + }, + "definitionKey": "ETPredictiveIntel", + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "namespace": "" + }, + { + "mID": 7330928, + "objectState": "Created", + "attributeSetIdentifiers": [ + { + "definitionID": "528b787a-5238-ee11-b85a-48df37d1de8a", + "definitionName": { + "value": "testExisting_dataExtensionShared" + }, + "definitionKey": "testExisting_dataExtensionShared", + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "namespace": "" + } + ], + "isOwner": true, + "isPrimary": false, + "isSystemDefined": false, + "isHidden": false, + "canAddProperties": true, + "canAddRelationships": true, + "containsSchemaAttributes": false, + "canRemove": true, + "canChangeProperties": true, + "displayOrder": 8, + "requiredRelationships": [], + "canModify": true, + "attributeGroupIconKey": "et-icon-databas", + "fullyQualifiedName": "testExisting_attributeGroup", + "attributeGroupType": "Standard", + "localizedDescription": {}, + "attributeCount": 6, + "definitionID": "79846c6e-5238-ee11-b85a-48df37d1de8a", + "definitionName": { + "value": "testExisting_attributeGroup" + }, + "definitionKey": "testExisting_attributeGroup", + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "namespace": "" + } + ], + "responseContext": { + "operationStatus": "OK", + "schemaType": "Contacts", + "populateInternalProperties": false + }, + "requestServiceMessageID": "9dac2279-40db-4e67-a862-d6ecbadf109a", + "responseDateTime": "2023-07-12T09:17:31.8837381-06:00", + "resultMessages": [], + "serviceMessageID": "92930c00-cacf-41e1-ba8d-04ad4d903f65" +} diff --git a/test/resources/9999999/hub/v1/contacts/schema/setDefinitions/get-response.json b/test/resources/9999999/hub/v1/contacts/schema/setDefinitions/get-response.json new file mode 100644 index 000000000..aef3bea05 --- /dev/null +++ b/test/resources/9999999/hub/v1/contacts/schema/setDefinitions/get-response.json @@ -0,0 +1,20194 @@ +{ + "setDefinition": [ + { + "definitionID": "0b86d645-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "PredictiveIntelProductSessions", + "definitionName": { + "value": "Predictive Intelligence Product Sessions" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "valueDefinitions": [ + { + "baseType": "Numeric", + "dataSourceID": 1, + "dataSourceName": {}, + "dataType": "LongNumber", + "description": "", + "localizedDescription": { + "value": "" + }, + "definitionID": "1386d645-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "CustomObjectKey", + "definitionName": { + "value": "Custom Object Key" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 1, + "fullyQualifiedName": "Predictive Intelligence Product Sessions.Custom Object Key", + "isHidden": true, + "isIdentityValue": true, + "isNullable": false, + "isPrimaryKey": false, + "isReadOnly": true, + "isSystemDefined": true, + "isUpdateable": false, + "ordinal": 1, + "parentDefinition": { + "definitionID": "0b86d645-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "PredictiveIntelProductSessions", + "definitionName": { + "value": "Predictive Intelligence Product Sessions" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "_CustomObjectKey", + "valueDefinitionID": "1386d645-31e2-e611-80cc-1402ec7222b4", + "valueDefinitionKey": "CustomObjectKey", + "name": "Custom Object Key", + "setDefinitionID": "0b86d645-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "PredictiveIntelProductSessions", + "setDefinitionName": { + "value": "Predictive Intelligence Product Sessions" + }, + "parentIdentifier": "0b86d645-31e2-e611-80cc-1402ec7222b4" + }, + { + "baseType": "Text", + "dataSourceID": 5, + "dataSourceName": {}, + "dataType": "Text", + "description": "session_id", + "localizedDescription": { + "value": "session_id" + }, + "definitionID": "1086d645-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "session_id", + "definitionName": { + "value": "Session ID" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 2, + "fullyQualifiedName": "Predictive Intelligence Product Sessions.Session ID", + "isHidden": false, + "isIdentityValue": false, + "isNullable": false, + "isPrimaryKey": true, + "isReadOnly": true, + "isSystemDefined": true, + "isUpdateable": false, + "length": 256, + "obfuscationProperties": { + "maskType": "None", + "maskTypeID": 0, + "storageTypeID": 1, + "storageType": "Plain", + "valueDefinitionID": "1086d645-31e2-e611-80cc-1402ec7222b4" + }, + "ordinal": 2, + "parentDefinition": { + "definitionID": "0b86d645-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "PredictiveIntelProductSessions", + "definitionName": { + "value": "Predictive Intelligence Product Sessions" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "session_id", + "storageFieldReferenceID": { + "type": "guid", + "value": "1ca32e3d-4f4e-4771-8d99-057f8bad3733" + }, + "valueDefinitionID": "1086d645-31e2-e611-80cc-1402ec7222b4", + "valueDefinitionKey": "session_id", + "name": "Session ID", + "setDefinitionID": "0b86d645-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "PredictiveIntelProductSessions", + "setDefinitionName": { + "value": "Predictive Intelligence Product Sessions" + }, + "parentIdentifier": "0b86d645-31e2-e611-80cc-1402ec7222b4" + }, + { + "baseType": "Text", + "dataSourceID": 5, + "dataSourceName": {}, + "dataType": "Text", + "description": "user_id", + "localizedDescription": { + "value": "user_id" + }, + "definitionID": "1286d645-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "User_ID", + "definitionName": { + "value": "User ID" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 3, + "fullyQualifiedName": "Predictive Intelligence Product Sessions.User ID", + "isHidden": false, + "isIdentityValue": false, + "isNullable": false, + "isPrimaryKey": true, + "isReadOnly": true, + "isSystemDefined": true, + "isUpdateable": false, + "length": 256, + "obfuscationProperties": { + "maskType": "None", + "maskTypeID": 0, + "storageTypeID": 1, + "storageType": "Plain", + "valueDefinitionID": "1286d645-31e2-e611-80cc-1402ec7222b4" + }, + "ordinal": 3, + "parentDefinition": { + "definitionID": "0b86d645-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "PredictiveIntelProductSessions", + "definitionName": { + "value": "Predictive Intelligence Product Sessions" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "user_id", + "storageFieldReferenceID": { + "type": "guid", + "value": "f2e9ddf5-e18d-43db-ad52-cc754c929811" + }, + "valueDefinitionID": "1286d645-31e2-e611-80cc-1402ec7222b4", + "valueDefinitionKey": "User_ID", + "name": "User ID", + "setDefinitionID": "0b86d645-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "PredictiveIntelProductSessions", + "setDefinitionName": { + "value": "Predictive Intelligence Product Sessions" + }, + "parentIdentifier": "0b86d645-31e2-e611-80cc-1402ec7222b4" + }, + { + "baseType": "Numeric", + "dataSourceID": 5, + "dataSourceName": {}, + "dataType": "LongNumber", + "description": "Batch_ID", + "localizedDescription": { + "value": "Batch_ID" + }, + "definitionID": "0c86d645-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "Batch_ID", + "definitionName": { + "value": "Batch ID" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 4, + "fullyQualifiedName": "Predictive Intelligence Product Sessions.Batch ID", + "isHidden": false, + "isIdentityValue": false, + "isNullable": true, + "isPrimaryKey": false, + "isReadOnly": true, + "isSystemDefined": true, + "isUpdateable": false, + "obfuscationProperties": { + "maskType": "None", + "maskTypeID": 0, + "storageTypeID": 1, + "storageType": "Plain", + "valueDefinitionID": "0c86d645-31e2-e611-80cc-1402ec7222b4" + }, + "ordinal": 4, + "parentDefinition": { + "definitionID": "0b86d645-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "PredictiveIntelProductSessions", + "definitionName": { + "value": "Predictive Intelligence Product Sessions" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "Batch_ID", + "storageFieldReferenceID": { + "type": "guid", + "value": "fed66cad-7da4-469c-b49c-79e8c82ae37f" + }, + "valueDefinitionID": "0c86d645-31e2-e611-80cc-1402ec7222b4", + "valueDefinitionKey": "Batch_ID", + "name": "Batch ID", + "setDefinitionID": "0b86d645-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "PredictiveIntelProductSessions", + "setDefinitionName": { + "value": "Predictive Intelligence Product Sessions" + }, + "parentIdentifier": "0b86d645-31e2-e611-80cc-1402ec7222b4" + }, + { + "baseType": "Numeric", + "dataSourceID": 5, + "dataSourceName": {}, + "dataType": "LongNumber", + "description": "List_ID", + "localizedDescription": { + "value": "List_ID" + }, + "definitionID": "0f86d645-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "List_ID", + "definitionName": { + "value": "List ID" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 5, + "fullyQualifiedName": "Predictive Intelligence Product Sessions.List ID", + "isHidden": false, + "isIdentityValue": false, + "isNullable": true, + "isPrimaryKey": false, + "isReadOnly": true, + "isSystemDefined": true, + "isUpdateable": false, + "obfuscationProperties": { + "maskType": "None", + "maskTypeID": 0, + "storageTypeID": 1, + "storageType": "Plain", + "valueDefinitionID": "0f86d645-31e2-e611-80cc-1402ec7222b4" + }, + "ordinal": 5, + "parentDefinition": { + "definitionID": "0b86d645-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "PredictiveIntelProductSessions", + "definitionName": { + "value": "Predictive Intelligence Product Sessions" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "List_ID", + "storageFieldReferenceID": { + "type": "guid", + "value": "39471713-05c1-43d5-ac0f-9ecb66bae213" + }, + "valueDefinitionID": "0f86d645-31e2-e611-80cc-1402ec7222b4", + "valueDefinitionKey": "List_ID", + "name": "List ID", + "setDefinitionID": "0b86d645-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "PredictiveIntelProductSessions", + "setDefinitionName": { + "value": "Predictive Intelligence Product Sessions" + }, + "parentIdentifier": "0b86d645-31e2-e611-80cc-1402ec7222b4" + }, + { + "baseType": "Numeric", + "dataSourceID": 5, + "dataSourceName": {}, + "dataType": "LongNumber", + "description": "Job_ID", + "localizedDescription": { + "value": "Job_ID" + }, + "definitionID": "0d86d645-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "Job_ID", + "definitionName": { + "value": "Job ID" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 6, + "fullyQualifiedName": "Predictive Intelligence Product Sessions.Job ID", + "isHidden": false, + "isIdentityValue": false, + "isNullable": true, + "isPrimaryKey": false, + "isReadOnly": true, + "isSystemDefined": true, + "isUpdateable": false, + "obfuscationProperties": { + "maskType": "None", + "maskTypeID": 0, + "storageTypeID": 1, + "storageType": "Plain", + "valueDefinitionID": "0d86d645-31e2-e611-80cc-1402ec7222b4" + }, + "ordinal": 6, + "parentDefinition": { + "definitionID": "0b86d645-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "PredictiveIntelProductSessions", + "definitionName": { + "value": "Predictive Intelligence Product Sessions" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "Job_ID", + "storageFieldReferenceID": { + "type": "guid", + "value": "5c73cf1c-8fbd-4275-bca1-5a232c5ebb35" + }, + "valueDefinitionID": "0d86d645-31e2-e611-80cc-1402ec7222b4", + "valueDefinitionKey": "Job_ID", + "name": "Job ID", + "setDefinitionID": "0b86d645-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "PredictiveIntelProductSessions", + "setDefinitionName": { + "value": "Predictive Intelligence Product Sessions" + }, + "parentIdentifier": "0b86d645-31e2-e611-80cc-1402ec7222b4" + }, + { + "baseType": "Numeric", + "dataSourceID": 5, + "dataSourceName": {}, + "dataType": "LongNumber", + "description": "Landing_URL_ID", + "localizedDescription": { + "value": "Landing_URL_ID" + }, + "definitionID": "0e86d645-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "Landing_URL_ID", + "definitionName": { + "value": "Landing URL ID" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 7, + "fullyQualifiedName": "Predictive Intelligence Product Sessions.Landing URL ID", + "isHidden": false, + "isIdentityValue": false, + "isNullable": true, + "isPrimaryKey": false, + "isReadOnly": true, + "isSystemDefined": true, + "isUpdateable": false, + "obfuscationProperties": { + "maskType": "None", + "maskTypeID": 0, + "storageTypeID": 1, + "storageType": "Plain", + "valueDefinitionID": "0e86d645-31e2-e611-80cc-1402ec7222b4" + }, + "ordinal": 7, + "parentDefinition": { + "definitionID": "0b86d645-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "PredictiveIntelProductSessions", + "definitionName": { + "value": "Predictive Intelligence Product Sessions" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "Landing_URL_ID", + "storageFieldReferenceID": { + "type": "guid", + "value": "60fd37ce-3306-4197-a0e2-7c1b51b46d3a" + }, + "valueDefinitionID": "0e86d645-31e2-e611-80cc-1402ec7222b4", + "valueDefinitionKey": "Landing_URL_ID", + "name": "Landing URL ID", + "setDefinitionID": "0b86d645-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "PredictiveIntelProductSessions", + "setDefinitionName": { + "value": "Predictive Intelligence Product Sessions" + }, + "parentIdentifier": "0b86d645-31e2-e611-80cc-1402ec7222b4" + }, + { + "baseType": "Numeric", + "dataSourceID": 5, + "dataSourceName": {}, + "dataType": "LongNumber", + "description": "Subscriber_ID", + "localizedDescription": { + "value": "Subscriber_ID" + }, + "definitionID": "1186d645-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "Subscriber_ID", + "definitionName": { + "value": "Subscriber_ID" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 8, + "fullyQualifiedName": "Predictive Intelligence Product Sessions.Subscriber_ID", + "isHidden": false, + "isIdentityValue": false, + "isNullable": true, + "isPrimaryKey": false, + "isReadOnly": true, + "isSystemDefined": true, + "isUpdateable": false, + "obfuscationProperties": { + "maskType": "None", + "maskTypeID": 0, + "storageTypeID": 1, + "storageType": "Plain", + "valueDefinitionID": "1186d645-31e2-e611-80cc-1402ec7222b4" + }, + "ordinal": 8, + "parentDefinition": { + "definitionID": "0b86d645-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "PredictiveIntelProductSessions", + "definitionName": { + "value": "Predictive Intelligence Product Sessions" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "Subscriber_ID", + "storageFieldReferenceID": { + "type": "guid", + "value": "f239f3c3-3ecc-4ec4-a4c9-de258fdefdea" + }, + "valueDefinitionID": "1186d645-31e2-e611-80cc-1402ec7222b4", + "valueDefinitionKey": "Subscriber_ID", + "name": "Subscriber_ID", + "setDefinitionID": "0b86d645-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "PredictiveIntelProductSessions", + "setDefinitionName": { + "value": "Predictive Intelligence Product Sessions" + }, + "parentIdentifier": "0b86d645-31e2-e611-80cc-1402ec7222b4" + } + ], + "applicationID": "f4981f88-a13e-4abf-b331-47f41c73258d", + "applicationKey": "com.exacttarget.Predictive Web", + "attributeCount": 0, + "canAddValues": false, + "canChangeValues": false, + "canModify": false, + "canRemove": false, + "categoryID": 386, + "createdBy": -1000, + "createDate": "2017-01-24T06:33:00", + "customObjectOwnerMID": 1111111, + "dataRetentionProperties": { + "isRowBasedRetention": false, + "isResetRetentionPeriodOnImport": false, + "isDeleteAtEndOfRetentionPeriod": false, + "periodUnitOfMeasure": 4, + "setDefinitionID": "0b86d645-31e2-e611-80cc-1402ec7222b4" + }, + "localizedDescription": {}, + "fullyQualifiedName": "Predictive Intelligence Product Sessions", + "isCustomObjectBacked": true, + "isEvent": false, + "isHidden": false, + "isReadOnly": true, + "isRoot": false, + "isSendable": false, + "isShared": false, + "isSystemDefined": true, + "isTestaable": false, + "parentID": "00000000-0000-0000-0000-000000000000", + "relationshipCount": 0, + "storageLogicalType": "DataExtension", + "storageName": "PI_SESSIONS", + "storageObjectIDs": ["0286d645-31e2-e611-80cc-1402ec7222b4"], + "storageReferenceID": { + "type": "guid", + "value": "dd52de3f-31e2-e611-80cc-1402ec7222b4" + }, + "setDefinitionID": "0b86d645-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "PredictiveIntelProductSessions", + "name": "Predictive Intelligence Product Sessions" + }, + { + "definitionID": "1051de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "EmailAddresses", + "definitionName": { + "value": "Email Addresses" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "relationships": [ + { + "canModify": false, + "canRemove": false, + "isHidden": false, + "isSystemDefined": false, + "isGroupToSetRelationship": true, + "leftItem": { + "cardinality": "One", + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "identifier": "8f93dc39-31e2-e611-80cc-1402ec7222b4", + "relationshipType": "AttributeGroup" + }, + "leftRelationshipIDs": [ + { + "type": "int16", + "value": "4" + } + ], + "leftRelationshipReferenceType": "CustomerData", + "relationshipAttributes": [ + { + "leftAttributeID": "1151de3f-31e2-e611-80cc-1402ec7222b4", + "leftConnectingID": { + "identifierType": "FullyQualifiedName" + }, + "rightAttributeID": "1151de3f-31e2-e611-80cc-1402ec7222b4", + "rightConnectingID": { + "identifierType": "FullyQualifiedName" + } + } + ], + "relationshipID": "1451de3f-31e2-e611-80cc-1402ec7222b4", + "rightItem": { + "cardinality": "Many", + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "identifier": "1051de3f-31e2-e611-80cc-1402ec7222b4", + "relationshipType": "AttributeSet" + } + } + ], + "valueDefinitions": [ + { + "baseType": "Numeric", + "dataSourceID": 1, + "dataSourceName": {}, + "dataType": "Number", + "description": "", + "localizedDescription": { + "value": "" + }, + "definitionID": "1251de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "ListID", + "definitionName": { + "value": "List ID" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 0, + "fullyQualifiedName": "Email Addresses.List ID", + "isHidden": true, + "isIdentityValue": false, + "isNullable": false, + "isPrimaryKey": true, + "isReadOnly": true, + "isSystemDefined": true, + "isUpdateable": false, + "ordinal": 0, + "parentDefinition": { + "definitionID": "1051de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "EmailAddresses", + "definitionName": { + "value": "Email Addresses" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "ListID", + "valueDefinitionID": "1251de3f-31e2-e611-80cc-1402ec7222b4", + "valueDefinitionKey": "ListID", + "name": "List ID", + "setDefinitionID": "1051de3f-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "EmailAddresses", + "setDefinitionName": { + "value": "Email Addresses" + }, + "parentIdentifier": "1051de3f-31e2-e611-80cc-1402ec7222b4" + }, + { + "baseType": "Numeric", + "dataSourceID": 1, + "dataSourceName": {}, + "dataType": "Number", + "description": "", + "localizedDescription": { + "value": "" + }, + "definitionID": "1351de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "MemberID", + "definitionName": { + "value": "Member ID" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 0, + "fullyQualifiedName": "Email Addresses.Member ID", + "isHidden": true, + "isIdentityValue": false, + "isNullable": false, + "isPrimaryKey": true, + "isReadOnly": true, + "isSystemDefined": true, + "isUpdateable": false, + "ordinal": 0, + "parentDefinition": { + "definitionID": "1051de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "EmailAddresses", + "definitionName": { + "value": "Email Addresses" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "MemberID_", + "valueDefinitionID": "1351de3f-31e2-e611-80cc-1402ec7222b4", + "valueDefinitionKey": "MemberID", + "name": "Member ID", + "setDefinitionID": "1051de3f-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "EmailAddresses", + "setDefinitionName": { + "value": "Email Addresses" + }, + "parentIdentifier": "1051de3f-31e2-e611-80cc-1402ec7222b4" + }, + { + "baseType": "Text", + "customerDataID": 4, + "dataSourceID": 2, + "dataSourceName": {}, + "dataType": "EmailAddress", + "description": "", + "localizedDescription": { + "value": "" + }, + "definitionID": "1151de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "EmailAddress", + "definitionName": { + "value": "Email Address" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 1, + "fullyQualifiedName": "Email Addresses.Email Address", + "isHidden": false, + "isIdentityValue": false, + "isNullable": false, + "isPrimaryKey": true, + "isReadOnly": false, + "isSystemDefined": true, + "isUpdateable": false, + "ordinal": 1, + "parentDefinition": { + "definitionID": "1051de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "EmailAddresses", + "definitionName": { + "value": "Email Addresses" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "EmailAddr_", + "valueDefinitionID": "1151de3f-31e2-e611-80cc-1402ec7222b4", + "valueDefinitionKey": "EmailAddress", + "name": "Email Address", + "setDefinitionID": "1051de3f-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "EmailAddresses", + "setDefinitionName": { + "value": "Email Addresses" + }, + "parentIdentifier": "1051de3f-31e2-e611-80cc-1402ec7222b4" + }, + { + "baseType": "Boolean", + "dataSourceID": 2, + "dataSourceName": {}, + "dataType": "Boolean", + "description": "", + "localizedDescription": { + "value": "" + }, + "definitionID": "b951de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "HTMLEnabled", + "definitionName": { + "value": "HTML Enabled" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 2, + "fullyQualifiedName": "Email Addresses.HTML Enabled", + "isHidden": false, + "isIdentityValue": false, + "isNullable": false, + "isPrimaryKey": false, + "isReadOnly": false, + "isSystemDefined": true, + "isUpdateable": false, + "ordinal": 2, + "parentDefinition": { + "definitionID": "1051de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "EmailAddresses", + "definitionName": { + "value": "Email Addresses" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "IsHTMLEnabled", + "valueDefinitionID": "b951de3f-31e2-e611-80cc-1402ec7222b4", + "valueDefinitionKey": "HTMLEnabled", + "name": "HTML Enabled", + "setDefinitionID": "1051de3f-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "EmailAddresses", + "setDefinitionName": { + "value": "Email Addresses" + }, + "parentIdentifier": "1051de3f-31e2-e611-80cc-1402ec7222b4" + } + ], + "applicationID": "b2ca1f50-3cc4-4fd7-a3a3-88bf09fb59fa", + "applicationKey": "com.exacttarget.email", + "attributeCount": 0, + "canAddValues": false, + "canChangeValues": false, + "canModify": false, + "canRemove": false, + "createdBy": -1000, + "createDate": "2017-01-24T06:33:00", + "localizedDescription": {}, + "fullyQualifiedName": "Email Addresses", + "isCustomObjectBacked": false, + "isEvent": false, + "isHidden": false, + "isReadOnly": true, + "isRoot": false, + "isSendable": false, + "isSystemDefined": true, + "parentID": "00000000-0000-0000-0000-000000000000", + "relationshipCount": 1, + "storageObjectIDs": [ + "92492fc1-7a08-4c96-8536-0344719009e1", + "c336765a-f24f-49b2-8a1f-b54f903def2a" + ], + "setDefinitionID": "1051de3f-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "EmailAddresses", + "name": "Email Addresses" + }, + { + "definitionID": "1e86d645-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "PredictiveIntelContentViews", + "definitionName": { + "value": "Predictive Intelligence Content Views" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "relationships": [ + { + "canModify": false, + "canRemove": false, + "isHidden": false, + "isSystemDefined": false, + "isGroupToSetRelationship": false, + "leftItem": { + "cardinality": "Many", + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "identifier": "1e86d645-31e2-e611-80cc-1402ec7222b4", + "relationshipType": "AttributeSet" + }, + "relationshipAttributes": [ + { + "leftAttributeID": "1f86d645-31e2-e611-80cc-1402ec7222b4", + "leftConnectingID": { + "identifierType": "FullyQualifiedName" + }, + "rightAttributeID": "3086d645-31e2-e611-80cc-1402ec7222b4", + "rightConnectingID": { + "identifierType": "FullyQualifiedName" + } + } + ], + "relationshipID": "3586d645-31e2-e611-80cc-1402ec7222b4", + "rightItem": { + "cardinality": "One", + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "identifier": "2e86d645-31e2-e611-80cc-1402ec7222b4", + "relationshipType": "AttributeSet" + } + } + ], + "valueDefinitions": [ + { + "baseType": "Numeric", + "dataSourceID": 1, + "dataSourceName": {}, + "dataType": "LongNumber", + "description": "", + "localizedDescription": { + "value": "" + }, + "definitionID": "2486d645-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "CustomObjectKey", + "definitionName": { + "value": "Custom Object Key" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 1, + "fullyQualifiedName": "Predictive Intelligence Content Views.Custom Object Key", + "isHidden": true, + "isIdentityValue": true, + "isNullable": false, + "isPrimaryKey": false, + "isReadOnly": true, + "isSystemDefined": true, + "isUpdateable": false, + "ordinal": 1, + "parentDefinition": { + "definitionID": "1e86d645-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "PredictiveIntelContentViews", + "definitionName": { + "value": "Predictive Intelligence Content Views" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "_CustomObjectKey", + "valueDefinitionID": "2486d645-31e2-e611-80cc-1402ec7222b4", + "valueDefinitionKey": "CustomObjectKey", + "name": "Custom Object Key", + "setDefinitionID": "1e86d645-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "PredictiveIntelContentViews", + "setDefinitionName": { + "value": "Predictive Intelligence Content Views" + }, + "parentIdentifier": "1e86d645-31e2-e611-80cc-1402ec7222b4" + }, + { + "baseType": "Text", + "dataSourceID": 5, + "dataSourceName": {}, + "dataType": "Text", + "description": "content_id", + "localizedDescription": { + "value": "content_id" + }, + "definitionID": "1f86d645-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "Content_ID", + "definitionName": { + "value": "Content ID" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 2, + "fullyQualifiedName": "Predictive Intelligence Content Views.Content ID", + "isHidden": false, + "isIdentityValue": false, + "isNullable": true, + "isPrimaryKey": false, + "isReadOnly": true, + "isSystemDefined": true, + "isUpdateable": false, + "length": 256, + "obfuscationProperties": { + "maskType": "None", + "maskTypeID": 0, + "storageTypeID": 1, + "storageType": "Plain", + "valueDefinitionID": "1f86d645-31e2-e611-80cc-1402ec7222b4" + }, + "ordinal": 2, + "parentDefinition": { + "definitionID": "1e86d645-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "PredictiveIntelContentViews", + "definitionName": { + "value": "Predictive Intelligence Content Views" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "content_id", + "storageFieldReferenceID": { + "type": "guid", + "value": "1abf7b9d-1222-469f-9df9-7835829ec41f" + }, + "valueDefinitionID": "1f86d645-31e2-e611-80cc-1402ec7222b4", + "valueDefinitionKey": "Content_ID", + "name": "Content ID", + "setDefinitionID": "1e86d645-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "PredictiveIntelContentViews", + "setDefinitionName": { + "value": "Predictive Intelligence Content Views" + }, + "parentIdentifier": "1e86d645-31e2-e611-80cc-1402ec7222b4" + }, + { + "baseType": "Text", + "dataSourceID": 5, + "dataSourceName": {}, + "dataType": "Text", + "description": "user_Id", + "localizedDescription": { + "value": "user_Id" + }, + "definitionID": "2386d645-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "User_ID", + "definitionName": { + "value": "User ID" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 3, + "fullyQualifiedName": "Predictive Intelligence Content Views.User ID", + "isHidden": false, + "isIdentityValue": false, + "isNullable": false, + "isPrimaryKey": true, + "isReadOnly": true, + "isSystemDefined": true, + "isUpdateable": false, + "length": 256, + "obfuscationProperties": { + "maskType": "None", + "maskTypeID": 0, + "storageTypeID": 1, + "storageType": "Plain", + "valueDefinitionID": "2386d645-31e2-e611-80cc-1402ec7222b4" + }, + "ordinal": 3, + "parentDefinition": { + "definitionID": "1e86d645-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "PredictiveIntelContentViews", + "definitionName": { + "value": "Predictive Intelligence Content Views" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "user_Id", + "storageFieldReferenceID": { + "type": "guid", + "value": "a6c60012-6673-4402-8262-c6f06e1b0d13" + }, + "valueDefinitionID": "2386d645-31e2-e611-80cc-1402ec7222b4", + "valueDefinitionKey": "User_ID", + "name": "User ID", + "setDefinitionID": "1e86d645-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "PredictiveIntelContentViews", + "setDefinitionName": { + "value": "Predictive Intelligence Content Views" + }, + "parentIdentifier": "1e86d645-31e2-e611-80cc-1402ec7222b4" + }, + { + "baseType": "Text", + "dataSourceID": 5, + "dataSourceName": {}, + "dataType": "Text", + "description": "session_id", + "localizedDescription": { + "value": "session_id" + }, + "definitionID": "2186d645-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "Session_ID", + "definitionName": { + "value": "Session ID" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 4, + "fullyQualifiedName": "Predictive Intelligence Content Views.Session ID", + "isHidden": false, + "isIdentityValue": false, + "isNullable": true, + "isPrimaryKey": false, + "isReadOnly": true, + "isSystemDefined": true, + "isUpdateable": false, + "length": 256, + "obfuscationProperties": { + "maskType": "None", + "maskTypeID": 0, + "storageTypeID": 1, + "storageType": "Plain", + "valueDefinitionID": "2186d645-31e2-e611-80cc-1402ec7222b4" + }, + "ordinal": 4, + "parentDefinition": { + "definitionID": "1e86d645-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "PredictiveIntelContentViews", + "definitionName": { + "value": "Predictive Intelligence Content Views" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "session_id", + "storageFieldReferenceID": { + "type": "guid", + "value": "78820841-1579-42dd-8300-3cfe4eec96cc" + }, + "valueDefinitionID": "2186d645-31e2-e611-80cc-1402ec7222b4", + "valueDefinitionKey": "Session_ID", + "name": "Session ID", + "setDefinitionID": "1e86d645-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "PredictiveIntelContentViews", + "setDefinitionName": { + "value": "Predictive Intelligence Content Views" + }, + "parentIdentifier": "1e86d645-31e2-e611-80cc-1402ec7222b4" + }, + { + "baseType": "Text", + "dataSourceID": 5, + "dataSourceName": {}, + "dataType": "Text", + "description": "Search", + "localizedDescription": { + "value": "Search" + }, + "definitionID": "2086d645-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "Search", + "definitionName": { + "value": "Search" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 5, + "fullyQualifiedName": "Predictive Intelligence Content Views.Search", + "isHidden": false, + "isIdentityValue": false, + "isNullable": true, + "isPrimaryKey": false, + "isReadOnly": true, + "isSystemDefined": true, + "isUpdateable": false, + "length": 1000, + "obfuscationProperties": { + "maskType": "None", + "maskTypeID": 0, + "storageTypeID": 1, + "storageType": "Plain", + "valueDefinitionID": "2086d645-31e2-e611-80cc-1402ec7222b4" + }, + "ordinal": 5, + "parentDefinition": { + "definitionID": "1e86d645-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "PredictiveIntelContentViews", + "definitionName": { + "value": "Predictive Intelligence Content Views" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "Search", + "storageFieldReferenceID": { + "type": "guid", + "value": "f1ecc397-6be7-4a53-8792-0fdbaff63505" + }, + "valueDefinitionID": "2086d645-31e2-e611-80cc-1402ec7222b4", + "valueDefinitionKey": "Search", + "name": "Search", + "setDefinitionID": "1e86d645-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "PredictiveIntelContentViews", + "setDefinitionName": { + "value": "Predictive Intelligence Content Views" + }, + "parentIdentifier": "1e86d645-31e2-e611-80cc-1402ec7222b4" + }, + { + "baseType": "Date", + "dataSourceID": 5, + "dataSourceName": {}, + "dataType": "Date", + "description": "Timestamp", + "localizedDescription": { + "value": "Timestamp" + }, + "definitionID": "2286d645-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "Timestamp", + "definitionName": { + "value": "Timestamp" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 6, + "fullyQualifiedName": "Predictive Intelligence Content Views.Timestamp", + "isHidden": false, + "isIdentityValue": false, + "isNullable": false, + "isPrimaryKey": true, + "isReadOnly": true, + "isSystemDefined": true, + "isUpdateable": false, + "obfuscationProperties": { + "maskType": "None", + "maskTypeID": 0, + "storageTypeID": 1, + "storageType": "Plain", + "valueDefinitionID": "2286d645-31e2-e611-80cc-1402ec7222b4" + }, + "ordinal": 6, + "parentDefinition": { + "definitionID": "1e86d645-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "PredictiveIntelContentViews", + "definitionName": { + "value": "Predictive Intelligence Content Views" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "Timestamp", + "storageFieldReferenceID": { + "type": "guid", + "value": "e5c8ef5d-f2df-464d-b0ba-aa06536ac934" + }, + "valueDefinitionID": "2286d645-31e2-e611-80cc-1402ec7222b4", + "valueDefinitionKey": "Timestamp", + "name": "Timestamp", + "setDefinitionID": "1e86d645-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "PredictiveIntelContentViews", + "setDefinitionName": { + "value": "Predictive Intelligence Content Views" + }, + "parentIdentifier": "1e86d645-31e2-e611-80cc-1402ec7222b4" + } + ], + "applicationID": "f4981f88-a13e-4abf-b331-47f41c73258d", + "applicationKey": "com.exacttarget.Predictive Web", + "attributeCount": 0, + "canAddValues": false, + "canChangeValues": false, + "canModify": false, + "canRemove": false, + "categoryID": 386, + "createdBy": -1000, + "createDate": "2017-01-24T06:33:00", + "customObjectOwnerMID": 1111111, + "dataRetentionProperties": { + "isRowBasedRetention": false, + "isResetRetentionPeriodOnImport": false, + "isDeleteAtEndOfRetentionPeriod": false, + "periodUnitOfMeasure": 4, + "setDefinitionID": "1e86d645-31e2-e611-80cc-1402ec7222b4" + }, + "localizedDescription": {}, + "fullyQualifiedName": "Predictive Intelligence Content Views", + "isCustomObjectBacked": true, + "isEvent": false, + "isHidden": false, + "isReadOnly": true, + "isRoot": false, + "isSendable": false, + "isShared": false, + "isSystemDefined": true, + "isTestaable": false, + "parentID": "00000000-0000-0000-0000-000000000000", + "relationshipCount": 1, + "storageLogicalType": "DataExtension", + "storageName": "PI_CONTENTVIEWS", + "storageObjectIDs": ["1786d645-31e2-e611-80cc-1402ec7222b4"], + "storageReferenceID": { + "type": "guid", + "value": "da52de3f-31e2-e611-80cc-1402ec7222b4" + }, + "setDefinitionID": "1e86d645-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "PredictiveIntelContentViews", + "name": "Predictive Intelligence Content Views" + }, + { + "definitionID": "2b51de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "MobileDemographics", + "definitionName": { + "value": "MobileConnect Demographics" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "relationships": [ + { + "canModify": false, + "canRemove": false, + "isHidden": false, + "isSystemDefined": false, + "isGroupToSetRelationship": true, + "leftItem": { + "cardinality": "One", + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "identifier": "4351de3f-31e2-e611-80cc-1402ec7222b4", + "relationshipType": "AttributeGroup" + }, + "leftRelationshipIDs": [ + { + "type": "int16", + "value": "2" + } + ], + "leftRelationshipReferenceType": "CustomerData", + "relationshipAttributes": [ + { + "leftAttributeID": "9293dc39-31e2-e611-80cc-1402ec7222b4", + "leftConnectingID": { + "identifierType": "FullyQualifiedName" + }, + "rightAttributeID": "2f51de3f-31e2-e611-80cc-1402ec7222b4", + "rightConnectingID": { + "identifierType": "FullyQualifiedName" + } + } + ], + "relationshipID": "4651de3f-31e2-e611-80cc-1402ec7222b4", + "rightItem": { + "cardinality": "Many", + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "identifier": "2b51de3f-31e2-e611-80cc-1402ec7222b4", + "relationshipType": "AttributeSet" + } + }, + { + "canModify": false, + "canRemove": false, + "isHidden": false, + "isSystemDefined": false, + "isGroupToSetRelationship": false, + "leftItem": { + "cardinality": "One", + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "identifier": "2b51de3f-31e2-e611-80cc-1402ec7222b4", + "relationshipType": "AttributeSet" + }, + "relationshipAttributes": [ + { + "leftAttributeID": "3651de3f-31e2-e611-80cc-1402ec7222b4", + "leftConnectingID": { + "identifierType": "FullyQualifiedName" + }, + "rightAttributeID": "3452de3f-31e2-e611-80cc-1402ec7222b4", + "rightConnectingID": { + "identifierType": "FullyQualifiedName" + } + } + ], + "relationshipID": "4352de3f-31e2-e611-80cc-1402ec7222b4", + "rightItem": { + "cardinality": "Many", + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "identifier": "3152de3f-31e2-e611-80cc-1402ec7222b4", + "relationshipType": "AttributeSet" + } + } + ], + "valueDefinitions": [ + { + "baseType": "Numeric", + "dataSourceID": 3, + "dataSourceName": {}, + "dataType": "LongNumber", + "description": "", + "localizedDescription": { + "value": "" + }, + "definitionID": "2c51de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "CarrierID", + "definitionName": { + "value": "Carrier ID" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 1, + "fullyQualifiedName": "MobileConnect Demographics.Carrier ID", + "isHidden": false, + "isIdentityValue": false, + "isNullable": false, + "isPrimaryKey": false, + "isReadOnly": true, + "isSystemDefined": true, + "isUpdateable": false, + "obfuscationProperties": { + "maskType": "None", + "maskTypeID": 0, + "storageTypeID": 1, + "storageType": "Plain", + "valueDefinitionID": "2c51de3f-31e2-e611-80cc-1402ec7222b4" + }, + "ordinal": 1, + "parentDefinition": { + "definitionID": "2b51de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "MobileDemographics", + "definitionName": { + "value": "MobileConnect Demographics" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "_CarrierID", + "storageFieldReferenceID": { + "type": "guid", + "value": "3fdc8842-cc0f-407c-a3ec-930d7a027d1d" + }, + "valueDefinitionID": "2c51de3f-31e2-e611-80cc-1402ec7222b4", + "valueDefinitionKey": "CarrierID", + "name": "Carrier ID", + "setDefinitionID": "2b51de3f-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "MobileDemographics", + "setDefinitionName": { + "value": "MobileConnect Demographics" + }, + "parentIdentifier": "2b51de3f-31e2-e611-80cc-1402ec7222b4" + }, + { + "baseType": "Text", + "dataSourceID": 3, + "dataSourceName": {}, + "dataType": "Text", + "description": "", + "localizedDescription": { + "value": "" + }, + "definitionID": "2d51de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "Channel", + "definitionName": { + "value": "Channel" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 2, + "fullyQualifiedName": "MobileConnect Demographics.Channel", + "isHidden": false, + "isIdentityValue": false, + "isNullable": true, + "isPrimaryKey": false, + "isReadOnly": true, + "isSystemDefined": true, + "isUpdateable": false, + "length": 20, + "obfuscationProperties": { + "maskType": "None", + "maskTypeID": 0, + "storageTypeID": 1, + "storageType": "Plain", + "valueDefinitionID": "2d51de3f-31e2-e611-80cc-1402ec7222b4" + }, + "ordinal": 2, + "parentDefinition": { + "definitionID": "2b51de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "MobileDemographics", + "definitionName": { + "value": "MobileConnect Demographics" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "_Channel", + "storageFieldReferenceID": { + "type": "guid", + "value": "ef36ded9-67b2-4daf-899f-6862af8e5ee7" + }, + "valueDefinitionID": "2d51de3f-31e2-e611-80cc-1402ec7222b4", + "valueDefinitionKey": "Channel", + "name": "Channel", + "setDefinitionID": "2b51de3f-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "MobileDemographics", + "setDefinitionName": { + "value": "MobileConnect Demographics" + }, + "parentIdentifier": "2b51de3f-31e2-e611-80cc-1402ec7222b4" + }, + { + "baseType": "Text", + "dataSourceID": 3, + "dataSourceName": {}, + "dataType": "Text", + "description": "", + "localizedDescription": { + "value": "" + }, + "definitionID": "2e51de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "City", + "definitionName": { + "value": "City" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 3, + "fullyQualifiedName": "MobileConnect Demographics.City", + "isHidden": false, + "isIdentityValue": false, + "isNullable": true, + "isPrimaryKey": false, + "isReadOnly": false, + "isSystemDefined": false, + "isUpdateable": false, + "length": 200, + "obfuscationProperties": { + "maskType": "None", + "maskTypeID": 0, + "storageTypeID": 1, + "storageType": "Plain", + "valueDefinitionID": "2e51de3f-31e2-e611-80cc-1402ec7222b4" + }, + "ordinal": 3, + "parentDefinition": { + "definitionID": "2b51de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "MobileDemographics", + "definitionName": { + "value": "MobileConnect Demographics" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "_City", + "storageFieldReferenceID": { + "type": "guid", + "value": "be7b4554-bf03-4a80-9101-3e396b2e345f" + }, + "valueDefinitionID": "2e51de3f-31e2-e611-80cc-1402ec7222b4", + "valueDefinitionKey": "City", + "name": "City", + "setDefinitionID": "2b51de3f-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "MobileDemographics", + "setDefinitionName": { + "value": "MobileConnect Demographics" + }, + "parentIdentifier": "2b51de3f-31e2-e611-80cc-1402ec7222b4" + }, + { + "baseType": "Numeric", + "dataSourceID": 3, + "dataSourceName": {}, + "dataType": "LongNumber", + "description": "", + "localizedDescription": { + "value": "" + }, + "definitionID": "2f51de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "ContactID", + "definitionName": { + "value": "Contact ID" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 4, + "fullyQualifiedName": "MobileConnect Demographics.Contact ID", + "isHidden": false, + "isIdentityValue": false, + "isNullable": false, + "isPrimaryKey": true, + "isReadOnly": true, + "isSystemDefined": true, + "isUpdateable": false, + "obfuscationProperties": { + "maskType": "None", + "maskTypeID": 0, + "storageTypeID": 1, + "storageType": "Plain", + "valueDefinitionID": "2f51de3f-31e2-e611-80cc-1402ec7222b4" + }, + "ordinal": 4, + "parentDefinition": { + "definitionID": "2b51de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "MobileDemographics", + "definitionName": { + "value": "MobileConnect Demographics" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "_ContactID", + "storageFieldReferenceID": { + "type": "guid", + "value": "b0e31883-cae8-4bc5-aa24-88565d375a18" + }, + "valueDefinitionID": "2f51de3f-31e2-e611-80cc-1402ec7222b4", + "valueDefinitionKey": "ContactID", + "name": "Contact ID", + "setDefinitionID": "2b51de3f-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "MobileDemographics", + "setDefinitionName": { + "value": "MobileConnect Demographics" + }, + "parentIdentifier": "2b51de3f-31e2-e611-80cc-1402ec7222b4" + }, + { + "baseType": "Numeric", + "dataSourceID": 3, + "dataSourceName": {}, + "dataType": "LongNumber", + "description": "", + "localizedDescription": { + "value": "" + }, + "definitionID": "3151de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "CreatedBy", + "definitionName": { + "value": "Created By" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 5, + "fullyQualifiedName": "MobileConnect Demographics.Created By", + "isHidden": true, + "isIdentityValue": false, + "isNullable": true, + "isPrimaryKey": false, + "isReadOnly": true, + "isSystemDefined": true, + "isUpdateable": false, + "obfuscationProperties": { + "maskType": "None", + "maskTypeID": 0, + "storageTypeID": 1, + "storageType": "Plain", + "valueDefinitionID": "3151de3f-31e2-e611-80cc-1402ec7222b4" + }, + "ordinal": 5, + "parentDefinition": { + "definitionID": "2b51de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "MobileDemographics", + "definitionName": { + "value": "MobileConnect Demographics" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "_CreatedBy", + "storageFieldReferenceID": { + "type": "guid", + "value": "1671a32a-8eb0-4dc5-b30d-8ad16e55a601" + }, + "valueDefinitionID": "3151de3f-31e2-e611-80cc-1402ec7222b4", + "valueDefinitionKey": "CreatedBy", + "name": "Created By", + "setDefinitionID": "2b51de3f-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "MobileDemographics", + "setDefinitionName": { + "value": "MobileConnect Demographics" + }, + "parentIdentifier": "2b51de3f-31e2-e611-80cc-1402ec7222b4" + }, + { + "baseType": "Date", + "dataSourceID": 3, + "dataSourceName": {}, + "dataType": "Date", + "defaultValue": "GETDATE()", + "description": "", + "localizedDescription": { + "value": "" + }, + "definitionID": "3251de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "CreatedDate", + "definitionName": { + "value": "Created Date" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 6, + "fullyQualifiedName": "MobileConnect Demographics.Created Date", + "isHidden": false, + "isIdentityValue": false, + "isNullable": false, + "isPrimaryKey": false, + "isReadOnly": true, + "isSystemDefined": true, + "isUpdateable": false, + "obfuscationProperties": { + "maskType": "None", + "maskTypeID": 0, + "storageTypeID": 1, + "storageType": "Plain", + "valueDefinitionID": "3251de3f-31e2-e611-80cc-1402ec7222b4" + }, + "ordinal": 6, + "parentDefinition": { + "definitionID": "2b51de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "MobileDemographics", + "definitionName": { + "value": "MobileConnect Demographics" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "_CreatedDate", + "storageFieldReferenceID": { + "type": "guid", + "value": "de543ca5-5920-4309-adb9-33472144defe" + }, + "valueDefinitionID": "3251de3f-31e2-e611-80cc-1402ec7222b4", + "valueDefinitionKey": "CreatedDate", + "name": "Created Date", + "setDefinitionID": "2b51de3f-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "MobileDemographics", + "setDefinitionName": { + "value": "MobileConnect Demographics" + }, + "parentIdentifier": "2b51de3f-31e2-e611-80cc-1402ec7222b4" + }, + { + "baseType": "Text", + "dataSourceID": 3, + "dataSourceName": {}, + "dataType": "Text", + "description": "", + "localizedDescription": { + "value": "" + }, + "definitionID": "3351de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "FirstName", + "definitionName": { + "value": "First Name" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 9, + "fullyQualifiedName": "MobileConnect Demographics.First Name", + "isHidden": false, + "isIdentityValue": false, + "isNullable": true, + "isPrimaryKey": false, + "isReadOnly": false, + "isSystemDefined": false, + "isUpdateable": false, + "length": 100, + "obfuscationProperties": { + "maskType": "None", + "maskTypeID": 0, + "storageTypeID": 1, + "storageType": "Plain", + "valueDefinitionID": "3351de3f-31e2-e611-80cc-1402ec7222b4" + }, + "ordinal": 9, + "parentDefinition": { + "definitionID": "2b51de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "MobileDemographics", + "definitionName": { + "value": "MobileConnect Demographics" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "_FirstName", + "storageFieldReferenceID": { + "type": "guid", + "value": "125f7c91-2f11-44bd-9687-f22cf2461496" + }, + "valueDefinitionID": "3351de3f-31e2-e611-80cc-1402ec7222b4", + "valueDefinitionKey": "FirstName", + "name": "First Name", + "setDefinitionID": "2b51de3f-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "MobileDemographics", + "setDefinitionName": { + "value": "MobileConnect Demographics" + }, + "parentIdentifier": "2b51de3f-31e2-e611-80cc-1402ec7222b4" + }, + { + "baseType": "Boolean", + "dataSourceID": 3, + "dataSourceName": {}, + "dataType": "Boolean", + "defaultValue": "False", + "description": "", + "localizedDescription": { + "value": "" + }, + "definitionID": "3451de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "IsHonorDST", + "definitionName": { + "value": "Is Honor DST" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 10, + "fullyQualifiedName": "MobileConnect Demographics.Is Honor DST", + "isHidden": false, + "isIdentityValue": false, + "isNullable": true, + "isPrimaryKey": false, + "isReadOnly": false, + "isSystemDefined": true, + "isUpdateable": false, + "obfuscationProperties": { + "maskType": "None", + "maskTypeID": 0, + "storageTypeID": 1, + "storageType": "Plain", + "valueDefinitionID": "3451de3f-31e2-e611-80cc-1402ec7222b4" + }, + "ordinal": 10, + "parentDefinition": { + "definitionID": "2b51de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "MobileDemographics", + "definitionName": { + "value": "MobileConnect Demographics" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "_IsHonorDST", + "storageFieldReferenceID": { + "type": "guid", + "value": "17abe00a-4306-43c5-b27f-a81f015d6dfb" + }, + "valueDefinitionID": "3451de3f-31e2-e611-80cc-1402ec7222b4", + "valueDefinitionKey": "IsHonorDST", + "name": "Is Honor DST", + "setDefinitionID": "2b51de3f-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "MobileDemographics", + "setDefinitionName": { + "value": "MobileConnect Demographics" + }, + "parentIdentifier": "2b51de3f-31e2-e611-80cc-1402ec7222b4" + }, + { + "baseType": "Text", + "dataSourceID": 3, + "dataSourceName": {}, + "dataType": "Text", + "description": "", + "localizedDescription": { + "value": "" + }, + "definitionID": "3551de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "LastName", + "definitionName": { + "value": "Last Name" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 11, + "fullyQualifiedName": "MobileConnect Demographics.Last Name", + "isHidden": false, + "isIdentityValue": false, + "isNullable": true, + "isPrimaryKey": false, + "isReadOnly": false, + "isSystemDefined": false, + "isUpdateable": false, + "length": 100, + "obfuscationProperties": { + "maskType": "None", + "maskTypeID": 0, + "storageTypeID": 1, + "storageType": "Plain", + "valueDefinitionID": "3551de3f-31e2-e611-80cc-1402ec7222b4" + }, + "ordinal": 11, + "parentDefinition": { + "definitionID": "2b51de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "MobileDemographics", + "definitionName": { + "value": "MobileConnect Demographics" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "_LastName", + "storageFieldReferenceID": { + "type": "guid", + "value": "e31f18f4-5422-410b-adcc-1b60f61cce5f" + }, + "valueDefinitionID": "3551de3f-31e2-e611-80cc-1402ec7222b4", + "valueDefinitionKey": "LastName", + "name": "Last Name", + "setDefinitionID": "2b51de3f-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "MobileDemographics", + "setDefinitionName": { + "value": "MobileConnect Demographics" + }, + "parentIdentifier": "2b51de3f-31e2-e611-80cc-1402ec7222b4" + }, + { + "baseType": "Text", + "dataSourceID": 3, + "dataSourceName": {}, + "dataType": "Text", + "description": "", + "localizedDescription": { + "value": "" + }, + "definitionID": "3051de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "CountryCode", + "definitionName": { + "value": "Locale" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 12, + "fullyQualifiedName": "MobileConnect Demographics.Locale", + "isHidden": false, + "isIdentityValue": false, + "isNullable": false, + "isPrimaryKey": false, + "isReadOnly": false, + "isSystemDefined": true, + "isUpdateable": false, + "length": 2, + "obfuscationProperties": { + "maskType": "None", + "maskTypeID": 0, + "storageTypeID": 1, + "storageType": "Plain", + "valueDefinitionID": "3051de3f-31e2-e611-80cc-1402ec7222b4" + }, + "ordinal": 12, + "parentDefinition": { + "definitionID": "2b51de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "MobileDemographics", + "definitionName": { + "value": "MobileConnect Demographics" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "_CountryCode", + "storageFieldReferenceID": { + "type": "guid", + "value": "4b5fda70-47cb-4f4b-8ba6-f5cac53ee344" + }, + "valueDefinitionID": "3051de3f-31e2-e611-80cc-1402ec7222b4", + "valueDefinitionKey": "CountryCode", + "name": "Locale", + "setDefinitionID": "2b51de3f-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "MobileDemographics", + "setDefinitionName": { + "value": "MobileConnect Demographics" + }, + "parentIdentifier": "2b51de3f-31e2-e611-80cc-1402ec7222b4" + }, + { + "baseType": "Numeric", + "dataSourceID": 3, + "dataSourceName": {}, + "dataType": "LongNumber", + "description": "", + "localizedDescription": { + "value": "" + }, + "definitionID": "2ddd5f89-bca1-ed11-b852-48df37d1df5b", + "definitionKey": "MobileID", + "definitionName": { + "value": "Mobile ID" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 13, + "fullyQualifiedName": "MobileConnect Demographics.Mobile ID", + "isHidden": true, + "isIdentityValue": true, + "isNullable": false, + "isPrimaryKey": false, + "isReadOnly": true, + "isSystemDefined": true, + "isUpdateable": false, + "ordinal": 13, + "parentDefinition": { + "definitionID": "2b51de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "MobileDemographics", + "definitionName": { + "value": "MobileConnect Demographics" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "_MobileId", + "valueDefinitionID": "2ddd5f89-bca1-ed11-b852-48df37d1df5b", + "valueDefinitionKey": "MobileID", + "name": "Mobile ID", + "setDefinitionID": "2b51de3f-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "MobileDemographics", + "setDefinitionName": { + "value": "MobileConnect Demographics" + }, + "parentIdentifier": "2b51de3f-31e2-e611-80cc-1402ec7222b4" + }, + { + "baseType": "Text", + "customerDataID": 5, + "dataSourceID": 3, + "dataSourceName": {}, + "dataType": "Phone", + "description": "", + "localizedDescription": { + "value": "" + }, + "definitionID": "3651de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "MobileNumber", + "definitionName": { + "value": "Mobile Number" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 14, + "fullyQualifiedName": "MobileConnect Demographics.Mobile Number", + "isHidden": false, + "isIdentityValue": false, + "isNullable": false, + "isPrimaryKey": true, + "isReadOnly": false, + "isSystemDefined": true, + "isUpdateable": false, + "length": 15, + "obfuscationProperties": { + "maskType": "None", + "maskTypeID": 0, + "storageTypeID": 1, + "storageType": "Plain", + "valueDefinitionID": "3651de3f-31e2-e611-80cc-1402ec7222b4" + }, + "ordinal": 14, + "parentDefinition": { + "definitionID": "2b51de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "MobileDemographics", + "definitionName": { + "value": "MobileConnect Demographics" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "_MobileNumber", + "storageFieldReferenceID": { + "type": "guid", + "value": "e31a7e3b-e943-440e-9be6-77224a4928fe" + }, + "valueDefinitionID": "3651de3f-31e2-e611-80cc-1402ec7222b4", + "valueDefinitionKey": "MobileNumber", + "name": "Mobile Number", + "setDefinitionID": "2b51de3f-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "MobileDemographics", + "setDefinitionName": { + "value": "MobileConnect Demographics" + }, + "parentIdentifier": "2b51de3f-31e2-e611-80cc-1402ec7222b4" + }, + { + "baseType": "Numeric", + "dataSourceID": 3, + "dataSourceName": {}, + "dataType": "LongNumber", + "description": "", + "localizedDescription": { + "value": "" + }, + "definitionID": "3751de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "ModifiedBy", + "definitionName": { + "value": "Modified By" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 15, + "fullyQualifiedName": "MobileConnect Demographics.Modified By", + "isHidden": true, + "isIdentityValue": false, + "isNullable": true, + "isPrimaryKey": false, + "isReadOnly": true, + "isSystemDefined": true, + "isUpdateable": false, + "obfuscationProperties": { + "maskType": "None", + "maskTypeID": 0, + "storageTypeID": 1, + "storageType": "Plain", + "valueDefinitionID": "3751de3f-31e2-e611-80cc-1402ec7222b4" + }, + "ordinal": 15, + "parentDefinition": { + "definitionID": "2b51de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "MobileDemographics", + "definitionName": { + "value": "MobileConnect Demographics" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "_ModifiedBy", + "storageFieldReferenceID": { + "type": "guid", + "value": "a9be58ef-884d-44f4-9926-d73ebe587847" + }, + "valueDefinitionID": "3751de3f-31e2-e611-80cc-1402ec7222b4", + "valueDefinitionKey": "ModifiedBy", + "name": "Modified By", + "setDefinitionID": "2b51de3f-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "MobileDemographics", + "setDefinitionName": { + "value": "MobileConnect Demographics" + }, + "parentIdentifier": "2b51de3f-31e2-e611-80cc-1402ec7222b4" + }, + { + "baseType": "Date", + "dataSourceID": 3, + "dataSourceName": {}, + "dataType": "Date", + "defaultValue": "GETDATE()", + "description": "", + "localizedDescription": { + "value": "" + }, + "definitionID": "3851de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "ModifiedDate", + "definitionName": { + "value": "Modified Date" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 16, + "fullyQualifiedName": "MobileConnect Demographics.Modified Date", + "isHidden": false, + "isIdentityValue": false, + "isNullable": false, + "isPrimaryKey": false, + "isReadOnly": true, + "isSystemDefined": true, + "isUpdateable": false, + "obfuscationProperties": { + "maskType": "None", + "maskTypeID": 0, + "storageTypeID": 1, + "storageType": "Plain", + "valueDefinitionID": "3851de3f-31e2-e611-80cc-1402ec7222b4" + }, + "ordinal": 16, + "parentDefinition": { + "definitionID": "2b51de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "MobileDemographics", + "definitionName": { + "value": "MobileConnect Demographics" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "_ModifiedDate", + "storageFieldReferenceID": { + "type": "guid", + "value": "216659c1-9512-47de-a9ee-822f48148514" + }, + "valueDefinitionID": "3851de3f-31e2-e611-80cc-1402ec7222b4", + "valueDefinitionKey": "ModifiedDate", + "name": "Modified Date", + "setDefinitionID": "2b51de3f-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "MobileDemographics", + "setDefinitionName": { + "value": "MobileConnect Demographics" + }, + "parentIdentifier": "2b51de3f-31e2-e611-80cc-1402ec7222b4" + }, + { + "baseType": "Numeric", + "dataSourceID": 3, + "dataSourceName": {}, + "dataType": "Byte", + "description": "", + "localizedDescription": { + "value": "" + }, + "definitionID": "3951de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "Priority", + "definitionName": { + "value": "Priority" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 17, + "fullyQualifiedName": "MobileConnect Demographics.Priority", + "isHidden": false, + "isIdentityValue": false, + "isNullable": true, + "isPrimaryKey": false, + "isReadOnly": true, + "isSystemDefined": true, + "isUpdateable": false, + "obfuscationProperties": { + "maskType": "None", + "maskTypeID": 0, + "storageTypeID": 1, + "storageType": "Plain", + "valueDefinitionID": "3951de3f-31e2-e611-80cc-1402ec7222b4" + }, + "ordinal": 17, + "parentDefinition": { + "definitionID": "2b51de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "MobileDemographics", + "definitionName": { + "value": "MobileConnect Demographics" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "_Priority", + "storageFieldReferenceID": { + "type": "guid", + "value": "71153ee5-a33f-4cf6-a963-0c3a893d9348" + }, + "valueDefinitionID": "3951de3f-31e2-e611-80cc-1402ec7222b4", + "valueDefinitionKey": "Priority", + "name": "Priority", + "setDefinitionID": "2b51de3f-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "MobileDemographics", + "setDefinitionName": { + "value": "MobileConnect Demographics" + }, + "parentIdentifier": "2b51de3f-31e2-e611-80cc-1402ec7222b4" + }, + { + "baseType": "Numeric", + "dataSourceID": 3, + "dataSourceName": {}, + "dataType": "Byte", + "description": "", + "localizedDescription": { + "value": "" + }, + "definitionID": "3a51de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "Source", + "definitionName": { + "value": "Source" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 18, + "fullyQualifiedName": "MobileConnect Demographics.Source", + "isHidden": false, + "isIdentityValue": false, + "isNullable": true, + "isPrimaryKey": false, + "isReadOnly": true, + "isSystemDefined": true, + "isUpdateable": false, + "obfuscationProperties": { + "maskType": "None", + "maskTypeID": 0, + "storageTypeID": 1, + "storageType": "Plain", + "valueDefinitionID": "3a51de3f-31e2-e611-80cc-1402ec7222b4" + }, + "ordinal": 18, + "parentDefinition": { + "definitionID": "2b51de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "MobileDemographics", + "definitionName": { + "value": "MobileConnect Demographics" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "restrictionLookupListID": 5, + "storageName": "_Source", + "storageFieldReferenceID": { + "type": "guid", + "value": "f6bafdfb-86bf-45e8-9b76-b878c904d6c5" + }, + "valueDefinitionID": "3a51de3f-31e2-e611-80cc-1402ec7222b4", + "valueDefinitionKey": "Source", + "name": "Source", + "setDefinitionID": "2b51de3f-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "MobileDemographics", + "setDefinitionName": { + "value": "MobileConnect Demographics" + }, + "parentIdentifier": "2b51de3f-31e2-e611-80cc-1402ec7222b4" + }, + { + "baseType": "Text", + "dataSourceID": 3, + "dataSourceName": {}, + "dataType": "Text", + "description": "", + "localizedDescription": { + "value": "" + }, + "definitionID": "3b51de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "SourceObjectID", + "definitionName": { + "value": "Source Object ID" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 19, + "fullyQualifiedName": "MobileConnect Demographics.Source Object ID", + "isHidden": false, + "isIdentityValue": false, + "isNullable": true, + "isPrimaryKey": false, + "isReadOnly": true, + "isSystemDefined": true, + "isUpdateable": false, + "length": 200, + "obfuscationProperties": { + "maskType": "None", + "maskTypeID": 0, + "storageTypeID": 1, + "storageType": "Plain", + "valueDefinitionID": "3b51de3f-31e2-e611-80cc-1402ec7222b4" + }, + "ordinal": 19, + "parentDefinition": { + "definitionID": "2b51de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "MobileDemographics", + "definitionName": { + "value": "MobileConnect Demographics" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "_SourceObjectId", + "storageFieldReferenceID": { + "type": "guid", + "value": "c67a7922-44e5-4c4b-a4c8-2ac3550a5f07" + }, + "valueDefinitionID": "3b51de3f-31e2-e611-80cc-1402ec7222b4", + "valueDefinitionKey": "SourceObjectID", + "name": "Source Object ID", + "setDefinitionID": "2b51de3f-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "MobileDemographics", + "setDefinitionName": { + "value": "MobileConnect Demographics" + }, + "parentIdentifier": "2b51de3f-31e2-e611-80cc-1402ec7222b4" + }, + { + "baseType": "Text", + "dataSourceID": 4, + "dataSourceName": {}, + "dataType": "Text", + "description": "", + "localizedDescription": { + "value": "" + }, + "definitionID": "67ace0e3-8563-e811-80d4-1402ec721f75", + "definitionKey": "SFContactID", + "definitionName": { + "value": "SFContactID" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 19, + "fullyQualifiedName": "MobileConnect Demographics.SFContactID", + "isHidden": false, + "isIdentityValue": false, + "isNullable": true, + "isPrimaryKey": false, + "isReadOnly": false, + "isSystemDefined": false, + "isUpdateable": true, + "length": 50, + "obfuscationProperties": { + "maskType": "None", + "maskTypeID": 0, + "storageTypeID": 1, + "storageType": "Plain", + "valueDefinitionID": "67ace0e3-8563-e811-80d4-1402ec721f75" + }, + "ordinal": 19, + "parentDefinition": { + "definitionID": "2b51de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "MobileDemographics", + "definitionName": { + "value": "MobileConnect Demographics" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "SFContactID", + "storageFieldReferenceID": { + "type": "guid", + "value": "ce5a90ea-88eb-4683-9a1a-5c776b5763ce" + }, + "valueDefinitionID": "67ace0e3-8563-e811-80d4-1402ec721f75", + "valueDefinitionKey": "SFContactID", + "name": "SFContactID", + "setDefinitionID": "2b51de3f-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "MobileDemographics", + "setDefinitionName": { + "value": "MobileConnect Demographics" + }, + "parentIdentifier": "2b51de3f-31e2-e611-80cc-1402ec7222b4" + }, + { + "baseType": "Text", + "dataSourceID": 3, + "dataSourceName": {}, + "dataType": "Text", + "description": "", + "localizedDescription": { + "value": "" + }, + "definitionID": "3c51de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "State", + "definitionName": { + "value": "State" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 20, + "fullyQualifiedName": "MobileConnect Demographics.State", + "isHidden": false, + "isIdentityValue": false, + "isNullable": true, + "isPrimaryKey": false, + "isReadOnly": false, + "isSystemDefined": false, + "isUpdateable": false, + "length": 200, + "obfuscationProperties": { + "maskType": "None", + "maskTypeID": 0, + "storageTypeID": 1, + "storageType": "Plain", + "valueDefinitionID": "3c51de3f-31e2-e611-80cc-1402ec7222b4" + }, + "ordinal": 20, + "parentDefinition": { + "definitionID": "2b51de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "MobileDemographics", + "definitionName": { + "value": "MobileConnect Demographics" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "_State", + "storageFieldReferenceID": { + "type": "guid", + "value": "c0ea1fac-d939-4dde-b45a-16586f661924" + }, + "valueDefinitionID": "3c51de3f-31e2-e611-80cc-1402ec7222b4", + "valueDefinitionKey": "State", + "name": "State", + "setDefinitionID": "2b51de3f-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "MobileDemographics", + "setDefinitionName": { + "value": "MobileConnect Demographics" + }, + "parentIdentifier": "2b51de3f-31e2-e611-80cc-1402ec7222b4" + }, + { + "baseType": "Numeric", + "dataSourceID": 3, + "dataSourceName": {}, + "dataType": "Byte", + "description": "", + "localizedDescription": { + "value": "" + }, + "definitionID": "3d51de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "Status", + "definitionName": { + "value": "Status" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 21, + "fullyQualifiedName": "MobileConnect Demographics.Status", + "isHidden": false, + "isIdentityValue": false, + "isNullable": true, + "isPrimaryKey": false, + "isReadOnly": false, + "isSystemDefined": true, + "isUpdateable": false, + "obfuscationProperties": { + "maskType": "None", + "maskTypeID": 0, + "storageTypeID": 1, + "storageType": "Plain", + "valueDefinitionID": "3d51de3f-31e2-e611-80cc-1402ec7222b4" + }, + "ordinal": 21, + "parentDefinition": { + "definitionID": "2b51de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "MobileDemographics", + "definitionName": { + "value": "MobileConnect Demographics" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "restrictionLookupListID": 6, + "storageName": "_Status", + "storageFieldReferenceID": { + "type": "guid", + "value": "fafff407-c055-411c-81ec-78907f5dbd58" + }, + "valueDefinitionID": "3d51de3f-31e2-e611-80cc-1402ec7222b4", + "valueDefinitionKey": "Status", + "name": "Status", + "setDefinitionID": "2b51de3f-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "MobileDemographics", + "setDefinitionName": { + "value": "MobileConnect Demographics" + }, + "parentIdentifier": "2b51de3f-31e2-e611-80cc-1402ec7222b4" + }, + { + "baseType": "Numeric", + "dataSourceID": 3, + "dataSourceName": {}, + "dataType": "Decimal", + "description": "", + "localizedDescription": { + "value": "" + }, + "definitionID": "3e51de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "UTCOffset", + "definitionName": { + "value": "UTC Offset" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 22, + "fullyQualifiedName": "MobileConnect Demographics.UTC Offset", + "isHidden": false, + "isIdentityValue": false, + "isNullable": true, + "isPrimaryKey": false, + "isReadOnly": false, + "isSystemDefined": true, + "isUpdateable": false, + "length": 4, + "obfuscationProperties": { + "maskType": "None", + "maskTypeID": 0, + "storageTypeID": 1, + "storageType": "Plain", + "valueDefinitionID": "3e51de3f-31e2-e611-80cc-1402ec7222b4" + }, + "ordinal": 22, + "parentDefinition": { + "definitionID": "2b51de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "MobileDemographics", + "definitionName": { + "value": "MobileConnect Demographics" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "scale": 2, + "storageName": "_UTCOffset", + "storageFieldReferenceID": { + "type": "guid", + "value": "84d29656-a348-43c2-ac2f-8c7ec5b18a3e" + }, + "valueDefinitionID": "3e51de3f-31e2-e611-80cc-1402ec7222b4", + "valueDefinitionKey": "UTCOffset", + "name": "UTC Offset", + "setDefinitionID": "2b51de3f-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "MobileDemographics", + "setDefinitionName": { + "value": "MobileConnect Demographics" + }, + "parentIdentifier": "2b51de3f-31e2-e611-80cc-1402ec7222b4" + }, + { + "baseType": "Text", + "dataSourceID": 3, + "dataSourceName": {}, + "dataType": "Text", + "description": "", + "localizedDescription": { + "value": "" + }, + "definitionID": "3f51de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "ZipCode", + "definitionName": { + "value": "Zip Code" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 23, + "fullyQualifiedName": "MobileConnect Demographics.Zip Code", + "isHidden": false, + "isIdentityValue": false, + "isNullable": true, + "isPrimaryKey": false, + "isReadOnly": false, + "isSystemDefined": false, + "isUpdateable": false, + "length": 20, + "obfuscationProperties": { + "maskType": "None", + "maskTypeID": 0, + "storageTypeID": 1, + "storageType": "Plain", + "valueDefinitionID": "3f51de3f-31e2-e611-80cc-1402ec7222b4" + }, + "ordinal": 23, + "parentDefinition": { + "definitionID": "2b51de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "MobileDemographics", + "definitionName": { + "value": "MobileConnect Demographics" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "_ZipCode", + "storageFieldReferenceID": { + "type": "guid", + "value": "11ce9d05-a1e3-47ba-9077-11097e0b4c8d" + }, + "valueDefinitionID": "3f51de3f-31e2-e611-80cc-1402ec7222b4", + "valueDefinitionKey": "ZipCode", + "name": "Zip Code", + "setDefinitionID": "2b51de3f-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "MobileDemographics", + "setDefinitionName": { + "value": "MobileConnect Demographics" + }, + "parentIdentifier": "2b51de3f-31e2-e611-80cc-1402ec7222b4" + } + ], + "applicationID": "e25893f9-08f3-480f-8def-7f8ab0583611", + "applicationKey": "com.exacttarget.mobileconnect", + "attributeCount": 0, + "canAddValues": true, + "canChangeValues": true, + "canModify": false, + "canRemove": false, + "categoryID": 2, + "createdBy": -1000, + "createDate": "2017-01-24T06:33:00", + "customObjectOwnerMID": 1111111, + "dataRetentionProperties": { + "isRowBasedRetention": false, + "isResetRetentionPeriodOnImport": false, + "isDeleteAtEndOfRetentionPeriod": false, + "setDefinitionID": "2b51de3f-31e2-e611-80cc-1402ec7222b4" + }, + "localizedDescription": {}, + "fullyQualifiedName": "MobileConnect Demographics", + "isCustomObjectBacked": true, + "isEvent": false, + "isHidden": false, + "isReadOnly": false, + "isRoot": false, + "isSendable": true, + "isShared": false, + "isSystemDefined": true, + "isTestaable": false, + "parentID": "00000000-0000-0000-0000-000000000000", + "relationshipCount": 2, + "sendAttributeStorageName": "_ContactID", + "sendContactKeyStorageName": "_SubscriberID", + "storageLogicalType": "MobileAttributes", + "storageName": "_MobileAddress", + "storageObjectIDs": ["1651de3f-31e2-e611-80cc-1402ec7222b4"], + "storageReferenceID": { + "type": "guid", + "value": "7693dc39-31e2-e611-80cc-1402ec7222b4" + }, + "setDefinitionID": "2b51de3f-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "MobileDemographics", + "name": "MobileConnect Demographics" + }, + { + "definitionID": "2e86d645-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "PredictiveIntelContent", + "definitionName": { + "value": "Predictive Intelligence Content" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "relationships": [ + { + "canModify": false, + "canRemove": false, + "isHidden": false, + "isSystemDefined": false, + "isGroupToSetRelationship": false, + "leftItem": { + "cardinality": "One", + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "identifier": "2e86d645-31e2-e611-80cc-1402ec7222b4", + "relationshipType": "AttributeSet" + }, + "relationshipAttributes": [ + { + "leftAttributeID": "3086d645-31e2-e611-80cc-1402ec7222b4", + "leftConnectingID": { + "identifierType": "FullyQualifiedName" + }, + "rightAttributeID": "4286d645-31e2-e611-80cc-1402ec7222b4", + "rightConnectingID": { + "identifierType": "FullyQualifiedName" + } + } + ], + "relationshipID": "4686d645-31e2-e611-80cc-1402ec7222b4", + "rightItem": { + "cardinality": "Many", + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "identifier": "3e86d645-31e2-e611-80cc-1402ec7222b4", + "relationshipType": "AttributeSet" + } + } + ], + "valueDefinitions": [ + { + "baseType": "Numeric", + "dataSourceID": 1, + "dataSourceName": {}, + "dataType": "LongNumber", + "description": "", + "localizedDescription": { + "value": "" + }, + "definitionID": "3386d645-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "CustomObjectKey", + "definitionName": { + "value": "Custom Object Key" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 1, + "fullyQualifiedName": "Predictive Intelligence Content.Custom Object Key", + "isHidden": true, + "isIdentityValue": true, + "isNullable": false, + "isPrimaryKey": false, + "isReadOnly": true, + "isSystemDefined": true, + "isUpdateable": false, + "ordinal": 1, + "parentDefinition": { + "definitionID": "2e86d645-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "PredictiveIntelContent", + "definitionName": { + "value": "Predictive Intelligence Content" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "_CustomObjectKey", + "valueDefinitionID": "3386d645-31e2-e611-80cc-1402ec7222b4", + "valueDefinitionKey": "CustomObjectKey", + "name": "Custom Object Key", + "setDefinitionID": "2e86d645-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "PredictiveIntelContent", + "setDefinitionName": { + "value": "Predictive Intelligence Content" + }, + "parentIdentifier": "2e86d645-31e2-e611-80cc-1402ec7222b4" + }, + { + "baseType": "Text", + "dataSourceID": 5, + "dataSourceName": {}, + "dataType": "Text", + "description": "content_id", + "localizedDescription": { + "value": "content_id" + }, + "definitionID": "3086d645-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "Content_ID", + "definitionName": { + "value": "Content ID" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 2, + "fullyQualifiedName": "Predictive Intelligence Content.Content ID", + "isHidden": false, + "isIdentityValue": false, + "isNullable": false, + "isPrimaryKey": false, + "isReadOnly": true, + "isSystemDefined": true, + "isUpdateable": false, + "length": 256, + "obfuscationProperties": { + "maskType": "None", + "maskTypeID": 0, + "storageTypeID": 1, + "storageType": "Plain", + "valueDefinitionID": "3086d645-31e2-e611-80cc-1402ec7222b4" + }, + "ordinal": 2, + "parentDefinition": { + "definitionID": "2e86d645-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "PredictiveIntelContent", + "definitionName": { + "value": "Predictive Intelligence Content" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "content_id", + "storageFieldReferenceID": { + "type": "guid", + "value": "9fd67d4d-cae5-4230-8cf1-f19cd230a233" + }, + "valueDefinitionID": "3086d645-31e2-e611-80cc-1402ec7222b4", + "valueDefinitionKey": "Content_ID", + "name": "Content ID", + "setDefinitionID": "2e86d645-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "PredictiveIntelContent", + "setDefinitionName": { + "value": "Predictive Intelligence Content" + }, + "parentIdentifier": "2e86d645-31e2-e611-80cc-1402ec7222b4" + }, + { + "baseType": "Boolean", + "dataSourceID": 5, + "dataSourceName": {}, + "dataType": "Boolean", + "description": "availability", + "localizedDescription": { + "value": "availability" + }, + "definitionID": "2f86d645-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "Availability", + "definitionName": { + "value": "Availability" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 3, + "fullyQualifiedName": "Predictive Intelligence Content.Availability", + "isHidden": false, + "isIdentityValue": false, + "isNullable": true, + "isPrimaryKey": false, + "isReadOnly": true, + "isSystemDefined": true, + "isUpdateable": false, + "obfuscationProperties": { + "maskType": "None", + "maskTypeID": 0, + "storageTypeID": 1, + "storageType": "Plain", + "valueDefinitionID": "2f86d645-31e2-e611-80cc-1402ec7222b4" + }, + "ordinal": 3, + "parentDefinition": { + "definitionID": "2e86d645-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "PredictiveIntelContent", + "definitionName": { + "value": "Predictive Intelligence Content" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "availability", + "storageFieldReferenceID": { + "type": "guid", + "value": "d32b9706-78a0-40fd-aae5-e345b1f217a6" + }, + "valueDefinitionID": "2f86d645-31e2-e611-80cc-1402ec7222b4", + "valueDefinitionKey": "Availability", + "name": "Availability", + "setDefinitionID": "2e86d645-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "PredictiveIntelContent", + "setDefinitionName": { + "value": "Predictive Intelligence Content" + }, + "parentIdentifier": "2e86d645-31e2-e611-80cc-1402ec7222b4" + }, + { + "baseType": "Text", + "dataSourceID": 5, + "dataSourceName": {}, + "dataType": "Text", + "description": "title", + "localizedDescription": { + "value": "title" + }, + "definitionID": "3186d645-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "Title", + "definitionName": { + "value": "Title" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 4, + "fullyQualifiedName": "Predictive Intelligence Content.Title", + "isHidden": false, + "isIdentityValue": false, + "isNullable": true, + "isPrimaryKey": false, + "isReadOnly": true, + "isSystemDefined": true, + "isUpdateable": false, + "length": 1000, + "obfuscationProperties": { + "maskType": "None", + "maskTypeID": 0, + "storageTypeID": 1, + "storageType": "Plain", + "valueDefinitionID": "3186d645-31e2-e611-80cc-1402ec7222b4" + }, + "ordinal": 4, + "parentDefinition": { + "definitionID": "2e86d645-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "PredictiveIntelContent", + "definitionName": { + "value": "Predictive Intelligence Content" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "title", + "storageFieldReferenceID": { + "type": "guid", + "value": "93497a91-7e2d-4c5f-8546-fd035fea3e92" + }, + "valueDefinitionID": "3186d645-31e2-e611-80cc-1402ec7222b4", + "valueDefinitionKey": "Title", + "name": "Title", + "setDefinitionID": "2e86d645-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "PredictiveIntelContent", + "setDefinitionName": { + "value": "Predictive Intelligence Content" + }, + "parentIdentifier": "2e86d645-31e2-e611-80cc-1402ec7222b4" + }, + { + "baseType": "Text", + "dataSourceID": 5, + "dataSourceName": {}, + "dataType": "Text", + "description": "uuid", + "localizedDescription": { + "value": "uuid" + }, + "definitionID": "3286d645-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "UUID", + "definitionName": { + "value": "UUID" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 5, + "fullyQualifiedName": "Predictive Intelligence Content.UUID", + "isHidden": false, + "isIdentityValue": false, + "isNullable": false, + "isPrimaryKey": true, + "isReadOnly": true, + "isSystemDefined": true, + "isUpdateable": false, + "length": 256, + "obfuscationProperties": { + "maskType": "None", + "maskTypeID": 0, + "storageTypeID": 1, + "storageType": "Plain", + "valueDefinitionID": "3286d645-31e2-e611-80cc-1402ec7222b4" + }, + "ordinal": 5, + "parentDefinition": { + "definitionID": "2e86d645-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "PredictiveIntelContent", + "definitionName": { + "value": "Predictive Intelligence Content" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "uuid", + "storageFieldReferenceID": { + "type": "guid", + "value": "d42586c8-bb5b-46a1-ac88-32fc232dbcc7" + }, + "valueDefinitionID": "3286d645-31e2-e611-80cc-1402ec7222b4", + "valueDefinitionKey": "UUID", + "name": "UUID", + "setDefinitionID": "2e86d645-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "PredictiveIntelContent", + "setDefinitionName": { + "value": "Predictive Intelligence Content" + }, + "parentIdentifier": "2e86d645-31e2-e611-80cc-1402ec7222b4" + } + ], + "applicationID": "f4981f88-a13e-4abf-b331-47f41c73258d", + "applicationKey": "com.exacttarget.Predictive Web", + "attributeCount": 0, + "canAddValues": false, + "canChangeValues": false, + "canModify": false, + "canRemove": false, + "categoryID": 386, + "createdBy": -1000, + "createDate": "2017-01-24T06:33:00", + "customObjectOwnerMID": 1111111, + "dataRetentionProperties": { + "isRowBasedRetention": false, + "isResetRetentionPeriodOnImport": false, + "isDeleteAtEndOfRetentionPeriod": false, + "periodUnitOfMeasure": 4, + "setDefinitionID": "2e86d645-31e2-e611-80cc-1402ec7222b4" + }, + "localizedDescription": {}, + "fullyQualifiedName": "Predictive Intelligence Content", + "isCustomObjectBacked": true, + "isEvent": false, + "isHidden": false, + "isReadOnly": true, + "isRoot": false, + "isSendable": false, + "isShared": false, + "isSystemDefined": true, + "isTestaable": false, + "parentID": "00000000-0000-0000-0000-000000000000", + "relationshipCount": 1, + "storageLogicalType": "DataExtension", + "storageName": "PI_CONTENT", + "storageObjectIDs": ["2886d645-31e2-e611-80cc-1402ec7222b4"], + "storageReferenceID": { + "type": "guid", + "value": "db52de3f-31e2-e611-80cc-1402ec7222b4" + }, + "setDefinitionID": "2e86d645-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "PredictiveIntelContent", + "name": "Predictive Intelligence Content" + }, + { + "definitionID": "3152de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "MobileSubscriptions", + "definitionName": { + "value": "MobileConnect Subscriptions" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "valueDefinitions": [ + { + "baseType": "Numeric", + "dataSourceID": 3, + "dataSourceName": {}, + "dataType": "LongNumber", + "description": "", + "localizedDescription": { + "value": "" + }, + "definitionID": "3252de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "CreatedBy", + "definitionName": { + "value": "Created By" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 1, + "fullyQualifiedName": "MobileConnect Subscriptions.Created By", + "isHidden": true, + "isIdentityValue": false, + "isNullable": true, + "isPrimaryKey": false, + "isReadOnly": true, + "isSystemDefined": true, + "isUpdateable": false, + "obfuscationProperties": { + "maskType": "None", + "maskTypeID": 0, + "storageTypeID": 1, + "storageType": "Plain", + "valueDefinitionID": "3252de3f-31e2-e611-80cc-1402ec7222b4" + }, + "ordinal": 1, + "parentDefinition": { + "definitionID": "3152de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "MobileSubscriptions", + "definitionName": { + "value": "MobileConnect Subscriptions" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "_CreatedBy", + "storageFieldReferenceID": { + "type": "guid", + "value": "a64a3ed9-b8fd-46cc-a10b-1d5fdf074ce6" + }, + "valueDefinitionID": "3252de3f-31e2-e611-80cc-1402ec7222b4", + "valueDefinitionKey": "CreatedBy", + "name": "Created By", + "setDefinitionID": "3152de3f-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "MobileSubscriptions", + "setDefinitionName": { + "value": "MobileConnect Subscriptions" + }, + "parentIdentifier": "3152de3f-31e2-e611-80cc-1402ec7222b4" + }, + { + "baseType": "Date", + "dataSourceID": 3, + "dataSourceName": {}, + "dataType": "Date", + "defaultValue": "GETDATE()", + "description": "", + "localizedDescription": { + "value": "" + }, + "definitionID": "3352de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "CreatedDate", + "definitionName": { + "value": "Created Date" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 2, + "fullyQualifiedName": "MobileConnect Subscriptions.Created Date", + "isHidden": false, + "isIdentityValue": false, + "isNullable": false, + "isPrimaryKey": false, + "isReadOnly": true, + "isSystemDefined": true, + "isUpdateable": false, + "obfuscationProperties": { + "maskType": "None", + "maskTypeID": 0, + "storageTypeID": 1, + "storageType": "Plain", + "valueDefinitionID": "3352de3f-31e2-e611-80cc-1402ec7222b4" + }, + "ordinal": 2, + "parentDefinition": { + "definitionID": "3152de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "MobileSubscriptions", + "definitionName": { + "value": "MobileConnect Subscriptions" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "_CreatedDate", + "storageFieldReferenceID": { + "type": "guid", + "value": "dfc3f6fb-a250-4ef8-93ed-bb079ced468d" + }, + "valueDefinitionID": "3352de3f-31e2-e611-80cc-1402ec7222b4", + "valueDefinitionKey": "CreatedDate", + "name": "Created Date", + "setDefinitionID": "3152de3f-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "MobileSubscriptions", + "setDefinitionName": { + "value": "MobileConnect Subscriptions" + }, + "parentIdentifier": "3152de3f-31e2-e611-80cc-1402ec7222b4" + }, + { + "baseType": "Text", + "dataSourceID": 3, + "dataSourceName": {}, + "dataType": "Text", + "description": "", + "localizedDescription": { + "value": "" + }, + "definitionID": "3f52de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "SubscriptionDefinitionID", + "definitionName": { + "value": "Keyword" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 3, + "fullyQualifiedName": "MobileConnect Subscriptions.Keyword", + "isHidden": false, + "isIdentityValue": false, + "isNullable": false, + "isPrimaryKey": true, + "isReadOnly": false, + "isSystemDefined": true, + "isUpdateable": false, + "length": 200, + "obfuscationProperties": { + "maskType": "None", + "maskTypeID": 0, + "storageTypeID": 1, + "storageType": "Plain", + "valueDefinitionID": "3f52de3f-31e2-e611-80cc-1402ec7222b4" + }, + "ordinal": 3, + "parentDefinition": { + "definitionID": "3152de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "MobileSubscriptions", + "definitionName": { + "value": "MobileConnect Subscriptions" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "restrictionLookupListID": 7, + "storageName": "_SubscriptionDefinitionID", + "storageFieldReferenceID": { + "type": "guid", + "value": "c13ab46d-6e65-475a-990d-291bd43e5063" + }, + "valueDefinitionID": "3f52de3f-31e2-e611-80cc-1402ec7222b4", + "valueDefinitionKey": "SubscriptionDefinitionID", + "name": "Keyword", + "setDefinitionID": "3152de3f-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "MobileSubscriptions", + "setDefinitionName": { + "value": "MobileConnect Subscriptions" + }, + "parentIdentifier": "3152de3f-31e2-e611-80cc-1402ec7222b4" + }, + { + "baseType": "Text", + "dataSourceID": 3, + "dataSourceName": {}, + "dataType": "Phone", + "description": "", + "localizedDescription": { + "value": "" + }, + "definitionID": "3452de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "MobileNumber", + "definitionName": { + "value": "Mobile Number" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 4, + "fullyQualifiedName": "MobileConnect Subscriptions.Mobile Number", + "isHidden": false, + "isIdentityValue": false, + "isNullable": false, + "isPrimaryKey": true, + "isReadOnly": true, + "isSystemDefined": true, + "isUpdateable": false, + "length": 15, + "obfuscationProperties": { + "maskType": "None", + "maskTypeID": 0, + "storageTypeID": 1, + "storageType": "Plain", + "valueDefinitionID": "3452de3f-31e2-e611-80cc-1402ec7222b4" + }, + "ordinal": 4, + "parentDefinition": { + "definitionID": "3152de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "MobileSubscriptions", + "definitionName": { + "value": "MobileConnect Subscriptions" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "_MobileNumber", + "storageFieldReferenceID": { + "type": "guid", + "value": "ead8a6d2-bc6c-4768-a6e3-c3cc749bfc1d" + }, + "valueDefinitionID": "3452de3f-31e2-e611-80cc-1402ec7222b4", + "valueDefinitionKey": "MobileNumber", + "name": "Mobile Number", + "setDefinitionID": "3152de3f-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "MobileSubscriptions", + "setDefinitionName": { + "value": "MobileConnect Subscriptions" + }, + "parentIdentifier": "3152de3f-31e2-e611-80cc-1402ec7222b4" + }, + { + "baseType": "Numeric", + "dataSourceID": 3, + "dataSourceName": {}, + "dataType": "LongNumber", + "description": "", + "localizedDescription": { + "value": "" + }, + "definitionID": "53dd5f89-bca1-ed11-b852-48df37d1df5b", + "definitionKey": "MobileSubscriptionID", + "definitionName": { + "value": "Mobile Subscription ID" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 5, + "fullyQualifiedName": "MobileConnect Subscriptions.Mobile Subscription ID", + "isHidden": true, + "isIdentityValue": true, + "isNullable": false, + "isPrimaryKey": false, + "isReadOnly": true, + "isSystemDefined": true, + "isUpdateable": false, + "ordinal": 5, + "parentDefinition": { + "definitionID": "3152de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "MobileSubscriptions", + "definitionName": { + "value": "MobileConnect Subscriptions" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "_MobileSubscriptionID", + "valueDefinitionID": "53dd5f89-bca1-ed11-b852-48df37d1df5b", + "valueDefinitionKey": "MobileSubscriptionID", + "name": "Mobile Subscription ID", + "setDefinitionID": "3152de3f-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "MobileSubscriptions", + "setDefinitionName": { + "value": "MobileConnect Subscriptions" + }, + "parentIdentifier": "3152de3f-31e2-e611-80cc-1402ec7222b4" + }, + { + "baseType": "Numeric", + "dataSourceID": 3, + "dataSourceName": {}, + "dataType": "LongNumber", + "description": "", + "localizedDescription": { + "value": "" + }, + "definitionID": "3552de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "ModifiedBy", + "definitionName": { + "value": "Modified By" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 6, + "fullyQualifiedName": "MobileConnect Subscriptions.Modified By", + "isHidden": true, + "isIdentityValue": false, + "isNullable": true, + "isPrimaryKey": false, + "isReadOnly": true, + "isSystemDefined": true, + "isUpdateable": false, + "obfuscationProperties": { + "maskType": "None", + "maskTypeID": 0, + "storageTypeID": 1, + "storageType": "Plain", + "valueDefinitionID": "3552de3f-31e2-e611-80cc-1402ec7222b4" + }, + "ordinal": 6, + "parentDefinition": { + "definitionID": "3152de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "MobileSubscriptions", + "definitionName": { + "value": "MobileConnect Subscriptions" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "_ModifiedBy", + "storageFieldReferenceID": { + "type": "guid", + "value": "30d7ec39-85d1-46dc-9888-771f11ffe10d" + }, + "valueDefinitionID": "3552de3f-31e2-e611-80cc-1402ec7222b4", + "valueDefinitionKey": "ModifiedBy", + "name": "Modified By", + "setDefinitionID": "3152de3f-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "MobileSubscriptions", + "setDefinitionName": { + "value": "MobileConnect Subscriptions" + }, + "parentIdentifier": "3152de3f-31e2-e611-80cc-1402ec7222b4" + }, + { + "baseType": "Date", + "dataSourceID": 3, + "dataSourceName": {}, + "dataType": "Date", + "defaultValue": "GETDATE()", + "description": "", + "localizedDescription": { + "value": "" + }, + "definitionID": "3652de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "ModifiedDate", + "definitionName": { + "value": "Modified Date" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 7, + "fullyQualifiedName": "MobileConnect Subscriptions.Modified Date", + "isHidden": false, + "isIdentityValue": false, + "isNullable": false, + "isPrimaryKey": false, + "isReadOnly": true, + "isSystemDefined": true, + "isUpdateable": false, + "obfuscationProperties": { + "maskType": "None", + "maskTypeID": 0, + "storageTypeID": 1, + "storageType": "Plain", + "valueDefinitionID": "3652de3f-31e2-e611-80cc-1402ec7222b4" + }, + "ordinal": 7, + "parentDefinition": { + "definitionID": "3152de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "MobileSubscriptions", + "definitionName": { + "value": "MobileConnect Subscriptions" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "_ModifiedDate", + "storageFieldReferenceID": { + "type": "guid", + "value": "b68155cc-e483-4949-82f9-fb47cbd59764" + }, + "valueDefinitionID": "3652de3f-31e2-e611-80cc-1402ec7222b4", + "valueDefinitionKey": "ModifiedDate", + "name": "Modified Date", + "setDefinitionID": "3152de3f-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "MobileSubscriptions", + "setDefinitionName": { + "value": "MobileConnect Subscriptions" + }, + "parentIdentifier": "3152de3f-31e2-e611-80cc-1402ec7222b4" + }, + { + "baseType": "Date", + "dataSourceID": 3, + "dataSourceName": {}, + "dataType": "Date", + "description": "", + "localizedDescription": { + "value": "" + }, + "definitionID": "3752de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "OptInDate", + "definitionName": { + "value": "Opt In Date" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 8, + "fullyQualifiedName": "MobileConnect Subscriptions.Opt In Date", + "isHidden": false, + "isIdentityValue": false, + "isNullable": true, + "isPrimaryKey": false, + "isReadOnly": true, + "isSystemDefined": true, + "isUpdateable": false, + "obfuscationProperties": { + "maskType": "None", + "maskTypeID": 0, + "storageTypeID": 1, + "storageType": "Plain", + "valueDefinitionID": "3752de3f-31e2-e611-80cc-1402ec7222b4" + }, + "ordinal": 8, + "parentDefinition": { + "definitionID": "3152de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "MobileSubscriptions", + "definitionName": { + "value": "MobileConnect Subscriptions" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "_OptInDate", + "storageFieldReferenceID": { + "type": "guid", + "value": "8da557ee-7ba7-44f4-99ba-0681cbeb1ba1" + }, + "valueDefinitionID": "3752de3f-31e2-e611-80cc-1402ec7222b4", + "valueDefinitionKey": "OptInDate", + "name": "Opt In Date", + "setDefinitionID": "3152de3f-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "MobileSubscriptions", + "setDefinitionName": { + "value": "MobileConnect Subscriptions" + }, + "parentIdentifier": "3152de3f-31e2-e611-80cc-1402ec7222b4" + }, + { + "baseType": "Numeric", + "dataSourceID": 3, + "dataSourceName": {}, + "dataType": "Byte", + "description": "", + "localizedDescription": { + "value": "" + }, + "definitionID": "3852de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "OptInMethodID", + "definitionName": { + "value": "Opt In Method" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 9, + "fullyQualifiedName": "MobileConnect Subscriptions.Opt In Method", + "isHidden": false, + "isIdentityValue": false, + "isNullable": true, + "isPrimaryKey": false, + "isReadOnly": true, + "isSystemDefined": true, + "isUpdateable": false, + "obfuscationProperties": { + "maskType": "None", + "maskTypeID": 0, + "storageTypeID": 1, + "storageType": "Plain", + "valueDefinitionID": "3852de3f-31e2-e611-80cc-1402ec7222b4" + }, + "ordinal": 9, + "parentDefinition": { + "definitionID": "3152de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "MobileSubscriptions", + "definitionName": { + "value": "MobileConnect Subscriptions" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "restrictionLookupListID": 2, + "storageName": "_OptInMethodID", + "storageFieldReferenceID": { + "type": "guid", + "value": "da2713ab-a802-4cd6-9e05-0a7444d62388" + }, + "valueDefinitionID": "3852de3f-31e2-e611-80cc-1402ec7222b4", + "valueDefinitionKey": "OptInMethodID", + "name": "Opt In Method", + "setDefinitionID": "3152de3f-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "MobileSubscriptions", + "setDefinitionName": { + "value": "MobileConnect Subscriptions" + }, + "parentIdentifier": "3152de3f-31e2-e611-80cc-1402ec7222b4" + }, + { + "baseType": "Numeric", + "dataSourceID": 3, + "dataSourceName": {}, + "dataType": "Byte", + "description": "", + "localizedDescription": { + "value": "" + }, + "definitionID": "3952de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "OptInStatusID", + "definitionName": { + "value": "Opt In Status" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 10, + "fullyQualifiedName": "MobileConnect Subscriptions.Opt In Status", + "isHidden": false, + "isIdentityValue": false, + "isNullable": false, + "isPrimaryKey": false, + "isReadOnly": false, + "isSystemDefined": true, + "isUpdateable": false, + "obfuscationProperties": { + "maskType": "None", + "maskTypeID": 0, + "storageTypeID": 1, + "storageType": "Plain", + "valueDefinitionID": "3952de3f-31e2-e611-80cc-1402ec7222b4" + }, + "ordinal": 10, + "parentDefinition": { + "definitionID": "3152de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "MobileSubscriptions", + "definitionName": { + "value": "MobileConnect Subscriptions" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "restrictionLookupListID": 1, + "storageName": "_OptInStatusID", + "storageFieldReferenceID": { + "type": "guid", + "value": "c733b80d-2ed5-4fb6-94a3-9c996cbae558" + }, + "valueDefinitionID": "3952de3f-31e2-e611-80cc-1402ec7222b4", + "valueDefinitionKey": "OptInStatusID", + "name": "Opt In Status", + "setDefinitionID": "3152de3f-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "MobileSubscriptions", + "setDefinitionName": { + "value": "MobileConnect Subscriptions" + }, + "parentIdentifier": "3152de3f-31e2-e611-80cc-1402ec7222b4" + }, + { + "baseType": "Date", + "dataSourceID": 3, + "dataSourceName": {}, + "dataType": "Date", + "description": "", + "localizedDescription": { + "value": "" + }, + "definitionID": "3a52de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "OptOutDate", + "definitionName": { + "value": "Opt Out Date" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 11, + "fullyQualifiedName": "MobileConnect Subscriptions.Opt Out Date", + "isHidden": false, + "isIdentityValue": false, + "isNullable": true, + "isPrimaryKey": false, + "isReadOnly": true, + "isSystemDefined": true, + "isUpdateable": false, + "obfuscationProperties": { + "maskType": "None", + "maskTypeID": 0, + "storageTypeID": 1, + "storageType": "Plain", + "valueDefinitionID": "3a52de3f-31e2-e611-80cc-1402ec7222b4" + }, + "ordinal": 11, + "parentDefinition": { + "definitionID": "3152de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "MobileSubscriptions", + "definitionName": { + "value": "MobileConnect Subscriptions" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "_OptOutDate", + "storageFieldReferenceID": { + "type": "guid", + "value": "27c3ccec-47ad-4578-9051-a41f85178049" + }, + "valueDefinitionID": "3a52de3f-31e2-e611-80cc-1402ec7222b4", + "valueDefinitionKey": "OptOutDate", + "name": "Opt Out Date", + "setDefinitionID": "3152de3f-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "MobileSubscriptions", + "setDefinitionName": { + "value": "MobileConnect Subscriptions" + }, + "parentIdentifier": "3152de3f-31e2-e611-80cc-1402ec7222b4" + }, + { + "baseType": "Numeric", + "dataSourceID": 3, + "dataSourceName": {}, + "dataType": "Byte", + "description": "", + "localizedDescription": { + "value": "" + }, + "definitionID": "3b52de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "OptOutMethodID", + "definitionName": { + "value": "Opt Out Method" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 12, + "fullyQualifiedName": "MobileConnect Subscriptions.Opt Out Method", + "isHidden": false, + "isIdentityValue": false, + "isNullable": true, + "isPrimaryKey": false, + "isReadOnly": true, + "isSystemDefined": true, + "isUpdateable": false, + "obfuscationProperties": { + "maskType": "None", + "maskTypeID": 0, + "storageTypeID": 1, + "storageType": "Plain", + "valueDefinitionID": "3b52de3f-31e2-e611-80cc-1402ec7222b4" + }, + "ordinal": 12, + "parentDefinition": { + "definitionID": "3152de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "MobileSubscriptions", + "definitionName": { + "value": "MobileConnect Subscriptions" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "restrictionLookupListID": 4, + "storageName": "_OptOutMethodID", + "storageFieldReferenceID": { + "type": "guid", + "value": "089b96fc-bfc6-402e-a481-1e18d3e18a8d" + }, + "valueDefinitionID": "3b52de3f-31e2-e611-80cc-1402ec7222b4", + "valueDefinitionKey": "OptOutMethodID", + "name": "Opt Out Method", + "setDefinitionID": "3152de3f-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "MobileSubscriptions", + "setDefinitionName": { + "value": "MobileConnect Subscriptions" + }, + "parentIdentifier": "3152de3f-31e2-e611-80cc-1402ec7222b4" + }, + { + "baseType": "Numeric", + "dataSourceID": 3, + "dataSourceName": {}, + "dataType": "Byte", + "description": "", + "localizedDescription": { + "value": "" + }, + "definitionID": "3c52de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "OptOutStatusID", + "definitionName": { + "value": "Opt Out Status" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 13, + "fullyQualifiedName": "MobileConnect Subscriptions.Opt Out Status", + "isHidden": false, + "isIdentityValue": false, + "isNullable": true, + "isPrimaryKey": false, + "isReadOnly": false, + "isSystemDefined": true, + "isUpdateable": false, + "obfuscationProperties": { + "maskType": "None", + "maskTypeID": 0, + "storageTypeID": 1, + "storageType": "Plain", + "valueDefinitionID": "3c52de3f-31e2-e611-80cc-1402ec7222b4" + }, + "ordinal": 13, + "parentDefinition": { + "definitionID": "3152de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "MobileSubscriptions", + "definitionName": { + "value": "MobileConnect Subscriptions" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "restrictionLookupListID": 3, + "storageName": "_OptOutStatusID", + "storageFieldReferenceID": { + "type": "guid", + "value": "67194503-acd8-4c1c-b042-9dfb3f3ebd44" + }, + "valueDefinitionID": "3c52de3f-31e2-e611-80cc-1402ec7222b4", + "valueDefinitionKey": "OptOutStatusID", + "name": "Opt Out Status", + "setDefinitionID": "3152de3f-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "MobileSubscriptions", + "setDefinitionName": { + "value": "MobileConnect Subscriptions" + }, + "parentIdentifier": "3152de3f-31e2-e611-80cc-1402ec7222b4" + }, + { + "baseType": "Numeric", + "dataSourceID": 3, + "dataSourceName": {}, + "dataType": "Byte", + "description": "", + "localizedDescription": { + "value": "" + }, + "definitionID": "3d52de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "Source", + "definitionName": { + "value": "Source" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 14, + "fullyQualifiedName": "MobileConnect Subscriptions.Source", + "isHidden": false, + "isIdentityValue": false, + "isNullable": true, + "isPrimaryKey": false, + "isReadOnly": true, + "isSystemDefined": true, + "isUpdateable": false, + "obfuscationProperties": { + "maskType": "None", + "maskTypeID": 0, + "storageTypeID": 1, + "storageType": "Plain", + "valueDefinitionID": "3d52de3f-31e2-e611-80cc-1402ec7222b4" + }, + "ordinal": 14, + "parentDefinition": { + "definitionID": "3152de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "MobileSubscriptions", + "definitionName": { + "value": "MobileConnect Subscriptions" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "restrictionLookupListID": 5, + "storageName": "_Source", + "storageFieldReferenceID": { + "type": "guid", + "value": "2e903257-43e8-4a7b-8ed4-757ca772ddbb" + }, + "valueDefinitionID": "3d52de3f-31e2-e611-80cc-1402ec7222b4", + "valueDefinitionKey": "Source", + "name": "Source", + "setDefinitionID": "3152de3f-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "MobileSubscriptions", + "setDefinitionName": { + "value": "MobileConnect Subscriptions" + }, + "parentIdentifier": "3152de3f-31e2-e611-80cc-1402ec7222b4" + }, + { + "baseType": "Text", + "dataSourceID": 3, + "dataSourceName": {}, + "dataType": "Text", + "description": "", + "localizedDescription": { + "value": "" + }, + "definitionID": "3e52de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "SourceObjectID", + "definitionName": { + "value": "Source Object ID" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 15, + "fullyQualifiedName": "MobileConnect Subscriptions.Source Object ID", + "isHidden": false, + "isIdentityValue": false, + "isNullable": true, + "isPrimaryKey": false, + "isReadOnly": true, + "isSystemDefined": true, + "isUpdateable": false, + "length": 200, + "obfuscationProperties": { + "maskType": "None", + "maskTypeID": 0, + "storageTypeID": 1, + "storageType": "Plain", + "valueDefinitionID": "3e52de3f-31e2-e611-80cc-1402ec7222b4" + }, + "ordinal": 15, + "parentDefinition": { + "definitionID": "3152de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "MobileSubscriptions", + "definitionName": { + "value": "MobileConnect Subscriptions" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "_SourceObjectId", + "storageFieldReferenceID": { + "type": "guid", + "value": "1d4f26f5-ec91-46de-9fc1-d819832f07e7" + }, + "valueDefinitionID": "3e52de3f-31e2-e611-80cc-1402ec7222b4", + "valueDefinitionKey": "SourceObjectID", + "name": "Source Object ID", + "setDefinitionID": "3152de3f-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "MobileSubscriptions", + "setDefinitionName": { + "value": "MobileConnect Subscriptions" + }, + "parentIdentifier": "3152de3f-31e2-e611-80cc-1402ec7222b4" + } + ], + "applicationID": "e25893f9-08f3-480f-8def-7f8ab0583611", + "applicationKey": "com.exacttarget.mobileconnect", + "attributeCount": 0, + "canAddValues": false, + "canChangeValues": false, + "canModify": false, + "canRemove": false, + "categoryID": 2, + "createdBy": -1000, + "createDate": "2017-01-24T06:33:00", + "customObjectOwnerMID": 1111111, + "dataRetentionProperties": { + "isRowBasedRetention": false, + "isResetRetentionPeriodOnImport": false, + "isDeleteAtEndOfRetentionPeriod": false, + "setDefinitionID": "3152de3f-31e2-e611-80cc-1402ec7222b4" + }, + "localizedDescription": {}, + "fullyQualifiedName": "MobileConnect Subscriptions", + "isCustomObjectBacked": true, + "isEvent": false, + "isHidden": false, + "isReadOnly": false, + "isRoot": false, + "isSendable": false, + "isShared": false, + "isSystemDefined": true, + "isTestaable": false, + "parentID": "00000000-0000-0000-0000-000000000000", + "relationshipCount": 0, + "storageLogicalType": "DataExtension", + "storageName": "_MobileSubscription", + "storageObjectIDs": ["2252de3f-31e2-e611-80cc-1402ec7222b4"], + "storageReferenceID": { + "type": "guid", + "value": "7793dc39-31e2-e611-80cc-1402ec7222b4" + }, + "setDefinitionID": "3152de3f-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "MobileSubscriptions", + "name": "MobileConnect Subscriptions" + }, + { + "definitionID": "3e86d645-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "PredictiveIntelContentAttribs", + "definitionName": { + "value": "Predictive Intelligence Content Attributes" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "valueDefinitions": [ + { + "baseType": "Numeric", + "dataSourceID": 1, + "dataSourceName": {}, + "dataType": "LongNumber", + "description": "", + "localizedDescription": { + "value": "" + }, + "definitionID": "4486d645-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "CustomObjectKey", + "definitionName": { + "value": "Custom Object Key" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 1, + "fullyQualifiedName": "Predictive Intelligence Content Attributes.Custom Object Key", + "isHidden": true, + "isIdentityValue": true, + "isNullable": false, + "isPrimaryKey": false, + "isReadOnly": true, + "isSystemDefined": true, + "isUpdateable": false, + "ordinal": 1, + "parentDefinition": { + "definitionID": "3e86d645-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "PredictiveIntelContentAttribs", + "definitionName": { + "value": "Predictive Intelligence Content Attributes" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "_CustomObjectKey", + "valueDefinitionID": "4486d645-31e2-e611-80cc-1402ec7222b4", + "valueDefinitionKey": "CustomObjectKey", + "name": "Custom Object Key", + "setDefinitionID": "3e86d645-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "PredictiveIntelContentAttribs", + "setDefinitionName": { + "value": "Predictive Intelligence Content Attributes" + }, + "parentIdentifier": "3e86d645-31e2-e611-80cc-1402ec7222b4" + }, + { + "baseType": "Text", + "dataSourceID": 5, + "dataSourceName": {}, + "dataType": "Text", + "description": "content_id", + "localizedDescription": { + "value": "content_id" + }, + "definitionID": "4286d645-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "Content_ID", + "definitionName": { + "value": "Content ID" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 2, + "fullyQualifiedName": "Predictive Intelligence Content Attributes.Content ID", + "isHidden": false, + "isIdentityValue": false, + "isNullable": false, + "isPrimaryKey": true, + "isReadOnly": true, + "isSystemDefined": true, + "isUpdateable": false, + "length": 256, + "obfuscationProperties": { + "maskType": "None", + "maskTypeID": 0, + "storageTypeID": 1, + "storageType": "Plain", + "valueDefinitionID": "4286d645-31e2-e611-80cc-1402ec7222b4" + }, + "ordinal": 2, + "parentDefinition": { + "definitionID": "3e86d645-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "PredictiveIntelContentAttribs", + "definitionName": { + "value": "Predictive Intelligence Content Attributes" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "content_id", + "storageFieldReferenceID": { + "type": "guid", + "value": "d1abd045-4670-41f2-a368-9e0a6f732146" + }, + "valueDefinitionID": "4286d645-31e2-e611-80cc-1402ec7222b4", + "valueDefinitionKey": "Content_ID", + "name": "Content ID", + "setDefinitionID": "3e86d645-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "PredictiveIntelContentAttribs", + "setDefinitionName": { + "value": "Predictive Intelligence Content Attributes" + }, + "parentIdentifier": "3e86d645-31e2-e611-80cc-1402ec7222b4" + }, + { + "baseType": "Text", + "dataSourceID": 5, + "dataSourceName": {}, + "dataType": "Text", + "description": "AttribName", + "localizedDescription": { + "value": "AttribName" + }, + "definitionID": "3f86d645-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "Attribute_Name", + "definitionName": { + "value": "Attribute Name" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 3, + "fullyQualifiedName": "Predictive Intelligence Content Attributes.Attribute Name", + "isHidden": false, + "isIdentityValue": false, + "isNullable": false, + "isPrimaryKey": true, + "isReadOnly": true, + "isSystemDefined": true, + "isUpdateable": false, + "length": 1000, + "obfuscationProperties": { + "maskType": "None", + "maskTypeID": 0, + "storageTypeID": 1, + "storageType": "Plain", + "valueDefinitionID": "3f86d645-31e2-e611-80cc-1402ec7222b4" + }, + "ordinal": 3, + "parentDefinition": { + "definitionID": "3e86d645-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "PredictiveIntelContentAttribs", + "definitionName": { + "value": "Predictive Intelligence Content Attributes" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "AttribName", + "storageFieldReferenceID": { + "type": "guid", + "value": "a55251d7-c1c5-49b3-bdc1-8ebdbf7cb517" + }, + "valueDefinitionID": "3f86d645-31e2-e611-80cc-1402ec7222b4", + "valueDefinitionKey": "Attribute_Name", + "name": "Attribute Name", + "setDefinitionID": "3e86d645-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "PredictiveIntelContentAttribs", + "setDefinitionName": { + "value": "Predictive Intelligence Content Attributes" + }, + "parentIdentifier": "3e86d645-31e2-e611-80cc-1402ec7222b4" + }, + { + "baseType": "Text", + "dataSourceID": 5, + "dataSourceName": {}, + "dataType": "Text", + "description": "AttribValue", + "localizedDescription": { + "value": "AttribValue" + }, + "definitionID": "4186d645-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "Attribute_Value", + "definitionName": { + "value": "Attribute Value" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 4, + "fullyQualifiedName": "Predictive Intelligence Content Attributes.Attribute Value", + "isHidden": false, + "isIdentityValue": false, + "isNullable": false, + "isPrimaryKey": false, + "isReadOnly": true, + "isSystemDefined": true, + "isUpdateable": false, + "length": 1000, + "obfuscationProperties": { + "maskType": "None", + "maskTypeID": 0, + "storageTypeID": 1, + "storageType": "Plain", + "valueDefinitionID": "4186d645-31e2-e611-80cc-1402ec7222b4" + }, + "ordinal": 4, + "parentDefinition": { + "definitionID": "3e86d645-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "PredictiveIntelContentAttribs", + "definitionName": { + "value": "Predictive Intelligence Content Attributes" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "AttribValue", + "storageFieldReferenceID": { + "type": "guid", + "value": "1742dd68-39af-4da9-ace4-0ad50ae08f05" + }, + "valueDefinitionID": "4186d645-31e2-e611-80cc-1402ec7222b4", + "valueDefinitionKey": "Attribute_Value", + "name": "Attribute Value", + "setDefinitionID": "3e86d645-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "PredictiveIntelContentAttribs", + "setDefinitionName": { + "value": "Predictive Intelligence Content Attributes" + }, + "parentIdentifier": "3e86d645-31e2-e611-80cc-1402ec7222b4" + }, + { + "baseType": "Date", + "dataSourceID": 5, + "dataSourceName": {}, + "dataType": "Date", + "description": "updated_at", + "localizedDescription": { + "value": "updated_at" + }, + "definitionID": "4386d645-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "Updated_At", + "definitionName": { + "value": "Updated At" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 5, + "fullyQualifiedName": "Predictive Intelligence Content Attributes.Updated At", + "isHidden": false, + "isIdentityValue": false, + "isNullable": false, + "isPrimaryKey": false, + "isReadOnly": true, + "isSystemDefined": true, + "isUpdateable": false, + "obfuscationProperties": { + "maskType": "None", + "maskTypeID": 0, + "storageTypeID": 1, + "storageType": "Plain", + "valueDefinitionID": "4386d645-31e2-e611-80cc-1402ec7222b4" + }, + "ordinal": 5, + "parentDefinition": { + "definitionID": "3e86d645-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "PredictiveIntelContentAttribs", + "definitionName": { + "value": "Predictive Intelligence Content Attributes" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "updated_at", + "storageFieldReferenceID": { + "type": "guid", + "value": "4ad58eb4-5e13-4064-ae43-71ab9786be00" + }, + "valueDefinitionID": "4386d645-31e2-e611-80cc-1402ec7222b4", + "valueDefinitionKey": "Updated_At", + "name": "Updated At", + "setDefinitionID": "3e86d645-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "PredictiveIntelContentAttribs", + "setDefinitionName": { + "value": "Predictive Intelligence Content Attributes" + }, + "parentIdentifier": "3e86d645-31e2-e611-80cc-1402ec7222b4" + }, + { + "baseType": "Numeric", + "dataSourceID": 5, + "dataSourceName": {}, + "dataType": "Number", + "description": "attributeValueIndex", + "localizedDescription": { + "value": "attributeValueIndex" + }, + "definitionID": "4086d645-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "Attribute_Value_Index", + "definitionName": { + "value": "Attribute Value Index" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 6, + "fullyQualifiedName": "Predictive Intelligence Content Attributes.Attribute Value Index", + "isHidden": false, + "isIdentityValue": false, + "isNullable": false, + "isPrimaryKey": true, + "isReadOnly": true, + "isSystemDefined": true, + "isUpdateable": false, + "obfuscationProperties": { + "maskType": "None", + "maskTypeID": 0, + "storageTypeID": 1, + "storageType": "Plain", + "valueDefinitionID": "4086d645-31e2-e611-80cc-1402ec7222b4" + }, + "ordinal": 6, + "parentDefinition": { + "definitionID": "3e86d645-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "PredictiveIntelContentAttribs", + "definitionName": { + "value": "Predictive Intelligence Content Attributes" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "attributeValueIndex", + "storageFieldReferenceID": { + "type": "guid", + "value": "3635848d-5e04-4fed-95ed-d487202a80b8" + }, + "valueDefinitionID": "4086d645-31e2-e611-80cc-1402ec7222b4", + "valueDefinitionKey": "Attribute_Value_Index", + "name": "Attribute Value Index", + "setDefinitionID": "3e86d645-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "PredictiveIntelContentAttribs", + "setDefinitionName": { + "value": "Predictive Intelligence Content Attributes" + }, + "parentIdentifier": "3e86d645-31e2-e611-80cc-1402ec7222b4" + } + ], + "applicationID": "f4981f88-a13e-4abf-b331-47f41c73258d", + "applicationKey": "com.exacttarget.Predictive Web", + "attributeCount": 0, + "canAddValues": false, + "canChangeValues": false, + "canModify": false, + "canRemove": false, + "categoryID": 386, + "createdBy": -1000, + "createDate": "2017-01-24T06:33:00", + "customObjectOwnerMID": 1111111, + "dataRetentionProperties": { + "isRowBasedRetention": false, + "isResetRetentionPeriodOnImport": false, + "isDeleteAtEndOfRetentionPeriod": false, + "periodUnitOfMeasure": 4, + "setDefinitionID": "3e86d645-31e2-e611-80cc-1402ec7222b4" + }, + "localizedDescription": {}, + "fullyQualifiedName": "Predictive Intelligence Content Attributes", + "isCustomObjectBacked": true, + "isEvent": false, + "isHidden": false, + "isReadOnly": true, + "isRoot": false, + "isSendable": false, + "isShared": false, + "isSystemDefined": true, + "isTestaable": false, + "parentID": "00000000-0000-0000-0000-000000000000", + "relationshipCount": 0, + "storageLogicalType": "DataExtension", + "storageName": "PI_CONTENTATTRIBS", + "storageObjectIDs": ["3786d645-31e2-e611-80cc-1402ec7222b4"], + "storageReferenceID": { + "type": "guid", + "value": "dc52de3f-31e2-e611-80cc-1402ec7222b4" + }, + "setDefinitionID": "3e86d645-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "PredictiveIntelContentAttribs", + "name": "Predictive Intelligence Content Attributes" + }, + { + "definitionID": "5286d645-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "PredictiveIntelAbandonedCartEvents", + "definitionName": { + "value": "Predictive Intelligence AbandonedCartEvents" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "relationships": [ + { + "canModify": false, + "canRemove": false, + "isHidden": false, + "isSystemDefined": false, + "isGroupToSetRelationship": false, + "leftItem": { + "cardinality": "One", + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "identifier": "5286d645-31e2-e611-80cc-1402ec7222b4", + "relationshipType": "AttributeSet" + }, + "relationshipAttributes": [ + { + "leftAttributeID": "5386d645-31e2-e611-80cc-1402ec7222b4", + "leftConnectingID": { + "identifierType": "FullyQualifiedName" + }, + "rightAttributeID": "6686d645-31e2-e611-80cc-1402ec7222b4", + "rightConnectingID": { + "identifierType": "FullyQualifiedName" + } + } + ], + "relationshipID": "6c86d645-31e2-e611-80cc-1402ec7222b4", + "rightItem": { + "cardinality": "Many", + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "identifier": "6586d645-31e2-e611-80cc-1402ec7222b4", + "relationshipType": "AttributeSet" + } + } + ], + "valueDefinitions": [ + { + "baseType": "Numeric", + "dataSourceID": 1, + "dataSourceName": {}, + "dataType": "LongNumber", + "description": "", + "localizedDescription": { + "value": "" + }, + "definitionID": "5b86d645-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "Custom_Object_Key", + "definitionName": { + "value": "Custom Object Key" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 1, + "fullyQualifiedName": "Predictive Intelligence AbandonedCartEvents.Custom Object Key", + "isHidden": true, + "isIdentityValue": true, + "isNullable": false, + "isPrimaryKey": false, + "isReadOnly": true, + "isSystemDefined": true, + "isUpdateable": false, + "ordinal": 1, + "parentDefinition": { + "definitionID": "5286d645-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "PredictiveIntelAbandonedCartEvents", + "definitionName": { + "value": "Predictive Intelligence AbandonedCartEvents" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "_CustomObjectKey", + "valueDefinitionID": "5b86d645-31e2-e611-80cc-1402ec7222b4", + "valueDefinitionKey": "Custom_Object_Key", + "name": "Custom Object Key", + "setDefinitionID": "5286d645-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "PredictiveIntelAbandonedCartEvents", + "setDefinitionName": { + "value": "Predictive Intelligence AbandonedCartEvents" + }, + "parentIdentifier": "5286d645-31e2-e611-80cc-1402ec7222b4" + }, + { + "baseType": "Text", + "dataSourceID": 5, + "dataSourceName": {}, + "dataType": "Text", + "description": "user_id", + "localizedDescription": { + "value": "user_id" + }, + "definitionID": "5a86d645-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "user_id", + "definitionName": { + "value": "user_id" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 2, + "fullyQualifiedName": "Predictive Intelligence AbandonedCartEvents.user_id", + "isHidden": false, + "isIdentityValue": false, + "isNullable": false, + "isPrimaryKey": false, + "isReadOnly": true, + "isSystemDefined": true, + "isUpdateable": false, + "length": 256, + "obfuscationProperties": { + "maskType": "None", + "maskTypeID": 0, + "storageTypeID": 1, + "storageType": "Plain", + "valueDefinitionID": "5a86d645-31e2-e611-80cc-1402ec7222b4" + }, + "ordinal": 2, + "parentDefinition": { + "definitionID": "5286d645-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "PredictiveIntelAbandonedCartEvents", + "definitionName": { + "value": "Predictive Intelligence AbandonedCartEvents" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "user_id", + "storageFieldReferenceID": { + "type": "guid", + "value": "e6f01b13-78b2-4cf7-956a-7a9a5db31a82" + }, + "valueDefinitionID": "5a86d645-31e2-e611-80cc-1402ec7222b4", + "valueDefinitionKey": "user_id", + "name": "user_id", + "setDefinitionID": "5286d645-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "PredictiveIntelAbandonedCartEvents", + "setDefinitionName": { + "value": "Predictive Intelligence AbandonedCartEvents" + }, + "parentIdentifier": "5286d645-31e2-e611-80cc-1402ec7222b4" + }, + { + "baseType": "Text", + "dataSourceID": 5, + "dataSourceName": {}, + "dataType": "Text", + "description": "cart_id", + "localizedDescription": { + "value": "cart_id" + }, + "definitionID": "5386d645-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "Cart_ID", + "definitionName": { + "value": "Cart ID" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 3, + "fullyQualifiedName": "Predictive Intelligence AbandonedCartEvents.Cart ID", + "isHidden": false, + "isIdentityValue": false, + "isNullable": false, + "isPrimaryKey": true, + "isReadOnly": true, + "isSystemDefined": true, + "isUpdateable": false, + "length": 256, + "obfuscationProperties": { + "maskType": "None", + "maskTypeID": 0, + "storageTypeID": 1, + "storageType": "Plain", + "valueDefinitionID": "5386d645-31e2-e611-80cc-1402ec7222b4" + }, + "ordinal": 3, + "parentDefinition": { + "definitionID": "5286d645-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "PredictiveIntelAbandonedCartEvents", + "definitionName": { + "value": "Predictive Intelligence AbandonedCartEvents" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "cart_id", + "storageFieldReferenceID": { + "type": "guid", + "value": "3f7d9be8-3af9-425b-9537-442a9e389582" + }, + "valueDefinitionID": "5386d645-31e2-e611-80cc-1402ec7222b4", + "valueDefinitionKey": "Cart_ID", + "name": "Cart ID", + "setDefinitionID": "5286d645-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "PredictiveIntelAbandonedCartEvents", + "setDefinitionName": { + "value": "Predictive Intelligence AbandonedCartEvents" + }, + "parentIdentifier": "5286d645-31e2-e611-80cc-1402ec7222b4" + }, + { + "baseType": "Text", + "dataSourceID": 5, + "dataSourceName": {}, + "dataType": "Text", + "description": "contact_key", + "localizedDescription": { + "value": "contact_key" + }, + "definitionID": "5586d645-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "Contact_Key", + "definitionName": { + "value": "Contact Key" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 4, + "fullyQualifiedName": "Predictive Intelligence AbandonedCartEvents.Contact Key", + "isHidden": false, + "isIdentityValue": false, + "isNullable": true, + "isPrimaryKey": false, + "isReadOnly": true, + "isSystemDefined": true, + "isUpdateable": false, + "length": 256, + "obfuscationProperties": { + "maskType": "None", + "maskTypeID": 0, + "storageTypeID": 1, + "storageType": "Plain", + "valueDefinitionID": "5586d645-31e2-e611-80cc-1402ec7222b4" + }, + "ordinal": 4, + "parentDefinition": { + "definitionID": "5286d645-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "PredictiveIntelAbandonedCartEvents", + "definitionName": { + "value": "Predictive Intelligence AbandonedCartEvents" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "contact_key", + "storageFieldReferenceID": { + "type": "guid", + "value": "7a8eb4a3-5270-4e28-9562-96067a13a6fd" + }, + "valueDefinitionID": "5586d645-31e2-e611-80cc-1402ec7222b4", + "valueDefinitionKey": "Contact_Key", + "name": "Contact Key", + "setDefinitionID": "5286d645-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "PredictiveIntelAbandonedCartEvents", + "setDefinitionName": { + "value": "Predictive Intelligence AbandonedCartEvents" + }, + "parentIdentifier": "5286d645-31e2-e611-80cc-1402ec7222b4" + }, + { + "baseType": "Text", + "dataSourceID": 5, + "dataSourceName": {}, + "dataType": "Text", + "description": "currency_type", + "localizedDescription": { + "value": "currency_type" + }, + "definitionID": "5686d645-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "Currency_Type", + "definitionName": { + "value": "Currency Type" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 5, + "fullyQualifiedName": "Predictive Intelligence AbandonedCartEvents.Currency Type", + "isHidden": false, + "isIdentityValue": false, + "isNullable": true, + "isPrimaryKey": false, + "isReadOnly": true, + "isSystemDefined": true, + "isUpdateable": false, + "length": 256, + "obfuscationProperties": { + "maskType": "None", + "maskTypeID": 0, + "storageTypeID": 1, + "storageType": "Plain", + "valueDefinitionID": "5686d645-31e2-e611-80cc-1402ec7222b4" + }, + "ordinal": 5, + "parentDefinition": { + "definitionID": "5286d645-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "PredictiveIntelAbandonedCartEvents", + "definitionName": { + "value": "Predictive Intelligence AbandonedCartEvents" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "currency_type", + "storageFieldReferenceID": { + "type": "guid", + "value": "32d910c3-7e8e-4cf6-af31-596b395246f0" + }, + "valueDefinitionID": "5686d645-31e2-e611-80cc-1402ec7222b4", + "valueDefinitionKey": "Currency_Type", + "name": "Currency Type", + "setDefinitionID": "5286d645-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "PredictiveIntelAbandonedCartEvents", + "setDefinitionName": { + "value": "Predictive Intelligence AbandonedCartEvents" + }, + "parentIdentifier": "5286d645-31e2-e611-80cc-1402ec7222b4" + }, + { + "baseType": "Numeric", + "dataSourceID": 5, + "dataSourceName": {}, + "dataType": "Number", + "description": "no_items_cart", + "localizedDescription": { + "value": "no_items_cart" + }, + "definitionID": "5886d645-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "No_Items_Cart", + "definitionName": { + "value": "No Items Cart" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 6, + "fullyQualifiedName": "Predictive Intelligence AbandonedCartEvents.No Items Cart", + "isHidden": false, + "isIdentityValue": false, + "isNullable": true, + "isPrimaryKey": false, + "isReadOnly": true, + "isSystemDefined": true, + "isUpdateable": false, + "obfuscationProperties": { + "maskType": "None", + "maskTypeID": 0, + "storageTypeID": 1, + "storageType": "Plain", + "valueDefinitionID": "5886d645-31e2-e611-80cc-1402ec7222b4" + }, + "ordinal": 6, + "parentDefinition": { + "definitionID": "5286d645-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "PredictiveIntelAbandonedCartEvents", + "definitionName": { + "value": "Predictive Intelligence AbandonedCartEvents" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "no_items_cart", + "storageFieldReferenceID": { + "type": "guid", + "value": "74f890d4-eb4b-46c1-9cd5-f2f89702825d" + }, + "valueDefinitionID": "5886d645-31e2-e611-80cc-1402ec7222b4", + "valueDefinitionKey": "No_Items_Cart", + "name": "No Items Cart", + "setDefinitionID": "5286d645-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "PredictiveIntelAbandonedCartEvents", + "setDefinitionName": { + "value": "Predictive Intelligence AbandonedCartEvents" + }, + "parentIdentifier": "5286d645-31e2-e611-80cc-1402ec7222b4" + }, + { + "baseType": "Numeric", + "dataSourceID": 5, + "dataSourceName": {}, + "dataType": "Decimal", + "description": "cart_value", + "localizedDescription": { + "value": "cart_value" + }, + "definitionID": "5486d645-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "Cart_Value", + "definitionName": { + "value": "Cart Value" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 7, + "fullyQualifiedName": "Predictive Intelligence AbandonedCartEvents.Cart Value", + "isHidden": false, + "isIdentityValue": false, + "isNullable": true, + "isPrimaryKey": false, + "isReadOnly": true, + "isSystemDefined": true, + "isUpdateable": false, + "length": 18, + "obfuscationProperties": { + "maskType": "None", + "maskTypeID": 0, + "storageTypeID": 1, + "storageType": "Plain", + "valueDefinitionID": "5486d645-31e2-e611-80cc-1402ec7222b4" + }, + "ordinal": 7, + "parentDefinition": { + "definitionID": "5286d645-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "PredictiveIntelAbandonedCartEvents", + "definitionName": { + "value": "Predictive Intelligence AbandonedCartEvents" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "scale": 2, + "storageName": "cart_value", + "storageFieldReferenceID": { + "type": "guid", + "value": "dc3238a5-1546-47b1-95ac-cfebae4bb4b6" + }, + "valueDefinitionID": "5486d645-31e2-e611-80cc-1402ec7222b4", + "valueDefinitionKey": "Cart_Value", + "name": "Cart Value", + "setDefinitionID": "5286d645-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "PredictiveIntelAbandonedCartEvents", + "setDefinitionName": { + "value": "Predictive Intelligence AbandonedCartEvents" + }, + "parentIdentifier": "5286d645-31e2-e611-80cc-1402ec7222b4" + }, + { + "baseType": "Date", + "dataSourceID": 5, + "dataSourceName": {}, + "dataType": "Date", + "defaultValue": "getdate()", + "description": "timestamp", + "localizedDescription": { + "value": "timestamp" + }, + "definitionID": "5986d645-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "Time_Stamp", + "definitionName": { + "value": "Time Stamp" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 8, + "fullyQualifiedName": "Predictive Intelligence AbandonedCartEvents.Time Stamp", + "isHidden": false, + "isIdentityValue": false, + "isNullable": false, + "isPrimaryKey": false, + "isReadOnly": true, + "isSystemDefined": true, + "isUpdateable": false, + "obfuscationProperties": { + "maskType": "None", + "maskTypeID": 0, + "storageTypeID": 1, + "storageType": "Plain", + "valueDefinitionID": "5986d645-31e2-e611-80cc-1402ec7222b4" + }, + "ordinal": 8, + "parentDefinition": { + "definitionID": "5286d645-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "PredictiveIntelAbandonedCartEvents", + "definitionName": { + "value": "Predictive Intelligence AbandonedCartEvents" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "timestamp", + "storageFieldReferenceID": { + "type": "guid", + "value": "e8051d08-f6e2-492b-9476-db03d0b4e71b" + }, + "valueDefinitionID": "5986d645-31e2-e611-80cc-1402ec7222b4", + "valueDefinitionKey": "Time_Stamp", + "name": "Time Stamp", + "setDefinitionID": "5286d645-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "PredictiveIntelAbandonedCartEvents", + "setDefinitionName": { + "value": "Predictive Intelligence AbandonedCartEvents" + }, + "parentIdentifier": "5286d645-31e2-e611-80cc-1402ec7222b4" + }, + { + "baseType": "Text", + "dataSourceID": 5, + "dataSourceName": {}, + "dataType": "Text", + "description": "email_address", + "localizedDescription": { + "value": "email_address" + }, + "definitionID": "5786d645-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "email_address", + "definitionName": { + "value": "email_address" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 9, + "fullyQualifiedName": "Predictive Intelligence AbandonedCartEvents.email_address", + "isHidden": false, + "isIdentityValue": false, + "isNullable": true, + "isPrimaryKey": false, + "isReadOnly": true, + "isSystemDefined": true, + "isUpdateable": false, + "length": 256, + "obfuscationProperties": { + "maskType": "None", + "maskTypeID": 0, + "storageTypeID": 1, + "storageType": "Plain", + "valueDefinitionID": "5786d645-31e2-e611-80cc-1402ec7222b4" + }, + "ordinal": 9, + "parentDefinition": { + "definitionID": "5286d645-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "PredictiveIntelAbandonedCartEvents", + "definitionName": { + "value": "Predictive Intelligence AbandonedCartEvents" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "email_address", + "storageFieldReferenceID": { + "type": "guid", + "value": "1a242f2d-4161-4713-b7b1-6426f26f5157" + }, + "valueDefinitionID": "5786d645-31e2-e611-80cc-1402ec7222b4", + "valueDefinitionKey": "email_address", + "name": "email_address", + "setDefinitionID": "5286d645-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "PredictiveIntelAbandonedCartEvents", + "setDefinitionName": { + "value": "Predictive Intelligence AbandonedCartEvents" + }, + "parentIdentifier": "5286d645-31e2-e611-80cc-1402ec7222b4" + } + ], + "applicationID": "f4981f88-a13e-4abf-b331-47f41c73258d", + "applicationKey": "com.exacttarget.Predictive Web", + "attributeCount": 0, + "canAddValues": false, + "canChangeValues": false, + "canModify": false, + "canRemove": false, + "categoryID": 386, + "createdBy": -1000, + "createDate": "2017-01-24T06:33:00", + "customObjectOwnerMID": 1111111, + "dataRetentionProperties": { + "isRowBasedRetention": false, + "isResetRetentionPeriodOnImport": false, + "isDeleteAtEndOfRetentionPeriod": false, + "periodUnitOfMeasure": 4, + "setDefinitionID": "5286d645-31e2-e611-80cc-1402ec7222b4" + }, + "localizedDescription": {}, + "fullyQualifiedName": "Predictive Intelligence AbandonedCartEvents", + "isCustomObjectBacked": true, + "isEvent": false, + "isHidden": false, + "isReadOnly": true, + "isRoot": false, + "isSendable": false, + "isShared": false, + "isSystemDefined": true, + "isTestaable": false, + "parentID": "00000000-0000-0000-0000-000000000000", + "relationshipCount": 1, + "storageLogicalType": "DataExtension", + "storageName": "PI_ABANDONED_CART_EVENT", + "storageObjectIDs": ["4886d645-31e2-e611-80cc-1402ec7222b4"], + "storageReferenceID": { + "type": "guid", + "value": "df52de3f-31e2-e611-80cc-1402ec7222b4" + }, + "setDefinitionID": "5286d645-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "PredictiveIntelAbandonedCartEvents", + "name": "Predictive Intelligence AbandonedCartEvents" + }, + { + "definitionID": "6586d645-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "PredictiveIntelAbandonedCartItems", + "definitionName": { + "value": "Predictive Intelligence AbandonedCartItems" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "relationships": [ + { + "canModify": false, + "canRemove": false, + "isHidden": false, + "isSystemDefined": false, + "isGroupToSetRelationship": false, + "leftItem": { + "cardinality": "One", + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "identifier": "6586d645-31e2-e611-80cc-1402ec7222b4", + "relationshipType": "AttributeSet" + }, + "relationshipAttributes": [ + { + "leftAttributeID": "6686d645-31e2-e611-80cc-1402ec7222b4", + "leftConnectingID": { + "identifierType": "FullyQualifiedName" + }, + "rightAttributeID": "6686d645-31e2-e611-80cc-1402ec7222b4", + "rightConnectingID": { + "identifierType": "FullyQualifiedName" + } + } + ], + "relationshipID": "7887d645-31e2-e611-80cc-1402ec7222b4", + "rightItem": { + "cardinality": "Many", + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "identifier": "6586d645-31e2-e611-80cc-1402ec7222b4", + "relationshipType": "AttributeSet" + } + } + ], + "valueDefinitions": [ + { + "baseType": "Numeric", + "dataSourceID": 1, + "dataSourceName": {}, + "dataType": "LongNumber", + "description": "", + "localizedDescription": { + "value": "" + }, + "definitionID": "6a86d645-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "Custom_Object_Key", + "definitionName": { + "value": "Custom Object Key" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 1, + "fullyQualifiedName": "Predictive Intelligence AbandonedCartItems.Custom Object Key", + "isHidden": true, + "isIdentityValue": true, + "isNullable": false, + "isPrimaryKey": false, + "isReadOnly": true, + "isSystemDefined": true, + "isUpdateable": false, + "ordinal": 1, + "parentDefinition": { + "definitionID": "6586d645-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "PredictiveIntelAbandonedCartItems", + "definitionName": { + "value": "Predictive Intelligence AbandonedCartItems" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "_CustomObjectKey", + "valueDefinitionID": "6a86d645-31e2-e611-80cc-1402ec7222b4", + "valueDefinitionKey": "Custom_Object_Key", + "name": "Custom Object Key", + "setDefinitionID": "6586d645-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "PredictiveIntelAbandonedCartItems", + "setDefinitionName": { + "value": "Predictive Intelligence AbandonedCartItems" + }, + "parentIdentifier": "6586d645-31e2-e611-80cc-1402ec7222b4" + }, + { + "baseType": "Text", + "dataSourceID": 5, + "dataSourceName": {}, + "dataType": "Text", + "description": "sku", + "localizedDescription": { + "value": "sku" + }, + "definitionID": "6986d645-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "sku", + "definitionName": { + "value": "sku" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 2, + "fullyQualifiedName": "Predictive Intelligence AbandonedCartItems.sku", + "isHidden": false, + "isIdentityValue": false, + "isNullable": false, + "isPrimaryKey": true, + "isReadOnly": true, + "isSystemDefined": true, + "isUpdateable": false, + "length": 256, + "obfuscationProperties": { + "maskType": "None", + "maskTypeID": 0, + "storageTypeID": 1, + "storageType": "Plain", + "valueDefinitionID": "6986d645-31e2-e611-80cc-1402ec7222b4" + }, + "ordinal": 2, + "parentDefinition": { + "definitionID": "6586d645-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "PredictiveIntelAbandonedCartItems", + "definitionName": { + "value": "Predictive Intelligence AbandonedCartItems" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "sku", + "storageFieldReferenceID": { + "type": "guid", + "value": "85feb2dd-3ea4-4e33-93ca-a0b2e129342f" + }, + "valueDefinitionID": "6986d645-31e2-e611-80cc-1402ec7222b4", + "valueDefinitionKey": "sku", + "name": "sku", + "setDefinitionID": "6586d645-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "PredictiveIntelAbandonedCartItems", + "setDefinitionName": { + "value": "Predictive Intelligence AbandonedCartItems" + }, + "parentIdentifier": "6586d645-31e2-e611-80cc-1402ec7222b4" + }, + { + "baseType": "Text", + "dataSourceID": 5, + "dataSourceName": {}, + "dataType": "Text", + "description": "cart_id", + "localizedDescription": { + "value": "cart_id" + }, + "definitionID": "6686d645-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "cart_id", + "definitionName": { + "value": "Cart ID" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 3, + "fullyQualifiedName": "Predictive Intelligence AbandonedCartItems.Cart ID", + "isHidden": false, + "isIdentityValue": false, + "isNullable": false, + "isPrimaryKey": true, + "isReadOnly": true, + "isSystemDefined": true, + "isUpdateable": false, + "length": 256, + "obfuscationProperties": { + "maskType": "None", + "maskTypeID": 0, + "storageTypeID": 1, + "storageType": "Plain", + "valueDefinitionID": "6686d645-31e2-e611-80cc-1402ec7222b4" + }, + "ordinal": 3, + "parentDefinition": { + "definitionID": "6586d645-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "PredictiveIntelAbandonedCartItems", + "definitionName": { + "value": "Predictive Intelligence AbandonedCartItems" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "cart_id", + "storageFieldReferenceID": { + "type": "guid", + "value": "686a5045-b1b9-497f-9226-9e43b5b09906" + }, + "valueDefinitionID": "6686d645-31e2-e611-80cc-1402ec7222b4", + "valueDefinitionKey": "cart_id", + "name": "Cart ID", + "setDefinitionID": "6586d645-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "PredictiveIntelAbandonedCartItems", + "setDefinitionName": { + "value": "Predictive Intelligence AbandonedCartItems" + }, + "parentIdentifier": "6586d645-31e2-e611-80cc-1402ec7222b4" + }, + { + "baseType": "Numeric", + "dataSourceID": 5, + "dataSourceName": {}, + "dataType": "Decimal", + "description": "price", + "localizedDescription": { + "value": "price" + }, + "definitionID": "6786d645-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "Price", + "definitionName": { + "value": "Price" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 4, + "fullyQualifiedName": "Predictive Intelligence AbandonedCartItems.Price", + "isHidden": false, + "isIdentityValue": false, + "isNullable": true, + "isPrimaryKey": false, + "isReadOnly": true, + "isSystemDefined": true, + "isUpdateable": false, + "length": 18, + "obfuscationProperties": { + "maskType": "None", + "maskTypeID": 0, + "storageTypeID": 1, + "storageType": "Plain", + "valueDefinitionID": "6786d645-31e2-e611-80cc-1402ec7222b4" + }, + "ordinal": 4, + "parentDefinition": { + "definitionID": "6586d645-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "PredictiveIntelAbandonedCartItems", + "definitionName": { + "value": "Predictive Intelligence AbandonedCartItems" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "scale": 2, + "storageName": "price", + "storageFieldReferenceID": { + "type": "guid", + "value": "9a62ef64-4993-4876-a16c-9786eae6fd53" + }, + "valueDefinitionID": "6786d645-31e2-e611-80cc-1402ec7222b4", + "valueDefinitionKey": "Price", + "name": "Price", + "setDefinitionID": "6586d645-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "PredictiveIntelAbandonedCartItems", + "setDefinitionName": { + "value": "Predictive Intelligence AbandonedCartItems" + }, + "parentIdentifier": "6586d645-31e2-e611-80cc-1402ec7222b4" + }, + { + "baseType": "Numeric", + "dataSourceID": 5, + "dataSourceName": {}, + "dataType": "Number", + "description": "quantity", + "localizedDescription": { + "value": "quantity" + }, + "definitionID": "6886d645-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "Quantity", + "definitionName": { + "value": "Quantity" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 5, + "fullyQualifiedName": "Predictive Intelligence AbandonedCartItems.Quantity", + "isHidden": false, + "isIdentityValue": false, + "isNullable": true, + "isPrimaryKey": false, + "isReadOnly": true, + "isSystemDefined": true, + "isUpdateable": false, + "obfuscationProperties": { + "maskType": "None", + "maskTypeID": 0, + "storageTypeID": 1, + "storageType": "Plain", + "valueDefinitionID": "6886d645-31e2-e611-80cc-1402ec7222b4" + }, + "ordinal": 5, + "parentDefinition": { + "definitionID": "6586d645-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "PredictiveIntelAbandonedCartItems", + "definitionName": { + "value": "Predictive Intelligence AbandonedCartItems" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "quantity", + "storageFieldReferenceID": { + "type": "guid", + "value": "20d85be0-e56d-4888-b66e-bb8b6466d07c" + }, + "valueDefinitionID": "6886d645-31e2-e611-80cc-1402ec7222b4", + "valueDefinitionKey": "Quantity", + "name": "Quantity", + "setDefinitionID": "6586d645-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "PredictiveIntelAbandonedCartItems", + "setDefinitionName": { + "value": "Predictive Intelligence AbandonedCartItems" + }, + "parentIdentifier": "6586d645-31e2-e611-80cc-1402ec7222b4" + } + ], + "applicationID": "f4981f88-a13e-4abf-b331-47f41c73258d", + "applicationKey": "com.exacttarget.Predictive Web", + "attributeCount": 0, + "canAddValues": false, + "canChangeValues": false, + "canModify": false, + "canRemove": false, + "categoryID": 386, + "createdBy": -1000, + "createDate": "2017-01-24T06:33:00", + "customObjectOwnerMID": 1111111, + "dataRetentionProperties": { + "isRowBasedRetention": false, + "isResetRetentionPeriodOnImport": false, + "isDeleteAtEndOfRetentionPeriod": false, + "periodUnitOfMeasure": 4, + "setDefinitionID": "6586d645-31e2-e611-80cc-1402ec7222b4" + }, + "localizedDescription": {}, + "fullyQualifiedName": "Predictive Intelligence AbandonedCartItems", + "isCustomObjectBacked": true, + "isEvent": false, + "isHidden": false, + "isReadOnly": true, + "isRoot": false, + "isSendable": false, + "isShared": false, + "isSystemDefined": true, + "isTestaable": false, + "parentID": "00000000-0000-0000-0000-000000000000", + "relationshipCount": 1, + "storageLogicalType": "DataExtension", + "storageName": "PI_ABANDONED_CART_ITEMS", + "storageObjectIDs": ["5f86d645-31e2-e611-80cc-1402ec7222b4"], + "storageReferenceID": { + "type": "guid", + "value": "e052de3f-31e2-e611-80cc-1402ec7222b4" + }, + "setDefinitionID": "6586d645-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "PredictiveIntelAbandonedCartItems", + "name": "Predictive Intelligence AbandonedCartItems" + }, + { + "definitionID": "6d51de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "PushDemographics", + "definitionName": { + "value": "MobilePush Demographics" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "relationships": [ + { + "canModify": false, + "canRemove": false, + "isHidden": false, + "isSystemDefined": false, + "isGroupToSetRelationship": true, + "leftItem": { + "cardinality": "One", + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "identifier": "9351de3f-31e2-e611-80cc-1402ec7222b4", + "relationshipType": "AttributeGroup" + }, + "leftRelationshipIDs": [ + { + "type": "int16", + "value": "2" + } + ], + "leftRelationshipReferenceType": "CustomerData", + "relationshipAttributes": [ + { + "leftAttributeID": "9293dc39-31e2-e611-80cc-1402ec7222b4", + "leftConnectingID": { + "identifierType": "FullyQualifiedName" + }, + "rightAttributeID": "7351de3f-31e2-e611-80cc-1402ec7222b4", + "rightConnectingID": { + "identifierType": "FullyQualifiedName" + } + } + ], + "relationshipID": "9651de3f-31e2-e611-80cc-1402ec7222b4", + "rightItem": { + "cardinality": "Many", + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "identifier": "6d51de3f-31e2-e611-80cc-1402ec7222b4", + "relationshipType": "AttributeSet" + } + }, + { + "canModify": false, + "canRemove": false, + "isHidden": false, + "isSystemDefined": false, + "isGroupToSetRelationship": false, + "leftItem": { + "cardinality": "One", + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "identifier": "6d51de3f-31e2-e611-80cc-1402ec7222b4", + "relationshipType": "AttributeSet" + }, + "relationshipAttributes": [ + { + "leftAttributeID": "6f51de3f-31e2-e611-80cc-1402ec7222b4", + "leftConnectingID": { + "identifierType": "FullyQualifiedName" + }, + "rightAttributeID": "b452de3f-31e2-e611-80cc-1402ec7222b4", + "rightConnectingID": { + "identifierType": "FullyQualifiedName" + } + }, + { + "leftAttributeID": "7751de3f-31e2-e611-80cc-1402ec7222b4", + "leftConnectingID": { + "identifierType": "FullyQualifiedName" + }, + "rightAttributeID": "b552de3f-31e2-e611-80cc-1402ec7222b4", + "rightConnectingID": { + "identifierType": "FullyQualifiedName" + } + } + ], + "relationshipID": "bc52de3f-31e2-e611-80cc-1402ec7222b4", + "rightItem": { + "cardinality": "Many", + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "identifier": "b352de3f-31e2-e611-80cc-1402ec7222b4", + "relationshipType": "AttributeSet" + } + }, + { + "canModify": false, + "canRemove": false, + "isHidden": false, + "isSystemDefined": false, + "isGroupToSetRelationship": false, + "leftItem": { + "cardinality": "One", + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "identifier": "6d51de3f-31e2-e611-80cc-1402ec7222b4", + "relationshipType": "AttributeSet" + }, + "relationshipAttributes": [ + { + "leftAttributeID": "6f51de3f-31e2-e611-80cc-1402ec7222b4", + "leftConnectingID": { + "identifierType": "FullyQualifiedName" + }, + "rightAttributeID": "c752de3f-31e2-e611-80cc-1402ec7222b4", + "rightConnectingID": { + "identifierType": "FullyQualifiedName" + } + }, + { + "leftAttributeID": "7751de3f-31e2-e611-80cc-1402ec7222b4", + "leftConnectingID": { + "identifierType": "FullyQualifiedName" + }, + "rightAttributeID": "ca52de3f-31e2-e611-80cc-1402ec7222b4", + "rightConnectingID": { + "identifierType": "FullyQualifiedName" + } + } + ], + "relationshipID": "d052de3f-31e2-e611-80cc-1402ec7222b4", + "rightItem": { + "cardinality": "Many", + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "identifier": "c652de3f-31e2-e611-80cc-1402ec7222b4", + "relationshipType": "AttributeSet" + } + } + ], + "valueDefinitions": [ + { + "baseType": "Text", + "dataSourceID": 3, + "dataSourceName": {}, + "dataType": "Text", + "description": "", + "localizedDescription": { + "value": "" + }, + "definitionID": "6e51de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "Alias", + "definitionName": { + "value": "Alias" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 1, + "fullyQualifiedName": "MobilePush Demographics.Alias", + "isHidden": true, + "isIdentityValue": false, + "isNullable": true, + "isPrimaryKey": false, + "isReadOnly": true, + "isSystemDefined": true, + "isUpdateable": false, + "length": 100, + "obfuscationProperties": { + "maskType": "None", + "maskTypeID": 0, + "storageTypeID": 1, + "storageType": "Plain", + "valueDefinitionID": "6e51de3f-31e2-e611-80cc-1402ec7222b4" + }, + "ordinal": 1, + "parentDefinition": { + "definitionID": "6d51de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "PushDemographics", + "definitionName": { + "value": "MobilePush Demographics" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "_Alias", + "storageFieldReferenceID": { + "type": "guid", + "value": "dcef58d9-dcaa-4a68-9ecf-6c663a57fb33" + }, + "valueDefinitionID": "6e51de3f-31e2-e611-80cc-1402ec7222b4", + "valueDefinitionKey": "Alias", + "name": "Alias", + "setDefinitionID": "6d51de3f-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "PushDemographics", + "setDefinitionName": { + "value": "MobilePush Demographics" + }, + "parentIdentifier": "6d51de3f-31e2-e611-80cc-1402ec7222b4" + }, + { + "baseType": "Text", + "customerDataID": 7, + "dataSourceID": 3, + "dataSourceName": {}, + "dataType": "Text", + "description": "", + "localizedDescription": { + "value": "" + }, + "definitionID": "6f51de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "PushAppID", + "definitionName": { + "value": "Application" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 2, + "fullyQualifiedName": "MobilePush Demographics.Application", + "isHidden": false, + "isIdentityValue": false, + "isNullable": false, + "isPrimaryKey": true, + "isReadOnly": true, + "isSystemDefined": true, + "isUpdateable": false, + "length": 38, + "obfuscationProperties": { + "maskType": "None", + "maskTypeID": 0, + "storageTypeID": 1, + "storageType": "Plain", + "valueDefinitionID": "6f51de3f-31e2-e611-80cc-1402ec7222b4" + }, + "ordinal": 2, + "parentDefinition": { + "definitionID": "6d51de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "PushDemographics", + "definitionName": { + "value": "MobilePush Demographics" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "restrictionLookupListID": 11, + "storageName": "_APID", + "storageFieldReferenceID": { + "type": "guid", + "value": "4e82734e-ff8a-4868-a786-20e9596a94d2" + }, + "valueDefinitionID": "6f51de3f-31e2-e611-80cc-1402ec7222b4", + "valueDefinitionKey": "PushAppID", + "name": "Application", + "setDefinitionID": "6d51de3f-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "PushDemographics", + "setDefinitionName": { + "value": "MobilePush Demographics" + }, + "parentIdentifier": "6d51de3f-31e2-e611-80cc-1402ec7222b4" + }, + { + "baseType": "Numeric", + "dataSourceID": 3, + "dataSourceName": {}, + "dataType": "Number", + "description": "", + "localizedDescription": { + "value": "" + }, + "definitionID": "7051de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "Badge", + "definitionName": { + "value": "Badge" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 3, + "fullyQualifiedName": "MobilePush Demographics.Badge", + "isHidden": false, + "isIdentityValue": false, + "isNullable": true, + "isPrimaryKey": false, + "isReadOnly": true, + "isSystemDefined": true, + "isUpdateable": false, + "obfuscationProperties": { + "maskType": "None", + "maskTypeID": 0, + "storageTypeID": 1, + "storageType": "Plain", + "valueDefinitionID": "7051de3f-31e2-e611-80cc-1402ec7222b4" + }, + "ordinal": 3, + "parentDefinition": { + "definitionID": "6d51de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "PushDemographics", + "definitionName": { + "value": "MobilePush Demographics" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "_Badge", + "storageFieldReferenceID": { + "type": "guid", + "value": "ae73cf07-6b58-4ae4-a75e-ccd1d4bdb98f" + }, + "valueDefinitionID": "7051de3f-31e2-e611-80cc-1402ec7222b4", + "valueDefinitionKey": "Badge", + "name": "Badge", + "setDefinitionID": "6d51de3f-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "PushDemographics", + "setDefinitionName": { + "value": "MobilePush Demographics" + }, + "parentIdentifier": "6d51de3f-31e2-e611-80cc-1402ec7222b4" + }, + { + "baseType": "Text", + "dataSourceID": 3, + "dataSourceName": {}, + "dataType": "Text", + "description": "", + "localizedDescription": { + "value": "" + }, + "definitionID": "7151de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "Channel", + "definitionName": { + "value": "Channel" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 4, + "fullyQualifiedName": "MobilePush Demographics.Channel", + "isHidden": false, + "isIdentityValue": false, + "isNullable": true, + "isPrimaryKey": false, + "isReadOnly": true, + "isSystemDefined": true, + "isUpdateable": false, + "length": 20, + "obfuscationProperties": { + "maskType": "None", + "maskTypeID": 0, + "storageTypeID": 1, + "storageType": "Plain", + "valueDefinitionID": "7151de3f-31e2-e611-80cc-1402ec7222b4" + }, + "ordinal": 4, + "parentDefinition": { + "definitionID": "6d51de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "PushDemographics", + "definitionName": { + "value": "MobilePush Demographics" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "_Channel", + "storageFieldReferenceID": { + "type": "guid", + "value": "84490d74-3c83-46b1-8a0b-b073dc45c208" + }, + "valueDefinitionID": "7151de3f-31e2-e611-80cc-1402ec7222b4", + "valueDefinitionKey": "Channel", + "name": "Channel", + "setDefinitionID": "6d51de3f-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "PushDemographics", + "setDefinitionName": { + "value": "MobilePush Demographics" + }, + "parentIdentifier": "6d51de3f-31e2-e611-80cc-1402ec7222b4" + }, + { + "baseType": "Text", + "dataSourceID": 3, + "dataSourceName": {}, + "dataType": "Text", + "description": "", + "localizedDescription": { + "value": "" + }, + "definitionID": "7251de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "City", + "definitionName": { + "value": "City" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 5, + "fullyQualifiedName": "MobilePush Demographics.City", + "isHidden": false, + "isIdentityValue": false, + "isNullable": true, + "isPrimaryKey": false, + "isReadOnly": false, + "isSystemDefined": false, + "isUpdateable": false, + "length": 200, + "obfuscationProperties": { + "maskType": "None", + "maskTypeID": 0, + "storageTypeID": 1, + "storageType": "Plain", + "valueDefinitionID": "7251de3f-31e2-e611-80cc-1402ec7222b4" + }, + "ordinal": 5, + "parentDefinition": { + "definitionID": "6d51de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "PushDemographics", + "definitionName": { + "value": "MobilePush Demographics" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "_City", + "storageFieldReferenceID": { + "type": "guid", + "value": "905b7a96-ba4e-4265-a271-6b8d32fdf56e" + }, + "valueDefinitionID": "7251de3f-31e2-e611-80cc-1402ec7222b4", + "valueDefinitionKey": "City", + "name": "City", + "setDefinitionID": "6d51de3f-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "PushDemographics", + "setDefinitionName": { + "value": "MobilePush Demographics" + }, + "parentIdentifier": "6d51de3f-31e2-e611-80cc-1402ec7222b4" + }, + { + "baseType": "Numeric", + "dataSourceID": 3, + "dataSourceName": {}, + "dataType": "LongNumber", + "description": "", + "localizedDescription": { + "value": "" + }, + "definitionID": "7351de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "ContactID", + "definitionName": { + "value": "Contact ID" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 6, + "fullyQualifiedName": "MobilePush Demographics.Contact ID", + "isHidden": false, + "isIdentityValue": false, + "isNullable": false, + "isPrimaryKey": false, + "isReadOnly": true, + "isSystemDefined": true, + "isUpdateable": false, + "obfuscationProperties": { + "maskType": "None", + "maskTypeID": 0, + "storageTypeID": 1, + "storageType": "Plain", + "valueDefinitionID": "7351de3f-31e2-e611-80cc-1402ec7222b4" + }, + "ordinal": 6, + "parentDefinition": { + "definitionID": "6d51de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "PushDemographics", + "definitionName": { + "value": "MobilePush Demographics" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "_ContactID", + "storageFieldReferenceID": { + "type": "guid", + "value": "f5c616a4-6ba4-4c3f-a55b-85d12dd41932" + }, + "valueDefinitionID": "7351de3f-31e2-e611-80cc-1402ec7222b4", + "valueDefinitionKey": "ContactID", + "name": "Contact ID", + "setDefinitionID": "6d51de3f-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "PushDemographics", + "setDefinitionName": { + "value": "MobilePush Demographics" + }, + "parentIdentifier": "6d51de3f-31e2-e611-80cc-1402ec7222b4" + }, + { + "baseType": "Numeric", + "dataSourceID": 3, + "dataSourceName": {}, + "dataType": "LongNumber", + "description": "", + "localizedDescription": { + "value": "" + }, + "definitionID": "7451de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "CreatedBy", + "definitionName": { + "value": "Created By" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 7, + "fullyQualifiedName": "MobilePush Demographics.Created By", + "isHidden": true, + "isIdentityValue": false, + "isNullable": true, + "isPrimaryKey": false, + "isReadOnly": true, + "isSystemDefined": true, + "isUpdateable": false, + "obfuscationProperties": { + "maskType": "None", + "maskTypeID": 0, + "storageTypeID": 1, + "storageType": "Plain", + "valueDefinitionID": "7451de3f-31e2-e611-80cc-1402ec7222b4" + }, + "ordinal": 7, + "parentDefinition": { + "definitionID": "6d51de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "PushDemographics", + "definitionName": { + "value": "MobilePush Demographics" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "_CreatedBy", + "storageFieldReferenceID": { + "type": "guid", + "value": "bf010c22-fd43-4303-a732-aff2510133f8" + }, + "valueDefinitionID": "7451de3f-31e2-e611-80cc-1402ec7222b4", + "valueDefinitionKey": "CreatedBy", + "name": "Created By", + "setDefinitionID": "6d51de3f-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "PushDemographics", + "setDefinitionName": { + "value": "MobilePush Demographics" + }, + "parentIdentifier": "6d51de3f-31e2-e611-80cc-1402ec7222b4" + }, + { + "baseType": "Date", + "dataSourceID": 3, + "dataSourceName": {}, + "dataType": "Date", + "defaultValue": "GETDATE()", + "description": "", + "localizedDescription": { + "value": "" + }, + "definitionID": "7551de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "CreatedDate", + "definitionName": { + "value": "Created Date" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 8, + "fullyQualifiedName": "MobilePush Demographics.Created Date", + "isHidden": false, + "isIdentityValue": false, + "isNullable": false, + "isPrimaryKey": false, + "isReadOnly": true, + "isSystemDefined": true, + "isUpdateable": false, + "obfuscationProperties": { + "maskType": "None", + "maskTypeID": 0, + "storageTypeID": 1, + "storageType": "Plain", + "valueDefinitionID": "7551de3f-31e2-e611-80cc-1402ec7222b4" + }, + "ordinal": 8, + "parentDefinition": { + "definitionID": "6d51de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "PushDemographics", + "definitionName": { + "value": "MobilePush Demographics" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "_CreatedDate", + "storageFieldReferenceID": { + "type": "guid", + "value": "1b450c10-bd4e-448e-ae6f-583ac616cc46" + }, + "valueDefinitionID": "7551de3f-31e2-e611-80cc-1402ec7222b4", + "valueDefinitionKey": "CreatedDate", + "name": "Created Date", + "setDefinitionID": "6d51de3f-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "PushDemographics", + "setDefinitionName": { + "value": "MobilePush Demographics" + }, + "parentIdentifier": "6d51de3f-31e2-e611-80cc-1402ec7222b4" + }, + { + "baseType": "Numeric", + "dataSourceID": 3, + "dataSourceName": {}, + "dataType": "LongNumber", + "description": "", + "localizedDescription": { + "value": "" + }, + "definitionID": "9151de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "CustomObjectKey", + "definitionName": { + "value": "Custom Object Key" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 9, + "fullyQualifiedName": "MobilePush Demographics.Custom Object Key", + "isHidden": true, + "isIdentityValue": true, + "isNullable": false, + "isPrimaryKey": false, + "isReadOnly": true, + "isSystemDefined": true, + "isUpdateable": false, + "ordinal": 9, + "parentDefinition": { + "definitionID": "6d51de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "PushDemographics", + "definitionName": { + "value": "MobilePush Demographics" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "_CustomObjectKey", + "valueDefinitionID": "9151de3f-31e2-e611-80cc-1402ec7222b4", + "valueDefinitionKey": "CustomObjectKey", + "name": "Custom Object Key", + "setDefinitionID": "6d51de3f-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "PushDemographics", + "setDefinitionName": { + "value": "MobilePush Demographics" + }, + "parentIdentifier": "6d51de3f-31e2-e611-80cc-1402ec7222b4" + }, + { + "baseType": "Text", + "dataSourceID": 3, + "dataSourceName": {}, + "dataType": "Text", + "description": "", + "localizedDescription": { + "value": "" + }, + "definitionID": "7651de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "Device", + "definitionName": { + "value": "Device" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 10, + "fullyQualifiedName": "MobilePush Demographics.Device", + "isHidden": false, + "isIdentityValue": false, + "isNullable": true, + "isPrimaryKey": false, + "isReadOnly": true, + "isSystemDefined": true, + "isUpdateable": false, + "length": 100, + "obfuscationProperties": { + "maskType": "None", + "maskTypeID": 0, + "storageTypeID": 1, + "storageType": "Plain", + "valueDefinitionID": "7651de3f-31e2-e611-80cc-1402ec7222b4" + }, + "ordinal": 10, + "parentDefinition": { + "definitionID": "6d51de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "PushDemographics", + "definitionName": { + "value": "MobilePush Demographics" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "_Device", + "storageFieldReferenceID": { + "type": "guid", + "value": "1aa7b10f-f32a-4620-af79-4210aeacf996" + }, + "valueDefinitionID": "7651de3f-31e2-e611-80cc-1402ec7222b4", + "valueDefinitionKey": "Device", + "name": "Device", + "setDefinitionID": "6d51de3f-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "PushDemographics", + "setDefinitionName": { + "value": "MobilePush Demographics" + }, + "parentIdentifier": "6d51de3f-31e2-e611-80cc-1402ec7222b4" + }, + { + "baseType": "Text", + "customerDataID": 6, + "dataSourceID": 3, + "dataSourceName": {}, + "dataType": "Text", + "description": "", + "localizedDescription": { + "value": "" + }, + "definitionID": "7751de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "PushDeviceID", + "definitionName": { + "value": "Device ID" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 11, + "fullyQualifiedName": "MobilePush Demographics.Device ID", + "isHidden": false, + "isIdentityValue": false, + "isNullable": false, + "isPrimaryKey": true, + "isReadOnly": true, + "isSystemDefined": true, + "isUpdateable": false, + "length": 200, + "obfuscationProperties": { + "maskType": "None", + "maskTypeID": 0, + "storageTypeID": 1, + "storageType": "Plain", + "valueDefinitionID": "7751de3f-31e2-e611-80cc-1402ec7222b4" + }, + "ordinal": 11, + "parentDefinition": { + "definitionID": "6d51de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "PushDemographics", + "definitionName": { + "value": "MobilePush Demographics" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "_DeviceID", + "storageFieldReferenceID": { + "type": "guid", + "value": "9d8db1d4-c00e-49bc-98d9-e30d2e3ed7cf" + }, + "valueDefinitionID": "7751de3f-31e2-e611-80cc-1402ec7222b4", + "valueDefinitionKey": "PushDeviceID", + "name": "Device ID", + "setDefinitionID": "6d51de3f-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "PushDemographics", + "setDefinitionName": { + "value": "MobilePush Demographics" + }, + "parentIdentifier": "6d51de3f-31e2-e611-80cc-1402ec7222b4" + }, + { + "baseType": "Text", + "dataSourceID": 3, + "dataSourceName": {}, + "dataType": "Text", + "description": "", + "localizedDescription": { + "value": "" + }, + "definitionID": "7851de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "DeviceType", + "definitionName": { + "value": "Device Type" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 12, + "fullyQualifiedName": "MobilePush Demographics.Device Type", + "isHidden": false, + "isIdentityValue": false, + "isNullable": true, + "isPrimaryKey": false, + "isReadOnly": true, + "isSystemDefined": true, + "isUpdateable": false, + "length": 20, + "obfuscationProperties": { + "maskType": "None", + "maskTypeID": 0, + "storageTypeID": 1, + "storageType": "Plain", + "valueDefinitionID": "7851de3f-31e2-e611-80cc-1402ec7222b4" + }, + "ordinal": 12, + "parentDefinition": { + "definitionID": "6d51de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "PushDemographics", + "definitionName": { + "value": "MobilePush Demographics" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "_DeviceType", + "storageFieldReferenceID": { + "type": "guid", + "value": "75f38dcd-559f-4663-8e84-a5f85abc3e0a" + }, + "valueDefinitionID": "7851de3f-31e2-e611-80cc-1402ec7222b4", + "valueDefinitionKey": "DeviceType", + "name": "Device Type", + "setDefinitionID": "6d51de3f-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "PushDemographics", + "setDefinitionName": { + "value": "MobilePush Demographics" + }, + "parentIdentifier": "6d51de3f-31e2-e611-80cc-1402ec7222b4" + }, + { + "baseType": "Text", + "dataSourceID": 3, + "dataSourceName": {}, + "dataType": "Text", + "description": "", + "localizedDescription": { + "value": "" + }, + "definitionID": "7951de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "FirstName", + "definitionName": { + "value": "First Name" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 13, + "fullyQualifiedName": "MobilePush Demographics.First Name", + "isHidden": false, + "isIdentityValue": false, + "isNullable": true, + "isPrimaryKey": false, + "isReadOnly": false, + "isSystemDefined": false, + "isUpdateable": false, + "length": 100, + "obfuscationProperties": { + "maskType": "None", + "maskTypeID": 0, + "storageTypeID": 1, + "storageType": "Plain", + "valueDefinitionID": "7951de3f-31e2-e611-80cc-1402ec7222b4" + }, + "ordinal": 13, + "parentDefinition": { + "definitionID": "6d51de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "PushDemographics", + "definitionName": { + "value": "MobilePush Demographics" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "_FirstName", + "storageFieldReferenceID": { + "type": "guid", + "value": "cf0e8f08-bba3-4ca3-b05c-e1360897f0f6" + }, + "valueDefinitionID": "7951de3f-31e2-e611-80cc-1402ec7222b4", + "valueDefinitionKey": "FirstName", + "name": "First Name", + "setDefinitionID": "6d51de3f-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "PushDemographics", + "setDefinitionName": { + "value": "MobilePush Demographics" + }, + "parentIdentifier": "6d51de3f-31e2-e611-80cc-1402ec7222b4" + }, + { + "baseType": "Text", + "dataSourceID": 3, + "dataSourceName": {}, + "dataType": "Text", + "description": "", + "localizedDescription": { + "value": "" + }, + "definitionID": "7a51de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "HardwareID", + "definitionName": { + "value": "Hardware ID" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 14, + "fullyQualifiedName": "MobilePush Demographics.Hardware ID", + "isHidden": false, + "isIdentityValue": false, + "isNullable": true, + "isPrimaryKey": false, + "isReadOnly": true, + "isSystemDefined": true, + "isUpdateable": false, + "length": 100, + "obfuscationProperties": { + "maskType": "None", + "maskTypeID": 0, + "storageTypeID": 1, + "storageType": "Plain", + "valueDefinitionID": "7a51de3f-31e2-e611-80cc-1402ec7222b4" + }, + "ordinal": 14, + "parentDefinition": { + "definitionID": "6d51de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "PushDemographics", + "definitionName": { + "value": "MobilePush Demographics" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "_HardwareId", + "storageFieldReferenceID": { + "type": "guid", + "value": "a7c7ac11-c93d-4512-ae1b-25e9debbdddc" + }, + "valueDefinitionID": "7a51de3f-31e2-e611-80cc-1402ec7222b4", + "valueDefinitionKey": "HardwareID", + "name": "Hardware ID", + "setDefinitionID": "6d51de3f-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "PushDemographics", + "setDefinitionName": { + "value": "MobilePush Demographics" + }, + "parentIdentifier": "6d51de3f-31e2-e611-80cc-1402ec7222b4" + }, + { + "baseType": "Boolean", + "dataSourceID": 3, + "dataSourceName": {}, + "dataType": "Boolean", + "defaultValue": "False", + "description": "", + "localizedDescription": { + "value": "" + }, + "definitionID": "7b51de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "IsHonorDST", + "definitionName": { + "value": "Is Honor DST" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 15, + "fullyQualifiedName": "MobilePush Demographics.Is Honor DST", + "isHidden": false, + "isIdentityValue": false, + "isNullable": true, + "isPrimaryKey": false, + "isReadOnly": false, + "isSystemDefined": true, + "isUpdateable": false, + "obfuscationProperties": { + "maskType": "None", + "maskTypeID": 0, + "storageTypeID": 1, + "storageType": "Plain", + "valueDefinitionID": "7b51de3f-31e2-e611-80cc-1402ec7222b4" + }, + "ordinal": 15, + "parentDefinition": { + "definitionID": "6d51de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "PushDemographics", + "definitionName": { + "value": "MobilePush Demographics" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "_IsHonorDST", + "storageFieldReferenceID": { + "type": "guid", + "value": "e5d1a20d-ec5a-40a2-a474-64513204cbac" + }, + "valueDefinitionID": "7b51de3f-31e2-e611-80cc-1402ec7222b4", + "valueDefinitionKey": "IsHonorDST", + "name": "Is Honor DST", + "setDefinitionID": "6d51de3f-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "PushDemographics", + "setDefinitionName": { + "value": "MobilePush Demographics" + }, + "parentIdentifier": "6d51de3f-31e2-e611-80cc-1402ec7222b4" + }, + { + "baseType": "Text", + "dataSourceID": 3, + "dataSourceName": {}, + "dataType": "Text", + "description": "", + "localizedDescription": { + "value": "" + }, + "definitionID": "7c51de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "LastName", + "definitionName": { + "value": "Last Name" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 16, + "fullyQualifiedName": "MobilePush Demographics.Last Name", + "isHidden": false, + "isIdentityValue": false, + "isNullable": true, + "isPrimaryKey": false, + "isReadOnly": false, + "isSystemDefined": false, + "isUpdateable": false, + "length": 100, + "obfuscationProperties": { + "maskType": "None", + "maskTypeID": 0, + "storageTypeID": 1, + "storageType": "Plain", + "valueDefinitionID": "7c51de3f-31e2-e611-80cc-1402ec7222b4" + }, + "ordinal": 16, + "parentDefinition": { + "definitionID": "6d51de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "PushDemographics", + "definitionName": { + "value": "MobilePush Demographics" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "_LastName", + "storageFieldReferenceID": { + "type": "guid", + "value": "92c01cad-907d-48c0-ac6a-691c12d62358" + }, + "valueDefinitionID": "7c51de3f-31e2-e611-80cc-1402ec7222b4", + "valueDefinitionKey": "LastName", + "name": "Last Name", + "setDefinitionID": "6d51de3f-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "PushDemographics", + "setDefinitionName": { + "value": "MobilePush Demographics" + }, + "parentIdentifier": "6d51de3f-31e2-e611-80cc-1402ec7222b4" + }, + { + "baseType": "Boolean", + "dataSourceID": 3, + "dataSourceName": {}, + "dataType": "Boolean", + "description": "", + "localizedDescription": { + "value": "" + }, + "definitionID": "7d51de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "LocationEnabled", + "definitionName": { + "value": "Location Enabled" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 17, + "fullyQualifiedName": "MobilePush Demographics.Location Enabled", + "isHidden": false, + "isIdentityValue": false, + "isNullable": true, + "isPrimaryKey": false, + "isReadOnly": true, + "isSystemDefined": true, + "isUpdateable": false, + "obfuscationProperties": { + "maskType": "None", + "maskTypeID": 0, + "storageTypeID": 1, + "storageType": "Plain", + "valueDefinitionID": "7d51de3f-31e2-e611-80cc-1402ec7222b4" + }, + "ordinal": 17, + "parentDefinition": { + "definitionID": "6d51de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "PushDemographics", + "definitionName": { + "value": "MobilePush Demographics" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "_LocationEnabled", + "storageFieldReferenceID": { + "type": "guid", + "value": "30b5144d-9b73-4804-b17b-fbf4d2d03bfe" + }, + "valueDefinitionID": "7d51de3f-31e2-e611-80cc-1402ec7222b4", + "valueDefinitionKey": "LocationEnabled", + "name": "Location Enabled", + "setDefinitionID": "6d51de3f-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "PushDemographics", + "setDefinitionName": { + "value": "MobilePush Demographics" + }, + "parentIdentifier": "6d51de3f-31e2-e611-80cc-1402ec7222b4" + }, + { + "baseType": "Numeric", + "dataSourceID": 3, + "dataSourceName": {}, + "dataType": "LongNumber", + "description": "", + "localizedDescription": { + "value": "" + }, + "definitionID": "7e51de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "ModifiedBy", + "definitionName": { + "value": "Modified By" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 18, + "fullyQualifiedName": "MobilePush Demographics.Modified By", + "isHidden": true, + "isIdentityValue": false, + "isNullable": true, + "isPrimaryKey": false, + "isReadOnly": true, + "isSystemDefined": true, + "isUpdateable": false, + "obfuscationProperties": { + "maskType": "None", + "maskTypeID": 0, + "storageTypeID": 1, + "storageType": "Plain", + "valueDefinitionID": "7e51de3f-31e2-e611-80cc-1402ec7222b4" + }, + "ordinal": 18, + "parentDefinition": { + "definitionID": "6d51de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "PushDemographics", + "definitionName": { + "value": "MobilePush Demographics" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "_ModifiedBy", + "storageFieldReferenceID": { + "type": "guid", + "value": "46975e48-0dbb-4ec4-91e9-9823aa2a5d0a" + }, + "valueDefinitionID": "7e51de3f-31e2-e611-80cc-1402ec7222b4", + "valueDefinitionKey": "ModifiedBy", + "name": "Modified By", + "setDefinitionID": "6d51de3f-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "PushDemographics", + "setDefinitionName": { + "value": "MobilePush Demographics" + }, + "parentIdentifier": "6d51de3f-31e2-e611-80cc-1402ec7222b4" + }, + { + "baseType": "Date", + "dataSourceID": 3, + "dataSourceName": {}, + "dataType": "Date", + "defaultValue": "GETDATE()", + "description": "", + "localizedDescription": { + "value": "" + }, + "definitionID": "7f51de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "ModifiedDate", + "definitionName": { + "value": "Modified Date" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 19, + "fullyQualifiedName": "MobilePush Demographics.Modified Date", + "isHidden": false, + "isIdentityValue": false, + "isNullable": false, + "isPrimaryKey": false, + "isReadOnly": true, + "isSystemDefined": true, + "isUpdateable": false, + "obfuscationProperties": { + "maskType": "None", + "maskTypeID": 0, + "storageTypeID": 1, + "storageType": "Plain", + "valueDefinitionID": "7f51de3f-31e2-e611-80cc-1402ec7222b4" + }, + "ordinal": 19, + "parentDefinition": { + "definitionID": "6d51de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "PushDemographics", + "definitionName": { + "value": "MobilePush Demographics" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "_ModifiedDate", + "storageFieldReferenceID": { + "type": "guid", + "value": "4602d692-06de-4974-84e4-e8facfa25be9" + }, + "valueDefinitionID": "7f51de3f-31e2-e611-80cc-1402ec7222b4", + "valueDefinitionKey": "ModifiedDate", + "name": "Modified Date", + "setDefinitionID": "6d51de3f-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "PushDemographics", + "setDefinitionName": { + "value": "MobilePush Demographics" + }, + "parentIdentifier": "6d51de3f-31e2-e611-80cc-1402ec7222b4" + }, + { + "baseType": "Date", + "dataSourceID": 3, + "dataSourceName": {}, + "dataType": "Date", + "description": "", + "localizedDescription": { + "value": "" + }, + "definitionID": "8051de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "OptInDate", + "definitionName": { + "value": "Opt In Date" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 20, + "fullyQualifiedName": "MobilePush Demographics.Opt In Date", + "isHidden": true, + "isIdentityValue": false, + "isNullable": true, + "isPrimaryKey": false, + "isReadOnly": true, + "isSystemDefined": true, + "isUpdateable": false, + "obfuscationProperties": { + "maskType": "None", + "maskTypeID": 0, + "storageTypeID": 1, + "storageType": "Plain", + "valueDefinitionID": "8051de3f-31e2-e611-80cc-1402ec7222b4" + }, + "ordinal": 20, + "parentDefinition": { + "definitionID": "6d51de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "PushDemographics", + "definitionName": { + "value": "MobilePush Demographics" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "_OptInDate", + "storageFieldReferenceID": { + "type": "guid", + "value": "68c6681d-6f0f-4ec2-9407-55c5eb19fc19" + }, + "valueDefinitionID": "8051de3f-31e2-e611-80cc-1402ec7222b4", + "valueDefinitionKey": "OptInDate", + "name": "Opt In Date", + "setDefinitionID": "6d51de3f-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "PushDemographics", + "setDefinitionName": { + "value": "MobilePush Demographics" + }, + "parentIdentifier": "6d51de3f-31e2-e611-80cc-1402ec7222b4" + }, + { + "baseType": "Numeric", + "dataSourceID": 3, + "dataSourceName": {}, + "dataType": "Byte", + "description": "", + "localizedDescription": { + "value": "" + }, + "definitionID": "8151de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "OptInMethodID", + "definitionName": { + "value": "Opt In Method" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 21, + "fullyQualifiedName": "MobilePush Demographics.Opt In Method", + "isHidden": true, + "isIdentityValue": false, + "isNullable": true, + "isPrimaryKey": false, + "isReadOnly": true, + "isSystemDefined": true, + "isUpdateable": false, + "obfuscationProperties": { + "maskType": "None", + "maskTypeID": 0, + "storageTypeID": 1, + "storageType": "Plain", + "valueDefinitionID": "8151de3f-31e2-e611-80cc-1402ec7222b4" + }, + "ordinal": 21, + "parentDefinition": { + "definitionID": "6d51de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "PushDemographics", + "definitionName": { + "value": "MobilePush Demographics" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "restrictionLookupListID": 9, + "storageName": "_OptInMethodID", + "storageFieldReferenceID": { + "type": "guid", + "value": "8b821a18-6cee-4204-9ef9-18d94112e84f" + }, + "valueDefinitionID": "8151de3f-31e2-e611-80cc-1402ec7222b4", + "valueDefinitionKey": "OptInMethodID", + "name": "Opt In Method", + "setDefinitionID": "6d51de3f-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "PushDemographics", + "setDefinitionName": { + "value": "MobilePush Demographics" + }, + "parentIdentifier": "6d51de3f-31e2-e611-80cc-1402ec7222b4" + }, + { + "baseType": "Numeric", + "dataSourceID": 3, + "dataSourceName": {}, + "dataType": "Byte", + "description": "", + "localizedDescription": { + "value": "" + }, + "definitionID": "8251de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "OptInStatusID", + "definitionName": { + "value": "Opt In Status" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 22, + "fullyQualifiedName": "MobilePush Demographics.Opt In Status", + "isHidden": true, + "isIdentityValue": false, + "isNullable": false, + "isPrimaryKey": false, + "isReadOnly": false, + "isSystemDefined": true, + "isUpdateable": false, + "obfuscationProperties": { + "maskType": "None", + "maskTypeID": 0, + "storageTypeID": 1, + "storageType": "Plain", + "valueDefinitionID": "8251de3f-31e2-e611-80cc-1402ec7222b4" + }, + "ordinal": 22, + "parentDefinition": { + "definitionID": "6d51de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "PushDemographics", + "definitionName": { + "value": "MobilePush Demographics" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "restrictionLookupListID": 8, + "storageName": "_OptInStatusID", + "storageFieldReferenceID": { + "type": "guid", + "value": "673470b8-8503-4c4c-b9ae-9bf554d0a235" + }, + "valueDefinitionID": "8251de3f-31e2-e611-80cc-1402ec7222b4", + "valueDefinitionKey": "OptInStatusID", + "name": "Opt In Status", + "setDefinitionID": "6d51de3f-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "PushDemographics", + "setDefinitionName": { + "value": "MobilePush Demographics" + }, + "parentIdentifier": "6d51de3f-31e2-e611-80cc-1402ec7222b4" + }, + { + "baseType": "Date", + "dataSourceID": 3, + "dataSourceName": {}, + "dataType": "Date", + "description": "", + "localizedDescription": { + "value": "" + }, + "definitionID": "8351de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "OptOutDate", + "definitionName": { + "value": "Opt Out Date" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 23, + "fullyQualifiedName": "MobilePush Demographics.Opt Out Date", + "isHidden": true, + "isIdentityValue": false, + "isNullable": true, + "isPrimaryKey": false, + "isReadOnly": true, + "isSystemDefined": true, + "isUpdateable": false, + "obfuscationProperties": { + "maskType": "None", + "maskTypeID": 0, + "storageTypeID": 1, + "storageType": "Plain", + "valueDefinitionID": "8351de3f-31e2-e611-80cc-1402ec7222b4" + }, + "ordinal": 23, + "parentDefinition": { + "definitionID": "6d51de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "PushDemographics", + "definitionName": { + "value": "MobilePush Demographics" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "_OptOutDate", + "storageFieldReferenceID": { + "type": "guid", + "value": "8424262e-6904-4915-a4b3-2957b044b3ee" + }, + "valueDefinitionID": "8351de3f-31e2-e611-80cc-1402ec7222b4", + "valueDefinitionKey": "OptOutDate", + "name": "Opt Out Date", + "setDefinitionID": "6d51de3f-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "PushDemographics", + "setDefinitionName": { + "value": "MobilePush Demographics" + }, + "parentIdentifier": "6d51de3f-31e2-e611-80cc-1402ec7222b4" + }, + { + "baseType": "Numeric", + "dataSourceID": 3, + "dataSourceName": {}, + "dataType": "Byte", + "description": "", + "localizedDescription": { + "value": "" + }, + "definitionID": "8451de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "OptOutMethodID", + "definitionName": { + "value": "Opt Out Method" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 24, + "fullyQualifiedName": "MobilePush Demographics.Opt Out Method", + "isHidden": true, + "isIdentityValue": false, + "isNullable": true, + "isPrimaryKey": false, + "isReadOnly": true, + "isSystemDefined": true, + "isUpdateable": false, + "obfuscationProperties": { + "maskType": "None", + "maskTypeID": 0, + "storageTypeID": 1, + "storageType": "Plain", + "valueDefinitionID": "8451de3f-31e2-e611-80cc-1402ec7222b4" + }, + "ordinal": 24, + "parentDefinition": { + "definitionID": "6d51de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "PushDemographics", + "definitionName": { + "value": "MobilePush Demographics" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "restrictionLookupListID": 10, + "storageName": "_OptOutMethodID", + "storageFieldReferenceID": { + "type": "guid", + "value": "3919bba5-e953-435d-8874-66be31cb1821" + }, + "valueDefinitionID": "8451de3f-31e2-e611-80cc-1402ec7222b4", + "valueDefinitionKey": "OptOutMethodID", + "name": "Opt Out Method", + "setDefinitionID": "6d51de3f-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "PushDemographics", + "setDefinitionName": { + "value": "MobilePush Demographics" + }, + "parentIdentifier": "6d51de3f-31e2-e611-80cc-1402ec7222b4" + }, + { + "baseType": "Numeric", + "dataSourceID": 3, + "dataSourceName": {}, + "dataType": "Byte", + "description": "", + "localizedDescription": { + "value": "" + }, + "definitionID": "8551de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "OptOutStatusID", + "definitionName": { + "value": "Opt Out Status" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 25, + "fullyQualifiedName": "MobilePush Demographics.Opt Out Status", + "isHidden": true, + "isIdentityValue": false, + "isNullable": true, + "isPrimaryKey": false, + "isReadOnly": true, + "isSystemDefined": true, + "isUpdateable": false, + "obfuscationProperties": { + "maskType": "None", + "maskTypeID": 0, + "storageTypeID": 1, + "storageType": "Plain", + "valueDefinitionID": "8551de3f-31e2-e611-80cc-1402ec7222b4" + }, + "ordinal": 25, + "parentDefinition": { + "definitionID": "6d51de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "PushDemographics", + "definitionName": { + "value": "MobilePush Demographics" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "_OptOutStatusID", + "storageFieldReferenceID": { + "type": "guid", + "value": "df789a9d-cfbc-4ed9-8a2b-e6427a631e28" + }, + "valueDefinitionID": "8551de3f-31e2-e611-80cc-1402ec7222b4", + "valueDefinitionKey": "OptOutStatusID", + "name": "Opt Out Status", + "setDefinitionID": "6d51de3f-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "PushDemographics", + "setDefinitionName": { + "value": "MobilePush Demographics" + }, + "parentIdentifier": "6d51de3f-31e2-e611-80cc-1402ec7222b4" + }, + { + "baseType": "Text", + "dataSourceID": 3, + "dataSourceName": {}, + "dataType": "Text", + "description": "", + "localizedDescription": { + "value": "" + }, + "definitionID": "8651de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "Platform", + "definitionName": { + "value": "Platform" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 26, + "fullyQualifiedName": "MobilePush Demographics.Platform", + "isHidden": false, + "isIdentityValue": false, + "isNullable": true, + "isPrimaryKey": false, + "isReadOnly": true, + "isSystemDefined": true, + "isUpdateable": false, + "length": 100, + "obfuscationProperties": { + "maskType": "None", + "maskTypeID": 0, + "storageTypeID": 1, + "storageType": "Plain", + "valueDefinitionID": "8651de3f-31e2-e611-80cc-1402ec7222b4" + }, + "ordinal": 26, + "parentDefinition": { + "definitionID": "6d51de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "PushDemographics", + "definitionName": { + "value": "MobilePush Demographics" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "_Platform", + "storageFieldReferenceID": { + "type": "guid", + "value": "353dc3ed-7578-4ee1-a1c1-e843f8b487f5" + }, + "valueDefinitionID": "8651de3f-31e2-e611-80cc-1402ec7222b4", + "valueDefinitionKey": "Platform", + "name": "Platform", + "setDefinitionID": "6d51de3f-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "PushDemographics", + "setDefinitionName": { + "value": "MobilePush Demographics" + }, + "parentIdentifier": "6d51de3f-31e2-e611-80cc-1402ec7222b4" + }, + { + "baseType": "Text", + "dataSourceID": 3, + "dataSourceName": {}, + "dataType": "Text", + "description": "", + "localizedDescription": { + "value": "" + }, + "definitionID": "8751de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "PlatformVersion", + "definitionName": { + "value": "Platform Version" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 27, + "fullyQualifiedName": "MobilePush Demographics.Platform Version", + "isHidden": false, + "isIdentityValue": false, + "isNullable": true, + "isPrimaryKey": false, + "isReadOnly": true, + "isSystemDefined": true, + "isUpdateable": false, + "length": 100, + "obfuscationProperties": { + "maskType": "None", + "maskTypeID": 0, + "storageTypeID": 1, + "storageType": "Plain", + "valueDefinitionID": "8751de3f-31e2-e611-80cc-1402ec7222b4" + }, + "ordinal": 27, + "parentDefinition": { + "definitionID": "6d51de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "PushDemographics", + "definitionName": { + "value": "MobilePush Demographics" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "_PlatformVersion", + "storageFieldReferenceID": { + "type": "guid", + "value": "99c03236-d908-498f-936a-6b7e110ef76a" + }, + "valueDefinitionID": "8751de3f-31e2-e611-80cc-1402ec7222b4", + "valueDefinitionKey": "PlatformVersion", + "name": "Platform Version", + "setDefinitionID": "6d51de3f-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "PushDemographics", + "setDefinitionName": { + "value": "MobilePush Demographics" + }, + "parentIdentifier": "6d51de3f-31e2-e611-80cc-1402ec7222b4" + }, + { + "baseType": "Text", + "dataSourceID": 3, + "dataSourceName": {}, + "dataType": "Text", + "description": "", + "localizedDescription": { + "value": "" + }, + "definitionID": "8851de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "ProviderToken", + "definitionName": { + "value": "Provider Token" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 28, + "fullyQualifiedName": "MobilePush Demographics.Provider Token", + "isHidden": true, + "isIdentityValue": false, + "isNullable": true, + "isPrimaryKey": false, + "isReadOnly": true, + "isSystemDefined": true, + "isUpdateable": false, + "length": 200, + "obfuscationProperties": { + "maskType": "None", + "maskTypeID": 0, + "storageTypeID": 1, + "storageType": "Plain", + "valueDefinitionID": "8851de3f-31e2-e611-80cc-1402ec7222b4" + }, + "ordinal": 28, + "parentDefinition": { + "definitionID": "6d51de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "PushDemographics", + "definitionName": { + "value": "MobilePush Demographics" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "_ProviderToken", + "storageFieldReferenceID": { + "type": "guid", + "value": "03b1ac7c-3cc4-4b82-b3db-7e6b43cefd7c" + }, + "valueDefinitionID": "8851de3f-31e2-e611-80cc-1402ec7222b4", + "valueDefinitionKey": "ProviderToken", + "name": "Provider Token", + "setDefinitionID": "6d51de3f-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "PushDemographics", + "setDefinitionName": { + "value": "MobilePush Demographics" + }, + "parentIdentifier": "6d51de3f-31e2-e611-80cc-1402ec7222b4" + }, + { + "baseType": "Numeric", + "dataSourceID": 3, + "dataSourceName": {}, + "dataType": "Byte", + "description": "", + "localizedDescription": { + "value": "" + }, + "definitionID": "8951de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "Source", + "definitionName": { + "value": "Source" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 29, + "fullyQualifiedName": "MobilePush Demographics.Source", + "isHidden": false, + "isIdentityValue": false, + "isNullable": true, + "isPrimaryKey": false, + "isReadOnly": true, + "isSystemDefined": true, + "isUpdateable": false, + "obfuscationProperties": { + "maskType": "None", + "maskTypeID": 0, + "storageTypeID": 1, + "storageType": "Plain", + "valueDefinitionID": "8951de3f-31e2-e611-80cc-1402ec7222b4" + }, + "ordinal": 29, + "parentDefinition": { + "definitionID": "6d51de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "PushDemographics", + "definitionName": { + "value": "MobilePush Demographics" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "restrictionLookupListID": 12, + "storageName": "_Source", + "storageFieldReferenceID": { + "type": "guid", + "value": "a0c5a9fe-d72b-41dd-9307-77db3da0b9f4" + }, + "valueDefinitionID": "8951de3f-31e2-e611-80cc-1402ec7222b4", + "valueDefinitionKey": "Source", + "name": "Source", + "setDefinitionID": "6d51de3f-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "PushDemographics", + "setDefinitionName": { + "value": "MobilePush Demographics" + }, + "parentIdentifier": "6d51de3f-31e2-e611-80cc-1402ec7222b4" + }, + { + "baseType": "Text", + "dataSourceID": 3, + "dataSourceName": {}, + "dataType": "Text", + "description": "", + "localizedDescription": { + "value": "" + }, + "definitionID": "8a51de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "SourceObjectID", + "definitionName": { + "value": "Source Object ID" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 30, + "fullyQualifiedName": "MobilePush Demographics.Source Object ID", + "isHidden": false, + "isIdentityValue": false, + "isNullable": true, + "isPrimaryKey": false, + "isReadOnly": true, + "isSystemDefined": true, + "isUpdateable": false, + "length": 200, + "obfuscationProperties": { + "maskType": "None", + "maskTypeID": 0, + "storageTypeID": 1, + "storageType": "Plain", + "valueDefinitionID": "8a51de3f-31e2-e611-80cc-1402ec7222b4" + }, + "ordinal": 30, + "parentDefinition": { + "definitionID": "6d51de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "PushDemographics", + "definitionName": { + "value": "MobilePush Demographics" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "_SourceObjectId", + "storageFieldReferenceID": { + "type": "guid", + "value": "020d90c4-4c9c-4a00-b661-5b75ec0c9b88" + }, + "valueDefinitionID": "8a51de3f-31e2-e611-80cc-1402ec7222b4", + "valueDefinitionKey": "SourceObjectID", + "name": "Source Object ID", + "setDefinitionID": "6d51de3f-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "PushDemographics", + "setDefinitionName": { + "value": "MobilePush Demographics" + }, + "parentIdentifier": "6d51de3f-31e2-e611-80cc-1402ec7222b4" + }, + { + "baseType": "Text", + "dataSourceID": 3, + "dataSourceName": {}, + "dataType": "Text", + "description": "", + "localizedDescription": { + "value": "" + }, + "definitionID": "8b51de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "State", + "definitionName": { + "value": "State" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 31, + "fullyQualifiedName": "MobilePush Demographics.State", + "isHidden": false, + "isIdentityValue": false, + "isNullable": true, + "isPrimaryKey": false, + "isReadOnly": false, + "isSystemDefined": false, + "isUpdateable": false, + "length": 200, + "obfuscationProperties": { + "maskType": "None", + "maskTypeID": 0, + "storageTypeID": 1, + "storageType": "Plain", + "valueDefinitionID": "8b51de3f-31e2-e611-80cc-1402ec7222b4" + }, + "ordinal": 31, + "parentDefinition": { + "definitionID": "6d51de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "PushDemographics", + "definitionName": { + "value": "MobilePush Demographics" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "_State", + "storageFieldReferenceID": { + "type": "guid", + "value": "e65c52fd-e623-45cc-bb7a-1842617c5491" + }, + "valueDefinitionID": "8b51de3f-31e2-e611-80cc-1402ec7222b4", + "valueDefinitionKey": "State", + "name": "State", + "setDefinitionID": "6d51de3f-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "PushDemographics", + "setDefinitionName": { + "value": "MobilePush Demographics" + }, + "parentIdentifier": "6d51de3f-31e2-e611-80cc-1402ec7222b4" + }, + { + "baseType": "Numeric", + "dataSourceID": 3, + "dataSourceName": {}, + "dataType": "Byte", + "description": "", + "localizedDescription": { + "value": "" + }, + "definitionID": "8c51de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "Status", + "definitionName": { + "value": "Status" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 32, + "fullyQualifiedName": "MobilePush Demographics.Status", + "isHidden": false, + "isIdentityValue": false, + "isNullable": true, + "isPrimaryKey": false, + "isReadOnly": false, + "isSystemDefined": true, + "isUpdateable": false, + "obfuscationProperties": { + "maskType": "None", + "maskTypeID": 0, + "storageTypeID": 1, + "storageType": "Plain", + "valueDefinitionID": "8c51de3f-31e2-e611-80cc-1402ec7222b4" + }, + "ordinal": 32, + "parentDefinition": { + "definitionID": "6d51de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "PushDemographics", + "definitionName": { + "value": "MobilePush Demographics" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "restrictionLookupListID": 13, + "storageName": "_Status", + "storageFieldReferenceID": { + "type": "guid", + "value": "a1c13a7c-566e-487f-8cc9-439064b6bfb4" + }, + "valueDefinitionID": "8c51de3f-31e2-e611-80cc-1402ec7222b4", + "valueDefinitionKey": "Status", + "name": "Status", + "setDefinitionID": "6d51de3f-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "PushDemographics", + "setDefinitionName": { + "value": "MobilePush Demographics" + }, + "parentIdentifier": "6d51de3f-31e2-e611-80cc-1402ec7222b4" + }, + { + "baseType": "Text", + "dataSourceID": 3, + "dataSourceName": {}, + "dataType": "Text", + "description": "", + "localizedDescription": { + "value": "" + }, + "definitionID": "8d51de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "SystemToken", + "definitionName": { + "value": "System Token" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 33, + "fullyQualifiedName": "MobilePush Demographics.System Token", + "isHidden": false, + "isIdentityValue": false, + "isNullable": true, + "isPrimaryKey": false, + "isReadOnly": true, + "isSystemDefined": true, + "isUpdateable": false, + "length": 4000, + "obfuscationProperties": { + "maskType": "None", + "maskTypeID": 0, + "storageTypeID": 1, + "storageType": "Plain", + "valueDefinitionID": "8d51de3f-31e2-e611-80cc-1402ec7222b4" + }, + "ordinal": 33, + "parentDefinition": { + "definitionID": "6d51de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "PushDemographics", + "definitionName": { + "value": "MobilePush Demographics" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "_SystemToken", + "storageFieldReferenceID": { + "type": "guid", + "value": "d7e80e54-124c-4260-986b-b32b58b8c0ee" + }, + "valueDefinitionID": "8d51de3f-31e2-e611-80cc-1402ec7222b4", + "valueDefinitionKey": "SystemToken", + "name": "System Token", + "setDefinitionID": "6d51de3f-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "PushDemographics", + "setDefinitionName": { + "value": "MobilePush Demographics" + }, + "parentIdentifier": "6d51de3f-31e2-e611-80cc-1402ec7222b4" + }, + { + "baseType": "Text", + "dataSourceID": 3, + "dataSourceName": {}, + "dataType": "Text", + "description": "", + "localizedDescription": { + "value": "" + }, + "definitionID": "8e51de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "TimeZone", + "definitionName": { + "value": "Time Zone" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 34, + "fullyQualifiedName": "MobilePush Demographics.Time Zone", + "isHidden": false, + "isIdentityValue": false, + "isNullable": true, + "isPrimaryKey": false, + "isReadOnly": true, + "isSystemDefined": true, + "isUpdateable": false, + "length": 50, + "obfuscationProperties": { + "maskType": "None", + "maskTypeID": 0, + "storageTypeID": 1, + "storageType": "Plain", + "valueDefinitionID": "8e51de3f-31e2-e611-80cc-1402ec7222b4" + }, + "ordinal": 34, + "parentDefinition": { + "definitionID": "6d51de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "PushDemographics", + "definitionName": { + "value": "MobilePush Demographics" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "_TimeZone", + "storageFieldReferenceID": { + "type": "guid", + "value": "980d0010-a443-4044-9ca1-5d1cfeaedec7" + }, + "valueDefinitionID": "8e51de3f-31e2-e611-80cc-1402ec7222b4", + "valueDefinitionKey": "TimeZone", + "name": "Time Zone", + "setDefinitionID": "6d51de3f-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "PushDemographics", + "setDefinitionName": { + "value": "MobilePush Demographics" + }, + "parentIdentifier": "6d51de3f-31e2-e611-80cc-1402ec7222b4" + }, + { + "baseType": "Numeric", + "dataSourceID": 3, + "dataSourceName": {}, + "dataType": "Decimal", + "description": "", + "localizedDescription": { + "value": "" + }, + "definitionID": "8f51de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "UTCOffset", + "definitionName": { + "value": "UTC Offset" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 35, + "fullyQualifiedName": "MobilePush Demographics.UTC Offset", + "isHidden": false, + "isIdentityValue": false, + "isNullable": true, + "isPrimaryKey": false, + "isReadOnly": false, + "isSystemDefined": true, + "isUpdateable": false, + "length": 4, + "obfuscationProperties": { + "maskType": "None", + "maskTypeID": 0, + "storageTypeID": 1, + "storageType": "Plain", + "valueDefinitionID": "8f51de3f-31e2-e611-80cc-1402ec7222b4" + }, + "ordinal": 35, + "parentDefinition": { + "definitionID": "6d51de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "PushDemographics", + "definitionName": { + "value": "MobilePush Demographics" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "scale": 2, + "storageName": "_UTCOffset", + "storageFieldReferenceID": { + "type": "guid", + "value": "5c7c2a61-80da-4233-b895-54fd7e957e48" + }, + "valueDefinitionID": "8f51de3f-31e2-e611-80cc-1402ec7222b4", + "valueDefinitionKey": "UTCOffset", + "name": "UTC Offset", + "setDefinitionID": "6d51de3f-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "PushDemographics", + "setDefinitionName": { + "value": "MobilePush Demographics" + }, + "parentIdentifier": "6d51de3f-31e2-e611-80cc-1402ec7222b4" + }, + { + "baseType": "Text", + "dataSourceID": 3, + "dataSourceName": {}, + "dataType": "Text", + "description": "", + "localizedDescription": { + "value": "" + }, + "definitionID": "9051de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "ZipCode", + "definitionName": { + "value": "Zip Code" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 36, + "fullyQualifiedName": "MobilePush Demographics.Zip Code", + "isHidden": false, + "isIdentityValue": false, + "isNullable": true, + "isPrimaryKey": false, + "isReadOnly": false, + "isSystemDefined": false, + "isUpdateable": false, + "length": 20, + "obfuscationProperties": { + "maskType": "None", + "maskTypeID": 0, + "storageTypeID": 1, + "storageType": "Plain", + "valueDefinitionID": "9051de3f-31e2-e611-80cc-1402ec7222b4" + }, + "ordinal": 36, + "parentDefinition": { + "definitionID": "6d51de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "PushDemographics", + "definitionName": { + "value": "MobilePush Demographics" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "_ZipCode", + "storageFieldReferenceID": { + "type": "guid", + "value": "ac282849-4bc1-4373-8412-16a5d9ab31e4" + }, + "valueDefinitionID": "9051de3f-31e2-e611-80cc-1402ec7222b4", + "valueDefinitionKey": "ZipCode", + "name": "Zip Code", + "setDefinitionID": "6d51de3f-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "PushDemographics", + "setDefinitionName": { + "value": "MobilePush Demographics" + }, + "parentIdentifier": "6d51de3f-31e2-e611-80cc-1402ec7222b4" + }, + { + "baseType": "Numeric", + "dataSourceID": 3, + "dataSourceName": {}, + "dataType": "Number", + "description": "", + "localizedDescription": { + "value": "" + }, + "definitionID": "08b0ae24-ee46-ea11-a2e0-1402ec94ec41", + "definitionKey": "PushAddressExtensionID", + "definitionName": { + "value": "Push Address Extension ID" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 37, + "fullyQualifiedName": "MobilePush Demographics.Push Address Extension ID", + "isHidden": true, + "isIdentityValue": true, + "isNullable": true, + "isPrimaryKey": false, + "isReadOnly": true, + "isSystemDefined": true, + "isUpdateable": false, + "ordinal": 37, + "parentDefinition": { + "definitionID": "6d51de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "PushDemographics", + "definitionName": { + "value": "MobilePush Demographics" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "PushAddressExtensionId", + "valueDefinitionID": "08b0ae24-ee46-ea11-a2e0-1402ec94ec41", + "valueDefinitionKey": "PushAddressExtensionID", + "name": "Push Address Extension ID", + "setDefinitionID": "6d51de3f-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "PushDemographics", + "setDefinitionName": { + "value": "MobilePush Demographics" + }, + "parentIdentifier": "6d51de3f-31e2-e611-80cc-1402ec7222b4" + }, + { + "baseType": "Text", + "dataSourceID": 3, + "dataSourceName": {}, + "dataType": "Text", + "description": "", + "localizedDescription": { + "value": "" + }, + "definitionID": "09b0ae24-ee46-ea11-a2e0-1402ec94ec41", + "definitionKey": "DeviceLanguage", + "definitionName": { + "value": "Device Language" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 38, + "fullyQualifiedName": "MobilePush Demographics.Device Language", + "isHidden": false, + "isIdentityValue": false, + "isNullable": true, + "isPrimaryKey": false, + "isReadOnly": true, + "isSystemDefined": true, + "isUpdateable": false, + "length": -1, + "ordinal": 38, + "parentDefinition": { + "definitionID": "6d51de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "PushDemographics", + "definitionName": { + "value": "MobilePush Demographics" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "DeviceLanguage", + "valueDefinitionID": "09b0ae24-ee46-ea11-a2e0-1402ec94ec41", + "valueDefinitionKey": "DeviceLanguage", + "name": "Device Language", + "setDefinitionID": "6d51de3f-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "PushDemographics", + "setDefinitionName": { + "value": "MobilePush Demographics" + }, + "parentIdentifier": "6d51de3f-31e2-e611-80cc-1402ec7222b4" + }, + { + "baseType": "Text", + "dataSourceID": 3, + "dataSourceName": {}, + "dataType": "Text", + "description": "", + "localizedDescription": { + "value": "" + }, + "definitionID": "0ab0ae24-ee46-ea11-a2e0-1402ec94ec41", + "definitionKey": "GcmSenderId", + "definitionName": { + "value": "GCM Sender ID" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 39, + "fullyQualifiedName": "MobilePush Demographics.GCM Sender ID", + "isHidden": false, + "isIdentityValue": false, + "isNullable": true, + "isPrimaryKey": false, + "isReadOnly": true, + "isSystemDefined": true, + "isUpdateable": false, + "length": -1, + "ordinal": 39, + "parentDefinition": { + "definitionID": "6d51de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "PushDemographics", + "definitionName": { + "value": "MobilePush Demographics" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "GcmSenderId", + "valueDefinitionID": "0ab0ae24-ee46-ea11-a2e0-1402ec94ec41", + "valueDefinitionKey": "GcmSenderId", + "name": "GCM Sender ID", + "setDefinitionID": "6d51de3f-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "PushDemographics", + "setDefinitionName": { + "value": "MobilePush Demographics" + }, + "parentIdentifier": "6d51de3f-31e2-e611-80cc-1402ec7222b4" + }, + { + "baseType": "Text", + "dataSourceID": 3, + "dataSourceName": {}, + "dataType": "Text", + "description": "", + "localizedDescription": { + "value": "" + }, + "definitionID": "0bb0ae24-ee46-ea11-a2e0-1402ec94ec41", + "definitionKey": "AppVersion", + "definitionName": { + "value": "Application Version" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 40, + "fullyQualifiedName": "MobilePush Demographics.Application Version", + "isHidden": false, + "isIdentityValue": false, + "isNullable": true, + "isPrimaryKey": false, + "isReadOnly": true, + "isSystemDefined": true, + "isUpdateable": false, + "length": -1, + "ordinal": 40, + "parentDefinition": { + "definitionID": "6d51de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "PushDemographics", + "definitionName": { + "value": "MobilePush Demographics" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "AppVersion", + "valueDefinitionID": "0bb0ae24-ee46-ea11-a2e0-1402ec94ec41", + "valueDefinitionKey": "AppVersion", + "name": "Application Version", + "setDefinitionID": "6d51de3f-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "PushDemographics", + "setDefinitionName": { + "value": "MobilePush Demographics" + }, + "parentIdentifier": "6d51de3f-31e2-e611-80cc-1402ec7222b4" + }, + { + "baseType": "Text", + "dataSourceID": 3, + "dataSourceName": {}, + "dataType": "Text", + "description": "", + "localizedDescription": { + "value": "" + }, + "definitionID": "0cb0ae24-ee46-ea11-a2e0-1402ec94ec41", + "definitionKey": "SdkVersion", + "definitionName": { + "value": "SDK Version" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 41, + "fullyQualifiedName": "MobilePush Demographics.SDK Version", + "isHidden": false, + "isIdentityValue": false, + "isNullable": true, + "isPrimaryKey": false, + "isReadOnly": true, + "isSystemDefined": true, + "isUpdateable": false, + "length": -1, + "ordinal": 41, + "parentDefinition": { + "definitionID": "6d51de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "PushDemographics", + "definitionName": { + "value": "MobilePush Demographics" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "SdkVersion", + "valueDefinitionID": "0cb0ae24-ee46-ea11-a2e0-1402ec94ec41", + "valueDefinitionKey": "SdkVersion", + "name": "SDK Version", + "setDefinitionID": "6d51de3f-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "PushDemographics", + "setDefinitionName": { + "value": "MobilePush Demographics" + }, + "parentIdentifier": "6d51de3f-31e2-e611-80cc-1402ec7222b4" + }, + { + "baseType": "Date", + "dataSourceID": 3, + "dataSourceName": {}, + "dataType": "Date", + "description": "", + "localizedDescription": { + "value": "" + }, + "definitionID": "0db0ae24-ee46-ea11-a2e0-1402ec94ec41", + "definitionKey": "LastAppOpen", + "definitionName": { + "value": "Last Application Open" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 42, + "fullyQualifiedName": "MobilePush Demographics.Last Application Open", + "isHidden": false, + "isIdentityValue": false, + "isNullable": true, + "isPrimaryKey": false, + "isReadOnly": true, + "isSystemDefined": true, + "isUpdateable": false, + "ordinal": 42, + "parentDefinition": { + "definitionID": "6d51de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "PushDemographics", + "definitionName": { + "value": "MobilePush Demographics" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "LastAppOpen", + "valueDefinitionID": "0db0ae24-ee46-ea11-a2e0-1402ec94ec41", + "valueDefinitionKey": "LastAppOpen", + "name": "Last Application Open", + "setDefinitionID": "6d51de3f-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "PushDemographics", + "setDefinitionName": { + "value": "MobilePush Demographics" + }, + "parentIdentifier": "6d51de3f-31e2-e611-80cc-1402ec7222b4" + }, + { + "baseType": "Date", + "dataSourceID": 3, + "dataSourceName": {}, + "dataType": "Date", + "description": "", + "localizedDescription": { + "value": "" + }, + "definitionID": "0eb0ae24-ee46-ea11-a2e0-1402ec94ec41", + "definitionKey": "LastMessageOpen", + "definitionName": { + "value": "Last Message Open" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 43, + "fullyQualifiedName": "MobilePush Demographics.Last Message Open", + "isHidden": false, + "isIdentityValue": false, + "isNullable": true, + "isPrimaryKey": false, + "isReadOnly": true, + "isSystemDefined": true, + "isUpdateable": false, + "ordinal": 43, + "parentDefinition": { + "definitionID": "6d51de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "PushDemographics", + "definitionName": { + "value": "MobilePush Demographics" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "LastMessageOpen", + "valueDefinitionID": "0eb0ae24-ee46-ea11-a2e0-1402ec94ec41", + "valueDefinitionKey": "LastMessageOpen", + "name": "Last Message Open", + "setDefinitionID": "6d51de3f-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "PushDemographics", + "setDefinitionName": { + "value": "MobilePush Demographics" + }, + "parentIdentifier": "6d51de3f-31e2-e611-80cc-1402ec7222b4" + }, + { + "baseType": "Date", + "dataSourceID": 3, + "dataSourceName": {}, + "dataType": "Date", + "description": "", + "localizedDescription": { + "value": "" + }, + "definitionID": "0fb0ae24-ee46-ea11-a2e0-1402ec94ec41", + "definitionKey": "LastSend", + "definitionName": { + "value": "Last Send" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 44, + "fullyQualifiedName": "MobilePush Demographics.Last Send", + "isHidden": false, + "isIdentityValue": false, + "isNullable": true, + "isPrimaryKey": false, + "isReadOnly": true, + "isSystemDefined": true, + "isUpdateable": false, + "ordinal": 44, + "parentDefinition": { + "definitionID": "6d51de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "PushDemographics", + "definitionName": { + "value": "MobilePush Demographics" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "LastSend", + "valueDefinitionID": "0fb0ae24-ee46-ea11-a2e0-1402ec94ec41", + "valueDefinitionKey": "LastSend", + "name": "Last Send", + "setDefinitionID": "6d51de3f-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "PushDemographics", + "setDefinitionName": { + "value": "MobilePush Demographics" + }, + "parentIdentifier": "6d51de3f-31e2-e611-80cc-1402ec7222b4" + }, + { + "baseType": "Numeric", + "dataSourceID": 3, + "dataSourceName": {}, + "dataType": "Number", + "description": "", + "localizedDescription": { + "value": "" + }, + "definitionID": "10b0ae24-ee46-ea11-a2e0-1402ec94ec41", + "definitionKey": "SendCount", + "definitionName": { + "value": "Send Count" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 45, + "fullyQualifiedName": "MobilePush Demographics.Send Count", + "isHidden": false, + "isIdentityValue": false, + "isNullable": true, + "isPrimaryKey": false, + "isReadOnly": true, + "isSystemDefined": true, + "isUpdateable": false, + "ordinal": 45, + "parentDefinition": { + "definitionID": "6d51de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "PushDemographics", + "definitionName": { + "value": "MobilePush Demographics" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "SendCount", + "valueDefinitionID": "10b0ae24-ee46-ea11-a2e0-1402ec94ec41", + "valueDefinitionKey": "SendCount", + "name": "Send Count", + "setDefinitionID": "6d51de3f-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "PushDemographics", + "setDefinitionName": { + "value": "MobilePush Demographics" + }, + "parentIdentifier": "6d51de3f-31e2-e611-80cc-1402ec7222b4" + }, + { + "baseType": "Numeric", + "dataSourceID": 3, + "dataSourceName": {}, + "dataType": "Number", + "description": "", + "localizedDescription": { + "value": "" + }, + "definitionID": "11b0ae24-ee46-ea11-a2e0-1402ec94ec41", + "definitionKey": "MessageOpenCount", + "definitionName": { + "value": "Message Open Count" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 46, + "fullyQualifiedName": "MobilePush Demographics.Message Open Count", + "isHidden": false, + "isIdentityValue": false, + "isNullable": true, + "isPrimaryKey": false, + "isReadOnly": true, + "isSystemDefined": true, + "isUpdateable": false, + "ordinal": 46, + "parentDefinition": { + "definitionID": "6d51de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "PushDemographics", + "definitionName": { + "value": "MobilePush Demographics" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "MessageOpenCount", + "valueDefinitionID": "11b0ae24-ee46-ea11-a2e0-1402ec94ec41", + "valueDefinitionKey": "MessageOpenCount", + "name": "Message Open Count", + "setDefinitionID": "6d51de3f-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "PushDemographics", + "setDefinitionName": { + "value": "MobilePush Demographics" + }, + "parentIdentifier": "6d51de3f-31e2-e611-80cc-1402ec7222b4" + }, + { + "baseType": "Boolean", + "dataSourceID": 3, + "dataSourceName": {}, + "dataType": "Boolean", + "description": "", + "localizedDescription": { + "value": "" + }, + "definitionID": "12b0ae24-ee46-ea11-a2e0-1402ec94ec41", + "definitionKey": "ProximityEnabled", + "definitionName": { + "value": "Proximity Enabled" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 47, + "fullyQualifiedName": "MobilePush Demographics.Proximity Enabled", + "isHidden": false, + "isIdentityValue": false, + "isNullable": true, + "isPrimaryKey": false, + "isReadOnly": true, + "isSystemDefined": true, + "isUpdateable": false, + "ordinal": 47, + "parentDefinition": { + "definitionID": "6d51de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "PushDemographics", + "definitionName": { + "value": "MobilePush Demographics" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "ProximityEnabled", + "valueDefinitionID": "12b0ae24-ee46-ea11-a2e0-1402ec94ec41", + "valueDefinitionKey": "ProximityEnabled", + "name": "Proximity Enabled", + "setDefinitionID": "6d51de3f-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "PushDemographics", + "setDefinitionName": { + "value": "MobilePush Demographics" + }, + "parentIdentifier": "6d51de3f-31e2-e611-80cc-1402ec7222b4" + }, + { + "baseType": "Boolean", + "dataSourceID": 3, + "dataSourceName": {}, + "dataType": "Boolean", + "description": "", + "localizedDescription": { + "value": "" + }, + "definitionID": "13b0ae24-ee46-ea11-a2e0-1402ec94ec41", + "definitionKey": "BackgroundRefreshEnabled", + "definitionName": { + "value": "Background Refresh Enabled" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 48, + "fullyQualifiedName": "MobilePush Demographics.Background Refresh Enabled", + "isHidden": false, + "isIdentityValue": false, + "isNullable": true, + "isPrimaryKey": false, + "isReadOnly": true, + "isSystemDefined": true, + "isUpdateable": false, + "ordinal": 48, + "parentDefinition": { + "definitionID": "6d51de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "PushDemographics", + "definitionName": { + "value": "MobilePush Demographics" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "BackgroundRefreshEnabled", + "valueDefinitionID": "13b0ae24-ee46-ea11-a2e0-1402ec94ec41", + "valueDefinitionKey": "BackgroundRefreshEnabled", + "name": "Background Refresh Enabled", + "setDefinitionID": "6d51de3f-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "PushDemographics", + "setDefinitionName": { + "value": "MobilePush Demographics" + }, + "parentIdentifier": "6d51de3f-31e2-e611-80cc-1402ec7222b4" + }, + { + "baseType": "Boolean", + "dataSourceID": 3, + "dataSourceName": {}, + "dataType": "Boolean", + "description": "", + "localizedDescription": { + "value": "" + }, + "definitionID": "14b0ae24-ee46-ea11-a2e0-1402ec94ec41", + "definitionKey": "QuietPushEnabled", + "definitionName": { + "value": "Quiet Push Enabled" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 49, + "fullyQualifiedName": "MobilePush Demographics.Quiet Push Enabled", + "isHidden": false, + "isIdentityValue": false, + "isNullable": true, + "isPrimaryKey": false, + "isReadOnly": true, + "isSystemDefined": true, + "isUpdateable": false, + "ordinal": 49, + "parentDefinition": { + "definitionID": "6d51de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "PushDemographics", + "definitionName": { + "value": "MobilePush Demographics" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "QuietPushEnabled", + "valueDefinitionID": "14b0ae24-ee46-ea11-a2e0-1402ec94ec41", + "valueDefinitionKey": "QuietPushEnabled", + "name": "Quiet Push Enabled", + "setDefinitionID": "6d51de3f-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "PushDemographics", + "setDefinitionName": { + "value": "MobilePush Demographics" + }, + "parentIdentifier": "6d51de3f-31e2-e611-80cc-1402ec7222b4" + } + ], + "applicationID": "2051892d-5de2-4ecf-98af-8ca9a40d2c9c", + "applicationKey": "com.exacttarget.mobilepush", + "attributeCount": 0, + "canAddValues": true, + "canChangeValues": true, + "canModify": false, + "canRemove": false, + "categoryID": 2, + "createdBy": -1000, + "createDate": "2017-01-24T06:33:00", + "customObjectOwnerMID": 1111111, + "dataRetentionProperties": { + "isRowBasedRetention": false, + "isResetRetentionPeriodOnImport": false, + "isDeleteAtEndOfRetentionPeriod": false, + "setDefinitionID": "6d51de3f-31e2-e611-80cc-1402ec7222b4" + }, + "localizedDescription": {}, + "fullyQualifiedName": "MobilePush Demographics", + "isCustomObjectBacked": true, + "isEvent": false, + "isHidden": false, + "isReadOnly": false, + "isRoot": false, + "isSendable": true, + "isShared": false, + "isSystemDefined": true, + "isTestaable": false, + "parentID": "00000000-0000-0000-0000-000000000000", + "relationshipCount": 3, + "sendAttributeStorageName": "_ContactID", + "sendContactKeyStorageName": "_SubscriberID", + "storageLogicalType": "PushAttributes", + "storageName": "_PushAddress", + "storageObjectIDs": [ + "4851de3f-31e2-e611-80cc-1402ec7222b4", + "9552de3f-31e2-e611-80cc-1402ec7222b4" + ], + "storageReferenceID": { + "type": "guid", + "value": "7893dc39-31e2-e611-80cc-1402ec7222b4" + }, + "setDefinitionID": "6d51de3f-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "PushDemographics", + "name": "MobilePush Demographics" + }, + { + "definitionID": "7586d645-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "PredictiveIntelSessionEnds", + "definitionName": { + "value": "Predictive Intelligence Session Ends" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "valueDefinitions": [ + { + "baseType": "Numeric", + "dataSourceID": 1, + "dataSourceName": {}, + "dataType": "LongNumber", + "description": "", + "localizedDescription": { + "value": "" + }, + "definitionID": "7b86d645-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "Custom_Object_Key", + "definitionName": { + "value": "Custom Object Key" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 1, + "fullyQualifiedName": "Predictive Intelligence Session Ends.Custom Object Key", + "isHidden": true, + "isIdentityValue": true, + "isNullable": false, + "isPrimaryKey": false, + "isReadOnly": true, + "isSystemDefined": true, + "isUpdateable": false, + "ordinal": 1, + "parentDefinition": { + "definitionID": "7586d645-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "PredictiveIntelSessionEnds", + "definitionName": { + "value": "Predictive Intelligence Session Ends" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "_CustomObjectKey", + "valueDefinitionID": "7b86d645-31e2-e611-80cc-1402ec7222b4", + "valueDefinitionKey": "Custom_Object_Key", + "name": "Custom Object Key", + "setDefinitionID": "7586d645-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "PredictiveIntelSessionEnds", + "setDefinitionName": { + "value": "Predictive Intelligence Session Ends" + }, + "parentIdentifier": "7586d645-31e2-e611-80cc-1402ec7222b4" + }, + { + "baseType": "Text", + "dataSourceID": 5, + "dataSourceName": {}, + "dataType": "Text", + "description": "user_id", + "localizedDescription": { + "value": "user_id" + }, + "definitionID": "7a86d645-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "user_id", + "definitionName": { + "value": "User Id" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 2, + "fullyQualifiedName": "Predictive Intelligence Session Ends.User Id", + "isHidden": false, + "isIdentityValue": false, + "isNullable": false, + "isPrimaryKey": false, + "isReadOnly": true, + "isSystemDefined": true, + "isUpdateable": false, + "length": 256, + "obfuscationProperties": { + "maskType": "None", + "maskTypeID": 0, + "storageTypeID": 1, + "storageType": "Plain", + "valueDefinitionID": "7a86d645-31e2-e611-80cc-1402ec7222b4" + }, + "ordinal": 2, + "parentDefinition": { + "definitionID": "7586d645-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "PredictiveIntelSessionEnds", + "definitionName": { + "value": "Predictive Intelligence Session Ends" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "user_id", + "storageFieldReferenceID": { + "type": "guid", + "value": "037a4978-3ce8-4311-95c3-b59d2e3f1a7f" + }, + "valueDefinitionID": "7a86d645-31e2-e611-80cc-1402ec7222b4", + "valueDefinitionKey": "user_id", + "name": "User Id", + "setDefinitionID": "7586d645-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "PredictiveIntelSessionEnds", + "setDefinitionName": { + "value": "Predictive Intelligence Session Ends" + }, + "parentIdentifier": "7586d645-31e2-e611-80cc-1402ec7222b4" + }, + { + "baseType": "Text", + "dataSourceID": 5, + "dataSourceName": {}, + "dataType": "Text", + "description": "session_id", + "localizedDescription": { + "value": "session_id" + }, + "definitionID": "7886d645-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "session_id", + "definitionName": { + "value": "Session Id" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 3, + "fullyQualifiedName": "Predictive Intelligence Session Ends.Session Id", + "isHidden": false, + "isIdentityValue": false, + "isNullable": false, + "isPrimaryKey": true, + "isReadOnly": true, + "isSystemDefined": true, + "isUpdateable": false, + "length": 256, + "obfuscationProperties": { + "maskType": "None", + "maskTypeID": 0, + "storageTypeID": 1, + "storageType": "Plain", + "valueDefinitionID": "7886d645-31e2-e611-80cc-1402ec7222b4" + }, + "ordinal": 3, + "parentDefinition": { + "definitionID": "7586d645-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "PredictiveIntelSessionEnds", + "definitionName": { + "value": "Predictive Intelligence Session Ends" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "session_id", + "storageFieldReferenceID": { + "type": "guid", + "value": "67b9fcff-4136-4b07-b5f6-e86d616e4136" + }, + "valueDefinitionID": "7886d645-31e2-e611-80cc-1402ec7222b4", + "valueDefinitionKey": "session_id", + "name": "Session Id", + "setDefinitionID": "7586d645-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "PredictiveIntelSessionEnds", + "setDefinitionName": { + "value": "Predictive Intelligence Session Ends" + }, + "parentIdentifier": "7586d645-31e2-e611-80cc-1402ec7222b4" + }, + { + "baseType": "Text", + "dataSourceID": 5, + "dataSourceName": {}, + "dataType": "Text", + "description": "email_address", + "localizedDescription": { + "value": "email_address" + }, + "definitionID": "7786d645-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "email_address", + "definitionName": { + "value": "Email Address" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 4, + "fullyQualifiedName": "Predictive Intelligence Session Ends.Email Address", + "isHidden": false, + "isIdentityValue": false, + "isNullable": true, + "isPrimaryKey": false, + "isReadOnly": true, + "isSystemDefined": true, + "isUpdateable": false, + "length": 256, + "obfuscationProperties": { + "maskType": "None", + "maskTypeID": 0, + "storageTypeID": 1, + "storageType": "Plain", + "valueDefinitionID": "7786d645-31e2-e611-80cc-1402ec7222b4" + }, + "ordinal": 4, + "parentDefinition": { + "definitionID": "7586d645-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "PredictiveIntelSessionEnds", + "definitionName": { + "value": "Predictive Intelligence Session Ends" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "email_address", + "storageFieldReferenceID": { + "type": "guid", + "value": "8f1bc9c8-32a3-4b54-83aa-ffb6e56ec709" + }, + "valueDefinitionID": "7786d645-31e2-e611-80cc-1402ec7222b4", + "valueDefinitionKey": "email_address", + "name": "Email Address", + "setDefinitionID": "7586d645-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "PredictiveIntelSessionEnds", + "setDefinitionName": { + "value": "Predictive Intelligence Session Ends" + }, + "parentIdentifier": "7586d645-31e2-e611-80cc-1402ec7222b4" + }, + { + "baseType": "Text", + "dataSourceID": 5, + "dataSourceName": {}, + "dataType": "Text", + "description": "contact_key", + "localizedDescription": { + "value": "contact_key" + }, + "definitionID": "7686d645-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "contact_key", + "definitionName": { + "value": "Contact Key" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 5, + "fullyQualifiedName": "Predictive Intelligence Session Ends.Contact Key", + "isHidden": false, + "isIdentityValue": false, + "isNullable": true, + "isPrimaryKey": false, + "isReadOnly": true, + "isSystemDefined": true, + "isUpdateable": false, + "length": 256, + "obfuscationProperties": { + "maskType": "None", + "maskTypeID": 0, + "storageTypeID": 1, + "storageType": "Plain", + "valueDefinitionID": "7686d645-31e2-e611-80cc-1402ec7222b4" + }, + "ordinal": 5, + "parentDefinition": { + "definitionID": "7586d645-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "PredictiveIntelSessionEnds", + "definitionName": { + "value": "Predictive Intelligence Session Ends" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "contact_key", + "storageFieldReferenceID": { + "type": "guid", + "value": "0dc0b53e-ce26-4508-89b2-f9cb0ab8404a" + }, + "valueDefinitionID": "7686d645-31e2-e611-80cc-1402ec7222b4", + "valueDefinitionKey": "contact_key", + "name": "Contact Key", + "setDefinitionID": "7586d645-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "PredictiveIntelSessionEnds", + "setDefinitionName": { + "value": "Predictive Intelligence Session Ends" + }, + "parentIdentifier": "7586d645-31e2-e611-80cc-1402ec7222b4" + }, + { + "baseType": "Date", + "dataSourceID": 5, + "dataSourceName": {}, + "dataType": "Date", + "defaultValue": "getdate()", + "description": "timestamp", + "localizedDescription": { + "value": "timestamp" + }, + "definitionID": "7986d645-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "timestamp", + "definitionName": { + "value": "Time stamp" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 6, + "fullyQualifiedName": "Predictive Intelligence Session Ends.Time stamp", + "isHidden": false, + "isIdentityValue": false, + "isNullable": false, + "isPrimaryKey": false, + "isReadOnly": true, + "isSystemDefined": true, + "isUpdateable": false, + "obfuscationProperties": { + "maskType": "None", + "maskTypeID": 0, + "storageTypeID": 1, + "storageType": "Plain", + "valueDefinitionID": "7986d645-31e2-e611-80cc-1402ec7222b4" + }, + "ordinal": 6, + "parentDefinition": { + "definitionID": "7586d645-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "PredictiveIntelSessionEnds", + "definitionName": { + "value": "Predictive Intelligence Session Ends" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "timestamp", + "storageFieldReferenceID": { + "type": "guid", + "value": "0c87ce00-c3f1-4c88-b652-ba8dfc3cc10f" + }, + "valueDefinitionID": "7986d645-31e2-e611-80cc-1402ec7222b4", + "valueDefinitionKey": "timestamp", + "name": "Time stamp", + "setDefinitionID": "7586d645-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "PredictiveIntelSessionEnds", + "setDefinitionName": { + "value": "Predictive Intelligence Session Ends" + }, + "parentIdentifier": "7586d645-31e2-e611-80cc-1402ec7222b4" + } + ], + "applicationID": "f4981f88-a13e-4abf-b331-47f41c73258d", + "applicationKey": "com.exacttarget.Predictive Web", + "attributeCount": 0, + "canAddValues": false, + "canChangeValues": false, + "canModify": false, + "canRemove": false, + "categoryID": 386, + "createdBy": -1000, + "createDate": "2017-01-24T06:33:00", + "customObjectOwnerMID": 1111111, + "dataRetentionProperties": { + "isRowBasedRetention": false, + "isResetRetentionPeriodOnImport": false, + "isDeleteAtEndOfRetentionPeriod": false, + "periodUnitOfMeasure": 4, + "setDefinitionID": "7586d645-31e2-e611-80cc-1402ec7222b4" + }, + "localizedDescription": {}, + "fullyQualifiedName": "Predictive Intelligence Session Ends", + "isCustomObjectBacked": true, + "isEvent": false, + "isHidden": false, + "isReadOnly": true, + "isRoot": false, + "isSendable": false, + "isShared": false, + "isSystemDefined": true, + "isTestaable": false, + "parentID": "00000000-0000-0000-0000-000000000000", + "relationshipCount": 0, + "storageLogicalType": "DataExtension", + "storageName": "PI_SESSION_ENDS", + "storageObjectIDs": ["6e86d645-31e2-e611-80cc-1402ec7222b4"], + "storageReferenceID": { + "type": "guid", + "value": "d652de3f-31e2-e611-80cc-1402ec7222b4" + }, + "setDefinitionID": "7586d645-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "PredictiveIntelSessionEnds", + "name": "Predictive Intelligence Session Ends" + }, + { + "definitionID": "7a86d247-3045-ea11-a2e0-1402ec94ec41", + "definitionKey": "GroupConnectLineAddress", + "definitionName": { + "value": "GroupConnect LINE Addresses" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "relationships": [ + { + "canModify": false, + "canRemove": false, + "isHidden": false, + "isSystemDefined": false, + "isGroupToSetRelationship": true, + "leftItem": { + "cardinality": "One", + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "identifier": "ab51de3f-31e2-e611-80cc-1402ec7222b4", + "relationshipType": "AttributeGroup" + }, + "leftRelationshipIDs": [ + { + "type": "int16", + "value": "2" + } + ], + "leftRelationshipReferenceType": "CustomerData", + "relationshipAttributes": [ + { + "leftAttributeID": "9293dc39-31e2-e611-80cc-1402ec7222b4", + "leftConnectingID": { + "identifierType": "FullyQualifiedName" + }, + "rightAttributeID": "7c86d247-3045-ea11-a2e0-1402ec94ec41", + "rightConnectingID": { + "identifierType": "FullyQualifiedName" + } + } + ], + "relationshipID": "8686d247-3045-ea11-a2e0-1402ec94ec41", + "rightItem": { + "cardinality": "Many", + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "identifier": "7a86d247-3045-ea11-a2e0-1402ec94ec41", + "relationshipType": "AttributeSet" + } + }, + { + "canModify": false, + "canRemove": false, + "isHidden": false, + "isSystemDefined": false, + "isGroupToSetRelationship": false, + "leftItem": { + "cardinality": "One", + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "identifier": "7a86d247-3045-ea11-a2e0-1402ec94ec41", + "relationshipType": "AttributeSet" + }, + "relationshipAttributes": [ + { + "leftAttributeID": "7b86d247-3045-ea11-a2e0-1402ec94ec41", + "leftConnectingID": { + "identifierType": "FullyQualifiedName" + }, + "rightAttributeID": "a251de3f-31e2-e611-80cc-1402ec7222b4", + "rightConnectingID": { + "identifierType": "FullyQualifiedName" + } + } + ], + "relationshipID": "9386d247-3045-ea11-a2e0-1402ec94ec41", + "rightItem": { + "cardinality": "One", + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "identifier": "a151de3f-31e2-e611-80cc-1402ec7222b4", + "relationshipType": "AttributeSet" + } + }, + { + "canModify": false, + "canRemove": false, + "isHidden": false, + "isSystemDefined": false, + "isGroupToSetRelationship": false, + "leftItem": { + "cardinality": "Many", + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "identifier": "7a86d247-3045-ea11-a2e0-1402ec94ec41", + "relationshipType": "AttributeSet" + }, + "relationshipAttributes": [ + { + "leftAttributeID": "7b86d247-3045-ea11-a2e0-1402ec94ec41", + "leftConnectingID": { + "identifierType": "FullyQualifiedName" + }, + "rightAttributeID": "e651de3f-31e2-e611-80cc-1402ec7222b4", + "rightConnectingID": { + "identifierType": "FullyQualifiedName" + } + } + ], + "relationshipID": "a686d247-3045-ea11-a2e0-1402ec94ec41", + "rightItem": { + "cardinality": "One", + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "identifier": "e551de3f-31e2-e611-80cc-1402ec7222b4", + "relationshipType": "AttributeSet" + } + } + ], + "valueDefinitions": [ + { + "baseType": "Text", + "customerDataID": 8, + "dataSourceID": 3, + "dataSourceName": {}, + "dataType": "Text", + "description": "", + "localizedDescription": { + "value": "" + }, + "definitionID": "7b86d247-3045-ea11-a2e0-1402ec94ec41", + "definitionKey": "AddressID", + "definitionName": { + "value": "Address ID" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 1, + "fullyQualifiedName": "GroupConnect LINE Addresses.Address ID", + "isHidden": false, + "isIdentityValue": false, + "isNullable": false, + "isPrimaryKey": true, + "isReadOnly": false, + "isSystemDefined": true, + "isUpdateable": false, + "length": 100, + "ordinal": 1, + "parentDefinition": { + "definitionID": "7a86d247-3045-ea11-a2e0-1402ec94ec41", + "definitionKey": "GroupConnectLineAddress", + "definitionName": { + "value": "GroupConnect LINE Addresses" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "AddressId", + "valueDefinitionID": "7b86d247-3045-ea11-a2e0-1402ec94ec41", + "valueDefinitionKey": "AddressID", + "name": "Address ID", + "setDefinitionID": "7a86d247-3045-ea11-a2e0-1402ec94ec41", + "setDefinitionKey": "GroupConnectLineAddress", + "setDefinitionName": { + "value": "GroupConnect LINE Addresses" + }, + "parentIdentifier": "7a86d247-3045-ea11-a2e0-1402ec94ec41" + }, + { + "baseType": "Numeric", + "dataSourceID": 3, + "dataSourceName": {}, + "dataType": "LongNumber", + "description": "", + "localizedDescription": { + "value": "" + }, + "definitionID": "7c86d247-3045-ea11-a2e0-1402ec94ec41", + "definitionKey": "ContactID", + "definitionName": { + "value": "Contact ID" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 2, + "fullyQualifiedName": "GroupConnect LINE Addresses.Contact ID", + "isHidden": false, + "isIdentityValue": false, + "isNullable": false, + "isPrimaryKey": true, + "isReadOnly": true, + "isSystemDefined": true, + "isUpdateable": false, + "ordinal": 2, + "parentDefinition": { + "definitionID": "7a86d247-3045-ea11-a2e0-1402ec94ec41", + "definitionKey": "GroupConnectLineAddress", + "definitionName": { + "value": "GroupConnect LINE Addresses" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "ContactId", + "valueDefinitionID": "7c86d247-3045-ea11-a2e0-1402ec94ec41", + "valueDefinitionKey": "ContactID", + "name": "Contact ID", + "setDefinitionID": "7a86d247-3045-ea11-a2e0-1402ec94ec41", + "setDefinitionKey": "GroupConnectLineAddress", + "setDefinitionName": { + "value": "GroupConnect LINE Addresses" + }, + "parentIdentifier": "7a86d247-3045-ea11-a2e0-1402ec94ec41" + }, + { + "baseType": "Text", + "dataSourceID": 3, + "dataSourceName": {}, + "dataType": "Text", + "description": "", + "localizedDescription": { + "value": "" + }, + "definitionID": "7d86d247-3045-ea11-a2e0-1402ec94ec41", + "definitionKey": "ContactKey", + "definitionName": { + "value": "Contact Key" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 3, + "fullyQualifiedName": "GroupConnect LINE Addresses.Contact Key", + "isHidden": false, + "isIdentityValue": false, + "isNullable": false, + "isPrimaryKey": false, + "isReadOnly": true, + "isSystemDefined": true, + "isUpdateable": false, + "length": 100, + "ordinal": 3, + "parentDefinition": { + "definitionID": "7a86d247-3045-ea11-a2e0-1402ec94ec41", + "definitionKey": "GroupConnectLineAddress", + "definitionName": { + "value": "GroupConnect LINE Addresses" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "ContactKey", + "valueDefinitionID": "7d86d247-3045-ea11-a2e0-1402ec94ec41", + "valueDefinitionKey": "ContactKey", + "name": "Contact Key", + "setDefinitionID": "7a86d247-3045-ea11-a2e0-1402ec94ec41", + "setDefinitionKey": "GroupConnectLineAddress", + "setDefinitionName": { + "value": "GroupConnect LINE Addresses" + }, + "parentIdentifier": "7a86d247-3045-ea11-a2e0-1402ec94ec41" + }, + { + "baseType": "Boolean", + "dataSourceID": 3, + "dataSourceName": {}, + "dataType": "Boolean", + "defaultValue": "True", + "description": "", + "localizedDescription": { + "value": "" + }, + "definitionID": "7e86d247-3045-ea11-a2e0-1402ec94ec41", + "definitionKey": "IsActive", + "definitionName": { + "value": "Is Active" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 7, + "fullyQualifiedName": "GroupConnect LINE Addresses.Is Active", + "isHidden": false, + "isIdentityValue": false, + "isNullable": false, + "isPrimaryKey": false, + "isReadOnly": true, + "isSystemDefined": true, + "isUpdateable": false, + "ordinal": 7, + "parentDefinition": { + "definitionID": "7a86d247-3045-ea11-a2e0-1402ec94ec41", + "definitionKey": "GroupConnectLineAddress", + "definitionName": { + "value": "GroupConnect LINE Addresses" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "IsActive", + "valueDefinitionID": "7e86d247-3045-ea11-a2e0-1402ec94ec41", + "valueDefinitionKey": "IsActive", + "name": "Is Active", + "setDefinitionID": "7a86d247-3045-ea11-a2e0-1402ec94ec41", + "setDefinitionKey": "GroupConnectLineAddress", + "setDefinitionName": { + "value": "GroupConnect LINE Addresses" + }, + "parentIdentifier": "7a86d247-3045-ea11-a2e0-1402ec94ec41" + }, + { + "baseType": "Date", + "dataSourceID": 3, + "dataSourceName": {}, + "dataType": "Date", + "defaultValue": "GETDATE()", + "description": "", + "localizedDescription": { + "value": "" + }, + "definitionID": "7f86d247-3045-ea11-a2e0-1402ec94ec41", + "definitionKey": "CreatedDate", + "definitionName": { + "value": "Created Date" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 8, + "fullyQualifiedName": "GroupConnect LINE Addresses.Created Date", + "isHidden": false, + "isIdentityValue": false, + "isNullable": false, + "isPrimaryKey": false, + "isReadOnly": true, + "isSystemDefined": true, + "isUpdateable": false, + "ordinal": 8, + "parentDefinition": { + "definitionID": "7a86d247-3045-ea11-a2e0-1402ec94ec41", + "definitionKey": "GroupConnectLineAddress", + "definitionName": { + "value": "GroupConnect LINE Addresses" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "CreatedDate", + "valueDefinitionID": "7f86d247-3045-ea11-a2e0-1402ec94ec41", + "valueDefinitionKey": "CreatedDate", + "name": "Created Date", + "setDefinitionID": "7a86d247-3045-ea11-a2e0-1402ec94ec41", + "setDefinitionKey": "GroupConnectLineAddress", + "setDefinitionName": { + "value": "GroupConnect LINE Addresses" + }, + "parentIdentifier": "7a86d247-3045-ea11-a2e0-1402ec94ec41" + }, + { + "baseType": "Numeric", + "dataSourceID": 3, + "dataSourceName": {}, + "dataType": "LongNumber", + "description": "", + "localizedDescription": { + "value": "" + }, + "definitionID": "8086d247-3045-ea11-a2e0-1402ec94ec41", + "definitionKey": "CreatedBy", + "definitionName": { + "value": "Created By" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 9, + "fullyQualifiedName": "GroupConnect LINE Addresses.Created By", + "isHidden": true, + "isIdentityValue": false, + "isNullable": false, + "isPrimaryKey": false, + "isReadOnly": true, + "isSystemDefined": true, + "isUpdateable": false, + "ordinal": 9, + "parentDefinition": { + "definitionID": "7a86d247-3045-ea11-a2e0-1402ec94ec41", + "definitionKey": "GroupConnectLineAddress", + "definitionName": { + "value": "GroupConnect LINE Addresses" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "CreatedBy", + "valueDefinitionID": "8086d247-3045-ea11-a2e0-1402ec94ec41", + "valueDefinitionKey": "CreatedBy", + "name": "Created By", + "setDefinitionID": "7a86d247-3045-ea11-a2e0-1402ec94ec41", + "setDefinitionKey": "GroupConnectLineAddress", + "setDefinitionName": { + "value": "GroupConnect LINE Addresses" + }, + "parentIdentifier": "7a86d247-3045-ea11-a2e0-1402ec94ec41" + }, + { + "baseType": "Date", + "dataSourceID": 3, + "dataSourceName": {}, + "dataType": "Date", + "defaultValue": "GETDATE()", + "description": "", + "localizedDescription": { + "value": "" + }, + "definitionID": "8186d247-3045-ea11-a2e0-1402ec94ec41", + "definitionKey": "ModifiedDate", + "definitionName": { + "value": "Modified Date" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 10, + "fullyQualifiedName": "GroupConnect LINE Addresses.Modified Date", + "isHidden": false, + "isIdentityValue": false, + "isNullable": true, + "isPrimaryKey": false, + "isReadOnly": true, + "isSystemDefined": true, + "isUpdateable": false, + "ordinal": 10, + "parentDefinition": { + "definitionID": "7a86d247-3045-ea11-a2e0-1402ec94ec41", + "definitionKey": "GroupConnectLineAddress", + "definitionName": { + "value": "GroupConnect LINE Addresses" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "ModifiedDate", + "valueDefinitionID": "8186d247-3045-ea11-a2e0-1402ec94ec41", + "valueDefinitionKey": "ModifiedDate", + "name": "Modified Date", + "setDefinitionID": "7a86d247-3045-ea11-a2e0-1402ec94ec41", + "setDefinitionKey": "GroupConnectLineAddress", + "setDefinitionName": { + "value": "GroupConnect LINE Addresses" + }, + "parentIdentifier": "7a86d247-3045-ea11-a2e0-1402ec94ec41" + }, + { + "baseType": "Numeric", + "dataSourceID": 3, + "dataSourceName": {}, + "dataType": "LongNumber", + "description": "", + "localizedDescription": { + "value": "" + }, + "definitionID": "8286d247-3045-ea11-a2e0-1402ec94ec41", + "definitionKey": "ModifiedBy", + "definitionName": { + "value": "Modified By" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 11, + "fullyQualifiedName": "GroupConnect LINE Addresses.Modified By", + "isHidden": true, + "isIdentityValue": false, + "isNullable": true, + "isPrimaryKey": false, + "isReadOnly": true, + "isSystemDefined": true, + "isUpdateable": false, + "ordinal": 11, + "parentDefinition": { + "definitionID": "7a86d247-3045-ea11-a2e0-1402ec94ec41", + "definitionKey": "GroupConnectLineAddress", + "definitionName": { + "value": "GroupConnect LINE Addresses" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "ModifiedBy", + "valueDefinitionID": "8286d247-3045-ea11-a2e0-1402ec94ec41", + "valueDefinitionKey": "ModifiedBy", + "name": "Modified By", + "setDefinitionID": "7a86d247-3045-ea11-a2e0-1402ec94ec41", + "setDefinitionKey": "GroupConnectLineAddress", + "setDefinitionName": { + "value": "GroupConnect LINE Addresses" + }, + "parentIdentifier": "7a86d247-3045-ea11-a2e0-1402ec94ec41" + } + ], + "applicationID": "4e9519db-ad21-483a-a3fc-8ab4557eded1", + "applicationKey": "com.exacttarget.GroupConnect", + "attributeCount": 0, + "canAddValues": false, + "canChangeValues": false, + "canModify": false, + "canRemove": false, + "createDate": "2020-02-01T14:20:00", + "localizedDescription": {}, + "fullyQualifiedName": "GroupConnect LINE Addresses", + "isCustomObjectBacked": false, + "isEvent": false, + "isHidden": false, + "isReadOnly": false, + "isRoot": false, + "isSendable": false, + "isSystemDefined": true, + "parentID": "00000000-0000-0000-0000-000000000000", + "relationshipCount": 3, + "storageObjectIDs": ["9851de3f-31e2-e611-80cc-1402ec7222b4"], + "setDefinitionID": "7a86d247-3045-ea11-a2e0-1402ec94ec41", + "setDefinitionKey": "GroupConnectLineAddress", + "name": "GroupConnect LINE Addresses" + }, + { + "definitionID": "8574266c-c416-ec11-b839-48df37d1dc79", + "definitionKey": "EinsteinMCPredictiveScores", + "definitionName": { + "value": "Einstein MC Predictive Scores" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "relationships": [ + { + "canModify": false, + "canRemove": false, + "isHidden": false, + "isSystemDefined": false, + "isGroupToSetRelationship": true, + "leftItem": { + "cardinality": "One", + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "identifier": "e152de3f-31e2-e611-80cc-1402ec7222b4", + "relationshipType": "AttributeGroup" + }, + "leftRelationshipIDs": [ + { + "type": "int16", + "value": "4" + } + ], + "leftRelationshipReferenceType": "CustomerData", + "relationshipAttributes": [ + { + "leftAttributeID": "1151de3f-31e2-e611-80cc-1402ec7222b4", + "leftConnectingID": { + "identifierType": "FullyQualifiedName" + }, + "rightAttributeID": "9174266c-c416-ec11-b839-48df37d1dc79", + "rightConnectingID": { + "identifierType": "FullyQualifiedName" + } + } + ], + "relationshipID": "c80f6472-c416-ec11-b839-48df37d1dc79", + "rightItem": { + "cardinality": "One", + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "identifier": "8574266c-c416-ec11-b839-48df37d1dc79", + "relationshipType": "AttributeSet" + } + } + ], + "valueDefinitions": [ + { + "baseType": "Numeric", + "dataSourceName": {}, + "dataType": "LongNumber", + "description": "", + "localizedDescription": { + "value": "" + }, + "definitionID": "9274266c-c416-ec11-b839-48df37d1dc79", + "definitionKey": "CustomObjectKey", + "definitionName": { + "value": "_CustomObjectKey" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "fullyQualifiedName": "Einstein MC Predictive Scores._CustomObjectKey", + "isHidden": false, + "isIdentityValue": false, + "isNullable": false, + "isPrimaryKey": false, + "isReadOnly": true, + "isSystemDefined": false, + "isUpdateable": false, + "parentDefinition": { + "definitionID": "8574266c-c416-ec11-b839-48df37d1dc79", + "definitionKey": "EinsteinMCPredictiveScores", + "definitionName": { + "value": "Einstein MC Predictive Scores" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "_CustomObjectKey", + "valueDefinitionID": "9274266c-c416-ec11-b839-48df37d1dc79", + "valueDefinitionKey": "CustomObjectKey", + "name": "_CustomObjectKey", + "setDefinitionID": "8574266c-c416-ec11-b839-48df37d1dc79", + "setDefinitionKey": "EinsteinMCPredictiveScores", + "setDefinitionName": { + "value": "Einstein MC Predictive Scores" + }, + "parentIdentifier": "8574266c-c416-ec11-b839-48df37d1dc79" + }, + { + "baseType": "Text", + "dataSourceName": {}, + "dataType": "Text", + "description": "", + "localizedDescription": { + "value": "" + }, + "definitionID": "9174266c-c416-ec11-b839-48df37d1dc79", + "definitionKey": "Email Address", + "definitionName": { + "value": "Email Address" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 0, + "fullyQualifiedName": "Einstein MC Predictive Scores.Email Address", + "isHidden": false, + "isIdentityValue": false, + "isNullable": false, + "isPrimaryKey": true, + "isReadOnly": true, + "isSystemDefined": true, + "isUpdateable": false, + "length": 256, + "obfuscationProperties": { + "maskType": "None", + "maskTypeID": 0, + "storageTypeID": 1, + "storageType": "Plain", + "valueDefinitionID": "9174266c-c416-ec11-b839-48df37d1dc79" + }, + "ordinal": 0, + "parentDefinition": { + "definitionID": "8574266c-c416-ec11-b839-48df37d1dc79", + "definitionKey": "EinsteinMCPredictiveScores", + "definitionName": { + "value": "Einstein MC Predictive Scores" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "email_address", + "storageFieldReferenceID": { + "type": "guid", + "value": "29554274-39da-460d-b721-15badcd533e0" + }, + "valueDefinitionID": "9174266c-c416-ec11-b839-48df37d1dc79", + "valueDefinitionKey": "Email Address", + "name": "Email Address", + "setDefinitionID": "8574266c-c416-ec11-b839-48df37d1dc79", + "setDefinitionKey": "EinsteinMCPredictiveScores", + "setDefinitionName": { + "value": "Einstein MC Predictive Scores" + }, + "parentIdentifier": "8574266c-c416-ec11-b839-48df37d1dc79" + }, + { + "baseType": "Text", + "dataSourceName": {}, + "dataType": "Text", + "description": "", + "localizedDescription": { + "value": "" + }, + "definitionID": "8b74266c-c416-ec11-b839-48df37d1dc79", + "definitionKey": "Email Open Likelihood", + "definitionName": { + "value": "Email Open Likelihood" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 2, + "fullyQualifiedName": "Einstein MC Predictive Scores.Email Open Likelihood", + "isHidden": false, + "isIdentityValue": false, + "isNullable": false, + "isPrimaryKey": false, + "isReadOnly": true, + "isSystemDefined": true, + "isUpdateable": false, + "length": 256, + "obfuscationProperties": { + "maskType": "None", + "maskTypeID": 0, + "storageTypeID": 1, + "storageType": "Plain", + "valueDefinitionID": "8b74266c-c416-ec11-b839-48df37d1dc79" + }, + "ordinal": 2, + "parentDefinition": { + "definitionID": "8574266c-c416-ec11-b839-48df37d1dc79", + "definitionKey": "EinsteinMCPredictiveScores", + "definitionName": { + "value": "Einstein MC Predictive Scores" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "EmailOpenLikelihood", + "storageFieldReferenceID": { + "type": "guid", + "value": "6a64b510-d27a-4d35-9bb4-23760adaa1f4" + }, + "valueDefinitionID": "8b74266c-c416-ec11-b839-48df37d1dc79", + "valueDefinitionKey": "Email Open Likelihood", + "name": "Email Open Likelihood", + "setDefinitionID": "8574266c-c416-ec11-b839-48df37d1dc79", + "setDefinitionKey": "EinsteinMCPredictiveScores", + "setDefinitionName": { + "value": "Einstein MC Predictive Scores" + }, + "parentIdentifier": "8574266c-c416-ec11-b839-48df37d1dc79" + }, + { + "baseType": "Text", + "dataSourceName": {}, + "dataType": "Text", + "description": "", + "localizedDescription": { + "value": "" + }, + "definitionID": "8d74266c-c416-ec11-b839-48df37d1dc79", + "definitionKey": "Email Click Likelihood", + "definitionName": { + "value": "Email Click Likelihood" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 2, + "fullyQualifiedName": "Einstein MC Predictive Scores.Email Click Likelihood", + "isHidden": false, + "isIdentityValue": false, + "isNullable": false, + "isPrimaryKey": false, + "isReadOnly": true, + "isSystemDefined": true, + "isUpdateable": false, + "length": 256, + "obfuscationProperties": { + "maskType": "None", + "maskTypeID": 0, + "storageTypeID": 1, + "storageType": "Plain", + "valueDefinitionID": "8d74266c-c416-ec11-b839-48df37d1dc79" + }, + "ordinal": 2, + "parentDefinition": { + "definitionID": "8574266c-c416-ec11-b839-48df37d1dc79", + "definitionKey": "EinsteinMCPredictiveScores", + "definitionName": { + "value": "Einstein MC Predictive Scores" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "EmailClickLikelihood", + "storageFieldReferenceID": { + "type": "guid", + "value": "6602de48-581e-497a-afae-2f97434db9b4" + }, + "valueDefinitionID": "8d74266c-c416-ec11-b839-48df37d1dc79", + "valueDefinitionKey": "Email Click Likelihood", + "name": "Email Click Likelihood", + "setDefinitionID": "8574266c-c416-ec11-b839-48df37d1dc79", + "setDefinitionKey": "EinsteinMCPredictiveScores", + "setDefinitionName": { + "value": "Einstein MC Predictive Scores" + }, + "parentIdentifier": "8574266c-c416-ec11-b839-48df37d1dc79" + }, + { + "baseType": "Numeric", + "dataSourceName": {}, + "dataType": "Decimal", + "description": "", + "localizedDescription": { + "value": "" + }, + "definitionID": "8f74266c-c416-ec11-b839-48df37d1dc79", + "definitionKey": "Email Open Score", + "definitionName": { + "value": "Email Open Score" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 3, + "fullyQualifiedName": "Einstein MC Predictive Scores.Email Open Score", + "isHidden": false, + "isIdentityValue": false, + "isNullable": false, + "isPrimaryKey": false, + "isReadOnly": true, + "isSystemDefined": true, + "isUpdateable": false, + "length": 18, + "obfuscationProperties": { + "maskType": "None", + "maskTypeID": 0, + "storageTypeID": 1, + "storageType": "Plain", + "valueDefinitionID": "8f74266c-c416-ec11-b839-48df37d1dc79" + }, + "ordinal": 3, + "parentDefinition": { + "definitionID": "8574266c-c416-ec11-b839-48df37d1dc79", + "definitionKey": "EinsteinMCPredictiveScores", + "definitionName": { + "value": "Einstein MC Predictive Scores" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "scale": 4, + "storageName": "EmailOpenScore", + "storageFieldReferenceID": { + "type": "guid", + "value": "5e315b7d-7135-4ffc-8520-8c9ec91e33fa" + }, + "valueDefinitionID": "8f74266c-c416-ec11-b839-48df37d1dc79", + "valueDefinitionKey": "Email Open Score", + "name": "Email Open Score", + "setDefinitionID": "8574266c-c416-ec11-b839-48df37d1dc79", + "setDefinitionKey": "EinsteinMCPredictiveScores", + "setDefinitionName": { + "value": "Einstein MC Predictive Scores" + }, + "parentIdentifier": "8574266c-c416-ec11-b839-48df37d1dc79" + }, + { + "baseType": "Text", + "dataSourceName": {}, + "dataType": "Text", + "description": "", + "localizedDescription": { + "value": "" + }, + "definitionID": "8774266c-c416-ec11-b839-48df37d1dc79", + "definitionKey": "Email Subscribe Likelihood", + "definitionName": { + "value": "Email Subscribe Likelihood" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 4, + "fullyQualifiedName": "Einstein MC Predictive Scores.Email Subscribe Likelihood", + "isHidden": false, + "isIdentityValue": false, + "isNullable": false, + "isPrimaryKey": false, + "isReadOnly": true, + "isSystemDefined": true, + "isUpdateable": false, + "length": 256, + "obfuscationProperties": { + "maskType": "None", + "maskTypeID": 0, + "storageTypeID": 1, + "storageType": "Plain", + "valueDefinitionID": "8774266c-c416-ec11-b839-48df37d1dc79" + }, + "ordinal": 4, + "parentDefinition": { + "definitionID": "8574266c-c416-ec11-b839-48df37d1dc79", + "definitionKey": "EinsteinMCPredictiveScores", + "definitionName": { + "value": "Einstein MC Predictive Scores" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "EmailSubscribeLikelihood", + "storageFieldReferenceID": { + "type": "guid", + "value": "be9bdd26-6875-4c1d-b9cc-64667e9155aa" + }, + "valueDefinitionID": "8774266c-c416-ec11-b839-48df37d1dc79", + "valueDefinitionKey": "Email Subscribe Likelihood", + "name": "Email Subscribe Likelihood", + "setDefinitionID": "8574266c-c416-ec11-b839-48df37d1dc79", + "setDefinitionKey": "EinsteinMCPredictiveScores", + "setDefinitionName": { + "value": "Einstein MC Predictive Scores" + }, + "parentIdentifier": "8574266c-c416-ec11-b839-48df37d1dc79" + }, + { + "baseType": "Numeric", + "dataSourceName": {}, + "dataType": "Decimal", + "description": "", + "localizedDescription": { + "value": "" + }, + "definitionID": "8e74266c-c416-ec11-b839-48df37d1dc79", + "definitionKey": "EmailClickScore", + "definitionName": { + "value": "EmailClickScore" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 5, + "fullyQualifiedName": "Einstein MC Predictive Scores.EmailClickScore", + "isHidden": false, + "isIdentityValue": false, + "isNullable": false, + "isPrimaryKey": false, + "isReadOnly": true, + "isSystemDefined": true, + "isUpdateable": false, + "length": 18, + "obfuscationProperties": { + "maskType": "None", + "maskTypeID": 0, + "storageTypeID": 1, + "storageType": "Plain", + "valueDefinitionID": "8e74266c-c416-ec11-b839-48df37d1dc79" + }, + "ordinal": 5, + "parentDefinition": { + "definitionID": "8574266c-c416-ec11-b839-48df37d1dc79", + "definitionKey": "EinsteinMCPredictiveScores", + "definitionName": { + "value": "Einstein MC Predictive Scores" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "scale": 4, + "storageName": "EmailClickScore", + "storageFieldReferenceID": { + "type": "guid", + "value": "64515ffd-067d-4abe-9a4e-c72eb303db0b" + }, + "valueDefinitionID": "8e74266c-c416-ec11-b839-48df37d1dc79", + "valueDefinitionKey": "EmailClickScore", + "name": "EmailClickScore", + "setDefinitionID": "8574266c-c416-ec11-b839-48df37d1dc79", + "setDefinitionKey": "EinsteinMCPredictiveScores", + "setDefinitionName": { + "value": "Einstein MC Predictive Scores" + }, + "parentIdentifier": "8574266c-c416-ec11-b839-48df37d1dc79" + }, + { + "baseType": "Numeric", + "dataSourceName": {}, + "dataType": "Decimal", + "description": "", + "localizedDescription": { + "value": "" + }, + "definitionID": "8674266c-c416-ec11-b839-48df37d1dc79", + "definitionKey": "Email Subscribe Score", + "definitionName": { + "value": "Email Subscribe Score" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 6, + "fullyQualifiedName": "Einstein MC Predictive Scores.Email Subscribe Score", + "isHidden": false, + "isIdentityValue": false, + "isNullable": false, + "isPrimaryKey": false, + "isReadOnly": true, + "isSystemDefined": true, + "isUpdateable": false, + "length": 18, + "obfuscationProperties": { + "maskType": "None", + "maskTypeID": 0, + "storageTypeID": 1, + "storageType": "Plain", + "valueDefinitionID": "8674266c-c416-ec11-b839-48df37d1dc79" + }, + "ordinal": 6, + "parentDefinition": { + "definitionID": "8574266c-c416-ec11-b839-48df37d1dc79", + "definitionKey": "EinsteinMCPredictiveScores", + "definitionName": { + "value": "Einstein MC Predictive Scores" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "scale": 4, + "storageName": "EmailSubscribeScore", + "storageFieldReferenceID": { + "type": "guid", + "value": "d392d512-6c6e-40dd-8bbf-a50c36321372" + }, + "valueDefinitionID": "8674266c-c416-ec11-b839-48df37d1dc79", + "valueDefinitionKey": "Email Subscribe Score", + "name": "Email Subscribe Score", + "setDefinitionID": "8574266c-c416-ec11-b839-48df37d1dc79", + "setDefinitionKey": "EinsteinMCPredictiveScores", + "setDefinitionName": { + "value": "Einstein MC Predictive Scores" + }, + "parentIdentifier": "8574266c-c416-ec11-b839-48df37d1dc79" + }, + { + "baseType": "Text", + "dataSourceName": {}, + "dataType": "Text", + "description": "", + "localizedDescription": { + "value": "" + }, + "definitionID": "8c74266c-c416-ec11-b839-48df37d1dc79", + "definitionKey": "EmailEngagementPersona", + "definitionName": { + "value": "EmailEngagementPersona" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 7, + "fullyQualifiedName": "Einstein MC Predictive Scores.EmailEngagementPersona", + "isHidden": false, + "isIdentityValue": false, + "isNullable": false, + "isPrimaryKey": false, + "isReadOnly": true, + "isSystemDefined": true, + "isUpdateable": false, + "length": 256, + "obfuscationProperties": { + "maskType": "None", + "maskTypeID": 0, + "storageTypeID": 1, + "storageType": "Plain", + "valueDefinitionID": "8c74266c-c416-ec11-b839-48df37d1dc79" + }, + "ordinal": 7, + "parentDefinition": { + "definitionID": "8574266c-c416-ec11-b839-48df37d1dc79", + "definitionKey": "EinsteinMCPredictiveScores", + "definitionName": { + "value": "Einstein MC Predictive Scores" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "EmailEngagementPersona", + "storageFieldReferenceID": { + "type": "guid", + "value": "67b5a098-1374-4d0a-9ffa-ad9a465eac66" + }, + "valueDefinitionID": "8c74266c-c416-ec11-b839-48df37d1dc79", + "valueDefinitionKey": "EmailEngagementPersona", + "name": "EmailEngagementPersona", + "setDefinitionID": "8574266c-c416-ec11-b839-48df37d1dc79", + "setDefinitionKey": "EinsteinMCPredictiveScores", + "setDefinitionName": { + "value": "Einstein MC Predictive Scores" + }, + "parentIdentifier": "8574266c-c416-ec11-b839-48df37d1dc79" + }, + { + "baseType": "Text", + "dataSourceName": {}, + "dataType": "Text", + "description": "", + "localizedDescription": { + "value": "" + }, + "definitionID": "8974266c-c416-ec11-b839-48df37d1dc79", + "definitionKey": "Conversion Likelihood", + "definitionName": { + "value": "Conversion Likelihood" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 8, + "fullyQualifiedName": "Einstein MC Predictive Scores.Conversion Likelihood", + "isHidden": false, + "isIdentityValue": false, + "isNullable": false, + "isPrimaryKey": false, + "isReadOnly": true, + "isSystemDefined": true, + "isUpdateable": false, + "length": 256, + "obfuscationProperties": { + "maskType": "None", + "maskTypeID": 0, + "storageTypeID": 1, + "storageType": "Plain", + "valueDefinitionID": "8974266c-c416-ec11-b839-48df37d1dc79" + }, + "ordinal": 8, + "parentDefinition": { + "definitionID": "8574266c-c416-ec11-b839-48df37d1dc79", + "definitionKey": "EinsteinMCPredictiveScores", + "definitionName": { + "value": "Einstein MC Predictive Scores" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "ConversionLikelihood", + "storageFieldReferenceID": { + "type": "guid", + "value": "a293ae7a-dc35-462d-8909-32eccc22fc58" + }, + "valueDefinitionID": "8974266c-c416-ec11-b839-48df37d1dc79", + "valueDefinitionKey": "Conversion Likelihood", + "name": "Conversion Likelihood", + "setDefinitionID": "8574266c-c416-ec11-b839-48df37d1dc79", + "setDefinitionKey": "EinsteinMCPredictiveScores", + "setDefinitionName": { + "value": "Einstein MC Predictive Scores" + }, + "parentIdentifier": "8574266c-c416-ec11-b839-48df37d1dc79" + }, + { + "baseType": "Numeric", + "dataSourceName": {}, + "dataType": "Decimal", + "description": "", + "localizedDescription": { + "value": "" + }, + "definitionID": "8a74266c-c416-ec11-b839-48df37d1dc79", + "definitionKey": "Conversion Score", + "definitionName": { + "value": "Conversion Score" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 9, + "fullyQualifiedName": "Einstein MC Predictive Scores.Conversion Score", + "isHidden": false, + "isIdentityValue": false, + "isNullable": false, + "isPrimaryKey": false, + "isReadOnly": true, + "isSystemDefined": true, + "isUpdateable": false, + "length": 18, + "obfuscationProperties": { + "maskType": "None", + "maskTypeID": 0, + "storageTypeID": 1, + "storageType": "Plain", + "valueDefinitionID": "8a74266c-c416-ec11-b839-48df37d1dc79" + }, + "ordinal": 9, + "parentDefinition": { + "definitionID": "8574266c-c416-ec11-b839-48df37d1dc79", + "definitionKey": "EinsteinMCPredictiveScores", + "definitionName": { + "value": "Einstein MC Predictive Scores" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "scale": 4, + "storageName": "ConversionScore", + "storageFieldReferenceID": { + "type": "guid", + "value": "75a99602-df46-4fcc-a731-1b56c0d24d0e" + }, + "valueDefinitionID": "8a74266c-c416-ec11-b839-48df37d1dc79", + "valueDefinitionKey": "Conversion Score", + "name": "Conversion Score", + "setDefinitionID": "8574266c-c416-ec11-b839-48df37d1dc79", + "setDefinitionKey": "EinsteinMCPredictiveScores", + "setDefinitionName": { + "value": "Einstein MC Predictive Scores" + }, + "parentIdentifier": "8574266c-c416-ec11-b839-48df37d1dc79" + }, + { + "baseType": "Date", + "dataSourceName": {}, + "dataType": "Date", + "defaultValue": "getdate()", + "description": "", + "localizedDescription": { + "value": "" + }, + "definitionID": "9074266c-c416-ec11-b839-48df37d1dc79", + "definitionKey": "Updated Date", + "definitionName": { + "value": "Updated Date" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 10, + "fullyQualifiedName": "Einstein MC Predictive Scores.Updated Date", + "isHidden": false, + "isIdentityValue": false, + "isNullable": false, + "isPrimaryKey": false, + "isReadOnly": true, + "isSystemDefined": true, + "isUpdateable": false, + "length": 18, + "obfuscationProperties": { + "maskType": "None", + "maskTypeID": 0, + "storageTypeID": 1, + "storageType": "Plain", + "valueDefinitionID": "9074266c-c416-ec11-b839-48df37d1dc79" + }, + "ordinal": 10, + "parentDefinition": { + "definitionID": "8574266c-c416-ec11-b839-48df37d1dc79", + "definitionKey": "EinsteinMCPredictiveScores", + "definitionName": { + "value": "Einstein MC Predictive Scores" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "scale": 4, + "storageName": "UpdatedDate", + "storageFieldReferenceID": { + "type": "guid", + "value": "4457d74f-2c14-4a3f-baf2-2cc34cf8858b" + }, + "valueDefinitionID": "9074266c-c416-ec11-b839-48df37d1dc79", + "valueDefinitionKey": "Updated Date", + "name": "Updated Date", + "setDefinitionID": "8574266c-c416-ec11-b839-48df37d1dc79", + "setDefinitionKey": "EinsteinMCPredictiveScores", + "setDefinitionName": { + "value": "Einstein MC Predictive Scores" + }, + "parentIdentifier": "8574266c-c416-ec11-b839-48df37d1dc79" + }, + { + "baseType": "Date", + "dataSourceName": {}, + "dataType": "Date", + "defaultValue": "getdate()", + "description": "", + "localizedDescription": { + "value": "" + }, + "definitionID": "8874266c-c416-ec11-b839-48df37d1dc79", + "definitionKey": "Created Date", + "definitionName": { + "value": "Created Date" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 11, + "fullyQualifiedName": "Einstein MC Predictive Scores.Created Date", + "isHidden": false, + "isIdentityValue": false, + "isNullable": false, + "isPrimaryKey": false, + "isReadOnly": true, + "isSystemDefined": true, + "isUpdateable": false, + "length": 18, + "obfuscationProperties": { + "maskType": "None", + "maskTypeID": 0, + "storageTypeID": 1, + "storageType": "Plain", + "valueDefinitionID": "8874266c-c416-ec11-b839-48df37d1dc79" + }, + "ordinal": 11, + "parentDefinition": { + "definitionID": "8574266c-c416-ec11-b839-48df37d1dc79", + "definitionKey": "EinsteinMCPredictiveScores", + "definitionName": { + "value": "Einstein MC Predictive Scores" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "scale": 4, + "storageName": "CreatedDate", + "storageFieldReferenceID": { + "type": "guid", + "value": "a4852a5f-2952-4648-911a-452533298dab" + }, + "valueDefinitionID": "8874266c-c416-ec11-b839-48df37d1dc79", + "valueDefinitionKey": "Created Date", + "name": "Created Date", + "setDefinitionID": "8574266c-c416-ec11-b839-48df37d1dc79", + "setDefinitionKey": "EinsteinMCPredictiveScores", + "setDefinitionName": { + "value": "Einstein MC Predictive Scores" + }, + "parentIdentifier": "8574266c-c416-ec11-b839-48df37d1dc79" + } + ], + "applicationID": "aed181bc-d7b7-465e-a3dd-9cdfb13943e2", + "applicationKey": "com.sfmc-einstein.Einstein Engagement Scoring", + "attributeCount": 0, + "canAddValues": false, + "canChangeValues": false, + "canModify": false, + "canRemove": false, + "categoryID": 2, + "createdBy": -1000, + "createDate": "2021-09-16T02:03:00", + "customObjectOwnerMID": 1111111, + "dataRetentionProperties": { + "isRowBasedRetention": false, + "isResetRetentionPeriodOnImport": false, + "isDeleteAtEndOfRetentionPeriod": false, + "setDefinitionID": "8574266c-c416-ec11-b839-48df37d1dc79" + }, + "localizedDescription": {}, + "fullyQualifiedName": "Einstein MC Predictive Scores", + "isCustomObjectBacked": false, + "isEvent": false, + "isHidden": false, + "isReadOnly": true, + "isRoot": false, + "isSendable": false, + "isShared": false, + "isSystemDefined": true, + "isTestaable": false, + "parentID": "00000000-0000-0000-0000-000000000000", + "relationshipCount": 1, + "storageLogicalType": "ExactTargetSchema", + "storageName": "Einstein_MC_Predictive_Scores", + "storageObjectIDs": ["c90f6472-c416-ec11-b839-48df37d1dc79"], + "storageReferenceID": { + "type": "guid", + "value": "e5ca7d21-aba6-e811-a2bf-1402ec94ecf1" + }, + "setDefinitionID": "8574266c-c416-ec11-b839-48df37d1dc79", + "setDefinitionKey": "EinsteinMCPredictiveScores", + "name": "Einstein MC Predictive Scores" + }, + { + "definitionID": "9093dc39-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "Contact", + "definitionName": { + "value": "Contact" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "relationships": [ + { + "canModify": false, + "canRemove": false, + "isHidden": false, + "isSystemDefined": false, + "isGroupToSetRelationship": true, + "leftItem": { + "cardinality": "One", + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "identifier": "8f93dc39-31e2-e611-80cc-1402ec7222b4", + "relationshipType": "AttributeGroup" + }, + "leftRelationshipIDs": [ + { + "type": "int16", + "value": "2" + } + ], + "leftRelationshipReferenceType": "CustomerData", + "relationshipAttributes": [ + { + "leftAttributeID": "9293dc39-31e2-e611-80cc-1402ec7222b4", + "leftConnectingID": { + "identifierType": "FullyQualifiedName" + }, + "rightAttributeID": "9293dc39-31e2-e611-80cc-1402ec7222b4", + "rightConnectingID": { + "identifierType": "FullyQualifiedName" + } + } + ], + "relationshipID": "9893dc39-31e2-e611-80cc-1402ec7222b4", + "rightItem": { + "cardinality": "One", + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "identifier": "9093dc39-31e2-e611-80cc-1402ec7222b4", + "relationshipType": "AttributeSet" + } + } + ], + "valueDefinitions": [ + { + "baseType": "Numeric", + "customerDataID": 2, + "dataSourceID": 1, + "dataSourceName": {}, + "dataType": "Number", + "description": "", + "localizedDescription": { + "value": "" + }, + "definitionID": "9293dc39-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "ContactID", + "definitionName": { + "value": "Contact ID" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "fullyQualifiedName": "Contact.Contact ID", + "isHidden": false, + "isIdentityValue": false, + "isNullable": false, + "isPrimaryKey": true, + "isReadOnly": true, + "isSystemDefined": true, + "isUpdateable": false, + "parentDefinition": { + "definitionID": "9093dc39-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "Contact", + "definitionName": { + "value": "Contact" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "SubscriberID", + "valueDefinitionID": "9293dc39-31e2-e611-80cc-1402ec7222b4", + "valueDefinitionKey": "ContactID", + "name": "Contact ID", + "setDefinitionID": "9093dc39-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "Contact", + "setDefinitionName": { + "value": "Contact" + }, + "parentIdentifier": "9093dc39-31e2-e611-80cc-1402ec7222b4" + }, + { + "baseType": "Text", + "customerDataID": 3, + "dataSourceID": 1, + "dataSourceName": {}, + "dataType": "Text", + "description": "", + "localizedDescription": { + "value": "" + }, + "definitionID": "9393dc39-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "ContactKey", + "definitionName": { + "value": "Contact Key" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "fullyQualifiedName": "Contact.Contact Key", + "isHidden": false, + "isIdentityValue": false, + "isNullable": false, + "isPrimaryKey": false, + "isReadOnly": true, + "isSystemDefined": true, + "isUpdateable": false, + "length": -1, + "parentDefinition": { + "definitionID": "9093dc39-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "Contact", + "definitionName": { + "value": "Contact" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "SubscriberKey", + "valueDefinitionID": "9393dc39-31e2-e611-80cc-1402ec7222b4", + "valueDefinitionKey": "ContactKey", + "name": "Contact Key", + "setDefinitionID": "9093dc39-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "Contact", + "setDefinitionName": { + "value": "Contact" + }, + "parentIdentifier": "9093dc39-31e2-e611-80cc-1402ec7222b4" + }, + { + "baseType": "Numeric", + "customerDataID": 1, + "dataSourceID": 1, + "dataSourceName": {}, + "dataType": "Number", + "description": "", + "localizedDescription": { + "value": "" + }, + "definitionID": "9193dc39-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "BusinessUnitID", + "definitionName": { + "value": "Business Unit ID" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "fullyQualifiedName": "Contact.Business Unit ID", + "isHidden": true, + "isIdentityValue": false, + "isNullable": false, + "isPrimaryKey": true, + "isReadOnly": true, + "isSystemDefined": true, + "isUpdateable": false, + "parentDefinition": { + "definitionID": "9093dc39-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "Contact", + "definitionName": { + "value": "Contact" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "ClientID", + "valueDefinitionID": "9193dc39-31e2-e611-80cc-1402ec7222b4", + "valueDefinitionKey": "BusinessUnitID", + "name": "Business Unit ID", + "setDefinitionID": "9093dc39-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "Contact", + "setDefinitionName": { + "value": "Contact" + }, + "parentIdentifier": "9093dc39-31e2-e611-80cc-1402ec7222b4" + } + ], + "applicationID": "ce703ed3-e01f-4f5f-900d-76a95b363e29", + "applicationKey": "com.exacttarget.contacts", + "attributeCount": 0, + "canAddValues": false, + "canChangeValues": false, + "canModify": false, + "canRemove": false, + "createdBy": -1000, + "createDate": "2017-01-24T06:33:00", + "localizedDescription": {}, + "fullyQualifiedName": "Contact", + "isCustomObjectBacked": false, + "isEvent": false, + "isHidden": false, + "isReadOnly": true, + "isRoot": false, + "isSendable": false, + "isSystemDefined": true, + "parentID": "00000000-0000-0000-0000-000000000000", + "relationshipCount": 1, + "storageObjectIDs": ["2ba72136-9f31-4a79-ab62-4ba5d19cd759"], + "setDefinitionID": "9093dc39-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "Contact", + "name": "Contact" + }, + { + "definitionID": "a151de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "GroupConnectLineDemographics", + "definitionName": { + "value": "GroupConnect LINE Demographics" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "valueDefinitions": [ + { + "baseType": "Text", + "dataSourceID": 3, + "dataSourceName": {}, + "dataType": "Text", + "description": "", + "localizedDescription": { + "value": "" + }, + "definitionID": "a251de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "AddressID", + "definitionName": { + "value": "Address ID" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 1, + "fullyQualifiedName": "GroupConnect LINE Demographics.Address ID", + "isHidden": false, + "isIdentityValue": false, + "isNullable": false, + "isPrimaryKey": true, + "isReadOnly": false, + "isSystemDefined": true, + "isUpdateable": false, + "length": 100, + "ordinal": 1, + "parentDefinition": { + "definitionID": "a151de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "GroupConnectLineDemographics", + "definitionName": { + "value": "GroupConnect LINE Demographics" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "AddressId", + "valueDefinitionID": "a251de3f-31e2-e611-80cc-1402ec7222b4", + "valueDefinitionKey": "AddressID", + "name": "Address ID", + "setDefinitionID": "a151de3f-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "GroupConnectLineDemographics", + "setDefinitionName": { + "value": "GroupConnect LINE Demographics" + }, + "parentIdentifier": "a151de3f-31e2-e611-80cc-1402ec7222b4" + }, + { + "baseType": "Text", + "dataSourceID": 3, + "dataSourceName": {}, + "dataType": "Text", + "description": "", + "localizedDescription": { + "value": "" + }, + "definitionID": "da51de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "DisplayName", + "definitionName": { + "value": "Display Name" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 2, + "fullyQualifiedName": "GroupConnect LINE Demographics.Display Name", + "isHidden": false, + "isIdentityValue": false, + "isNullable": true, + "isPrimaryKey": false, + "isReadOnly": true, + "isSystemDefined": true, + "isUpdateable": false, + "length": 200, + "ordinal": 2, + "parentDefinition": { + "definitionID": "a151de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "GroupConnectLineDemographics", + "definitionName": { + "value": "GroupConnect LINE Demographics" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "DisplayName", + "valueDefinitionID": "da51de3f-31e2-e611-80cc-1402ec7222b4", + "valueDefinitionKey": "DisplayName", + "name": "Display Name", + "setDefinitionID": "a151de3f-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "GroupConnectLineDemographics", + "setDefinitionName": { + "value": "GroupConnect LINE Demographics" + }, + "parentIdentifier": "a151de3f-31e2-e611-80cc-1402ec7222b4" + }, + { + "baseType": "Text", + "dataSourceID": 3, + "dataSourceName": {}, + "dataType": "Text", + "description": "", + "localizedDescription": { + "value": "" + }, + "definitionID": "db51de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "PictureUrl", + "definitionName": { + "value": "Picture Url" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 3, + "fullyQualifiedName": "GroupConnect LINE Demographics.Picture Url", + "isHidden": false, + "isIdentityValue": false, + "isNullable": true, + "isPrimaryKey": false, + "isReadOnly": true, + "isSystemDefined": true, + "isUpdateable": false, + "length": 200, + "ordinal": 3, + "parentDefinition": { + "definitionID": "a151de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "GroupConnectLineDemographics", + "definitionName": { + "value": "GroupConnect LINE Demographics" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "PictureUrl", + "valueDefinitionID": "db51de3f-31e2-e611-80cc-1402ec7222b4", + "valueDefinitionKey": "PictureUrl", + "name": "Picture Url", + "setDefinitionID": "a151de3f-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "GroupConnectLineDemographics", + "setDefinitionName": { + "value": "GroupConnect LINE Demographics" + }, + "parentIdentifier": "a151de3f-31e2-e611-80cc-1402ec7222b4" + }, + { + "baseType": "Text", + "dataSourceID": 3, + "dataSourceName": {}, + "dataType": "Text", + "description": "", + "localizedDescription": { + "value": "" + }, + "definitionID": "dc51de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "StatusMessage", + "definitionName": { + "value": "Status Message" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 4, + "fullyQualifiedName": "GroupConnect LINE Demographics.Status Message", + "isHidden": false, + "isIdentityValue": false, + "isNullable": true, + "isPrimaryKey": false, + "isReadOnly": true, + "isSystemDefined": true, + "isUpdateable": false, + "length": 200, + "ordinal": 4, + "parentDefinition": { + "definitionID": "a151de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "GroupConnectLineDemographics", + "definitionName": { + "value": "GroupConnect LINE Demographics" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "StatusMessage", + "valueDefinitionID": "dc51de3f-31e2-e611-80cc-1402ec7222b4", + "valueDefinitionKey": "StatusMessage", + "name": "Status Message", + "setDefinitionID": "a151de3f-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "GroupConnectLineDemographics", + "setDefinitionName": { + "value": "GroupConnect LINE Demographics" + }, + "parentIdentifier": "a151de3f-31e2-e611-80cc-1402ec7222b4" + }, + { + "baseType": "Date", + "dataSourceID": 3, + "dataSourceName": {}, + "dataType": "Date", + "defaultValue": "GETDATE()", + "description": "", + "localizedDescription": { + "value": "" + }, + "definitionID": "a651de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "CreatedDate", + "definitionName": { + "value": "Created Date" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 8, + "fullyQualifiedName": "GroupConnect LINE Demographics.Created Date", + "isHidden": false, + "isIdentityValue": false, + "isNullable": false, + "isPrimaryKey": false, + "isReadOnly": true, + "isSystemDefined": true, + "isUpdateable": false, + "ordinal": 8, + "parentDefinition": { + "definitionID": "a151de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "GroupConnectLineDemographics", + "definitionName": { + "value": "GroupConnect LINE Demographics" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "CreatedDate", + "valueDefinitionID": "a651de3f-31e2-e611-80cc-1402ec7222b4", + "valueDefinitionKey": "CreatedDate", + "name": "Created Date", + "setDefinitionID": "a151de3f-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "GroupConnectLineDemographics", + "setDefinitionName": { + "value": "GroupConnect LINE Demographics" + }, + "parentIdentifier": "a151de3f-31e2-e611-80cc-1402ec7222b4" + }, + { + "baseType": "Numeric", + "dataSourceID": 3, + "dataSourceName": {}, + "dataType": "LongNumber", + "description": "", + "localizedDescription": { + "value": "" + }, + "definitionID": "a751de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "CreatedBy", + "definitionName": { + "value": "Created By" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 9, + "fullyQualifiedName": "GroupConnect LINE Demographics.Created By", + "isHidden": true, + "isIdentityValue": false, + "isNullable": false, + "isPrimaryKey": false, + "isReadOnly": true, + "isSystemDefined": true, + "isUpdateable": false, + "ordinal": 9, + "parentDefinition": { + "definitionID": "a151de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "GroupConnectLineDemographics", + "definitionName": { + "value": "GroupConnect LINE Demographics" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "CreatedBy", + "valueDefinitionID": "a751de3f-31e2-e611-80cc-1402ec7222b4", + "valueDefinitionKey": "CreatedBy", + "name": "Created By", + "setDefinitionID": "a151de3f-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "GroupConnectLineDemographics", + "setDefinitionName": { + "value": "GroupConnect LINE Demographics" + }, + "parentIdentifier": "a151de3f-31e2-e611-80cc-1402ec7222b4" + }, + { + "baseType": "Date", + "dataSourceID": 3, + "dataSourceName": {}, + "dataType": "Date", + "defaultValue": "GETDATE()", + "description": "", + "localizedDescription": { + "value": "" + }, + "definitionID": "a851de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "ModifiedDate", + "definitionName": { + "value": "Modified Date" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 10, + "fullyQualifiedName": "GroupConnect LINE Demographics.Modified Date", + "isHidden": false, + "isIdentityValue": false, + "isNullable": true, + "isPrimaryKey": false, + "isReadOnly": true, + "isSystemDefined": true, + "isUpdateable": false, + "ordinal": 10, + "parentDefinition": { + "definitionID": "a151de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "GroupConnectLineDemographics", + "definitionName": { + "value": "GroupConnect LINE Demographics" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "ModifiedDate", + "valueDefinitionID": "a851de3f-31e2-e611-80cc-1402ec7222b4", + "valueDefinitionKey": "ModifiedDate", + "name": "Modified Date", + "setDefinitionID": "a151de3f-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "GroupConnectLineDemographics", + "setDefinitionName": { + "value": "GroupConnect LINE Demographics" + }, + "parentIdentifier": "a151de3f-31e2-e611-80cc-1402ec7222b4" + }, + { + "baseType": "Numeric", + "dataSourceID": 3, + "dataSourceName": {}, + "dataType": "LongNumber", + "description": "", + "localizedDescription": { + "value": "" + }, + "definitionID": "a951de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "ModifiedBy", + "definitionName": { + "value": "Modified By" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 11, + "fullyQualifiedName": "GroupConnect LINE Demographics.Modified By", + "isHidden": true, + "isIdentityValue": false, + "isNullable": true, + "isPrimaryKey": false, + "isReadOnly": true, + "isSystemDefined": true, + "isUpdateable": false, + "ordinal": 11, + "parentDefinition": { + "definitionID": "a151de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "GroupConnectLineDemographics", + "definitionName": { + "value": "GroupConnect LINE Demographics" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "ModifiedBy", + "valueDefinitionID": "a951de3f-31e2-e611-80cc-1402ec7222b4", + "valueDefinitionKey": "ModifiedBy", + "name": "Modified By", + "setDefinitionID": "a151de3f-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "GroupConnectLineDemographics", + "setDefinitionName": { + "value": "GroupConnect LINE Demographics" + }, + "parentIdentifier": "a151de3f-31e2-e611-80cc-1402ec7222b4" + } + ], + "applicationID": "4e9519db-ad21-483a-a3fc-8ab4557eded1", + "applicationKey": "com.exacttarget.GroupConnect", + "attributeCount": 0, + "canAddValues": false, + "canChangeValues": false, + "canModify": false, + "canRemove": false, + "createdBy": -1000, + "createDate": "2017-01-24T06:33:00", + "localizedDescription": {}, + "fullyQualifiedName": "GroupConnect LINE Demographics", + "isCustomObjectBacked": false, + "isEvent": false, + "isHidden": false, + "isReadOnly": false, + "isRoot": false, + "isSendable": false, + "isSystemDefined": true, + "parentID": "00000000-0000-0000-0000-000000000000", + "relationshipCount": 0, + "storageObjectIDs": [ + "9851de3f-31e2-e611-80cc-1402ec7222b4", + "d351de3f-31e2-e611-80cc-1402ec7222b4" + ], + "setDefinitionID": "a151de3f-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "GroupConnectLineDemographics", + "name": "GroupConnect LINE Demographics" + }, + { + "definitionID": "a185d645-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "PredictiveIntelScores", + "definitionName": { + "value": "Predictive Scores" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "relationships": [ + { + "canModify": false, + "canRemove": false, + "isHidden": false, + "isSystemDefined": false, + "isGroupToSetRelationship": true, + "leftItem": { + "cardinality": "One", + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "identifier": "e152de3f-31e2-e611-80cc-1402ec7222b4", + "relationshipType": "AttributeGroup" + }, + "leftRelationshipIDs": [ + { + "type": "int16", + "value": "3" + } + ], + "leftRelationshipReferenceType": "CustomerData", + "relationshipAttributes": [ + { + "leftAttributeID": "9393dc39-31e2-e611-80cc-1402ec7222b4", + "leftConnectingID": { + "identifierType": "FullyQualifiedName" + }, + "rightAttributeID": "a585d645-31e2-e611-80cc-1402ec7222b4", + "rightConnectingID": { + "identifierType": "FullyQualifiedName" + } + } + ], + "relationshipID": "a985d645-31e2-e611-80cc-1402ec7222b4", + "rightItem": { + "cardinality": "Many", + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "identifier": "a185d645-31e2-e611-80cc-1402ec7222b4", + "relationshipType": "AttributeSet" + } + } + ], + "valueDefinitions": [ + { + "baseType": "Numeric", + "dataSourceID": 1, + "dataSourceName": {}, + "dataType": "LongNumber", + "description": "", + "localizedDescription": { + "value": "" + }, + "definitionID": "a785d645-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "CustomObjectKey", + "definitionName": { + "value": "Custom Object Key" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 1, + "fullyQualifiedName": "Predictive Scores.Custom Object Key", + "isHidden": true, + "isIdentityValue": true, + "isNullable": false, + "isPrimaryKey": false, + "isReadOnly": true, + "isSystemDefined": true, + "isUpdateable": false, + "ordinal": 1, + "parentDefinition": { + "definitionID": "a185d645-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "PredictiveIntelScores", + "definitionName": { + "value": "Predictive Scores" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "_CustomObjectKey", + "valueDefinitionID": "a785d645-31e2-e611-80cc-1402ec7222b4", + "valueDefinitionKey": "CustomObjectKey", + "name": "Custom Object Key", + "setDefinitionID": "a185d645-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "PredictiveIntelScores", + "setDefinitionName": { + "value": "Predictive Scores" + }, + "parentIdentifier": "a185d645-31e2-e611-80cc-1402ec7222b4" + }, + { + "baseType": "Text", + "dataSourceID": 5, + "dataSourceName": {}, + "dataType": "Text", + "description": "subscriber_key", + "localizedDescription": { + "value": "subscriber_key" + }, + "definitionID": "a585d645-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "Subscriber Key", + "definitionName": { + "value": "Subscriber Key" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 2, + "fullyQualifiedName": "Predictive Scores.Subscriber Key", + "isHidden": false, + "isIdentityValue": false, + "isNullable": false, + "isPrimaryKey": true, + "isReadOnly": true, + "isSystemDefined": true, + "isUpdateable": false, + "length": 256, + "obfuscationProperties": { + "maskType": "None", + "maskTypeID": 0, + "storageTypeID": 1, + "storageType": "Plain", + "valueDefinitionID": "a585d645-31e2-e611-80cc-1402ec7222b4" + }, + "ordinal": 2, + "parentDefinition": { + "definitionID": "a185d645-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "PredictiveIntelScores", + "definitionName": { + "value": "Predictive Scores" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "subscriber_key", + "storageFieldReferenceID": { + "type": "guid", + "value": "f6ce2639-bfff-40c0-835c-9fa89e627592" + }, + "valueDefinitionID": "a585d645-31e2-e611-80cc-1402ec7222b4", + "valueDefinitionKey": "Subscriber Key", + "name": "Subscriber Key", + "setDefinitionID": "a185d645-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "PredictiveIntelScores", + "setDefinitionName": { + "value": "Predictive Scores" + }, + "parentIdentifier": "a185d645-31e2-e611-80cc-1402ec7222b4" + }, + { + "baseType": "Text", + "dataSourceID": 5, + "dataSourceName": {}, + "dataType": "Text", + "description": "goal_name", + "localizedDescription": { + "value": "goal_name" + }, + "definitionID": "a285d645-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "Goal Name", + "definitionName": { + "value": "Goal Name" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 3, + "fullyQualifiedName": "Predictive Scores.Goal Name", + "isHidden": false, + "isIdentityValue": false, + "isNullable": false, + "isPrimaryKey": false, + "isReadOnly": true, + "isSystemDefined": true, + "isUpdateable": false, + "length": 100, + "obfuscationProperties": { + "maskType": "None", + "maskTypeID": 0, + "storageTypeID": 1, + "storageType": "Plain", + "valueDefinitionID": "a285d645-31e2-e611-80cc-1402ec7222b4" + }, + "ordinal": 3, + "parentDefinition": { + "definitionID": "a185d645-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "PredictiveIntelScores", + "definitionName": { + "value": "Predictive Scores" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "goal_name", + "storageFieldReferenceID": { + "type": "guid", + "value": "62f73dda-4116-4fdd-ae38-a5cb74fafc6b" + }, + "valueDefinitionID": "a285d645-31e2-e611-80cc-1402ec7222b4", + "valueDefinitionKey": "Goal Name", + "name": "Goal Name", + "setDefinitionID": "a185d645-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "PredictiveIntelScores", + "setDefinitionName": { + "value": "Predictive Scores" + }, + "parentIdentifier": "a185d645-31e2-e611-80cc-1402ec7222b4" + }, + { + "baseType": "Text", + "dataSourceID": 5, + "dataSourceName": {}, + "dataType": "Text", + "description": "goal_name_key", + "localizedDescription": { + "value": "goal_name_key" + }, + "definitionID": "a385d645-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "Goal Name Key", + "definitionName": { + "value": "Goal Name Key" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 4, + "fullyQualifiedName": "Predictive Scores.Goal Name Key", + "isHidden": false, + "isIdentityValue": false, + "isNullable": false, + "isPrimaryKey": true, + "isReadOnly": true, + "isSystemDefined": true, + "isUpdateable": false, + "length": 100, + "obfuscationProperties": { + "maskType": "None", + "maskTypeID": 0, + "storageTypeID": 1, + "storageType": "Plain", + "valueDefinitionID": "a385d645-31e2-e611-80cc-1402ec7222b4" + }, + "ordinal": 4, + "parentDefinition": { + "definitionID": "a185d645-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "PredictiveIntelScores", + "definitionName": { + "value": "Predictive Scores" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "goal_name_key", + "storageFieldReferenceID": { + "type": "guid", + "value": "5c34b4cc-5d35-460e-a0b7-ba8e349d725b" + }, + "valueDefinitionID": "a385d645-31e2-e611-80cc-1402ec7222b4", + "valueDefinitionKey": "Goal Name Key", + "name": "Goal Name Key", + "setDefinitionID": "a185d645-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "PredictiveIntelScores", + "setDefinitionName": { + "value": "Predictive Scores" + }, + "parentIdentifier": "a185d645-31e2-e611-80cc-1402ec7222b4" + }, + { + "baseType": "Numeric", + "dataSourceID": 5, + "dataSourceName": {}, + "dataType": "Decimal", + "description": "score", + "localizedDescription": { + "value": "score" + }, + "definitionID": "a485d645-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "Score", + "definitionName": { + "value": "Score" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 5, + "fullyQualifiedName": "Predictive Scores.Score", + "isHidden": false, + "isIdentityValue": false, + "isNullable": false, + "isPrimaryKey": false, + "isReadOnly": true, + "isSystemDefined": true, + "isUpdateable": false, + "length": 18, + "obfuscationProperties": { + "maskType": "None", + "maskTypeID": 0, + "storageTypeID": 1, + "storageType": "Plain", + "valueDefinitionID": "a485d645-31e2-e611-80cc-1402ec7222b4" + }, + "ordinal": 5, + "parentDefinition": { + "definitionID": "a185d645-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "PredictiveIntelScores", + "definitionName": { + "value": "Predictive Scores" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "scale": 4, + "storageName": "score", + "storageFieldReferenceID": { + "type": "guid", + "value": "8baf5deb-f215-4984-9d91-6e05b88c2f94" + }, + "valueDefinitionID": "a485d645-31e2-e611-80cc-1402ec7222b4", + "valueDefinitionKey": "Score", + "name": "Score", + "setDefinitionID": "a185d645-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "PredictiveIntelScores", + "setDefinitionName": { + "value": "Predictive Scores" + }, + "parentIdentifier": "a185d645-31e2-e611-80cc-1402ec7222b4" + }, + { + "baseType": "Date", + "dataSourceID": 5, + "dataSourceName": {}, + "dataType": "Date", + "description": "updated_at", + "localizedDescription": { + "value": "updated_at" + }, + "definitionID": "a685d645-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "Updated At", + "definitionName": { + "value": "Updated At" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 6, + "fullyQualifiedName": "Predictive Scores.Updated At", + "isHidden": false, + "isIdentityValue": false, + "isNullable": false, + "isPrimaryKey": false, + "isReadOnly": true, + "isSystemDefined": true, + "isUpdateable": false, + "obfuscationProperties": { + "maskType": "None", + "maskTypeID": 0, + "storageTypeID": 1, + "storageType": "Plain", + "valueDefinitionID": "a685d645-31e2-e611-80cc-1402ec7222b4" + }, + "ordinal": 6, + "parentDefinition": { + "definitionID": "a185d645-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "PredictiveIntelScores", + "definitionName": { + "value": "Predictive Scores" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "updated_at", + "storageFieldReferenceID": { + "type": "guid", + "value": "d6fefe2f-e2d5-42bb-bee2-5dd8da16b8e4" + }, + "valueDefinitionID": "a685d645-31e2-e611-80cc-1402ec7222b4", + "valueDefinitionKey": "Updated At", + "name": "Updated At", + "setDefinitionID": "a185d645-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "PredictiveIntelScores", + "setDefinitionName": { + "value": "Predictive Scores" + }, + "parentIdentifier": "a185d645-31e2-e611-80cc-1402ec7222b4" + } + ], + "applicationID": "f4981f88-a13e-4abf-b331-47f41c73258d", + "applicationKey": "com.exacttarget.Predictive Web", + "attributeCount": 0, + "canAddValues": false, + "canChangeValues": false, + "canModify": false, + "canRemove": false, + "categoryID": 386, + "createdBy": -1000, + "createDate": "2017-01-24T06:33:00", + "customObjectOwnerMID": 1111111, + "dataRetentionProperties": { + "isRowBasedRetention": false, + "isResetRetentionPeriodOnImport": false, + "isDeleteAtEndOfRetentionPeriod": false, + "periodUnitOfMeasure": 4, + "setDefinitionID": "a185d645-31e2-e611-80cc-1402ec7222b4" + }, + "localizedDescription": {}, + "fullyQualifiedName": "Predictive Scores", + "isCustomObjectBacked": true, + "isEvent": false, + "isHidden": false, + "isReadOnly": true, + "isRoot": false, + "isSendable": false, + "isShared": false, + "isSystemDefined": true, + "isTestaable": false, + "parentID": "00000000-0000-0000-0000-000000000000", + "relationshipCount": 1, + "storageLogicalType": "DataExtension", + "storageName": "PREDICTIVE_SCORES", + "storageObjectIDs": ["9a85d645-31e2-e611-80cc-1402ec7222b4"], + "storageReferenceID": { + "type": "guid", + "value": "de52de3f-31e2-e611-80cc-1402ec7222b4" + }, + "setDefinitionID": "a185d645-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "PredictiveIntelScores", + "name": "Predictive Scores" + }, + { + "definitionID": "b151de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "EmailDemographics", + "definitionName": { + "value": "Email Demographics" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "relationships": [ + { + "canModify": false, + "canRemove": false, + "isHidden": false, + "isSystemDefined": false, + "isGroupToSetRelationship": true, + "leftItem": { + "cardinality": "One", + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "identifier": "b451de3f-31e2-e611-80cc-1402ec7222b4", + "relationshipType": "AttributeGroup" + }, + "leftRelationshipIDs": [ + { + "type": "int16", + "value": "2" + } + ], + "leftRelationshipReferenceType": "CustomerData", + "relationshipAttributes": [ + { + "leftAttributeID": "9293dc39-31e2-e611-80cc-1402ec7222b4", + "leftConnectingID": { + "identifierType": "FullyQualifiedName" + }, + "rightAttributeID": "b351de3f-31e2-e611-80cc-1402ec7222b4", + "rightConnectingID": { + "identifierType": "FullyQualifiedName" + } + } + ], + "relationshipID": "b751de3f-31e2-e611-80cc-1402ec7222b4", + "rightItem": { + "cardinality": "One", + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "identifier": "b151de3f-31e2-e611-80cc-1402ec7222b4", + "relationshipType": "AttributeSet" + } + } + ], + "valueDefinitions": [ + { + "baseType": "Numeric", + "dataSourceID": 2, + "dataSourceName": {}, + "dataType": "LongNumber", + "description": "", + "localizedDescription": { + "value": "" + }, + "definitionID": "b351de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "ContactsID", + "definitionName": { + "value": "Contacts ID" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 0, + "fullyQualifiedName": "Email Demographics.Contacts ID", + "isHidden": false, + "isIdentityValue": false, + "isNullable": false, + "isPrimaryKey": true, + "isReadOnly": false, + "isSystemDefined": true, + "isUpdateable": true, + "ordinal": 0, + "parentDefinition": { + "definitionID": "b151de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "EmailDemographics", + "definitionName": { + "value": "Email Demographics" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "_SubscriberID", + "valueDefinitionID": "b351de3f-31e2-e611-80cc-1402ec7222b4", + "valueDefinitionKey": "ContactsID", + "name": "Contacts ID", + "setDefinitionID": "b151de3f-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "EmailDemographics", + "setDefinitionName": { + "value": "Email Demographics" + }, + "parentIdentifier": "b151de3f-31e2-e611-80cc-1402ec7222b4" + }, + { + "baseType": "Text", + "dataSourceID": 2, + "dataSourceName": {}, + "dataType": "Text", + "description": "", + "localizedDescription": { + "value": "" + }, + "definitionID": "b4e96cfc-85f7-e611-80cc-1402ec7222b4", + "definitionKey": "First Name", + "definitionName": { + "value": "First Name" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 1, + "fullyQualifiedName": "Email Demographics.First Name", + "isHidden": false, + "isIdentityValue": false, + "isNullable": true, + "isPrimaryKey": false, + "isReadOnly": false, + "isSystemDefined": false, + "isUpdateable": true, + "length": 100, + "obfuscationProperties": { + "maskType": "None", + "maskTypeID": 0, + "storageTypeID": 1, + "storageType": "Plain", + "valueDefinitionID": "b4e96cfc-85f7-e611-80cc-1402ec7222b4" + }, + "ordinal": 1, + "parentDefinition": { + "definitionID": "b151de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "EmailDemographics", + "definitionName": { + "value": "Email Demographics" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "First Name", + "storageFieldReferenceID": { + "type": "guid", + "value": "eef81ae9-14e8-47b3-bede-5a691614c7c3" + }, + "storageFieldValueID": { + "type": "int32", + "value": "10025" + }, + "valueDefinitionID": "b4e96cfc-85f7-e611-80cc-1402ec7222b4", + "valueDefinitionKey": "First Name", + "name": "First Name", + "setDefinitionID": "b151de3f-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "EmailDemographics", + "setDefinitionName": { + "value": "Email Demographics" + }, + "parentIdentifier": "b151de3f-31e2-e611-80cc-1402ec7222b4" + }, + { + "baseType": "Text", + "dataSourceID": 2, + "dataSourceName": {}, + "dataType": "Text", + "description": "", + "localizedDescription": { + "value": "" + }, + "definitionID": "b6e96cfc-85f7-e611-80cc-1402ec7222b4", + "definitionKey": "Last Name", + "definitionName": { + "value": "Last Name" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 2, + "fullyQualifiedName": "Email Demographics.Last Name", + "isHidden": false, + "isIdentityValue": false, + "isNullable": true, + "isPrimaryKey": false, + "isReadOnly": false, + "isSystemDefined": false, + "isUpdateable": true, + "length": 100, + "obfuscationProperties": { + "maskType": "None", + "maskTypeID": 0, + "storageTypeID": 1, + "storageType": "Plain", + "valueDefinitionID": "b6e96cfc-85f7-e611-80cc-1402ec7222b4" + }, + "ordinal": 2, + "parentDefinition": { + "definitionID": "b151de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "EmailDemographics", + "definitionName": { + "value": "Email Demographics" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "Last Name", + "storageFieldReferenceID": { + "type": "guid", + "value": "4434d534-4fb8-4ec4-9ffc-fe386781f8ef" + }, + "storageFieldValueID": { + "type": "int32", + "value": "10026" + }, + "valueDefinitionID": "b6e96cfc-85f7-e611-80cc-1402ec7222b4", + "valueDefinitionKey": "Last Name", + "name": "Last Name", + "setDefinitionID": "b151de3f-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "EmailDemographics", + "setDefinitionName": { + "value": "Email Demographics" + }, + "parentIdentifier": "b151de3f-31e2-e611-80cc-1402ec7222b4" + }, + { + "baseType": "Text", + "dataSourceID": 2, + "dataSourceName": {}, + "dataType": "Text", + "description": "", + "localizedDescription": { + "value": "" + }, + "definitionID": "b2e96cfc-85f7-e611-80cc-1402ec7222b4", + "definitionKey": "Language", + "definitionName": { + "value": "Language" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 3, + "fullyQualifiedName": "Email Demographics.Language", + "isHidden": false, + "isIdentityValue": false, + "isNullable": true, + "isPrimaryKey": false, + "isReadOnly": false, + "isSystemDefined": false, + "isUpdateable": true, + "length": 50, + "obfuscationProperties": { + "maskType": "None", + "maskTypeID": 0, + "storageTypeID": 1, + "storageType": "Plain", + "valueDefinitionID": "b2e96cfc-85f7-e611-80cc-1402ec7222b4" + }, + "ordinal": 3, + "parentDefinition": { + "definitionID": "b151de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "EmailDemographics", + "definitionName": { + "value": "Email Demographics" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "Language", + "storageFieldReferenceID": { + "type": "guid", + "value": "4b06d940-5f23-461f-859d-9c2aeee53525" + }, + "storageFieldValueID": { + "type": "int32", + "value": "10027" + }, + "valueDefinitionID": "b2e96cfc-85f7-e611-80cc-1402ec7222b4", + "valueDefinitionKey": "Language", + "name": "Language", + "setDefinitionID": "b151de3f-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "EmailDemographics", + "setDefinitionName": { + "value": "Email Demographics" + }, + "parentIdentifier": "b151de3f-31e2-e611-80cc-1402ec7222b4" + }, + { + "baseType": "Text", + "dataSourceID": 2, + "dataSourceName": {}, + "dataType": "Text", + "description": "", + "localizedDescription": { + "value": "" + }, + "definitionID": "720e6c78-9709-e711-80cc-1402ec7222b4", + "definitionKey": "Transaction Points1", + "definitionName": { + "value": "Transaction Points" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 6, + "fullyQualifiedName": "Email Demographics.Transaction Points", + "isHidden": false, + "isIdentityValue": false, + "isNullable": true, + "isPrimaryKey": false, + "isReadOnly": false, + "isSystemDefined": false, + "isUpdateable": true, + "length": 256, + "obfuscationProperties": { + "maskType": "None", + "maskTypeID": 0, + "storageTypeID": 1, + "storageType": "Plain", + "valueDefinitionID": "720e6c78-9709-e711-80cc-1402ec7222b4" + }, + "ordinal": 6, + "parentDefinition": { + "definitionID": "b151de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "EmailDemographics", + "definitionName": { + "value": "Email Demographics" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "Transaction Points", + "storageFieldReferenceID": { + "type": "guid", + "value": "fdcb28a8-59fd-489a-bdce-b286bccc147e" + }, + "storageFieldValueID": { + "type": "int32", + "value": "10033" + }, + "valueDefinitionID": "720e6c78-9709-e711-80cc-1402ec7222b4", + "valueDefinitionKey": "Transaction Points1", + "name": "Transaction Points", + "setDefinitionID": "b151de3f-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "EmailDemographics", + "setDefinitionName": { + "value": "Email Demographics" + }, + "parentIdentifier": "b151de3f-31e2-e611-80cc-1402ec7222b4" + }, + { + "baseType": "Text", + "dataSourceID": 2, + "dataSourceName": {}, + "dataType": "Text", + "description": "", + "localizedDescription": { + "value": "" + }, + "definitionID": "f05cc16f-8a14-e711-80cc-1402ec7222b4", + "definitionKey": "Market", + "definitionName": { + "value": "Market" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 7, + "fullyQualifiedName": "Email Demographics.Market", + "isHidden": false, + "isIdentityValue": false, + "isNullable": true, + "isPrimaryKey": false, + "isReadOnly": false, + "isSystemDefined": false, + "isUpdateable": true, + "length": 50, + "obfuscationProperties": { + "maskType": "None", + "maskTypeID": 0, + "storageTypeID": 1, + "storageType": "Plain", + "valueDefinitionID": "f05cc16f-8a14-e711-80cc-1402ec7222b4" + }, + "ordinal": 7, + "parentDefinition": { + "definitionID": "b151de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "EmailDemographics", + "definitionName": { + "value": "Email Demographics" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "Market", + "storageFieldReferenceID": { + "type": "guid", + "value": "d6f80d57-488f-401b-822b-1b556d631d1c" + }, + "storageFieldValueID": { + "type": "int32", + "value": "10034" + }, + "valueDefinitionID": "f05cc16f-8a14-e711-80cc-1402ec7222b4", + "valueDefinitionKey": "Market", + "name": "Market", + "setDefinitionID": "b151de3f-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "EmailDemographics", + "setDefinitionName": { + "value": "Email Demographics" + }, + "parentIdentifier": "b151de3f-31e2-e611-80cc-1402ec7222b4" + }, + { + "baseType": "Text", + "dataSourceID": 2, + "dataSourceName": {}, + "dataType": "Text", + "description": "", + "localizedDescription": { + "value": "" + }, + "definitionID": "32c8b204-85ff-e711-80d0-1402ec7222b5", + "definitionKey": "SFOrg", + "definitionName": { + "value": "SFOrg" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 8, + "fullyQualifiedName": "Email Demographics.SFOrg", + "isHidden": false, + "isIdentityValue": false, + "isNullable": true, + "isPrimaryKey": false, + "isReadOnly": false, + "isSystemDefined": false, + "isUpdateable": true, + "length": 50, + "obfuscationProperties": { + "maskType": "None", + "maskTypeID": 0, + "storageTypeID": 1, + "storageType": "Plain", + "valueDefinitionID": "32c8b204-85ff-e711-80d0-1402ec7222b5" + }, + "ordinal": 8, + "parentDefinition": { + "definitionID": "b151de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "EmailDemographics", + "definitionName": { + "value": "Email Demographics" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "SFOrg", + "storageFieldReferenceID": { + "type": "guid", + "value": "5d1032d3-5c92-4de4-bfb8-0e377f4483e2" + }, + "storageFieldValueID": { + "type": "int32", + "value": "10081" + }, + "valueDefinitionID": "32c8b204-85ff-e711-80d0-1402ec7222b5", + "valueDefinitionKey": "SFOrg", + "name": "SFOrg", + "setDefinitionID": "b151de3f-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "EmailDemographics", + "setDefinitionName": { + "value": "Email Demographics" + }, + "parentIdentifier": "b151de3f-31e2-e611-80cc-1402ec7222b4" + }, + { + "baseType": "Text", + "dataSourceID": 2, + "dataSourceName": {}, + "dataType": "Text", + "description": "", + "localizedDescription": { + "value": "" + }, + "definitionID": "8775d770-e194-e911-a2cf-1402ec94ecf1", + "definitionKey": "Username", + "definitionName": { + "value": "Username" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 9, + "fullyQualifiedName": "Email Demographics.Username", + "isHidden": false, + "isIdentityValue": false, + "isNullable": true, + "isPrimaryKey": false, + "isReadOnly": false, + "isSystemDefined": false, + "isUpdateable": true, + "length": 255, + "obfuscationProperties": { + "maskType": "None", + "maskTypeID": 0, + "storageTypeID": 1, + "storageType": "Plain", + "valueDefinitionID": "8775d770-e194-e911-a2cf-1402ec94ecf1" + }, + "ordinal": 9, + "parentDefinition": { + "definitionID": "b151de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "EmailDemographics", + "definitionName": { + "value": "Email Demographics" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "Username", + "storageFieldReferenceID": { + "type": "guid", + "value": "55ac244c-2afd-4134-8495-9c1c188debdc" + }, + "storageFieldValueID": { + "type": "int32", + "value": "10299" + }, + "valueDefinitionID": "8775d770-e194-e911-a2cf-1402ec94ecf1", + "valueDefinitionKey": "Username", + "name": "Username", + "setDefinitionID": "b151de3f-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "EmailDemographics", + "setDefinitionName": { + "value": "Email Demographics" + }, + "parentIdentifier": "b151de3f-31e2-e611-80cc-1402ec7222b4" + }, + { + "baseType": "Text", + "dataSourceID": 2, + "dataSourceName": {}, + "dataType": "Text", + "description": "", + "localizedDescription": { + "value": "" + }, + "definitionID": "570dea88-6e94-ea11-a2e5-1402ec9386e5", + "definitionKey": "Account Id", + "definitionName": { + "value": "Account Id" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 10, + "fullyQualifiedName": "Email Demographics.Account Id", + "isHidden": false, + "isIdentityValue": false, + "isNullable": true, + "isPrimaryKey": false, + "isReadOnly": false, + "isSystemDefined": false, + "isUpdateable": true, + "length": 50, + "obfuscationProperties": { + "maskType": "None", + "maskTypeID": 0, + "storageTypeID": 1, + "storageType": "Plain", + "valueDefinitionID": "570dea88-6e94-ea11-a2e5-1402ec9386e5" + }, + "ordinal": 10, + "parentDefinition": { + "definitionID": "b151de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "EmailDemographics", + "definitionName": { + "value": "Email Demographics" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "Account Id", + "storageFieldReferenceID": { + "type": "guid", + "value": "eb2f7e92-f7f8-435c-835a-3c24d5e003d5" + }, + "storageFieldValueID": { + "type": "int32", + "value": "10334" + }, + "valueDefinitionID": "570dea88-6e94-ea11-a2e5-1402ec9386e5", + "valueDefinitionKey": "Account Id", + "name": "Account Id", + "setDefinitionID": "b151de3f-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "EmailDemographics", + "setDefinitionName": { + "value": "Email Demographics" + }, + "parentIdentifier": "b151de3f-31e2-e611-80cc-1402ec7222b4" + }, + { + "baseType": "Text", + "dataSourceID": 2, + "dataSourceName": {}, + "dataType": "Text", + "description": "", + "localizedDescription": { + "value": "" + }, + "definitionID": "74c1c047-9e94-ea11-a2e5-1402ec9386e5", + "definitionKey": "AccountId", + "definitionName": { + "value": "AccountId" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 10, + "fullyQualifiedName": "Email Demographics.AccountId", + "isHidden": false, + "isIdentityValue": false, + "isNullable": true, + "isPrimaryKey": false, + "isReadOnly": false, + "isSystemDefined": false, + "isUpdateable": true, + "length": 50, + "obfuscationProperties": { + "maskType": "None", + "maskTypeID": 0, + "storageTypeID": 1, + "storageType": "Plain", + "valueDefinitionID": "74c1c047-9e94-ea11-a2e5-1402ec9386e5" + }, + "ordinal": 10, + "parentDefinition": { + "definitionID": "b151de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "EmailDemographics", + "definitionName": { + "value": "Email Demographics" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "Account Id", + "storageFieldReferenceID": { + "type": "guid", + "value": "eb2f7e92-f7f8-435c-835a-3c24d5e003d5" + }, + "storageFieldValueID": { + "type": "int32", + "value": "10334" + }, + "valueDefinitionID": "74c1c047-9e94-ea11-a2e5-1402ec9386e5", + "valueDefinitionKey": "AccountId", + "name": "AccountId", + "setDefinitionID": "b151de3f-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "EmailDemographics", + "setDefinitionName": { + "value": "Email Demographics" + }, + "parentIdentifier": "b151de3f-31e2-e611-80cc-1402ec7222b4" + }, + { + "baseType": "Text", + "dataSourceID": 2, + "dataSourceName": {}, + "dataType": "Text", + "description": "", + "localizedDescription": { + "value": "" + }, + "definitionID": "560dea88-6e94-ea11-a2e5-1402ec9386e5", + "definitionKey": "Preferred language", + "definitionName": { + "value": "Preferred language" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 12, + "fullyQualifiedName": "Email Demographics.Preferred language", + "isHidden": false, + "isIdentityValue": false, + "isNullable": true, + "isPrimaryKey": false, + "isReadOnly": false, + "isSystemDefined": false, + "isUpdateable": true, + "length": 50, + "obfuscationProperties": { + "maskType": "None", + "maskTypeID": 0, + "storageTypeID": 1, + "storageType": "Plain", + "valueDefinitionID": "560dea88-6e94-ea11-a2e5-1402ec9386e5" + }, + "ordinal": 12, + "parentDefinition": { + "definitionID": "b151de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "EmailDemographics", + "definitionName": { + "value": "Email Demographics" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "Preferred language", + "storageFieldReferenceID": { + "type": "guid", + "value": "be1fac02-93ef-4c9e-b06d-22757e1aeda8" + }, + "storageFieldValueID": { + "type": "int32", + "value": "10336" + }, + "valueDefinitionID": "560dea88-6e94-ea11-a2e5-1402ec9386e5", + "valueDefinitionKey": "Preferred language", + "name": "Preferred language", + "setDefinitionID": "b151de3f-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "EmailDemographics", + "setDefinitionName": { + "value": "Email Demographics" + }, + "parentIdentifier": "b151de3f-31e2-e611-80cc-1402ec7222b4" + }, + { + "baseType": "Text", + "dataSourceID": 2, + "dataSourceName": {}, + "dataType": "Text", + "description": "", + "localizedDescription": { + "value": "" + }, + "definitionID": "550dea88-6e94-ea11-a2e5-1402ec9386e5", + "definitionKey": "Flex Parameter 1", + "definitionName": { + "value": "Flex Parameter 1" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 13, + "fullyQualifiedName": "Email Demographics.Flex Parameter 1", + "isHidden": false, + "isIdentityValue": false, + "isNullable": true, + "isPrimaryKey": false, + "isReadOnly": false, + "isSystemDefined": false, + "isUpdateable": true, + "length": 100, + "obfuscationProperties": { + "maskType": "None", + "maskTypeID": 0, + "storageTypeID": 1, + "storageType": "Plain", + "valueDefinitionID": "550dea88-6e94-ea11-a2e5-1402ec9386e5" + }, + "ordinal": 13, + "parentDefinition": { + "definitionID": "b151de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "EmailDemographics", + "definitionName": { + "value": "Email Demographics" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "Flex Parameter 1", + "storageFieldReferenceID": { + "type": "guid", + "value": "96436704-494e-4bb1-914a-3ad6994bbf2d" + }, + "storageFieldValueID": { + "type": "int32", + "value": "10337" + }, + "valueDefinitionID": "550dea88-6e94-ea11-a2e5-1402ec9386e5", + "valueDefinitionKey": "Flex Parameter 1", + "name": "Flex Parameter 1", + "setDefinitionID": "b151de3f-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "EmailDemographics", + "setDefinitionName": { + "value": "Email Demographics" + }, + "parentIdentifier": "b151de3f-31e2-e611-80cc-1402ec7222b4" + }, + { + "baseType": "Text", + "dataSourceID": 2, + "dataSourceName": {}, + "dataType": "Text", + "description": "", + "localizedDescription": { + "value": "" + }, + "definitionID": "866d4451-7d94-ea11-a2e5-1402ec9386e5", + "definitionKey": "Flex Parameter 2", + "definitionName": { + "value": "Flex Parameter 2" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 14, + "fullyQualifiedName": "Email Demographics.Flex Parameter 2", + "isHidden": false, + "isIdentityValue": false, + "isNullable": true, + "isPrimaryKey": false, + "isReadOnly": false, + "isSystemDefined": false, + "isUpdateable": true, + "length": 100, + "obfuscationProperties": { + "maskType": "None", + "maskTypeID": 0, + "storageTypeID": 1, + "storageType": "Plain", + "valueDefinitionID": "866d4451-7d94-ea11-a2e5-1402ec9386e5" + }, + "ordinal": 14, + "parentDefinition": { + "definitionID": "b151de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "EmailDemographics", + "definitionName": { + "value": "Email Demographics" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "Flex Parameter 2", + "storageFieldReferenceID": { + "type": "guid", + "value": "02a5b26c-05f6-426b-8735-de6033503f8f" + }, + "storageFieldValueID": { + "type": "int32", + "value": "10338" + }, + "valueDefinitionID": "866d4451-7d94-ea11-a2e5-1402ec9386e5", + "valueDefinitionKey": "Flex Parameter 2", + "name": "Flex Parameter 2", + "setDefinitionID": "b151de3f-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "EmailDemographics", + "setDefinitionName": { + "value": "Email Demographics" + }, + "parentIdentifier": "b151de3f-31e2-e611-80cc-1402ec7222b4" + }, + { + "baseType": "Text", + "dataSourceID": 2, + "dataSourceName": {}, + "dataType": "Text", + "description": "", + "localizedDescription": { + "value": "" + }, + "definitionID": "876d4451-7d94-ea11-a2e5-1402ec9386e5", + "definitionKey": "Flex Parameter 3", + "definitionName": { + "value": "Flex Parameter 3" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 15, + "fullyQualifiedName": "Email Demographics.Flex Parameter 3", + "isHidden": false, + "isIdentityValue": false, + "isNullable": true, + "isPrimaryKey": false, + "isReadOnly": false, + "isSystemDefined": false, + "isUpdateable": true, + "length": 100, + "obfuscationProperties": { + "maskType": "None", + "maskTypeID": 0, + "storageTypeID": 1, + "storageType": "Plain", + "valueDefinitionID": "876d4451-7d94-ea11-a2e5-1402ec9386e5" + }, + "ordinal": 15, + "parentDefinition": { + "definitionID": "b151de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "EmailDemographics", + "definitionName": { + "value": "Email Demographics" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "Flex Parameter 3", + "storageFieldReferenceID": { + "type": "guid", + "value": "058f7489-c272-466c-88ce-b528b5b17955" + }, + "storageFieldValueID": { + "type": "int32", + "value": "10339" + }, + "valueDefinitionID": "876d4451-7d94-ea11-a2e5-1402ec9386e5", + "valueDefinitionKey": "Flex Parameter 3", + "name": "Flex Parameter 3", + "setDefinitionID": "b151de3f-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "EmailDemographics", + "setDefinitionName": { + "value": "Email Demographics" + }, + "parentIdentifier": "b151de3f-31e2-e611-80cc-1402ec7222b4" + }, + { + "baseType": "Text", + "dataSourceID": 2, + "dataSourceName": {}, + "dataType": "Text", + "description": "", + "localizedDescription": { + "value": "" + }, + "definitionID": "886d4451-7d94-ea11-a2e5-1402ec9386e5", + "definitionKey": "Flex Parameter 4", + "definitionName": { + "value": "Flex Parameter 4" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 16, + "fullyQualifiedName": "Email Demographics.Flex Parameter 4", + "isHidden": false, + "isIdentityValue": false, + "isNullable": true, + "isPrimaryKey": false, + "isReadOnly": false, + "isSystemDefined": false, + "isUpdateable": true, + "length": 100, + "obfuscationProperties": { + "maskType": "None", + "maskTypeID": 0, + "storageTypeID": 1, + "storageType": "Plain", + "valueDefinitionID": "886d4451-7d94-ea11-a2e5-1402ec9386e5" + }, + "ordinal": 16, + "parentDefinition": { + "definitionID": "b151de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "EmailDemographics", + "definitionName": { + "value": "Email Demographics" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "Flex Parameter 4", + "storageFieldReferenceID": { + "type": "guid", + "value": "2702b318-539d-4fe3-9c52-c7ba3e32a949" + }, + "storageFieldValueID": { + "type": "int32", + "value": "10340" + }, + "valueDefinitionID": "886d4451-7d94-ea11-a2e5-1402ec9386e5", + "valueDefinitionKey": "Flex Parameter 4", + "name": "Flex Parameter 4", + "setDefinitionID": "b151de3f-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "EmailDemographics", + "setDefinitionName": { + "value": "Email Demographics" + }, + "parentIdentifier": "b151de3f-31e2-e611-80cc-1402ec7222b4" + }, + { + "baseType": "Text", + "dataSourceID": 2, + "dataSourceName": {}, + "dataType": "Text", + "description": "", + "localizedDescription": { + "value": "" + }, + "definitionID": "1a4f88cd-a194-ea11-a2e5-1402ec9386e5", + "definitionKey": "Contact Role", + "definitionName": { + "value": "Contact Role" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 17, + "fullyQualifiedName": "Email Demographics.Contact Role", + "isHidden": false, + "isIdentityValue": false, + "isNullable": true, + "isPrimaryKey": false, + "isReadOnly": false, + "isSystemDefined": false, + "isUpdateable": true, + "length": 100, + "obfuscationProperties": { + "maskType": "None", + "maskTypeID": 0, + "storageTypeID": 1, + "storageType": "Plain", + "valueDefinitionID": "1a4f88cd-a194-ea11-a2e5-1402ec9386e5" + }, + "ordinal": 17, + "parentDefinition": { + "definitionID": "b151de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "EmailDemographics", + "definitionName": { + "value": "Email Demographics" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "Contact Role", + "storageFieldReferenceID": { + "type": "guid", + "value": "f3412d1f-bf50-4e3a-8db8-7e1bc15e019b" + }, + "storageFieldValueID": { + "type": "int32", + "value": "10341" + }, + "valueDefinitionID": "1a4f88cd-a194-ea11-a2e5-1402ec9386e5", + "valueDefinitionKey": "Contact Role", + "name": "Contact Role", + "setDefinitionID": "b151de3f-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "EmailDemographics", + "setDefinitionName": { + "value": "Email Demographics" + }, + "parentIdentifier": "b151de3f-31e2-e611-80cc-1402ec7222b4" + } + ], + "applicationID": "b2ca1f50-3cc4-4fd7-a3a3-88bf09fb59fa", + "applicationKey": "com.exacttarget.email", + "attributeCount": 0, + "canAddValues": true, + "canChangeValues": true, + "canModify": false, + "canRemove": false, + "categoryID": 2, + "createdBy": -1000, + "createDate": "2017-01-24T06:33:00", + "dataRetentionProperties": { + "isRowBasedRetention": false, + "isResetRetentionPeriodOnImport": false, + "isDeleteAtEndOfRetentionPeriod": false, + "periodUnitOfMeasure": 0, + "setDefinitionID": "b151de3f-31e2-e611-80cc-1402ec7222b4" + }, + "localizedDescription": {}, + "fullyQualifiedName": "Email Demographics", + "isCustomObjectBacked": false, + "isEvent": false, + "isHidden": false, + "isReadOnly": false, + "isRoot": false, + "isSendable": false, + "isShared": false, + "isSystemDefined": true, + "isTestaable": false, + "parentID": "00000000-0000-0000-0000-000000000000", + "relationshipCount": 1, + "storageLogicalType": "EnterpriseAttributes", + "storageName": "_EnterpriseAttribute", + "storageObjectIDs": ["b051de3f-31e2-e611-80cc-1402ec7222b4"], + "storageReferenceID": { + "type": "guid", + "value": "1ba7e67d-2647-4537-beb3-b0c5bac65d3c" + }, + "setDefinitionID": "b151de3f-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "EmailDemographics", + "name": "Email Demographics" + }, + { + "definitionID": "b285d645-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "PredictiveIntelProductViews", + "definitionName": { + "value": "Predictive Intelligence Product Views" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "relationships": [ + { + "canModify": false, + "canRemove": false, + "isHidden": false, + "isSystemDefined": false, + "isGroupToSetRelationship": false, + "leftItem": { + "cardinality": "One", + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "identifier": "b285d645-31e2-e611-80cc-1402ec7222b4", + "relationshipType": "AttributeSet" + }, + "relationshipAttributes": [ + { + "leftAttributeID": "b485d645-31e2-e611-80cc-1402ec7222b4", + "leftConnectingID": { + "identifierType": "FullyQualifiedName" + }, + "rightAttributeID": "7886d645-31e2-e611-80cc-1402ec7222b4", + "rightConnectingID": { + "identifierType": "FullyQualifiedName" + } + } + ], + "relationshipID": "7d86d645-31e2-e611-80cc-1402ec7222b4", + "rightItem": { + "cardinality": "Many", + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "identifier": "7586d645-31e2-e611-80cc-1402ec7222b4", + "relationshipType": "AttributeSet" + } + }, + { + "canModify": false, + "canRemove": false, + "isHidden": false, + "isSystemDefined": false, + "isGroupToSetRelationship": false, + "leftItem": { + "cardinality": "Many", + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "identifier": "b285d645-31e2-e611-80cc-1402ec7222b4", + "relationshipType": "AttributeSet" + }, + "relationshipAttributes": [ + { + "leftAttributeID": "b585d645-31e2-e611-80cc-1402ec7222b4", + "leftConnectingID": { + "identifierType": "FullyQualifiedName" + }, + "rightAttributeID": "c885d645-31e2-e611-80cc-1402ec7222b4", + "rightConnectingID": { + "identifierType": "FullyQualifiedName" + } + } + ], + "relationshipID": "cd85d645-31e2-e611-80cc-1402ec7222b4", + "rightItem": { + "cardinality": "One", + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "identifier": "c485d645-31e2-e611-80cc-1402ec7222b4", + "relationshipType": "AttributeSet" + } + } + ], + "valueDefinitions": [ + { + "baseType": "Numeric", + "dataSourceID": 1, + "dataSourceName": {}, + "dataType": "LongNumber", + "description": "", + "localizedDescription": { + "value": "" + }, + "definitionID": "b885d645-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "CustomObjectKey", + "definitionName": { + "value": "Custom Object Key" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 1, + "fullyQualifiedName": "Predictive Intelligence Product Views.Custom Object Key", + "isHidden": true, + "isIdentityValue": true, + "isNullable": false, + "isPrimaryKey": false, + "isReadOnly": true, + "isSystemDefined": true, + "isUpdateable": false, + "ordinal": 1, + "parentDefinition": { + "definitionID": "b285d645-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "PredictiveIntelProductViews", + "definitionName": { + "value": "Predictive Intelligence Product Views" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "_CustomObjectKey", + "valueDefinitionID": "b885d645-31e2-e611-80cc-1402ec7222b4", + "valueDefinitionKey": "CustomObjectKey", + "name": "Custom Object Key", + "setDefinitionID": "b285d645-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "PredictiveIntelProductViews", + "setDefinitionName": { + "value": "Predictive Intelligence Product Views" + }, + "parentIdentifier": "b285d645-31e2-e611-80cc-1402ec7222b4" + }, + { + "baseType": "Text", + "dataSourceID": 5, + "dataSourceName": {}, + "dataType": "Text", + "description": "sku", + "localizedDescription": { + "value": "sku" + }, + "definitionID": "b585d645-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "SKU", + "definitionName": { + "value": "SKU" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 2, + "fullyQualifiedName": "Predictive Intelligence Product Views.SKU", + "isHidden": false, + "isIdentityValue": false, + "isNullable": true, + "isPrimaryKey": false, + "isReadOnly": true, + "isSystemDefined": true, + "isUpdateable": false, + "length": 256, + "obfuscationProperties": { + "maskType": "None", + "maskTypeID": 0, + "storageTypeID": 1, + "storageType": "Plain", + "valueDefinitionID": "b585d645-31e2-e611-80cc-1402ec7222b4" + }, + "ordinal": 2, + "parentDefinition": { + "definitionID": "b285d645-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "PredictiveIntelProductViews", + "definitionName": { + "value": "Predictive Intelligence Product Views" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "sku", + "storageFieldReferenceID": { + "type": "guid", + "value": "f8553b64-8076-449d-aea0-450aed1a793c" + }, + "valueDefinitionID": "b585d645-31e2-e611-80cc-1402ec7222b4", + "valueDefinitionKey": "SKU", + "name": "SKU", + "setDefinitionID": "b285d645-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "PredictiveIntelProductViews", + "setDefinitionName": { + "value": "Predictive Intelligence Product Views" + }, + "parentIdentifier": "b285d645-31e2-e611-80cc-1402ec7222b4" + }, + { + "baseType": "Text", + "dataSourceID": 5, + "dataSourceName": {}, + "dataType": "Text", + "description": "user_id", + "localizedDescription": { + "value": "user_id" + }, + "definitionID": "b785d645-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "User_ID", + "definitionName": { + "value": "User ID" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 3, + "fullyQualifiedName": "Predictive Intelligence Product Views.User ID", + "isHidden": false, + "isIdentityValue": false, + "isNullable": false, + "isPrimaryKey": true, + "isReadOnly": true, + "isSystemDefined": true, + "isUpdateable": false, + "length": 256, + "obfuscationProperties": { + "maskType": "None", + "maskTypeID": 0, + "storageTypeID": 1, + "storageType": "Plain", + "valueDefinitionID": "b785d645-31e2-e611-80cc-1402ec7222b4" + }, + "ordinal": 3, + "parentDefinition": { + "definitionID": "b285d645-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "PredictiveIntelProductViews", + "definitionName": { + "value": "Predictive Intelligence Product Views" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "user_id", + "storageFieldReferenceID": { + "type": "guid", + "value": "f8e9c116-3218-4064-92e4-dcccaf730a4f" + }, + "valueDefinitionID": "b785d645-31e2-e611-80cc-1402ec7222b4", + "valueDefinitionKey": "User_ID", + "name": "User ID", + "setDefinitionID": "b285d645-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "PredictiveIntelProductViews", + "setDefinitionName": { + "value": "Predictive Intelligence Product Views" + }, + "parentIdentifier": "b285d645-31e2-e611-80cc-1402ec7222b4" + }, + { + "baseType": "Text", + "dataSourceID": 5, + "dataSourceName": {}, + "dataType": "Text", + "description": "session_id", + "localizedDescription": { + "value": "session_id" + }, + "definitionID": "b485d645-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "Session_ID", + "definitionName": { + "value": "Session ID" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 4, + "fullyQualifiedName": "Predictive Intelligence Product Views.Session ID", + "isHidden": false, + "isIdentityValue": false, + "isNullable": true, + "isPrimaryKey": false, + "isReadOnly": true, + "isSystemDefined": true, + "isUpdateable": false, + "length": 256, + "obfuscationProperties": { + "maskType": "None", + "maskTypeID": 0, + "storageTypeID": 1, + "storageType": "Plain", + "valueDefinitionID": "b485d645-31e2-e611-80cc-1402ec7222b4" + }, + "ordinal": 4, + "parentDefinition": { + "definitionID": "b285d645-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "PredictiveIntelProductViews", + "definitionName": { + "value": "Predictive Intelligence Product Views" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "session_id", + "storageFieldReferenceID": { + "type": "guid", + "value": "bbca44f6-6353-464d-aba1-4285ae5072b6" + }, + "valueDefinitionID": "b485d645-31e2-e611-80cc-1402ec7222b4", + "valueDefinitionKey": "Session_ID", + "name": "Session ID", + "setDefinitionID": "b285d645-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "PredictiveIntelProductViews", + "setDefinitionName": { + "value": "Predictive Intelligence Product Views" + }, + "parentIdentifier": "b285d645-31e2-e611-80cc-1402ec7222b4" + }, + { + "baseType": "Text", + "dataSourceID": 5, + "dataSourceName": {}, + "dataType": "Text", + "description": "Search", + "localizedDescription": { + "value": "Search" + }, + "definitionID": "b385d645-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "Search", + "definitionName": { + "value": "Search" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 5, + "fullyQualifiedName": "Predictive Intelligence Product Views.Search", + "isHidden": false, + "isIdentityValue": false, + "isNullable": true, + "isPrimaryKey": false, + "isReadOnly": true, + "isSystemDefined": true, + "isUpdateable": false, + "length": 1000, + "obfuscationProperties": { + "maskType": "None", + "maskTypeID": 0, + "storageTypeID": 1, + "storageType": "Plain", + "valueDefinitionID": "b385d645-31e2-e611-80cc-1402ec7222b4" + }, + "ordinal": 5, + "parentDefinition": { + "definitionID": "b285d645-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "PredictiveIntelProductViews", + "definitionName": { + "value": "Predictive Intelligence Product Views" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "Search", + "storageFieldReferenceID": { + "type": "guid", + "value": "68949690-06d5-452d-b4c7-b8daab2f3681" + }, + "valueDefinitionID": "b385d645-31e2-e611-80cc-1402ec7222b4", + "valueDefinitionKey": "Search", + "name": "Search", + "setDefinitionID": "b285d645-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "PredictiveIntelProductViews", + "setDefinitionName": { + "value": "Predictive Intelligence Product Views" + }, + "parentIdentifier": "b285d645-31e2-e611-80cc-1402ec7222b4" + }, + { + "baseType": "Date", + "dataSourceID": 5, + "dataSourceName": {}, + "dataType": "Date", + "description": "Timestamp", + "localizedDescription": { + "value": "Timestamp" + }, + "definitionID": "b685d645-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "Timestamp", + "definitionName": { + "value": "Timestamp" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 6, + "fullyQualifiedName": "Predictive Intelligence Product Views.Timestamp", + "isHidden": false, + "isIdentityValue": false, + "isNullable": false, + "isPrimaryKey": true, + "isReadOnly": true, + "isSystemDefined": true, + "isUpdateable": false, + "obfuscationProperties": { + "maskType": "None", + "maskTypeID": 0, + "storageTypeID": 1, + "storageType": "Plain", + "valueDefinitionID": "b685d645-31e2-e611-80cc-1402ec7222b4" + }, + "ordinal": 6, + "parentDefinition": { + "definitionID": "b285d645-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "PredictiveIntelProductViews", + "definitionName": { + "value": "Predictive Intelligence Product Views" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "Timestamp", + "storageFieldReferenceID": { + "type": "guid", + "value": "4fb7775d-277f-4f87-ba60-da24b120ba49" + }, + "valueDefinitionID": "b685d645-31e2-e611-80cc-1402ec7222b4", + "valueDefinitionKey": "Timestamp", + "name": "Timestamp", + "setDefinitionID": "b285d645-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "PredictiveIntelProductViews", + "setDefinitionName": { + "value": "Predictive Intelligence Product Views" + }, + "parentIdentifier": "b285d645-31e2-e611-80cc-1402ec7222b4" + } + ], + "applicationID": "f4981f88-a13e-4abf-b331-47f41c73258d", + "applicationKey": "com.exacttarget.Predictive Web", + "attributeCount": 0, + "canAddValues": false, + "canChangeValues": false, + "canModify": false, + "canRemove": false, + "categoryID": 386, + "createdBy": -1000, + "createDate": "2017-01-24T06:33:00", + "customObjectOwnerMID": 1111111, + "dataRetentionProperties": { + "isRowBasedRetention": false, + "isResetRetentionPeriodOnImport": false, + "isDeleteAtEndOfRetentionPeriod": false, + "periodUnitOfMeasure": 4, + "setDefinitionID": "b285d645-31e2-e611-80cc-1402ec7222b4" + }, + "localizedDescription": {}, + "fullyQualifiedName": "Predictive Intelligence Product Views", + "isCustomObjectBacked": true, + "isEvent": false, + "isHidden": false, + "isReadOnly": true, + "isRoot": false, + "isSendable": false, + "isShared": false, + "isSystemDefined": true, + "isTestaable": false, + "parentID": "00000000-0000-0000-0000-000000000000", + "relationshipCount": 2, + "storageLogicalType": "DataExtension", + "storageName": "IGO_VIEWS", + "storageObjectIDs": ["ab85d645-31e2-e611-80cc-1402ec7222b4"], + "storageReferenceID": { + "type": "guid", + "value": "d552de3f-31e2-e611-80cc-1402ec7222b4" + }, + "setDefinitionID": "b285d645-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "PredictiveIntelProductViews", + "name": "Predictive Intelligence Product Views" + }, + { + "definitionID": "b352de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "PushSubscriptions", + "definitionName": { + "value": "MobilePush Subscriptions" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "valueDefinitions": [ + { + "baseType": "Text", + "dataSourceID": 3, + "dataSourceName": {}, + "dataType": "Text", + "description": "", + "localizedDescription": { + "value": "" + }, + "definitionID": "b452de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "PushAppID", + "definitionName": { + "value": "Application" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 2, + "fullyQualifiedName": "MobilePush Subscriptions.Application", + "isHidden": false, + "isIdentityValue": false, + "isNullable": false, + "isPrimaryKey": true, + "isReadOnly": true, + "isSystemDefined": true, + "isUpdateable": false, + "length": 38, + "obfuscationProperties": { + "maskType": "None", + "maskTypeID": 0, + "storageTypeID": 1, + "storageType": "Plain", + "valueDefinitionID": "b452de3f-31e2-e611-80cc-1402ec7222b4" + }, + "ordinal": 2, + "parentDefinition": { + "definitionID": "b352de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "PushSubscriptions", + "definitionName": { + "value": "MobilePush Subscriptions" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "restrictionLookupListID": 11, + "storageName": "_APID", + "storageFieldReferenceID": { + "type": "guid", + "value": "4e82734e-ff8a-4868-a786-20e9596a94d2" + }, + "valueDefinitionID": "b452de3f-31e2-e611-80cc-1402ec7222b4", + "valueDefinitionKey": "PushAppID", + "name": "Application", + "setDefinitionID": "b352de3f-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "PushSubscriptions", + "setDefinitionName": { + "value": "MobilePush Subscriptions" + }, + "parentIdentifier": "b352de3f-31e2-e611-80cc-1402ec7222b4" + }, + { + "baseType": "Numeric", + "dataSourceID": 3, + "dataSourceName": {}, + "dataType": "LongNumber", + "description": "", + "localizedDescription": { + "value": "" + }, + "definitionID": "bb52de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "CustomObjectKey", + "definitionName": { + "value": "Custom Object Key" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 9, + "fullyQualifiedName": "MobilePush Subscriptions.Custom Object Key", + "isHidden": true, + "isIdentityValue": true, + "isNullable": false, + "isPrimaryKey": false, + "isReadOnly": true, + "isSystemDefined": true, + "isUpdateable": false, + "ordinal": 9, + "parentDefinition": { + "definitionID": "b352de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "PushSubscriptions", + "definitionName": { + "value": "MobilePush Subscriptions" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "_CustomObjectKey", + "valueDefinitionID": "bb52de3f-31e2-e611-80cc-1402ec7222b4", + "valueDefinitionKey": "CustomObjectKey", + "name": "Custom Object Key", + "setDefinitionID": "b352de3f-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "PushSubscriptions", + "setDefinitionName": { + "value": "MobilePush Subscriptions" + }, + "parentIdentifier": "b352de3f-31e2-e611-80cc-1402ec7222b4" + }, + { + "baseType": "Text", + "dataSourceID": 3, + "dataSourceName": {}, + "dataType": "Text", + "description": "", + "localizedDescription": { + "value": "" + }, + "definitionID": "b552de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "PushDeviceID", + "definitionName": { + "value": "Device ID" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 11, + "fullyQualifiedName": "MobilePush Subscriptions.Device ID", + "isHidden": false, + "isIdentityValue": false, + "isNullable": false, + "isPrimaryKey": true, + "isReadOnly": true, + "isSystemDefined": true, + "isUpdateable": false, + "length": 200, + "obfuscationProperties": { + "maskType": "None", + "maskTypeID": 0, + "storageTypeID": 1, + "storageType": "Plain", + "valueDefinitionID": "b552de3f-31e2-e611-80cc-1402ec7222b4" + }, + "ordinal": 11, + "parentDefinition": { + "definitionID": "b352de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "PushSubscriptions", + "definitionName": { + "value": "MobilePush Subscriptions" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "_DeviceID", + "storageFieldReferenceID": { + "type": "guid", + "value": "9d8db1d4-c00e-49bc-98d9-e30d2e3ed7cf" + }, + "valueDefinitionID": "b552de3f-31e2-e611-80cc-1402ec7222b4", + "valueDefinitionKey": "PushDeviceID", + "name": "Device ID", + "setDefinitionID": "b352de3f-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "PushSubscriptions", + "setDefinitionName": { + "value": "MobilePush Subscriptions" + }, + "parentIdentifier": "b352de3f-31e2-e611-80cc-1402ec7222b4" + }, + { + "baseType": "Date", + "dataSourceID": 3, + "dataSourceName": {}, + "dataType": "Date", + "description": "", + "localizedDescription": { + "value": "" + }, + "definitionID": "b652de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "OptInDate", + "definitionName": { + "value": "Opt In Date" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 20, + "fullyQualifiedName": "MobilePush Subscriptions.Opt In Date", + "isHidden": false, + "isIdentityValue": false, + "isNullable": true, + "isPrimaryKey": false, + "isReadOnly": true, + "isSystemDefined": true, + "isUpdateable": false, + "obfuscationProperties": { + "maskType": "None", + "maskTypeID": 0, + "storageTypeID": 1, + "storageType": "Plain", + "valueDefinitionID": "b652de3f-31e2-e611-80cc-1402ec7222b4" + }, + "ordinal": 20, + "parentDefinition": { + "definitionID": "b352de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "PushSubscriptions", + "definitionName": { + "value": "MobilePush Subscriptions" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "_OptInDate", + "storageFieldReferenceID": { + "type": "guid", + "value": "68c6681d-6f0f-4ec2-9407-55c5eb19fc19" + }, + "valueDefinitionID": "b652de3f-31e2-e611-80cc-1402ec7222b4", + "valueDefinitionKey": "OptInDate", + "name": "Opt In Date", + "setDefinitionID": "b352de3f-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "PushSubscriptions", + "setDefinitionName": { + "value": "MobilePush Subscriptions" + }, + "parentIdentifier": "b352de3f-31e2-e611-80cc-1402ec7222b4" + }, + { + "baseType": "Numeric", + "dataSourceID": 3, + "dataSourceName": {}, + "dataType": "Byte", + "description": "", + "localizedDescription": { + "value": "" + }, + "definitionID": "b752de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "OptInMethodID", + "definitionName": { + "value": "Opt In Method" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 21, + "fullyQualifiedName": "MobilePush Subscriptions.Opt In Method", + "isHidden": false, + "isIdentityValue": false, + "isNullable": true, + "isPrimaryKey": false, + "isReadOnly": true, + "isSystemDefined": true, + "isUpdateable": false, + "obfuscationProperties": { + "maskType": "None", + "maskTypeID": 0, + "storageTypeID": 1, + "storageType": "Plain", + "valueDefinitionID": "b752de3f-31e2-e611-80cc-1402ec7222b4" + }, + "ordinal": 21, + "parentDefinition": { + "definitionID": "b352de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "PushSubscriptions", + "definitionName": { + "value": "MobilePush Subscriptions" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "restrictionLookupListID": 9, + "storageName": "_OptInMethodID", + "storageFieldReferenceID": { + "type": "guid", + "value": "8b821a18-6cee-4204-9ef9-18d94112e84f" + }, + "valueDefinitionID": "b752de3f-31e2-e611-80cc-1402ec7222b4", + "valueDefinitionKey": "OptInMethodID", + "name": "Opt In Method", + "setDefinitionID": "b352de3f-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "PushSubscriptions", + "setDefinitionName": { + "value": "MobilePush Subscriptions" + }, + "parentIdentifier": "b352de3f-31e2-e611-80cc-1402ec7222b4" + }, + { + "baseType": "Numeric", + "dataSourceID": 3, + "dataSourceName": {}, + "dataType": "Byte", + "description": "", + "localizedDescription": { + "value": "" + }, + "definitionID": "b852de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "OptInStatusID", + "definitionName": { + "value": "Opt In Status" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 22, + "fullyQualifiedName": "MobilePush Subscriptions.Opt In Status", + "isHidden": false, + "isIdentityValue": false, + "isNullable": false, + "isPrimaryKey": false, + "isReadOnly": false, + "isSystemDefined": true, + "isUpdateable": false, + "obfuscationProperties": { + "maskType": "None", + "maskTypeID": 0, + "storageTypeID": 1, + "storageType": "Plain", + "valueDefinitionID": "b852de3f-31e2-e611-80cc-1402ec7222b4" + }, + "ordinal": 22, + "parentDefinition": { + "definitionID": "b352de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "PushSubscriptions", + "definitionName": { + "value": "MobilePush Subscriptions" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "restrictionLookupListID": 8, + "storageName": "_OptInStatusID", + "storageFieldReferenceID": { + "type": "guid", + "value": "673470b8-8503-4c4c-b9ae-9bf554d0a235" + }, + "valueDefinitionID": "b852de3f-31e2-e611-80cc-1402ec7222b4", + "valueDefinitionKey": "OptInStatusID", + "name": "Opt In Status", + "setDefinitionID": "b352de3f-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "PushSubscriptions", + "setDefinitionName": { + "value": "MobilePush Subscriptions" + }, + "parentIdentifier": "b352de3f-31e2-e611-80cc-1402ec7222b4" + }, + { + "baseType": "Date", + "dataSourceID": 3, + "dataSourceName": {}, + "dataType": "Date", + "description": "", + "localizedDescription": { + "value": "" + }, + "definitionID": "b952de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "OptOutDate", + "definitionName": { + "value": "Opt Out Date" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 23, + "fullyQualifiedName": "MobilePush Subscriptions.Opt Out Date", + "isHidden": false, + "isIdentityValue": false, + "isNullable": true, + "isPrimaryKey": false, + "isReadOnly": true, + "isSystemDefined": true, + "isUpdateable": false, + "obfuscationProperties": { + "maskType": "None", + "maskTypeID": 0, + "storageTypeID": 1, + "storageType": "Plain", + "valueDefinitionID": "b952de3f-31e2-e611-80cc-1402ec7222b4" + }, + "ordinal": 23, + "parentDefinition": { + "definitionID": "b352de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "PushSubscriptions", + "definitionName": { + "value": "MobilePush Subscriptions" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "_OptOutDate", + "storageFieldReferenceID": { + "type": "guid", + "value": "8424262e-6904-4915-a4b3-2957b044b3ee" + }, + "valueDefinitionID": "b952de3f-31e2-e611-80cc-1402ec7222b4", + "valueDefinitionKey": "OptOutDate", + "name": "Opt Out Date", + "setDefinitionID": "b352de3f-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "PushSubscriptions", + "setDefinitionName": { + "value": "MobilePush Subscriptions" + }, + "parentIdentifier": "b352de3f-31e2-e611-80cc-1402ec7222b4" + }, + { + "baseType": "Numeric", + "dataSourceID": 3, + "dataSourceName": {}, + "dataType": "Byte", + "description": "", + "localizedDescription": { + "value": "" + }, + "definitionID": "ba52de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "OptOutMethodID", + "definitionName": { + "value": "Opt Out Method" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 24, + "fullyQualifiedName": "MobilePush Subscriptions.Opt Out Method", + "isHidden": false, + "isIdentityValue": false, + "isNullable": true, + "isPrimaryKey": false, + "isReadOnly": true, + "isSystemDefined": true, + "isUpdateable": false, + "obfuscationProperties": { + "maskType": "None", + "maskTypeID": 0, + "storageTypeID": 1, + "storageType": "Plain", + "valueDefinitionID": "ba52de3f-31e2-e611-80cc-1402ec7222b4" + }, + "ordinal": 24, + "parentDefinition": { + "definitionID": "b352de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "PushSubscriptions", + "definitionName": { + "value": "MobilePush Subscriptions" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "restrictionLookupListID": 10, + "storageName": "_OptOutMethodID", + "storageFieldReferenceID": { + "type": "guid", + "value": "3919bba5-e953-435d-8874-66be31cb1821" + }, + "valueDefinitionID": "ba52de3f-31e2-e611-80cc-1402ec7222b4", + "valueDefinitionKey": "OptOutMethodID", + "name": "Opt Out Method", + "setDefinitionID": "b352de3f-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "PushSubscriptions", + "setDefinitionName": { + "value": "MobilePush Subscriptions" + }, + "parentIdentifier": "b352de3f-31e2-e611-80cc-1402ec7222b4" + } + ], + "applicationID": "2051892d-5de2-4ecf-98af-8ca9a40d2c9c", + "applicationKey": "com.exacttarget.mobilepush", + "attributeCount": 0, + "canAddValues": false, + "canChangeValues": false, + "canModify": false, + "canRemove": false, + "categoryID": 2, + "createdBy": -1000, + "createDate": "2017-01-24T06:33:00", + "customObjectOwnerMID": 1111111, + "dataRetentionProperties": { + "isRowBasedRetention": false, + "isResetRetentionPeriodOnImport": false, + "isDeleteAtEndOfRetentionPeriod": false, + "setDefinitionID": "b352de3f-31e2-e611-80cc-1402ec7222b4" + }, + "localizedDescription": {}, + "fullyQualifiedName": "MobilePush Subscriptions", + "isCustomObjectBacked": true, + "isEvent": false, + "isHidden": false, + "isReadOnly": false, + "isRoot": false, + "isSendable": false, + "isShared": false, + "isSystemDefined": true, + "isTestaable": false, + "parentID": "00000000-0000-0000-0000-000000000000", + "relationshipCount": 0, + "sendAttributeStorageName": "_ContactID", + "sendContactKeyStorageName": "_SubscriberID", + "storageLogicalType": "PushAttributes", + "storageName": "_PushAddress", + "storageObjectIDs": ["4851de3f-31e2-e611-80cc-1402ec7222b4"], + "storageReferenceID": { + "type": "guid", + "value": "7893dc39-31e2-e611-80cc-1402ec7222b4" + }, + "setDefinitionID": "b352de3f-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "PushSubscriptions", + "name": "MobilePush Subscriptions" + }, + { + "definitionID": "c485d645-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "PredictiveIntelProducts", + "definitionName": { + "value": "Predictive Intelligence Products" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "relationships": [ + { + "canModify": false, + "canRemove": false, + "isHidden": false, + "isSystemDefined": false, + "isGroupToSetRelationship": false, + "leftItem": { + "cardinality": "One", + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "identifier": "c485d645-31e2-e611-80cc-1402ec7222b4", + "relationshipType": "AttributeSet" + }, + "relationshipAttributes": [ + { + "leftAttributeID": "c885d645-31e2-e611-80cc-1402ec7222b4", + "leftConnectingID": { + "identifierType": "FullyQualifiedName" + }, + "rightAttributeID": "da85d645-31e2-e611-80cc-1402ec7222b4", + "rightConnectingID": { + "identifierType": "FullyQualifiedName" + } + } + ], + "relationshipID": "de85d645-31e2-e611-80cc-1402ec7222b4", + "rightItem": { + "cardinality": "Many", + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "identifier": "d685d645-31e2-e611-80cc-1402ec7222b4", + "relationshipType": "AttributeSet" + } + } + ], + "valueDefinitions": [ + { + "baseType": "Numeric", + "dataSourceID": 1, + "dataSourceName": {}, + "dataType": "LongNumber", + "description": "", + "localizedDescription": { + "value": "" + }, + "definitionID": "cb85d645-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "CustomObjectKey", + "definitionName": { + "value": "Custom Object Key" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 1, + "fullyQualifiedName": "Predictive Intelligence Products.Custom Object Key", + "isHidden": true, + "isIdentityValue": true, + "isNullable": false, + "isPrimaryKey": false, + "isReadOnly": true, + "isSystemDefined": true, + "isUpdateable": false, + "ordinal": 1, + "parentDefinition": { + "definitionID": "c485d645-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "PredictiveIntelProducts", + "definitionName": { + "value": "Predictive Intelligence Products" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "_CustomObjectKey", + "valueDefinitionID": "cb85d645-31e2-e611-80cc-1402ec7222b4", + "valueDefinitionKey": "CustomObjectKey", + "name": "Custom Object Key", + "setDefinitionID": "c485d645-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "PredictiveIntelProducts", + "setDefinitionName": { + "value": "Predictive Intelligence Products" + }, + "parentIdentifier": "c485d645-31e2-e611-80cc-1402ec7222b4" + }, + { + "baseType": "Text", + "dataSourceID": 5, + "dataSourceName": {}, + "dataType": "Text", + "description": "name", + "localizedDescription": { + "value": "name" + }, + "definitionID": "c585d645-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "Name", + "definitionName": { + "value": "Name" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 2, + "fullyQualifiedName": "Predictive Intelligence Products.Name", + "isHidden": false, + "isIdentityValue": false, + "isNullable": true, + "isPrimaryKey": false, + "isReadOnly": true, + "isSystemDefined": true, + "isUpdateable": false, + "length": 1000, + "obfuscationProperties": { + "maskType": "None", + "maskTypeID": 0, + "storageTypeID": 1, + "storageType": "Plain", + "valueDefinitionID": "c585d645-31e2-e611-80cc-1402ec7222b4" + }, + "ordinal": 2, + "parentDefinition": { + "definitionID": "c485d645-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "PredictiveIntelProducts", + "definitionName": { + "value": "Predictive Intelligence Products" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "name", + "storageFieldReferenceID": { + "type": "guid", + "value": "116f93a1-da7c-4b0a-876c-7f6f107881c5" + }, + "valueDefinitionID": "c585d645-31e2-e611-80cc-1402ec7222b4", + "valueDefinitionKey": "Name", + "name": "Name", + "setDefinitionID": "c485d645-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "PredictiveIntelProducts", + "setDefinitionName": { + "value": "Predictive Intelligence Products" + }, + "parentIdentifier": "c485d645-31e2-e611-80cc-1402ec7222b4" + }, + { + "baseType": "Numeric", + "dataSourceID": 5, + "dataSourceName": {}, + "dataType": "Decimal", + "description": "regPrice", + "localizedDescription": { + "value": "regPrice" + }, + "definitionID": "c685d645-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "Regular_Price", + "definitionName": { + "value": "Regular Price" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 3, + "fullyQualifiedName": "Predictive Intelligence Products.Regular Price", + "isHidden": false, + "isIdentityValue": false, + "isNullable": true, + "isPrimaryKey": false, + "isReadOnly": true, + "isSystemDefined": true, + "isUpdateable": false, + "length": 18, + "obfuscationProperties": { + "maskType": "None", + "maskTypeID": 0, + "storageTypeID": 1, + "storageType": "Plain", + "valueDefinitionID": "c685d645-31e2-e611-80cc-1402ec7222b4" + }, + "ordinal": 3, + "parentDefinition": { + "definitionID": "c485d645-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "PredictiveIntelProducts", + "definitionName": { + "value": "Predictive Intelligence Products" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "scale": 2, + "storageName": "regPrice", + "storageFieldReferenceID": { + "type": "guid", + "value": "d651f3d5-5b32-4fd7-907d-2d6caf42f827" + }, + "valueDefinitionID": "c685d645-31e2-e611-80cc-1402ec7222b4", + "valueDefinitionKey": "Regular_Price", + "name": "Regular Price", + "setDefinitionID": "c485d645-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "PredictiveIntelProducts", + "setDefinitionName": { + "value": "Predictive Intelligence Products" + }, + "parentIdentifier": "c485d645-31e2-e611-80cc-1402ec7222b4" + }, + { + "baseType": "Numeric", + "dataSourceID": 5, + "dataSourceName": {}, + "dataType": "Decimal", + "description": "salePrice", + "localizedDescription": { + "value": "salePrice" + }, + "definitionID": "c785d645-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "Sale_Price", + "definitionName": { + "value": "Sale Price" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 4, + "fullyQualifiedName": "Predictive Intelligence Products.Sale Price", + "isHidden": false, + "isIdentityValue": false, + "isNullable": true, + "isPrimaryKey": false, + "isReadOnly": true, + "isSystemDefined": true, + "isUpdateable": false, + "length": 18, + "obfuscationProperties": { + "maskType": "None", + "maskTypeID": 0, + "storageTypeID": 1, + "storageType": "Plain", + "valueDefinitionID": "c785d645-31e2-e611-80cc-1402ec7222b4" + }, + "ordinal": 4, + "parentDefinition": { + "definitionID": "c485d645-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "PredictiveIntelProducts", + "definitionName": { + "value": "Predictive Intelligence Products" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "scale": 2, + "storageName": "salePrice", + "storageFieldReferenceID": { + "type": "guid", + "value": "b10ebf49-6195-40c2-beaa-810d2c5b39d4" + }, + "valueDefinitionID": "c785d645-31e2-e611-80cc-1402ec7222b4", + "valueDefinitionKey": "Sale_Price", + "name": "Sale Price", + "setDefinitionID": "c485d645-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "PredictiveIntelProducts", + "setDefinitionName": { + "value": "Predictive Intelligence Products" + }, + "parentIdentifier": "c485d645-31e2-e611-80cc-1402ec7222b4" + }, + { + "baseType": "Text", + "dataSourceID": 5, + "dataSourceName": {}, + "dataType": "Text", + "description": "Uuid", + "localizedDescription": { + "value": "Uuid" + }, + "definitionID": "ca85d645-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "UUID", + "definitionName": { + "value": "UUID" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 5, + "fullyQualifiedName": "Predictive Intelligence Products.UUID", + "isHidden": false, + "isIdentityValue": false, + "isNullable": false, + "isPrimaryKey": true, + "isReadOnly": true, + "isSystemDefined": true, + "isUpdateable": false, + "length": 256, + "obfuscationProperties": { + "maskType": "None", + "maskTypeID": 0, + "storageTypeID": 1, + "storageType": "Plain", + "valueDefinitionID": "ca85d645-31e2-e611-80cc-1402ec7222b4" + }, + "ordinal": 5, + "parentDefinition": { + "definitionID": "c485d645-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "PredictiveIntelProducts", + "definitionName": { + "value": "Predictive Intelligence Products" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "Uuid", + "storageFieldReferenceID": { + "type": "guid", + "value": "7fc0495c-f03d-496a-a74d-770a9e672518" + }, + "valueDefinitionID": "ca85d645-31e2-e611-80cc-1402ec7222b4", + "valueDefinitionKey": "UUID", + "name": "UUID", + "setDefinitionID": "c485d645-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "PredictiveIntelProducts", + "setDefinitionName": { + "value": "Predictive Intelligence Products" + }, + "parentIdentifier": "c485d645-31e2-e611-80cc-1402ec7222b4" + }, + { + "baseType": "Text", + "dataSourceID": 5, + "dataSourceName": {}, + "dataType": "Text", + "description": "sku", + "localizedDescription": { + "value": "sku" + }, + "definitionID": "c885d645-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "SKU", + "definitionName": { + "value": "SKU" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 6, + "fullyQualifiedName": "Predictive Intelligence Products.SKU", + "isHidden": false, + "isIdentityValue": false, + "isNullable": false, + "isPrimaryKey": false, + "isReadOnly": true, + "isSystemDefined": true, + "isUpdateable": false, + "length": 256, + "obfuscationProperties": { + "maskType": "None", + "maskTypeID": 0, + "storageTypeID": 1, + "storageType": "Plain", + "valueDefinitionID": "c885d645-31e2-e611-80cc-1402ec7222b4" + }, + "ordinal": 6, + "parentDefinition": { + "definitionID": "c485d645-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "PredictiveIntelProducts", + "definitionName": { + "value": "Predictive Intelligence Products" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "sku", + "storageFieldReferenceID": { + "type": "guid", + "value": "603870ea-b2e0-4613-bb22-08f582f34a94" + }, + "valueDefinitionID": "c885d645-31e2-e611-80cc-1402ec7222b4", + "valueDefinitionKey": "SKU", + "name": "SKU", + "setDefinitionID": "c485d645-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "PredictiveIntelProducts", + "setDefinitionName": { + "value": "Predictive Intelligence Products" + }, + "parentIdentifier": "c485d645-31e2-e611-80cc-1402ec7222b4" + }, + { + "baseType": "Text", + "dataSourceID": 5, + "dataSourceName": {}, + "dataType": "Text", + "description": "type", + "localizedDescription": { + "value": "type" + }, + "definitionID": "c985d645-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "Type", + "definitionName": { + "value": "Type" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 7, + "fullyQualifiedName": "Predictive Intelligence Products.Type", + "isHidden": false, + "isIdentityValue": false, + "isNullable": false, + "isPrimaryKey": false, + "isReadOnly": true, + "isSystemDefined": true, + "isUpdateable": false, + "length": 50, + "obfuscationProperties": { + "maskType": "None", + "maskTypeID": 0, + "storageTypeID": 1, + "storageType": "Plain", + "valueDefinitionID": "c985d645-31e2-e611-80cc-1402ec7222b4" + }, + "ordinal": 7, + "parentDefinition": { + "definitionID": "c485d645-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "PredictiveIntelProducts", + "definitionName": { + "value": "Predictive Intelligence Products" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "type", + "storageFieldReferenceID": { + "type": "guid", + "value": "9f3e8ffe-c631-4397-ab2e-8cbc50d7f6c1" + }, + "valueDefinitionID": "c985d645-31e2-e611-80cc-1402ec7222b4", + "valueDefinitionKey": "Type", + "name": "Type", + "setDefinitionID": "c485d645-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "PredictiveIntelProducts", + "setDefinitionName": { + "value": "Predictive Intelligence Products" + }, + "parentIdentifier": "c485d645-31e2-e611-80cc-1402ec7222b4" + } + ], + "applicationID": "f4981f88-a13e-4abf-b331-47f41c73258d", + "applicationKey": "com.exacttarget.Predictive Web", + "attributeCount": 0, + "canAddValues": false, + "canChangeValues": false, + "canModify": false, + "canRemove": false, + "categoryID": 386, + "createdBy": -1000, + "createDate": "2017-01-24T06:33:00", + "customObjectOwnerMID": 1111111, + "dataRetentionProperties": { + "isRowBasedRetention": false, + "isResetRetentionPeriodOnImport": false, + "isDeleteAtEndOfRetentionPeriod": false, + "periodUnitOfMeasure": 4, + "setDefinitionID": "c485d645-31e2-e611-80cc-1402ec7222b4" + }, + "localizedDescription": {}, + "fullyQualifiedName": "Predictive Intelligence Products", + "isCustomObjectBacked": true, + "isEvent": false, + "isHidden": false, + "isReadOnly": true, + "isRoot": false, + "isSendable": false, + "isShared": false, + "isSystemDefined": true, + "isTestaable": false, + "parentID": "00000000-0000-0000-0000-000000000000", + "relationshipCount": 1, + "storageLogicalType": "DataExtension", + "storageName": "IGO_PRODUCTS", + "storageObjectIDs": ["bc85d645-31e2-e611-80cc-1402ec7222b4"], + "storageReferenceID": { + "type": "guid", + "value": "d852de3f-31e2-e611-80cc-1402ec7222b4" + }, + "setDefinitionID": "c485d645-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "PredictiveIntelProducts", + "name": "Predictive Intelligence Products" + }, + { + "definitionID": "c652de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "PushTags", + "definitionName": { + "value": "MobilePush Tags" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "valueDefinitions": [ + { + "baseType": "Text", + "dataSourceID": 3, + "dataSourceName": {}, + "dataType": "Text", + "description": "", + "localizedDescription": { + "value": "" + }, + "definitionID": "c752de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "PushAppID", + "definitionName": { + "value": "Application" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 1, + "fullyQualifiedName": "MobilePush Tags.Application", + "isHidden": false, + "isIdentityValue": false, + "isNullable": false, + "isPrimaryKey": false, + "isReadOnly": true, + "isSystemDefined": true, + "isUpdateable": false, + "length": 38, + "obfuscationProperties": { + "maskType": "None", + "maskTypeID": 0, + "storageTypeID": 1, + "storageType": "Plain", + "valueDefinitionID": "c752de3f-31e2-e611-80cc-1402ec7222b4" + }, + "ordinal": 1, + "parentDefinition": { + "definitionID": "c652de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "PushTags", + "definitionName": { + "value": "MobilePush Tags" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "restrictionLookupListID": 11, + "storageName": "_APID", + "storageFieldReferenceID": { + "type": "guid", + "value": "7f711754-1b97-4c7d-86d8-507f9fcb877d" + }, + "valueDefinitionID": "c752de3f-31e2-e611-80cc-1402ec7222b4", + "valueDefinitionKey": "PushAppID", + "name": "Application", + "setDefinitionID": "c652de3f-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "PushTags", + "setDefinitionName": { + "value": "MobilePush Tags" + }, + "parentIdentifier": "c652de3f-31e2-e611-80cc-1402ec7222b4" + }, + { + "baseType": "Numeric", + "dataSourceID": 3, + "dataSourceName": {}, + "dataType": "LongNumber", + "description": "", + "localizedDescription": { + "value": "" + }, + "definitionID": "ce52de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "CustomObjectKey", + "definitionName": { + "value": "Custom Object Key" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 2, + "fullyQualifiedName": "MobilePush Tags.Custom Object Key", + "isHidden": true, + "isIdentityValue": true, + "isNullable": false, + "isPrimaryKey": false, + "isReadOnly": true, + "isSystemDefined": true, + "isUpdateable": false, + "ordinal": 2, + "parentDefinition": { + "definitionID": "c652de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "PushTags", + "definitionName": { + "value": "MobilePush Tags" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "_CustomObjectKey", + "valueDefinitionID": "ce52de3f-31e2-e611-80cc-1402ec7222b4", + "valueDefinitionKey": "CustomObjectKey", + "name": "Custom Object Key", + "setDefinitionID": "c652de3f-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "PushTags", + "setDefinitionName": { + "value": "MobilePush Tags" + }, + "parentIdentifier": "c652de3f-31e2-e611-80cc-1402ec7222b4" + }, + { + "baseType": "Numeric", + "dataSourceID": 3, + "dataSourceName": {}, + "dataType": "LongNumber", + "description": "", + "localizedDescription": { + "value": "" + }, + "definitionID": "c852de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "CreatedBy", + "definitionName": { + "value": "Created By" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 3, + "fullyQualifiedName": "MobilePush Tags.Created By", + "isHidden": true, + "isIdentityValue": false, + "isNullable": true, + "isPrimaryKey": false, + "isReadOnly": true, + "isSystemDefined": true, + "isUpdateable": false, + "obfuscationProperties": { + "maskType": "None", + "maskTypeID": 0, + "storageTypeID": 1, + "storageType": "Plain", + "valueDefinitionID": "c852de3f-31e2-e611-80cc-1402ec7222b4" + }, + "ordinal": 3, + "parentDefinition": { + "definitionID": "c652de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "PushTags", + "definitionName": { + "value": "MobilePush Tags" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "_CreatedBy", + "storageFieldReferenceID": { + "type": "guid", + "value": "dbc7917c-95cd-4294-b116-eb215d1c5c0b" + }, + "valueDefinitionID": "c852de3f-31e2-e611-80cc-1402ec7222b4", + "valueDefinitionKey": "CreatedBy", + "name": "Created By", + "setDefinitionID": "c652de3f-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "PushTags", + "setDefinitionName": { + "value": "MobilePush Tags" + }, + "parentIdentifier": "c652de3f-31e2-e611-80cc-1402ec7222b4" + }, + { + "baseType": "Date", + "dataSourceID": 3, + "dataSourceName": {}, + "dataType": "Date", + "defaultValue": "GETDATE()", + "description": "", + "localizedDescription": { + "value": "" + }, + "definitionID": "c952de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "CreatedDate", + "definitionName": { + "value": "Created Date" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 4, + "fullyQualifiedName": "MobilePush Tags.Created Date", + "isHidden": true, + "isIdentityValue": false, + "isNullable": false, + "isPrimaryKey": false, + "isReadOnly": true, + "isSystemDefined": true, + "isUpdateable": false, + "obfuscationProperties": { + "maskType": "None", + "maskTypeID": 0, + "storageTypeID": 1, + "storageType": "Plain", + "valueDefinitionID": "c952de3f-31e2-e611-80cc-1402ec7222b4" + }, + "ordinal": 4, + "parentDefinition": { + "definitionID": "c652de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "PushTags", + "definitionName": { + "value": "MobilePush Tags" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "_CreatedDate", + "storageFieldReferenceID": { + "type": "guid", + "value": "30e22e41-0415-4d8a-b817-c56b0bffa168" + }, + "valueDefinitionID": "c952de3f-31e2-e611-80cc-1402ec7222b4", + "valueDefinitionKey": "CreatedDate", + "name": "Created Date", + "setDefinitionID": "c652de3f-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "PushTags", + "setDefinitionName": { + "value": "MobilePush Tags" + }, + "parentIdentifier": "c652de3f-31e2-e611-80cc-1402ec7222b4" + }, + { + "baseType": "Text", + "dataSourceID": 3, + "dataSourceName": {}, + "dataType": "Text", + "description": "", + "localizedDescription": { + "value": "" + }, + "definitionID": "ca52de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "PushDeviceID", + "definitionName": { + "value": "Device ID" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 5, + "fullyQualifiedName": "MobilePush Tags.Device ID", + "isHidden": false, + "isIdentityValue": false, + "isNullable": false, + "isPrimaryKey": false, + "isReadOnly": true, + "isSystemDefined": true, + "isUpdateable": false, + "length": 200, + "obfuscationProperties": { + "maskType": "None", + "maskTypeID": 0, + "storageTypeID": 1, + "storageType": "Plain", + "valueDefinitionID": "ca52de3f-31e2-e611-80cc-1402ec7222b4" + }, + "ordinal": 5, + "parentDefinition": { + "definitionID": "c652de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "PushTags", + "definitionName": { + "value": "MobilePush Tags" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "_DeviceID", + "storageFieldReferenceID": { + "type": "guid", + "value": "ee23b0fd-76ad-46b5-9e14-aef0e17ec28f" + }, + "valueDefinitionID": "ca52de3f-31e2-e611-80cc-1402ec7222b4", + "valueDefinitionKey": "PushDeviceID", + "name": "Device ID", + "setDefinitionID": "c652de3f-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "PushTags", + "setDefinitionName": { + "value": "MobilePush Tags" + }, + "parentIdentifier": "c652de3f-31e2-e611-80cc-1402ec7222b4" + }, + { + "baseType": "Numeric", + "dataSourceID": 3, + "dataSourceName": {}, + "dataType": "LongNumber", + "description": "", + "localizedDescription": { + "value": "" + }, + "definitionID": "cb52de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "ModifiedBy", + "definitionName": { + "value": "Modified By" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 6, + "fullyQualifiedName": "MobilePush Tags.Modified By", + "isHidden": true, + "isIdentityValue": false, + "isNullable": true, + "isPrimaryKey": false, + "isReadOnly": true, + "isSystemDefined": true, + "isUpdateable": false, + "obfuscationProperties": { + "maskType": "None", + "maskTypeID": 0, + "storageTypeID": 1, + "storageType": "Plain", + "valueDefinitionID": "cb52de3f-31e2-e611-80cc-1402ec7222b4" + }, + "ordinal": 6, + "parentDefinition": { + "definitionID": "c652de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "PushTags", + "definitionName": { + "value": "MobilePush Tags" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "_ModifiedBy", + "storageFieldReferenceID": { + "type": "guid", + "value": "36b8827e-6017-4cba-bd0f-ba2261480736" + }, + "valueDefinitionID": "cb52de3f-31e2-e611-80cc-1402ec7222b4", + "valueDefinitionKey": "ModifiedBy", + "name": "Modified By", + "setDefinitionID": "c652de3f-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "PushTags", + "setDefinitionName": { + "value": "MobilePush Tags" + }, + "parentIdentifier": "c652de3f-31e2-e611-80cc-1402ec7222b4" + }, + { + "baseType": "Date", + "dataSourceID": 3, + "dataSourceName": {}, + "dataType": "Date", + "defaultValue": "GETDATE()", + "description": "", + "localizedDescription": { + "value": "" + }, + "definitionID": "cc52de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "ModifiedDate", + "definitionName": { + "value": "Modified Date" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 7, + "fullyQualifiedName": "MobilePush Tags.Modified Date", + "isHidden": true, + "isIdentityValue": false, + "isNullable": false, + "isPrimaryKey": false, + "isReadOnly": true, + "isSystemDefined": true, + "isUpdateable": false, + "obfuscationProperties": { + "maskType": "None", + "maskTypeID": 0, + "storageTypeID": 1, + "storageType": "Plain", + "valueDefinitionID": "cc52de3f-31e2-e611-80cc-1402ec7222b4" + }, + "ordinal": 7, + "parentDefinition": { + "definitionID": "c652de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "PushTags", + "definitionName": { + "value": "MobilePush Tags" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "_ModifiedDate", + "storageFieldReferenceID": { + "type": "guid", + "value": "685ea0db-0ecb-4111-8676-0a7c0a29c79f" + }, + "valueDefinitionID": "cc52de3f-31e2-e611-80cc-1402ec7222b4", + "valueDefinitionKey": "ModifiedDate", + "name": "Modified Date", + "setDefinitionID": "c652de3f-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "PushTags", + "setDefinitionName": { + "value": "MobilePush Tags" + }, + "parentIdentifier": "c652de3f-31e2-e611-80cc-1402ec7222b4" + }, + { + "baseType": "Text", + "dataSourceID": 3, + "dataSourceName": {}, + "dataType": "Text", + "description": "", + "localizedDescription": { + "value": "" + }, + "definitionID": "cd52de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "Value", + "definitionName": { + "value": "Value" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 8, + "fullyQualifiedName": "MobilePush Tags.Value", + "isHidden": false, + "isIdentityValue": false, + "isNullable": true, + "isPrimaryKey": false, + "isReadOnly": true, + "isSystemDefined": true, + "isUpdateable": false, + "length": 128, + "obfuscationProperties": { + "maskType": "None", + "maskTypeID": 0, + "storageTypeID": 1, + "storageType": "Plain", + "valueDefinitionID": "cd52de3f-31e2-e611-80cc-1402ec7222b4" + }, + "ordinal": 8, + "parentDefinition": { + "definitionID": "c652de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "PushTags", + "definitionName": { + "value": "MobilePush Tags" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "_Value", + "storageFieldReferenceID": { + "type": "guid", + "value": "cd7e2a3c-2551-4518-96c7-5c6b0d42423e" + }, + "valueDefinitionID": "cd52de3f-31e2-e611-80cc-1402ec7222b4", + "valueDefinitionKey": "Value", + "name": "Value", + "setDefinitionID": "c652de3f-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "PushTags", + "setDefinitionName": { + "value": "MobilePush Tags" + }, + "parentIdentifier": "c652de3f-31e2-e611-80cc-1402ec7222b4" + } + ], + "applicationID": "2051892d-5de2-4ecf-98af-8ca9a40d2c9c", + "applicationKey": "com.exacttarget.mobilepush", + "attributeCount": 0, + "canAddValues": false, + "canChangeValues": false, + "canModify": false, + "canRemove": false, + "categoryID": 2, + "createdBy": -1000, + "createDate": "2017-01-24T06:33:00", + "customObjectOwnerMID": 1111111, + "dataRetentionProperties": { + "isRowBasedRetention": false, + "isResetRetentionPeriodOnImport": false, + "isDeleteAtEndOfRetentionPeriod": false, + "setDefinitionID": "c652de3f-31e2-e611-80cc-1402ec7222b4" + }, + "localizedDescription": {}, + "fullyQualifiedName": "MobilePush Tags", + "isCustomObjectBacked": true, + "isEvent": false, + "isHidden": false, + "isReadOnly": false, + "isRoot": false, + "isSendable": false, + "isShared": false, + "isSystemDefined": true, + "isTestaable": false, + "parentID": "00000000-0000-0000-0000-000000000000", + "relationshipCount": 0, + "storageLogicalType": "DataExtension", + "storageName": "_PushTag", + "storageObjectIDs": ["bd52de3f-31e2-e611-80cc-1402ec7222b4"], + "storageReferenceID": { + "type": "guid", + "value": "7993dc39-31e2-e611-80cc-1402ec7222b4" + }, + "setDefinitionID": "c652de3f-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "PushTags", + "name": "MobilePush Tags" + }, + { + "definitionID": "c9e9847d-696d-eb11-b81e-48df37d1df5a", + "definitionKey": "ChatMessageDemographics", + "definitionName": { + "value": "Chat Message Demographics" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "relationships": [ + { + "canModify": false, + "canRemove": false, + "isHidden": false, + "isSystemDefined": false, + "isGroupToSetRelationship": true, + "leftItem": { + "cardinality": "One", + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "identifier": "cae9847d-696d-eb11-b81e-48df37d1df5a", + "relationshipType": "AttributeGroup" + }, + "leftRelationshipIDs": [ + { + "type": "int16", + "value": "2" + } + ], + "leftRelationshipReferenceType": "CustomerData", + "relationshipAttributes": [ + { + "leftAttributeID": "9293dc39-31e2-e611-80cc-1402ec7222b4", + "leftConnectingID": { + "identifierType": "FullyQualifiedName" + }, + "rightAttributeID": "cee9847d-696d-eb11-b81e-48df37d1df5a", + "rightConnectingID": { + "identifierType": "FullyQualifiedName" + } + } + ], + "relationshipID": "9a42dcad-ae72-4cde-9937-193e17485ad6", + "rightItem": { + "cardinality": "Many", + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "identifier": "c9e9847d-696d-eb11-b81e-48df37d1df5a", + "relationshipType": "AttributeSet" + } + }, + { + "canModify": false, + "canRemove": false, + "isHidden": false, + "isSystemDefined": false, + "isGroupToSetRelationship": false, + "leftItem": { + "cardinality": "One", + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "identifier": "c9e9847d-696d-eb11-b81e-48df37d1df5a", + "relationshipType": "AttributeSet" + }, + "relationshipAttributes": [ + { + "leftAttributeID": "d5e9847d-696d-eb11-b81e-48df37d1df5a", + "leftConnectingID": { + "identifierType": "FullyQualifiedName" + }, + "rightAttributeID": "f7e9847d-696d-eb11-b81e-48df37d1df5a", + "rightConnectingID": { + "identifierType": "FullyQualifiedName" + } + } + ], + "relationshipID": "04ea847d-696d-eb11-b81e-48df37d1df5a", + "rightItem": { + "cardinality": "Many", + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "identifier": "f2e9847d-696d-eb11-b81e-48df37d1df5a", + "relationshipType": "AttributeSet" + } + } + ], + "valueDefinitions": [ + { + "baseType": "Numeric", + "dataSourceID": 3, + "dataSourceName": {}, + "dataType": "LongNumber", + "description": "", + "localizedDescription": { + "value": "" + }, + "definitionID": "cbe9847d-696d-eb11-b81e-48df37d1df5a", + "definitionKey": "CarrierID", + "definitionName": { + "value": "Carrier ID" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 1, + "fullyQualifiedName": "Chat Message Demographics.Carrier ID", + "isHidden": false, + "isIdentityValue": false, + "isNullable": false, + "isPrimaryKey": false, + "isReadOnly": true, + "isSystemDefined": true, + "isUpdateable": false, + "obfuscationProperties": { + "maskType": "None", + "maskTypeID": 0, + "storageTypeID": 1, + "storageType": "Plain", + "valueDefinitionID": "cbe9847d-696d-eb11-b81e-48df37d1df5a" + }, + "ordinal": 1, + "parentDefinition": { + "definitionID": "c9e9847d-696d-eb11-b81e-48df37d1df5a", + "definitionKey": "ChatMessageDemographics", + "definitionName": { + "value": "Chat Message Demographics" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "_CarrierID", + "storageFieldReferenceID": { + "type": "guid", + "value": "3fdc8842-cc0f-407c-a3ec-930d7a027d1d" + }, + "valueDefinitionID": "cbe9847d-696d-eb11-b81e-48df37d1df5a", + "valueDefinitionKey": "CarrierID", + "name": "Carrier ID", + "setDefinitionID": "c9e9847d-696d-eb11-b81e-48df37d1df5a", + "setDefinitionKey": "ChatMessageDemographics", + "setDefinitionName": { + "value": "Chat Message Demographics" + }, + "parentIdentifier": "c9e9847d-696d-eb11-b81e-48df37d1df5a" + }, + { + "baseType": "Text", + "dataSourceID": 3, + "dataSourceName": {}, + "dataType": "Text", + "description": "", + "localizedDescription": { + "value": "" + }, + "definitionID": "cce9847d-696d-eb11-b81e-48df37d1df5a", + "definitionKey": "Channel", + "definitionName": { + "value": "Channel" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 2, + "fullyQualifiedName": "Chat Message Demographics.Channel", + "isHidden": false, + "isIdentityValue": false, + "isNullable": true, + "isPrimaryKey": false, + "isReadOnly": true, + "isSystemDefined": true, + "isUpdateable": false, + "length": 20, + "obfuscationProperties": { + "maskType": "None", + "maskTypeID": 0, + "storageTypeID": 1, + "storageType": "Plain", + "valueDefinitionID": "cce9847d-696d-eb11-b81e-48df37d1df5a" + }, + "ordinal": 2, + "parentDefinition": { + "definitionID": "c9e9847d-696d-eb11-b81e-48df37d1df5a", + "definitionKey": "ChatMessageDemographics", + "definitionName": { + "value": "Chat Message Demographics" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "_Channel", + "storageFieldReferenceID": { + "type": "guid", + "value": "ef36ded9-67b2-4daf-899f-6862af8e5ee7" + }, + "valueDefinitionID": "cce9847d-696d-eb11-b81e-48df37d1df5a", + "valueDefinitionKey": "Channel", + "name": "Channel", + "setDefinitionID": "c9e9847d-696d-eb11-b81e-48df37d1df5a", + "setDefinitionKey": "ChatMessageDemographics", + "setDefinitionName": { + "value": "Chat Message Demographics" + }, + "parentIdentifier": "c9e9847d-696d-eb11-b81e-48df37d1df5a" + }, + { + "baseType": "Text", + "dataSourceID": 3, + "dataSourceName": {}, + "dataType": "Text", + "description": "", + "localizedDescription": { + "value": "" + }, + "definitionID": "cde9847d-696d-eb11-b81e-48df37d1df5a", + "definitionKey": "City", + "definitionName": { + "value": "City" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 3, + "fullyQualifiedName": "Chat Message Demographics.City", + "isHidden": false, + "isIdentityValue": false, + "isNullable": true, + "isPrimaryKey": false, + "isReadOnly": false, + "isSystemDefined": false, + "isUpdateable": false, + "length": 200, + "obfuscationProperties": { + "maskType": "None", + "maskTypeID": 0, + "storageTypeID": 1, + "storageType": "Plain", + "valueDefinitionID": "cde9847d-696d-eb11-b81e-48df37d1df5a" + }, + "ordinal": 3, + "parentDefinition": { + "definitionID": "c9e9847d-696d-eb11-b81e-48df37d1df5a", + "definitionKey": "ChatMessageDemographics", + "definitionName": { + "value": "Chat Message Demographics" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "_City", + "storageFieldReferenceID": { + "type": "guid", + "value": "be7b4554-bf03-4a80-9101-3e396b2e345f" + }, + "valueDefinitionID": "cde9847d-696d-eb11-b81e-48df37d1df5a", + "valueDefinitionKey": "City", + "name": "City", + "setDefinitionID": "c9e9847d-696d-eb11-b81e-48df37d1df5a", + "setDefinitionKey": "ChatMessageDemographics", + "setDefinitionName": { + "value": "Chat Message Demographics" + }, + "parentIdentifier": "c9e9847d-696d-eb11-b81e-48df37d1df5a" + }, + { + "baseType": "Numeric", + "dataSourceID": 3, + "dataSourceName": {}, + "dataType": "LongNumber", + "description": "", + "localizedDescription": { + "value": "" + }, + "definitionID": "cee9847d-696d-eb11-b81e-48df37d1df5a", + "definitionKey": "ContactID", + "definitionName": { + "value": "Contact ID" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 4, + "fullyQualifiedName": "Chat Message Demographics.Contact ID", + "isHidden": false, + "isIdentityValue": false, + "isNullable": false, + "isPrimaryKey": true, + "isReadOnly": true, + "isSystemDefined": true, + "isUpdateable": false, + "obfuscationProperties": { + "maskType": "None", + "maskTypeID": 0, + "storageTypeID": 1, + "storageType": "Plain", + "valueDefinitionID": "cee9847d-696d-eb11-b81e-48df37d1df5a" + }, + "ordinal": 4, + "parentDefinition": { + "definitionID": "c9e9847d-696d-eb11-b81e-48df37d1df5a", + "definitionKey": "ChatMessageDemographics", + "definitionName": { + "value": "Chat Message Demographics" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "_ContactID", + "storageFieldReferenceID": { + "type": "guid", + "value": "b0e31883-cae8-4bc5-aa24-88565d375a18" + }, + "valueDefinitionID": "cee9847d-696d-eb11-b81e-48df37d1df5a", + "valueDefinitionKey": "ContactID", + "name": "Contact ID", + "setDefinitionID": "c9e9847d-696d-eb11-b81e-48df37d1df5a", + "setDefinitionKey": "ChatMessageDemographics", + "setDefinitionName": { + "value": "Chat Message Demographics" + }, + "parentIdentifier": "c9e9847d-696d-eb11-b81e-48df37d1df5a" + }, + { + "baseType": "Numeric", + "dataSourceID": 3, + "dataSourceName": {}, + "dataType": "LongNumber", + "description": "", + "localizedDescription": { + "value": "" + }, + "definitionID": "d0e9847d-696d-eb11-b81e-48df37d1df5a", + "definitionKey": "CreatedBy", + "definitionName": { + "value": "Created By" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 5, + "fullyQualifiedName": "Chat Message Demographics.Created By", + "isHidden": true, + "isIdentityValue": false, + "isNullable": true, + "isPrimaryKey": false, + "isReadOnly": true, + "isSystemDefined": true, + "isUpdateable": false, + "obfuscationProperties": { + "maskType": "None", + "maskTypeID": 0, + "storageTypeID": 1, + "storageType": "Plain", + "valueDefinitionID": "d0e9847d-696d-eb11-b81e-48df37d1df5a" + }, + "ordinal": 5, + "parentDefinition": { + "definitionID": "c9e9847d-696d-eb11-b81e-48df37d1df5a", + "definitionKey": "ChatMessageDemographics", + "definitionName": { + "value": "Chat Message Demographics" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "_CreatedBy", + "storageFieldReferenceID": { + "type": "guid", + "value": "1671a32a-8eb0-4dc5-b30d-8ad16e55a601" + }, + "valueDefinitionID": "d0e9847d-696d-eb11-b81e-48df37d1df5a", + "valueDefinitionKey": "CreatedBy", + "name": "Created By", + "setDefinitionID": "c9e9847d-696d-eb11-b81e-48df37d1df5a", + "setDefinitionKey": "ChatMessageDemographics", + "setDefinitionName": { + "value": "Chat Message Demographics" + }, + "parentIdentifier": "c9e9847d-696d-eb11-b81e-48df37d1df5a" + }, + { + "baseType": "Date", + "dataSourceID": 3, + "dataSourceName": {}, + "dataType": "Date", + "defaultValue": "GETDATE()", + "description": "", + "localizedDescription": { + "value": "" + }, + "definitionID": "d1e9847d-696d-eb11-b81e-48df37d1df5a", + "definitionKey": "CreatedDate", + "definitionName": { + "value": "Created Date" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 6, + "fullyQualifiedName": "Chat Message Demographics.Created Date", + "isHidden": false, + "isIdentityValue": false, + "isNullable": false, + "isPrimaryKey": false, + "isReadOnly": true, + "isSystemDefined": true, + "isUpdateable": false, + "obfuscationProperties": { + "maskType": "None", + "maskTypeID": 0, + "storageTypeID": 1, + "storageType": "Plain", + "valueDefinitionID": "d1e9847d-696d-eb11-b81e-48df37d1df5a" + }, + "ordinal": 6, + "parentDefinition": { + "definitionID": "c9e9847d-696d-eb11-b81e-48df37d1df5a", + "definitionKey": "ChatMessageDemographics", + "definitionName": { + "value": "Chat Message Demographics" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "_CreatedDate", + "storageFieldReferenceID": { + "type": "guid", + "value": "de543ca5-5920-4309-adb9-33472144defe" + }, + "valueDefinitionID": "d1e9847d-696d-eb11-b81e-48df37d1df5a", + "valueDefinitionKey": "CreatedDate", + "name": "Created Date", + "setDefinitionID": "c9e9847d-696d-eb11-b81e-48df37d1df5a", + "setDefinitionKey": "ChatMessageDemographics", + "setDefinitionName": { + "value": "Chat Message Demographics" + }, + "parentIdentifier": "c9e9847d-696d-eb11-b81e-48df37d1df5a" + }, + { + "baseType": "Text", + "dataSourceID": 3, + "dataSourceName": {}, + "dataType": "Text", + "description": "", + "localizedDescription": { + "value": "" + }, + "definitionID": "d2e9847d-696d-eb11-b81e-48df37d1df5a", + "definitionKey": "FirstName", + "definitionName": { + "value": "First Name" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 9, + "fullyQualifiedName": "Chat Message Demographics.First Name", + "isHidden": false, + "isIdentityValue": false, + "isNullable": true, + "isPrimaryKey": false, + "isReadOnly": false, + "isSystemDefined": false, + "isUpdateable": false, + "length": 100, + "obfuscationProperties": { + "maskType": "None", + "maskTypeID": 0, + "storageTypeID": 1, + "storageType": "Plain", + "valueDefinitionID": "d2e9847d-696d-eb11-b81e-48df37d1df5a" + }, + "ordinal": 9, + "parentDefinition": { + "definitionID": "c9e9847d-696d-eb11-b81e-48df37d1df5a", + "definitionKey": "ChatMessageDemographics", + "definitionName": { + "value": "Chat Message Demographics" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "_FirstName", + "storageFieldReferenceID": { + "type": "guid", + "value": "125f7c91-2f11-44bd-9687-f22cf2461496" + }, + "valueDefinitionID": "d2e9847d-696d-eb11-b81e-48df37d1df5a", + "valueDefinitionKey": "FirstName", + "name": "First Name", + "setDefinitionID": "c9e9847d-696d-eb11-b81e-48df37d1df5a", + "setDefinitionKey": "ChatMessageDemographics", + "setDefinitionName": { + "value": "Chat Message Demographics" + }, + "parentIdentifier": "c9e9847d-696d-eb11-b81e-48df37d1df5a" + }, + { + "baseType": "Boolean", + "dataSourceID": 3, + "dataSourceName": {}, + "dataType": "Boolean", + "defaultValue": "False", + "description": "", + "localizedDescription": { + "value": "" + }, + "definitionID": "d3e9847d-696d-eb11-b81e-48df37d1df5a", + "definitionKey": "IsHonorDST", + "definitionName": { + "value": "Is Honor DST" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 10, + "fullyQualifiedName": "Chat Message Demographics.Is Honor DST", + "isHidden": false, + "isIdentityValue": false, + "isNullable": true, + "isPrimaryKey": false, + "isReadOnly": false, + "isSystemDefined": true, + "isUpdateable": false, + "obfuscationProperties": { + "maskType": "None", + "maskTypeID": 0, + "storageTypeID": 1, + "storageType": "Plain", + "valueDefinitionID": "d3e9847d-696d-eb11-b81e-48df37d1df5a" + }, + "ordinal": 10, + "parentDefinition": { + "definitionID": "c9e9847d-696d-eb11-b81e-48df37d1df5a", + "definitionKey": "ChatMessageDemographics", + "definitionName": { + "value": "Chat Message Demographics" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "_IsHonorDST", + "storageFieldReferenceID": { + "type": "guid", + "value": "17abe00a-4306-43c5-b27f-a81f015d6dfb" + }, + "valueDefinitionID": "d3e9847d-696d-eb11-b81e-48df37d1df5a", + "valueDefinitionKey": "IsHonorDST", + "name": "Is Honor DST", + "setDefinitionID": "c9e9847d-696d-eb11-b81e-48df37d1df5a", + "setDefinitionKey": "ChatMessageDemographics", + "setDefinitionName": { + "value": "Chat Message Demographics" + }, + "parentIdentifier": "c9e9847d-696d-eb11-b81e-48df37d1df5a" + }, + { + "baseType": "Text", + "dataSourceID": 3, + "dataSourceName": {}, + "dataType": "Text", + "description": "", + "localizedDescription": { + "value": "" + }, + "definitionID": "d4e9847d-696d-eb11-b81e-48df37d1df5a", + "definitionKey": "LastName", + "definitionName": { + "value": "Last Name" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 11, + "fullyQualifiedName": "Chat Message Demographics.Last Name", + "isHidden": false, + "isIdentityValue": false, + "isNullable": true, + "isPrimaryKey": false, + "isReadOnly": false, + "isSystemDefined": false, + "isUpdateable": false, + "length": 100, + "obfuscationProperties": { + "maskType": "None", + "maskTypeID": 0, + "storageTypeID": 1, + "storageType": "Plain", + "valueDefinitionID": "d4e9847d-696d-eb11-b81e-48df37d1df5a" + }, + "ordinal": 11, + "parentDefinition": { + "definitionID": "c9e9847d-696d-eb11-b81e-48df37d1df5a", + "definitionKey": "ChatMessageDemographics", + "definitionName": { + "value": "Chat Message Demographics" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "_LastName", + "storageFieldReferenceID": { + "type": "guid", + "value": "e31f18f4-5422-410b-adcc-1b60f61cce5f" + }, + "valueDefinitionID": "d4e9847d-696d-eb11-b81e-48df37d1df5a", + "valueDefinitionKey": "LastName", + "name": "Last Name", + "setDefinitionID": "c9e9847d-696d-eb11-b81e-48df37d1df5a", + "setDefinitionKey": "ChatMessageDemographics", + "setDefinitionName": { + "value": "Chat Message Demographics" + }, + "parentIdentifier": "c9e9847d-696d-eb11-b81e-48df37d1df5a" + }, + { + "baseType": "Text", + "dataSourceID": 3, + "dataSourceName": {}, + "dataType": "Text", + "description": "", + "localizedDescription": { + "value": "" + }, + "definitionID": "cfe9847d-696d-eb11-b81e-48df37d1df5a", + "definitionKey": "CountryCode", + "definitionName": { + "value": "Locale" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 12, + "fullyQualifiedName": "Chat Message Demographics.Locale", + "isHidden": false, + "isIdentityValue": false, + "isNullable": false, + "isPrimaryKey": false, + "isReadOnly": false, + "isSystemDefined": true, + "isUpdateable": false, + "length": 2, + "obfuscationProperties": { + "maskType": "None", + "maskTypeID": 0, + "storageTypeID": 1, + "storageType": "Plain", + "valueDefinitionID": "cfe9847d-696d-eb11-b81e-48df37d1df5a" + }, + "ordinal": 12, + "parentDefinition": { + "definitionID": "c9e9847d-696d-eb11-b81e-48df37d1df5a", + "definitionKey": "ChatMessageDemographics", + "definitionName": { + "value": "Chat Message Demographics" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "_CountryCode", + "storageFieldReferenceID": { + "type": "guid", + "value": "4b5fda70-47cb-4f4b-8ba6-f5cac53ee344" + }, + "valueDefinitionID": "cfe9847d-696d-eb11-b81e-48df37d1df5a", + "valueDefinitionKey": "CountryCode", + "name": "Locale", + "setDefinitionID": "c9e9847d-696d-eb11-b81e-48df37d1df5a", + "setDefinitionKey": "ChatMessageDemographics", + "setDefinitionName": { + "value": "Chat Message Demographics" + }, + "parentIdentifier": "c9e9847d-696d-eb11-b81e-48df37d1df5a" + }, + { + "baseType": "Text", + "dataSourceID": 3, + "dataSourceName": {}, + "dataType": "Phone", + "description": "", + "localizedDescription": { + "value": "" + }, + "definitionID": "d5e9847d-696d-eb11-b81e-48df37d1df5a", + "definitionKey": "MobileNumber", + "definitionName": { + "value": "Mobile Number" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 14, + "fullyQualifiedName": "Chat Message Demographics.Mobile Number", + "isHidden": false, + "isIdentityValue": false, + "isNullable": false, + "isPrimaryKey": true, + "isReadOnly": false, + "isSystemDefined": true, + "isUpdateable": false, + "length": 15, + "obfuscationProperties": { + "maskType": "None", + "maskTypeID": 0, + "storageTypeID": 1, + "storageType": "Plain", + "valueDefinitionID": "d5e9847d-696d-eb11-b81e-48df37d1df5a" + }, + "ordinal": 14, + "parentDefinition": { + "definitionID": "c9e9847d-696d-eb11-b81e-48df37d1df5a", + "definitionKey": "ChatMessageDemographics", + "definitionName": { + "value": "Chat Message Demographics" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "_MobileNumber", + "storageFieldReferenceID": { + "type": "guid", + "value": "e31a7e3b-e943-440e-9be6-77224a4928fe" + }, + "valueDefinitionID": "d5e9847d-696d-eb11-b81e-48df37d1df5a", + "valueDefinitionKey": "MobileNumber", + "name": "Mobile Number", + "setDefinitionID": "c9e9847d-696d-eb11-b81e-48df37d1df5a", + "setDefinitionKey": "ChatMessageDemographics", + "setDefinitionName": { + "value": "Chat Message Demographics" + }, + "parentIdentifier": "c9e9847d-696d-eb11-b81e-48df37d1df5a" + }, + { + "baseType": "Numeric", + "dataSourceID": 3, + "dataSourceName": {}, + "dataType": "LongNumber", + "description": "", + "localizedDescription": { + "value": "" + }, + "definitionID": "d6e9847d-696d-eb11-b81e-48df37d1df5a", + "definitionKey": "ModifiedBy", + "definitionName": { + "value": "Modified By" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 15, + "fullyQualifiedName": "Chat Message Demographics.Modified By", + "isHidden": true, + "isIdentityValue": false, + "isNullable": true, + "isPrimaryKey": false, + "isReadOnly": true, + "isSystemDefined": true, + "isUpdateable": false, + "obfuscationProperties": { + "maskType": "None", + "maskTypeID": 0, + "storageTypeID": 1, + "storageType": "Plain", + "valueDefinitionID": "d6e9847d-696d-eb11-b81e-48df37d1df5a" + }, + "ordinal": 15, + "parentDefinition": { + "definitionID": "c9e9847d-696d-eb11-b81e-48df37d1df5a", + "definitionKey": "ChatMessageDemographics", + "definitionName": { + "value": "Chat Message Demographics" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "_ModifiedBy", + "storageFieldReferenceID": { + "type": "guid", + "value": "a9be58ef-884d-44f4-9926-d73ebe587847" + }, + "valueDefinitionID": "d6e9847d-696d-eb11-b81e-48df37d1df5a", + "valueDefinitionKey": "ModifiedBy", + "name": "Modified By", + "setDefinitionID": "c9e9847d-696d-eb11-b81e-48df37d1df5a", + "setDefinitionKey": "ChatMessageDemographics", + "setDefinitionName": { + "value": "Chat Message Demographics" + }, + "parentIdentifier": "c9e9847d-696d-eb11-b81e-48df37d1df5a" + }, + { + "baseType": "Date", + "dataSourceID": 3, + "dataSourceName": {}, + "dataType": "Date", + "defaultValue": "GETDATE()", + "description": "", + "localizedDescription": { + "value": "" + }, + "definitionID": "d7e9847d-696d-eb11-b81e-48df37d1df5a", + "definitionKey": "ModifiedDate", + "definitionName": { + "value": "Modified Date" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 16, + "fullyQualifiedName": "Chat Message Demographics.Modified Date", + "isHidden": false, + "isIdentityValue": false, + "isNullable": false, + "isPrimaryKey": false, + "isReadOnly": true, + "isSystemDefined": true, + "isUpdateable": false, + "obfuscationProperties": { + "maskType": "None", + "maskTypeID": 0, + "storageTypeID": 1, + "storageType": "Plain", + "valueDefinitionID": "d7e9847d-696d-eb11-b81e-48df37d1df5a" + }, + "ordinal": 16, + "parentDefinition": { + "definitionID": "c9e9847d-696d-eb11-b81e-48df37d1df5a", + "definitionKey": "ChatMessageDemographics", + "definitionName": { + "value": "Chat Message Demographics" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "_ModifiedDate", + "storageFieldReferenceID": { + "type": "guid", + "value": "216659c1-9512-47de-a9ee-822f48148514" + }, + "valueDefinitionID": "d7e9847d-696d-eb11-b81e-48df37d1df5a", + "valueDefinitionKey": "ModifiedDate", + "name": "Modified Date", + "setDefinitionID": "c9e9847d-696d-eb11-b81e-48df37d1df5a", + "setDefinitionKey": "ChatMessageDemographics", + "setDefinitionName": { + "value": "Chat Message Demographics" + }, + "parentIdentifier": "c9e9847d-696d-eb11-b81e-48df37d1df5a" + }, + { + "baseType": "Numeric", + "dataSourceID": 3, + "dataSourceName": {}, + "dataType": "Byte", + "description": "", + "localizedDescription": { + "value": "" + }, + "definitionID": "d8e9847d-696d-eb11-b81e-48df37d1df5a", + "definitionKey": "Priority", + "definitionName": { + "value": "Priority" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 17, + "fullyQualifiedName": "Chat Message Demographics.Priority", + "isHidden": false, + "isIdentityValue": false, + "isNullable": true, + "isPrimaryKey": false, + "isReadOnly": true, + "isSystemDefined": true, + "isUpdateable": false, + "obfuscationProperties": { + "maskType": "None", + "maskTypeID": 0, + "storageTypeID": 1, + "storageType": "Plain", + "valueDefinitionID": "d8e9847d-696d-eb11-b81e-48df37d1df5a" + }, + "ordinal": 17, + "parentDefinition": { + "definitionID": "c9e9847d-696d-eb11-b81e-48df37d1df5a", + "definitionKey": "ChatMessageDemographics", + "definitionName": { + "value": "Chat Message Demographics" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "_Priority", + "storageFieldReferenceID": { + "type": "guid", + "value": "71153ee5-a33f-4cf6-a963-0c3a893d9348" + }, + "valueDefinitionID": "d8e9847d-696d-eb11-b81e-48df37d1df5a", + "valueDefinitionKey": "Priority", + "name": "Priority", + "setDefinitionID": "c9e9847d-696d-eb11-b81e-48df37d1df5a", + "setDefinitionKey": "ChatMessageDemographics", + "setDefinitionName": { + "value": "Chat Message Demographics" + }, + "parentIdentifier": "c9e9847d-696d-eb11-b81e-48df37d1df5a" + }, + { + "baseType": "Numeric", + "dataSourceID": 3, + "dataSourceName": {}, + "dataType": "Byte", + "description": "", + "localizedDescription": { + "value": "" + }, + "definitionID": "d9e9847d-696d-eb11-b81e-48df37d1df5a", + "definitionKey": "Source", + "definitionName": { + "value": "Source" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 18, + "fullyQualifiedName": "Chat Message Demographics.Source", + "isHidden": false, + "isIdentityValue": false, + "isNullable": true, + "isPrimaryKey": false, + "isReadOnly": true, + "isSystemDefined": true, + "isUpdateable": false, + "obfuscationProperties": { + "maskType": "None", + "maskTypeID": 0, + "storageTypeID": 1, + "storageType": "Plain", + "valueDefinitionID": "d9e9847d-696d-eb11-b81e-48df37d1df5a" + }, + "ordinal": 18, + "parentDefinition": { + "definitionID": "c9e9847d-696d-eb11-b81e-48df37d1df5a", + "definitionKey": "ChatMessageDemographics", + "definitionName": { + "value": "Chat Message Demographics" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "restrictionLookupListID": 5, + "storageName": "_Source", + "storageFieldReferenceID": { + "type": "guid", + "value": "f6bafdfb-86bf-45e8-9b76-b878c904d6c5" + }, + "valueDefinitionID": "d9e9847d-696d-eb11-b81e-48df37d1df5a", + "valueDefinitionKey": "Source", + "name": "Source", + "setDefinitionID": "c9e9847d-696d-eb11-b81e-48df37d1df5a", + "setDefinitionKey": "ChatMessageDemographics", + "setDefinitionName": { + "value": "Chat Message Demographics" + }, + "parentIdentifier": "c9e9847d-696d-eb11-b81e-48df37d1df5a" + }, + { + "baseType": "Text", + "dataSourceID": 3, + "dataSourceName": {}, + "dataType": "Text", + "description": "", + "localizedDescription": { + "value": "" + }, + "definitionID": "dae9847d-696d-eb11-b81e-48df37d1df5a", + "definitionKey": "SourceObjectID", + "definitionName": { + "value": "Source Object ID" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 19, + "fullyQualifiedName": "Chat Message Demographics.Source Object ID", + "isHidden": false, + "isIdentityValue": false, + "isNullable": true, + "isPrimaryKey": false, + "isReadOnly": true, + "isSystemDefined": true, + "isUpdateable": false, + "length": 200, + "obfuscationProperties": { + "maskType": "None", + "maskTypeID": 0, + "storageTypeID": 1, + "storageType": "Plain", + "valueDefinitionID": "dae9847d-696d-eb11-b81e-48df37d1df5a" + }, + "ordinal": 19, + "parentDefinition": { + "definitionID": "c9e9847d-696d-eb11-b81e-48df37d1df5a", + "definitionKey": "ChatMessageDemographics", + "definitionName": { + "value": "Chat Message Demographics" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "_SourceObjectId", + "storageFieldReferenceID": { + "type": "guid", + "value": "c67a7922-44e5-4c4b-a4c8-2ac3550a5f07" + }, + "valueDefinitionID": "dae9847d-696d-eb11-b81e-48df37d1df5a", + "valueDefinitionKey": "SourceObjectID", + "name": "Source Object ID", + "setDefinitionID": "c9e9847d-696d-eb11-b81e-48df37d1df5a", + "setDefinitionKey": "ChatMessageDemographics", + "setDefinitionName": { + "value": "Chat Message Demographics" + }, + "parentIdentifier": "c9e9847d-696d-eb11-b81e-48df37d1df5a" + }, + { + "baseType": "Text", + "dataSourceID": 4, + "dataSourceName": {}, + "dataType": "Text", + "description": "", + "localizedDescription": { + "value": "" + }, + "definitionID": "dfe9847d-696d-eb11-b81e-48df37d1df5a", + "definitionKey": "SFContactID", + "definitionName": { + "value": "SFContactID" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 19, + "fullyQualifiedName": "Chat Message Demographics.SFContactID", + "isHidden": false, + "isIdentityValue": false, + "isNullable": true, + "isPrimaryKey": false, + "isReadOnly": false, + "isSystemDefined": false, + "isUpdateable": true, + "length": 50, + "obfuscationProperties": { + "maskType": "None", + "maskTypeID": 0, + "storageTypeID": 1, + "storageType": "Plain", + "valueDefinitionID": "dfe9847d-696d-eb11-b81e-48df37d1df5a" + }, + "ordinal": 19, + "parentDefinition": { + "definitionID": "c9e9847d-696d-eb11-b81e-48df37d1df5a", + "definitionKey": "ChatMessageDemographics", + "definitionName": { + "value": "Chat Message Demographics" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "SFContactID", + "storageFieldReferenceID": { + "type": "guid", + "value": "ce5a90ea-88eb-4683-9a1a-5c776b5763ce" + }, + "valueDefinitionID": "dfe9847d-696d-eb11-b81e-48df37d1df5a", + "valueDefinitionKey": "SFContactID", + "name": "SFContactID", + "setDefinitionID": "c9e9847d-696d-eb11-b81e-48df37d1df5a", + "setDefinitionKey": "ChatMessageDemographics", + "setDefinitionName": { + "value": "Chat Message Demographics" + }, + "parentIdentifier": "c9e9847d-696d-eb11-b81e-48df37d1df5a" + }, + { + "baseType": "Text", + "dataSourceID": 3, + "dataSourceName": {}, + "dataType": "Text", + "description": "", + "localizedDescription": { + "value": "" + }, + "definitionID": "dbe9847d-696d-eb11-b81e-48df37d1df5a", + "definitionKey": "State", + "definitionName": { + "value": "State" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 20, + "fullyQualifiedName": "Chat Message Demographics.State", + "isHidden": false, + "isIdentityValue": false, + "isNullable": true, + "isPrimaryKey": false, + "isReadOnly": false, + "isSystemDefined": false, + "isUpdateable": false, + "length": 200, + "obfuscationProperties": { + "maskType": "None", + "maskTypeID": 0, + "storageTypeID": 1, + "storageType": "Plain", + "valueDefinitionID": "dbe9847d-696d-eb11-b81e-48df37d1df5a" + }, + "ordinal": 20, + "parentDefinition": { + "definitionID": "c9e9847d-696d-eb11-b81e-48df37d1df5a", + "definitionKey": "ChatMessageDemographics", + "definitionName": { + "value": "Chat Message Demographics" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "_State", + "storageFieldReferenceID": { + "type": "guid", + "value": "c0ea1fac-d939-4dde-b45a-16586f661924" + }, + "valueDefinitionID": "dbe9847d-696d-eb11-b81e-48df37d1df5a", + "valueDefinitionKey": "State", + "name": "State", + "setDefinitionID": "c9e9847d-696d-eb11-b81e-48df37d1df5a", + "setDefinitionKey": "ChatMessageDemographics", + "setDefinitionName": { + "value": "Chat Message Demographics" + }, + "parentIdentifier": "c9e9847d-696d-eb11-b81e-48df37d1df5a" + }, + { + "baseType": "Numeric", + "dataSourceID": 3, + "dataSourceName": {}, + "dataType": "Byte", + "description": "", + "localizedDescription": { + "value": "" + }, + "definitionID": "dce9847d-696d-eb11-b81e-48df37d1df5a", + "definitionKey": "Status", + "definitionName": { + "value": "Status" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 21, + "fullyQualifiedName": "Chat Message Demographics.Status", + "isHidden": false, + "isIdentityValue": false, + "isNullable": true, + "isPrimaryKey": false, + "isReadOnly": false, + "isSystemDefined": true, + "isUpdateable": false, + "obfuscationProperties": { + "maskType": "None", + "maskTypeID": 0, + "storageTypeID": 1, + "storageType": "Plain", + "valueDefinitionID": "dce9847d-696d-eb11-b81e-48df37d1df5a" + }, + "ordinal": 21, + "parentDefinition": { + "definitionID": "c9e9847d-696d-eb11-b81e-48df37d1df5a", + "definitionKey": "ChatMessageDemographics", + "definitionName": { + "value": "Chat Message Demographics" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "restrictionLookupListID": 6, + "storageName": "_Status", + "storageFieldReferenceID": { + "type": "guid", + "value": "fafff407-c055-411c-81ec-78907f5dbd58" + }, + "valueDefinitionID": "dce9847d-696d-eb11-b81e-48df37d1df5a", + "valueDefinitionKey": "Status", + "name": "Status", + "setDefinitionID": "c9e9847d-696d-eb11-b81e-48df37d1df5a", + "setDefinitionKey": "ChatMessageDemographics", + "setDefinitionName": { + "value": "Chat Message Demographics" + }, + "parentIdentifier": "c9e9847d-696d-eb11-b81e-48df37d1df5a" + }, + { + "baseType": "Numeric", + "dataSourceID": 3, + "dataSourceName": {}, + "dataType": "Decimal", + "description": "", + "localizedDescription": { + "value": "" + }, + "definitionID": "dde9847d-696d-eb11-b81e-48df37d1df5a", + "definitionKey": "UTCOffset", + "definitionName": { + "value": "UTC Offset" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 22, + "fullyQualifiedName": "Chat Message Demographics.UTC Offset", + "isHidden": false, + "isIdentityValue": false, + "isNullable": true, + "isPrimaryKey": false, + "isReadOnly": false, + "isSystemDefined": true, + "isUpdateable": false, + "length": 4, + "obfuscationProperties": { + "maskType": "None", + "maskTypeID": 0, + "storageTypeID": 1, + "storageType": "Plain", + "valueDefinitionID": "dde9847d-696d-eb11-b81e-48df37d1df5a" + }, + "ordinal": 22, + "parentDefinition": { + "definitionID": "c9e9847d-696d-eb11-b81e-48df37d1df5a", + "definitionKey": "ChatMessageDemographics", + "definitionName": { + "value": "Chat Message Demographics" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "scale": 2, + "storageName": "_UTCOffset", + "storageFieldReferenceID": { + "type": "guid", + "value": "84d29656-a348-43c2-ac2f-8c7ec5b18a3e" + }, + "valueDefinitionID": "dde9847d-696d-eb11-b81e-48df37d1df5a", + "valueDefinitionKey": "UTCOffset", + "name": "UTC Offset", + "setDefinitionID": "c9e9847d-696d-eb11-b81e-48df37d1df5a", + "setDefinitionKey": "ChatMessageDemographics", + "setDefinitionName": { + "value": "Chat Message Demographics" + }, + "parentIdentifier": "c9e9847d-696d-eb11-b81e-48df37d1df5a" + }, + { + "baseType": "Text", + "dataSourceID": 3, + "dataSourceName": {}, + "dataType": "Text", + "description": "", + "localizedDescription": { + "value": "" + }, + "definitionID": "e0e9847d-696d-eb11-b81e-48df37d1df5a", + "definitionKey": "ZipCode", + "definitionName": { + "value": "Zip Code" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 23, + "fullyQualifiedName": "Chat Message Demographics.Zip Code", + "isHidden": false, + "isIdentityValue": false, + "isNullable": true, + "isPrimaryKey": false, + "isReadOnly": false, + "isSystemDefined": false, + "isUpdateable": false, + "length": 20, + "obfuscationProperties": { + "maskType": "None", + "maskTypeID": 0, + "storageTypeID": 1, + "storageType": "Plain", + "valueDefinitionID": "e0e9847d-696d-eb11-b81e-48df37d1df5a" + }, + "ordinal": 23, + "parentDefinition": { + "definitionID": "c9e9847d-696d-eb11-b81e-48df37d1df5a", + "definitionKey": "ChatMessageDemographics", + "definitionName": { + "value": "Chat Message Demographics" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "_ZipCode", + "storageFieldReferenceID": { + "type": "guid", + "value": "11ce9d05-a1e3-47ba-9077-11097e0b4c8d" + }, + "valueDefinitionID": "e0e9847d-696d-eb11-b81e-48df37d1df5a", + "valueDefinitionKey": "ZipCode", + "name": "Zip Code", + "setDefinitionID": "c9e9847d-696d-eb11-b81e-48df37d1df5a", + "setDefinitionKey": "ChatMessageDemographics", + "setDefinitionName": { + "value": "Chat Message Demographics" + }, + "parentIdentifier": "c9e9847d-696d-eb11-b81e-48df37d1df5a" + } + ], + "applicationID": "e25893f9-08f3-480f-8def-7f8ab0583611", + "applicationKey": "com.exacttarget.mobileconnect", + "attributeCount": 0, + "canAddValues": true, + "canChangeValues": true, + "canModify": false, + "canRemove": false, + "categoryID": 2, + "createDate": "2021-02-12T13:36:00", + "customObjectOwnerMID": 1111111, + "dataRetentionProperties": { + "isRowBasedRetention": false, + "isResetRetentionPeriodOnImport": false, + "isDeleteAtEndOfRetentionPeriod": false, + "setDefinitionID": "c9e9847d-696d-eb11-b81e-48df37d1df5a" + }, + "localizedDescription": {}, + "fullyQualifiedName": "Chat Message Demographics", + "isCustomObjectBacked": true, + "isEvent": false, + "isHidden": false, + "isReadOnly": false, + "isRoot": false, + "isSendable": true, + "isShared": false, + "isSystemDefined": true, + "isTestaable": false, + "parentID": "00000000-0000-0000-0000-000000000000", + "relationshipCount": 2, + "sendAttributeStorageName": "_ContactID", + "sendContactKeyStorageName": "_SubscriberID", + "storageLogicalType": "MobileAttributes", + "storageName": "_MobileAddress", + "storageObjectIDs": ["1651de3f-31e2-e611-80cc-1402ec7222b4"], + "storageReferenceID": { + "type": "guid", + "value": "7693dc39-31e2-e611-80cc-1402ec7222b4" + }, + "setDefinitionID": "c9e9847d-696d-eb11-b81e-48df37d1df5a", + "setDefinitionKey": "ChatMessageDemographics", + "name": "Chat Message Demographics" + }, + { + "definitionID": "d685d645-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "PredictiveIntelProductAttribs", + "definitionName": { + "value": "Predictive Intelligence Product Attributes" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "valueDefinitions": [ + { + "baseType": "Numeric", + "dataSourceID": 1, + "dataSourceName": {}, + "dataType": "LongNumber", + "description": "", + "localizedDescription": { + "value": "" + }, + "definitionID": "dc85d645-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "CustomObjectKey", + "definitionName": { + "value": "Custom Object Key" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 1, + "fullyQualifiedName": "Predictive Intelligence Product Attributes.Custom Object Key", + "isHidden": true, + "isIdentityValue": true, + "isNullable": false, + "isPrimaryKey": false, + "isReadOnly": true, + "isSystemDefined": true, + "isUpdateable": false, + "ordinal": 1, + "parentDefinition": { + "definitionID": "d685d645-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "PredictiveIntelProductAttribs", + "definitionName": { + "value": "Predictive Intelligence Product Attributes" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "_CustomObjectKey", + "valueDefinitionID": "dc85d645-31e2-e611-80cc-1402ec7222b4", + "valueDefinitionKey": "CustomObjectKey", + "name": "Custom Object Key", + "setDefinitionID": "d685d645-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "PredictiveIntelProductAttribs", + "setDefinitionName": { + "value": "Predictive Intelligence Product Attributes" + }, + "parentIdentifier": "d685d645-31e2-e611-80cc-1402ec7222b4" + }, + { + "baseType": "Text", + "dataSourceID": 5, + "dataSourceName": {}, + "dataType": "Text", + "description": "attribName", + "localizedDescription": { + "value": "attribName" + }, + "definitionID": "d785d645-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "Attribute_Name", + "definitionName": { + "value": "Attribute Name" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 2, + "fullyQualifiedName": "Predictive Intelligence Product Attributes.Attribute Name", + "isHidden": false, + "isIdentityValue": false, + "isNullable": false, + "isPrimaryKey": true, + "isReadOnly": true, + "isSystemDefined": true, + "isUpdateable": false, + "length": 1000, + "obfuscationProperties": { + "maskType": "None", + "maskTypeID": 0, + "storageTypeID": 1, + "storageType": "Plain", + "valueDefinitionID": "d785d645-31e2-e611-80cc-1402ec7222b4" + }, + "ordinal": 2, + "parentDefinition": { + "definitionID": "d685d645-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "PredictiveIntelProductAttribs", + "definitionName": { + "value": "Predictive Intelligence Product Attributes" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "attribName", + "storageFieldReferenceID": { + "type": "guid", + "value": "a29facf4-9173-43b7-98d5-57bef44c832f" + }, + "valueDefinitionID": "d785d645-31e2-e611-80cc-1402ec7222b4", + "valueDefinitionKey": "Attribute_Name", + "name": "Attribute Name", + "setDefinitionID": "d685d645-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "PredictiveIntelProductAttribs", + "setDefinitionName": { + "value": "Predictive Intelligence Product Attributes" + }, + "parentIdentifier": "d685d645-31e2-e611-80cc-1402ec7222b4" + }, + { + "baseType": "Text", + "dataSourceID": 5, + "dataSourceName": {}, + "dataType": "Text", + "description": "attribValue", + "localizedDescription": { + "value": "attribValue" + }, + "definitionID": "d985d645-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "Attribute_Value", + "definitionName": { + "value": "Attribute Value" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 3, + "fullyQualifiedName": "Predictive Intelligence Product Attributes.Attribute Value", + "isHidden": false, + "isIdentityValue": false, + "isNullable": false, + "isPrimaryKey": false, + "isReadOnly": true, + "isSystemDefined": true, + "isUpdateable": false, + "length": 1000, + "obfuscationProperties": { + "maskType": "None", + "maskTypeID": 0, + "storageTypeID": 1, + "storageType": "Plain", + "valueDefinitionID": "d985d645-31e2-e611-80cc-1402ec7222b4" + }, + "ordinal": 3, + "parentDefinition": { + "definitionID": "d685d645-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "PredictiveIntelProductAttribs", + "definitionName": { + "value": "Predictive Intelligence Product Attributes" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "attribValue", + "storageFieldReferenceID": { + "type": "guid", + "value": "b023eb98-10c7-481d-a809-38af6af65b17" + }, + "valueDefinitionID": "d985d645-31e2-e611-80cc-1402ec7222b4", + "valueDefinitionKey": "Attribute_Value", + "name": "Attribute Value", + "setDefinitionID": "d685d645-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "PredictiveIntelProductAttribs", + "setDefinitionName": { + "value": "Predictive Intelligence Product Attributes" + }, + "parentIdentifier": "d685d645-31e2-e611-80cc-1402ec7222b4" + }, + { + "baseType": "Text", + "dataSourceID": 5, + "dataSourceName": {}, + "dataType": "Text", + "description": "sku", + "localizedDescription": { + "value": "sku" + }, + "definitionID": "da85d645-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "SKU", + "definitionName": { + "value": "SKU" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 4, + "fullyQualifiedName": "Predictive Intelligence Product Attributes.SKU", + "isHidden": false, + "isIdentityValue": false, + "isNullable": false, + "isPrimaryKey": true, + "isReadOnly": true, + "isSystemDefined": true, + "isUpdateable": false, + "length": 256, + "obfuscationProperties": { + "maskType": "None", + "maskTypeID": 0, + "storageTypeID": 1, + "storageType": "Plain", + "valueDefinitionID": "da85d645-31e2-e611-80cc-1402ec7222b4" + }, + "ordinal": 4, + "parentDefinition": { + "definitionID": "d685d645-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "PredictiveIntelProductAttribs", + "definitionName": { + "value": "Predictive Intelligence Product Attributes" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "sku", + "storageFieldReferenceID": { + "type": "guid", + "value": "35919388-7813-48d0-a45f-2c0cf64d6e1e" + }, + "valueDefinitionID": "da85d645-31e2-e611-80cc-1402ec7222b4", + "valueDefinitionKey": "SKU", + "name": "SKU", + "setDefinitionID": "d685d645-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "PredictiveIntelProductAttribs", + "setDefinitionName": { + "value": "Predictive Intelligence Product Attributes" + }, + "parentIdentifier": "d685d645-31e2-e611-80cc-1402ec7222b4" + }, + { + "baseType": "Date", + "dataSourceID": 5, + "dataSourceName": {}, + "dataType": "Date", + "description": "updated_at", + "localizedDescription": { + "value": "updated_at" + }, + "definitionID": "db85d645-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "Updated_At", + "definitionName": { + "value": "Updated At" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 5, + "fullyQualifiedName": "Predictive Intelligence Product Attributes.Updated At", + "isHidden": false, + "isIdentityValue": false, + "isNullable": false, + "isPrimaryKey": false, + "isReadOnly": true, + "isSystemDefined": true, + "isUpdateable": false, + "obfuscationProperties": { + "maskType": "None", + "maskTypeID": 0, + "storageTypeID": 1, + "storageType": "Plain", + "valueDefinitionID": "db85d645-31e2-e611-80cc-1402ec7222b4" + }, + "ordinal": 5, + "parentDefinition": { + "definitionID": "d685d645-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "PredictiveIntelProductAttribs", + "definitionName": { + "value": "Predictive Intelligence Product Attributes" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "updated_at", + "storageFieldReferenceID": { + "type": "guid", + "value": "a8a96a08-576c-4b45-842c-fe6c36da6f41" + }, + "valueDefinitionID": "db85d645-31e2-e611-80cc-1402ec7222b4", + "valueDefinitionKey": "Updated_At", + "name": "Updated At", + "setDefinitionID": "d685d645-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "PredictiveIntelProductAttribs", + "setDefinitionName": { + "value": "Predictive Intelligence Product Attributes" + }, + "parentIdentifier": "d685d645-31e2-e611-80cc-1402ec7222b4" + }, + { + "baseType": "Numeric", + "dataSourceID": 5, + "dataSourceName": {}, + "dataType": "Number", + "description": "attributeValueIndex", + "localizedDescription": { + "value": "attributeValueIndex" + }, + "definitionID": "d885d645-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "Attribute_Value_Index", + "definitionName": { + "value": "Attribute Value Index" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 6, + "fullyQualifiedName": "Predictive Intelligence Product Attributes.Attribute Value Index", + "isHidden": false, + "isIdentityValue": false, + "isNullable": false, + "isPrimaryKey": true, + "isReadOnly": true, + "isSystemDefined": true, + "isUpdateable": false, + "obfuscationProperties": { + "maskType": "None", + "maskTypeID": 0, + "storageTypeID": 1, + "storageType": "Plain", + "valueDefinitionID": "d885d645-31e2-e611-80cc-1402ec7222b4" + }, + "ordinal": 6, + "parentDefinition": { + "definitionID": "d685d645-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "PredictiveIntelProductAttribs", + "definitionName": { + "value": "Predictive Intelligence Product Attributes" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "attributeValueIndex", + "storageFieldReferenceID": { + "type": "guid", + "value": "619fe747-d142-4522-91dd-4228546d282d" + }, + "valueDefinitionID": "d885d645-31e2-e611-80cc-1402ec7222b4", + "valueDefinitionKey": "Attribute_Value_Index", + "name": "Attribute Value Index", + "setDefinitionID": "d685d645-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "PredictiveIntelProductAttribs", + "setDefinitionName": { + "value": "Predictive Intelligence Product Attributes" + }, + "parentIdentifier": "d685d645-31e2-e611-80cc-1402ec7222b4" + } + ], + "applicationID": "f4981f88-a13e-4abf-b331-47f41c73258d", + "applicationKey": "com.exacttarget.Predictive Web", + "attributeCount": 0, + "canAddValues": false, + "canChangeValues": false, + "canModify": false, + "canRemove": false, + "categoryID": 386, + "createdBy": -1000, + "createDate": "2017-01-24T06:33:00", + "customObjectOwnerMID": 1111111, + "dataRetentionProperties": { + "isRowBasedRetention": false, + "isResetRetentionPeriodOnImport": false, + "isDeleteAtEndOfRetentionPeriod": false, + "periodUnitOfMeasure": 4, + "setDefinitionID": "d685d645-31e2-e611-80cc-1402ec7222b4" + }, + "localizedDescription": {}, + "fullyQualifiedName": "Predictive Intelligence Product Attributes", + "isCustomObjectBacked": true, + "isEvent": false, + "isHidden": false, + "isReadOnly": true, + "isRoot": false, + "isSendable": false, + "isShared": false, + "isSystemDefined": true, + "isTestaable": false, + "parentID": "00000000-0000-0000-0000-000000000000", + "relationshipCount": 0, + "storageLogicalType": "DataExtension", + "storageName": "IGO_PRODUCTATTRIBS", + "storageObjectIDs": ["cf85d645-31e2-e611-80cc-1402ec7222b4"], + "storageReferenceID": { + "type": "guid", + "value": "d952de3f-31e2-e611-80cc-1402ec7222b4" + }, + "setDefinitionID": "d685d645-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "PredictiveIntelProductAttribs", + "name": "Predictive Intelligence Product Attributes" + }, + { + "definitionID": "e551de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "GroupConnectLineSubscriptions", + "definitionName": { + "value": "GroupConnect LINE Subscriptions" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "valueDefinitions": [ + { + "baseType": "Text", + "dataSourceID": 3, + "dataSourceName": {}, + "dataType": "Text", + "description": "", + "localizedDescription": { + "value": "" + }, + "definitionID": "e651de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "AddressID", + "definitionName": { + "value": "Address ID" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 1, + "fullyQualifiedName": "GroupConnect LINE Subscriptions.Address ID", + "isHidden": false, + "isIdentityValue": false, + "isNullable": false, + "isPrimaryKey": true, + "isReadOnly": false, + "isSystemDefined": true, + "isUpdateable": false, + "length": -1, + "ordinal": 1, + "parentDefinition": { + "definitionID": "e551de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "GroupConnectLineSubscriptions", + "definitionName": { + "value": "GroupConnect LINE Subscriptions" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "AddressId", + "valueDefinitionID": "e651de3f-31e2-e611-80cc-1402ec7222b4", + "valueDefinitionKey": "AddressID", + "name": "Address ID", + "setDefinitionID": "e551de3f-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "GroupConnectLineSubscriptions", + "setDefinitionName": { + "value": "GroupConnect LINE Subscriptions" + }, + "parentIdentifier": "e551de3f-31e2-e611-80cc-1402ec7222b4" + }, + { + "baseType": "Text", + "dataSourceID": 3, + "dataSourceName": {}, + "dataType": "Text", + "description": "", + "localizedDescription": { + "value": "" + }, + "definitionID": "e751de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "ChannelID", + "definitionName": { + "value": "Channel ID" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 2, + "fullyQualifiedName": "GroupConnect LINE Subscriptions.Channel ID", + "isHidden": false, + "isIdentityValue": false, + "isNullable": false, + "isPrimaryKey": true, + "isReadOnly": true, + "isSystemDefined": true, + "isUpdateable": false, + "length": -1, + "ordinal": 2, + "parentDefinition": { + "definitionID": "e551de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "GroupConnectLineSubscriptions", + "definitionName": { + "value": "GroupConnect LINE Subscriptions" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "ChannelId", + "valueDefinitionID": "e751de3f-31e2-e611-80cc-1402ec7222b4", + "valueDefinitionKey": "ChannelID", + "name": "Channel ID", + "setDefinitionID": "e551de3f-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "GroupConnectLineSubscriptions", + "setDefinitionName": { + "value": "GroupConnect LINE Subscriptions" + }, + "parentIdentifier": "e551de3f-31e2-e611-80cc-1402ec7222b4" + }, + { + "baseType": "Boolean", + "dataSourceID": 3, + "dataSourceName": {}, + "dataType": "Boolean", + "defaultValue": "False", + "description": "", + "localizedDescription": { + "value": "" + }, + "definitionID": "e851de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "IsSubscribed", + "definitionName": { + "value": "Is Subscribed" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 3, + "fullyQualifiedName": "GroupConnect LINE Subscriptions.Is Subscribed", + "isHidden": false, + "isIdentityValue": false, + "isNullable": false, + "isPrimaryKey": false, + "isReadOnly": true, + "isSystemDefined": true, + "isUpdateable": false, + "ordinal": 3, + "parentDefinition": { + "definitionID": "e551de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "GroupConnectLineSubscriptions", + "definitionName": { + "value": "GroupConnect LINE Subscriptions" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "IsSubscribed", + "valueDefinitionID": "e851de3f-31e2-e611-80cc-1402ec7222b4", + "valueDefinitionKey": "IsSubscribed", + "name": "Is Subscribed", + "setDefinitionID": "e551de3f-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "GroupConnectLineSubscriptions", + "setDefinitionName": { + "value": "GroupConnect LINE Subscriptions" + }, + "parentIdentifier": "e551de3f-31e2-e611-80cc-1402ec7222b4" + }, + { + "baseType": "Date", + "dataSourceID": 3, + "dataSourceName": {}, + "dataType": "Date", + "defaultValue": "GETDATE()", + "description": "", + "localizedDescription": { + "value": "" + }, + "definitionID": "e951de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "CreatedDate", + "definitionName": { + "value": "Created Date" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 4, + "fullyQualifiedName": "GroupConnect LINE Subscriptions.Created Date", + "isHidden": false, + "isIdentityValue": false, + "isNullable": false, + "isPrimaryKey": false, + "isReadOnly": true, + "isSystemDefined": true, + "isUpdateable": false, + "ordinal": 4, + "parentDefinition": { + "definitionID": "e551de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "GroupConnectLineSubscriptions", + "definitionName": { + "value": "GroupConnect LINE Subscriptions" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "CreatedDate", + "valueDefinitionID": "e951de3f-31e2-e611-80cc-1402ec7222b4", + "valueDefinitionKey": "CreatedDate", + "name": "Created Date", + "setDefinitionID": "e551de3f-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "GroupConnectLineSubscriptions", + "setDefinitionName": { + "value": "GroupConnect LINE Subscriptions" + }, + "parentIdentifier": "e551de3f-31e2-e611-80cc-1402ec7222b4" + }, + { + "baseType": "Numeric", + "dataSourceID": 3, + "dataSourceName": {}, + "dataType": "LongNumber", + "description": "", + "localizedDescription": { + "value": "" + }, + "definitionID": "ea51de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "CreatedBy", + "definitionName": { + "value": "Created By" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 5, + "fullyQualifiedName": "GroupConnect LINE Subscriptions.Created By", + "isHidden": false, + "isIdentityValue": false, + "isNullable": false, + "isPrimaryKey": false, + "isReadOnly": true, + "isSystemDefined": true, + "isUpdateable": false, + "ordinal": 5, + "parentDefinition": { + "definitionID": "e551de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "GroupConnectLineSubscriptions", + "definitionName": { + "value": "GroupConnect LINE Subscriptions" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "CreatedBy", + "valueDefinitionID": "ea51de3f-31e2-e611-80cc-1402ec7222b4", + "valueDefinitionKey": "CreatedBy", + "name": "Created By", + "setDefinitionID": "e551de3f-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "GroupConnectLineSubscriptions", + "setDefinitionName": { + "value": "GroupConnect LINE Subscriptions" + }, + "parentIdentifier": "e551de3f-31e2-e611-80cc-1402ec7222b4" + }, + { + "baseType": "Date", + "dataSourceID": 3, + "dataSourceName": {}, + "dataType": "Date", + "defaultValue": "GETDATE()", + "description": "", + "localizedDescription": { + "value": "" + }, + "definitionID": "eb51de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "ModifiedDate", + "definitionName": { + "value": "Modified Date" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 6, + "fullyQualifiedName": "GroupConnect LINE Subscriptions.Modified Date", + "isHidden": false, + "isIdentityValue": false, + "isNullable": true, + "isPrimaryKey": false, + "isReadOnly": true, + "isSystemDefined": true, + "isUpdateable": false, + "ordinal": 6, + "parentDefinition": { + "definitionID": "e551de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "GroupConnectLineSubscriptions", + "definitionName": { + "value": "GroupConnect LINE Subscriptions" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "ModifiedDate", + "valueDefinitionID": "eb51de3f-31e2-e611-80cc-1402ec7222b4", + "valueDefinitionKey": "ModifiedDate", + "name": "Modified Date", + "setDefinitionID": "e551de3f-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "GroupConnectLineSubscriptions", + "setDefinitionName": { + "value": "GroupConnect LINE Subscriptions" + }, + "parentIdentifier": "e551de3f-31e2-e611-80cc-1402ec7222b4" + }, + { + "baseType": "Numeric", + "dataSourceID": 3, + "dataSourceName": {}, + "dataType": "LongNumber", + "description": "", + "localizedDescription": { + "value": "" + }, + "definitionID": "ec51de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "ModifiedBy", + "definitionName": { + "value": "Modified By" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 7, + "fullyQualifiedName": "GroupConnect LINE Subscriptions.Modified By", + "isHidden": false, + "isIdentityValue": false, + "isNullable": true, + "isPrimaryKey": false, + "isReadOnly": true, + "isSystemDefined": true, + "isUpdateable": false, + "ordinal": 7, + "parentDefinition": { + "definitionID": "e551de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "GroupConnectLineSubscriptions", + "definitionName": { + "value": "GroupConnect LINE Subscriptions" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "ModifiedBy", + "valueDefinitionID": "ec51de3f-31e2-e611-80cc-1402ec7222b4", + "valueDefinitionKey": "ModifiedBy", + "name": "Modified By", + "setDefinitionID": "e551de3f-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "GroupConnectLineSubscriptions", + "setDefinitionName": { + "value": "GroupConnect LINE Subscriptions" + }, + "parentIdentifier": "e551de3f-31e2-e611-80cc-1402ec7222b4" + } + ], + "applicationID": "4e9519db-ad21-483a-a3fc-8ab4557eded1", + "applicationKey": "com.exacttarget.GroupConnect", + "attributeCount": 0, + "canAddValues": false, + "canChangeValues": false, + "canModify": false, + "canRemove": false, + "createdBy": -1000, + "createDate": "2017-01-24T06:33:00", + "localizedDescription": {}, + "fullyQualifiedName": "GroupConnect LINE Subscriptions", + "isCustomObjectBacked": false, + "isEvent": false, + "isHidden": false, + "isReadOnly": false, + "isRoot": false, + "isSendable": false, + "isSystemDefined": true, + "parentID": "00000000-0000-0000-0000-000000000000", + "relationshipCount": 0, + "storageObjectIDs": ["dd51de3f-31e2-e611-80cc-1402ec7222b4"], + "setDefinitionID": "e551de3f-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "GroupConnectLineSubscriptions", + "name": "GroupConnect LINE Subscriptions" + }, + { + "definitionID": "ee85d645-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "PredictiveIntelProductPurchases", + "definitionName": { + "value": "Predictive Intelligence Product Purchases" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "relationships": [ + { + "canModify": false, + "canRemove": false, + "isHidden": false, + "isSystemDefined": false, + "isGroupToSetRelationship": false, + "leftItem": { + "cardinality": "Many", + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "identifier": "ee85d645-31e2-e611-80cc-1402ec7222b4", + "relationshipType": "AttributeSet" + }, + "relationshipAttributes": [ + { + "leftAttributeID": "f785d645-31e2-e611-80cc-1402ec7222b4", + "leftConnectingID": { + "identifierType": "FullyQualifiedName" + }, + "rightAttributeID": "c885d645-31e2-e611-80cc-1402ec7222b4", + "rightConnectingID": { + "identifierType": "FullyQualifiedName" + } + } + ], + "relationshipID": "0086d645-31e2-e611-80cc-1402ec7222b4", + "rightItem": { + "cardinality": "One", + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "identifier": "c485d645-31e2-e611-80cc-1402ec7222b4", + "relationshipType": "AttributeSet" + } + }, + { + "canModify": false, + "canRemove": false, + "isHidden": false, + "isSystemDefined": false, + "isGroupToSetRelationship": false, + "leftItem": { + "cardinality": "One", + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "identifier": "ee85d645-31e2-e611-80cc-1402ec7222b4", + "relationshipType": "AttributeSet" + }, + "relationshipAttributes": [ + { + "leftAttributeID": "fa85d645-31e2-e611-80cc-1402ec7222b4", + "leftConnectingID": { + "identifierType": "FullyQualifiedName" + }, + "rightAttributeID": "1286d645-31e2-e611-80cc-1402ec7222b4", + "rightConnectingID": { + "identifierType": "FullyQualifiedName" + } + } + ], + "relationshipID": "1586d645-31e2-e611-80cc-1402ec7222b4", + "rightItem": { + "cardinality": "Many", + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "identifier": "0b86d645-31e2-e611-80cc-1402ec7222b4", + "relationshipType": "AttributeSet" + } + } + ], + "valueDefinitions": [ + { + "baseType": "Numeric", + "dataSourceID": 1, + "dataSourceName": {}, + "dataType": "LongNumber", + "description": "", + "localizedDescription": { + "value": "" + }, + "definitionID": "fb85d645-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "CustomObjectKey", + "definitionName": { + "value": "Custom Object Key" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 1, + "fullyQualifiedName": "Predictive Intelligence Product Purchases.Custom Object Key", + "isHidden": true, + "isIdentityValue": true, + "isNullable": false, + "isPrimaryKey": false, + "isReadOnly": true, + "isSystemDefined": true, + "isUpdateable": false, + "ordinal": 1, + "parentDefinition": { + "definitionID": "ee85d645-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "PredictiveIntelProductPurchases", + "definitionName": { + "value": "Predictive Intelligence Product Purchases" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "_CustomObjectKey", + "valueDefinitionID": "fb85d645-31e2-e611-80cc-1402ec7222b4", + "valueDefinitionKey": "CustomObjectKey", + "name": "Custom Object Key", + "setDefinitionID": "ee85d645-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "PredictiveIntelProductPurchases", + "setDefinitionName": { + "value": "Predictive Intelligence Product Purchases" + }, + "parentIdentifier": "ee85d645-31e2-e611-80cc-1402ec7222b4" + }, + { + "baseType": "Text", + "dataSourceID": 5, + "dataSourceName": {}, + "dataType": "Text", + "description": "Sku", + "localizedDescription": { + "value": "Sku" + }, + "definitionID": "f785d645-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "SKU", + "definitionName": { + "value": "SKU" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 2, + "fullyQualifiedName": "Predictive Intelligence Product Purchases.SKU", + "isHidden": false, + "isIdentityValue": false, + "isNullable": false, + "isPrimaryKey": true, + "isReadOnly": true, + "isSystemDefined": true, + "isUpdateable": false, + "length": 256, + "obfuscationProperties": { + "maskType": "None", + "maskTypeID": 0, + "storageTypeID": 1, + "storageType": "Plain", + "valueDefinitionID": "f785d645-31e2-e611-80cc-1402ec7222b4" + }, + "ordinal": 2, + "parentDefinition": { + "definitionID": "ee85d645-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "PredictiveIntelProductPurchases", + "definitionName": { + "value": "Predictive Intelligence Product Purchases" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "Sku", + "storageFieldReferenceID": { + "type": "guid", + "value": "8fbf489f-b82c-4c03-ab47-e8576a5625db" + }, + "valueDefinitionID": "f785d645-31e2-e611-80cc-1402ec7222b4", + "valueDefinitionKey": "SKU", + "name": "SKU", + "setDefinitionID": "ee85d645-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "PredictiveIntelProductPurchases", + "setDefinitionName": { + "value": "Predictive Intelligence Product Purchases" + }, + "parentIdentifier": "ee85d645-31e2-e611-80cc-1402ec7222b4" + }, + { + "baseType": "Numeric", + "dataSourceID": 5, + "dataSourceName": {}, + "dataType": "Decimal", + "description": "Price", + "localizedDescription": { + "value": "Price" + }, + "definitionID": "f485d645-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "Price", + "definitionName": { + "value": "Price" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 3, + "fullyQualifiedName": "Predictive Intelligence Product Purchases.Price", + "isHidden": false, + "isIdentityValue": false, + "isNullable": true, + "isPrimaryKey": false, + "isReadOnly": true, + "isSystemDefined": true, + "isUpdateable": false, + "length": 18, + "obfuscationProperties": { + "maskType": "None", + "maskTypeID": 0, + "storageTypeID": 1, + "storageType": "Plain", + "valueDefinitionID": "f485d645-31e2-e611-80cc-1402ec7222b4" + }, + "ordinal": 3, + "parentDefinition": { + "definitionID": "ee85d645-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "PredictiveIntelProductPurchases", + "definitionName": { + "value": "Predictive Intelligence Product Purchases" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "scale": 2, + "storageName": "Price", + "storageFieldReferenceID": { + "type": "guid", + "value": "f6942680-95e1-4000-9026-77fbfd8d5e41" + }, + "valueDefinitionID": "f485d645-31e2-e611-80cc-1402ec7222b4", + "valueDefinitionKey": "Price", + "name": "Price", + "setDefinitionID": "ee85d645-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "PredictiveIntelProductPurchases", + "setDefinitionName": { + "value": "Predictive Intelligence Product Purchases" + }, + "parentIdentifier": "ee85d645-31e2-e611-80cc-1402ec7222b4" + }, + { + "baseType": "Numeric", + "dataSourceID": 5, + "dataSourceName": {}, + "dataType": "Number", + "description": "Quantity", + "localizedDescription": { + "value": "Quantity" + }, + "definitionID": "f585d645-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "Quantity", + "definitionName": { + "value": "Quantity" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 4, + "fullyQualifiedName": "Predictive Intelligence Product Purchases.Quantity", + "isHidden": false, + "isIdentityValue": false, + "isNullable": true, + "isPrimaryKey": false, + "isReadOnly": true, + "isSystemDefined": true, + "isUpdateable": false, + "obfuscationProperties": { + "maskType": "None", + "maskTypeID": 0, + "storageTypeID": 1, + "storageType": "Plain", + "valueDefinitionID": "f585d645-31e2-e611-80cc-1402ec7222b4" + }, + "ordinal": 4, + "parentDefinition": { + "definitionID": "ee85d645-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "PredictiveIntelProductPurchases", + "definitionName": { + "value": "Predictive Intelligence Product Purchases" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "Quantity", + "storageFieldReferenceID": { + "type": "guid", + "value": "29508cf9-fac3-4d64-8e28-e691978bd659" + }, + "valueDefinitionID": "f585d645-31e2-e611-80cc-1402ec7222b4", + "valueDefinitionKey": "Quantity", + "name": "Quantity", + "setDefinitionID": "ee85d645-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "PredictiveIntelProductPurchases", + "setDefinitionName": { + "value": "Predictive Intelligence Product Purchases" + }, + "parentIdentifier": "ee85d645-31e2-e611-80cc-1402ec7222b4" + }, + { + "baseType": "Text", + "dataSourceID": 5, + "dataSourceName": {}, + "dataType": "Text", + "description": "order_number", + "localizedDescription": { + "value": "order_number" + }, + "definitionID": "f385d645-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "Order_Number", + "definitionName": { + "value": "Order Number" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 5, + "fullyQualifiedName": "Predictive Intelligence Product Purchases.Order Number", + "isHidden": false, + "isIdentityValue": false, + "isNullable": true, + "isPrimaryKey": false, + "isReadOnly": true, + "isSystemDefined": true, + "isUpdateable": false, + "length": 256, + "obfuscationProperties": { + "maskType": "None", + "maskTypeID": 0, + "storageTypeID": 1, + "storageType": "Plain", + "valueDefinitionID": "f385d645-31e2-e611-80cc-1402ec7222b4" + }, + "ordinal": 5, + "parentDefinition": { + "definitionID": "ee85d645-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "PredictiveIntelProductPurchases", + "definitionName": { + "value": "Predictive Intelligence Product Purchases" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "order_number", + "storageFieldReferenceID": { + "type": "guid", + "value": "d4024f16-8e2a-4f19-a852-6736071d8ec6" + }, + "valueDefinitionID": "f385d645-31e2-e611-80cc-1402ec7222b4", + "valueDefinitionKey": "Order_Number", + "name": "Order Number", + "setDefinitionID": "ee85d645-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "PredictiveIntelProductPurchases", + "setDefinitionName": { + "value": "Predictive Intelligence Product Purchases" + }, + "parentIdentifier": "ee85d645-31e2-e611-80cc-1402ec7222b4" + }, + { + "baseType": "Text", + "dataSourceID": 5, + "dataSourceName": {}, + "dataType": "Text", + "description": "user_id", + "localizedDescription": { + "value": "user_id" + }, + "definitionID": "fa85d645-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "User_ID", + "definitionName": { + "value": "User ID" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 6, + "fullyQualifiedName": "Predictive Intelligence Product Purchases.User ID", + "isHidden": false, + "isIdentityValue": false, + "isNullable": false, + "isPrimaryKey": true, + "isReadOnly": true, + "isSystemDefined": true, + "isUpdateable": false, + "length": 256, + "obfuscationProperties": { + "maskType": "None", + "maskTypeID": 0, + "storageTypeID": 1, + "storageType": "Plain", + "valueDefinitionID": "fa85d645-31e2-e611-80cc-1402ec7222b4" + }, + "ordinal": 6, + "parentDefinition": { + "definitionID": "ee85d645-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "PredictiveIntelProductPurchases", + "definitionName": { + "value": "Predictive Intelligence Product Purchases" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "user_id", + "storageFieldReferenceID": { + "type": "guid", + "value": "c318e0f3-c386-4beb-ab78-be4067c5520d" + }, + "valueDefinitionID": "fa85d645-31e2-e611-80cc-1402ec7222b4", + "valueDefinitionKey": "User_ID", + "name": "User ID", + "setDefinitionID": "ee85d645-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "PredictiveIntelProductPurchases", + "setDefinitionName": { + "value": "Predictive Intelligence Product Purchases" + }, + "parentIdentifier": "ee85d645-31e2-e611-80cc-1402ec7222b4" + }, + { + "baseType": "Date", + "dataSourceID": 5, + "dataSourceName": {}, + "dataType": "Date", + "description": "Timestamp", + "localizedDescription": { + "value": "Timestamp" + }, + "definitionID": "f985d645-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "Timestamp", + "definitionName": { + "value": "Timestamp" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 7, + "fullyQualifiedName": "Predictive Intelligence Product Purchases.Timestamp", + "isHidden": false, + "isIdentityValue": false, + "isNullable": false, + "isPrimaryKey": true, + "isReadOnly": true, + "isSystemDefined": true, + "isUpdateable": false, + "obfuscationProperties": { + "maskType": "None", + "maskTypeID": 0, + "storageTypeID": 1, + "storageType": "Plain", + "valueDefinitionID": "f985d645-31e2-e611-80cc-1402ec7222b4" + }, + "ordinal": 7, + "parentDefinition": { + "definitionID": "ee85d645-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "PredictiveIntelProductPurchases", + "definitionName": { + "value": "Predictive Intelligence Product Purchases" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "Timestamp", + "storageFieldReferenceID": { + "type": "guid", + "value": "499933ee-cc51-4a79-8db1-bf6bf304d61f" + }, + "valueDefinitionID": "f985d645-31e2-e611-80cc-1402ec7222b4", + "valueDefinitionKey": "Timestamp", + "name": "Timestamp", + "setDefinitionID": "ee85d645-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "PredictiveIntelProductPurchases", + "setDefinitionName": { + "value": "Predictive Intelligence Product Purchases" + }, + "parentIdentifier": "ee85d645-31e2-e611-80cc-1402ec7222b4" + }, + { + "baseType": "Numeric", + "dataSourceID": 5, + "dataSourceName": {}, + "dataType": "LongNumber", + "description": "Job_ID", + "localizedDescription": { + "value": "Job_ID" + }, + "definitionID": "f085d645-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "Job_ID", + "definitionName": { + "value": "Job_ID" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 9, + "fullyQualifiedName": "Predictive Intelligence Product Purchases.Job_ID", + "isHidden": false, + "isIdentityValue": false, + "isNullable": true, + "isPrimaryKey": false, + "isReadOnly": true, + "isSystemDefined": true, + "isUpdateable": false, + "obfuscationProperties": { + "maskType": "None", + "maskTypeID": 0, + "storageTypeID": 1, + "storageType": "Plain", + "valueDefinitionID": "f085d645-31e2-e611-80cc-1402ec7222b4" + }, + "ordinal": 9, + "parentDefinition": { + "definitionID": "ee85d645-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "PredictiveIntelProductPurchases", + "definitionName": { + "value": "Predictive Intelligence Product Purchases" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "Job_ID", + "storageFieldReferenceID": { + "type": "guid", + "value": "f021da2f-c005-46ca-a561-b6c3d9e095d0" + }, + "valueDefinitionID": "f085d645-31e2-e611-80cc-1402ec7222b4", + "valueDefinitionKey": "Job_ID", + "name": "Job_ID", + "setDefinitionID": "ee85d645-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "PredictiveIntelProductPurchases", + "setDefinitionName": { + "value": "Predictive Intelligence Product Purchases" + }, + "parentIdentifier": "ee85d645-31e2-e611-80cc-1402ec7222b4" + }, + { + "baseType": "Numeric", + "dataSourceID": 5, + "dataSourceName": {}, + "dataType": "LongNumber", + "description": "List_ID", + "localizedDescription": { + "value": "List_ID" + }, + "definitionID": "f285d645-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "List_ID", + "definitionName": { + "value": "List_ID" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 10, + "fullyQualifiedName": "Predictive Intelligence Product Purchases.List_ID", + "isHidden": false, + "isIdentityValue": false, + "isNullable": true, + "isPrimaryKey": false, + "isReadOnly": true, + "isSystemDefined": true, + "isUpdateable": false, + "obfuscationProperties": { + "maskType": "None", + "maskTypeID": 0, + "storageTypeID": 1, + "storageType": "Plain", + "valueDefinitionID": "f285d645-31e2-e611-80cc-1402ec7222b4" + }, + "ordinal": 10, + "parentDefinition": { + "definitionID": "ee85d645-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "PredictiveIntelProductPurchases", + "definitionName": { + "value": "Predictive Intelligence Product Purchases" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "List_ID", + "storageFieldReferenceID": { + "type": "guid", + "value": "6a8da7cf-8496-4ffe-8c5c-057fce68cccc" + }, + "valueDefinitionID": "f285d645-31e2-e611-80cc-1402ec7222b4", + "valueDefinitionKey": "List_ID", + "name": "List_ID", + "setDefinitionID": "ee85d645-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "PredictiveIntelProductPurchases", + "setDefinitionName": { + "value": "Predictive Intelligence Product Purchases" + }, + "parentIdentifier": "ee85d645-31e2-e611-80cc-1402ec7222b4" + }, + { + "baseType": "Numeric", + "dataSourceID": 5, + "dataSourceName": {}, + "dataType": "LongNumber", + "description": "Batch_ID", + "localizedDescription": { + "value": "Batch_ID" + }, + "definitionID": "ef85d645-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "Batch_ID", + "definitionName": { + "value": "Batch_ID" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 11, + "fullyQualifiedName": "Predictive Intelligence Product Purchases.Batch_ID", + "isHidden": false, + "isIdentityValue": false, + "isNullable": true, + "isPrimaryKey": false, + "isReadOnly": true, + "isSystemDefined": true, + "isUpdateable": false, + "obfuscationProperties": { + "maskType": "None", + "maskTypeID": 0, + "storageTypeID": 1, + "storageType": "Plain", + "valueDefinitionID": "ef85d645-31e2-e611-80cc-1402ec7222b4" + }, + "ordinal": 11, + "parentDefinition": { + "definitionID": "ee85d645-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "PredictiveIntelProductPurchases", + "definitionName": { + "value": "Predictive Intelligence Product Purchases" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "Batch_ID", + "storageFieldReferenceID": { + "type": "guid", + "value": "053d483c-62a0-4361-80a4-e99d8bde4550" + }, + "valueDefinitionID": "ef85d645-31e2-e611-80cc-1402ec7222b4", + "valueDefinitionKey": "Batch_ID", + "name": "Batch_ID", + "setDefinitionID": "ee85d645-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "PredictiveIntelProductPurchases", + "setDefinitionName": { + "value": "Predictive Intelligence Product Purchases" + }, + "parentIdentifier": "ee85d645-31e2-e611-80cc-1402ec7222b4" + }, + { + "baseType": "Numeric", + "dataSourceID": 5, + "dataSourceName": {}, + "dataType": "Number", + "description": "Landing_URL_ID", + "localizedDescription": { + "value": "Landing_URL_ID" + }, + "definitionID": "f185d645-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "Landing_URL_ID", + "definitionName": { + "value": "Landing_URL_ID" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 12, + "fullyQualifiedName": "Predictive Intelligence Product Purchases.Landing_URL_ID", + "isHidden": false, + "isIdentityValue": false, + "isNullable": true, + "isPrimaryKey": false, + "isReadOnly": true, + "isSystemDefined": true, + "isUpdateable": false, + "obfuscationProperties": { + "maskType": "None", + "maskTypeID": 0, + "storageTypeID": 1, + "storageType": "Plain", + "valueDefinitionID": "f185d645-31e2-e611-80cc-1402ec7222b4" + }, + "ordinal": 12, + "parentDefinition": { + "definitionID": "ee85d645-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "PredictiveIntelProductPurchases", + "definitionName": { + "value": "Predictive Intelligence Product Purchases" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "Landing_URL_ID", + "storageFieldReferenceID": { + "type": "guid", + "value": "d37c4358-5810-4d47-bcec-92829b828703" + }, + "valueDefinitionID": "f185d645-31e2-e611-80cc-1402ec7222b4", + "valueDefinitionKey": "Landing_URL_ID", + "name": "Landing_URL_ID", + "setDefinitionID": "ee85d645-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "PredictiveIntelProductPurchases", + "setDefinitionName": { + "value": "Predictive Intelligence Product Purchases" + }, + "parentIdentifier": "ee85d645-31e2-e611-80cc-1402ec7222b4" + }, + { + "baseType": "Numeric", + "dataSourceID": 5, + "dataSourceName": {}, + "dataType": "LongNumber", + "description": "Subscriber_ID", + "localizedDescription": { + "value": "Subscriber_ID" + }, + "definitionID": "f885d645-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "Subscriber_ID", + "definitionName": { + "value": "Subscriber_ID" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 13, + "fullyQualifiedName": "Predictive Intelligence Product Purchases.Subscriber_ID", + "isHidden": false, + "isIdentityValue": false, + "isNullable": true, + "isPrimaryKey": false, + "isReadOnly": true, + "isSystemDefined": true, + "isUpdateable": false, + "obfuscationProperties": { + "maskType": "None", + "maskTypeID": 0, + "storageTypeID": 1, + "storageType": "Plain", + "valueDefinitionID": "f885d645-31e2-e611-80cc-1402ec7222b4" + }, + "ordinal": 13, + "parentDefinition": { + "definitionID": "ee85d645-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "PredictiveIntelProductPurchases", + "definitionName": { + "value": "Predictive Intelligence Product Purchases" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "Subscriber_ID", + "storageFieldReferenceID": { + "type": "guid", + "value": "5c0c3f04-baec-434a-b463-4f82e3a9fb9c" + }, + "valueDefinitionID": "f885d645-31e2-e611-80cc-1402ec7222b4", + "valueDefinitionKey": "Subscriber_ID", + "name": "Subscriber_ID", + "setDefinitionID": "ee85d645-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "PredictiveIntelProductPurchases", + "setDefinitionName": { + "value": "Predictive Intelligence Product Purchases" + }, + "parentIdentifier": "ee85d645-31e2-e611-80cc-1402ec7222b4" + }, + { + "baseType": "Text", + "dataSourceID": 5, + "dataSourceName": {}, + "dataType": "Text", + "description": "session_id", + "localizedDescription": { + "value": "session_id" + }, + "definitionID": "f685d645-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "session_id", + "definitionName": { + "value": "session_id" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 14, + "fullyQualifiedName": "Predictive Intelligence Product Purchases.session_id", + "isHidden": false, + "isIdentityValue": false, + "isNullable": true, + "isPrimaryKey": false, + "isReadOnly": true, + "isSystemDefined": true, + "isUpdateable": false, + "length": 256, + "obfuscationProperties": { + "maskType": "None", + "maskTypeID": 0, + "storageTypeID": 1, + "storageType": "Plain", + "valueDefinitionID": "f685d645-31e2-e611-80cc-1402ec7222b4" + }, + "ordinal": 14, + "parentDefinition": { + "definitionID": "ee85d645-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "PredictiveIntelProductPurchases", + "definitionName": { + "value": "Predictive Intelligence Product Purchases" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "session_id", + "storageFieldReferenceID": { + "type": "guid", + "value": "33bf36ba-c6b7-43cd-b996-abf12ced61fb" + }, + "valueDefinitionID": "f685d645-31e2-e611-80cc-1402ec7222b4", + "valueDefinitionKey": "session_id", + "name": "session_id", + "setDefinitionID": "ee85d645-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "PredictiveIntelProductPurchases", + "setDefinitionName": { + "value": "Predictive Intelligence Product Purchases" + }, + "parentIdentifier": "ee85d645-31e2-e611-80cc-1402ec7222b4" + } + ], + "applicationID": "f4981f88-a13e-4abf-b331-47f41c73258d", + "applicationKey": "com.exacttarget.Predictive Web", + "attributeCount": 0, + "canAddValues": false, + "canChangeValues": false, + "canModify": false, + "canRemove": false, + "categoryID": 386, + "createdBy": -1000, + "createDate": "2017-01-24T06:33:00", + "customObjectOwnerMID": 1111111, + "dataRetentionProperties": { + "isRowBasedRetention": false, + "isResetRetentionPeriodOnImport": false, + "isDeleteAtEndOfRetentionPeriod": false, + "periodUnitOfMeasure": 4, + "setDefinitionID": "ee85d645-31e2-e611-80cc-1402ec7222b4" + }, + "localizedDescription": {}, + "fullyQualifiedName": "Predictive Intelligence Product Purchases", + "isCustomObjectBacked": true, + "isEvent": false, + "isHidden": false, + "isReadOnly": true, + "isRoot": false, + "isSendable": false, + "isShared": false, + "isSystemDefined": true, + "isTestaable": false, + "parentID": "00000000-0000-0000-0000-000000000000", + "relationshipCount": 2, + "storageLogicalType": "DataExtension", + "storageName": "IGO_PURCHASES", + "storageObjectIDs": ["e085d645-31e2-e611-80cc-1402ec7222b4"], + "storageReferenceID": { + "type": "guid", + "value": "d752de3f-31e2-e611-80cc-1402ec7222b4" + }, + "setDefinitionID": "ee85d645-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "PredictiveIntelProductPurchases", + "name": "Predictive Intelligence Product Purchases" + }, + { + "definitionID": "f2e9847d-696d-eb11-b81e-48df37d1df5a", + "definitionKey": "ChatMessageSubscriptions", + "definitionName": { + "value": "Chat Message Subscriptions" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "valueDefinitions": [ + { + "baseType": "Numeric", + "dataSourceID": 1, + "dataSourceName": {}, + "dataType": "LongNumber", + "description": "", + "localizedDescription": { + "value": "" + }, + "definitionID": "02ea847d-696d-eb11-b81e-48df37d1df5a", + "definitionKey": "CustomObjectKey", + "definitionName": { + "value": "Custom Object Key" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "fullyQualifiedName": "Chat Message Subscriptions.Custom Object Key", + "isHidden": true, + "isIdentityValue": true, + "isNullable": false, + "isPrimaryKey": false, + "isReadOnly": true, + "isSystemDefined": true, + "isUpdateable": false, + "parentDefinition": { + "definitionID": "f2e9847d-696d-eb11-b81e-48df37d1df5a", + "definitionKey": "ChatMessageSubscriptions", + "definitionName": { + "value": "Chat Message Subscriptions" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "_CustomObjectKey", + "valueDefinitionID": "02ea847d-696d-eb11-b81e-48df37d1df5a", + "valueDefinitionKey": "CustomObjectKey", + "name": "Custom Object Key", + "setDefinitionID": "f2e9847d-696d-eb11-b81e-48df37d1df5a", + "setDefinitionKey": "ChatMessageSubscriptions", + "setDefinitionName": { + "value": "Chat Message Subscriptions" + }, + "parentIdentifier": "f2e9847d-696d-eb11-b81e-48df37d1df5a" + }, + { + "baseType": "Text", + "dataSourceID": 1, + "dataSourceName": {}, + "dataType": "Text", + "description": "", + "localizedDescription": { + "value": "" + }, + "definitionID": "f7e9847d-696d-eb11-b81e-48df37d1df5a", + "definitionKey": "_MobileNumber", + "definitionName": { + "value": "MobileNumber" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 2, + "fullyQualifiedName": "Chat Message Subscriptions.MobileNumber", + "isHidden": false, + "isIdentityValue": false, + "isNullable": false, + "isPrimaryKey": true, + "isReadOnly": true, + "isSystemDefined": true, + "isUpdateable": false, + "length": 254, + "ordinal": 2, + "parentDefinition": { + "definitionID": "f2e9847d-696d-eb11-b81e-48df37d1df5a", + "definitionKey": "ChatMessageSubscriptions", + "definitionName": { + "value": "Chat Message Subscriptions" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "_MobileNumber", + "storageFieldReferenceID": { + "type": "guid", + "value": "169e88d8-d9fe-43f4-82e2-f325674328ee" + }, + "valueDefinitionID": "f7e9847d-696d-eb11-b81e-48df37d1df5a", + "valueDefinitionKey": "_MobileNumber", + "name": "MobileNumber", + "setDefinitionID": "f2e9847d-696d-eb11-b81e-48df37d1df5a", + "setDefinitionKey": "ChatMessageSubscriptions", + "setDefinitionName": { + "value": "Chat Message Subscriptions" + }, + "parentIdentifier": "f2e9847d-696d-eb11-b81e-48df37d1df5a" + }, + { + "baseType": "Text", + "dataSourceID": 1, + "dataSourceName": {}, + "dataType": "Text", + "description": "", + "localizedDescription": { + "value": "" + }, + "definitionID": "f3e9847d-696d-eb11-b81e-48df37d1df5a", + "definitionKey": "_ChannelId", + "definitionName": { + "value": "ChannelId" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 3, + "fullyQualifiedName": "Chat Message Subscriptions.ChannelId", + "isHidden": false, + "isIdentityValue": false, + "isNullable": false, + "isPrimaryKey": true, + "isReadOnly": true, + "isSystemDefined": true, + "isUpdateable": false, + "length": 50, + "ordinal": 3, + "parentDefinition": { + "definitionID": "f2e9847d-696d-eb11-b81e-48df37d1df5a", + "definitionKey": "ChatMessageSubscriptions", + "definitionName": { + "value": "Chat Message Subscriptions" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "_ChannelId", + "storageFieldReferenceID": { + "type": "guid", + "value": "5f56cbc2-6799-4b37-b24d-38b16e9ed30a" + }, + "valueDefinitionID": "f3e9847d-696d-eb11-b81e-48df37d1df5a", + "valueDefinitionKey": "_ChannelId", + "name": "ChannelId", + "setDefinitionID": "f2e9847d-696d-eb11-b81e-48df37d1df5a", + "setDefinitionKey": "ChatMessageSubscriptions", + "setDefinitionName": { + "value": "Chat Message Subscriptions" + }, + "parentIdentifier": "f2e9847d-696d-eb11-b81e-48df37d1df5a" + }, + { + "baseType": "Text", + "dataSourceID": 1, + "dataSourceName": {}, + "dataType": "Text", + "description": "", + "localizedDescription": { + "value": "" + }, + "definitionID": "f4e9847d-696d-eb11-b81e-48df37d1df5a", + "definitionKey": "_ChannelType", + "definitionName": { + "value": "ChannelType" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 4, + "fullyQualifiedName": "Chat Message Subscriptions.ChannelType", + "isHidden": false, + "isIdentityValue": false, + "isNullable": false, + "isPrimaryKey": true, + "isReadOnly": true, + "isSystemDefined": true, + "isUpdateable": false, + "length": 20, + "ordinal": 4, + "parentDefinition": { + "definitionID": "f2e9847d-696d-eb11-b81e-48df37d1df5a", + "definitionKey": "ChatMessageSubscriptions", + "definitionName": { + "value": "Chat Message Subscriptions" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "_ChannelType", + "storageFieldReferenceID": { + "type": "guid", + "value": "d442b162-248b-4546-b0ee-7d86d4444d3b" + }, + "valueDefinitionID": "f4e9847d-696d-eb11-b81e-48df37d1df5a", + "valueDefinitionKey": "_ChannelType", + "name": "ChannelType", + "setDefinitionID": "f2e9847d-696d-eb11-b81e-48df37d1df5a", + "setDefinitionKey": "ChatMessageSubscriptions", + "setDefinitionName": { + "value": "Chat Message Subscriptions" + }, + "parentIdentifier": "f2e9847d-696d-eb11-b81e-48df37d1df5a" + }, + { + "baseType": "Numeric", + "dataSourceID": 1, + "dataSourceName": {}, + "dataType": "Byte", + "description": "", + "localizedDescription": { + "value": "" + }, + "definitionID": "ffe9847d-696d-eb11-b81e-48df37d1df5a", + "definitionKey": "_OptOutStatusID", + "definitionName": { + "value": "OptOutStatusID" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 5, + "fullyQualifiedName": "Chat Message Subscriptions.OptOutStatusID", + "isHidden": false, + "isIdentityValue": false, + "isNullable": true, + "isPrimaryKey": false, + "isReadOnly": false, + "isSystemDefined": true, + "isUpdateable": false, + "ordinal": 5, + "parentDefinition": { + "definitionID": "f2e9847d-696d-eb11-b81e-48df37d1df5a", + "definitionKey": "ChatMessageSubscriptions", + "definitionName": { + "value": "Chat Message Subscriptions" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "restrictionLookupListID": 15, + "storageName": "_OptOutStatusID", + "storageFieldReferenceID": { + "type": "guid", + "value": "ca82f469-ea9e-44d8-ad4f-d8ed7536518f" + }, + "valueDefinitionID": "ffe9847d-696d-eb11-b81e-48df37d1df5a", + "valueDefinitionKey": "_OptOutStatusID", + "name": "OptOutStatusID", + "setDefinitionID": "f2e9847d-696d-eb11-b81e-48df37d1df5a", + "setDefinitionKey": "ChatMessageSubscriptions", + "setDefinitionName": { + "value": "Chat Message Subscriptions" + }, + "parentIdentifier": "f2e9847d-696d-eb11-b81e-48df37d1df5a" + }, + { + "baseType": "Numeric", + "dataSourceID": 1, + "dataSourceName": {}, + "dataType": "Byte", + "description": "", + "localizedDescription": { + "value": "" + }, + "definitionID": "fee9847d-696d-eb11-b81e-48df37d1df5a", + "definitionKey": "_OptOutMethodID", + "definitionName": { + "value": "OptOutMethodID" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 6, + "fullyQualifiedName": "Chat Message Subscriptions.OptOutMethodID", + "isHidden": false, + "isIdentityValue": false, + "isNullable": true, + "isPrimaryKey": false, + "isReadOnly": true, + "isSystemDefined": true, + "isUpdateable": false, + "ordinal": 6, + "parentDefinition": { + "definitionID": "f2e9847d-696d-eb11-b81e-48df37d1df5a", + "definitionKey": "ChatMessageSubscriptions", + "definitionName": { + "value": "Chat Message Subscriptions" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "_OptOutMethodID", + "storageFieldReferenceID": { + "type": "guid", + "value": "c47ca0dc-f8b3-4476-8ffb-1cbf22b6254e" + }, + "valueDefinitionID": "fee9847d-696d-eb11-b81e-48df37d1df5a", + "valueDefinitionKey": "_OptOutMethodID", + "name": "OptOutMethodID", + "setDefinitionID": "f2e9847d-696d-eb11-b81e-48df37d1df5a", + "setDefinitionKey": "ChatMessageSubscriptions", + "setDefinitionName": { + "value": "Chat Message Subscriptions" + }, + "parentIdentifier": "f2e9847d-696d-eb11-b81e-48df37d1df5a" + }, + { + "baseType": "Date", + "dataSourceID": 1, + "dataSourceName": {}, + "dataType": "Date", + "description": "", + "localizedDescription": { + "value": "" + }, + "definitionID": "fde9847d-696d-eb11-b81e-48df37d1df5a", + "definitionKey": "_OptOutDate", + "definitionName": { + "value": "OptOutDate" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 7, + "fullyQualifiedName": "Chat Message Subscriptions.OptOutDate", + "isHidden": false, + "isIdentityValue": false, + "isNullable": true, + "isPrimaryKey": false, + "isReadOnly": true, + "isSystemDefined": true, + "isUpdateable": false, + "ordinal": 7, + "parentDefinition": { + "definitionID": "f2e9847d-696d-eb11-b81e-48df37d1df5a", + "definitionKey": "ChatMessageSubscriptions", + "definitionName": { + "value": "Chat Message Subscriptions" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "_OptOutDate", + "storageFieldReferenceID": { + "type": "guid", + "value": "0b8b6cdd-86ba-4d36-8e27-0e0b4bde256f" + }, + "valueDefinitionID": "fde9847d-696d-eb11-b81e-48df37d1df5a", + "valueDefinitionKey": "_OptOutDate", + "name": "OptOutDate", + "setDefinitionID": "f2e9847d-696d-eb11-b81e-48df37d1df5a", + "setDefinitionKey": "ChatMessageSubscriptions", + "setDefinitionName": { + "value": "Chat Message Subscriptions" + }, + "parentIdentifier": "f2e9847d-696d-eb11-b81e-48df37d1df5a" + }, + { + "baseType": "Numeric", + "dataSourceID": 1, + "dataSourceName": {}, + "dataType": "Byte", + "description": "", + "localizedDescription": { + "value": "" + }, + "definitionID": "fce9847d-696d-eb11-b81e-48df37d1df5a", + "definitionKey": "_OptInStatusID", + "definitionName": { + "value": "OptInStatusID" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 8, + "fullyQualifiedName": "Chat Message Subscriptions.OptInStatusID", + "isHidden": false, + "isIdentityValue": false, + "isNullable": false, + "isPrimaryKey": false, + "isReadOnly": false, + "isSystemDefined": true, + "isUpdateable": false, + "ordinal": 8, + "parentDefinition": { + "definitionID": "f2e9847d-696d-eb11-b81e-48df37d1df5a", + "definitionKey": "ChatMessageSubscriptions", + "definitionName": { + "value": "Chat Message Subscriptions" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "_OptInStatusID", + "storageFieldReferenceID": { + "type": "guid", + "value": "c0f3cd62-55cb-4f61-bb97-d3676e9c7eea" + }, + "valueDefinitionID": "fce9847d-696d-eb11-b81e-48df37d1df5a", + "valueDefinitionKey": "_OptInStatusID", + "name": "OptInStatusID", + "setDefinitionID": "f2e9847d-696d-eb11-b81e-48df37d1df5a", + "setDefinitionKey": "ChatMessageSubscriptions", + "setDefinitionName": { + "value": "Chat Message Subscriptions" + }, + "parentIdentifier": "f2e9847d-696d-eb11-b81e-48df37d1df5a" + }, + { + "baseType": "Numeric", + "dataSourceID": 1, + "dataSourceName": {}, + "dataType": "Byte", + "description": "", + "localizedDescription": { + "value": "" + }, + "definitionID": "fbe9847d-696d-eb11-b81e-48df37d1df5a", + "definitionKey": "_OptInMethodID", + "definitionName": { + "value": "OptInMethodID" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 9, + "fullyQualifiedName": "Chat Message Subscriptions.OptInMethodID", + "isHidden": false, + "isIdentityValue": false, + "isNullable": true, + "isPrimaryKey": false, + "isReadOnly": true, + "isSystemDefined": true, + "isUpdateable": false, + "ordinal": 9, + "parentDefinition": { + "definitionID": "f2e9847d-696d-eb11-b81e-48df37d1df5a", + "definitionKey": "ChatMessageSubscriptions", + "definitionName": { + "value": "Chat Message Subscriptions" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "_OptInMethodID", + "storageFieldReferenceID": { + "type": "guid", + "value": "a4d5dea8-cd22-435c-b389-9cdce054149c" + }, + "valueDefinitionID": "fbe9847d-696d-eb11-b81e-48df37d1df5a", + "valueDefinitionKey": "_OptInMethodID", + "name": "OptInMethodID", + "setDefinitionID": "f2e9847d-696d-eb11-b81e-48df37d1df5a", + "setDefinitionKey": "ChatMessageSubscriptions", + "setDefinitionName": { + "value": "Chat Message Subscriptions" + }, + "parentIdentifier": "f2e9847d-696d-eb11-b81e-48df37d1df5a" + }, + { + "baseType": "Date", + "dataSourceID": 1, + "dataSourceName": {}, + "dataType": "Date", + "description": "", + "localizedDescription": { + "value": "" + }, + "definitionID": "fae9847d-696d-eb11-b81e-48df37d1df5a", + "definitionKey": "_OptInDate", + "definitionName": { + "value": "OptInDate" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 10, + "fullyQualifiedName": "Chat Message Subscriptions.OptInDate", + "isHidden": false, + "isIdentityValue": false, + "isNullable": true, + "isPrimaryKey": false, + "isReadOnly": false, + "isSystemDefined": true, + "isUpdateable": false, + "ordinal": 10, + "parentDefinition": { + "definitionID": "f2e9847d-696d-eb11-b81e-48df37d1df5a", + "definitionKey": "ChatMessageSubscriptions", + "definitionName": { + "value": "Chat Message Subscriptions" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "_OptInDate", + "storageFieldReferenceID": { + "type": "guid", + "value": "4fbd9715-9b10-4e4b-bf89-215786c84e96" + }, + "valueDefinitionID": "fae9847d-696d-eb11-b81e-48df37d1df5a", + "valueDefinitionKey": "_OptInDate", + "name": "OptInDate", + "setDefinitionID": "f2e9847d-696d-eb11-b81e-48df37d1df5a", + "setDefinitionKey": "ChatMessageSubscriptions", + "setDefinitionName": { + "value": "Chat Message Subscriptions" + }, + "parentIdentifier": "f2e9847d-696d-eb11-b81e-48df37d1df5a" + }, + { + "baseType": "Numeric", + "dataSourceID": 1, + "dataSourceName": {}, + "dataType": "Byte", + "description": "", + "localizedDescription": { + "value": "" + }, + "definitionID": "00ea847d-696d-eb11-b81e-48df37d1df5a", + "definitionKey": "_Source", + "definitionName": { + "value": "Source" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 11, + "fullyQualifiedName": "Chat Message Subscriptions.Source", + "isHidden": false, + "isIdentityValue": false, + "isNullable": true, + "isPrimaryKey": false, + "isReadOnly": true, + "isSystemDefined": true, + "isUpdateable": false, + "ordinal": 11, + "parentDefinition": { + "definitionID": "f2e9847d-696d-eb11-b81e-48df37d1df5a", + "definitionKey": "ChatMessageSubscriptions", + "definitionName": { + "value": "Chat Message Subscriptions" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "_Source", + "storageFieldReferenceID": { + "type": "guid", + "value": "2b7a081b-127c-4d65-bdfe-f80f274f4580" + }, + "valueDefinitionID": "00ea847d-696d-eb11-b81e-48df37d1df5a", + "valueDefinitionKey": "_Source", + "name": "Source", + "setDefinitionID": "f2e9847d-696d-eb11-b81e-48df37d1df5a", + "setDefinitionKey": "ChatMessageSubscriptions", + "setDefinitionName": { + "value": "Chat Message Subscriptions" + }, + "parentIdentifier": "f2e9847d-696d-eb11-b81e-48df37d1df5a" + }, + { + "baseType": "Text", + "dataSourceID": 1, + "dataSourceName": {}, + "dataType": "Text", + "description": "", + "localizedDescription": { + "value": "" + }, + "definitionID": "01ea847d-696d-eb11-b81e-48df37d1df5a", + "definitionKey": "_SourceObjectId ", + "definitionName": { + "value": "SourceObjectId" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 12, + "fullyQualifiedName": "Chat Message Subscriptions.SourceObjectId", + "isHidden": false, + "isIdentityValue": false, + "isNullable": true, + "isPrimaryKey": false, + "isReadOnly": true, + "isSystemDefined": true, + "isUpdateable": false, + "length": 200, + "ordinal": 12, + "parentDefinition": { + "definitionID": "f2e9847d-696d-eb11-b81e-48df37d1df5a", + "definitionKey": "ChatMessageSubscriptions", + "definitionName": { + "value": "Chat Message Subscriptions" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "_SourceObjectId ", + "storageFieldReferenceID": { + "type": "guid", + "value": "47505922-899e-45b8-a1cc-c0049d280504" + }, + "valueDefinitionID": "01ea847d-696d-eb11-b81e-48df37d1df5a", + "valueDefinitionKey": "_SourceObjectId ", + "name": "SourceObjectId", + "setDefinitionID": "f2e9847d-696d-eb11-b81e-48df37d1df5a", + "setDefinitionKey": "ChatMessageSubscriptions", + "setDefinitionName": { + "value": "Chat Message Subscriptions" + }, + "parentIdentifier": "f2e9847d-696d-eb11-b81e-48df37d1df5a" + }, + { + "baseType": "Date", + "dataSourceID": 1, + "dataSourceName": {}, + "dataType": "Date", + "defaultValue": "GETDATE()", + "description": "", + "localizedDescription": { + "value": "" + }, + "definitionID": "f6e9847d-696d-eb11-b81e-48df37d1df5a", + "definitionKey": "_CreatedDate", + "definitionName": { + "value": "CreatedDate" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 13, + "fullyQualifiedName": "Chat Message Subscriptions.CreatedDate", + "isHidden": false, + "isIdentityValue": false, + "isNullable": false, + "isPrimaryKey": false, + "isReadOnly": true, + "isSystemDefined": true, + "isUpdateable": false, + "ordinal": 13, + "parentDefinition": { + "definitionID": "f2e9847d-696d-eb11-b81e-48df37d1df5a", + "definitionKey": "ChatMessageSubscriptions", + "definitionName": { + "value": "Chat Message Subscriptions" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "_CreatedDate", + "storageFieldReferenceID": { + "type": "guid", + "value": "ae8a3f3e-1020-484e-8e24-5c11c7393d56" + }, + "valueDefinitionID": "f6e9847d-696d-eb11-b81e-48df37d1df5a", + "valueDefinitionKey": "_CreatedDate", + "name": "CreatedDate", + "setDefinitionID": "f2e9847d-696d-eb11-b81e-48df37d1df5a", + "setDefinitionKey": "ChatMessageSubscriptions", + "setDefinitionName": { + "value": "Chat Message Subscriptions" + }, + "parentIdentifier": "f2e9847d-696d-eb11-b81e-48df37d1df5a" + }, + { + "baseType": "Numeric", + "dataSourceID": 1, + "dataSourceName": {}, + "dataType": "LongNumber", + "description": "", + "localizedDescription": { + "value": "" + }, + "definitionID": "f5e9847d-696d-eb11-b81e-48df37d1df5a", + "definitionKey": "_CreatedBy ", + "definitionName": { + "value": "CreatedBy" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 14, + "fullyQualifiedName": "Chat Message Subscriptions.CreatedBy", + "isHidden": false, + "isIdentityValue": false, + "isNullable": true, + "isPrimaryKey": false, + "isReadOnly": true, + "isSystemDefined": true, + "isUpdateable": false, + "ordinal": 14, + "parentDefinition": { + "definitionID": "f2e9847d-696d-eb11-b81e-48df37d1df5a", + "definitionKey": "ChatMessageSubscriptions", + "definitionName": { + "value": "Chat Message Subscriptions" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "_CreatedBy ", + "storageFieldReferenceID": { + "type": "guid", + "value": "0b7dac0b-728a-4fb7-a63e-c21311d784d3" + }, + "valueDefinitionID": "f5e9847d-696d-eb11-b81e-48df37d1df5a", + "valueDefinitionKey": "_CreatedBy ", + "name": "CreatedBy", + "setDefinitionID": "f2e9847d-696d-eb11-b81e-48df37d1df5a", + "setDefinitionKey": "ChatMessageSubscriptions", + "setDefinitionName": { + "value": "Chat Message Subscriptions" + }, + "parentIdentifier": "f2e9847d-696d-eb11-b81e-48df37d1df5a" + }, + { + "baseType": "Date", + "dataSourceID": 1, + "dataSourceName": {}, + "dataType": "Date", + "defaultValue": "GETDATE()", + "description": "", + "localizedDescription": { + "value": "" + }, + "definitionID": "f9e9847d-696d-eb11-b81e-48df37d1df5a", + "definitionKey": "_ModifiedDate", + "definitionName": { + "value": "ModifiedDate" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 15, + "fullyQualifiedName": "Chat Message Subscriptions.ModifiedDate", + "isHidden": false, + "isIdentityValue": false, + "isNullable": false, + "isPrimaryKey": false, + "isReadOnly": true, + "isSystemDefined": true, + "isUpdateable": false, + "ordinal": 15, + "parentDefinition": { + "definitionID": "f2e9847d-696d-eb11-b81e-48df37d1df5a", + "definitionKey": "ChatMessageSubscriptions", + "definitionName": { + "value": "Chat Message Subscriptions" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "_ModifiedDate", + "storageFieldReferenceID": { + "type": "guid", + "value": "10d39942-4628-4e99-a927-523fe48d1068" + }, + "valueDefinitionID": "f9e9847d-696d-eb11-b81e-48df37d1df5a", + "valueDefinitionKey": "_ModifiedDate", + "name": "ModifiedDate", + "setDefinitionID": "f2e9847d-696d-eb11-b81e-48df37d1df5a", + "setDefinitionKey": "ChatMessageSubscriptions", + "setDefinitionName": { + "value": "Chat Message Subscriptions" + }, + "parentIdentifier": "f2e9847d-696d-eb11-b81e-48df37d1df5a" + }, + { + "baseType": "Numeric", + "dataSourceID": 1, + "dataSourceName": {}, + "dataType": "LongNumber", + "description": "", + "localizedDescription": { + "value": "" + }, + "definitionID": "f8e9847d-696d-eb11-b81e-48df37d1df5a", + "definitionKey": "_ModifiedBy ", + "definitionName": { + "value": "ModifiedBy" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 16, + "fullyQualifiedName": "Chat Message Subscriptions.ModifiedBy", + "isHidden": false, + "isIdentityValue": false, + "isNullable": true, + "isPrimaryKey": false, + "isReadOnly": true, + "isSystemDefined": true, + "isUpdateable": false, + "ordinal": 16, + "parentDefinition": { + "definitionID": "f2e9847d-696d-eb11-b81e-48df37d1df5a", + "definitionKey": "ChatMessageSubscriptions", + "definitionName": { + "value": "Chat Message Subscriptions" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "_ModifiedBy ", + "storageFieldReferenceID": { + "type": "guid", + "value": "a0486cff-d96e-41dd-9286-c77ddad92f75" + }, + "valueDefinitionID": "f8e9847d-696d-eb11-b81e-48df37d1df5a", + "valueDefinitionKey": "_ModifiedBy ", + "name": "ModifiedBy", + "setDefinitionID": "f2e9847d-696d-eb11-b81e-48df37d1df5a", + "setDefinitionKey": "ChatMessageSubscriptions", + "setDefinitionName": { + "value": "Chat Message Subscriptions" + }, + "parentIdentifier": "f2e9847d-696d-eb11-b81e-48df37d1df5a" + } + ], + "applicationID": "e25893f9-08f3-480f-8def-7f8ab0583611", + "applicationKey": "com.exacttarget.mobileconnect", + "attributeCount": 0, + "canAddValues": false, + "canChangeValues": false, + "canModify": false, + "canRemove": false, + "categoryID": 2, + "createDate": "2021-02-12T13:36:00", + "customObjectOwnerMID": 1111111, + "dataRetentionProperties": { + "isRowBasedRetention": false, + "isResetRetentionPeriodOnImport": false, + "isDeleteAtEndOfRetentionPeriod": false, + "setDefinitionID": "f2e9847d-696d-eb11-b81e-48df37d1df5a" + }, + "localizedDescription": {}, + "fullyQualifiedName": "Chat Message Subscriptions", + "isCustomObjectBacked": true, + "isEvent": false, + "isHidden": false, + "isReadOnly": false, + "isRoot": false, + "isSendable": false, + "isShared": false, + "isSystemDefined": true, + "isTestaable": false, + "parentID": "00000000-0000-0000-0000-000000000000", + "relationshipCount": 0, + "storageLogicalType": "DataExtension", + "storageName": "_ChatMessagingSubscription", + "storageObjectIDs": ["e1e9847d-696d-eb11-b81e-48df37d1df5a"], + "storageReferenceID": { + "type": "guid", + "value": "38042500-a868-eb11-b81e-48df37d1df5a" + }, + "setDefinitionID": "f2e9847d-696d-eb11-b81e-48df37d1df5a", + "setDefinitionKey": "ChatMessageSubscriptions", + "name": "Chat Message Subscriptions" + }, + { + "definitionID": "f452de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "PredictiveIntelProfiles", + "definitionName": { + "value": "Predictive Intelligence Profiles" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "relationships": [ + { + "canModify": false, + "canRemove": false, + "isHidden": false, + "isSystemDefined": false, + "isGroupToSetRelationship": true, + "leftItem": { + "cardinality": "One", + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "identifier": "e152de3f-31e2-e611-80cc-1402ec7222b4", + "relationshipType": "AttributeGroup" + }, + "leftRelationshipIDs": [ + { + "type": "int16", + "value": "4" + } + ], + "leftRelationshipReferenceType": "CustomerData", + "relationshipAttributes": [ + { + "leftAttributeID": "1151de3f-31e2-e611-80cc-1402ec7222b4", + "leftConnectingID": { + "identifierType": "FullyQualifiedName" + }, + "rightAttributeID": "fc52de3f-31e2-e611-80cc-1402ec7222b4", + "rightConnectingID": { + "identifierType": "FullyQualifiedName" + } + } + ], + "relationshipID": "9885d645-31e2-e611-80cc-1402ec7222b4", + "rightItem": { + "cardinality": "Many", + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "identifier": "f452de3f-31e2-e611-80cc-1402ec7222b4", + "relationshipType": "AttributeSet" + } + }, + { + "canModify": false, + "canRemove": false, + "isHidden": false, + "isSystemDefined": false, + "isGroupToSetRelationship": false, + "leftItem": { + "cardinality": "One", + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "identifier": "f452de3f-31e2-e611-80cc-1402ec7222b4", + "relationshipType": "AttributeSet" + }, + "relationshipAttributes": [ + { + "leftAttributeID": "fe52de3f-31e2-e611-80cc-1402ec7222b4", + "leftConnectingID": { + "identifierType": "FullyQualifiedName" + }, + "rightAttributeID": "2386d645-31e2-e611-80cc-1402ec7222b4", + "rightConnectingID": { + "identifierType": "FullyQualifiedName" + } + } + ], + "relationshipID": "2686d645-31e2-e611-80cc-1402ec7222b4", + "rightItem": { + "cardinality": "Many", + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "identifier": "1e86d645-31e2-e611-80cc-1402ec7222b4", + "relationshipType": "AttributeSet" + } + }, + { + "canModify": false, + "canRemove": false, + "isHidden": false, + "isSystemDefined": false, + "isGroupToSetRelationship": false, + "leftItem": { + "cardinality": "One", + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "identifier": "f452de3f-31e2-e611-80cc-1402ec7222b4", + "relationshipType": "AttributeSet" + }, + "relationshipAttributes": [ + { + "leftAttributeID": "fe52de3f-31e2-e611-80cc-1402ec7222b4", + "leftConnectingID": { + "identifierType": "FullyQualifiedName" + }, + "rightAttributeID": "5a86d645-31e2-e611-80cc-1402ec7222b4", + "rightConnectingID": { + "identifierType": "FullyQualifiedName" + } + } + ], + "relationshipID": "5d86d645-31e2-e611-80cc-1402ec7222b4", + "rightItem": { + "cardinality": "One", + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "identifier": "5286d645-31e2-e611-80cc-1402ec7222b4", + "relationshipType": "AttributeSet" + } + }, + { + "canModify": false, + "canRemove": false, + "isHidden": false, + "isSystemDefined": false, + "isGroupToSetRelationship": false, + "leftItem": { + "cardinality": "One", + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "identifier": "f452de3f-31e2-e611-80cc-1402ec7222b4", + "relationshipType": "AttributeSet" + }, + "relationshipAttributes": [ + { + "leftAttributeID": "fe52de3f-31e2-e611-80cc-1402ec7222b4", + "leftConnectingID": { + "identifierType": "FullyQualifiedName" + }, + "rightAttributeID": "b785d645-31e2-e611-80cc-1402ec7222b4", + "rightConnectingID": { + "identifierType": "FullyQualifiedName" + } + } + ], + "relationshipID": "ba85d645-31e2-e611-80cc-1402ec7222b4", + "rightItem": { + "cardinality": "Many", + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "identifier": "b285d645-31e2-e611-80cc-1402ec7222b4", + "relationshipType": "AttributeSet" + } + }, + { + "canModify": false, + "canRemove": false, + "isHidden": false, + "isSystemDefined": false, + "isGroupToSetRelationship": false, + "leftItem": { + "cardinality": "One", + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "identifier": "f452de3f-31e2-e611-80cc-1402ec7222b4", + "relationshipType": "AttributeSet" + }, + "relationshipAttributes": [ + { + "leftAttributeID": "fe52de3f-31e2-e611-80cc-1402ec7222b4", + "leftConnectingID": { + "identifierType": "FullyQualifiedName" + }, + "rightAttributeID": "fa85d645-31e2-e611-80cc-1402ec7222b4", + "rightConnectingID": { + "identifierType": "FullyQualifiedName" + } + } + ], + "relationshipID": "fd85d645-31e2-e611-80cc-1402ec7222b4", + "rightItem": { + "cardinality": "Many", + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "identifier": "ee85d645-31e2-e611-80cc-1402ec7222b4", + "relationshipType": "AttributeSet" + } + } + ], + "valueDefinitions": [ + { + "baseType": "Numeric", + "dataSourceID": 1, + "dataSourceName": {}, + "dataType": "LongNumber", + "description": "", + "localizedDescription": { + "value": "" + }, + "definitionID": "0453de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "CustomObjectKey", + "definitionName": { + "value": "Custom Object Key" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 1, + "fullyQualifiedName": "Predictive Intelligence Profiles.Custom Object Key", + "isHidden": true, + "isIdentityValue": true, + "isNullable": false, + "isPrimaryKey": false, + "isReadOnly": true, + "isSystemDefined": true, + "isUpdateable": false, + "ordinal": 1, + "parentDefinition": { + "definitionID": "f452de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "PredictiveIntelProfiles", + "definitionName": { + "value": "Predictive Intelligence Profiles" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "_CustomObjectKey", + "valueDefinitionID": "0453de3f-31e2-e611-80cc-1402ec7222b4", + "valueDefinitionKey": "CustomObjectKey", + "name": "Custom Object Key", + "setDefinitionID": "f452de3f-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "PredictiveIntelProfiles", + "setDefinitionName": { + "value": "Predictive Intelligence Profiles" + }, + "parentIdentifier": "f452de3f-31e2-e611-80cc-1402ec7222b4" + }, + { + "baseType": "Text", + "dataSourceID": 5, + "dataSourceName": {}, + "dataType": "Text", + "description": "user_id", + "localizedDescription": { + "value": "user_id" + }, + "definitionID": "fe52de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "User_ID", + "definitionName": { + "value": "User ID" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 2, + "fullyQualifiedName": "Predictive Intelligence Profiles.User ID", + "isHidden": false, + "isIdentityValue": false, + "isNullable": false, + "isPrimaryKey": true, + "isReadOnly": true, + "isSystemDefined": true, + "isUpdateable": false, + "length": 256, + "obfuscationProperties": { + "maskType": "None", + "maskTypeID": 0, + "storageTypeID": 1, + "storageType": "Plain", + "valueDefinitionID": "fe52de3f-31e2-e611-80cc-1402ec7222b4" + }, + "ordinal": 2, + "parentDefinition": { + "definitionID": "f452de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "PredictiveIntelProfiles", + "definitionName": { + "value": "Predictive Intelligence Profiles" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "user_id", + "storageFieldReferenceID": { + "type": "guid", + "value": "eceebc11-78ad-421f-a94f-020667aac6d4" + }, + "valueDefinitionID": "fe52de3f-31e2-e611-80cc-1402ec7222b4", + "valueDefinitionKey": "User_ID", + "name": "User ID", + "setDefinitionID": "f452de3f-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "PredictiveIntelProfiles", + "setDefinitionName": { + "value": "Predictive Intelligence Profiles" + }, + "parentIdentifier": "f452de3f-31e2-e611-80cc-1402ec7222b4" + }, + { + "baseType": "Text", + "dataSourceID": 5, + "dataSourceName": {}, + "dataType": "Text", + "description": "email", + "localizedDescription": { + "value": "email" + }, + "definitionID": "fc52de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "Email", + "definitionName": { + "value": "Email" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 3, + "fullyQualifiedName": "Predictive Intelligence Profiles.Email", + "isHidden": false, + "isIdentityValue": false, + "isNullable": true, + "isPrimaryKey": false, + "isReadOnly": true, + "isSystemDefined": true, + "isUpdateable": false, + "length": 256, + "obfuscationProperties": { + "maskType": "None", + "maskTypeID": 0, + "storageTypeID": 1, + "storageType": "Plain", + "valueDefinitionID": "fc52de3f-31e2-e611-80cc-1402ec7222b4" + }, + "ordinal": 3, + "parentDefinition": { + "definitionID": "f452de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "PredictiveIntelProfiles", + "definitionName": { + "value": "Predictive Intelligence Profiles" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "email", + "storageFieldReferenceID": { + "type": "guid", + "value": "71e4d8c6-e3d4-430e-9c9f-7e56b092d36a" + }, + "valueDefinitionID": "fc52de3f-31e2-e611-80cc-1402ec7222b4", + "valueDefinitionKey": "Email", + "name": "Email", + "setDefinitionID": "f452de3f-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "PredictiveIntelProfiles", + "setDefinitionName": { + "value": "Predictive Intelligence Profiles" + }, + "parentIdentifier": "f452de3f-31e2-e611-80cc-1402ec7222b4" + }, + { + "baseType": "Text", + "dataSourceID": 5, + "dataSourceName": {}, + "dataType": "Text", + "description": "Value_1", + "localizedDescription": { + "value": "Value_1" + }, + "definitionID": "ff52de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "Value_1", + "definitionName": { + "value": "Value 1" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 4, + "fullyQualifiedName": "Predictive Intelligence Profiles.Value 1", + "isHidden": false, + "isIdentityValue": false, + "isNullable": true, + "isPrimaryKey": false, + "isReadOnly": true, + "isSystemDefined": true, + "isUpdateable": false, + "length": 256, + "obfuscationProperties": { + "maskType": "None", + "maskTypeID": 0, + "storageTypeID": 1, + "storageType": "Plain", + "valueDefinitionID": "ff52de3f-31e2-e611-80cc-1402ec7222b4" + }, + "ordinal": 4, + "parentDefinition": { + "definitionID": "f452de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "PredictiveIntelProfiles", + "definitionName": { + "value": "Predictive Intelligence Profiles" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "Value_1", + "storageFieldReferenceID": { + "type": "guid", + "value": "8e0573f4-8bc8-4fb3-afc8-ad933a8d823b" + }, + "valueDefinitionID": "ff52de3f-31e2-e611-80cc-1402ec7222b4", + "valueDefinitionKey": "Value_1", + "name": "Value 1", + "setDefinitionID": "f452de3f-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "PredictiveIntelProfiles", + "setDefinitionName": { + "value": "Predictive Intelligence Profiles" + }, + "parentIdentifier": "f452de3f-31e2-e611-80cc-1402ec7222b4" + }, + { + "baseType": "Text", + "dataSourceID": 5, + "dataSourceName": {}, + "dataType": "Text", + "description": "Value_2", + "localizedDescription": { + "value": "Value_2" + }, + "definitionID": "0053de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "Value_2", + "definitionName": { + "value": "Value 2" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 5, + "fullyQualifiedName": "Predictive Intelligence Profiles.Value 2", + "isHidden": false, + "isIdentityValue": false, + "isNullable": true, + "isPrimaryKey": false, + "isReadOnly": true, + "isSystemDefined": true, + "isUpdateable": false, + "length": 256, + "obfuscationProperties": { + "maskType": "None", + "maskTypeID": 0, + "storageTypeID": 1, + "storageType": "Plain", + "valueDefinitionID": "0053de3f-31e2-e611-80cc-1402ec7222b4" + }, + "ordinal": 5, + "parentDefinition": { + "definitionID": "f452de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "PredictiveIntelProfiles", + "definitionName": { + "value": "Predictive Intelligence Profiles" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "Value_2", + "storageFieldReferenceID": { + "type": "guid", + "value": "dcf6690a-4fbe-418c-baa7-e1c50443560b" + }, + "valueDefinitionID": "0053de3f-31e2-e611-80cc-1402ec7222b4", + "valueDefinitionKey": "Value_2", + "name": "Value 2", + "setDefinitionID": "f452de3f-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "PredictiveIntelProfiles", + "setDefinitionName": { + "value": "Predictive Intelligence Profiles" + }, + "parentIdentifier": "f452de3f-31e2-e611-80cc-1402ec7222b4" + }, + { + "baseType": "Text", + "dataSourceID": 5, + "dataSourceName": {}, + "dataType": "Text", + "description": "Value_3", + "localizedDescription": { + "value": "Value_3" + }, + "definitionID": "0153de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "Value_3", + "definitionName": { + "value": "Value 3" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 6, + "fullyQualifiedName": "Predictive Intelligence Profiles.Value 3", + "isHidden": false, + "isIdentityValue": false, + "isNullable": true, + "isPrimaryKey": false, + "isReadOnly": true, + "isSystemDefined": true, + "isUpdateable": false, + "length": 256, + "obfuscationProperties": { + "maskType": "None", + "maskTypeID": 0, + "storageTypeID": 1, + "storageType": "Plain", + "valueDefinitionID": "0153de3f-31e2-e611-80cc-1402ec7222b4" + }, + "ordinal": 6, + "parentDefinition": { + "definitionID": "f452de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "PredictiveIntelProfiles", + "definitionName": { + "value": "Predictive Intelligence Profiles" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "Value_3", + "storageFieldReferenceID": { + "type": "guid", + "value": "b2a7de94-c985-4337-afcc-445aa80c2ced" + }, + "valueDefinitionID": "0153de3f-31e2-e611-80cc-1402ec7222b4", + "valueDefinitionKey": "Value_3", + "name": "Value 3", + "setDefinitionID": "f452de3f-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "PredictiveIntelProfiles", + "setDefinitionName": { + "value": "Predictive Intelligence Profiles" + }, + "parentIdentifier": "f452de3f-31e2-e611-80cc-1402ec7222b4" + }, + { + "baseType": "Text", + "dataSourceID": 5, + "dataSourceName": {}, + "dataType": "Text", + "description": "Value_4", + "localizedDescription": { + "value": "Value_4" + }, + "definitionID": "0253de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "Value_4", + "definitionName": { + "value": "Value 4" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 7, + "fullyQualifiedName": "Predictive Intelligence Profiles.Value 4", + "isHidden": false, + "isIdentityValue": false, + "isNullable": true, + "isPrimaryKey": false, + "isReadOnly": true, + "isSystemDefined": true, + "isUpdateable": false, + "length": 256, + "obfuscationProperties": { + "maskType": "None", + "maskTypeID": 0, + "storageTypeID": 1, + "storageType": "Plain", + "valueDefinitionID": "0253de3f-31e2-e611-80cc-1402ec7222b4" + }, + "ordinal": 7, + "parentDefinition": { + "definitionID": "f452de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "PredictiveIntelProfiles", + "definitionName": { + "value": "Predictive Intelligence Profiles" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "Value_4", + "storageFieldReferenceID": { + "type": "guid", + "value": "28984526-60dc-4768-aaff-4018d9842e77" + }, + "valueDefinitionID": "0253de3f-31e2-e611-80cc-1402ec7222b4", + "valueDefinitionKey": "Value_4", + "name": "Value 4", + "setDefinitionID": "f452de3f-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "PredictiveIntelProfiles", + "setDefinitionName": { + "value": "Predictive Intelligence Profiles" + }, + "parentIdentifier": "f452de3f-31e2-e611-80cc-1402ec7222b4" + }, + { + "baseType": "Text", + "dataSourceID": 5, + "dataSourceName": {}, + "dataType": "Text", + "description": "Value_5", + "localizedDescription": { + "value": "Value_5" + }, + "definitionID": "0353de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "Value_5", + "definitionName": { + "value": "Value 5" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 8, + "fullyQualifiedName": "Predictive Intelligence Profiles.Value 5", + "isHidden": false, + "isIdentityValue": false, + "isNullable": true, + "isPrimaryKey": false, + "isReadOnly": true, + "isSystemDefined": true, + "isUpdateable": false, + "length": 256, + "obfuscationProperties": { + "maskType": "None", + "maskTypeID": 0, + "storageTypeID": 1, + "storageType": "Plain", + "valueDefinitionID": "0353de3f-31e2-e611-80cc-1402ec7222b4" + }, + "ordinal": 8, + "parentDefinition": { + "definitionID": "f452de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "PredictiveIntelProfiles", + "definitionName": { + "value": "Predictive Intelligence Profiles" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "Value_5", + "storageFieldReferenceID": { + "type": "guid", + "value": "aa50e6f3-6863-41fa-a536-8ed1d0fca989" + }, + "valueDefinitionID": "0353de3f-31e2-e611-80cc-1402ec7222b4", + "valueDefinitionKey": "Value_5", + "name": "Value 5", + "setDefinitionID": "f452de3f-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "PredictiveIntelProfiles", + "setDefinitionName": { + "value": "Predictive Intelligence Profiles" + }, + "parentIdentifier": "f452de3f-31e2-e611-80cc-1402ec7222b4" + }, + { + "baseType": "Text", + "dataSourceID": 5, + "dataSourceName": {}, + "dataType": "Text", + "description": "Attribute_1", + "localizedDescription": { + "value": "Attribute_1" + }, + "definitionID": "f552de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "Attribute_1", + "definitionName": { + "value": "Attribute 1" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 9, + "fullyQualifiedName": "Predictive Intelligence Profiles.Attribute 1", + "isHidden": false, + "isIdentityValue": false, + "isNullable": true, + "isPrimaryKey": false, + "isReadOnly": true, + "isSystemDefined": true, + "isUpdateable": false, + "length": 256, + "obfuscationProperties": { + "maskType": "None", + "maskTypeID": 0, + "storageTypeID": 1, + "storageType": "Plain", + "valueDefinitionID": "f552de3f-31e2-e611-80cc-1402ec7222b4" + }, + "ordinal": 9, + "parentDefinition": { + "definitionID": "f452de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "PredictiveIntelProfiles", + "definitionName": { + "value": "Predictive Intelligence Profiles" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "Attribute_1", + "storageFieldReferenceID": { + "type": "guid", + "value": "16934a3e-d869-4b8c-b817-48ff5b554f30" + }, + "valueDefinitionID": "f552de3f-31e2-e611-80cc-1402ec7222b4", + "valueDefinitionKey": "Attribute_1", + "name": "Attribute 1", + "setDefinitionID": "f452de3f-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "PredictiveIntelProfiles", + "setDefinitionName": { + "value": "Predictive Intelligence Profiles" + }, + "parentIdentifier": "f452de3f-31e2-e611-80cc-1402ec7222b4" + }, + { + "baseType": "Text", + "dataSourceID": 5, + "dataSourceName": {}, + "dataType": "Text", + "description": "Attribute_2", + "localizedDescription": { + "value": "Attribute_2" + }, + "definitionID": "f652de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "Attribute_2", + "definitionName": { + "value": "Attribute 2" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 10, + "fullyQualifiedName": "Predictive Intelligence Profiles.Attribute 2", + "isHidden": false, + "isIdentityValue": false, + "isNullable": true, + "isPrimaryKey": false, + "isReadOnly": true, + "isSystemDefined": true, + "isUpdateable": false, + "length": 256, + "obfuscationProperties": { + "maskType": "None", + "maskTypeID": 0, + "storageTypeID": 1, + "storageType": "Plain", + "valueDefinitionID": "f652de3f-31e2-e611-80cc-1402ec7222b4" + }, + "ordinal": 10, + "parentDefinition": { + "definitionID": "f452de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "PredictiveIntelProfiles", + "definitionName": { + "value": "Predictive Intelligence Profiles" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "Attribute_2", + "storageFieldReferenceID": { + "type": "guid", + "value": "121ce628-61aa-4344-91b1-7f27413a16e5" + }, + "valueDefinitionID": "f652de3f-31e2-e611-80cc-1402ec7222b4", + "valueDefinitionKey": "Attribute_2", + "name": "Attribute 2", + "setDefinitionID": "f452de3f-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "PredictiveIntelProfiles", + "setDefinitionName": { + "value": "Predictive Intelligence Profiles" + }, + "parentIdentifier": "f452de3f-31e2-e611-80cc-1402ec7222b4" + }, + { + "baseType": "Text", + "dataSourceID": 5, + "dataSourceName": {}, + "dataType": "Text", + "description": "Attribute_3", + "localizedDescription": { + "value": "Attribute_3" + }, + "definitionID": "f752de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "Attribute_3", + "definitionName": { + "value": "Attribute 3" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 11, + "fullyQualifiedName": "Predictive Intelligence Profiles.Attribute 3", + "isHidden": false, + "isIdentityValue": false, + "isNullable": true, + "isPrimaryKey": false, + "isReadOnly": true, + "isSystemDefined": true, + "isUpdateable": false, + "length": 256, + "obfuscationProperties": { + "maskType": "None", + "maskTypeID": 0, + "storageTypeID": 1, + "storageType": "Plain", + "valueDefinitionID": "f752de3f-31e2-e611-80cc-1402ec7222b4" + }, + "ordinal": 11, + "parentDefinition": { + "definitionID": "f452de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "PredictiveIntelProfiles", + "definitionName": { + "value": "Predictive Intelligence Profiles" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "Attribute_3", + "storageFieldReferenceID": { + "type": "guid", + "value": "34e53678-e867-4526-9fd6-d31e2771a003" + }, + "valueDefinitionID": "f752de3f-31e2-e611-80cc-1402ec7222b4", + "valueDefinitionKey": "Attribute_3", + "name": "Attribute 3", + "setDefinitionID": "f452de3f-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "PredictiveIntelProfiles", + "setDefinitionName": { + "value": "Predictive Intelligence Profiles" + }, + "parentIdentifier": "f452de3f-31e2-e611-80cc-1402ec7222b4" + }, + { + "baseType": "Text", + "dataSourceID": 5, + "dataSourceName": {}, + "dataType": "Text", + "description": "Attribute_4", + "localizedDescription": { + "value": "Attribute_4" + }, + "definitionID": "f852de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "Attribute_4", + "definitionName": { + "value": "Attribute 4" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 12, + "fullyQualifiedName": "Predictive Intelligence Profiles.Attribute 4", + "isHidden": false, + "isIdentityValue": false, + "isNullable": true, + "isPrimaryKey": false, + "isReadOnly": true, + "isSystemDefined": true, + "isUpdateable": false, + "length": 256, + "obfuscationProperties": { + "maskType": "None", + "maskTypeID": 0, + "storageTypeID": 1, + "storageType": "Plain", + "valueDefinitionID": "f852de3f-31e2-e611-80cc-1402ec7222b4" + }, + "ordinal": 12, + "parentDefinition": { + "definitionID": "f452de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "PredictiveIntelProfiles", + "definitionName": { + "value": "Predictive Intelligence Profiles" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "Attribute_4", + "storageFieldReferenceID": { + "type": "guid", + "value": "b3efb625-de9a-4eef-b6eb-6add451d2f7a" + }, + "valueDefinitionID": "f852de3f-31e2-e611-80cc-1402ec7222b4", + "valueDefinitionKey": "Attribute_4", + "name": "Attribute 4", + "setDefinitionID": "f452de3f-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "PredictiveIntelProfiles", + "setDefinitionName": { + "value": "Predictive Intelligence Profiles" + }, + "parentIdentifier": "f452de3f-31e2-e611-80cc-1402ec7222b4" + }, + { + "baseType": "Text", + "dataSourceID": 5, + "dataSourceName": {}, + "dataType": "Text", + "description": "Attribute_5", + "localizedDescription": { + "value": "Attribute_5" + }, + "definitionID": "f952de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "Attribute_5", + "definitionName": { + "value": "Attribute 5" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 13, + "fullyQualifiedName": "Predictive Intelligence Profiles.Attribute 5", + "isHidden": false, + "isIdentityValue": false, + "isNullable": true, + "isPrimaryKey": false, + "isReadOnly": true, + "isSystemDefined": true, + "isUpdateable": false, + "length": 256, + "obfuscationProperties": { + "maskType": "None", + "maskTypeID": 0, + "storageTypeID": 1, + "storageType": "Plain", + "valueDefinitionID": "f952de3f-31e2-e611-80cc-1402ec7222b4" + }, + "ordinal": 13, + "parentDefinition": { + "definitionID": "f452de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "PredictiveIntelProfiles", + "definitionName": { + "value": "Predictive Intelligence Profiles" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "Attribute_5", + "storageFieldReferenceID": { + "type": "guid", + "value": "f4836380-72eb-49c2-a8af-5a283d168683" + }, + "valueDefinitionID": "f952de3f-31e2-e611-80cc-1402ec7222b4", + "valueDefinitionKey": "Attribute_5", + "name": "Attribute 5", + "setDefinitionID": "f452de3f-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "PredictiveIntelProfiles", + "setDefinitionName": { + "value": "Predictive Intelligence Profiles" + }, + "parentIdentifier": "f452de3f-31e2-e611-80cc-1402ec7222b4" + }, + { + "baseType": "Text", + "dataSourceID": 5, + "dataSourceName": {}, + "dataType": "Text", + "description": "city", + "localizedDescription": { + "value": "city" + }, + "definitionID": "fa52de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "City", + "definitionName": { + "value": "City" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 14, + "fullyQualifiedName": "Predictive Intelligence Profiles.City", + "isHidden": false, + "isIdentityValue": false, + "isNullable": true, + "isPrimaryKey": false, + "isReadOnly": true, + "isSystemDefined": true, + "isUpdateable": false, + "length": 256, + "obfuscationProperties": { + "maskType": "None", + "maskTypeID": 0, + "storageTypeID": 1, + "storageType": "Plain", + "valueDefinitionID": "fa52de3f-31e2-e611-80cc-1402ec7222b4" + }, + "ordinal": 14, + "parentDefinition": { + "definitionID": "f452de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "PredictiveIntelProfiles", + "definitionName": { + "value": "Predictive Intelligence Profiles" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "city", + "storageFieldReferenceID": { + "type": "guid", + "value": "486ae151-74f7-4b98-ba9b-6ad927399de9" + }, + "valueDefinitionID": "fa52de3f-31e2-e611-80cc-1402ec7222b4", + "valueDefinitionKey": "City", + "name": "City", + "setDefinitionID": "f452de3f-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "PredictiveIntelProfiles", + "setDefinitionName": { + "value": "Predictive Intelligence Profiles" + }, + "parentIdentifier": "f452de3f-31e2-e611-80cc-1402ec7222b4" + }, + { + "baseType": "Text", + "dataSourceID": 5, + "dataSourceName": {}, + "dataType": "Text", + "description": "region", + "localizedDescription": { + "value": "region" + }, + "definitionID": "fd52de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "Region", + "definitionName": { + "value": "Region" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 15, + "fullyQualifiedName": "Predictive Intelligence Profiles.Region", + "isHidden": false, + "isIdentityValue": false, + "isNullable": true, + "isPrimaryKey": false, + "isReadOnly": true, + "isSystemDefined": true, + "isUpdateable": false, + "length": 256, + "obfuscationProperties": { + "maskType": "None", + "maskTypeID": 0, + "storageTypeID": 1, + "storageType": "Plain", + "valueDefinitionID": "fd52de3f-31e2-e611-80cc-1402ec7222b4" + }, + "ordinal": 15, + "parentDefinition": { + "definitionID": "f452de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "PredictiveIntelProfiles", + "definitionName": { + "value": "Predictive Intelligence Profiles" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "region", + "storageFieldReferenceID": { + "type": "guid", + "value": "4b8bb8f1-0bcb-4201-9c26-fdd8e10c7ad8" + }, + "valueDefinitionID": "fd52de3f-31e2-e611-80cc-1402ec7222b4", + "valueDefinitionKey": "Region", + "name": "Region", + "setDefinitionID": "f452de3f-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "PredictiveIntelProfiles", + "setDefinitionName": { + "value": "Predictive Intelligence Profiles" + }, + "parentIdentifier": "f452de3f-31e2-e611-80cc-1402ec7222b4" + }, + { + "baseType": "Text", + "dataSourceID": 5, + "dataSourceName": {}, + "dataType": "Text", + "description": "country", + "localizedDescription": { + "value": "country" + }, + "definitionID": "fb52de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "Country", + "definitionName": { + "value": "Country" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 16, + "fullyQualifiedName": "Predictive Intelligence Profiles.Country", + "isHidden": false, + "isIdentityValue": false, + "isNullable": true, + "isPrimaryKey": false, + "isReadOnly": true, + "isSystemDefined": true, + "isUpdateable": false, + "length": 256, + "obfuscationProperties": { + "maskType": "None", + "maskTypeID": 0, + "storageTypeID": 1, + "storageType": "Plain", + "valueDefinitionID": "fb52de3f-31e2-e611-80cc-1402ec7222b4" + }, + "ordinal": 16, + "parentDefinition": { + "definitionID": "f452de3f-31e2-e611-80cc-1402ec7222b4", + "definitionKey": "PredictiveIntelProfiles", + "definitionName": { + "value": "Predictive Intelligence Profiles" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "country", + "storageFieldReferenceID": { + "type": "guid", + "value": "f9e65e6a-45dc-4f08-9a44-715e6e4763f7" + }, + "valueDefinitionID": "fb52de3f-31e2-e611-80cc-1402ec7222b4", + "valueDefinitionKey": "Country", + "name": "Country", + "setDefinitionID": "f452de3f-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "PredictiveIntelProfiles", + "setDefinitionName": { + "value": "Predictive Intelligence Profiles" + }, + "parentIdentifier": "f452de3f-31e2-e611-80cc-1402ec7222b4" + } + ], + "applicationID": "f4981f88-a13e-4abf-b331-47f41c73258d", + "applicationKey": "com.exacttarget.Predictive Web", + "attributeCount": 0, + "canAddValues": false, + "canChangeValues": false, + "canModify": false, + "canRemove": false, + "categoryID": 386, + "createdBy": -1000, + "createDate": "2017-01-24T06:33:00", + "customObjectOwnerMID": 1111111, + "dataRetentionProperties": { + "isRowBasedRetention": false, + "isResetRetentionPeriodOnImport": false, + "isDeleteAtEndOfRetentionPeriod": false, + "periodUnitOfMeasure": 4, + "setDefinitionID": "f452de3f-31e2-e611-80cc-1402ec7222b4" + }, + "localizedDescription": {}, + "fullyQualifiedName": "Predictive Intelligence Profiles", + "isCustomObjectBacked": true, + "isEvent": false, + "isHidden": false, + "isReadOnly": true, + "isRoot": false, + "isSendable": false, + "isShared": false, + "isSystemDefined": true, + "isTestaable": false, + "parentID": "00000000-0000-0000-0000-000000000000", + "relationshipCount": 5, + "storageLogicalType": "DataExtension", + "storageName": "IGO_PROFILES", + "storageObjectIDs": ["e352de3f-31e2-e611-80cc-1402ec7222b4"], + "storageReferenceID": { + "type": "guid", + "value": "d452de3f-31e2-e611-80cc-1402ec7222b4" + }, + "setDefinitionID": "f452de3f-31e2-e611-80cc-1402ec7222b4", + "setDefinitionKey": "PredictiveIntelProfiles", + "name": "Predictive Intelligence Profiles" + }, + { + "definitionID": "528b787a-5238-ee11-b85a-48df37d1de8a", + "definitionKey": "testExisting_dataExtensionShared", + "definitionName": { + "value": "testExisting_dataExtensionShared" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "relationships": [ + { + "canModify": true, + "canRemove": true, + "isHidden": false, + "isSystemDefined": false, + "isGroupToSetRelationship": true, + "leftItem": { + "cardinality": "One", + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "identifier": "79846c6e-5238-ee11-b85a-48df37d1de8a", + "relationshipType": "AttributeGroup" + }, + "leftRelationshipIDs": [ + { + "type": "int16", + "value": "3" + } + ], + "leftRelationshipReferenceType": "CustomerData", + "relationshipAttributes": [ + { + "leftAttributeID": "9393dc39-31e2-e611-80cc-1402ec7222b4", + "leftConnectingID": { + "identifierType": "FullyQualifiedName" + }, + "rightAttributeID": "558b787a-5238-ee11-b85a-48df37d1de8a", + "rightConnectingID": { + "identifierType": "FullyQualifiedName" + } + } + ], + "relationshipID": "598b787a-5238-ee11-b85a-48df37d1de8a", + "rightItem": { + "cardinality": "One", + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "identifier": "528b787a-5238-ee11-b85a-48df37d1de8a", + "relationshipType": "AttributeSet" + } + } + ], + "valueDefinitions": [ + { + "baseType": "Numeric", + "dataSourceName": {}, + "dataType": "LongNumber", + "description": "", + "localizedDescription": { + "value": "" + }, + "definitionID": "548b787a-5238-ee11-b85a-48df37d1de8a", + "definitionKey": "CustomObjectKey", + "definitionName": { + "value": "Custom Object Key" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "fullyQualifiedName": "testExisting_dataExtensionShared.Custom Object Key", + "isHidden": true, + "isIdentityValue": true, + "isNullable": false, + "isPrimaryKey": false, + "isReadOnly": true, + "isSystemDefined": true, + "isUpdateable": true, + "parentDefinition": { + "definitionID": "528b787a-5238-ee11-b85a-48df37d1de8a", + "definitionKey": "testExisting_dataExtensionShared", + "definitionName": { + "value": "testExisting_dataExtensionShared" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "_CustomObjectKey", + "valueDefinitionID": "548b787a-5238-ee11-b85a-48df37d1de8a", + "valueDefinitionKey": "CustomObjectKey", + "name": "Custom Object Key", + "setDefinitionID": "528b787a-5238-ee11-b85a-48df37d1de8a", + "setDefinitionKey": "testExisting_dataExtensionShared", + "setDefinitionName": { + "value": "testExisting_dataExtensionShared" + }, + "parentIdentifier": "528b787a-5238-ee11-b85a-48df37d1de8a" + }, + { + "baseType": "Text", + "dataSourceName": {}, + "dataType": "Text", + "description": "", + "localizedDescription": { + "value": "" + }, + "definitionID": "588b787a-5238-ee11-b85a-48df37d1de8a", + "definitionKey": "FirstName", + "definitionName": { + "value": "FirstName" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 0, + "fullyQualifiedName": "testExisting_dataExtensionShared.FirstName", + "isHidden": false, + "isIdentityValue": false, + "isNullable": true, + "isPrimaryKey": false, + "isReadOnly": false, + "isSystemDefined": false, + "isUpdateable": true, + "length": 50, + "obfuscationProperties": { + "maskType": "None", + "maskTypeID": 0, + "storageTypeID": 1, + "storageType": "Plain", + "valueDefinitionID": "588b787a-5238-ee11-b85a-48df37d1de8a" + }, + "ordinal": 0, + "parentDefinition": { + "definitionID": "528b787a-5238-ee11-b85a-48df37d1de8a", + "definitionKey": "testExisting_dataExtensionShared", + "definitionName": { + "value": "testExisting_dataExtensionShared" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "FirstName", + "storageFieldReferenceID": { + "type": "guid", + "value": "391bfc9e-ea85-4610-a24b-d8400a36cdfc" + }, + "valueDefinitionID": "588b787a-5238-ee11-b85a-48df37d1de8a", + "valueDefinitionKey": "FirstName", + "name": "FirstName", + "setDefinitionID": "528b787a-5238-ee11-b85a-48df37d1de8a", + "setDefinitionKey": "testExisting_dataExtensionShared", + "setDefinitionName": { + "value": "testExisting_dataExtensionShared" + }, + "parentIdentifier": "528b787a-5238-ee11-b85a-48df37d1de8a" + }, + { + "baseType": "Text", + "dataSourceName": {}, + "dataType": "Text", + "description": "", + "localizedDescription": { + "value": "" + }, + "definitionID": "578b787a-5238-ee11-b85a-48df37d1de8a", + "definitionKey": "LastName", + "definitionName": { + "value": "LastName" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 1, + "fullyQualifiedName": "testExisting_dataExtensionShared.LastName", + "isHidden": false, + "isIdentityValue": false, + "isNullable": true, + "isPrimaryKey": false, + "isReadOnly": false, + "isSystemDefined": false, + "isUpdateable": true, + "length": 55, + "obfuscationProperties": { + "maskType": "None", + "maskTypeID": 0, + "storageTypeID": 1, + "storageType": "Plain", + "valueDefinitionID": "578b787a-5238-ee11-b85a-48df37d1de8a" + }, + "ordinal": 1, + "parentDefinition": { + "definitionID": "528b787a-5238-ee11-b85a-48df37d1de8a", + "definitionKey": "testExisting_dataExtensionShared", + "definitionName": { + "value": "testExisting_dataExtensionShared" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "LastName", + "storageFieldReferenceID": { + "type": "guid", + "value": "3f80ba1f-f957-400f-88cb-a9303491026d" + }, + "valueDefinitionID": "578b787a-5238-ee11-b85a-48df37d1de8a", + "valueDefinitionKey": "LastName", + "name": "LastName", + "setDefinitionID": "528b787a-5238-ee11-b85a-48df37d1de8a", + "setDefinitionKey": "testExisting_dataExtensionShared", + "setDefinitionName": { + "value": "testExisting_dataExtensionShared" + }, + "parentIdentifier": "528b787a-5238-ee11-b85a-48df37d1de8a" + }, + { + "baseType": "Text", + "dataSourceName": {}, + "dataType": "EmailAddress", + "description": "", + "localizedDescription": { + "value": "" + }, + "definitionID": "568b787a-5238-ee11-b85a-48df37d1de8a", + "definitionKey": "EmailAddress", + "definitionName": { + "value": "EmailAddress" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 2, + "fullyQualifiedName": "testExisting_dataExtensionShared.EmailAddress", + "isHidden": false, + "isIdentityValue": false, + "isNullable": false, + "isPrimaryKey": false, + "isReadOnly": false, + "isSystemDefined": false, + "isUpdateable": true, + "length": 254, + "obfuscationProperties": { + "maskType": "None", + "maskTypeID": 0, + "storageTypeID": 1, + "storageType": "Plain", + "valueDefinitionID": "568b787a-5238-ee11-b85a-48df37d1de8a" + }, + "ordinal": 2, + "parentDefinition": { + "definitionID": "528b787a-5238-ee11-b85a-48df37d1de8a", + "definitionKey": "testExisting_dataExtensionShared", + "definitionName": { + "value": "testExisting_dataExtensionShared" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "EmailAddress", + "storageFieldReferenceID": { + "type": "guid", + "value": "41b9575b-da06-41ed-8551-f76868451a51" + }, + "valueDefinitionID": "568b787a-5238-ee11-b85a-48df37d1de8a", + "valueDefinitionKey": "EmailAddress", + "name": "EmailAddress", + "setDefinitionID": "528b787a-5238-ee11-b85a-48df37d1de8a", + "setDefinitionKey": "testExisting_dataExtensionShared", + "setDefinitionName": { + "value": "testExisting_dataExtensionShared" + }, + "parentIdentifier": "528b787a-5238-ee11-b85a-48df37d1de8a" + }, + { + "baseType": "Text", + "dataSourceName": {}, + "dataType": "Text", + "description": "", + "localizedDescription": { + "value": "" + }, + "definitionID": "558b787a-5238-ee11-b85a-48df37d1de8a", + "definitionKey": "ContactKey", + "definitionName": { + "value": "ContactKey" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + }, + "displayOrder": 4, + "fullyQualifiedName": "testExisting_dataExtensionShared.ContactKey", + "isHidden": false, + "isIdentityValue": false, + "isNullable": false, + "isPrimaryKey": true, + "isReadOnly": false, + "isSystemDefined": false, + "isUpdateable": true, + "length": 50, + "obfuscationProperties": { + "maskType": "None", + "maskTypeID": 0, + "storageTypeID": 1, + "storageType": "Plain", + "valueDefinitionID": "558b787a-5238-ee11-b85a-48df37d1de8a" + }, + "ordinal": 4, + "parentDefinition": { + "definitionID": "528b787a-5238-ee11-b85a-48df37d1de8a", + "definitionKey": "testExisting_dataExtensionShared", + "definitionName": { + "value": "testExisting_dataExtensionShared" + }, + "connectingID": { + "identifierType": "FullyQualifiedName" + } + }, + "parentType": "Set", + "storageName": "ContactKey", + "storageFieldReferenceID": { + "type": "guid", + "value": "49d0db37-dff0-49d9-9d82-eb29b345f238" + }, + "valueDefinitionID": "558b787a-5238-ee11-b85a-48df37d1de8a", + "valueDefinitionKey": "ContactKey", + "name": "ContactKey", + "setDefinitionID": "528b787a-5238-ee11-b85a-48df37d1de8a", + "setDefinitionKey": "testExisting_dataExtensionShared", + "setDefinitionName": { + "value": "testExisting_dataExtensionShared" + }, + "parentIdentifier": "528b787a-5238-ee11-b85a-48df37d1de8a" + } + ], + "attributeCount": 0, + "canAddValues": true, + "canChangeValues": true, + "canModify": true, + "canRemove": true, + "categoryID": 89356, + "createdBy": 700301950, + "createDate": "2023-08-11T08:22:00", + "customObjectOwnerMID": 7281698, + "dataRetentionProperties": { + "isRowBasedRetention": true, + "isResetRetentionPeriodOnImport": false, + "isDeleteAtEndOfRetentionPeriod": false, + "periodLength": 6, + "periodUnitOfMeasure": 5, + "setDefinitionID": "528b787a-5238-ee11-b85a-48df37d1de8a" + }, + "localizedDescription": { + "value": "Container for my test emails" + }, + "fullyQualifiedName": "testExisting_dataExtensionShared", + "isCustomObjectBacked": true, + "isEvent": false, + "isHidden": false, + "isReadOnly": false, + "isRoot": false, + "isSendable": true, + "isShared": true, + "isSystemDefined": false, + "isTestaable": true, + "parentID": "00000000-0000-0000-0000-000000000000", + "relationshipCount": 1, + "sendAttributeStorageName": "ContactKey", + "sendContactKeyStorageName": "_SubscriberKey", + "storageLogicalType": "DataExtension", + "storageName": "testExisting_dataExtensionShared", + "storageObjectIDs": ["5b8b787a-5238-ee11-b85a-48df37d1de8a"], + "storageReferenceID": { + "type": "guid", + "value": "21711373-72c1-ec11-b83b-shared" + }, + "setDefinitionID": "528b787a-5238-ee11-b85a-48df37d1de8a", + "setDefinitionKey": "testExisting_dataExtensionShared", + "name": "testExisting_dataExtensionShared" + } + ], + "responseContext": { + "operationStatus": "OK", + "schemaType": "Contacts", + "populateInternalProperties": false + }, + "requestServiceMessageID": "ae488366-fa20-449a-ba74-ee353a7ab446", + "responseDateTime": "2023-07-12T09:17:32.1332068-06:00", + "resultMessages": [], + "serviceMessageID": "3206d5b6-f603-4049-bce8-6afce627a7c6" +} diff --git a/test/resources/9999999/importDefinition/retrieve-CustomerKey=testExisting_importFile-response.xml b/test/resources/9999999/importDefinition/retrieve-CustomerKey=testExisting_importFile-response.xml new file mode 100644 index 000000000..0af2d2588 --- /dev/null +++ b/test/resources/9999999/importDefinition/retrieve-CustomerKey=testExisting_importFile-response.xml @@ -0,0 +1,30 @@ +<?xml version="1.0" encoding="utf-8"?> +<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:xsd="http://www.w3.org/2001/XMLSchema" + xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing" + xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" + xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"> + <soap:Header> + <wsa:Action>RetrieveResponse</wsa:Action> + <wsa:MessageID>urn:uuid:58a4181c-9ea7-4d26-835b-f1eb50877b0b</wsa:MessageID> + <wsa:RelatesTo>urn:uuid:dab39bb4-2262-453a-9cb1-c591db9222d9</wsa:RelatesTo> + <wsa:To>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</wsa:To> + <wsse:Security> + <wsu:Timestamp wsu:Id="Timestamp-b8a68a2b-ad18-4ac0-8cea-dabe7d7d55c9"> + <wsu:Created>2024-01-25T21:59:01Z</wsu:Created> + <wsu:Expires>2024-01-25T22:04:01Z</wsu:Expires> + </wsu:Timestamp> + </wsse:Security> + </soap:Header> + <soap:Body> + <RetrieveResponseMsg xmlns="http://exacttarget.com/wsdl/partnerAPI"> + <OverallStatus>OK</OverallStatus> + <RequestID>fdc476c9-46dc-43f5-b8a6-57f2299c65ac</RequestID> + <Results xsi:type="ImportDefinition"> + <PartnerKey xsi:nil="true" /> + <ObjectID>9d16f42c-2260-ed11-b849-48df37d1de8b</ObjectID> + </Results> + </RetrieveResponseMsg> + </soap:Body> +</soap:Envelope> diff --git a/test/resources/9999999/importDefinition/retrieve-Name=testExisting_importFile-response.xml b/test/resources/9999999/importDefinition/retrieve-Name=testExisting_importFile-response.xml new file mode 100644 index 000000000..0af2d2588 --- /dev/null +++ b/test/resources/9999999/importDefinition/retrieve-Name=testExisting_importFile-response.xml @@ -0,0 +1,30 @@ +<?xml version="1.0" encoding="utf-8"?> +<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:xsd="http://www.w3.org/2001/XMLSchema" + xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing" + xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" + xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"> + <soap:Header> + <wsa:Action>RetrieveResponse</wsa:Action> + <wsa:MessageID>urn:uuid:58a4181c-9ea7-4d26-835b-f1eb50877b0b</wsa:MessageID> + <wsa:RelatesTo>urn:uuid:dab39bb4-2262-453a-9cb1-c591db9222d9</wsa:RelatesTo> + <wsa:To>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</wsa:To> + <wsse:Security> + <wsu:Timestamp wsu:Id="Timestamp-b8a68a2b-ad18-4ac0-8cea-dabe7d7d55c9"> + <wsu:Created>2024-01-25T21:59:01Z</wsu:Created> + <wsu:Expires>2024-01-25T22:04:01Z</wsu:Expires> + </wsu:Timestamp> + </wsse:Security> + </soap:Header> + <soap:Body> + <RetrieveResponseMsg xmlns="http://exacttarget.com/wsdl/partnerAPI"> + <OverallStatus>OK</OverallStatus> + <RequestID>fdc476c9-46dc-43f5-b8a6-57f2299c65ac</RequestID> + <Results xsi:type="ImportDefinition"> + <PartnerKey xsi:nil="true" /> + <ObjectID>9d16f42c-2260-ed11-b849-48df37d1de8b</ObjectID> + </Results> + </RetrieveResponseMsg> + </soap:Body> +</soap:Envelope> diff --git a/test/resources/9999999/importFile/build-expected.json b/test/resources/9999999/importFile/build-expected.json new file mode 100644 index 000000000..0c61c5e77 --- /dev/null +++ b/test/resources/9999999/importFile/build-expected.json @@ -0,0 +1,30 @@ +{ + "allowErrors": true, + "c__blankFileProcessing": "Skip", + "c__dataAction": "AddUpdate", + "c__subscriberImportType": "DataExtension", + "customerKey": "testTemplated_importFile", + "dateFormatLocale": "en-US", + "deleteFile": false, + "description": "17.11.2022", + "encodingName": "utf-8", + "fieldMappings": [], + "fieldMappingType": "InferFromColumnHeadings", + "fileNamingPattern": "blabla", + "fileType": "CSV", + "filter": "", + "hasColumnHeader": true, + "isOrderedImport": true, + "isSequential": true, + "maxFileAgeHours": 0, + "maxFileAgeScheduleOffsetHours": 0, + "maxImportFrequencyHours": 0, + "name": "testTemplated_importFile", + "sendEmailNotification": false, + "standardQuotedStrings": true, + "destination": { + "c__type": "DataExtension", + "r__dataExtension_key": "testTemplated_dataExtension" + }, + "source": { "c__type": "File Location", "r__fileLocation_name": "ExactTarget Enhanced FTP" } +} diff --git a/test/resources/9999999/importFile/get-dataImport-expected.json b/test/resources/9999999/importFile/get-dataImport-expected.json new file mode 100644 index 000000000..a21604b34 --- /dev/null +++ b/test/resources/9999999/importFile/get-dataImport-expected.json @@ -0,0 +1,36 @@ +{ + "allowErrors": true, + "customerKey": "testExisting_importFileDataImport", + "createdDate": "2024-07-24T04:10:42.15", + "modifiedDate": "2024-07-24T04:10:42.15", + "dateFormatLocale": "en-US", + "deleteFile": false, + "fieldMappings": [], + "fieldMappingType": "InferFromColumnHeadings", + "fileNamingPattern": "_CustomObject", + "fileSpec": "_CustomObject", + "fileType": "CSV", + "filter": "", + "hasColumnHeader": true, + "isOrderedImport": true, + "isSequential": true, + "maxFileAgeHours": 0, + "maxImportFrequencyHours": 0, + "maxFileAgeScheduleOffsetHours": 0, + "name": "testExisting_importFileDataImport", + "sendEmailNotification": false, + "standardQuotedStrings": true, + "encodingName": "utf-8", + "c__blankFileProcessing": "Fail", + "destination": { + "c__type": "DataExtension", + "r__dataExtension_key": "testExisting_journey_Quicksend" + }, + "source": { + "c__type": "DataExtension", + "r__fileLocation_name": "ExactTarget Enhanced FTP", + "r__dataExtension_key": "testExisting_dataExtension" + }, + "c__subscriberImportType": "DataExtension", + "c__dataAction": "Overwrite" +} diff --git a/test/resources/9999999/importFile/get-expected.json b/test/resources/9999999/importFile/get-expected.json new file mode 100644 index 000000000..bf17929d0 --- /dev/null +++ b/test/resources/9999999/importFile/get-expected.json @@ -0,0 +1,36 @@ +{ + "allowErrors": true, + "c__blankFileProcessing": "Skip", + "c__dataAction": "AddUpdate", + "c__subscriberImportType": "DataExtension", + "createdDate": "2022-11-09T05:32:30.533", + "customerKey": "testExisting_importFile", + "dateFormatLocale": "en-US", + "deleteFile": false, + "description": "17.11.2022", + "encodingName": "utf-8", + "fieldMappings": [], + "fieldMappingType": "InferFromColumnHeadings", + "fileNamingPattern": "blabla", + "fileType": "CSV", + "filter": "", + "hasColumnHeader": true, + "isOrderedImport": true, + "isSequential": true, + "maxFileAgeHours": 0, + "maxFileAgeScheduleOffsetHours": 0, + "maxImportFrequencyHours": 0, + "modifiedDate": "2022-11-17T07:13:03.95", + "name": "testExisting_importFile", + + "sendEmailNotification": false, + "standardQuotedStrings": true, + "destination": { + "c__type": "DataExtension", + "r__dataExtension_key": "testExisting_dataExtension" + }, + "source": { + "c__type": "File Location", + "r__fileLocation_name": "ExactTarget Enhanced FTP" + } +} diff --git a/test/resources/9999999/importFile/get-sms-expected.json b/test/resources/9999999/importFile/get-sms-expected.json new file mode 100644 index 000000000..cfc89493c --- /dev/null +++ b/test/resources/9999999/importFile/get-sms-expected.json @@ -0,0 +1,80 @@ +{ + "allowErrors": true, + "c__dataAction": "AddUpdate", + "c__subscriberImportType": "DataExtension", + "createdDate": "2022-11-24T03:29:01.05", + "customerKey": "testExisting_importFileSMS", + "dateFormatLocale": "en-US", + "deleteFile": false, + "description": "Unsub for Keyword", + "fieldMappingType": "ManualMap", + "fieldMappings": [ + { + "destinationFieldName": "_CountryCode", + "sourceFieldName": "Locale" + }, + { + "destinationFieldName": "_FirstName", + "sourceFieldName": "FirstName" + }, + { + "destinationFieldName": "_IsHonorDST", + "sourceFieldName": "IsHonorDST" + }, + { + "destinationFieldName": "_LastName", + "sourceFieldName": "LastName" + }, + { + "destinationFieldName": "_MobileNumber", + "sourceFieldName": "MobileNumber" + }, + { + "destinationFieldName": "_Status", + "sourceFieldName": "Status" + }, + { + "destinationFieldName": "_SubscriberKey", + "sourceFieldName": "ContactKey" + }, + { + "destinationFieldName": "_UTCOffset", + "sourceFieldName": "UTCoffset" + }, + { + "destinationFieldName": "Action", + "sourceFieldName": "Action" + }, + { + "destinationFieldName": "SalesforceModified", + "sourceFieldName": "ModifiedDate" + }, + { + "destinationFieldName": "SFContactID", + "sourceFieldName": "SFContactID" + } + ], + "fileNamingPattern": "_CustomObject", + "fileType": "CSV", + "filter": "", + "hasColumnHeader": true, + "isOrderedImport": false, + "isSequential": true, + "maxFileAgeHours": 0, + "maxFileAgeScheduleOffsetHours": 0, + "maxImportFrequencyHours": 0, + "modifiedDate": "2023-07-19T23:06:33.577", + "name": "testExisting_importFileSMS", + "notificationEmailAddress": "joern.berkefeld@accenture.com", + "sendEmailNotification": true, + "standardQuotedStrings": false, + "destination": { + "c__type": "SMS", + "r__mobileKeyword_key": "4912312345678.TESTEXISTING_KEYWORD" + }, + "source": { + "c__type": "DataExtension", + "r__dataExtension_key": "testExisting_dataExtension", + "r__fileLocation_name": "ExactTarget Enhanced FTP" + } +} diff --git a/test/resources/9999999/importFile/patch-expected.json b/test/resources/9999999/importFile/patch-expected.json new file mode 100644 index 000000000..b84c1119b --- /dev/null +++ b/test/resources/9999999/importFile/patch-expected.json @@ -0,0 +1,32 @@ +{ + "allowErrors": true, + "c__blankFileProcessing": "Process", + "c__dataAction": "AddUpdate", + "c__subscriberImportType": "DataExtension", + "createdDate": "2022-11-09T05:32:30.533", + "customerKey": "testExisting_importFile", + "dateFormatLocale": "en-US", + "deleteFile": false, + "description": "updated on deploy", + "encodingName": "utf-8", + "fieldMappings": [], + "fieldMappingType": "InferFromColumnHeadings", + "fileNamingPattern": "blabla", + "fileType": "CSV", + "filter": "", + "hasColumnHeader": true, + "isOrderedImport": true, + "isSequential": true, + "maxFileAgeHours": 0, + "maxFileAgeScheduleOffsetHours": 0, + "maxImportFrequencyHours": 0, + "modifiedDate": "2023-07-18T09:11:26.19", + "name": "testExisting_importFile", + "sendEmailNotification": false, + "standardQuotedStrings": true, + "destination": { + "c__type": "DataExtension", + "r__dataExtension_key": "testExisting_dataExtension" + }, + "source": { "c__type": "File Location", "r__fileLocation_name": "ExactTarget Enhanced FTP" } +} diff --git a/test/resources/9999999/importFile/post-expected.json b/test/resources/9999999/importFile/post-expected.json new file mode 100644 index 000000000..44bd0264f --- /dev/null +++ b/test/resources/9999999/importFile/post-expected.json @@ -0,0 +1,30 @@ +{ + "allowErrors": true, + "c__dataAction": "AddUpdate", + "c__subscriberImportType": "DataExtension", + "createdDate": "2022-11-09T05:53:03.243", + "customerKey": "testNew_importFile", + "dateFormatLocale": "en-US", + "deleteFile": false, + "description": "created via deploy", + "fieldMappingType": "InferFromColumnHeadings", + "fieldMappings": [], + "fileNamingPattern": "blabla", + "fileType": "CSV", + "filter": "", + "hasColumnHeader": true, + "isOrderedImport": true, + "isSequential": true, + "maxFileAgeHours": 0, + "maxFileAgeScheduleOffsetHours": 0, + "maxImportFrequencyHours": 0, + "modifiedDate": "2023-07-18T09:11:26.19", + "name": "testNew_importFile", + "sendEmailNotification": false, + "standardQuotedStrings": true, + "destination": { + "c__type": "DataExtension", + "r__dataExtension_key": "testExisting_dataExtension" + }, + "source": { "c__type": "File Location", "r__fileLocation_name": "ExactTarget Enhanced FTP" } +} diff --git a/test/resources/9999999/importFile/template-expected.json b/test/resources/9999999/importFile/template-expected.json new file mode 100644 index 000000000..26ffed49a --- /dev/null +++ b/test/resources/9999999/importFile/template-expected.json @@ -0,0 +1,30 @@ +{ + "allowErrors": true, + "c__blankFileProcessing": "Skip", + "c__dataAction": "AddUpdate", + "c__subscriberImportType": "DataExtension", + "customerKey": "{{{prefix}}}importFile", + "dateFormatLocale": "en-US", + "deleteFile": false, + "description": "17.11.2022", + "encodingName": "utf-8", + "fieldMappingType": "InferFromColumnHeadings", + "fieldMappings": [], + "fileNamingPattern": "blabla", + "fileType": "CSV", + "filter": "", + "hasColumnHeader": true, + "isOrderedImport": true, + "isSequential": true, + "maxFileAgeHours": 0, + "maxFileAgeScheduleOffsetHours": 0, + "maxImportFrequencyHours": 0, + "name": "{{{prefix}}}importFile", + "sendEmailNotification": false, + "standardQuotedStrings": true, + "destination": { + "c__type": "DataExtension", + "r__dataExtension_key": "{{{prefix}}}dataExtension" + }, + "source": { "c__type": "File Location", "r__fileLocation_name": "ExactTarget Enhanced FTP" } +} diff --git a/test/resources/9999999/interaction/v1/eventDefinitions/get-response.json b/test/resources/9999999/interaction/v1/eventDefinitions/get-response.json new file mode 100644 index 000000000..a299c3591 --- /dev/null +++ b/test/resources/9999999/interaction/v1/eventDefinitions/get-response.json @@ -0,0 +1,426 @@ +{ + "count": 5, + "page": 1, + "pageSize": 50, + "links": {}, + "items": [ + { + "id": "161b64a1-1867-4272-8c5c-4d7abe880702", + "type": "AutomationAudience", + "name": "testExisting_event_automation", + "description": "", + "createdDate": "2024-11-07T04:58:46.51", + "createdBy": 700301950, + "modifiedDate": "2024-11-07T04:58:46.51", + "modifiedBy": 700301950, + "mode": "Production", + "eventDefinitionKey": "testExisting_event_automation", + "dataExtensionId": "21711373-72c1-ec11-b83b-48df37d1deb7", + "dataExtensionName": "testExisting_automation_event", + "sourceApplicationExtensionId": "97e942ee-6914-4d3d-9e52-37ecb71f79ed", + "filterDefinitionId": "00000000-0000-0000-0000-000000000000", + "filterDefinitionTemplate": "", + "iconUrl": "/images/icon-data-extension.svg", + "arguments": { + "serializedObjectType": 9, + "useHighWatermark": true, + "resetHighWatermark": false, + "automationId": "8f82c2a7-0bae-45a9-bdee-e631ab25c0d5", + "eventDefinitionId": "161b64a1-1867-4272-8c5c-4d7abe880702", + "eventDefinitionKey": "testExisting_event_automation", + "dataExtensionId": "21711373-72c1-ec11-b83b-48df37d1deb7", + "criteria": "" + }, + "configurationArguments": { + "unconfigured": false + }, + "metaData": { + "criteriaDescription": "", + "scheduleFlowMode": "automation" + }, + "schedule": { + "startDateTime": "2024-11-07T12:15:00", + "endDateTime": "2079-06-06T00:00:00", + "timeZone": "W. Europe Standard Time", + "occurrences": 478403, + "endType": "EndDate", + "frequency": "Hourly", + "recurrencePattern": "Interval", + "interval": 1 + }, + "interactionCount": 1, + "isVisibleInPicker": false, + "isPlatformObject": false, + "category": "Audience", + "publishedInteractionCount": 1, + "automationId": "8f82c2a7-0bae-45a9-bdee-e631ab25c0d5", + "disableDEDataLogging": false + }, + { + "id": "33b4dbc5-4b58-4a54-ab57-24388f1eefe4", + "type": "APIEvent", + "name": "TestContact_Event", + "description": "", + "createdDate": "2018-08-03T07:55:27.38", + "createdBy": 700301950, + "modifiedDate": "2018-08-03T08:22:03.76", + "modifiedBy": 700301950, + "mode": "Production", + "eventDefinitionKey": "APIEvent-60130566-e2fe-eb29-4140-15c27093a80b", + "dataExtensionId": "1c8064d5-6502-ef11-a5c8-5cba2c702db8", + "dataExtensionName": "testExisting_journey_Quicksend", + "sourceApplicationExtensionId": "7db1f972-f8b7-49b6-91b5-fa218e13953d", + "filterDefinitionTemplate": "", + "iconUrl": "/events/images/icon_journeyBuilder-event-api-blue.svg", + "arguments": { + "serializedObjectType": 11, + "eventDefinitionKey": "APIEvent-60130566-e2fe-eb29-4140-15c27093a80b", + "dataExtensionId": "C25D5A59-5EBC-40C9-8D27-149831881D89", + "automationId": "00000000-0000-0000-0000-000000000000", + "criteria": "", + "useHighWatermark": false + }, + "metaData": { + "scheduleState": "No Schedule", + "criteriaDescription": "" + }, + "interactionCount": 1, + "isVisibleInPicker": true, + "isPlatformObject": false, + "category": "Event", + "publishedInteractionCount": 1, + "automationId": "00000000-0000-0000-0000-000000000000", + "disableDEDataLogging": false + }, + { + "id": "9e1995f8-951d-4019-855c-826b45e5b028", + "type": "EmailAudience", + "name": "testExisting_journey_Quicksend", + "description": "", + "createdDate": "2024-04-24T12:18:40.573", + "createdBy": 700301950, + "modifiedDate": "2024-04-24T12:18:40.573", + "modifiedBy": 700301950, + "mode": "Production", + "eventDefinitionKey": "DEAudience-11be962d-064c-83d9-2804-7d1befc10325", + "dataExtensionId": "1c8064d5-6502-ef11-a5c8-5cba2c702db8", + "dataExtensionName": "testExisting_journey_Quicksend", + "sourceApplicationExtensionId": "97e942ee-6914-4d3d-9e52-37ecb71f79ed", + "filterDefinitionId": "00000000-0000-0000-0000-000000000000", + "filterDefinitionTemplate": "", + "iconUrl": "/images/icon-data-extension.svg", + "arguments": { + "serializedObjectType": 3, + "useHighWatermark": false, + "eventDefinitionId": "9e1995f8-951d-4019-855c-826b45e5b028", + "eventDefinitionKey": "DEAudience-11be962d-064c-83d9-2804-7d1befc10325", + "dataExtensionId": "1c8064d5-6502-ef11-a5c8-5cba2c702db8", + "criteria": "" + }, + "configurationArguments": { + "unconfigured": false + }, + "metaData": { + "criteriaDescription": "", + "scheduleFlowMode": "runOnce", + "runOnceScheduleMode": "onPublish", + "scheduleState": "No Schedule" + }, + "interactionCount": 1, + "isVisibleInPicker": false, + "isPlatformObject": false, + "category": "Audience", + "publishedInteractionCount": 0, + "automationId": "00000000-0000-0000-0000-000000000000", + "disableDEDataLogging": false + }, + { + "id": "649d512b-4d08-4eca-a14e-fc7b64b4ada8", + "type": "EmailAudience", + "name": "testExisting_journey_Multistep", + "description": "", + "createdDate": "2024-05-04T05:54:44.95", + "createdBy": 700301950, + "modifiedDate": "2024-05-04T05:54:44.95", + "modifiedBy": 700301950, + "mode": "Production", + "eventDefinitionKey": "DEAudience-2e3c73b6-48cc-2ec0-5522-48636e1a236e", + "dataExtensionId": "ed305df3-6502-ef11-a5c8-5cba2c702db8", + "dataExtensionName": "testExisting_journey_Multistep", + "sourceApplicationExtensionId": "97e942ee-6914-4d3d-9e52-37ecb71f79ed", + "filterDefinitionId": "00000000-0000-0000-0000-000000000000", + "filterDefinitionTemplate": "", + "iconUrl": "/images/icon-data-extension.svg", + "arguments": { + "serializedObjectType": 3, + "eventDefinitionId": "649d512b-4d08-4eca-a14e-fc7b64b4ada8", + "eventDefinitionKey": "DEAudience-2e3c73b6-48cc-2ec0-5522-48636e1a236e", + "dataExtensionId": "ed305df3-6502-ef11-a5c8-5cba2c702db8", + "criteria": "" + }, + "configurationArguments": { + "unconfigured": true + }, + "metaData": { + "criteriaDescription": "", + "scheduleState": "No Schedule" + }, + "interactionCount": 1, + "isVisibleInPicker": false, + "isPlatformObject": false, + "category": "Audience", + "publishedInteractionCount": 0, + "automationId": "00000000-0000-0000-0000-000000000000", + "disableDEDataLogging": false + }, + { + "id": "d8d57832-ce9c-4bf6-8c24-3044ece5dffd", + "type": "APIEvent", + "name": "testExisting_event", + "description": "", + "createdDate": "2024-07-05T06:12:24.227", + "createdBy": 700301950, + "modifiedDate": "2024-07-05T08:01:55.4", + "modifiedBy": 700301950, + "mode": "Production", + "eventDefinitionKey": "testExisting_event", + "dataExtensionId": "f2cc2b21-d73a-ef11-a5c8-5cba2c702db8", + "dataExtensionName": "testExisting_event - 2024-07-05T080154625", + "schema": { + "id": "f2cc2b21-d73a-ef11-a5c8-5cba2c702db8", + "name": "testExisting_event - 2024-07-05T080154625", + "fields": [ + { + "name": "ContactId", + "dataType": "Text", + "maxLength": "18", + "isNullable": false, + "isPrimaryKey": true, + "isDevicePreference": false + }, + { + "name": "Type", + "dataType": "Text", + "maxLength": "50", + "isNullable": false, + "isPrimaryKey": false, + "isDevicePreference": false + }, + { + "name": "Status", + "dataType": "Text", + "maxLength": "50", + "isNullable": false, + "isPrimaryKey": true, + "isDevicePreference": false + }, + { + "name": "Respondent", + "dataType": "Text", + "maxLength": "256", + "isNullable": true, + "isPrimaryKey": false, + "isDevicePreference": false + }, + { + "name": "FirstName", + "dataType": "Text", + "maxLength": "256", + "isNullable": true, + "isPrimaryKey": false, + "isDevicePreference": false + }, + { + "name": "LastName", + "dataType": "Text", + "maxLength": "256", + "isNullable": true, + "isPrimaryKey": false, + "isDevicePreference": false + }, + { + "name": "PreferredLanguage", + "dataType": "Text", + "maxLength": "50", + "isNullable": true, + "isPrimaryKey": false, + "isDevicePreference": false + }, + { + "name": "TouchPoint", + "dataType": "Text", + "maxLength": "256", + "isNullable": true, + "isPrimaryKey": false, + "isDevicePreference": false + }, + { + "name": "Datestamp", + "dataType": "Date", + "isNullable": true, + "defaultValue": "GetDate()", + "isPrimaryKey": false, + "isDevicePreference": false + }, + { + "name": "StartDate", + "dataType": "Date", + "isNullable": true, + "defaultValue": "", + "isPrimaryKey": false, + "isDevicePreference": false + }, + { + "name": "EndDate", + "dataType": "Date", + "isNullable": true, + "isPrimaryKey": false, + "isDevicePreference": false + }, + { + "name": "BroadcastedNotificationDate", + "dataType": "Date", + "isNullable": true, + "defaultValue": "", + "isPrimaryKey": false, + "isDevicePreference": false + }, + { + "name": "FirstReminderDate", + "dataType": "Date", + "isNullable": true, + "isPrimaryKey": false, + "isDevicePreference": false + }, + { + "name": "SecondReminderDate", + "dataType": "Date", + "isNullable": true, + "isPrimaryKey": false, + "isDevicePreference": false + }, + { + "name": "Title", + "dataType": "Text", + "maxLength": "256", + "isNullable": true, + "isPrimaryKey": false, + "isDevicePreference": false + }, + { + "name": "DisplayName", + "dataType": "Text", + "maxLength": "256", + "isNullable": true, + "isPrimaryKey": false, + "isDevicePreference": false + }, + { + "name": "Text", + "dataType": "Text", + "maxLength": "256", + "isNullable": true, + "isPrimaryKey": false, + "isDevicePreference": false + }, + { + "name": "Description", + "dataType": "Text", + "maxLength": "4000", + "isNullable": true, + "isPrimaryKey": false, + "isDevicePreference": false + }, + { + "name": "Channel", + "dataType": "Text", + "maxLength": "256", + "isNullable": true, + "isPrimaryKey": false, + "isDevicePreference": false + }, + { + "name": "FirstReminderChannel", + "dataType": "Text", + "maxLength": "256", + "isNullable": true, + "isPrimaryKey": false, + "isDevicePreference": false + }, + { + "name": "SecondReminderChannel", + "dataType": "Text", + "maxLength": "256", + "isNullable": true, + "isPrimaryKey": false, + "isDevicePreference": false + }, + { + "name": "Email", + "dataType": "Email", + "maxLength": "", + "isNullable": true, + "isPrimaryKey": false, + "isDevicePreference": false + }, + { + "name": "ArticleOrTaskID", + "dataType": "Text", + "maxLength": "18", + "isNullable": false, + "isPrimaryKey": true, + "isDevicePreference": false + }, + { + "name": "Points", + "dataType": "Number", + "maxLength": "", + "isNullable": true, + "isPrimaryKey": false, + "isDevicePreference": false + }, + { + "name": "TaskType", + "dataType": "Text", + "maxLength": "255", + "isNullable": true, + "isPrimaryKey": false, + "isDevicePreference": false + }, + { + "name": "TaskArea", + "dataType": "Text", + "maxLength": "255", + "isNullable": true, + "isPrimaryKey": false, + "isDevicePreference": false + } + ], + "sendableCustomObjectField": "ContactId", + "sendableSubscriberField": "_SubscriberKey", + "isPlatformObject": false + }, + "sourceApplicationExtensionId": "00000000-0000-0000-0000-000000000000", + "filterDefinitionId": "00000000-0000-0000-0000-000000000000", + "filterDefinitionTemplate": "", + "iconUrl": "", + "arguments": { + "serializedObjectType": 11, + "eventDefinitionKey": "testExisting_event", + "eventDefinitionId": "d8d57832-ce9c-4bf6-8c24-3044ece5dffd", + "dataExtensionId": "00000000-0000-0000-0000-000000000000", + "criteria": "" + }, + "metaData": { + "scheduleState": "No Schedule" + }, + "interactionCount": 0, + "isVisibleInPicker": true, + "isPlatformObject": false, + "category": "Event", + "publishedInteractionCount": 0, + "automationId": "00000000-0000-0000-0000-000000000000", + "disableDEDataLogging": false + } + ] +} diff --git a/test/resources/9999999/interaction/v1/eventDefinitions/key_DEAudience-2e3c73b6-48cc-2ec0-5522-48636e1a236e/get-response.json b/test/resources/9999999/interaction/v1/eventDefinitions/key_DEAudience-2e3c73b6-48cc-2ec0-5522-48636e1a236e/get-response.json new file mode 100644 index 000000000..355c083d7 --- /dev/null +++ b/test/resources/9999999/interaction/v1/eventDefinitions/key_DEAudience-2e3c73b6-48cc-2ec0-5522-48636e1a236e/get-response.json @@ -0,0 +1,39 @@ +{ + "id": "649d512b-4d08-4eca-a14e-fc7b64b4ada8", + "type": "EmailAudience", + "name": "testExisting_journey_Multistep", + "description": "", + "createdDate": "2024-05-04T05:54:44.95", + "createdBy": 700301950, + "modifiedDate": "2024-05-04T05:54:44.95", + "modifiedBy": 700301950, + "mode": "Production", + "eventDefinitionKey": "DEAudience-2e3c73b6-48cc-2ec0-5522-48636e1a236e", + "dataExtensionId": "ed305df3-6502-ef11-a5c8-5cba2c702db8", + "dataExtensionName": "testExisting_journey_Multistep", + "sourceApplicationExtensionId": "97e942ee-6914-4d3d-9e52-37ecb71f79ed", + "filterDefinitionId": "00000000-0000-0000-0000-000000000000", + "filterDefinitionTemplate": "", + "iconUrl": "/images/icon-data-extension.svg", + "arguments": { + "serializedObjectType": 3, + "eventDefinitionId": "649d512b-4d08-4eca-a14e-fc7b64b4ada8", + "eventDefinitionKey": "DEAudience-2e3c73b6-48cc-2ec0-5522-48636e1a236e", + "dataExtensionId": "ed305df3-6502-ef11-a5c8-5cba2c702db8", + "criteria": "" + }, + "configurationArguments": { + "unconfigured": true + }, + "metaData": { + "criteriaDescription": "", + "scheduleState": "No Schedule" + }, + "interactionCount": 1, + "isVisibleInPicker": false, + "isPlatformObject": false, + "category": "Audience", + "publishedInteractionCount": 0, + "automationId": "00000000-0000-0000-0000-000000000000", + "disableDEDataLogging": false +} diff --git a/test/resources/9999999/interaction/v1/eventDefinitions/key_testExisting_event/delete-response.txt b/test/resources/9999999/interaction/v1/eventDefinitions/key_testExisting_event/delete-response.txt new file mode 100644 index 000000000..e69de29bb diff --git a/test/resources/9999999/interaction/v1/eventDefinitions/key_testExisting_event/put-response.json b/test/resources/9999999/interaction/v1/eventDefinitions/key_testExisting_event/put-response.json new file mode 100644 index 000000000..422500294 --- /dev/null +++ b/test/resources/9999999/interaction/v1/eventDefinitions/key_testExisting_event/put-response.json @@ -0,0 +1,242 @@ +{ + "id": "d8d57832-ce9c-4bf6-8c24-3044ece5dffd", + "type": "APIEvent", + "name": "testExisting_event", + "description": "updated on deploy", + "createdDate": "0001-01-01T00:00:00", + "createdBy": 0, + "modifiedDate": "0001-01-01T00:00:00", + "modifiedBy": 0, + "mode": "Production", + "eventDefinitionKey": "testExisting_event", + "iconUrl": "/images/icon_journeyBuilder-event-api-blue.svg", + "dataExtensionId": "f2cc2b21-d73a-ef11-a5c8-5cba2c702db8", + "schema": { + "id": "f2cc2b21-d73a-ef11-a5c8-5cba2c702db8", + "name": "testExisting_event - 2024-07-05T080154625", + "fields": [ + { + "name": "ContactId", + "dataType": "Text", + "maxLength": "18", + "isNullable": false, + "isPrimaryKey": true, + "isDevicePreference": false + }, + { + "name": "Type", + "dataType": "Text", + "maxLength": "50", + "isNullable": false, + "isPrimaryKey": false, + "isDevicePreference": false + }, + { + "name": "Status", + "dataType": "Text", + "maxLength": "50", + "isNullable": false, + "isPrimaryKey": true, + "isDevicePreference": false + }, + { + "name": "Respondent", + "dataType": "Text", + "maxLength": "256", + "isNullable": true, + "isPrimaryKey": false, + "isDevicePreference": false + }, + { + "name": "FirstName", + "dataType": "Text", + "maxLength": "256", + "isNullable": true, + "isPrimaryKey": false, + "isDevicePreference": false + }, + { + "name": "LastName", + "dataType": "Text", + "maxLength": "256", + "isNullable": true, + "isPrimaryKey": false, + "isDevicePreference": false + }, + { + "name": "PreferredLanguage", + "dataType": "Text", + "maxLength": "50", + "isNullable": true, + "isPrimaryKey": false, + "isDevicePreference": false + }, + { + "name": "TouchPoint", + "dataType": "Text", + "maxLength": "256", + "isNullable": true, + "isPrimaryKey": false, + "isDevicePreference": false + }, + { + "name": "Datestamp", + "dataType": "Date", + "isNullable": true, + "defaultValue": "GetDate()", + "isPrimaryKey": false, + "isDevicePreference": false + }, + { + "name": "StartDate", + "dataType": "Date", + "isNullable": true, + "defaultValue": "", + "isPrimaryKey": false, + "isDevicePreference": false + }, + { + "name": "EndDate", + "dataType": "Date", + "isNullable": true, + "isPrimaryKey": false, + "isDevicePreference": false + }, + { + "name": "BroadcastedNotificationDate", + "dataType": "Date", + "isNullable": true, + "defaultValue": "", + "isPrimaryKey": false, + "isDevicePreference": false + }, + { + "name": "FirstReminderDate", + "dataType": "Date", + "isNullable": true, + "isPrimaryKey": false, + "isDevicePreference": false + }, + { + "name": "SecondReminderDate", + "dataType": "Date", + "isNullable": true, + "isPrimaryKey": false, + "isDevicePreference": false + }, + { + "name": "Title", + "dataType": "Text", + "maxLength": "256", + "isNullable": true, + "isPrimaryKey": false, + "isDevicePreference": false + }, + { + "name": "DisplayName", + "dataType": "Text", + "maxLength": "256", + "isNullable": true, + "isPrimaryKey": false, + "isDevicePreference": false + }, + { + "name": "Text", + "dataType": "Text", + "maxLength": "256", + "isNullable": true, + "isPrimaryKey": false, + "isDevicePreference": false + }, + { + "name": "Description", + "dataType": "Text", + "maxLength": "4000", + "isNullable": true, + "isPrimaryKey": false, + "isDevicePreference": false + }, + { + "name": "Channel", + "dataType": "Text", + "maxLength": "256", + "isNullable": true, + "isPrimaryKey": false, + "isDevicePreference": false + }, + { + "name": "FirstReminderChannel", + "dataType": "Text", + "maxLength": "256", + "isNullable": true, + "isPrimaryKey": false, + "isDevicePreference": false + }, + { + "name": "SecondReminderChannel", + "dataType": "Text", + "maxLength": "256", + "isNullable": true, + "isPrimaryKey": false, + "isDevicePreference": false + }, + { + "name": "Email", + "dataType": "Email", + "maxLength": "", + "isNullable": true, + "isPrimaryKey": false, + "isDevicePreference": false + }, + { + "name": "ArticleOrTaskID", + "dataType": "Text", + "maxLength": "18", + "isNullable": false, + "isPrimaryKey": true, + "isDevicePreference": false + }, + { + "name": "Points", + "dataType": "Number", + "maxLength": "", + "isNullable": true, + "isPrimaryKey": false, + "isDevicePreference": false + }, + { + "name": "TaskType", + "dataType": "Text", + "maxLength": "255", + "isNullable": true, + "isPrimaryKey": false, + "isDevicePreference": false + }, + { + "name": "TaskArea", + "dataType": "Text", + "maxLength": "255", + "isNullable": true, + "isPrimaryKey": false, + "isDevicePreference": false + } + ], + "sendableCustomObjectField": "ContactId", + "sendableSubscriberField": "_SubscriberKey", + "isPlatformObject": false + }, + "filterDefinitionId": "00000000-0000-0000-0000-000000000000", + "arguments": { + "serializedObjectType": 11, + "eventDefinitionKey": "testExisting_event", + "dataExtensionId": "f2cc2b21-d73a-ef11-a5c8-5cba2c702db8", + "eventDefinitionId": "d8d57832-ce9c-4bf6-8c24-3044ece5dffd" + }, + "metaData": {}, + "interactionCount": 0, + "isVisibleInPicker": false, + "isPlatformObject": false, + "category": "Event", + "publishedInteractionCount": 0, + "automationId": "00000000-0000-0000-0000-000000000000" +} diff --git a/test/resources/9999999/interaction/v1/eventDefinitions/key_testExisting_event_automation/get-response.json b/test/resources/9999999/interaction/v1/eventDefinitions/key_testExisting_event_automation/get-response.json new file mode 100644 index 000000000..f323cf24f --- /dev/null +++ b/test/resources/9999999/interaction/v1/eventDefinitions/key_testExisting_event_automation/get-response.json @@ -0,0 +1,52 @@ +{ + "id": "161b64a1-1867-4272-8c5c-4d7abe880702", + "type": "AutomationAudience", + "name": "testExisting_event_automation", + "description": "", + "createdDate": "2024-11-07T04:58:46.51", + "createdBy": 700301950, + "modifiedDate": "2024-11-07T04:58:46.51", + "modifiedBy": 700301950, + "mode": "Production", + "eventDefinitionKey": "testExisting_event_automation", + "dataExtensionId": "21711373-72c1-ec11-b83b-48df37d1deb7", + "dataExtensionName": "testExisting_dataExtension", + "sourceApplicationExtensionId": "97e942ee-6914-4d3d-9e52-37ecb71f79ed", + "filterDefinitionId": "00000000-0000-0000-0000-000000000000", + "filterDefinitionTemplate": "", + "iconUrl": "/images/icon-data-extension.svg", + "arguments": { + "serializedObjectType": 9, + "useHighWatermark": true, + "resetHighWatermark": false, + "automationId": "8f82c2a7-0bae-45a9-bdee-e631ab25c0d5", + "eventDefinitionId": "161b64a1-1867-4272-8c5c-4d7abe880702", + "eventDefinitionKey": "testExisting_event_automation", + "dataExtensionId": "21711373-72c1-ec11-b83b-48df37d1deb7", + "criteria": "" + }, + "configurationArguments": { + "unconfigured": false + }, + "metaData": { + "criteriaDescription": "", + "scheduleFlowMode": "automation" + }, + "schedule": { + "startDateTime": "2024-11-07T12:15:00", + "endDateTime": "2079-06-06T00:00:00", + "timeZone": "W. Europe Standard Time", + "occurrences": 478403, + "endType": "EndDate", + "frequency": "Hourly", + "recurrencePattern": "Interval", + "interval": 1 + }, + "interactionCount": 1, + "isVisibleInPicker": false, + "isPlatformObject": false, + "category": "Audience", + "publishedInteractionCount": 1, + "automationId": "8f82c2a7-0bae-45a9-bdee-e631ab25c0d5", + "disableDEDataLogging": false +} diff --git a/test/resources/9999999/interaction/v1/eventDefinitions/post_withExistingDE-response.json b/test/resources/9999999/interaction/v1/eventDefinitions/post_withExistingDE-response.json new file mode 100644 index 000000000..552bf3d63 --- /dev/null +++ b/test/resources/9999999/interaction/v1/eventDefinitions/post_withExistingDE-response.json @@ -0,0 +1,28 @@ +{ + "id": "21ab68de-2e2f-40b2-b455-c977cbdd4335", + "type": "APIEvent", + "name": "testNew_event_withExistingDE", + "description": "created on deploy", + "createdDate": "0001-01-01T00:00:00", + "createdBy": 0, + "modifiedDate": "0001-01-01T00:00:00", + "modifiedBy": 0, + "mode": "Production", + "eventDefinitionKey": "testNew_event_withExistingDE", + "iconUrl": "/images/icon_journeyBuilder-event-api-blue.svg", + "sourceApplicationExtensionId": "7db1f972-f8b7-49b6-91b5-fa218e13953d", + "dataExtensionId": "f2cc2b21-d73a-ef11-a5c8-5cba2c702db8", + "filterDefinitionId": "00000000-0000-0000-0000-000000000000", + "arguments": { + "serializedObjectType": 11, + "eventDefinitionKey": "testNew_event_withExistingDE", + "eventDefinitionId": "21ab68de-2e2f-40b2-b455-c977cbdd4335", + "dataExtensionId": "f2cc2b21-d73a-ef11-a5c8-5cba2c702db8" + }, + "metaData": {}, + "interactionCount": 0, + "isVisibleInPicker": true, + "category": "Event", + "publishedInteractionCount": 0, + "automationId": "00000000-0000-0000-0000-000000000000" +} diff --git a/test/resources/9999999/interaction/v1/eventDefinitions/post_withSchema-response.json b/test/resources/9999999/interaction/v1/eventDefinitions/post_withSchema-response.json new file mode 100644 index 000000000..4e2cc0627 --- /dev/null +++ b/test/resources/9999999/interaction/v1/eventDefinitions/post_withSchema-response.json @@ -0,0 +1,243 @@ +{ + "id": "b9cb2b05-738d-4f49-b53d-28e3bbe52d12", + "type": "APIEvent", + "name": "testNew_event_withSchema", + "description": "created on deploy", + "createdDate": "0001-01-01T00:00:00", + "createdBy": 0, + "modifiedDate": "0001-01-01T00:00:00", + "modifiedBy": 0, + "mode": "Production", + "eventDefinitionKey": "testNew_event_withSchema", + "iconUrl": "/images/icon_journeyBuilder-event-api-blue.svg", + "sourceApplicationExtensionId": "7db1f972-f8b7-49b6-91b5-fa218e13953d", + "dataExtensionId": "4342972c-a43c-ef11-a5c8-5cba2c702db8", + "dataExtensionName": "testNew_event_withSchema - 2024-07-08T014814443", + "schema": { + "id": "4342972c-a43c-ef11-a5c8-5cba2c702db8", + "name": "testNew_event_withSchema - 2024-07-08T014814443", + "fields": [ + { + "name": "ContactId", + "dataType": "Text", + "maxLength": "18", + "isNullable": false, + "isPrimaryKey": true, + "isDevicePreference": false + }, + { + "name": "Type", + "dataType": "Text", + "maxLength": "50", + "isNullable": false, + "isPrimaryKey": false, + "isDevicePreference": false + }, + { + "name": "Status", + "dataType": "Text", + "maxLength": "50", + "isNullable": false, + "isPrimaryKey": true, + "isDevicePreference": false + }, + { + "name": "Respondent", + "dataType": "Text", + "maxLength": "256", + "isNullable": true, + "isPrimaryKey": false, + "isDevicePreference": false + }, + { + "name": "FirstName", + "dataType": "Text", + "maxLength": "256", + "isNullable": true, + "isPrimaryKey": false, + "isDevicePreference": false + }, + { + "name": "LastName", + "dataType": "Text", + "maxLength": "256", + "isNullable": true, + "isPrimaryKey": false, + "isDevicePreference": false + }, + { + "name": "PreferredLanguage", + "dataType": "Text", + "maxLength": "50", + "isNullable": true, + "isPrimaryKey": false, + "isDevicePreference": false + }, + { + "name": "TouchPoint", + "dataType": "Text", + "maxLength": "256", + "isNullable": true, + "isPrimaryKey": false, + "isDevicePreference": false + }, + { + "name": "Datestamp", + "dataType": "Date", + "isNullable": true, + "defaultValue": "GetDate()", + "isPrimaryKey": false, + "isDevicePreference": false + }, + { + "name": "StartDate", + "dataType": "Date", + "isNullable": true, + "defaultValue": "", + "isPrimaryKey": false, + "isDevicePreference": false + }, + { + "name": "EndDate", + "dataType": "Date", + "isNullable": true, + "isPrimaryKey": false, + "isDevicePreference": false + }, + { + "name": "BroadcastedNotificationDate", + "dataType": "Date", + "isNullable": true, + "defaultValue": "", + "isPrimaryKey": false, + "isDevicePreference": false + }, + { + "name": "FirstReminderDate", + "dataType": "Date", + "isNullable": true, + "isPrimaryKey": false, + "isDevicePreference": false + }, + { + "name": "SecondReminderDate", + "dataType": "Date", + "isNullable": true, + "isPrimaryKey": false, + "isDevicePreference": false + }, + { + "name": "Title", + "dataType": "Text", + "maxLength": "256", + "isNullable": true, + "isPrimaryKey": false, + "isDevicePreference": false + }, + { + "name": "DisplayName", + "dataType": "Text", + "maxLength": "256", + "isNullable": true, + "isPrimaryKey": false, + "isDevicePreference": false + }, + { + "name": "Text", + "dataType": "Text", + "maxLength": "256", + "isNullable": true, + "isPrimaryKey": false, + "isDevicePreference": false + }, + { + "name": "Description", + "dataType": "Text", + "maxLength": "4000", + "isNullable": true, + "isPrimaryKey": false, + "isDevicePreference": false + }, + { + "name": "Channel", + "dataType": "Text", + "maxLength": "256", + "isNullable": true, + "isPrimaryKey": false, + "isDevicePreference": false + }, + { + "name": "FirstReminderChannel", + "dataType": "Text", + "maxLength": "256", + "isNullable": true, + "isPrimaryKey": false, + "isDevicePreference": false + }, + { + "name": "SecondReminderChannel", + "dataType": "Text", + "maxLength": "256", + "isNullable": true, + "isPrimaryKey": false, + "isDevicePreference": false + }, + { + "name": "Email", + "dataType": "Email", + "maxLength": "", + "isNullable": true, + "isPrimaryKey": false, + "isDevicePreference": false + }, + { + "name": "ArticleOrTaskID", + "dataType": "Text", + "maxLength": "18", + "isNullable": false, + "isPrimaryKey": true, + "isDevicePreference": false + }, + { + "name": "Points", + "dataType": "Number", + "maxLength": "", + "isNullable": true, + "isPrimaryKey": false, + "isDevicePreference": false + }, + { + "name": "TaskType", + "dataType": "Text", + "maxLength": "255", + "isNullable": true, + "isPrimaryKey": false, + "isDevicePreference": false + }, + { + "name": "TaskArea", + "dataType": "Text", + "maxLength": "255", + "isNullable": true, + "isPrimaryKey": false, + "isDevicePreference": false + } + ], + "sendableCustomObjectField": "ContactId", + "sendableSubscriberField": "_SubscriberKey", + "isPlatformObject": false + }, + "filterDefinitionId": "00000000-0000-0000-0000-000000000000", + "arguments": { + "serializedObjectType": 11, + "eventDefinitionKey": "testNew_event_withSchema", + "eventDefinitionId": "b9cb2b05-738d-4f49-b53d-28e3bbe52d12", + "dataExtensionId": "00000000-0000-0000-0000-000000000000" + }, + "metaData": {}, + "interactionCount": 0, + "isVisibleInPicker": true, + "category": "Event", + "publishedInteractionCount": 0, + "automationId": "00000000-0000-0000-0000-000000000000" +} diff --git a/test/resources/9999999/interaction/v1/interactions/0175b971-71a3-4d8e-98ac-48121f3fbf4f/audit/all/get-response-versionNumber=1.json b/test/resources/9999999/interaction/v1/interactions/0175b971-71a3-4d8e-98ac-48121f3fbf4f/audit/all/get-response-versionNumber=1.json new file mode 100644 index 000000000..2ed236e6e --- /dev/null +++ b/test/resources/9999999/interaction/v1/interactions/0175b971-71a3-4d8e-98ac-48121f3fbf4f/audit/all/get-response-versionNumber=1.json @@ -0,0 +1,86 @@ +{ + "count": 5, + "page": 1, + "pageSize": 50, + "links": {}, + "items": [ + { + "id": "0175b971-71a3-4d8e-98ac-48121f3fbf4f", + "action": "Stop", + "user": { + "name": "Jörn Berkefeld", + "userId": 710355723 + }, + "timeStamp": "2024-10-24T02:00:00.73", + "key": "testExisting_journey_Multistep", + "versionNumber": 1, + "originalDefinitionId": "0175b971-71a3-4d8e-98ac-48121f3fbf4f", + "name": "testExisting_journey_Multistep", + "description": "" + }, + { + "id": "0175b971-71a3-4d8e-98ac-48121f3fbf4f", + "action": "Publish", + "user": { + "name": "Jörn Berkefeld", + "userId": 710355723 + }, + "timeStamp": "2024-09-05T01:58:55.43", + "key": "testExisting_journey_Multistep", + "versionNumber": 1, + "originalDefinitionId": "0175b971-71a3-4d8e-98ac-48121f3fbf4f", + "name": "testExisting_journey_Multistep", + "description": "", + "executionMode": "Production", + "publishStatus": "PublishCompleted", + "publishRequestId": "98c2d709-5c9a-4610-804b-ae8f72ff29ce" + }, + { + "id": "0175b971-71a3-4d8e-98ac-48121f3fbf4f", + "action": "Publish", + "user": { + "name": "Jörn Berkefeld", + "userId": 710355723 + }, + "timeStamp": "2024-09-05T01:58:04.913", + "key": "testExisting_journey_Multistep", + "versionNumber": 1, + "originalDefinitionId": "0175b971-71a3-4d8e-98ac-48121f3fbf4f", + "name": "testExisting_journey_Multistep", + "description": "", + "executionMode": "Production", + "publishStatus": "PublishCompleted", + "publishRequestId": "651bc5e1-688a-4d68-bc51-c404bc20bf9c" + }, + { + "id": "0175b971-71a3-4d8e-98ac-48121f3fbf4f", + "action": "Modify", + "user": { + "name": "Jörn Berkefeld", + "userId": 710355723 + }, + "timeStamp": "2024-09-05T01:57:55.043", + "key": "testExisting_journey_Multistep", + "versionNumber": 1, + "originalDefinitionId": "0175b971-71a3-4d8e-98ac-48121f3fbf4f", + "name": "testExisting_journey_Multistep", + "description": "", + "executionMode": "Production" + }, + { + "id": "0175b971-71a3-4d8e-98ac-48121f3fbf4f", + "action": "Create", + "user": { + "name": "joern.berkefeld app user", + "userId": 710420432 + }, + "timeStamp": "2024-09-04T06:50:21.85", + "key": "testExisting_journey_Multistep", + "versionNumber": 1, + "originalDefinitionId": "0175b971-71a3-4d8e-98ac-48121f3fbf4f", + "name": "testExisting_journey_Multistep", + "description": "", + "executionMode": "Production" + } + ] +} diff --git a/test/resources/9999999/interaction/v1/interactions/0175b971-71a3-4d8e-98ac-48121f3fbf4f/audit/all/get-response-versionNumber=2.json b/test/resources/9999999/interaction/v1/interactions/0175b971-71a3-4d8e-98ac-48121f3fbf4f/audit/all/get-response-versionNumber=2.json new file mode 100644 index 000000000..fdb20d761 --- /dev/null +++ b/test/resources/9999999/interaction/v1/interactions/0175b971-71a3-4d8e-98ac-48121f3fbf4f/audit/all/get-response-versionNumber=2.json @@ -0,0 +1,101 @@ +{ + "count": 6, + "page": 1, + "pageSize": 50, + "links": {}, + "items": [ + { + "id": "0175b971-71a3-4d8e-98ac-48121f3fbf4f", + "action": "Stop", + "user": { + "name": "Jörn Berkefeld", + "userId": 710355723 + }, + "timeStamp": "2024-10-28T08:03:18.297", + "key": "testExisting_journey_Multistep", + "versionNumber": 2, + "originalDefinitionId": "0175b971-71a3-4d8e-98ac-48121f3fbf4f", + "name": "testExisting_journey_Multistep", + "description": "" + }, + { + "id": "0175b971-71a3-4d8e-98ac-48121f3fbf4f", + "action": "Publish", + "user": { + "name": "Jörn Berkefeld", + "userId": 710355723 + }, + "timeStamp": "2024-10-24T02:11:04.73", + "key": "testExisting_journey_Multistep", + "versionNumber": 2, + "originalDefinitionId": "0175b971-71a3-4d8e-98ac-48121f3fbf4f", + "name": "testExisting_journey_Multistep", + "description": "", + "executionMode": "Production", + "publishStatus": "PublishCompleted", + "publishRequestId": "1d100137-575d-40d9-9266-0e3be8461190" + }, + { + "id": "0175b971-71a3-4d8e-98ac-48121f3fbf4f", + "action": "Publish", + "user": { + "name": "Jörn Berkefeld", + "userId": 710355723 + }, + "timeStamp": "2024-10-24T02:09:55.743", + "key": "testExisting_journey_Multistep", + "versionNumber": 2, + "originalDefinitionId": "0175b971-71a3-4d8e-98ac-48121f3fbf4f", + "name": "testExisting_journey_Multistep", + "description": "", + "executionMode": "Production", + "publishStatus": "PublishCompleted", + "publishRequestId": "6e9efccd-7561-4385-a8ca-cba45342183a" + }, + { + "id": "0175b971-71a3-4d8e-98ac-48121f3fbf4f", + "action": "Modify", + "user": { + "name": "Jörn Berkefeld", + "userId": 710355723 + }, + "timeStamp": "2024-10-24T02:09:43.423", + "key": "testExisting_journey_Multistep", + "versionNumber": 2, + "originalDefinitionId": "0175b971-71a3-4d8e-98ac-48121f3fbf4f", + "name": "testExisting_journey_Multistep", + "description": "", + "executionMode": "Production" + }, + { + "id": "0175b971-71a3-4d8e-98ac-48121f3fbf4f", + "action": "Modify", + "user": { + "name": "Jörn Berkefeld", + "userId": 710355723 + }, + "timeStamp": "2024-10-24T02:08:32.047", + "key": "testExisting_journey_Multistep", + "versionNumber": 2, + "originalDefinitionId": "0175b971-71a3-4d8e-98ac-48121f3fbf4f", + "name": "testExisting_journey_Multistep", + "description": "", + "executionMode": "Production" + }, + { + "id": "0175b971-71a3-4d8e-98ac-48121f3fbf4f", + "action": "Create", + "user": { + "name": "Jörn Berkefeld", + "userId": 710355723 + }, + "timeStamp": "2024-10-24T02:00:17.683", + "key": "testExisting_journey_Multistep", + "versionNumber": 2, + "originalDefinitionId": "0175b971-71a3-4d8e-98ac-48121f3fbf4f", + "name": "testExisting_journey_Multistep", + "description": "", + "executionMode": "Production" + } + ] +} diff --git a/test/resources/9999999/interaction/v1/interactions/0175b971-71a3-4d8e-98ac-48121f3fbf4f/audit/all/get-response-versionNumber=3.json b/test/resources/9999999/interaction/v1/interactions/0175b971-71a3-4d8e-98ac-48121f3fbf4f/audit/all/get-response-versionNumber=3.json new file mode 100644 index 000000000..5099e85d7 --- /dev/null +++ b/test/resources/9999999/interaction/v1/interactions/0175b971-71a3-4d8e-98ac-48121f3fbf4f/audit/all/get-response-versionNumber=3.json @@ -0,0 +1,86 @@ +{ + "count": 6, + "page": 1, + "pageSize": 50, + "links": {}, + "items": [ + { + "id": "0175b971-71a3-4d8e-98ac-48121f3fbf4f", + "action": "Stop", + "user": { + "name": "Jörn Berkefeld", + "userId": 710355723 + }, + "timeStamp": "2024-11-26T08:07:00.867", + "key": "testExisting_journey_Multistep", + "versionNumber": 3, + "originalDefinitionId": "0175b971-71a3-4d8e-98ac-48121f3fbf4f", + "name": "testExisting_journey_Multistep", + "description": "" + }, + { + "id": "0175b971-71a3-4d8e-98ac-48121f3fbf4f", + "action": "Publish", + "user": { + "name": "Jörn Berkefeld", + "userId": 710355723 + }, + "timeStamp": "2024-10-28T08:05:01.087", + "key": "testExisting_journey_Multistep", + "versionNumber": 3, + "originalDefinitionId": "0175b971-71a3-4d8e-98ac-48121f3fbf4f", + "name": "testExisting_journey_Multistep", + "description": "", + "executionMode": "Production", + "publishStatus": "PublishCompleted", + "publishRequestId": "f91be603-e9d0-4f12-b75a-6f4d6dae760c" + }, + { + "id": "0175b971-71a3-4d8e-98ac-48121f3fbf4f", + "action": "Publish", + "user": { + "name": "Jörn Berkefeld", + "userId": 710355723 + }, + "timeStamp": "2024-10-28T08:04:22.4", + "key": "testExisting_journey_Multistep", + "versionNumber": 3, + "originalDefinitionId": "0175b971-71a3-4d8e-98ac-48121f3fbf4f", + "name": "testExisting_journey_Multistep", + "description": "", + "executionMode": "Production", + "publishStatus": "PublishCompleted", + "publishRequestId": "8ee64518-181d-4c49-b1ba-de8314c306dd" + }, + { + "id": "0175b971-71a3-4d8e-98ac-48121f3fbf4f", + "action": "Modify", + "user": { + "name": "Jörn Berkefeld", + "userId": 710355723 + }, + "timeStamp": "2024-10-28T08:04:14.607", + "key": "testExisting_journey_Multistep", + "versionNumber": 3, + "originalDefinitionId": "0175b971-71a3-4d8e-98ac-48121f3fbf4f", + "name": "testExisting_journey_Multistep", + "description": "", + "executionMode": "Production" + }, + { + "id": "0175b971-71a3-4d8e-98ac-48121f3fbf4f", + "action": "Create", + "user": { + "name": "Jörn Berkefeld", + "userId": 710355723 + }, + "timeStamp": "2024-10-28T08:03:21.383", + "key": "testExisting_journey_Multistep", + "versionNumber": 3, + "originalDefinitionId": "0175b971-71a3-4d8e-98ac-48121f3fbf4f", + "name": "testExisting_journey_Multistep", + "description": "", + "executionMode": "Production" + } + ] +} diff --git a/test/resources/9999999/interaction/v1/interactions/0175b971-71a3-4d8e-98ac-48121f3fbf4f/delete-response-versionNumber=1.txt b/test/resources/9999999/interaction/v1/interactions/0175b971-71a3-4d8e-98ac-48121f3fbf4f/delete-response-versionNumber=1.txt new file mode 100644 index 000000000..9d53d75c0 --- /dev/null +++ b/test/resources/9999999/interaction/v1/interactions/0175b971-71a3-4d8e-98ac-48121f3fbf4f/delete-response-versionNumber=1.txt @@ -0,0 +1 @@ +0175b971-71a3-4d8e-98ac-48121f3fbf4f \ No newline at end of file diff --git a/test/resources/9999999/interaction/v1/interactions/0175b971-71a3-4d8e-98ac-48121f3fbf4f/delete-response.txt b/test/resources/9999999/interaction/v1/interactions/0175b971-71a3-4d8e-98ac-48121f3fbf4f/delete-response.txt new file mode 100644 index 000000000..9d53d75c0 --- /dev/null +++ b/test/resources/9999999/interaction/v1/interactions/0175b971-71a3-4d8e-98ac-48121f3fbf4f/delete-response.txt @@ -0,0 +1 @@ +0175b971-71a3-4d8e-98ac-48121f3fbf4f \ No newline at end of file diff --git a/test/resources/9999999/interaction/v1/interactions/0175b971-71a3-4d8e-98ac-48121f3fbf4f/get-response-versionNumber=1.json b/test/resources/9999999/interaction/v1/interactions/0175b971-71a3-4d8e-98ac-48121f3fbf4f/get-response-versionNumber=1.json new file mode 100644 index 000000000..144d4fc7e --- /dev/null +++ b/test/resources/9999999/interaction/v1/interactions/0175b971-71a3-4d8e-98ac-48121f3fbf4f/get-response-versionNumber=1.json @@ -0,0 +1,461 @@ +{ + "id": "0175b971-71a3-4d8e-98ac-48121f3fbf4f", + "key": "testExisting_journey_Multistep", + "name": "testExisting_journey_Multistep", + "lastPublishedDate": "0001-01-01T00:00:00", + "description": "", + "version": 1, + "workflowApiVersion": 1, + "createdDate": "2024-05-04T05:54:48.027", + "modifiedDate": "2024-05-04T17:25:57.9", + "activities": [ + { + "id": "342dd0aa-a6be-401e-8614-3538800bfd7c", + "key": "MULTICRITERIADECISIONV2-1", + "name": "", + "description": "", + "type": "MULTICRITERIADECISION", + "outcomes": [ + { + "key": "default_path_1", + "next": "EMAILV2-1", + "arguments": {}, + "metaData": { + "label": "send message", + "skipI18n": true, + "isLabelFromConversion": false, + "criteriaDescription": "Email is not null" + } + }, + { + "key": "remainder_path", + "next": "WAITBYDURATION-2", + "arguments": {}, + "metaData": { + "label": null + } + } + ], + "arguments": {}, + "configurationArguments": { + "criteria": { + "default_path_1": "<FilterDefinition><ConditionSet Operator=\"AND\" ConditionSetName=\"Individual Filter Grouping\"><Condition IsEphemeralAttribute=\"true\" Key=\"Event.DEAudience-2e3c73b6-48cc-2ec0-5522-48636e1a236e.Email\" Operator=\"IsNotNull\" UiMetaData=\"{}\"><Value><![CDATA[]]></Value></Condition></ConditionSet></FilterDefinition>" + }, + "schemaVersionId": "252" + }, + "metaData": { + "isConfigured": true + }, + "schema": { + "arguments": { + "actualChoice": { + "dataType": "Number", + "isNullable": false, + "direction": "Out", + "readOnly": false, + "access": "Hidden" + }, + "filterResult": { + "dataType": "Text", + "isNullable": false, + "direction": "In", + "readOnly": true, + "access": "Hidden" + } + } + } + }, + { + "id": "7ba1e59a-6be4-46c7-b76f-4c06feb1268a", + "key": "EMAILV2-1", + "name": "my custom activity name", + "description": "", + "type": "EMAILV2", + "outcomes": [ + { + "key": "ff60a294-3804-4165-85cd-c7c19c8e3a6d", + "next": "WAITBYDURATION-1", + "arguments": {}, + "metaData": { + "invalid": false + } + } + ], + "arguments": {}, + "configurationArguments": { + "applicationExtensionKey": "jb-email-activity", + "isModified": true, + "googleAnalyticsCampaignName": "", + "triggeredSendId": "b3150cf0-6e78-e811-80d4-1402ec721c9d", + "triggeredSendKey": "testExisting_triggeredSend", + "triggeredSend": { + "id": "outdated id", + "key": "outdated key", + "autoAddSubscribers": true, + "autoUpdateSubscribers": true, + "bccEmail": "", + "ccEmail": "", + "created": { + "name": "", + "date": "" + }, + "description": "my custom description", + "domainExclusions": [], + "dynamicEmailSubject": "testExisting_ email subject", + "emailId": 808714, + "emailSubject": "testExisting_ email subject", + "exclusionFilter": "", + "isSalesforceTracking": false, + "isMultipart": true, + "isSendLogging": true, + "isStoppedOnJobError": false, + "modified": { + "name": "", + "date": "" + }, + "preHeader": "testExisting_ email preheader", + "priority": 4, + "sendClassificationId": "95da425b-a06f-e611-96fe-38eaa7142c61", + "throttleOpens": "1/1/0001 12:00:00 AM", + "throttleCloses": "1/1/0001 12:00:00 AM", + "deliveryProfileId": "163f8417-13f7-e911-a2d8-1402ec938a35", + "senderProfileId": "a75d452b-7ef4-eb11-b82d-48df37d1da95", + "isTrackingClicks": true, + "publicationListId": 15 + } + }, + "metaData": { + "category": "message", + "version": "1.0", + "icon": "https://jb-email-activity.s7.marketingcloudapps.com/img/email-icon.svg", + "iconSmall": "https://jb-email-activity.s7.marketingcloudapps.com/img/email-icon.svg", + "statsContactIcon": null, + "original_icon": "/img/email-icon.svg", + "original_iconSmall": "/img/email-icon.svg", + "sections": {}, + "isConfigured": true + }, + "schema": { + "arguments": { + "requestID": { + "dataType": "Text", + "isNullable": true, + "direction": "Out", + "readOnly": false, + "access": "Hidden" + }, + "messageKey": { + "dataType": "Text", + "isNullable": true, + "direction": "Out", + "readOnly": false, + "access": "Hidden" + }, + "activityId": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "definitionId": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": true, + "access": "Hidden" + }, + "emailSubjectDataBound": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": true, + "access": "Hidden" + }, + "contactId": { + "dataType": "Number", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "contactKey": { + "dataType": "Text", + "isNullable": false, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "emailAddress": { + "dataType": "Text", + "isNullable": false, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "sourceCustomObjectId": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "sourceCustomObjectKey": { + "dataType": "LongNumber", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "fieldType": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "eventData": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "obfuscationProperties": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "customObjectKey": { + "dataType": "LongNumber", + "isNullable": true, + "direction": "In", + "readOnly": true, + "access": "Hidden" + }, + "definitionInstanceId": { + "dataType": "Text", + "isNullable": false, + "direction": "In", + "readOnly": false, + "access": "Hidden" + } + } + } + }, + { + "id": "70572b1a-e274-4f09-a3fa-6fc0732ec52b", + "key": "WAITBYDURATION-2", + "name": "", + "description": "", + "type": "WAIT", + "outcomes": [ + { + "key": "a0908f9f-bc3c-47f7-9489-7fef5af25ce3", + "arguments": {}, + "metaData": { + "invalid": false + } + } + ], + "arguments": {}, + "configurationArguments": { + "waitDuration": 1, + "waitUnit": "DAYS" + }, + "metaData": { + "isConfigured": true, + "uiType": "WAITBYDURATION" + }, + "schema": { + "arguments": { + "endDate": { + "dataType": "Date", + "isNullable": false, + "direction": "Out", + "readOnly": false, + "access": "Hidden" + }, + "waitEndDateAttributeDataBound": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "waitDefinitionId": { + "dataType": "Text", + "isNullable": false, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "waitForEventId": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "executionMode": { + "dataType": "Text", + "isNullable": false, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "startActivityKey": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "waitQueueId": { + "dataType": "LongNumber", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + } + } + } + }, + { + "id": "e2a486cf-c85f-4543-88a2-d579cac1e0de", + "key": "WAITBYDURATION-1", + "name": "1 day", + "description": "", + "type": "WAIT", + "outcomes": [ + { + "key": "97af222a-450a-429e-8925-649b72f01ccf", + "arguments": {}, + "metaData": { + "invalid": false + } + } + ], + "arguments": {}, + "configurationArguments": { + "waitDuration": 1, + "waitUnit": "DAYS" + }, + "metaData": { + "isConfigured": true, + "uiType": "WAITBYDURATION" + }, + "schema": { + "arguments": { + "endDate": { + "dataType": "Date", + "isNullable": false, + "direction": "Out", + "readOnly": false, + "access": "Hidden" + }, + "waitEndDateAttributeDataBound": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "waitDefinitionId": { + "dataType": "Text", + "isNullable": false, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "waitForEventId": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "executionMode": { + "dataType": "Text", + "isNullable": false, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "startActivityKey": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "waitQueueId": { + "dataType": "LongNumber", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + } + } + } + } + ], + "triggers": [ + { + "id": "92753481-1258-49bd-8a84-921ed63bcc2e", + "key": "TRIGGER", + "name": "TRIGGER", + "description": "", + "type": "EmailAudience", + "outcomes": [], + "arguments": {}, + "configurationArguments": {}, + "metaData": { + "eventDefinitionId": "649d512b-4d08-4eca-a14e-fc7b64b4ada8", + "eventDefinitionKey": "DEAudience-2e3c73b6-48cc-2ec0-5522-48636e1a236e", + "chainType": "None", + "configurationRequired": false, + "iconUrl": "/images/icon-data-extension.svg", + "title": "Data Extension", + "entrySourceGroupConfigUrl": "jb:///data/entry/audience/entrysourcegroupconfig.json", + "sourceInteractionId": "00000000-0000-0000-0000-000000000000" + } + } + ], + "goals": [], + "exits": [], + "notifiers": [], + "stats": { + "currentPopulation": 0, + "cumulativePopulation": 0, + "metGoal": 0, + "metExitCriteria": 0, + "goalPerformance": 0 + }, + "entryMode": "NotSet", + "definitionType": "Multistep", + "channel": "", + "defaults": { + "email": ["{{Event.DEAudience-2e3c73b6-48cc-2ec0-5522-48636e1a236e.\"Email\"}}"], + "properties": { + "analyticsTracking": { + "enabled": true, + "analyticsType": "google", + "urlDomainsToTrack": [] + } + } + }, + "metaData": { + "dataSource": "ContactsModel", + "highThroughputSending": { + "email": false + } + }, + "executionMode": "Production", + "categoryId": 6298, + "status": "Published", + "definitionId": "0175b971-71a3-4d8e-98ac-48121f3fbf4f", + "scheduledStatus": "Draft" +} diff --git a/test/resources/9999999/interaction/v1/interactions/0175b971-71a3-4d8e-98ac-48121f3fbf4f/get-response-versionNumber=3.json b/test/resources/9999999/interaction/v1/interactions/0175b971-71a3-4d8e-98ac-48121f3fbf4f/get-response-versionNumber=3.json new file mode 100644 index 000000000..eebe198ea --- /dev/null +++ b/test/resources/9999999/interaction/v1/interactions/0175b971-71a3-4d8e-98ac-48121f3fbf4f/get-response-versionNumber=3.json @@ -0,0 +1,461 @@ +{ + "id": "0175b971-71a3-4d8e-98ac-48121f3fbf4f", + "key": "testExisting_journey_Multistep", + "name": "testExisting_journey_Multistep", + "lastPublishedDate": "0001-01-01T00:00:00", + "description": "", + "version": 3, + "workflowApiVersion": 1, + "createdDate": "2024-05-04T05:54:48.027", + "modifiedDate": "2024-05-04T17:25:57.9", + "activities": [ + { + "id": "342dd0aa-a6be-401e-8614-3538800bfd7c", + "key": "MULTICRITERIADECISIONV2-1", + "name": "", + "description": "", + "type": "MULTICRITERIADECISION", + "outcomes": [ + { + "key": "default_path_1", + "next": "EMAILV2-1", + "arguments": {}, + "metaData": { + "label": "send message", + "skipI18n": true, + "isLabelFromConversion": false, + "criteriaDescription": "Email is not null" + } + }, + { + "key": "remainder_path", + "next": "WAITBYDURATION-2", + "arguments": {}, + "metaData": { + "label": null + } + } + ], + "arguments": {}, + "configurationArguments": { + "criteria": { + "default_path_1": "<FilterDefinition><ConditionSet Operator=\"AND\" ConditionSetName=\"Individual Filter Grouping\"><Condition IsEphemeralAttribute=\"true\" Key=\"Event.DEAudience-2e3c73b6-48cc-2ec0-5522-48636e1a236e.Email\" Operator=\"IsNotNull\" UiMetaData=\"{}\"><Value><![CDATA[]]></Value></Condition></ConditionSet></FilterDefinition>" + }, + "schemaVersionId": "252" + }, + "metaData": { + "isConfigured": true + }, + "schema": { + "arguments": { + "actualChoice": { + "dataType": "Number", + "isNullable": false, + "direction": "Out", + "readOnly": false, + "access": "Hidden" + }, + "filterResult": { + "dataType": "Text", + "isNullable": false, + "direction": "In", + "readOnly": true, + "access": "Hidden" + } + } + } + }, + { + "id": "7ba1e59a-6be4-46c7-b76f-4c06feb1268a", + "key": "EMAILV2-1", + "name": "my custom activity name", + "description": "", + "type": "EMAILV2", + "outcomes": [ + { + "key": "ff60a294-3804-4165-85cd-c7c19c8e3a6d", + "next": "WAITBYDURATION-1", + "arguments": {}, + "metaData": { + "invalid": false + } + } + ], + "arguments": {}, + "configurationArguments": { + "applicationExtensionKey": "jb-email-activity", + "isModified": true, + "googleAnalyticsCampaignName": "", + "triggeredSendId": "b3150cf0-6e78-e811-80d4-1402ec721c9d", + "triggeredSendKey": "testExisting_triggeredSend", + "triggeredSend": { + "id": "outdated id", + "key": "outdated key", + "autoAddSubscribers": true, + "autoUpdateSubscribers": true, + "bccEmail": "", + "ccEmail": "", + "created": { + "name": "", + "date": "" + }, + "description": "my custom description", + "domainExclusions": [], + "dynamicEmailSubject": "testExisting_ email subject", + "emailId": 808714, + "emailSubject": "testExisting_ email subject", + "exclusionFilter": "", + "isSalesforceTracking": false, + "isMultipart": true, + "isSendLogging": true, + "isStoppedOnJobError": false, + "modified": { + "name": "", + "date": "" + }, + "preHeader": "testExisting_ email preheader", + "priority": 4, + "sendClassificationId": "95da425b-a06f-e611-96fe-38eaa7142c61", + "throttleOpens": "1/1/0001 12:00:00 AM", + "throttleCloses": "1/1/0001 12:00:00 AM", + "deliveryProfileId": "163f8417-13f7-e911-a2d8-1402ec938a35", + "senderProfileId": "a75d452b-7ef4-eb11-b82d-48df37d1da95", + "isTrackingClicks": true, + "publicationListId": 15 + } + }, + "metaData": { + "category": "message", + "version": "1.0", + "icon": "https://jb-email-activity.s7.marketingcloudapps.com/img/email-icon.svg", + "iconSmall": "https://jb-email-activity.s7.marketingcloudapps.com/img/email-icon.svg", + "statsContactIcon": null, + "original_icon": "/img/email-icon.svg", + "original_iconSmall": "/img/email-icon.svg", + "sections": {}, + "isConfigured": true + }, + "schema": { + "arguments": { + "requestID": { + "dataType": "Text", + "isNullable": true, + "direction": "Out", + "readOnly": false, + "access": "Hidden" + }, + "messageKey": { + "dataType": "Text", + "isNullable": true, + "direction": "Out", + "readOnly": false, + "access": "Hidden" + }, + "activityId": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "definitionId": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": true, + "access": "Hidden" + }, + "emailSubjectDataBound": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": true, + "access": "Hidden" + }, + "contactId": { + "dataType": "Number", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "contactKey": { + "dataType": "Text", + "isNullable": false, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "emailAddress": { + "dataType": "Text", + "isNullable": false, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "sourceCustomObjectId": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "sourceCustomObjectKey": { + "dataType": "LongNumber", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "fieldType": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "eventData": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "obfuscationProperties": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "customObjectKey": { + "dataType": "LongNumber", + "isNullable": true, + "direction": "In", + "readOnly": true, + "access": "Hidden" + }, + "definitionInstanceId": { + "dataType": "Text", + "isNullable": false, + "direction": "In", + "readOnly": false, + "access": "Hidden" + } + } + } + }, + { + "id": "70572b1a-e274-4f09-a3fa-6fc0732ec52b", + "key": "WAITBYDURATION-2", + "name": "", + "description": "", + "type": "WAIT", + "outcomes": [ + { + "key": "a0908f9f-bc3c-47f7-9489-7fef5af25ce3", + "arguments": {}, + "metaData": { + "invalid": false + } + } + ], + "arguments": {}, + "configurationArguments": { + "waitDuration": 1, + "waitUnit": "DAYS" + }, + "metaData": { + "isConfigured": true, + "uiType": "WAITBYDURATION" + }, + "schema": { + "arguments": { + "endDate": { + "dataType": "Date", + "isNullable": false, + "direction": "Out", + "readOnly": false, + "access": "Hidden" + }, + "waitEndDateAttributeDataBound": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "waitDefinitionId": { + "dataType": "Text", + "isNullable": false, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "waitForEventId": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "executionMode": { + "dataType": "Text", + "isNullable": false, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "startActivityKey": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "waitQueueId": { + "dataType": "LongNumber", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + } + } + } + }, + { + "id": "e2a486cf-c85f-4543-88a2-d579cac1e0de", + "key": "WAITBYDURATION-1", + "name": "1 day", + "description": "", + "type": "WAIT", + "outcomes": [ + { + "key": "97af222a-450a-429e-8925-649b72f01ccf", + "arguments": {}, + "metaData": { + "invalid": false + } + } + ], + "arguments": {}, + "configurationArguments": { + "waitDuration": 1, + "waitUnit": "DAYS" + }, + "metaData": { + "isConfigured": true, + "uiType": "WAITBYDURATION" + }, + "schema": { + "arguments": { + "endDate": { + "dataType": "Date", + "isNullable": false, + "direction": "Out", + "readOnly": false, + "access": "Hidden" + }, + "waitEndDateAttributeDataBound": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "waitDefinitionId": { + "dataType": "Text", + "isNullable": false, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "waitForEventId": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "executionMode": { + "dataType": "Text", + "isNullable": false, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "startActivityKey": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "waitQueueId": { + "dataType": "LongNumber", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + } + } + } + } + ], + "triggers": [ + { + "id": "92753481-1258-49bd-8a84-921ed63bcc2e", + "key": "TRIGGER", + "name": "TRIGGER", + "description": "", + "type": "EmailAudience", + "outcomes": [], + "arguments": {}, + "configurationArguments": {}, + "metaData": { + "eventDefinitionId": "649d512b-4d08-4eca-a14e-fc7b64b4ada8", + "eventDefinitionKey": "DEAudience-2e3c73b6-48cc-2ec0-5522-48636e1a236e", + "chainType": "None", + "configurationRequired": false, + "iconUrl": "/images/icon-data-extension.svg", + "title": "Data Extension", + "entrySourceGroupConfigUrl": "jb:///data/entry/audience/entrysourcegroupconfig.json", + "sourceInteractionId": "00000000-0000-0000-0000-000000000000" + } + } + ], + "goals": [], + "exits": [], + "notifiers": [], + "stats": { + "currentPopulation": 0, + "cumulativePopulation": 0, + "metGoal": 0, + "metExitCriteria": 0, + "goalPerformance": 0 + }, + "entryMode": "NotSet", + "definitionType": "Multistep", + "channel": "", + "defaults": { + "email": ["{{Event.DEAudience-2e3c73b6-48cc-2ec0-5522-48636e1a236e.\"Email\"}}"], + "properties": { + "analyticsTracking": { + "enabled": true, + "analyticsType": "google", + "urlDomainsToTrack": [] + } + } + }, + "metaData": { + "dataSource": "ContactsModel", + "highThroughputSending": { + "email": false + } + }, + "executionMode": "Production", + "categoryId": 6298, + "status": "Published", + "definitionId": "0175b971-71a3-4d8e-98ac-48121f3fbf4f", + "scheduledStatus": "Draft" +} diff --git a/test/resources/9999999/interaction/v1/interactions/0175b971-71a3-4d8e-98ac-48121f3fbf4f/get-response.json b/test/resources/9999999/interaction/v1/interactions/0175b971-71a3-4d8e-98ac-48121f3fbf4f/get-response.json new file mode 100644 index 000000000..e8c682b12 --- /dev/null +++ b/test/resources/9999999/interaction/v1/interactions/0175b971-71a3-4d8e-98ac-48121f3fbf4f/get-response.json @@ -0,0 +1,461 @@ +{ + "id": "0175b971-71a3-4d8e-98ac-48121f3fbf4f", + "key": "testExisting_journey_Multistep", + "name": "testExisting_journey_Multistep", + "lastPublishedDate": "0001-01-01T00:00:00", + "description": "", + "version": 1, + "workflowApiVersion": 1, + "createdDate": "2024-05-04T05:54:48.027", + "modifiedDate": "2024-05-04T17:25:57.9", + "activities": [ + { + "id": "342dd0aa-a6be-401e-8614-3538800bfd7c", + "key": "MULTICRITERIADECISIONV2-1", + "name": "", + "description": "", + "type": "MULTICRITERIADECISION", + "outcomes": [ + { + "key": "default_path_1", + "next": "EMAILV2-1", + "arguments": {}, + "metaData": { + "label": "send message", + "skipI18n": true, + "isLabelFromConversion": false, + "criteriaDescription": "Email is not null" + } + }, + { + "key": "remainder_path", + "next": "WAITBYDURATION-2", + "arguments": {}, + "metaData": { + "label": null + } + } + ], + "arguments": {}, + "configurationArguments": { + "criteria": { + "default_path_1": "<FilterDefinition><ConditionSet Operator=\"AND\" ConditionSetName=\"Individual Filter Grouping\"><Condition IsEphemeralAttribute=\"true\" Key=\"Event.DEAudience-2e3c73b6-48cc-2ec0-5522-48636e1a236e.Email\" Operator=\"IsNotNull\" UiMetaData=\"{}\"><Value><![CDATA[]]></Value></Condition></ConditionSet></FilterDefinition>" + }, + "schemaVersionId": "252" + }, + "metaData": { + "isConfigured": true + }, + "schema": { + "arguments": { + "actualChoice": { + "dataType": "Number", + "isNullable": false, + "direction": "Out", + "readOnly": false, + "access": "Hidden" + }, + "filterResult": { + "dataType": "Text", + "isNullable": false, + "direction": "In", + "readOnly": true, + "access": "Hidden" + } + } + } + }, + { + "id": "7ba1e59a-6be4-46c7-b76f-4c06feb1268a", + "key": "EMAILV2-1", + "name": "my custom activity name", + "description": "", + "type": "EMAILV2", + "outcomes": [ + { + "key": "ff60a294-3804-4165-85cd-c7c19c8e3a6d", + "next": "WAITBYDURATION-1", + "arguments": {}, + "metaData": { + "invalid": false + } + } + ], + "arguments": {}, + "configurationArguments": { + "applicationExtensionKey": "jb-email-activity", + "isModified": true, + "googleAnalyticsCampaignName": "", + "triggeredSendId": "b3150cf0-6e78-e811-80d4-1402ec721c9d", + "triggeredSendKey": "testExisting_triggeredSend", + "triggeredSend": { + "id": "outdated id", + "key": "outdated key", + "autoAddSubscribers": true, + "autoUpdateSubscribers": true, + "bccEmail": "", + "ccEmail": "", + "created": { + "name": "", + "date": "" + }, + "description": "my custom description", + "domainExclusions": [], + "dynamicEmailSubject": "testExisting_ email subject", + "emailId": 808714, + "emailSubject": "testExisting_ email subject", + "exclusionFilter": "", + "isSalesforceTracking": false, + "isMultipart": true, + "isSendLogging": true, + "isStoppedOnJobError": false, + "modified": { + "name": "", + "date": "" + }, + "preHeader": "testExisting_ email preheader", + "priority": 4, + "sendClassificationId": "95da425b-a06f-e611-96fe-38eaa7142c61", + "throttleOpens": "1/1/0001 12:00:00 AM", + "throttleCloses": "1/1/0001 12:00:00 AM", + "deliveryProfileId": "163f8417-13f7-e911-a2d8-1402ec938a35", + "senderProfileId": "a75d452b-7ef4-eb11-b82d-48df37d1da95", + "isTrackingClicks": true, + "publicationListId": 15 + } + }, + "metaData": { + "category": "message", + "version": "1.0", + "icon": "https://jb-email-activity.s7.marketingcloudapps.com/img/email-icon.svg", + "iconSmall": "https://jb-email-activity.s7.marketingcloudapps.com/img/email-icon.svg", + "statsContactIcon": null, + "original_icon": "/img/email-icon.svg", + "original_iconSmall": "/img/email-icon.svg", + "sections": {}, + "isConfigured": true + }, + "schema": { + "arguments": { + "requestID": { + "dataType": "Text", + "isNullable": true, + "direction": "Out", + "readOnly": false, + "access": "Hidden" + }, + "messageKey": { + "dataType": "Text", + "isNullable": true, + "direction": "Out", + "readOnly": false, + "access": "Hidden" + }, + "activityId": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "definitionId": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": true, + "access": "Hidden" + }, + "emailSubjectDataBound": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": true, + "access": "Hidden" + }, + "contactId": { + "dataType": "Number", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "contactKey": { + "dataType": "Text", + "isNullable": false, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "emailAddress": { + "dataType": "Text", + "isNullable": false, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "sourceCustomObjectId": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "sourceCustomObjectKey": { + "dataType": "LongNumber", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "fieldType": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "eventData": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "obfuscationProperties": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "customObjectKey": { + "dataType": "LongNumber", + "isNullable": true, + "direction": "In", + "readOnly": true, + "access": "Hidden" + }, + "definitionInstanceId": { + "dataType": "Text", + "isNullable": false, + "direction": "In", + "readOnly": false, + "access": "Hidden" + } + } + } + }, + { + "id": "70572b1a-e274-4f09-a3fa-6fc0732ec52b", + "key": "WAITBYDURATION-2", + "name": "", + "description": "", + "type": "WAIT", + "outcomes": [ + { + "key": "a0908f9f-bc3c-47f7-9489-7fef5af25ce3", + "arguments": {}, + "metaData": { + "invalid": false + } + } + ], + "arguments": {}, + "configurationArguments": { + "waitDuration": 1, + "waitUnit": "DAYS" + }, + "metaData": { + "isConfigured": true, + "uiType": "WAITBYDURATION" + }, + "schema": { + "arguments": { + "endDate": { + "dataType": "Date", + "isNullable": false, + "direction": "Out", + "readOnly": false, + "access": "Hidden" + }, + "waitEndDateAttributeDataBound": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "waitDefinitionId": { + "dataType": "Text", + "isNullable": false, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "waitForEventId": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "executionMode": { + "dataType": "Text", + "isNullable": false, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "startActivityKey": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "waitQueueId": { + "dataType": "LongNumber", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + } + } + } + }, + { + "id": "e2a486cf-c85f-4543-88a2-d579cac1e0de", + "key": "WAITBYDURATION-1", + "name": "1 day", + "description": "", + "type": "WAIT", + "outcomes": [ + { + "key": "97af222a-450a-429e-8925-649b72f01ccf", + "arguments": {}, + "metaData": { + "invalid": false + } + } + ], + "arguments": {}, + "configurationArguments": { + "waitDuration": 1, + "waitUnit": "DAYS" + }, + "metaData": { + "isConfigured": true, + "uiType": "WAITBYDURATION" + }, + "schema": { + "arguments": { + "endDate": { + "dataType": "Date", + "isNullable": false, + "direction": "Out", + "readOnly": false, + "access": "Hidden" + }, + "waitEndDateAttributeDataBound": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "waitDefinitionId": { + "dataType": "Text", + "isNullable": false, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "waitForEventId": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "executionMode": { + "dataType": "Text", + "isNullable": false, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "startActivityKey": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "waitQueueId": { + "dataType": "LongNumber", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + } + } + } + } + ], + "triggers": [ + { + "id": "92753481-1258-49bd-8a84-921ed63bcc2e", + "key": "TRIGGER", + "name": "TRIGGER", + "description": "", + "type": "EmailAudience", + "outcomes": [], + "arguments": {}, + "configurationArguments": {}, + "metaData": { + "eventDefinitionId": "649d512b-4d08-4eca-a14e-fc7b64b4ada8", + "eventDefinitionKey": "DEAudience-2e3c73b6-48cc-2ec0-5522-48636e1a236e", + "chainType": "None", + "configurationRequired": false, + "iconUrl": "/images/icon-data-extension.svg", + "title": "Data Extension", + "entrySourceGroupConfigUrl": "jb:///data/entry/audience/entrysourcegroupconfig.json", + "sourceInteractionId": "00000000-0000-0000-0000-000000000000" + } + } + ], + "goals": [], + "exits": [], + "notifiers": [], + "stats": { + "currentPopulation": 0, + "cumulativePopulation": 0, + "metGoal": 0, + "metExitCriteria": 0, + "goalPerformance": 0 + }, + "entryMode": "NotSet", + "definitionType": "Multistep", + "channel": "", + "defaults": { + "email": ["{{Event.DEAudience-2e3c73b6-48cc-2ec0-5522-48636e1a236e.\"Email\"}}"], + "properties": { + "analyticsTracking": { + "enabled": true, + "analyticsType": "google", + "urlDomainsToTrack": [] + } + } + }, + "metaData": { + "dataSource": "ContactsModel", + "highThroughputSending": { + "email": false + } + }, + "executionMode": "Production", + "categoryId": 6298, + "status": "Draft", + "definitionId": "0175b971-71a3-4d8e-98ac-48121f3fbf4f", + "scheduledStatus": "Draft" +} diff --git a/test/resources/9999999/interaction/v1/interactions/3c3f4112-9b43-43ca-8a89-aa0375b2c1a2/delete-response.txt b/test/resources/9999999/interaction/v1/interactions/3c3f4112-9b43-43ca-8a89-aa0375b2c1a2/delete-response.txt new file mode 100644 index 000000000..ea0c6d67a --- /dev/null +++ b/test/resources/9999999/interaction/v1/interactions/3c3f4112-9b43-43ca-8a89-aa0375b2c1a2/delete-response.txt @@ -0,0 +1 @@ +3c3f4112-9b43-43ca-8a89-aa0375b2c1a2 \ No newline at end of file diff --git a/test/resources/9999999/interaction/v1/interactions/3c3f4112-9b43-43ca-8a89-aa0375b2c1a2/get-response.json b/test/resources/9999999/interaction/v1/interactions/3c3f4112-9b43-43ca-8a89-aa0375b2c1a2/get-response.json new file mode 100644 index 000000000..f6508f62d --- /dev/null +++ b/test/resources/9999999/interaction/v1/interactions/3c3f4112-9b43-43ca-8a89-aa0375b2c1a2/get-response.json @@ -0,0 +1,253 @@ +{ + "id": "3c3f4112-9b43-43ca-8a89-aa0375b2c1a2", + "key": "testExisting_journey_Quicksend", + "name": "testExisting_journey_Quicksend", + "lastPublishedDate": "0001-01-01T00:00:00", + "description": "", + "version": 1, + "workflowApiVersion": 1, + "createdDate": "2024-04-24T12:18:43.47", + "modifiedDate": "2024-04-24T12:19:12.803", + "activities": [ + { + "id": "e20dcaa3-a750-44cf-9ce8-42d00378b8b4", + "key": "EMAILV2-1", + "name": "testExisting_asset_mail", + "description": "", + "type": "EMAILV2", + "outcomes": [ + { + "key": "a6b9c1af-cd89-4ce8-ba4f-bd4289188dc2", + "arguments": {}, + "metaData": { + "invalid": false + } + } + ], + "arguments": {}, + "configurationArguments": { + "isModified": true, + "googleAnalyticsCampaignName": "", + "triggeredSend": { + "autoAddSubscribers": true, + "autoUpdateSubscribers": true, + "bccEmail": "%%= ContentBlockByName(\"Content Builder\\dont strip non ssjs content\") =%%", + "ccEmail": "%%= ContentBlockByKey(\"testExisting_asset_htmlblock\") =%%", + "created": {}, + "description": "my activity info text", + "domainExclusions": [ + { + "id": "5a7194ad-6602-ef11-a5c8-5cba2c702db8", + "name": "testExisting_DomainExclusion" + } + ], + "dynamicEmailSubject": "testExisting_ dynamic email subject %%= ContentBlockByKey(\"testExisting_asset_htmlblock\") =%%", + "emailId": 531213, + "emailSubject": "testExisting_ email subject %%= ContentBlockByKey(\"testExisting_asset_htmlblock\") =%%", + "exclusionFilter": "/* insert ampscript here */ %%= ContentBlockById(1295064) =%%", + "isSalesforceTracking": false, + "isMultipart": true, + "isSendLogging": true, + "isStoppedOnJobError": false, + "keyword": "", + "modified": {}, + "preHeader": "testExisting_ email preheader %%= ContentBlockByKey(\"testExisting_asset_htmlblock\") =%%", + "priority": 3, + "sendClassificationId": "95da425b-a06f-e611-96fe-38eaa7142c61", + "suppressionLists": [ + { + "id": 75520, + "name": "testExisting_suppressionList" + } + ], + "suppressTracking": true, + "throttleLimit": 0, + "throttleOpens": "1/1/0001 12:00:00 AM", + "throttleCloses": "1/1/0001 12:00:00 AM", + "deliveryProfileId": "163f8417-13f7-e911-a2d8-1402ec938a35", + "senderProfileId": "a75d452b-7ef4-eb11-b82d-48df37d1da95", + "isTrackingClicks": true, + "publicationListId": 15 + }, + "applicationExtensionKey": "jb-email-activity" + }, + "metaData": { + "category": "message", + "version": "1.0", + "icon": "https://jb-email-activity.s7.marketingcloudapps.com/img/email-icon.svg", + "iconSmall": "https://jb-email-activity.s7.marketingcloudapps.com/img/email-icon.svg", + "statsContactIcon": null, + "original_icon": "/img/email-icon.svg", + "original_iconSmall": "/img/email-icon.svg", + "sections": {}, + "isConfigured": true + }, + "schema": { + "arguments": { + "requestID": { + "dataType": "Text", + "isNullable": true, + "direction": "Out", + "readOnly": false, + "access": "Hidden" + }, + "messageKey": { + "dataType": "Text", + "isNullable": true, + "direction": "Out", + "readOnly": false, + "access": "Hidden" + }, + "activityId": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "definitionId": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": true, + "access": "Hidden" + }, + "emailSubjectDataBound": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": true, + "access": "Hidden" + }, + "contactId": { + "dataType": "Number", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "contactKey": { + "dataType": "Text", + "isNullable": false, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "emailAddress": { + "dataType": "Text", + "isNullable": false, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "sourceCustomObjectId": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "sourceCustomObjectKey": { + "dataType": "LongNumber", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "fieldType": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "eventData": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "obfuscationProperties": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "customObjectKey": { + "dataType": "LongNumber", + "isNullable": true, + "direction": "In", + "readOnly": true, + "access": "Hidden" + }, + "definitionInstanceId": { + "dataType": "Text", + "isNullable": false, + "direction": "In", + "readOnly": false, + "access": "Hidden" + } + } + } + } + ], + "triggers": [ + { + "id": "abe42b4d-736d-4d26-a8f0-ce67d410782f", + "key": "TRIGGER", + "name": "TRIGGER", + "description": "", + "type": "EmailAudience", + "outcomes": [], + "arguments": {}, + "configurationArguments": {}, + "metaData": { + "sourceInteractionId": "00000000-0000-0000-0000-000000000000", + "eventDefinitionId": "9e1995f8-951d-4019-855c-826b45e5b028", + "eventDefinitionKey": "DEAudience-11be962d-064c-83d9-2804-7d1befc10325", + "chainType": "None", + "configurationRequired": false, + "iconUrl": "/images/icon-data-extension.svg", + "title": "Data Extension", + "entrySourceGroupConfigUrl": "jb:///data/entry/audience/entrysourcegroupconfig.json" + } + } + ], + "goals": [], + "exits": [], + "notifiers": [], + "stats": { + "currentPopulation": 0, + "cumulativePopulation": 0, + "metGoal": 0, + "metExitCriteria": 0, + "goalPerformance": 0 + }, + "entryMode": "MultipleEntries", + "definitionType": "Quicksend", + "channel": "email", + "defaults": { + "email": ["{{Event.DEAudience-11be962d-064c-83d9-2804-7d1befc10325.\"Email\"}}"], + "properties": { + "analyticsTracking": { + "enabled": true, + "analyticsType": "google", + "urlDomainsToTrack": [] + } + } + }, + "metaData": { + "dataSource": "ContactsModel", + "isScheduleSet": true, + "highThroughputSending": { + "email": false + } + }, + "executionMode": "Production", + "categoryId": 6298, + "status": "Draft", + "definitionId": "3c3f4112-9b43-43ca-8a89-aa0375b2c1a2", + "scheduledStatus": "Draft" +} diff --git a/test/resources/9999999/interaction/v1/interactions/dsfdsafdsa-922c-4568-85a5-e5cc77efc3be/audit/all/get-response-versionNumber=1.json b/test/resources/9999999/interaction/v1/interactions/dsfdsafdsa-922c-4568-85a5-e5cc77efc3be/audit/all/get-response-versionNumber=1.json new file mode 100644 index 000000000..7fc534544 --- /dev/null +++ b/test/resources/9999999/interaction/v1/interactions/dsfdsafdsa-922c-4568-85a5-e5cc77efc3be/audit/all/get-response-versionNumber=1.json @@ -0,0 +1,38 @@ +{ + "count": 1, + "page": 1, + "pageSize": 50, + "links": {}, + "items": [ + { + "id": "dsfdsafdsa-922c-4568-85a5-e5cc77efc3be", + "action": "Delete", + "user": { + "name": "joern.berkefeld app user", + "userId": 710420432 + }, + "timeStamp": "2024-10-02T09:37:07.99", + "key": "testExisting_temail", + "versionNumber": 1, + "originalDefinitionId": "dsfdsafdsa-922c-4568-85a5-e5cc77efc3be", + "name": "testExisting_temail", + "description": "", + "executionMode": "Production" + }, + { + "id": "dsfdsafdsa-922c-4568-85a5-e5cc77efc3be", + "action": "Create", + "user": { + "name": "joern.berkefeld app user", + "userId": 710420432 + }, + "timeStamp": "2024-10-01T07:07:51.967", + "key": "testExisting_temail", + "versionNumber": 1, + "originalDefinitionId": "dsfdsafdsa-922c-4568-85a5-e5cc77efc3be", + "name": "testExisting_temail", + "description": "", + "executionMode": "Production" + } + ] +} diff --git a/test/resources/9999999/interaction/v1/interactions/dsfdsafdsa-922c-4568-85a5-e5cc77efc3be/audit/all/get-response-versionNumber=2.json b/test/resources/9999999/interaction/v1/interactions/dsfdsafdsa-922c-4568-85a5-e5cc77efc3be/audit/all/get-response-versionNumber=2.json new file mode 100644 index 000000000..72d4533d7 --- /dev/null +++ b/test/resources/9999999/interaction/v1/interactions/dsfdsafdsa-922c-4568-85a5-e5cc77efc3be/audit/all/get-response-versionNumber=2.json @@ -0,0 +1,53 @@ +{ + "count": 3, + "page": 1, + "pageSize": 50, + "links": {}, + "items": [ + { + "id": "dsfdsafdsa-922c-4568-85a5-e5cc77efc3be", + "action": "Modify", + "user": { + "name": "Jörn Berkefeld", + "userId": 710420418 + }, + "timeStamp": "2024-10-04T09:17:51.967", + "key": "testExisting_temail", + "versionNumber": 2, + "originalDefinitionId": "dsfdsafdsa-922c-4568-85a5-e5cc77efc3be", + "name": "testExisting_temail", + "description": "", + "executionMode": "Production" + }, + { + "id": "dsfdsafdsa-922c-4568-85a5-e5cc77efc3be", + "action": "Modify", + "user": { + "name": "joern.berkefeld app user", + "userId": 710420432 + }, + "timeStamp": "2024-10-04T07:07:51.967", + "key": "testExisting_temail", + "versionNumber": 2, + "originalDefinitionId": "dsfdsafdsa-922c-4568-85a5-e5cc77efc3be", + "name": "testExisting_temail", + "description": "", + "executionMode": "Production" + }, + { + "id": "dsfdsafdsa-922c-4568-85a5-e5cc77efc3be", + "action": "Create", + "user": { + "name": "joern.berkefeld app user", + "userId": 710420432 + }, + "timeStamp": "2024-10-03T07:07:51.967", + "key": "testExisting_temail", + "versionNumber": 2, + "originalDefinitionId": "dsfdsafdsa-922c-4568-85a5-e5cc77efc3be", + "name": "testExisting_temail", + "description": "", + "executionMode": "Production" + } + ] +} diff --git a/test/resources/9999999/interaction/v1/interactions/dsfdsafdsa-922c-4568-85a5-e5cc77efc3be/delete-response.txt b/test/resources/9999999/interaction/v1/interactions/dsfdsafdsa-922c-4568-85a5-e5cc77efc3be/delete-response.txt new file mode 100644 index 000000000..85c35b04a --- /dev/null +++ b/test/resources/9999999/interaction/v1/interactions/dsfdsafdsa-922c-4568-85a5-e5cc77efc3be/delete-response.txt @@ -0,0 +1 @@ +dsfdsafdsa-922c-4568-85a5-e5cc77efc3be \ No newline at end of file diff --git a/test/resources/9999999/interaction/v1/interactions/get-response-status=Published.json b/test/resources/9999999/interaction/v1/interactions/get-response-status=Published.json new file mode 100644 index 000000000..9f3018518 --- /dev/null +++ b/test/resources/9999999/interaction/v1/interactions/get-response-status=Published.json @@ -0,0 +1,40 @@ +{ + "count": 1, + "page": 1, + "pageSize": 500, + "links": {}, + "items": [ + { + "id": "dsfdsafdsa-922c-4568-85a5-e5cc77efc3be", + "key": "testExisting_temail", + "name": "testExisting_temail", + "lastPublishedDate": "0001-01-01T00:00:00", + "description": "", + "version": 2, + "workflowApiVersion": 1, + "createdDate": "2022-03-24T02:20:32.74", + "modifiedDate": "2022-03-24T02:20:40.45", + "goals": [], + "exits": [], + "notifiers": [], + "entryMode": "MultipleEntries", + "definitionType": "Transactional", + "channel": "email", + "defaults": { + "properties": { + "analyticsTracking": { + "enabled": false, + "analyticsType": "google", + "urlDomainsToTrack": [] + } + } + }, + "metaData": {}, + "executionMode": "Production", + "categoryId": 6298, + "status": "Published", + "scheduledStatus": "Draft", + "definitionId": "dsfdsafdsa-922c-4568-85a5-e5cc77efc3be" + } + ] +} diff --git a/test/resources/9999999/interaction/v1/interactions/get-response.json b/test/resources/9999999/interaction/v1/interactions/get-response.json new file mode 100644 index 000000000..00f2e3228 --- /dev/null +++ b/test/resources/9999999/interaction/v1/interactions/get-response.json @@ -0,0 +1,211 @@ +{ + "count": 3, + "page": 1, + "pageSize": 500, + "links": {}, + "items": [ + { + "id": "3c3f4112-9b43-43ca-8a89-aa0375b2c1a2", + "key": "testExisting_journey_Quicksend", + "name": "testExisting_journey_Quicksend", + "lastPublishedDate": "0001-01-01T00:00:00", + "description": "", + "version": 1, + "workflowApiVersion": 1, + "createdDate": "2024-04-24T12:18:43.47", + "modifiedDate": "2024-04-24T12:19:12.803", + "goals": [], + "exits": [], + "notifiers": [], + "stats": { + "currentPopulation": 0, + "cumulativePopulation": 0, + "metGoal": 0, + "metExitCriteria": 0, + "goalPerformance": 0 + }, + "entryMode": "MultipleEntries", + "definitionType": "Quicksend", + "channel": "email", + "defaults": { + "email": [ + "{{Event.DEAudience-11be962d-064c-83d9-2804-7d1befc10325.\"Email\"}}" + ], + "properties": { + "analyticsTracking": { + "enabled": true, + "analyticsType": "google", + "urlDomainsToTrack": [] + } + } + }, + "metaData": { + "dataSource": "ContactsModel", + "isScheduleSet": true, + "highThroughputSending": { + "email": false + } + }, + "executionMode": "Production", + "categoryId": 6298, + "status": "Draft", + "definitionId": "3c3f4112-9b43-43ca-8a89-aa0375b2c1a2", + "scheduledStatus": "Draft" + }, + { + "id": "0175b971-71a3-4d8e-98ac-48121f3fbf4f", + "key": "testExisting_journey_Multistep", + "name": "testExisting_journey_Multistep", + "lastPublishedDate": "0001-01-01T00:00:00", + "description": "", + "version": 3, + "workflowApiVersion": 1, + "createdDate": "2024-05-04T05:54:48.027", + "modifiedDate": "2024-05-04T05:54:48.027", + "goals": [], + "exits": [], + "notifiers": [], + "stats": { + "currentPopulation": 0, + "cumulativePopulation": 0, + "metGoal": 0, + "metExitCriteria": 0, + "goalPerformance": 0 + }, + "entryMode": "NotSet", + "definitionType": "Multistep", + "channel": "", + "defaults": { + "email": [ + "{{Event.DEAudience-2e3c73b6-48cc-2ec0-5522-48636e1a236e.\"Email\"}}" + ], + "properties": { + "analyticsTracking": { + "enabled": true, + "analyticsType": "google", + "urlDomainsToTrack": [] + } + } + }, + "metaData": { + "dataSource": "ContactsModel", + "highThroughputSending": { + "email": false + } + }, + "executionMode": "Production", + "categoryId": 6298, + "status": "Draft", + "definitionId": "0175b971-71a3-4d8e-98ac-48121f3fbf4f", + "scheduledStatus": "Draft" + }, + { + "id": "dsfdsafdsa-922c-4568-85a5-e5cc77efc3be", + "key": "testExisting_temail", + "name": "testExisting_temail", + "lastPublishedDate": "0001-01-01T00:00:00", + "description": "", + "version": 2, + "workflowApiVersion": 1, + "createdDate": "2022-03-24T02:20:32.74", + "modifiedDate": "2022-03-24T02:20:40.45", + "goals": [], + "exits": [], + "notifiers": [], + "entryMode": "MultipleEntries", + "definitionType": "Transactional", + "channel": "email", + "defaults": { + "properties": { + "analyticsTracking": { + "enabled": false, + "analyticsType": "google", + "urlDomainsToTrack": [] + } + } + }, + "metaData": {}, + "executionMode": "Production", + "categoryId": 6298, + "status": "Published", + "scheduledStatus": "Draft", + "definitionId": "dsfdsafdsa-922c-4568-85a5-e5cc77efc3be" + }, + { + "id": "d4a900fe-3a8f-4cc5-9a49-81286e3e2cd2", + "key": "testExisting_temail_notPublished", + "name": "testExisting_temail_notPublished", + "lastPublishedDate": "0001-01-01T00:00:00", + "description": "", + "version": 1, + "workflowApiVersion": 1, + "createdDate": "2024-08-23T00:29:39.55", + "modifiedDate": "2024-08-23T00:29:39.55", + "goals": [], + "exits": [], + "notifiers": [], + "stats": { + "currentPopulation": 0, + "cumulativePopulation": 0, + "metGoal": 0, + "metExitCriteria": 0, + "goalPerformance": 0 + }, + "entryMode": "MultipleEntries", + "definitionType": "Transactional", + "channel": "email", + "defaults": { + "properties": {} + }, + "metaData": { + "dataSource": "ContactsModel", + "highThroughputSending": { + "email": false + } + }, + "executionMode": "Production", + "categoryId": 6298, + "status": "Draft", + "definitionId": "d4a900fe-3a8f-4cc5-9a49-81286e3e2cd2", + "scheduledStatus": "Draft" + }, + { + "key": "testExisting_journey_updatecontact", + "name": "testExisting_journey_updatecontact", + "lastPublishedDate": "0001-01-01T00:00:00", + "description": "", + "version": 1, + "workflowApiVersion": 1, + "createdDate": "2024-05-04T05:54:48.027", + "modifiedDate": "2024-05-04T17:25:57.9", + "goals": [], + "exits": [], + "notifiers": [], + "entryMode": "NotSet", + "definitionType": "Multistep", + "channel": "", + "defaults": { + "email": [ + "{{Event.DEAudience-2e3c73b6-48cc-2ec0-5522-48636e1a236e.\"Email\"}}" + ], + "properties": { + "analyticsTracking": { + "enabled": true, + "analyticsType": "google", + "urlDomainsToTrack": [] + } + } + }, + "metaData": { + "dataSource": "ContactsModel", + "highThroughputSending": { + "email": false + } + }, + "executionMode": "Production", + "status": "Draft", + "scheduledStatus": "Draft", + "r__folder_Path": "my journeys" + } + ] +} \ No newline at end of file diff --git a/test/resources/9999999/interaction/v1/interactions/key_testExisting_journey_Multistep/get-response-versionNumber=1.json b/test/resources/9999999/interaction/v1/interactions/key_testExisting_journey_Multistep/get-response-versionNumber=1.json new file mode 100644 index 000000000..b3a10af04 --- /dev/null +++ b/test/resources/9999999/interaction/v1/interactions/key_testExisting_journey_Multistep/get-response-versionNumber=1.json @@ -0,0 +1,461 @@ +{ + "id": "0175b971-71a3-4d8e-98ac-48121f3fbf4f", + "key": "testExisting_journey_Multistep", + "name": "testExisting_journey_Multistep", + "lastPublishedDate": "0001-01-01T00:00:00", + "description": "", + "version": 1, + "workflowApiVersion": 1, + "createdDate": "2024-05-04T05:54:48.027", + "modifiedDate": "2024-05-04T17:25:57.9", + "activities": [ + { + "id": "342dd0aa-a6be-401e-8614-3538800bfd7c", + "key": "MULTICRITERIADECISIONV2-1", + "name": "", + "description": "", + "type": "MULTICRITERIADECISION", + "outcomes": [ + { + "key": "default_path_1", + "next": "EMAILV2-1", + "arguments": {}, + "metaData": { + "label": "send message", + "skipI18n": true, + "isLabelFromConversion": false, + "criteriaDescription": "Email is not null" + } + }, + { + "key": "remainder_path", + "next": "WAITBYDURATION-2", + "arguments": {}, + "metaData": { + "label": null + } + } + ], + "arguments": {}, + "configurationArguments": { + "criteria": { + "default_path_1": "<FilterDefinition><ConditionSet Operator=\"AND\" ConditionSetName=\"Individual Filter Grouping\"><Condition IsEphemeralAttribute=\"true\" Key=\"Event.DEAudience-2e3c73b6-48cc-2ec0-5522-48636e1a236e.Email\" Operator=\"IsNotNull\" UiMetaData=\"{}\"><Value><![CDATA[]]></Value></Condition></ConditionSet></FilterDefinition>" + }, + "schemaVersionId": "252" + }, + "metaData": { + "isConfigured": true + }, + "schema": { + "arguments": { + "actualChoice": { + "dataType": "Number", + "isNullable": false, + "direction": "Out", + "readOnly": false, + "access": "Hidden" + }, + "filterResult": { + "dataType": "Text", + "isNullable": false, + "direction": "In", + "readOnly": true, + "access": "Hidden" + } + } + } + }, + { + "id": "7ba1e59a-6be4-46c7-b76f-4c06feb1268a", + "key": "EMAILV2-1", + "name": "my custom activity name", + "description": "", + "type": "EMAILV2", + "outcomes": [ + { + "key": "ff60a294-3804-4165-85cd-c7c19c8e3a6d", + "next": "WAITBYDURATION-1", + "arguments": {}, + "metaData": { + "invalid": false + } + } + ], + "arguments": {}, + "configurationArguments": { + "applicationExtensionKey": "jb-email-activity", + "isModified": true, + "googleAnalyticsCampaignName": "", + "triggeredSendId": "b3150cf0-6e78-e811-80d4-1402ec721c9d", + "triggeredSendKey": "wrong key", + "triggeredSend": { + "id": "outdated id", + "key": "outdated key", + "autoAddSubscribers": true, + "autoUpdateSubscribers": true, + "bccEmail": "", + "ccEmail": "", + "created": { + "name": "", + "date": "" + }, + "description": "my custom description", + "domainExclusions": [], + "dynamicEmailSubject": "testExisting_ email subject", + "emailId": 808714, + "emailSubject": "testExisting_ email subject", + "exclusionFilter": "", + "isSalesforceTracking": false, + "isMultipart": true, + "isSendLogging": true, + "isStoppedOnJobError": false, + "modified": { + "name": "", + "date": "" + }, + "preHeader": "testExisting_ email preheader", + "priority": 4, + "sendClassificationId": "95da425b-a06f-e611-96fe-38eaa7142c61", + "throttleOpens": "1/1/0001 12:00:00 AM", + "throttleCloses": "1/1/0001 12:00:00 AM", + "deliveryProfileId": "163f8417-13f7-e911-a2d8-1402ec938a35", + "senderProfileId": "a75d452b-7ef4-eb11-b82d-48df37d1da95", + "isTrackingClicks": true, + "publicationListId": 15 + } + }, + "metaData": { + "category": "message", + "version": "1.0", + "icon": "https://jb-email-activity.s7.marketingcloudapps.com/img/email-icon.svg", + "iconSmall": "https://jb-email-activity.s7.marketingcloudapps.com/img/email-icon.svg", + "statsContactIcon": null, + "original_icon": "/img/email-icon.svg", + "original_iconSmall": "/img/email-icon.svg", + "sections": {}, + "isConfigured": true + }, + "schema": { + "arguments": { + "requestID": { + "dataType": "Text", + "isNullable": true, + "direction": "Out", + "readOnly": false, + "access": "Hidden" + }, + "messageKey": { + "dataType": "Text", + "isNullable": true, + "direction": "Out", + "readOnly": false, + "access": "Hidden" + }, + "activityId": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "definitionId": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": true, + "access": "Hidden" + }, + "emailSubjectDataBound": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": true, + "access": "Hidden" + }, + "contactId": { + "dataType": "Number", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "contactKey": { + "dataType": "Text", + "isNullable": false, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "emailAddress": { + "dataType": "Text", + "isNullable": false, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "sourceCustomObjectId": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "sourceCustomObjectKey": { + "dataType": "LongNumber", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "fieldType": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "eventData": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "obfuscationProperties": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "customObjectKey": { + "dataType": "LongNumber", + "isNullable": true, + "direction": "In", + "readOnly": true, + "access": "Hidden" + }, + "definitionInstanceId": { + "dataType": "Text", + "isNullable": false, + "direction": "In", + "readOnly": false, + "access": "Hidden" + } + } + } + }, + { + "id": "70572b1a-e274-4f09-a3fa-6fc0732ec52b", + "key": "WAITBYDURATION-2", + "name": "", + "description": "", + "type": "WAIT", + "outcomes": [ + { + "key": "a0908f9f-bc3c-47f7-9489-7fef5af25ce3", + "arguments": {}, + "metaData": { + "invalid": false + } + } + ], + "arguments": {}, + "configurationArguments": { + "waitDuration": 1, + "waitUnit": "DAYS" + }, + "metaData": { + "isConfigured": true, + "uiType": "WAITBYDURATION" + }, + "schema": { + "arguments": { + "endDate": { + "dataType": "Date", + "isNullable": false, + "direction": "Out", + "readOnly": false, + "access": "Hidden" + }, + "waitEndDateAttributeDataBound": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "waitDefinitionId": { + "dataType": "Text", + "isNullable": false, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "waitForEventId": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "executionMode": { + "dataType": "Text", + "isNullable": false, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "startActivityKey": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "waitQueueId": { + "dataType": "LongNumber", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + } + } + } + }, + { + "id": "e2a486cf-c85f-4543-88a2-d579cac1e0de", + "key": "WAITBYDURATION-1", + "name": "1 day", + "description": "", + "type": "WAIT", + "outcomes": [ + { + "key": "97af222a-450a-429e-8925-649b72f01ccf", + "arguments": {}, + "metaData": { + "invalid": false + } + } + ], + "arguments": {}, + "configurationArguments": { + "waitDuration": 1, + "waitUnit": "DAYS" + }, + "metaData": { + "isConfigured": true, + "uiType": "WAITBYDURATION" + }, + "schema": { + "arguments": { + "endDate": { + "dataType": "Date", + "isNullable": false, + "direction": "Out", + "readOnly": false, + "access": "Hidden" + }, + "waitEndDateAttributeDataBound": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "waitDefinitionId": { + "dataType": "Text", + "isNullable": false, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "waitForEventId": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "executionMode": { + "dataType": "Text", + "isNullable": false, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "startActivityKey": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "waitQueueId": { + "dataType": "LongNumber", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + } + } + } + } + ], + "triggers": [ + { + "id": "92753481-1258-49bd-8a84-921ed63bcc2e", + "key": "TRIGGER", + "name": "TRIGGER", + "description": "", + "type": "EmailAudience", + "outcomes": [], + "arguments": {}, + "configurationArguments": {}, + "metaData": { + "eventDefinitionId": "649d512b-4d08-4eca-a14e-fc7b64b4ada8", + "eventDefinitionKey": "DEAudience-2e3c73b6-48cc-2ec0-5522-48636e1a236e", + "chainType": "None", + "configurationRequired": false, + "iconUrl": "/images/icon-data-extension.svg", + "title": "Data Extension", + "entrySourceGroupConfigUrl": "jb:///data/entry/audience/entrysourcegroupconfig.json", + "sourceInteractionId": "00000000-0000-0000-0000-000000000000" + } + } + ], + "goals": [], + "exits": [], + "notifiers": [], + "stats": { + "currentPopulation": 0, + "cumulativePopulation": 0, + "metGoal": 0, + "metExitCriteria": 0, + "goalPerformance": 0 + }, + "entryMode": "NotSet", + "definitionType": "Multistep", + "channel": "", + "defaults": { + "email": ["{{Event.DEAudience-2e3c73b6-48cc-2ec0-5522-48636e1a236e.\"Email\"}}"], + "properties": { + "analyticsTracking": { + "enabled": true, + "analyticsType": "google", + "urlDomainsToTrack": [] + } + } + }, + "metaData": { + "dataSource": "ContactsModel", + "highThroughputSending": { + "email": false + } + }, + "executionMode": "Production", + "categoryId": 6298, + "status": "Draft", + "definitionId": "0175b971-71a3-4d8e-98ac-48121f3fbf4f", + "scheduledStatus": "Draft" +} diff --git a/test/resources/9999999/interaction/v1/interactions/key_testExisting_journey_Multistep/get-response.json b/test/resources/9999999/interaction/v1/interactions/key_testExisting_journey_Multistep/get-response.json new file mode 100644 index 000000000..b3a10af04 --- /dev/null +++ b/test/resources/9999999/interaction/v1/interactions/key_testExisting_journey_Multistep/get-response.json @@ -0,0 +1,461 @@ +{ + "id": "0175b971-71a3-4d8e-98ac-48121f3fbf4f", + "key": "testExisting_journey_Multistep", + "name": "testExisting_journey_Multistep", + "lastPublishedDate": "0001-01-01T00:00:00", + "description": "", + "version": 1, + "workflowApiVersion": 1, + "createdDate": "2024-05-04T05:54:48.027", + "modifiedDate": "2024-05-04T17:25:57.9", + "activities": [ + { + "id": "342dd0aa-a6be-401e-8614-3538800bfd7c", + "key": "MULTICRITERIADECISIONV2-1", + "name": "", + "description": "", + "type": "MULTICRITERIADECISION", + "outcomes": [ + { + "key": "default_path_1", + "next": "EMAILV2-1", + "arguments": {}, + "metaData": { + "label": "send message", + "skipI18n": true, + "isLabelFromConversion": false, + "criteriaDescription": "Email is not null" + } + }, + { + "key": "remainder_path", + "next": "WAITBYDURATION-2", + "arguments": {}, + "metaData": { + "label": null + } + } + ], + "arguments": {}, + "configurationArguments": { + "criteria": { + "default_path_1": "<FilterDefinition><ConditionSet Operator=\"AND\" ConditionSetName=\"Individual Filter Grouping\"><Condition IsEphemeralAttribute=\"true\" Key=\"Event.DEAudience-2e3c73b6-48cc-2ec0-5522-48636e1a236e.Email\" Operator=\"IsNotNull\" UiMetaData=\"{}\"><Value><![CDATA[]]></Value></Condition></ConditionSet></FilterDefinition>" + }, + "schemaVersionId": "252" + }, + "metaData": { + "isConfigured": true + }, + "schema": { + "arguments": { + "actualChoice": { + "dataType": "Number", + "isNullable": false, + "direction": "Out", + "readOnly": false, + "access": "Hidden" + }, + "filterResult": { + "dataType": "Text", + "isNullable": false, + "direction": "In", + "readOnly": true, + "access": "Hidden" + } + } + } + }, + { + "id": "7ba1e59a-6be4-46c7-b76f-4c06feb1268a", + "key": "EMAILV2-1", + "name": "my custom activity name", + "description": "", + "type": "EMAILV2", + "outcomes": [ + { + "key": "ff60a294-3804-4165-85cd-c7c19c8e3a6d", + "next": "WAITBYDURATION-1", + "arguments": {}, + "metaData": { + "invalid": false + } + } + ], + "arguments": {}, + "configurationArguments": { + "applicationExtensionKey": "jb-email-activity", + "isModified": true, + "googleAnalyticsCampaignName": "", + "triggeredSendId": "b3150cf0-6e78-e811-80d4-1402ec721c9d", + "triggeredSendKey": "wrong key", + "triggeredSend": { + "id": "outdated id", + "key": "outdated key", + "autoAddSubscribers": true, + "autoUpdateSubscribers": true, + "bccEmail": "", + "ccEmail": "", + "created": { + "name": "", + "date": "" + }, + "description": "my custom description", + "domainExclusions": [], + "dynamicEmailSubject": "testExisting_ email subject", + "emailId": 808714, + "emailSubject": "testExisting_ email subject", + "exclusionFilter": "", + "isSalesforceTracking": false, + "isMultipart": true, + "isSendLogging": true, + "isStoppedOnJobError": false, + "modified": { + "name": "", + "date": "" + }, + "preHeader": "testExisting_ email preheader", + "priority": 4, + "sendClassificationId": "95da425b-a06f-e611-96fe-38eaa7142c61", + "throttleOpens": "1/1/0001 12:00:00 AM", + "throttleCloses": "1/1/0001 12:00:00 AM", + "deliveryProfileId": "163f8417-13f7-e911-a2d8-1402ec938a35", + "senderProfileId": "a75d452b-7ef4-eb11-b82d-48df37d1da95", + "isTrackingClicks": true, + "publicationListId": 15 + } + }, + "metaData": { + "category": "message", + "version": "1.0", + "icon": "https://jb-email-activity.s7.marketingcloudapps.com/img/email-icon.svg", + "iconSmall": "https://jb-email-activity.s7.marketingcloudapps.com/img/email-icon.svg", + "statsContactIcon": null, + "original_icon": "/img/email-icon.svg", + "original_iconSmall": "/img/email-icon.svg", + "sections": {}, + "isConfigured": true + }, + "schema": { + "arguments": { + "requestID": { + "dataType": "Text", + "isNullable": true, + "direction": "Out", + "readOnly": false, + "access": "Hidden" + }, + "messageKey": { + "dataType": "Text", + "isNullable": true, + "direction": "Out", + "readOnly": false, + "access": "Hidden" + }, + "activityId": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "definitionId": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": true, + "access": "Hidden" + }, + "emailSubjectDataBound": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": true, + "access": "Hidden" + }, + "contactId": { + "dataType": "Number", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "contactKey": { + "dataType": "Text", + "isNullable": false, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "emailAddress": { + "dataType": "Text", + "isNullable": false, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "sourceCustomObjectId": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "sourceCustomObjectKey": { + "dataType": "LongNumber", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "fieldType": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "eventData": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "obfuscationProperties": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "customObjectKey": { + "dataType": "LongNumber", + "isNullable": true, + "direction": "In", + "readOnly": true, + "access": "Hidden" + }, + "definitionInstanceId": { + "dataType": "Text", + "isNullable": false, + "direction": "In", + "readOnly": false, + "access": "Hidden" + } + } + } + }, + { + "id": "70572b1a-e274-4f09-a3fa-6fc0732ec52b", + "key": "WAITBYDURATION-2", + "name": "", + "description": "", + "type": "WAIT", + "outcomes": [ + { + "key": "a0908f9f-bc3c-47f7-9489-7fef5af25ce3", + "arguments": {}, + "metaData": { + "invalid": false + } + } + ], + "arguments": {}, + "configurationArguments": { + "waitDuration": 1, + "waitUnit": "DAYS" + }, + "metaData": { + "isConfigured": true, + "uiType": "WAITBYDURATION" + }, + "schema": { + "arguments": { + "endDate": { + "dataType": "Date", + "isNullable": false, + "direction": "Out", + "readOnly": false, + "access": "Hidden" + }, + "waitEndDateAttributeDataBound": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "waitDefinitionId": { + "dataType": "Text", + "isNullable": false, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "waitForEventId": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "executionMode": { + "dataType": "Text", + "isNullable": false, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "startActivityKey": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "waitQueueId": { + "dataType": "LongNumber", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + } + } + } + }, + { + "id": "e2a486cf-c85f-4543-88a2-d579cac1e0de", + "key": "WAITBYDURATION-1", + "name": "1 day", + "description": "", + "type": "WAIT", + "outcomes": [ + { + "key": "97af222a-450a-429e-8925-649b72f01ccf", + "arguments": {}, + "metaData": { + "invalid": false + } + } + ], + "arguments": {}, + "configurationArguments": { + "waitDuration": 1, + "waitUnit": "DAYS" + }, + "metaData": { + "isConfigured": true, + "uiType": "WAITBYDURATION" + }, + "schema": { + "arguments": { + "endDate": { + "dataType": "Date", + "isNullable": false, + "direction": "Out", + "readOnly": false, + "access": "Hidden" + }, + "waitEndDateAttributeDataBound": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "waitDefinitionId": { + "dataType": "Text", + "isNullable": false, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "waitForEventId": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "executionMode": { + "dataType": "Text", + "isNullable": false, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "startActivityKey": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "waitQueueId": { + "dataType": "LongNumber", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + } + } + } + } + ], + "triggers": [ + { + "id": "92753481-1258-49bd-8a84-921ed63bcc2e", + "key": "TRIGGER", + "name": "TRIGGER", + "description": "", + "type": "EmailAudience", + "outcomes": [], + "arguments": {}, + "configurationArguments": {}, + "metaData": { + "eventDefinitionId": "649d512b-4d08-4eca-a14e-fc7b64b4ada8", + "eventDefinitionKey": "DEAudience-2e3c73b6-48cc-2ec0-5522-48636e1a236e", + "chainType": "None", + "configurationRequired": false, + "iconUrl": "/images/icon-data-extension.svg", + "title": "Data Extension", + "entrySourceGroupConfigUrl": "jb:///data/entry/audience/entrysourcegroupconfig.json", + "sourceInteractionId": "00000000-0000-0000-0000-000000000000" + } + } + ], + "goals": [], + "exits": [], + "notifiers": [], + "stats": { + "currentPopulation": 0, + "cumulativePopulation": 0, + "metGoal": 0, + "metExitCriteria": 0, + "goalPerformance": 0 + }, + "entryMode": "NotSet", + "definitionType": "Multistep", + "channel": "", + "defaults": { + "email": ["{{Event.DEAudience-2e3c73b6-48cc-2ec0-5522-48636e1a236e.\"Email\"}}"], + "properties": { + "analyticsTracking": { + "enabled": true, + "analyticsType": "google", + "urlDomainsToTrack": [] + } + } + }, + "metaData": { + "dataSource": "ContactsModel", + "highThroughputSending": { + "email": false + } + }, + "executionMode": "Production", + "categoryId": 6298, + "status": "Draft", + "definitionId": "0175b971-71a3-4d8e-98ac-48121f3fbf4f", + "scheduledStatus": "Draft" +} diff --git a/test/resources/9999999/interaction/v1/interactions/key_testExisting_journey_Multistep/put-response.json b/test/resources/9999999/interaction/v1/interactions/key_testExisting_journey_Multistep/put-response.json new file mode 100644 index 000000000..2ad2f842e --- /dev/null +++ b/test/resources/9999999/interaction/v1/interactions/key_testExisting_journey_Multistep/put-response.json @@ -0,0 +1,461 @@ +{ + "id": "0175b971-71a3-4d8e-98ac-48121f3fbf4f", + "key": "testExisting_journey_Multistep", + "name": "testExisting_journey_Multistep", + "lastPublishedDate": "0001-01-01T00:00:00", + "description": "", + "version": 1, + "workflowApiVersion": 1, + "createdDate": "0001-01-01T00:00:00", + "modifiedDate": "2024-05-04T17:25:57.9", + "activities": [ + { + "id": "342dd0aa-a6be-401e-8614-3538800bfd7c", + "key": "MULTICRITERIADECISIONV2-1", + "name": "", + "description": "", + "type": "MULTICRITERIADECISION", + "outcomes": [ + { + "key": "default_path_1", + "next": "EMAILV2-1", + "arguments": {}, + "metaData": { + "label": "send message", + "skipI18n": true, + "isLabelFromConversion": false, + "criteriaDescription": "Email is not null" + } + }, + { + "key": "remainder_path", + "next": "WAITBYDURATION-2", + "arguments": {}, + "metaData": { + "label": null + } + } + ], + "arguments": {}, + "configurationArguments": { + "criteria": { + "default_path_1": "<FilterDefinition><ConditionSet Operator=\"AND\" ConditionSetName=\"Individual Filter Grouping\"><Condition IsEphemeralAttribute=\"true\" Key=\"Event.DEAudience-2e3c73b6-48cc-2ec0-5522-48636e1a236e.Email\" Operator=\"IsNotNull\" UiMetaData=\"{}\"><Value><![CDATA[]]></Value></Condition></ConditionSet></FilterDefinition>" + }, + "schemaVersionId": "252" + }, + "metaData": { + "isConfigured": true + }, + "schema": { + "arguments": { + "actualChoice": { + "dataType": "Number", + "isNullable": false, + "direction": "Out", + "readOnly": false, + "access": "Hidden" + }, + "filterResult": { + "dataType": "Text", + "isNullable": false, + "direction": "In", + "readOnly": true, + "access": "Hidden" + } + } + } + }, + { + "id": "7ba1e59a-6be4-46c7-b76f-4c06feb1268a", + "key": "EMAILV2-1", + "name": "my custom activity name", + "description": "", + "type": "EMAILV2", + "outcomes": [ + { + "key": "ff60a294-3804-4165-85cd-c7c19c8e3a6d", + "next": "WAITBYDURATION-1", + "arguments": {}, + "metaData": { + "invalid": false + } + } + ], + "arguments": {}, + "configurationArguments": { + "applicationExtensionKey": "jb-email-activity", + "isModified": true, + "googleAnalyticsCampaignName": "", + "triggeredSendId": "b3150cf0-6e78-e811-80d4-1402ec721c9d", + "triggeredSendKey": "wrong key", + "triggeredSend": { + "id": "outdated id", + "key": "outdated key", + "autoAddSubscribers": true, + "autoUpdateSubscribers": true, + "bccEmail": "", + "ccEmail": "", + "created": { + "name": "", + "date": "" + }, + "description": "my custom description", + "domainExclusions": [], + "dynamicEmailSubject": "testExisting_ email subject", + "emailId": 808714, + "emailSubject": "testExisting_ email subject", + "exclusionFilter": "", + "isSalesforceTracking": false, + "isMultipart": true, + "isSendLogging": true, + "isStoppedOnJobError": false, + "modified": { + "name": "", + "date": "" + }, + "preHeader": "testExisting_ email preheader", + "priority": 4, + "sendClassificationId": "95da425b-a06f-e611-96fe-38eaa7142c61", + "throttleOpens": "1/1/0001 12:00:00 AM", + "throttleCloses": "1/1/0001 12:00:00 AM", + "deliveryProfileId": "163f8417-13f7-e911-a2d8-1402ec938a35", + "senderProfileId": "a75d452b-7ef4-eb11-b82d-48df37d1da95", + "isTrackingClicks": true, + "publicationListId": 15 + } + }, + "metaData": { + "category": "message", + "version": "1.0", + "icon": "https://jb-email-activity.s7.marketingcloudapps.com/img/email-icon.svg", + "iconSmall": "https://jb-email-activity.s7.marketingcloudapps.com/img/email-icon.svg", + "statsContactIcon": null, + "original_icon": "/img/email-icon.svg", + "original_iconSmall": "/img/email-icon.svg", + "sections": {}, + "isConfigured": true + }, + "schema": { + "arguments": { + "requestID": { + "dataType": "Text", + "isNullable": true, + "direction": "Out", + "readOnly": false, + "access": "Hidden" + }, + "messageKey": { + "dataType": "Text", + "isNullable": true, + "direction": "Out", + "readOnly": false, + "access": "Hidden" + }, + "activityId": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "definitionId": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": true, + "access": "Hidden" + }, + "emailSubjectDataBound": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": true, + "access": "Hidden" + }, + "contactId": { + "dataType": "Number", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "contactKey": { + "dataType": "Text", + "isNullable": false, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "emailAddress": { + "dataType": "Text", + "isNullable": false, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "sourceCustomObjectId": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "sourceCustomObjectKey": { + "dataType": "LongNumber", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "fieldType": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "eventData": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "obfuscationProperties": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "customObjectKey": { + "dataType": "LongNumber", + "isNullable": true, + "direction": "In", + "readOnly": true, + "access": "Hidden" + }, + "definitionInstanceId": { + "dataType": "Text", + "isNullable": false, + "direction": "In", + "readOnly": false, + "access": "Hidden" + } + } + } + }, + { + "id": "70572b1a-e274-4f09-a3fa-6fc0732ec52b", + "key": "WAITBYDURATION-2", + "name": "", + "description": "", + "type": "WAIT", + "outcomes": [ + { + "key": "a0908f9f-bc3c-47f7-9489-7fef5af25ce3", + "arguments": {}, + "metaData": { + "invalid": false + } + } + ], + "arguments": {}, + "configurationArguments": { + "waitDuration": 1, + "waitUnit": "DAYS" + }, + "metaData": { + "isConfigured": true, + "uiType": "WAITBYDURATION" + }, + "schema": { + "arguments": { + "endDate": { + "dataType": "Date", + "isNullable": false, + "direction": "Out", + "readOnly": false, + "access": "Hidden" + }, + "waitEndDateAttributeDataBound": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "waitDefinitionId": { + "dataType": "Text", + "isNullable": false, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "waitForEventId": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "executionMode": { + "dataType": "Text", + "isNullable": false, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "startActivityKey": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "waitQueueId": { + "dataType": "LongNumber", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + } + } + } + }, + { + "id": "e2a486cf-c85f-4543-88a2-d579cac1e0de", + "key": "WAITBYDURATION-1", + "name": "1 day", + "description": "", + "type": "WAIT", + "outcomes": [ + { + "key": "97af222a-450a-429e-8925-649b72f01ccf", + "arguments": {}, + "metaData": { + "invalid": false + } + } + ], + "arguments": {}, + "configurationArguments": { + "waitDuration": 1, + "waitUnit": "DAYS" + }, + "metaData": { + "isConfigured": true, + "uiType": "WAITBYDURATION" + }, + "schema": { + "arguments": { + "endDate": { + "dataType": "Date", + "isNullable": false, + "direction": "Out", + "readOnly": false, + "access": "Hidden" + }, + "waitEndDateAttributeDataBound": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "waitDefinitionId": { + "dataType": "Text", + "isNullable": false, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "waitForEventId": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "executionMode": { + "dataType": "Text", + "isNullable": false, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "startActivityKey": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "waitQueueId": { + "dataType": "LongNumber", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + } + } + } + } + ], + "triggers": [ + { + "id": "92753481-1258-49bd-8a84-921ed63bcc2e", + "key": "TRIGGER", + "name": "TRIGGER", + "description": "", + "type": "EmailAudience", + "outcomes": [], + "arguments": {}, + "configurationArguments": {}, + "metaData": { + "eventDefinitionId": "649d512b-4d08-4eca-a14e-fc7b64b4ada8", + "eventDefinitionKey": "DEAudience-2e3c73b6-48cc-2ec0-5522-48636e1a236e", + "chainType": "None", + "configurationRequired": false, + "iconUrl": "/images/icon-data-extension.svg", + "title": "Data Extension", + "entrySourceGroupConfigUrl": "jb:///data/entry/audience/entrysourcegroupconfig.json", + "sourceInteractionId": "00000000-0000-0000-0000-000000000000" + } + } + ], + "goals": [], + "exits": [], + "notifiers": [], + "stats": { + "currentPopulation": 0, + "cumulativePopulation": 0, + "metGoal": 0, + "metExitCriteria": 0, + "goalPerformance": 0 + }, + "entryMode": "NotSet", + "definitionType": "Multistep", + "channel": "", + "defaults": { + "email": ["{{Event.DEAudience-2e3c73b6-48cc-2ec0-5522-48636e1a236e.\"Email\"}}"], + "properties": { + "analyticsTracking": { + "enabled": true, + "analyticsType": "google", + "urlDomainsToTrack": [] + } + } + }, + "metaData": { + "dataSource": "ContactsModel", + "highThroughputSending": { + "email": false + } + }, + "executionMode": "Production", + "categoryId": 6298, + "status": "Draft", + "definitionId": "0175b971-71a3-4d8e-98ac-48121f3fbf4f", + "scheduledStatus": "Draft" +} diff --git a/test/resources/9999999/interaction/v1/interactions/key_testExisting_journey_Quicksend/get-response-versionNumber=1.json b/test/resources/9999999/interaction/v1/interactions/key_testExisting_journey_Quicksend/get-response-versionNumber=1.json new file mode 100644 index 000000000..f6508f62d --- /dev/null +++ b/test/resources/9999999/interaction/v1/interactions/key_testExisting_journey_Quicksend/get-response-versionNumber=1.json @@ -0,0 +1,253 @@ +{ + "id": "3c3f4112-9b43-43ca-8a89-aa0375b2c1a2", + "key": "testExisting_journey_Quicksend", + "name": "testExisting_journey_Quicksend", + "lastPublishedDate": "0001-01-01T00:00:00", + "description": "", + "version": 1, + "workflowApiVersion": 1, + "createdDate": "2024-04-24T12:18:43.47", + "modifiedDate": "2024-04-24T12:19:12.803", + "activities": [ + { + "id": "e20dcaa3-a750-44cf-9ce8-42d00378b8b4", + "key": "EMAILV2-1", + "name": "testExisting_asset_mail", + "description": "", + "type": "EMAILV2", + "outcomes": [ + { + "key": "a6b9c1af-cd89-4ce8-ba4f-bd4289188dc2", + "arguments": {}, + "metaData": { + "invalid": false + } + } + ], + "arguments": {}, + "configurationArguments": { + "isModified": true, + "googleAnalyticsCampaignName": "", + "triggeredSend": { + "autoAddSubscribers": true, + "autoUpdateSubscribers": true, + "bccEmail": "%%= ContentBlockByName(\"Content Builder\\dont strip non ssjs content\") =%%", + "ccEmail": "%%= ContentBlockByKey(\"testExisting_asset_htmlblock\") =%%", + "created": {}, + "description": "my activity info text", + "domainExclusions": [ + { + "id": "5a7194ad-6602-ef11-a5c8-5cba2c702db8", + "name": "testExisting_DomainExclusion" + } + ], + "dynamicEmailSubject": "testExisting_ dynamic email subject %%= ContentBlockByKey(\"testExisting_asset_htmlblock\") =%%", + "emailId": 531213, + "emailSubject": "testExisting_ email subject %%= ContentBlockByKey(\"testExisting_asset_htmlblock\") =%%", + "exclusionFilter": "/* insert ampscript here */ %%= ContentBlockById(1295064) =%%", + "isSalesforceTracking": false, + "isMultipart": true, + "isSendLogging": true, + "isStoppedOnJobError": false, + "keyword": "", + "modified": {}, + "preHeader": "testExisting_ email preheader %%= ContentBlockByKey(\"testExisting_asset_htmlblock\") =%%", + "priority": 3, + "sendClassificationId": "95da425b-a06f-e611-96fe-38eaa7142c61", + "suppressionLists": [ + { + "id": 75520, + "name": "testExisting_suppressionList" + } + ], + "suppressTracking": true, + "throttleLimit": 0, + "throttleOpens": "1/1/0001 12:00:00 AM", + "throttleCloses": "1/1/0001 12:00:00 AM", + "deliveryProfileId": "163f8417-13f7-e911-a2d8-1402ec938a35", + "senderProfileId": "a75d452b-7ef4-eb11-b82d-48df37d1da95", + "isTrackingClicks": true, + "publicationListId": 15 + }, + "applicationExtensionKey": "jb-email-activity" + }, + "metaData": { + "category": "message", + "version": "1.0", + "icon": "https://jb-email-activity.s7.marketingcloudapps.com/img/email-icon.svg", + "iconSmall": "https://jb-email-activity.s7.marketingcloudapps.com/img/email-icon.svg", + "statsContactIcon": null, + "original_icon": "/img/email-icon.svg", + "original_iconSmall": "/img/email-icon.svg", + "sections": {}, + "isConfigured": true + }, + "schema": { + "arguments": { + "requestID": { + "dataType": "Text", + "isNullable": true, + "direction": "Out", + "readOnly": false, + "access": "Hidden" + }, + "messageKey": { + "dataType": "Text", + "isNullable": true, + "direction": "Out", + "readOnly": false, + "access": "Hidden" + }, + "activityId": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "definitionId": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": true, + "access": "Hidden" + }, + "emailSubjectDataBound": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": true, + "access": "Hidden" + }, + "contactId": { + "dataType": "Number", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "contactKey": { + "dataType": "Text", + "isNullable": false, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "emailAddress": { + "dataType": "Text", + "isNullable": false, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "sourceCustomObjectId": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "sourceCustomObjectKey": { + "dataType": "LongNumber", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "fieldType": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "eventData": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "obfuscationProperties": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "customObjectKey": { + "dataType": "LongNumber", + "isNullable": true, + "direction": "In", + "readOnly": true, + "access": "Hidden" + }, + "definitionInstanceId": { + "dataType": "Text", + "isNullable": false, + "direction": "In", + "readOnly": false, + "access": "Hidden" + } + } + } + } + ], + "triggers": [ + { + "id": "abe42b4d-736d-4d26-a8f0-ce67d410782f", + "key": "TRIGGER", + "name": "TRIGGER", + "description": "", + "type": "EmailAudience", + "outcomes": [], + "arguments": {}, + "configurationArguments": {}, + "metaData": { + "sourceInteractionId": "00000000-0000-0000-0000-000000000000", + "eventDefinitionId": "9e1995f8-951d-4019-855c-826b45e5b028", + "eventDefinitionKey": "DEAudience-11be962d-064c-83d9-2804-7d1befc10325", + "chainType": "None", + "configurationRequired": false, + "iconUrl": "/images/icon-data-extension.svg", + "title": "Data Extension", + "entrySourceGroupConfigUrl": "jb:///data/entry/audience/entrysourcegroupconfig.json" + } + } + ], + "goals": [], + "exits": [], + "notifiers": [], + "stats": { + "currentPopulation": 0, + "cumulativePopulation": 0, + "metGoal": 0, + "metExitCriteria": 0, + "goalPerformance": 0 + }, + "entryMode": "MultipleEntries", + "definitionType": "Quicksend", + "channel": "email", + "defaults": { + "email": ["{{Event.DEAudience-11be962d-064c-83d9-2804-7d1befc10325.\"Email\"}}"], + "properties": { + "analyticsTracking": { + "enabled": true, + "analyticsType": "google", + "urlDomainsToTrack": [] + } + } + }, + "metaData": { + "dataSource": "ContactsModel", + "isScheduleSet": true, + "highThroughputSending": { + "email": false + } + }, + "executionMode": "Production", + "categoryId": 6298, + "status": "Draft", + "definitionId": "3c3f4112-9b43-43ca-8a89-aa0375b2c1a2", + "scheduledStatus": "Draft" +} diff --git a/test/resources/9999999/interaction/v1/interactions/key_testExisting_journey_Quicksend/get-response.json b/test/resources/9999999/interaction/v1/interactions/key_testExisting_journey_Quicksend/get-response.json new file mode 100644 index 000000000..f6508f62d --- /dev/null +++ b/test/resources/9999999/interaction/v1/interactions/key_testExisting_journey_Quicksend/get-response.json @@ -0,0 +1,253 @@ +{ + "id": "3c3f4112-9b43-43ca-8a89-aa0375b2c1a2", + "key": "testExisting_journey_Quicksend", + "name": "testExisting_journey_Quicksend", + "lastPublishedDate": "0001-01-01T00:00:00", + "description": "", + "version": 1, + "workflowApiVersion": 1, + "createdDate": "2024-04-24T12:18:43.47", + "modifiedDate": "2024-04-24T12:19:12.803", + "activities": [ + { + "id": "e20dcaa3-a750-44cf-9ce8-42d00378b8b4", + "key": "EMAILV2-1", + "name": "testExisting_asset_mail", + "description": "", + "type": "EMAILV2", + "outcomes": [ + { + "key": "a6b9c1af-cd89-4ce8-ba4f-bd4289188dc2", + "arguments": {}, + "metaData": { + "invalid": false + } + } + ], + "arguments": {}, + "configurationArguments": { + "isModified": true, + "googleAnalyticsCampaignName": "", + "triggeredSend": { + "autoAddSubscribers": true, + "autoUpdateSubscribers": true, + "bccEmail": "%%= ContentBlockByName(\"Content Builder\\dont strip non ssjs content\") =%%", + "ccEmail": "%%= ContentBlockByKey(\"testExisting_asset_htmlblock\") =%%", + "created": {}, + "description": "my activity info text", + "domainExclusions": [ + { + "id": "5a7194ad-6602-ef11-a5c8-5cba2c702db8", + "name": "testExisting_DomainExclusion" + } + ], + "dynamicEmailSubject": "testExisting_ dynamic email subject %%= ContentBlockByKey(\"testExisting_asset_htmlblock\") =%%", + "emailId": 531213, + "emailSubject": "testExisting_ email subject %%= ContentBlockByKey(\"testExisting_asset_htmlblock\") =%%", + "exclusionFilter": "/* insert ampscript here */ %%= ContentBlockById(1295064) =%%", + "isSalesforceTracking": false, + "isMultipart": true, + "isSendLogging": true, + "isStoppedOnJobError": false, + "keyword": "", + "modified": {}, + "preHeader": "testExisting_ email preheader %%= ContentBlockByKey(\"testExisting_asset_htmlblock\") =%%", + "priority": 3, + "sendClassificationId": "95da425b-a06f-e611-96fe-38eaa7142c61", + "suppressionLists": [ + { + "id": 75520, + "name": "testExisting_suppressionList" + } + ], + "suppressTracking": true, + "throttleLimit": 0, + "throttleOpens": "1/1/0001 12:00:00 AM", + "throttleCloses": "1/1/0001 12:00:00 AM", + "deliveryProfileId": "163f8417-13f7-e911-a2d8-1402ec938a35", + "senderProfileId": "a75d452b-7ef4-eb11-b82d-48df37d1da95", + "isTrackingClicks": true, + "publicationListId": 15 + }, + "applicationExtensionKey": "jb-email-activity" + }, + "metaData": { + "category": "message", + "version": "1.0", + "icon": "https://jb-email-activity.s7.marketingcloudapps.com/img/email-icon.svg", + "iconSmall": "https://jb-email-activity.s7.marketingcloudapps.com/img/email-icon.svg", + "statsContactIcon": null, + "original_icon": "/img/email-icon.svg", + "original_iconSmall": "/img/email-icon.svg", + "sections": {}, + "isConfigured": true + }, + "schema": { + "arguments": { + "requestID": { + "dataType": "Text", + "isNullable": true, + "direction": "Out", + "readOnly": false, + "access": "Hidden" + }, + "messageKey": { + "dataType": "Text", + "isNullable": true, + "direction": "Out", + "readOnly": false, + "access": "Hidden" + }, + "activityId": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "definitionId": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": true, + "access": "Hidden" + }, + "emailSubjectDataBound": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": true, + "access": "Hidden" + }, + "contactId": { + "dataType": "Number", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "contactKey": { + "dataType": "Text", + "isNullable": false, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "emailAddress": { + "dataType": "Text", + "isNullable": false, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "sourceCustomObjectId": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "sourceCustomObjectKey": { + "dataType": "LongNumber", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "fieldType": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "eventData": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "obfuscationProperties": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "customObjectKey": { + "dataType": "LongNumber", + "isNullable": true, + "direction": "In", + "readOnly": true, + "access": "Hidden" + }, + "definitionInstanceId": { + "dataType": "Text", + "isNullable": false, + "direction": "In", + "readOnly": false, + "access": "Hidden" + } + } + } + } + ], + "triggers": [ + { + "id": "abe42b4d-736d-4d26-a8f0-ce67d410782f", + "key": "TRIGGER", + "name": "TRIGGER", + "description": "", + "type": "EmailAudience", + "outcomes": [], + "arguments": {}, + "configurationArguments": {}, + "metaData": { + "sourceInteractionId": "00000000-0000-0000-0000-000000000000", + "eventDefinitionId": "9e1995f8-951d-4019-855c-826b45e5b028", + "eventDefinitionKey": "DEAudience-11be962d-064c-83d9-2804-7d1befc10325", + "chainType": "None", + "configurationRequired": false, + "iconUrl": "/images/icon-data-extension.svg", + "title": "Data Extension", + "entrySourceGroupConfigUrl": "jb:///data/entry/audience/entrysourcegroupconfig.json" + } + } + ], + "goals": [], + "exits": [], + "notifiers": [], + "stats": { + "currentPopulation": 0, + "cumulativePopulation": 0, + "metGoal": 0, + "metExitCriteria": 0, + "goalPerformance": 0 + }, + "entryMode": "MultipleEntries", + "definitionType": "Quicksend", + "channel": "email", + "defaults": { + "email": ["{{Event.DEAudience-11be962d-064c-83d9-2804-7d1befc10325.\"Email\"}}"], + "properties": { + "analyticsTracking": { + "enabled": true, + "analyticsType": "google", + "urlDomainsToTrack": [] + } + } + }, + "metaData": { + "dataSource": "ContactsModel", + "isScheduleSet": true, + "highThroughputSending": { + "email": false + } + }, + "executionMode": "Production", + "categoryId": 6298, + "status": "Draft", + "definitionId": "3c3f4112-9b43-43ca-8a89-aa0375b2c1a2", + "scheduledStatus": "Draft" +} diff --git a/test/resources/9999999/interaction/v1/interactions/key_testExisting_journey_updatecontact/get-response.json b/test/resources/9999999/interaction/v1/interactions/key_testExisting_journey_updatecontact/get-response.json new file mode 100644 index 000000000..863fea7f1 --- /dev/null +++ b/test/resources/9999999/interaction/v1/interactions/key_testExisting_journey_updatecontact/get-response.json @@ -0,0 +1,119 @@ +{ + "id": "0175b971-71a3-4d8e-98ac-48121f3fbf4f", + "key": "testExisting_journey_updatecontact", + "name": "testExisting_journey_updatecontact", + "lastPublishedDate": "0001-01-01T00:00:00", + "description": "", + "version": 1, + "workflowApiVersion": 1, + "createdDate": "2024-05-04T05:54:48.027", + "modifiedDate": "2024-05-04T17:25:57.9", + "activities": [ + { + "key": "UPDATECONTACTDATAV2-1", + "name": "Update Contact - TEST", + "description": "", + "type": "UPDATECONTACTDATA", + "outcomes": [ + { + "key": "9f21d42b-4679-4561-911a-4bccf84672ba", + "arguments": {}, + "metaData": { + "invalid": false + } + } + ], + "arguments": { + "activityData": { + "updateContactFields": [ + { + "r__dataExtensionField_name": "LastName", + "value": "TEST", + "r__dataExtension_key": "testExisting_dataExtension" + } + ] + } + }, + "configurationArguments": {}, + "metaData": { + "isConfigured": true + }, + "schema": { + "arguments": { + "activityData": { + "dataType": "Text", + "isNullable": false, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "contactKey": { + "dataType": "Text", + "isNullable": false, + "direction": "In", + "readOnly": false, + "access": "Hidden" + } + } + } + } + ], + "triggers": [ + { + "id": "92753481-1258-49bd-8a84-921ed63bcc2e", + "key": "TRIGGER", + "name": "TRIGGER", + "description": "", + "type": "EmailAudience", + "outcomes": [], + "arguments": {}, + "configurationArguments": {}, + "metaData": { + "eventDefinitionId": "649d512b-4d08-4eca-a14e-fc7b64b4ada8", + "eventDefinitionKey": "DEAudience-2e3c73b6-48cc-2ec0-5522-48636e1a236e", + "chainType": "None", + "configurationRequired": false, + "iconUrl": "/images/icon-data-extension.svg", + "title": "Data Extension", + "entrySourceGroupConfigUrl": "jb:///data/entry/audience/entrysourcegroupconfig.json", + "sourceInteractionId": "00000000-0000-0000-0000-000000000000" + } + } + ], + "goals": [], + "exits": [], + "notifiers": [], + "stats": { + "currentPopulation": 0, + "cumulativePopulation": 0, + "metGoal": 0, + "metExitCriteria": 0, + "goalPerformance": 0 + }, + "entryMode": "NotSet", + "definitionType": "Multistep", + "channel": "", + "defaults": { + "email": [ + "{{Event.DEAudience-2e3c73b6-48cc-2ec0-5522-48636e1a236e.\"Email\"}}" + ], + "properties": { + "analyticsTracking": { + "enabled": true, + "analyticsType": "google", + "urlDomainsToTrack": [] + } + } + }, + "metaData": { + "dataSource": "ContactsModel", + "highThroughputSending": { + "email": false + } + }, + "executionMode": "Production", + "categoryId": 6298, + "status": "Draft", + "definitionId": "0175b971-71a3-4d8e-98ac-48121f3fbf4f", + "scheduledStatus": "Draft" +} \ No newline at end of file diff --git a/test/resources/9999999/interaction/v1/interactions/key_testExisting_journey_updatecontact/put-response.json b/test/resources/9999999/interaction/v1/interactions/key_testExisting_journey_updatecontact/put-response.json new file mode 100644 index 000000000..f42b8fa51 --- /dev/null +++ b/test/resources/9999999/interaction/v1/interactions/key_testExisting_journey_updatecontact/put-response.json @@ -0,0 +1,106 @@ +{ + "key": "testExisting_journey_updatecontact", + "name": "testExisting_journey_updatecontact", + "lastPublishedDate": "0001-01-01T00:00:00", + "description": "", + "version": 1, + "workflowApiVersion": 1, + "createdDate": "0001-01-01T00:00:00", + "modifiedDate": "2024-05-04T17:25:57.9", + "activities": [ + { + "key": "UPDATECONTACTDATAV2-1", + "name": "Update Contact - TEST", + "description": "", + "type": "UPDATECONTACTDATA", + "outcomes": [ + { + "key": "9f21d42b-4679-4561-911a-4bccf84672ba", + "arguments": {}, + "metaData": { + "invalid": false + } + } + ], + "arguments": { + "activityData": { + "updateContactFields": [ + { + "field": "bea0e308-5d45-4181-a673-da9972a7c674", + "value": "TEST", + "dataExtensionId": "21711373-72c1-ec11-b83b-48df37d1deb7" + } + ] + } + }, + "configurationArguments": {}, + "metaData": { + "isConfigured": true + }, + "schema": { + "arguments": { + "activityData": { + "dataType": "Text", + "isNullable": false, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "contactKey": { + "dataType": "Text", + "isNullable": false, + "direction": "In", + "readOnly": false, + "access": "Hidden" + } + } + } + } + ], + "triggers": [ + { + "key": "TRIGGER", + "name": "TRIGGER", + "description": "", + "type": "EmailAudience", + "outcomes": [], + "arguments": {}, + "configurationArguments": {}, + "metaData": { + "r__event_key": "DEAudience-2e3c73b6-48cc-2ec0-5522-48636e1a236e", + "chainType": "None", + "configurationRequired": false, + "iconUrl": "/images/icon-data-extension.svg", + "title": "Data Extension", + "entrySourceGroupConfigUrl": "jb:///data/entry/audience/entrysourcegroupconfig.json", + "sourceInteractionId": "00000000-0000-0000-0000-000000000000" + } + } + ], + "goals": [], + "exits": [], + "notifiers": [], + "entryMode": "NotSet", + "definitionType": "Multistep", + "channel": "", + "defaults": { + "email": ["{{Event.DEAudience-2e3c73b6-48cc-2ec0-5522-48636e1a236e.\"Email\"}}"], + "properties": { + "analyticsTracking": { + "enabled": true, + "analyticsType": "google", + "urlDomainsToTrack": [] + } + } + }, + "metaData": { + "dataSource": "ContactsModel", + "highThroughputSending": { + "email": false + } + }, + "executionMode": "Production", + "status": "Draft", + "scheduledStatus": "Draft", + "r__folder_Path": "my journeys" +} diff --git a/test/resources/9999999/interaction/v1/interactions/key_testExisting_temail/get-response-versionNumber=1.json b/test/resources/9999999/interaction/v1/interactions/key_testExisting_temail/get-response-versionNumber=1.json new file mode 100644 index 000000000..8427da85d --- /dev/null +++ b/test/resources/9999999/interaction/v1/interactions/key_testExisting_temail/get-response-versionNumber=1.json @@ -0,0 +1,219 @@ +{ + "id": "dsfdsafdsa-922c-4568-85a5-e5cc77efc3be", + "key": "testExisting_temail", + "name": "testExisting_temail", + "lastPublishedDate": "0001-01-01T00:00:00", + "description": "", + "version": 1, + "workflowApiVersion": 1, + "createdDate": "2022-03-24T02:20:32.74", + "modifiedDate": "2022-03-24T02:20:40.45", + "activities": [ + { + "id": "9606bcb0-9246-4610-9800-963bc77fc20a", + "key": "EMAILV2-4", + "name": "testExisting_temail", + "description": "", + "type": "EMAILV2", + "outcomes": [ + { + "key": "1f44021a-74ac-49be-a07c-67862228214d", + "arguments": {}, + "metaData": { + "invalid": false + } + } + ], + "arguments": {}, + "configurationArguments": { + "applicationExtensionKey": "jb-email-activity", + "isModified": true, + "triggeredSend": { + "autoAddSubscribers": true, + "autoUpdateSubscribers": true, + "bccEmail": "", + "ccEmail": "", + "created": {}, + "domainExclusions": [], + "dynamicEmailSubject": "test email", + "emailId": 531213, + "emailSubject": "test email", + "exclusionFilter": "", + "isSalesforceTracking": true, + "isMultipart": true, + "isSendLogging": false, + "isStoppedOnJobError": false, + "modified": {}, + "preHeader": "", + "priority": 4, + "sendClassificationId": "95da425b-a06f-e611-96fe-38eaa7142c61", + "throttleOpens": "1/1/0001 12:00:00 AM", + "throttleCloses": "1/1/0001 12:00:00 AM", + "deliveryProfileId": "163f8417-13f7-e911-a2d8-1402ec938a35", + "senderProfileId": "a75d452b-7ef4-eb11-b82d-48df37d1da95", + "isTrackingClicks": true, + "publicationListId": 15 + }, + "triggeredSendId": "0a650d90-755e-ed11-b852-48df37d1df5b", + "triggeredSendKey": "testExisting_temail" + }, + "metaData": { + "highThroughput": { + "definitionKey": "testExisting_temail", + "dataExtensionId": "21711373-72c1-ec11-b83b-48df37d1deb7" + }, + "sections": {}, + "isConfigured": true + }, + "schema": { + "arguments": { + "requestID": { + "dataType": "Text", + "isNullable": true, + "direction": "Out", + "readOnly": false, + "access": "Hidden" + }, + "messageKey": { + "dataType": "Text", + "isNullable": true, + "direction": "Out", + "readOnly": false, + "access": "Hidden" + }, + "activityId": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "definitionId": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": true, + "access": "Hidden" + }, + "emailSubjectDataBound": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": true, + "access": "Hidden" + }, + "contactId": { + "dataType": "Number", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "contactKey": { + "dataType": "Text", + "isNullable": false, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "emailAddress": { + "dataType": "Text", + "isNullable": false, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "sourceCustomObjectId": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "sourceCustomObjectKey": { + "dataType": "LongNumber", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "fieldType": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "eventData": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "obfuscationProperties": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "customObjectKey": { + "dataType": "LongNumber", + "isNullable": true, + "direction": "In", + "readOnly": true, + "access": "Hidden" + }, + "definitionInstanceId": { + "dataType": "Text", + "isNullable": false, + "direction": "In", + "readOnly": false, + "access": "Hidden" + } + } + } + } + ], + "triggers": [ + { + "key": "TRIGGER", + "name": "TRIGGER", + "description": "", + "type": "transactional-api", + "outcomes": [], + "arguments": {}, + "configurationArguments": {}, + "metaData": { + "chainType": "none", + "configurationRequired": false, + "iconUrl": "/images/icon_journeyBuilder-event-transactional-blue.svg", + "title": "Transactional API Event", + "category": "Transactional", + "entrySourceGroupConfigUrl": "null" + } + } + ], + "goals": [], + "exits": [], + "notifiers": [], + "entryMode": "MultipleEntries", + "definitionType": "Transactional", + "channel": "email", + "defaults": { + "properties": { + "analyticsTracking": { + "enabled": false, + "analyticsType": "google", + "urlDomainsToTrack": [] + } + } + }, + "metaData": {}, + "executionMode": "Production", + "categoryId": 6298, + "status": "Published", + "scheduledStatus": "Draft", + "definitionId": "dsfdsafdsa-922c-4568-85a5-e5cc77efc3be" +} diff --git a/test/resources/9999999/interaction/v1/interactions/key_testExisting_temail/get-response.json b/test/resources/9999999/interaction/v1/interactions/key_testExisting_temail/get-response.json new file mode 100644 index 000000000..8427da85d --- /dev/null +++ b/test/resources/9999999/interaction/v1/interactions/key_testExisting_temail/get-response.json @@ -0,0 +1,219 @@ +{ + "id": "dsfdsafdsa-922c-4568-85a5-e5cc77efc3be", + "key": "testExisting_temail", + "name": "testExisting_temail", + "lastPublishedDate": "0001-01-01T00:00:00", + "description": "", + "version": 1, + "workflowApiVersion": 1, + "createdDate": "2022-03-24T02:20:32.74", + "modifiedDate": "2022-03-24T02:20:40.45", + "activities": [ + { + "id": "9606bcb0-9246-4610-9800-963bc77fc20a", + "key": "EMAILV2-4", + "name": "testExisting_temail", + "description": "", + "type": "EMAILV2", + "outcomes": [ + { + "key": "1f44021a-74ac-49be-a07c-67862228214d", + "arguments": {}, + "metaData": { + "invalid": false + } + } + ], + "arguments": {}, + "configurationArguments": { + "applicationExtensionKey": "jb-email-activity", + "isModified": true, + "triggeredSend": { + "autoAddSubscribers": true, + "autoUpdateSubscribers": true, + "bccEmail": "", + "ccEmail": "", + "created": {}, + "domainExclusions": [], + "dynamicEmailSubject": "test email", + "emailId": 531213, + "emailSubject": "test email", + "exclusionFilter": "", + "isSalesforceTracking": true, + "isMultipart": true, + "isSendLogging": false, + "isStoppedOnJobError": false, + "modified": {}, + "preHeader": "", + "priority": 4, + "sendClassificationId": "95da425b-a06f-e611-96fe-38eaa7142c61", + "throttleOpens": "1/1/0001 12:00:00 AM", + "throttleCloses": "1/1/0001 12:00:00 AM", + "deliveryProfileId": "163f8417-13f7-e911-a2d8-1402ec938a35", + "senderProfileId": "a75d452b-7ef4-eb11-b82d-48df37d1da95", + "isTrackingClicks": true, + "publicationListId": 15 + }, + "triggeredSendId": "0a650d90-755e-ed11-b852-48df37d1df5b", + "triggeredSendKey": "testExisting_temail" + }, + "metaData": { + "highThroughput": { + "definitionKey": "testExisting_temail", + "dataExtensionId": "21711373-72c1-ec11-b83b-48df37d1deb7" + }, + "sections": {}, + "isConfigured": true + }, + "schema": { + "arguments": { + "requestID": { + "dataType": "Text", + "isNullable": true, + "direction": "Out", + "readOnly": false, + "access": "Hidden" + }, + "messageKey": { + "dataType": "Text", + "isNullable": true, + "direction": "Out", + "readOnly": false, + "access": "Hidden" + }, + "activityId": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "definitionId": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": true, + "access": "Hidden" + }, + "emailSubjectDataBound": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": true, + "access": "Hidden" + }, + "contactId": { + "dataType": "Number", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "contactKey": { + "dataType": "Text", + "isNullable": false, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "emailAddress": { + "dataType": "Text", + "isNullable": false, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "sourceCustomObjectId": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "sourceCustomObjectKey": { + "dataType": "LongNumber", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "fieldType": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "eventData": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "obfuscationProperties": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "customObjectKey": { + "dataType": "LongNumber", + "isNullable": true, + "direction": "In", + "readOnly": true, + "access": "Hidden" + }, + "definitionInstanceId": { + "dataType": "Text", + "isNullable": false, + "direction": "In", + "readOnly": false, + "access": "Hidden" + } + } + } + } + ], + "triggers": [ + { + "key": "TRIGGER", + "name": "TRIGGER", + "description": "", + "type": "transactional-api", + "outcomes": [], + "arguments": {}, + "configurationArguments": {}, + "metaData": { + "chainType": "none", + "configurationRequired": false, + "iconUrl": "/images/icon_journeyBuilder-event-transactional-blue.svg", + "title": "Transactional API Event", + "category": "Transactional", + "entrySourceGroupConfigUrl": "null" + } + } + ], + "goals": [], + "exits": [], + "notifiers": [], + "entryMode": "MultipleEntries", + "definitionType": "Transactional", + "channel": "email", + "defaults": { + "properties": { + "analyticsTracking": { + "enabled": false, + "analyticsType": "google", + "urlDomainsToTrack": [] + } + } + }, + "metaData": {}, + "executionMode": "Production", + "categoryId": 6298, + "status": "Published", + "scheduledStatus": "Draft", + "definitionId": "dsfdsafdsa-922c-4568-85a5-e5cc77efc3be" +} diff --git a/test/resources/9999999/interaction/v1/interactions/key_testExisting_temail/put-response-paused.json b/test/resources/9999999/interaction/v1/interactions/key_testExisting_temail/put-response-paused.json new file mode 100644 index 000000000..c65333503 --- /dev/null +++ b/test/resources/9999999/interaction/v1/interactions/key_testExisting_temail/put-response-paused.json @@ -0,0 +1,219 @@ +{ + "id": "dsfdsafdsa-922c-4568-85a5-e5cc77efc3be", + "key": "testExisting_temail", + "name": "testExisting_temail", + "lastPublishedDate": "0001-01-01T00:00:00", + "description": "", + "version": 1, + "workflowApiVersion": 1, + "createdDate": "0001-01-01T00:00:00", + "modifiedDate": "2022-03-24T02:20:40.45", + "activities": [ + { + "id": "9606bcb0-9246-4610-9800-963bc77fc20a", + "key": "EMAILV2-4", + "name": "testExisting_temail", + "description": "", + "type": "EMAILV2", + "outcomes": [ + { + "key": "1f44021a-74ac-49be-a07c-67862228214d", + "arguments": {}, + "metaData": { + "invalid": false + } + } + ], + "arguments": {}, + "configurationArguments": { + "applicationExtensionKey": "jb-email-activity", + "isModified": true, + "triggeredSend": { + "autoAddSubscribers": true, + "autoUpdateSubscribers": true, + "bccEmail": "", + "ccEmail": "", + "created": {}, + "domainExclusions": [], + "dynamicEmailSubject": "test email", + "emailId": 531213, + "emailSubject": "test email", + "exclusionFilter": "", + "isSalesforceTracking": true, + "isMultipart": true, + "isSendLogging": false, + "isStoppedOnJobError": false, + "modified": {}, + "preHeader": "", + "priority": 4, + "sendClassificationId": "95da425b-a06f-e611-96fe-38eaa7142c61", + "throttleOpens": "1/1/0001 12:00:00 AM", + "throttleCloses": "1/1/0001 12:00:00 AM", + "deliveryProfileId": "163f8417-13f7-e911-a2d8-1402ec938a35", + "senderProfileId": "a75d452b-7ef4-eb11-b82d-48df37d1da95", + "isTrackingClicks": true, + "publicationListId": 15 + }, + "triggeredSendId": "ae8511d0-9bf0-42d0-af4f-bd9c1218c812", + "triggeredSendKey": "testExisting_temail" + }, + "metaData": { + "highThroughput": { + "definitionKey": "testExisting_temail", + "dataExtensionId": "21711373-72c1-ec11-b83b-48df37d1deb7" + }, + "sections": {}, + "isConfigured": true + }, + "schema": { + "arguments": { + "requestID": { + "dataType": "Text", + "isNullable": true, + "direction": "Out", + "readOnly": false, + "access": "Hidden" + }, + "messageKey": { + "dataType": "Text", + "isNullable": true, + "direction": "Out", + "readOnly": false, + "access": "Hidden" + }, + "activityId": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "definitionId": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": true, + "access": "Hidden" + }, + "emailSubjectDataBound": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": true, + "access": "Hidden" + }, + "contactId": { + "dataType": "Number", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "contactKey": { + "dataType": "Text", + "isNullable": false, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "emailAddress": { + "dataType": "Text", + "isNullable": false, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "sourceCustomObjectId": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "sourceCustomObjectKey": { + "dataType": "LongNumber", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "fieldType": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "eventData": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "obfuscationProperties": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "customObjectKey": { + "dataType": "LongNumber", + "isNullable": true, + "direction": "In", + "readOnly": true, + "access": "Hidden" + }, + "definitionInstanceId": { + "dataType": "Text", + "isNullable": false, + "direction": "In", + "readOnly": false, + "access": "Hidden" + } + } + } + } + ], + "triggers": [ + { + "key": "TRIGGER", + "name": "TRIGGER", + "description": "", + "type": "transactional-api", + "outcomes": [], + "arguments": {}, + "configurationArguments": {}, + "metaData": { + "chainType": "none", + "configurationRequired": false, + "iconUrl": "/images/icon_journeyBuilder-event-transactional-blue.svg", + "title": "Transactional API Event", + "category": "Transactional", + "entrySourceGroupConfigUrl": "null" + } + } + ], + "goals": [], + "exits": [], + "notifiers": [], + "entryMode": "MultipleEntries", + "definitionType": "Transactional", + "channel": "email", + "defaults": { + "properties": { + "analyticsTracking": { + "enabled": false, + "analyticsType": "google", + "urlDomainsToTrack": [] + } + } + }, + "metaData": {}, + "executionMode": "Production", + "categoryId": 6298, + "status": "Paused", + "scheduledStatus": "Draft", + "definitionId": "dsfdsafdsa-922c-4568-85a5-e5cc77efc3be" +} diff --git a/test/resources/9999999/interaction/v1/interactions/key_testExisting_temail/put-response.json b/test/resources/9999999/interaction/v1/interactions/key_testExisting_temail/put-response.json new file mode 100644 index 000000000..5536bdd23 --- /dev/null +++ b/test/resources/9999999/interaction/v1/interactions/key_testExisting_temail/put-response.json @@ -0,0 +1,219 @@ +{ + "id": "dsfdsafdsa-922c-4568-85a5-e5cc77efc3be", + "key": "testExisting_temail", + "name": "testExisting_temail", + "lastPublishedDate": "0001-01-01T00:00:00", + "description": "", + "version": 1, + "workflowApiVersion": 1, + "createdDate": "0001-01-01T00:00:00", + "modifiedDate": "2022-03-24T02:20:40.45", + "activities": [ + { + "id": "9606bcb0-9246-4610-9800-963bc77fc20a", + "key": "EMAILV2-4", + "name": "testExisting_temail", + "description": "", + "type": "EMAILV2", + "outcomes": [ + { + "key": "1f44021a-74ac-49be-a07c-67862228214d", + "arguments": {}, + "metaData": { + "invalid": false + } + } + ], + "arguments": {}, + "configurationArguments": { + "applicationExtensionKey": "jb-email-activity", + "isModified": true, + "triggeredSend": { + "autoAddSubscribers": true, + "autoUpdateSubscribers": true, + "bccEmail": "", + "ccEmail": "", + "created": {}, + "domainExclusions": [], + "dynamicEmailSubject": "test email", + "emailId": 531213, + "emailSubject": "test email", + "exclusionFilter": "", + "isSalesforceTracking": true, + "isMultipart": true, + "isSendLogging": false, + "isStoppedOnJobError": false, + "modified": {}, + "preHeader": "", + "priority": 4, + "sendClassificationId": "95da425b-a06f-e611-96fe-38eaa7142c61", + "throttleOpens": "1/1/0001 12:00:00 AM", + "throttleCloses": "1/1/0001 12:00:00 AM", + "deliveryProfileId": "163f8417-13f7-e911-a2d8-1402ec938a35", + "senderProfileId": "a75d452b-7ef4-eb11-b82d-48df37d1da95", + "isTrackingClicks": true, + "publicationListId": 15 + }, + "triggeredSendId": "0a650d90-755e-ed11-b852-48df37d1df5b", + "triggeredSendKey": "testExisting_temail" + }, + "metaData": { + "highThroughput": { + "definitionKey": "testExisting_temail", + "dataExtensionId": "21711373-72c1-ec11-b83b-48df37d1deb7" + }, + "sections": {}, + "isConfigured": true + }, + "schema": { + "arguments": { + "requestID": { + "dataType": "Text", + "isNullable": true, + "direction": "Out", + "readOnly": false, + "access": "Hidden" + }, + "messageKey": { + "dataType": "Text", + "isNullable": true, + "direction": "Out", + "readOnly": false, + "access": "Hidden" + }, + "activityId": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "definitionId": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": true, + "access": "Hidden" + }, + "emailSubjectDataBound": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": true, + "access": "Hidden" + }, + "contactId": { + "dataType": "Number", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "contactKey": { + "dataType": "Text", + "isNullable": false, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "emailAddress": { + "dataType": "Text", + "isNullable": false, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "sourceCustomObjectId": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "sourceCustomObjectKey": { + "dataType": "LongNumber", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "fieldType": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "eventData": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "obfuscationProperties": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "customObjectKey": { + "dataType": "LongNumber", + "isNullable": true, + "direction": "In", + "readOnly": true, + "access": "Hidden" + }, + "definitionInstanceId": { + "dataType": "Text", + "isNullable": false, + "direction": "In", + "readOnly": false, + "access": "Hidden" + } + } + } + } + ], + "triggers": [ + { + "key": "TRIGGER", + "name": "TRIGGER", + "description": "", + "type": "transactional-api", + "outcomes": [], + "arguments": {}, + "configurationArguments": {}, + "metaData": { + "chainType": "none", + "configurationRequired": false, + "iconUrl": "/images/icon_journeyBuilder-event-transactional-blue.svg", + "title": "Transactional API Event", + "category": "Transactional", + "entrySourceGroupConfigUrl": "null" + } + } + ], + "goals": [], + "exits": [], + "notifiers": [], + "entryMode": "MultipleEntries", + "definitionType": "Transactional", + "channel": "email", + "defaults": { + "properties": { + "analyticsTracking": { + "enabled": false, + "analyticsType": "google", + "urlDomainsToTrack": [] + } + } + }, + "metaData": {}, + "executionMode": "Production", + "categoryId": 6298, + "status": "Published", + "scheduledStatus": "Draft", + "definitionId": "dsfdsafdsa-922c-4568-85a5-e5cc77efc3be" +} diff --git a/test/resources/9999999/interaction/v1/interactions/key_testExisting_temail_notPublished/get-response-versionNumber=1.json b/test/resources/9999999/interaction/v1/interactions/key_testExisting_temail_notPublished/get-response-versionNumber=1.json new file mode 100644 index 000000000..9211e0c8f --- /dev/null +++ b/test/resources/9999999/interaction/v1/interactions/key_testExisting_temail_notPublished/get-response-versionNumber=1.json @@ -0,0 +1,226 @@ +{ + "id": "d4a900fe-3a8f-4cc5-9a49-81286e3e2cd2", + "key": "testExisting_temail_notPublished", + "name": "testExisting_temail_notPublished", + "lastPublishedDate": "0001-01-01T00:00:00", + "description": "", + "version": 1, + "workflowApiVersion": 1, + "createdDate": "2024-08-23T01:29:33.233", + "modifiedDate": "2024-08-23T02:00:44.57", + "activities": [ + { + "id": "4ae63473-ea1e-4963-a257-6fea45a9038a", + "key": "EMAILV2-3", + "name": "my email activity", + "description": "", + "type": "EMAILV2", + "outcomes": [ + { + "key": "067f20ba-af36-4401-99d8-934100e1935d", + "arguments": {}, + "metaData": { + "invalid": false + } + } + ], + "arguments": {}, + "configurationArguments": { + "applicationExtensionKey": "jb-email-activity", + "isModified": true, + "triggeredSend": { + "autoAddSubscribers": true, + "autoUpdateSubscribers": true, + "bccEmail": "", + "ccEmail": "", + "created": {}, + "domainExclusions": [], + "dynamicEmailSubject": "%%=treatascontent(@subject)=%%", + "emailId": 531213, + "emailSubject": "%%=treatascontent(@subject)=%%", + "exclusionFilter": "", + "isSalesforceTracking": true, + "isMultipart": true, + "isSendLogging": false, + "isStoppedOnJobError": false, + "modified": {}, + "preHeader": "%%=treatascontent(@preheader)=%%\n", + "priority": 4, + "sendClassificationId": "95da425b-a06f-e611-96fe-38eaa7142c61", + "throttleOpens": "1/1/0001 12:00:00 AM", + "throttleCloses": "1/1/0001 12:00:00 AM", + "deliveryProfileId": "163f8417-13f7-e911-a2d8-1402ec938a35", + "senderProfileId": "a75d452b-7ef4-eb11-b82d-48df37d1da95", + "isTrackingClicks": true, + "publicationListId": 15 + }, + "triggeredSendId": "6a2f70c5-2561-ef11-b876-f40343c95928", + "triggeredSendKey": "testExisting_temail_notPublished" + }, + "metaData": { + "highThroughput": { + "definitionKey": "testExisting_temail_notPublished", + "dataExtensionId": "3c3a54a5-d55f-ef11-b876-f40343c95928" + }, + "isConfigured": true, + "sections": {} + }, + "schema": { + "arguments": { + "requestID": { + "dataType": "Text", + "isNullable": true, + "direction": "Out", + "readOnly": false, + "access": "Hidden" + }, + "messageKey": { + "dataType": "Text", + "isNullable": true, + "direction": "Out", + "readOnly": false, + "access": "Hidden" + }, + "activityId": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "definitionId": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": true, + "access": "Hidden" + }, + "emailSubjectDataBound": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": true, + "access": "Hidden" + }, + "contactId": { + "dataType": "Number", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "contactKey": { + "dataType": "Text", + "isNullable": false, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "emailAddress": { + "dataType": "Text", + "isNullable": false, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "sourceCustomObjectId": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "sourceCustomObjectKey": { + "dataType": "LongNumber", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "fieldType": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "eventData": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "obfuscationProperties": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "customObjectKey": { + "dataType": "LongNumber", + "isNullable": true, + "direction": "In", + "readOnly": true, + "access": "Hidden" + }, + "definitionInstanceId": { + "dataType": "Text", + "isNullable": false, + "direction": "In", + "readOnly": false, + "access": "Hidden" + } + } + } + } + ], + "triggers": [ + { + "id": "64a93832-fd23-487e-b585-8f3af3b5b6eb", + "key": "TRIGGER", + "name": "TRIGGER", + "description": "", + "type": "transactional-api", + "outcomes": [], + "arguments": {}, + "configurationArguments": {}, + "metaData": { + "chainType": "none", + "configurationRequired": false, + "iconUrl": "/images/icon_journeyBuilder-event-transactional-blue.svg", + "title": "Transactional API Event", + "category": "Transactional", + "entrySourceGroupConfigUrl": "null" + } + } + ], + "goals": [], + "exits": [], + "notifiers": [], + "stats": { + "currentPopulation": 0, + "cumulativePopulation": 0, + "metGoal": 0, + "metExitCriteria": 0, + "goalPerformance": 0 + }, + "entryMode": "MultipleEntries", + "definitionType": "Transactional", + "channel": "email", + "defaults": { + "properties": {} + }, + "metaData": { + "dataSource": "ContactsModel", + "highThroughputSending": { + "email": false + } + }, + "executionMode": "Production", + "categoryId": 6298, + "status": "Published", + "definitionId": "d4a900fe-3a8f-4cc5-9a49-81286e3e2cd2", + "scheduledStatus": "Draft" +} diff --git a/test/resources/9999999/interaction/v1/interactions/key_testExisting_temail_notPublished/get-response.json b/test/resources/9999999/interaction/v1/interactions/key_testExisting_temail_notPublished/get-response.json new file mode 100644 index 000000000..9211e0c8f --- /dev/null +++ b/test/resources/9999999/interaction/v1/interactions/key_testExisting_temail_notPublished/get-response.json @@ -0,0 +1,226 @@ +{ + "id": "d4a900fe-3a8f-4cc5-9a49-81286e3e2cd2", + "key": "testExisting_temail_notPublished", + "name": "testExisting_temail_notPublished", + "lastPublishedDate": "0001-01-01T00:00:00", + "description": "", + "version": 1, + "workflowApiVersion": 1, + "createdDate": "2024-08-23T01:29:33.233", + "modifiedDate": "2024-08-23T02:00:44.57", + "activities": [ + { + "id": "4ae63473-ea1e-4963-a257-6fea45a9038a", + "key": "EMAILV2-3", + "name": "my email activity", + "description": "", + "type": "EMAILV2", + "outcomes": [ + { + "key": "067f20ba-af36-4401-99d8-934100e1935d", + "arguments": {}, + "metaData": { + "invalid": false + } + } + ], + "arguments": {}, + "configurationArguments": { + "applicationExtensionKey": "jb-email-activity", + "isModified": true, + "triggeredSend": { + "autoAddSubscribers": true, + "autoUpdateSubscribers": true, + "bccEmail": "", + "ccEmail": "", + "created": {}, + "domainExclusions": [], + "dynamicEmailSubject": "%%=treatascontent(@subject)=%%", + "emailId": 531213, + "emailSubject": "%%=treatascontent(@subject)=%%", + "exclusionFilter": "", + "isSalesforceTracking": true, + "isMultipart": true, + "isSendLogging": false, + "isStoppedOnJobError": false, + "modified": {}, + "preHeader": "%%=treatascontent(@preheader)=%%\n", + "priority": 4, + "sendClassificationId": "95da425b-a06f-e611-96fe-38eaa7142c61", + "throttleOpens": "1/1/0001 12:00:00 AM", + "throttleCloses": "1/1/0001 12:00:00 AM", + "deliveryProfileId": "163f8417-13f7-e911-a2d8-1402ec938a35", + "senderProfileId": "a75d452b-7ef4-eb11-b82d-48df37d1da95", + "isTrackingClicks": true, + "publicationListId": 15 + }, + "triggeredSendId": "6a2f70c5-2561-ef11-b876-f40343c95928", + "triggeredSendKey": "testExisting_temail_notPublished" + }, + "metaData": { + "highThroughput": { + "definitionKey": "testExisting_temail_notPublished", + "dataExtensionId": "3c3a54a5-d55f-ef11-b876-f40343c95928" + }, + "isConfigured": true, + "sections": {} + }, + "schema": { + "arguments": { + "requestID": { + "dataType": "Text", + "isNullable": true, + "direction": "Out", + "readOnly": false, + "access": "Hidden" + }, + "messageKey": { + "dataType": "Text", + "isNullable": true, + "direction": "Out", + "readOnly": false, + "access": "Hidden" + }, + "activityId": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "definitionId": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": true, + "access": "Hidden" + }, + "emailSubjectDataBound": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": true, + "access": "Hidden" + }, + "contactId": { + "dataType": "Number", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "contactKey": { + "dataType": "Text", + "isNullable": false, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "emailAddress": { + "dataType": "Text", + "isNullable": false, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "sourceCustomObjectId": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "sourceCustomObjectKey": { + "dataType": "LongNumber", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "fieldType": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "eventData": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "obfuscationProperties": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "customObjectKey": { + "dataType": "LongNumber", + "isNullable": true, + "direction": "In", + "readOnly": true, + "access": "Hidden" + }, + "definitionInstanceId": { + "dataType": "Text", + "isNullable": false, + "direction": "In", + "readOnly": false, + "access": "Hidden" + } + } + } + } + ], + "triggers": [ + { + "id": "64a93832-fd23-487e-b585-8f3af3b5b6eb", + "key": "TRIGGER", + "name": "TRIGGER", + "description": "", + "type": "transactional-api", + "outcomes": [], + "arguments": {}, + "configurationArguments": {}, + "metaData": { + "chainType": "none", + "configurationRequired": false, + "iconUrl": "/images/icon_journeyBuilder-event-transactional-blue.svg", + "title": "Transactional API Event", + "category": "Transactional", + "entrySourceGroupConfigUrl": "null" + } + } + ], + "goals": [], + "exits": [], + "notifiers": [], + "stats": { + "currentPopulation": 0, + "cumulativePopulation": 0, + "metGoal": 0, + "metExitCriteria": 0, + "goalPerformance": 0 + }, + "entryMode": "MultipleEntries", + "definitionType": "Transactional", + "channel": "email", + "defaults": { + "properties": {} + }, + "metaData": { + "dataSource": "ContactsModel", + "highThroughputSending": { + "email": false + } + }, + "executionMode": "Production", + "categoryId": 6298, + "status": "Published", + "definitionId": "d4a900fe-3a8f-4cc5-9a49-81286e3e2cd2", + "scheduledStatus": "Draft" +} diff --git a/test/resources/9999999/interaction/v1/interactions/key_testExisting_temail_notPublished/put-response.json b/test/resources/9999999/interaction/v1/interactions/key_testExisting_temail_notPublished/put-response.json new file mode 100644 index 000000000..006a29e51 --- /dev/null +++ b/test/resources/9999999/interaction/v1/interactions/key_testExisting_temail_notPublished/put-response.json @@ -0,0 +1,226 @@ +{ + "id": "d4a900fe-3a8f-4cc5-9a49-81286e3e2cd2", + "key": "testExisting_temail_notPublished", + "name": "testExisting_temail_notPublished", + "lastPublishedDate": "0001-01-01T00:00:00", + "description": "", + "version": 1, + "workflowApiVersion": 1, + "createdDate": "0001-01-01T00:00:00", + "modifiedDate": "2024-08-23T02:00:44.57", + "activities": [ + { + "id": "4ae63473-ea1e-4963-a257-6fea45a9038a", + "key": "EMAILV2-3", + "name": "my email activity", + "description": "", + "type": "EMAILV2", + "outcomes": [ + { + "key": "067f20ba-af36-4401-99d8-934100e1935d", + "arguments": {}, + "metaData": { + "invalid": false + } + } + ], + "arguments": {}, + "configurationArguments": { + "applicationExtensionKey": "jb-email-activity", + "isModified": true, + "triggeredSend": { + "autoAddSubscribers": true, + "autoUpdateSubscribers": true, + "bccEmail": "", + "ccEmail": "", + "created": {}, + "domainExclusions": [], + "dynamicEmailSubject": "%%=treatascontent(@subject)=%%", + "emailId": 531213, + "emailSubject": "%%=treatascontent(@subject)=%%", + "exclusionFilter": "", + "isSalesforceTracking": true, + "isMultipart": true, + "isSendLogging": false, + "isStoppedOnJobError": false, + "modified": {}, + "preHeader": "%%=treatascontent(@preheader)=%%\n", + "priority": 4, + "sendClassificationId": "95da425b-a06f-e611-96fe-38eaa7142c61", + "throttleOpens": "1/1/0001 12:00:00 AM", + "throttleCloses": "1/1/0001 12:00:00 AM", + "deliveryProfileId": "163f8417-13f7-e911-a2d8-1402ec938a35", + "senderProfileId": "a75d452b-7ef4-eb11-b82d-48df37d1da95", + "isTrackingClicks": true, + "publicationListId": 15 + }, + "triggeredSendId": "6a2f70c5-2561-ef11-b876-f40343c95928", + "triggeredSendKey": "testExisting_temail_notPublished" + }, + "metaData": { + "highThroughput": { + "definitionKey": "testExisting_temail_notPublished", + "dataExtensionId": "3c3a54a5-d55f-ef11-b876-f40343c95928" + }, + "isConfigured": true, + "sections": {} + }, + "schema": { + "arguments": { + "requestID": { + "dataType": "Text", + "isNullable": true, + "direction": "Out", + "readOnly": false, + "access": "Hidden" + }, + "messageKey": { + "dataType": "Text", + "isNullable": true, + "direction": "Out", + "readOnly": false, + "access": "Hidden" + }, + "activityId": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "definitionId": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": true, + "access": "Hidden" + }, + "emailSubjectDataBound": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": true, + "access": "Hidden" + }, + "contactId": { + "dataType": "Number", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "contactKey": { + "dataType": "Text", + "isNullable": false, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "emailAddress": { + "dataType": "Text", + "isNullable": false, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "sourceCustomObjectId": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "sourceCustomObjectKey": { + "dataType": "LongNumber", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "fieldType": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "eventData": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "obfuscationProperties": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "customObjectKey": { + "dataType": "LongNumber", + "isNullable": true, + "direction": "In", + "readOnly": true, + "access": "Hidden" + }, + "definitionInstanceId": { + "dataType": "Text", + "isNullable": false, + "direction": "In", + "readOnly": false, + "access": "Hidden" + } + } + } + } + ], + "triggers": [ + { + "id": "64a93832-fd23-487e-b585-8f3af3b5b6eb", + "key": "TRIGGER", + "name": "TRIGGER", + "description": "", + "type": "transactional-api", + "outcomes": [], + "arguments": {}, + "configurationArguments": {}, + "metaData": { + "chainType": "none", + "configurationRequired": false, + "iconUrl": "/images/icon_journeyBuilder-event-transactional-blue.svg", + "title": "Transactional API Event", + "category": "Transactional", + "entrySourceGroupConfigUrl": "null" + } + } + ], + "goals": [], + "exits": [], + "notifiers": [], + "stats": { + "currentPopulation": 0, + "cumulativePopulation": 0, + "metGoal": 0, + "metExitCriteria": 0, + "goalPerformance": 0 + }, + "entryMode": "MultipleEntries", + "definitionType": "Transactional", + "channel": "email", + "defaults": { + "properties": {} + }, + "metaData": { + "dataSource": "ContactsModel", + "highThroughputSending": { + "email": false + } + }, + "executionMode": "Production", + "categoryId": 6298, + "status": "Draft", + "definitionId": "d4a900fe-3a8f-4cc5-9a49-81286e3e2cd2", + "scheduledStatus": "Draft" +} diff --git a/test/resources/9999999/interaction/v1/interactions/key_testNew_temail_notPublished/get-response.json b/test/resources/9999999/interaction/v1/interactions/key_testNew_temail_notPublished/get-response.json new file mode 100644 index 000000000..dcba0b0e5 --- /dev/null +++ b/test/resources/9999999/interaction/v1/interactions/key_testNew_temail_notPublished/get-response.json @@ -0,0 +1,218 @@ +{ + "id": "4c39662b-7c47-4df4-8bd6-65f01c313e8c", + "key": "testNew_temail_notPublished", + "name": "testNew_temail_notPublished", + "lastPublishedDate": "2025-01-31T03:46:39.267", + "description": "", + "version": 1, + "workflowApiVersion": 1, + "createdDate": "2025-01-31T03:46:39.267", + "modifiedDate": "2025-01-31T03:46:39.267", + "activities": [ + { + "id": "1ce8a9e3-bee4-43e3-88a5-a1b3d21f1813", + "key": "EMAILV2-1", + "name": "testNew_temail_notPublished_24Q3", + "description": "", + "type": "EMAILV2", + "outcomes": [ + { + "key": "920e8b4c-1598-48d0-b2c4-8a5072e0b738", + "arguments": {}, + "metaData": { + "invalid": false + } + } + ], + "arguments": {}, + "configurationArguments": { + "applicationExtensionKey": "jb-email-activity", + "isModified": true, + "triggeredSend": { + "autoAddSubscribers": true, + "autoUpdateSubscribers": true, + "bccEmail": "", + "ccEmail": "", + "created": {}, + "domainExclusions": [], + "dynamicEmailSubject": "%%=treatascontent(@subject)=%%", + "emailSubject": "%%=treatascontent(@subject)=%%", + "exclusionFilter": "", + "isMultipart": true, + "isSalesforceTracking": true, + "isSendLogging": false, + "isStoppedOnJobError": false, + "isTrackingClicks": true, + "modified": {}, + "preHeader": "%%=treatascontent(@preheader)=%%\n", + "throttleCloses": "1/1/0001 12:00:00 AM", + "throttleOpens": "1/1/0001 12:00:00 AM", + "throttleLimit": 0, + "publicationListId": 15, + "senderProfileId": "a75d452b-7ef4-eb11-b82d-48df37d1da95", + "sendClassificationId": "95da425b-a06f-e611-96fe-38eaa7142c61", + "deliveryProfileId": "163f8417-13f7-e911-a2d8-1402ec938a35", + "priority": 4, + "emailId": 531213 + }, + "triggeredSendId": "6a2f70c5-2561-ef11-b876-f40343c95929" + }, + "metaData": { + "highThroughput": { + "definitionKey": "testNew_temail_notPublished", + "dataExtensionId": "21711373-72c1-ec11-b83b-48df37d1deb7" + }, + "isConfigured": true + }, + "schema": { + "arguments": { + "requestID": { + "dataType": "Text", + "isNullable": true, + "direction": "Out", + "readOnly": false, + "access": "Hidden" + }, + "messageKey": { + "dataType": "Text", + "isNullable": true, + "direction": "Out", + "readOnly": false, + "access": "Hidden" + }, + "activityId": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "definitionId": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": true, + "access": "Hidden" + }, + "emailSubjectDataBound": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": true, + "access": "Hidden" + }, + "contactId": { + "dataType": "Number", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "contactKey": { + "dataType": "Text", + "isNullable": false, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "emailAddress": { + "dataType": "Text", + "isNullable": false, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "sourceCustomObjectId": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "sourceCustomObjectKey": { + "dataType": "LongNumber", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "fieldType": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "eventData": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "obfuscationProperties": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "customObjectKey": { + "dataType": "LongNumber", + "isNullable": true, + "direction": "In", + "readOnly": true, + "access": "Hidden" + }, + "definitionInstanceId": { + "dataType": "Text", + "isNullable": false, + "direction": "In", + "readOnly": false, + "access": "Hidden" + } + } + } + } + ], + "triggers": [ + { + "id": "6a33ad9b-a46d-4758-902b-35ce1759650d", + "key": "TRIGGER", + "name": "TRIGGER", + "description": "", + "type": "transactional-api", + "outcomes": [], + "arguments": {}, + "configurationArguments": {}, + "metaData": { + "chainType": "none", + "configurationRequired": false, + "iconUrl": "/images/icon_journeyBuilder-event-transactional-blue.svg", + "title": "Transactional API Event", + "category": "Transactional", + "entrySourceGroupConfigUrl": "null" + } + } + ], + "goals": [], + "exits": [], + "notifiers": [], + "entryMode": "MultipleEntries", + "definitionType": "Transactional", + "channel": "email", + "defaults": { + "properties": {} + }, + "metaData": { + "dataSource": "ContactsModel", + "highThroughputSending": { + "email": false + } + }, + "executionMode": "Production", + "categoryId": 6298, + "status": "Published", + "definitionId": "4c39662b-7c47-4df4-8bd6-65f01c313e8c", + "scheduledStatus": "Draft" +} diff --git a/test/resources/9999999/interaction/v1/interactions/post-response.json b/test/resources/9999999/interaction/v1/interactions/post-response.json new file mode 100644 index 000000000..73e175d9a --- /dev/null +++ b/test/resources/9999999/interaction/v1/interactions/post-response.json @@ -0,0 +1,216 @@ +{ + "id": "4c39662b-7c47-4df4-8bd6-65f01c313e8c", + "key": "testNew_temail_notPublished", + "name": "testNew_temail_notPublished", + "lastPublishedDate": "0001-01-01T00:00:00", + "description": "", + "version": 1, + "workflowApiVersion": 1, + "createdDate": "2025-01-31T03:46:39.267", + "modifiedDate": "2025-01-31T03:46:39.267", + "activities": [ + { + "id": "1ce8a9e3-bee4-43e3-88a5-a1b3d21f1813", + "key": "EMAILV2-1", + "name": "Email", + "description": "", + "type": "EMAILV2", + "outcomes": [ + { + "key": "b9a05a3c-0bd6-49b6-a4a1-4b8f8d08da6a", + "arguments": {}, + "metaData": { + "invalid": false + } + } + ], + "arguments": {}, + "configurationArguments": { + "applicationExtensionKey": "jb-email-activity", + "isModified": true, + "triggeredSend": { + "autoAddSubscribers": true, + "autoUpdateSubscribers": true, + "bccEmail": "", + "ccEmail": "", + "created": {}, + "domainExclusions": [], + "dynamicEmailSubject": "%%=treatascontent(@subject)=%%", + "emailSubject": "%%=treatascontent(@subject)=%%", + "exclusionFilter": "", + "isMultipart": true, + "isSalesforceTracking": true, + "isSendLogging": false, + "isStoppedOnJobError": false, + "isTrackingClicks": true, + "modified": {}, + "preHeader": "%%=treatascontent(@preheader)=%%\n", + "throttleCloses": "1/1/0001 12:00:00 AM", + "throttleOpens": "1/1/0001 12:00:00 AM", + "publicationListId": 15, + "senderProfileId": "a75d452b-7ef4-eb11-b82d-48df37d1da95", + "sendClassificationId": "95da425b-a06f-e611-96fe-38eaa7142c61", + "deliveryProfileId": "163f8417-13f7-e911-a2d8-1402ec938a35", + "priority": 4, + "emailId": 531213 + } + }, + "metaData": { + "highThroughput": { + "definitionKey": "testNew_temail_notPublished", + "dataExtensionId": "21711373-72c1-ec11-b83b-48df37d1deb7" + }, + "isConfigured": false + }, + "schema": { + "arguments": { + "requestID": { + "dataType": "Text", + "isNullable": true, + "direction": "Out", + "readOnly": false, + "access": "Hidden" + }, + "messageKey": { + "dataType": "Text", + "isNullable": true, + "direction": "Out", + "readOnly": false, + "access": "Hidden" + }, + "activityId": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "definitionId": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": true, + "access": "Hidden" + }, + "emailSubjectDataBound": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": true, + "access": "Hidden" + }, + "contactId": { + "dataType": "Number", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "contactKey": { + "dataType": "Text", + "isNullable": false, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "emailAddress": { + "dataType": "Text", + "isNullable": false, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "sourceCustomObjectId": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "sourceCustomObjectKey": { + "dataType": "LongNumber", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "fieldType": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "eventData": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "obfuscationProperties": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "customObjectKey": { + "dataType": "LongNumber", + "isNullable": true, + "direction": "In", + "readOnly": true, + "access": "Hidden" + }, + "definitionInstanceId": { + "dataType": "Text", + "isNullable": false, + "direction": "In", + "readOnly": false, + "access": "Hidden" + } + } + } + } + ], + "triggers": [ + { + "id": "6a33ad9b-a46d-4758-902b-35ce1759650d", + "key": "TRIGGER", + "name": "TRIGGER", + "description": "", + "type": "transactional-api", + "outcomes": [], + "arguments": {}, + "configurationArguments": {}, + "metaData": { + "chainType": "none", + "configurationRequired": false, + "iconUrl": "/images/icon_journeyBuilder-event-transactional-blue.svg", + "title": "Transactional API Event", + "category": "Transactional", + "entrySourceGroupConfigUrl": "null" + } + } + ], + "goals": [], + "exits": [], + "notifiers": [], + "entryMode": "MultipleEntries", + "definitionType": "Transactional", + "channel": "email", + "defaults": { + "properties": {} + }, + "metaData": { + "dataSource": "ContactsModel", + "highThroughputSending": { + "email": false + } + }, + "executionMode": "Production", + "categoryId": 6298, + "status": "Draft", + "definitionId": "4c39662b-7c47-4df4-8bd6-65f01c313e8c", + "scheduledStatus": "Draft" +} diff --git a/test/resources/9999999/interaction/v1/interactions/publishAsync/0175b971-71a3-4d8e-98ac-48121f3fbf4f/post-response-versionNumber=1.json b/test/resources/9999999/interaction/v1/interactions/publishAsync/0175b971-71a3-4d8e-98ac-48121f3fbf4f/post-response-versionNumber=1.json new file mode 100644 index 000000000..0fa947394 --- /dev/null +++ b/test/resources/9999999/interaction/v1/interactions/publishAsync/0175b971-71a3-4d8e-98ac-48121f3fbf4f/post-response-versionNumber=1.json @@ -0,0 +1,4 @@ +{ + "statusUrl": "/interaction/v1/interactions/publishStatus/45f06c0a-3ed2-48b2-a6a8-b5119253f01c", + "statusId": "45f06c0a-3ed2-48b2-a6a8-b5119253f01c" +} diff --git a/test/resources/9999999/interaction/v1/interactions/publishAsync/0175b971-71a3-4d8e-98ac-48121f3fbf4f/post-response-versionNumber=3.json b/test/resources/9999999/interaction/v1/interactions/publishAsync/0175b971-71a3-4d8e-98ac-48121f3fbf4f/post-response-versionNumber=3.json new file mode 100644 index 000000000..0fa947394 --- /dev/null +++ b/test/resources/9999999/interaction/v1/interactions/publishAsync/0175b971-71a3-4d8e-98ac-48121f3fbf4f/post-response-versionNumber=3.json @@ -0,0 +1,4 @@ +{ + "statusUrl": "/interaction/v1/interactions/publishStatus/45f06c0a-3ed2-48b2-a6a8-b5119253f01c", + "statusId": "45f06c0a-3ed2-48b2-a6a8-b5119253f01c" +} diff --git a/test/resources/9999999/interaction/v1/interactions/publishStatus/45f06c0a-3ed2-48b2-a6a8-b5119253f01c/get-response-failed.json b/test/resources/9999999/interaction/v1/interactions/publishStatus/45f06c0a-3ed2-48b2-a6a8-b5119253f01c/get-response-failed.json new file mode 100644 index 000000000..c157b4968 --- /dev/null +++ b/test/resources/9999999/interaction/v1/interactions/publishStatus/45f06c0a-3ed2-48b2-a6a8-b5119253f01c/get-response-failed.json @@ -0,0 +1,34 @@ +{ + "status": "Error", + "errors": [ + { + "errorDetail": "The default email or mobile address in Journey Settings is invalid. Select a different one.", + "errorCode": "121226", + "errorType": "Error", + "additionalInfo": {} + }, + { + "errorDetail": "Email Activity: CCE OpsIssue Satisfaction Email -- The email specified for the job did not pass validation. EmailID: 72604 An unverified from email address was detected. ", + "errorCode": "121008", + "errorType": "Error", + "additionalInfo": { + "activityKey": "EMAILV2-1", + "activityId": "620dbe27-665a-49a3-ad61-ceea5aab720f", + "activityType": "EMAILV2", + "definitionId": "2d5f37b8-7acf-4ac4-b76a-74690255600c" + } + } + ], + "warnings": [ + { + "errorDetail": "Last modified date for email activity is more then 6 months ago. Please review the content or use path optimizer to test it.", + "errorCode": "121546", + "errorType": "Warning", + "additionalInfo": { + "activityKey": "EMAILV2-1", + "activityId": "620dbe27-665a-49a3-ad61-ceea5aab720f", + "activityType": "EMAILV2" + } + } + ] +} diff --git a/test/resources/9999999/interaction/v1/interactions/publishStatus/45f06c0a-3ed2-48b2-a6a8-b5119253f01c/get-response-success.json b/test/resources/9999999/interaction/v1/interactions/publishStatus/45f06c0a-3ed2-48b2-a6a8-b5119253f01c/get-response-success.json new file mode 100644 index 000000000..a9eeca73d --- /dev/null +++ b/test/resources/9999999/interaction/v1/interactions/publishStatus/45f06c0a-3ed2-48b2-a6a8-b5119253f01c/get-response-success.json @@ -0,0 +1,5 @@ +{ + "status": "PublishCompleted", + "errors": [], + "warnings": [] +} diff --git a/test/resources/9999999/interaction/v1/interactions/publishStatus/45f06c0a-3ed2-48b2-a6a8-b5119253f01c/get-response-successWarnings.json b/test/resources/9999999/interaction/v1/interactions/publishStatus/45f06c0a-3ed2-48b2-a6a8-b5119253f01c/get-response-successWarnings.json new file mode 100644 index 000000000..dd05822b9 --- /dev/null +++ b/test/resources/9999999/interaction/v1/interactions/publishStatus/45f06c0a-3ed2-48b2-a6a8-b5119253f01c/get-response-successWarnings.json @@ -0,0 +1,36 @@ +{ + "status": "PublishCompleted", + "errors": [], + "warnings": [ + { + "errorDetail": "The journey has a long wait (1 days), please consider reducing wait to under 4 minutes.", + "errorCode": "121547", + "errorType": "Warning", + "additionalInfo": { + "activityKey": "WAITBYDURATION-5", + "activityId": "2d0b5dbf-14cc-4635-acee-64071c8e1022", + "activityType": "WAIT" + } + }, + { + "errorDetail": "The journey has a long wait (1 days), please consider reducing wait to under 4 minutes.", + "errorCode": "121547", + "errorType": "Warning", + "additionalInfo": { + "activityKey": "WAITBYDURATION-4", + "activityId": "26298616-e89b-4166-8e7e-8417031f276b", + "activityType": "WAIT" + } + }, + { + "errorDetail": "Last modified date for email activity is more then 6 months ago. Please review the content or use path optimizer to test it.", + "errorCode": "121546", + "errorType": "Warning", + "additionalInfo": { + "activityKey": "EMAILV2-1", + "activityId": "966651f8-e1b6-4261-849c-e95589001c75", + "activityType": "EMAILV2" + } + } + ] +} diff --git a/test/resources/9999999/interaction/v1/interactions/transactional/create/post-response.json b/test/resources/9999999/interaction/v1/interactions/transactional/create/post-response.json new file mode 100644 index 000000000..00c4d5506 --- /dev/null +++ b/test/resources/9999999/interaction/v1/interactions/transactional/create/post-response.json @@ -0,0 +1,3 @@ +{ + "errors": [] +} diff --git a/test/resources/9999999/interaction/v1/interactions/transactional/pause/post-response.json b/test/resources/9999999/interaction/v1/interactions/transactional/pause/post-response.json new file mode 100644 index 000000000..00c4d5506 --- /dev/null +++ b/test/resources/9999999/interaction/v1/interactions/transactional/pause/post-response.json @@ -0,0 +1,3 @@ +{ + "errors": [] +} diff --git a/test/resources/9999999/interaction/v1/interactions/transactional/resume/post-response.json b/test/resources/9999999/interaction/v1/interactions/transactional/resume/post-response.json new file mode 100644 index 000000000..00c4d5506 --- /dev/null +++ b/test/resources/9999999/interaction/v1/interactions/transactional/resume/post-response.json @@ -0,0 +1,3 @@ +{ + "errors": [] +} diff --git a/test/resources/9999999/interaction/v1/interactions/validateAsync/0175b971-71a3-4d8e-98ac-48121f3fbf4f/post-response.json b/test/resources/9999999/interaction/v1/interactions/validateAsync/0175b971-71a3-4d8e-98ac-48121f3fbf4f/post-response.json new file mode 100644 index 000000000..2eacf991e --- /dev/null +++ b/test/resources/9999999/interaction/v1/interactions/validateAsync/0175b971-71a3-4d8e-98ac-48121f3fbf4f/post-response.json @@ -0,0 +1,4 @@ +{ + "statusUrl": "/interaction/v1/interactions/validateStatus/45f06c0a-3ed2-48b2-a6a8-b5119253f01c", + "statusId": "45f06c0a-3ed2-48b2-a6a8-b5119253f01c" +} diff --git a/test/resources/9999999/interaction/v1/interactions/validateStatus/45f06c0a-3ed2-48b2-a6a8-b5119253f01c/get-response-failed.json b/test/resources/9999999/interaction/v1/interactions/validateStatus/45f06c0a-3ed2-48b2-a6a8-b5119253f01c/get-response-failed.json new file mode 100644 index 000000000..c157b4968 --- /dev/null +++ b/test/resources/9999999/interaction/v1/interactions/validateStatus/45f06c0a-3ed2-48b2-a6a8-b5119253f01c/get-response-failed.json @@ -0,0 +1,34 @@ +{ + "status": "Error", + "errors": [ + { + "errorDetail": "The default email or mobile address in Journey Settings is invalid. Select a different one.", + "errorCode": "121226", + "errorType": "Error", + "additionalInfo": {} + }, + { + "errorDetail": "Email Activity: CCE OpsIssue Satisfaction Email -- The email specified for the job did not pass validation. EmailID: 72604 An unverified from email address was detected. ", + "errorCode": "121008", + "errorType": "Error", + "additionalInfo": { + "activityKey": "EMAILV2-1", + "activityId": "620dbe27-665a-49a3-ad61-ceea5aab720f", + "activityType": "EMAILV2", + "definitionId": "2d5f37b8-7acf-4ac4-b76a-74690255600c" + } + } + ], + "warnings": [ + { + "errorDetail": "Last modified date for email activity is more then 6 months ago. Please review the content or use path optimizer to test it.", + "errorCode": "121546", + "errorType": "Warning", + "additionalInfo": { + "activityKey": "EMAILV2-1", + "activityId": "620dbe27-665a-49a3-ad61-ceea5aab720f", + "activityType": "EMAILV2" + } + } + ] +} diff --git a/test/resources/9999999/interaction/v1/interactions/validateStatus/45f06c0a-3ed2-48b2-a6a8-b5119253f01c/get-response-success.json b/test/resources/9999999/interaction/v1/interactions/validateStatus/45f06c0a-3ed2-48b2-a6a8-b5119253f01c/get-response-success.json new file mode 100644 index 000000000..ca2c94aa3 --- /dev/null +++ b/test/resources/9999999/interaction/v1/interactions/validateStatus/45f06c0a-3ed2-48b2-a6a8-b5119253f01c/get-response-success.json @@ -0,0 +1,5 @@ +{ + "status": "ValidateCompleted", + "errors": [], + "warnings": [] +} diff --git a/test/resources/9999999/interaction/v1/interactions/validateStatus/45f06c0a-3ed2-48b2-a6a8-b5119253f01c/get-response-successWarnings.json b/test/resources/9999999/interaction/v1/interactions/validateStatus/45f06c0a-3ed2-48b2-a6a8-b5119253f01c/get-response-successWarnings.json new file mode 100644 index 000000000..4b135ee6f --- /dev/null +++ b/test/resources/9999999/interaction/v1/interactions/validateStatus/45f06c0a-3ed2-48b2-a6a8-b5119253f01c/get-response-successWarnings.json @@ -0,0 +1,36 @@ +{ + "status": "ValidateCompleted", + "errors": [], + "warnings": [ + { + "errorDetail": "The journey has a long wait (1 days), please consider reducing wait to under 4 minutes.", + "errorCode": "121547", + "errorType": "Warning", + "additionalInfo": { + "activityKey": "WAITBYDURATION-5", + "activityId": "2d0b5dbf-14cc-4635-acee-64071c8e1022", + "activityType": "WAIT" + } + }, + { + "errorDetail": "The journey has a long wait (1 days), please consider reducing wait to under 4 minutes.", + "errorCode": "121547", + "errorType": "Warning", + "additionalInfo": { + "activityKey": "WAITBYDURATION-4", + "activityId": "26298616-e89b-4166-8e7e-8417031f276b", + "activityType": "WAIT" + } + }, + { + "errorDetail": "Last modified date for email activity is more then 6 months ago. Please review the content or use path optimizer to test it.", + "errorCode": "121546", + "errorType": "Warning", + "additionalInfo": { + "activityKey": "EMAILV2-1", + "activityId": "966651f8-e1b6-4261-849c-e95589001c75", + "activityType": "EMAILV2" + } + } + ] +} diff --git a/test/resources/9999999/interaction/v1/interactions/validateStatus/45f06c0a-3ed2-48b2-a6a8-b5119253f01c/get-response.json b/test/resources/9999999/interaction/v1/interactions/validateStatus/45f06c0a-3ed2-48b2-a6a8-b5119253f01c/get-response.json new file mode 100644 index 000000000..e69de29bb diff --git a/test/resources/9999999/journey/build-expected.json b/test/resources/9999999/journey/build-expected.json new file mode 100644 index 000000000..4ebebe009 --- /dev/null +++ b/test/resources/9999999/journey/build-expected.json @@ -0,0 +1,229 @@ +{ + "key": "testTemplated_journey_Quicksend", + "name": "testTemplated_journey_Quicksend", + "description": "", + "workflowApiVersion": 1, + "modifiedDate": "2024-04-24T12:19:12.803", + "activities": [ + { + "key": "EMAILV2-1", + "name": "testTemplated_asset_mail", + "description": "", + "type": "EMAILV2", + "outcomes": [ + { + "key": "a6b9c1af-cd89-4ce8-ba4f-bd4289188dc2", + "arguments": {}, + "metaData": { "invalid": false } + } + ], + "arguments": {}, + "configurationArguments": { + "isModified": true, + "googleAnalyticsCampaignName": "", + "triggeredSend": { + "autoAddSubscribers": true, + "autoUpdateSubscribers": true, + "bccEmail": [ + "%%= ContentBlockByName(\"Content Builder\\dont strip non ssjs content\") =%%" + ], + "ccEmail": ["%%= ContentBlockByKey(\"testTemplated_asset_htmlblock\") =%%"], + "created": {}, + "description": "my activity info text", + "dynamicEmailSubject": "testTemplated_ dynamic email subject %%= ContentBlockByKey(\"testTemplated_asset_htmlblock\") =%%", + "emailSubject": "testTemplated_ email subject %%= ContentBlockByKey(\"testTemplated_asset_htmlblock\") =%%", + "exclusionFilter": "/* insert ampscript here */ %%= ContentBlockById(1295064) =%%", + "isSalesforceTracking": false, + "isMultipart": true, + "isSendLogging": true, + "isStoppedOnJobError": false, + "keyword": "", + "modified": {}, + "preHeader": "testTemplated_ email preheader %%= ContentBlockByKey(\"testTemplated_asset_htmlblock\") =%%", + "suppressTracking": true, + "throttleLimit": 0, + "throttleOpens": "1/1/0001 12:00:00 AM", + "throttleCloses": "1/1/0001 12:00:00 AM", + "isTrackingClicks": true, + "r__list_PathName": { + "publicationList": "my subscribers/All Subscribers", + "suppressionLists": ["Suppression Lists/testTemplated_suppressionList"] + }, + "r__dataExtension_key": { + "domainExclusions": ["testTemplated_DomainExclusion"] + }, + "r__deliveryProfile_key": "Default", + "r__senderProfile_key": "testTemplated_senderProfile", + "r__sendClassification_key": "testTemplated_sendClassification", + "c__priority": "High", + "r__asset_key": "testTemplated_asset_message" + }, + "applicationExtensionKey": "jb-email-activity" + }, + "metaData": { + "category": "message", + "version": "1.0", + "icon": "https://jb-email-activity.s7.marketingcloudapps.com/img/email-icon.svg", + "iconSmall": "https://jb-email-activity.s7.marketingcloudapps.com/img/email-icon.svg", + "statsContactIcon": null, + "original_icon": "/img/email-icon.svg", + "original_iconSmall": "/img/email-icon.svg", + "sections": {}, + "isConfigured": true + }, + "schema": { + "arguments": { + "requestID": { + "dataType": "Text", + "isNullable": true, + "direction": "Out", + "readOnly": false, + "access": "Hidden" + }, + "messageKey": { + "dataType": "Text", + "isNullable": true, + "direction": "Out", + "readOnly": false, + "access": "Hidden" + }, + "activityId": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "definitionId": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": true, + "access": "Hidden" + }, + "emailSubjectDataBound": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": true, + "access": "Hidden" + }, + "contactId": { + "dataType": "Number", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "contactKey": { + "dataType": "Text", + "isNullable": false, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "emailAddress": { + "dataType": "Text", + "isNullable": false, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "sourceCustomObjectId": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "sourceCustomObjectKey": { + "dataType": "LongNumber", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "fieldType": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "eventData": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "obfuscationProperties": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "customObjectKey": { + "dataType": "LongNumber", + "isNullable": true, + "direction": "In", + "readOnly": true, + "access": "Hidden" + }, + "definitionInstanceId": { + "dataType": "Text", + "isNullable": false, + "direction": "In", + "readOnly": false, + "access": "Hidden" + } + } + } + } + ], + "triggers": [ + { + "key": "TRIGGER", + "name": "TRIGGER", + "description": "", + "type": "EmailAudience", + "outcomes": [], + "arguments": {}, + "configurationArguments": {}, + "metaData": { + "sourceInteractionId": "00000000-0000-0000-0000-000000000000", + "r__event_key": "DEAudience-11be962d-064c-83d9-2804-7d1befc10325", + "chainType": "None", + "configurationRequired": false, + "iconUrl": "/images/icon-data-extension.svg", + "title": "Data Extension", + "entrySourceGroupConfigUrl": "jb:///data/entry/audience/entrysourcegroupconfig.json" + } + } + ], + "goals": [], + "exits": [], + "notifiers": [], + "entryMode": "MultipleEntries", + "definitionType": "Quicksend", + "channel": "email", + "defaults": { + "email": ["{{Event.DEAudience-11be962d-064c-83d9-2804-7d1befc10325.\"Email\"}}"], + "properties": { + "analyticsTracking": { + "enabled": true, + "analyticsType": "google", + "urlDomainsToTrack": [] + } + } + }, + "metaData": { + "dataSource": "ContactsModel", + "isScheduleSet": true, + "highThroughputSending": { "email": false } + }, + "executionMode": "Production", + "scheduledStatus": "Draft", + "r__folder_Path": "my journeys" +} diff --git a/test/resources/9999999/journey/create-transactionaEmail-publish-expected.json b/test/resources/9999999/journey/create-transactionaEmail-publish-expected.json new file mode 100644 index 000000000..337d2e1db --- /dev/null +++ b/test/resources/9999999/journey/create-transactionaEmail-publish-expected.json @@ -0,0 +1,216 @@ +{ + "key": "testNew_temail_notPublished", + "name": "testNew_temail_notPublished", + "description": "", + "workflowApiVersion": 1, + "version": 1, + "lastPublishedDate": "2025-01-31T03:46:39.267", + "modifiedDate": "2025-01-31T03:46:39.267", + "createdDate": "2025-01-31T03:46:39.267", + "activities": [ + { + "key": "EMAILV2-1", + "name": "testNew_temail_notPublished_24Q3", + "description": "", + "type": "EMAILV2", + "outcomes": [ + { + "key": "920e8b4c-1598-48d0-b2c4-8a5072e0b738", + "arguments": {}, + "metaData": { + "invalid": false + } + } + ], + "arguments": {}, + "configurationArguments": { + "applicationExtensionKey": "jb-email-activity", + "isModified": true, + "triggeredSend": { + "autoAddSubscribers": true, + "autoUpdateSubscribers": true, + "bccEmail": [], + "c__priority": "Medium", + "ccEmail": [], + "created": {}, + "domainExclusions": [], + "dynamicEmailSubject": "%%=treatascontent(@subject)=%%", + "emailSubject": "%%=treatascontent(@subject)=%%", + "exclusionFilter": "", + "isMultipart": true, + "isSalesforceTracking": true, + "isSendLogging": false, + "isStoppedOnJobError": false, + "isTrackingClicks": true, + "modified": {}, + "preHeader": "%%=treatascontent(@preheader)=%%\n", + "r__asset_key": "testExisting_asset_message", + "r__asset_name_readOnly": "testExisting_asset_message", + "r__deliveryProfile_key": "Default", + "r__list_PathName": { + "publicationList": "my subscribers/All Subscribers" + }, + "r__sendClassification_key": "testExisting_sendClassification", + "r__senderProfile_key": "testExisting_senderProfile", + "throttleCloses": "1/1/0001 12:00:00 AM", + "throttleLimit": 0, + "throttleOpens": "1/1/0001 12:00:00 AM" + }, + "r__transactionalEmail_key": "testNew_temail_notPublished" + }, + "metaData": { + "highThroughput": { + "r__dataExtension_key": "testExisting_dataExtension" + }, + "isConfigured": true + }, + "schema": { + "arguments": { + "requestID": { + "dataType": "Text", + "isNullable": true, + "direction": "Out", + "readOnly": false, + "access": "Hidden" + }, + "messageKey": { + "dataType": "Text", + "isNullable": true, + "direction": "Out", + "readOnly": false, + "access": "Hidden" + }, + "activityId": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "definitionId": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": true, + "access": "Hidden" + }, + "emailSubjectDataBound": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": true, + "access": "Hidden" + }, + "contactId": { + "dataType": "Number", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "contactKey": { + "dataType": "Text", + "isNullable": false, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "emailAddress": { + "dataType": "Text", + "isNullable": false, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "sourceCustomObjectId": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "sourceCustomObjectKey": { + "dataType": "LongNumber", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "fieldType": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "eventData": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "obfuscationProperties": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "customObjectKey": { + "dataType": "LongNumber", + "isNullable": true, + "direction": "In", + "readOnly": true, + "access": "Hidden" + }, + "definitionInstanceId": { + "dataType": "Text", + "isNullable": false, + "direction": "In", + "readOnly": false, + "access": "Hidden" + } + } + } + } + ], + "triggers": [ + { + "key": "TRIGGER", + "name": "TRIGGER", + "description": "", + "type": "transactional-api", + "outcomes": [], + "arguments": {}, + "configurationArguments": {}, + "metaData": { + "chainType": "none", + "configurationRequired": false, + "iconUrl": "/images/icon_journeyBuilder-event-transactional-blue.svg", + "title": "Transactional API Event", + "category": "Transactional", + "entrySourceGroupConfigUrl": "null" + } + } + ], + "goals": [], + "exits": [], + "notifiers": [], + "entryMode": "MultipleEntries", + "definitionType": "Transactional", + "channel": "email", + "defaults": { + "properties": {} + }, + "metaData": { + "dataSource": "ContactsModel", + "highThroughputSending": { + "email": false + } + }, + "executionMode": "Production", + "scheduledStatus": "Draft", + "status": "Published", + "r__folder_Path": "my journeys" +} diff --git a/test/resources/9999999/journey/get-multistep-expected.json b/test/resources/9999999/journey/get-multistep-expected.json new file mode 100644 index 000000000..a281fc5db --- /dev/null +++ b/test/resources/9999999/journey/get-multistep-expected.json @@ -0,0 +1,414 @@ +{ + "key": "testExisting_journey_Multistep", + "name": "testExisting_journey_Multistep", + "lastPublishedDate": "0001-01-01T00:00:00", + "description": "", + "version": 1, + "workflowApiVersion": 1, + "createdDate": "2024-05-04T05:54:48.027", + "modifiedDate": "2024-05-04T17:25:57.9", + "activities": [ + { + "key": "EMAILV2-1", + "name": "my custom activity name", + "description": "", + "type": "EMAILV2", + "outcomes": [ + { + "key": "ff60a294-3804-4165-85cd-c7c19c8e3a6d", + "next": "WAITBYDURATION-1", + "arguments": {}, + "metaData": { "invalid": false } + } + ], + "arguments": {}, + "configurationArguments": { + "applicationExtensionKey": "jb-email-activity", + "isModified": true, + "googleAnalyticsCampaignName": "", + "r__triggeredSend_key": "testExisting_triggeredSend", + "triggeredSend": { + "autoAddSubscribers": false, + "autoUpdateSubscribers": false, + "bccEmail": [], + "ccEmail": [], + "created": { "name": "", "date": "" }, + "description": "my custom description", + "domainExclusions": [], + "dynamicEmailSubject": "You are successfully unsubscribed", + "emailSubject": "You are successfully unsubscribed", + "exclusionFilter": "", + "isSalesforceTracking": false, + "isMultipart": false, + "isSendLogging": true, + "isStoppedOnJobError": false, + "modified": { "name": "", "date": "" }, + "preHeader": "testExisting_ email preheader", + "throttleOpens": "1/1/0001 12:00:00 AM", + "throttleCloses": "1/1/0001 12:00:00 AM", + "isTrackingClicks": true, + "suppressTracking": false, + "triggeredSendStatus": "New", + "r__list_PathName": { "publicationList": "my subscribers/All Subscribers" }, + "r__deliveryProfile_key": "Default", + "r__senderProfile_key": "testExisting_senderProfile", + "r__sendClassification_key": "testExisting_sendClassification", + "c__priority": "Medium", + "r__asset_name_readOnly": "testExisting_asset_message", + "r__asset_key": "testExisting_asset_message", + "r__triggeredSend_key": "testExisting_triggeredSend" + } + }, + "metaData": { + "category": "message", + "version": "1.0", + "icon": "https://jb-email-activity.s7.marketingcloudapps.com/img/email-icon.svg", + "iconSmall": "https://jb-email-activity.s7.marketingcloudapps.com/img/email-icon.svg", + "statsContactIcon": null, + "original_icon": "/img/email-icon.svg", + "original_iconSmall": "/img/email-icon.svg", + "sections": {}, + "isConfigured": true + }, + "schema": { + "arguments": { + "requestID": { + "dataType": "Text", + "isNullable": true, + "direction": "Out", + "readOnly": false, + "access": "Hidden" + }, + "messageKey": { + "dataType": "Text", + "isNullable": true, + "direction": "Out", + "readOnly": false, + "access": "Hidden" + }, + "activityId": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "definitionId": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": true, + "access": "Hidden" + }, + "emailSubjectDataBound": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": true, + "access": "Hidden" + }, + "contactId": { + "dataType": "Number", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "contactKey": { + "dataType": "Text", + "isNullable": false, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "emailAddress": { + "dataType": "Text", + "isNullable": false, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "sourceCustomObjectId": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "sourceCustomObjectKey": { + "dataType": "LongNumber", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "fieldType": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "eventData": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "obfuscationProperties": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "customObjectKey": { + "dataType": "LongNumber", + "isNullable": true, + "direction": "In", + "readOnly": true, + "access": "Hidden" + }, + "definitionInstanceId": { + "dataType": "Text", + "isNullable": false, + "direction": "In", + "readOnly": false, + "access": "Hidden" + } + } + } + }, + { + "key": "MULTICRITERIADECISIONV2-1", + "name": "", + "description": "", + "type": "MULTICRITERIADECISION", + "outcomes": [ + { + "key": "default_path_1", + "next": "EMAILV2-1", + "arguments": {}, + "metaData": { + "label": "send message", + "skipI18n": true, + "isLabelFromConversion": false, + "criteriaDescription": "Email is not null" + } + }, + { + "key": "remainder_path", + "next": "WAITBYDURATION-2", + "arguments": {}, + "metaData": { "label": null } + } + ], + "arguments": {}, + "configurationArguments": { + "criteria": { + "default_path_1": "<FilterDefinition><ConditionSet Operator=\"AND\" ConditionSetName=\"Individual Filter Grouping\"><Condition IsEphemeralAttribute=\"true\" Key=\"Event.DEAudience-2e3c73b6-48cc-2ec0-5522-48636e1a236e.Email\" Operator=\"IsNotNull\" UiMetaData=\"{}\"><Value><![CDATA[]]></Value></Condition></ConditionSet></FilterDefinition>" + }, + "schemaVersionId": "252" + }, + "metaData": { "isConfigured": true }, + "schema": { + "arguments": { + "actualChoice": { + "dataType": "Number", + "isNullable": false, + "direction": "Out", + "readOnly": false, + "access": "Hidden" + }, + "filterResult": { + "dataType": "Text", + "isNullable": false, + "direction": "In", + "readOnly": true, + "access": "Hidden" + } + } + } + }, + { + "key": "WAITBYDURATION-1", + "name": "1 day", + "description": "", + "type": "WAIT", + "outcomes": [ + { + "key": "97af222a-450a-429e-8925-649b72f01ccf", + "arguments": {}, + "metaData": { "invalid": false } + } + ], + "arguments": {}, + "configurationArguments": { "waitDuration": 1, "waitUnit": "DAYS" }, + "metaData": { "isConfigured": true, "uiType": "WAITBYDURATION" }, + "schema": { + "arguments": { + "endDate": { + "dataType": "Date", + "isNullable": false, + "direction": "Out", + "readOnly": false, + "access": "Hidden" + }, + "waitEndDateAttributeDataBound": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "waitDefinitionId": { + "dataType": "Text", + "isNullable": false, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "waitForEventId": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "executionMode": { + "dataType": "Text", + "isNullable": false, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "startActivityKey": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "waitQueueId": { + "dataType": "LongNumber", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + } + } + } + }, + { + "key": "WAITBYDURATION-2", + "name": "", + "description": "", + "type": "WAIT", + "outcomes": [ + { + "key": "a0908f9f-bc3c-47f7-9489-7fef5af25ce3", + "arguments": {}, + "metaData": { "invalid": false } + } + ], + "arguments": {}, + "configurationArguments": { "waitDuration": 1, "waitUnit": "DAYS" }, + "metaData": { "isConfigured": true, "uiType": "WAITBYDURATION" }, + "schema": { + "arguments": { + "endDate": { + "dataType": "Date", + "isNullable": false, + "direction": "Out", + "readOnly": false, + "access": "Hidden" + }, + "waitEndDateAttributeDataBound": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "waitDefinitionId": { + "dataType": "Text", + "isNullable": false, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "waitForEventId": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "executionMode": { + "dataType": "Text", + "isNullable": false, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "startActivityKey": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "waitQueueId": { + "dataType": "LongNumber", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + } + } + } + } + ], + "triggers": [ + { + "key": "TRIGGER", + "name": "TRIGGER", + "description": "", + "type": "EmailAudience", + "outcomes": [], + "arguments": {}, + "configurationArguments": {}, + "metaData": { + "r__event_key": "DEAudience-2e3c73b6-48cc-2ec0-5522-48636e1a236e", + "chainType": "None", + "configurationRequired": false, + "iconUrl": "/images/icon-data-extension.svg", + "title": "Data Extension", + "entrySourceGroupConfigUrl": "jb:///data/entry/audience/entrysourcegroupconfig.json", + "sourceInteractionId": "00000000-0000-0000-0000-000000000000" + } + } + ], + "goals": [], + "exits": [], + "notifiers": [], + "entryMode": "NotSet", + "definitionType": "Multistep", + "channel": "", + "defaults": { + "email": ["{{Event.DEAudience-2e3c73b6-48cc-2ec0-5522-48636e1a236e.\"Email\"}}"], + "properties": { + "analyticsTracking": { + "enabled": true, + "analyticsType": "google", + "urlDomainsToTrack": [] + } + } + }, + "metaData": { "dataSource": "ContactsModel", "highThroughputSending": { "email": false } }, + "executionMode": "Production", + "status": "Draft", + "scheduledStatus": "Draft", + "r__folder_Path": "my journeys" +} diff --git a/test/resources/9999999/journey/get-published-expected.json b/test/resources/9999999/journey/get-published-expected.json new file mode 100644 index 000000000..08cd197c9 --- /dev/null +++ b/test/resources/9999999/journey/get-published-expected.json @@ -0,0 +1,216 @@ +{ + "activities": [ + { + "arguments": {}, + "configurationArguments": { + "applicationExtensionKey": "jb-email-activity", + "isModified": true, + "r__transactionalEmail_key": "testExisting_temail_notPublished", + "triggeredSend": { + "autoAddSubscribers": true, + "autoUpdateSubscribers": true, + "bccEmail": [], + "c__priority": "Medium", + "ccEmail": [], + "created": {}, + "domainExclusions": [], + "dynamicEmailSubject": "%%=treatascontent(@subject)=%%", + "emailSubject": "%%=treatascontent(@subject)=%%", + "exclusionFilter": "", + "isMultipart": true, + "isSalesforceTracking": true, + "isSendLogging": false, + "isStoppedOnJobError": false, + "isTrackingClicks": true, + "modified": {}, + "preHeader": "%%=treatascontent(@preheader)=%%\n", + "r__asset_key": "testExisting_asset_message", + "r__asset_name_readOnly": "testExisting_asset_message", + "r__deliveryProfile_key": "Default", + "r__list_PathName": { + "publicationList": "my subscribers/All Subscribers" + }, + "r__sendClassification_key": "Default Transactional", + "r__senderProfile_key": "Default", + "throttleCloses": "1/1/0001 12:00:00 AM", + "throttleOpens": "1/1/0001 12:00:00 AM" + } + }, + "description": "", + "key": "EMAILV2-3", + "metaData": { + "highThroughput": { + "r__dataExtension_key": "testExisting_temail_notPublished" + }, + "isConfigured": true, + "sections": {} + }, + "name": "my email activity", + "outcomes": [ + { + "arguments": {}, + "key": "067f20ba-af36-4401-99d8-934100e1935d", + "metaData": { + "invalid": false + } + } + ], + "schema": { + "arguments": { + "activityId": { + "access": "Hidden", + "dataType": "Text", + "direction": "In", + "isNullable": true, + "readOnly": false + }, + "contactId": { + "access": "Hidden", + "dataType": "Number", + "direction": "In", + "isNullable": true, + "readOnly": false + }, + "contactKey": { + "access": "Hidden", + "dataType": "Text", + "direction": "In", + "isNullable": false, + "readOnly": false + }, + "customObjectKey": { + "access": "Hidden", + "dataType": "LongNumber", + "direction": "In", + "isNullable": true, + "readOnly": true + }, + "definitionId": { + "access": "Hidden", + "dataType": "Text", + "direction": "In", + "isNullable": true, + "readOnly": true + }, + "definitionInstanceId": { + "access": "Hidden", + "dataType": "Text", + "direction": "In", + "isNullable": false, + "readOnly": false + }, + "emailAddress": { + "access": "Hidden", + "dataType": "Text", + "direction": "In", + "isNullable": false, + "readOnly": false + }, + "emailSubjectDataBound": { + "access": "Hidden", + "dataType": "Text", + "direction": "In", + "isNullable": true, + "readOnly": true + }, + "eventData": { + "access": "Hidden", + "dataType": "Text", + "direction": "In", + "isNullable": true, + "readOnly": false + }, + "fieldType": { + "access": "Hidden", + "dataType": "Text", + "direction": "In", + "isNullable": true, + "readOnly": false + }, + "messageKey": { + "access": "Hidden", + "dataType": "Text", + "direction": "Out", + "isNullable": true, + "readOnly": false + }, + "obfuscationProperties": { + "access": "Hidden", + "dataType": "Text", + "direction": "In", + "isNullable": true, + "readOnly": false + }, + "requestID": { + "access": "Hidden", + "dataType": "Text", + "direction": "Out", + "isNullable": true, + "readOnly": false + }, + "sourceCustomObjectId": { + "access": "Hidden", + "dataType": "Text", + "direction": "In", + "isNullable": true, + "readOnly": false + }, + "sourceCustomObjectKey": { + "access": "Hidden", + "dataType": "LongNumber", + "direction": "In", + "isNullable": true, + "readOnly": false + } + } + }, + "type": "EMAILV2" + } + ], + "channel": "email", + "createdDate": "2024-08-23T01:29:33.233", + "defaults": { + "properties": {} + }, + "definitionType": "Transactional", + "description": "", + "entryMode": "MultipleEntries", + "executionMode": "Production", + "exits": [], + "goals": [], + "key": "testExisting_temail_notPublished", + "lastPublishedDate": "0001-01-01T00:00:00", + "metaData": { + "dataSource": "ContactsModel", + "highThroughputSending": { + "email": false + } + }, + "modifiedDate": "2024-08-23T02:00:44.57", + "name": "testExisting_temail_notPublished", + "notifiers": [], + "r__folder_Path": "my journeys", + "scheduledStatus": "Draft", + "status": "Published", + "triggers": [ + { + "arguments": {}, + "configurationArguments": {}, + "description": "", + "key": "TRIGGER", + "metaData": { + "category": "Transactional", + "chainType": "none", + "configurationRequired": false, + "entrySourceGroupConfigUrl": "null", + "iconUrl": "/images/icon_journeyBuilder-event-transactional-blue.svg", + "title": "Transactional API Event" + }, + "name": "TRIGGER", + "outcomes": [], + "type": "transactional-api" + } + ], + "version": 1, + "workflowApiVersion": 1 +} diff --git a/test/resources/9999999/journey/get-quicksend-expected.json b/test/resources/9999999/journey/get-quicksend-expected.json new file mode 100644 index 000000000..6d2993c4a --- /dev/null +++ b/test/resources/9999999/journey/get-quicksend-expected.json @@ -0,0 +1,234 @@ +{ + "key": "testExisting_journey_Quicksend", + "name": "testExisting_journey_Quicksend", + "lastPublishedDate": "0001-01-01T00:00:00", + "description": "", + "version": 1, + "workflowApiVersion": 1, + "createdDate": "2024-04-24T12:18:43.47", + "modifiedDate": "2024-04-24T12:19:12.803", + "activities": [ + { + "key": "EMAILV2-1", + "name": "testExisting_asset_mail", + "description": "", + "type": "EMAILV2", + "outcomes": [ + { + "key": "a6b9c1af-cd89-4ce8-ba4f-bd4289188dc2", + "arguments": {}, + "metaData": { "invalid": false } + } + ], + "arguments": {}, + "configurationArguments": { + "isModified": true, + "googleAnalyticsCampaignName": "", + "triggeredSend": { + "autoAddSubscribers": true, + "autoUpdateSubscribers": true, + "bccEmail": [ + "%%= ContentBlockByName(\"Content Builder\\dont strip non ssjs content\") =%%" + ], + "ccEmail": ["%%= ContentBlockByKey(\"testExisting_asset_htmlblock\") =%%"], + "created": {}, + "description": "my activity info text", + "dynamicEmailSubject": "testExisting_ dynamic email subject %%= ContentBlockByKey(\"testExisting_asset_htmlblock\") =%%", + "emailSubject": "testExisting_ email subject %%= ContentBlockByKey(\"testExisting_asset_htmlblock\") =%%", + "exclusionFilter": "/* insert ampscript here */ %%= ContentBlockById(1295064) =%%", + "isSalesforceTracking": false, + "isMultipart": true, + "isSendLogging": true, + "isStoppedOnJobError": false, + "keyword": "", + "modified": {}, + "preHeader": "testExisting_ email preheader %%= ContentBlockByKey(\"testExisting_asset_htmlblock\") =%%", + "suppressTracking": true, + "throttleLimit": 0, + "throttleOpens": "1/1/0001 12:00:00 AM", + "throttleCloses": "1/1/0001 12:00:00 AM", + "isTrackingClicks": true, + "r__list_PathName": { + "publicationList": "my subscribers/All Subscribers", + "suppressionLists": ["Suppression Lists/testExisting_suppressionList"] + }, + "r__dataExtension_key": { + "domainExclusions": ["testExisting_DomainExclusion"] + }, + "r__deliveryProfile_key": "Default", + "r__senderProfile_key": "testExisting_senderProfile", + "r__sendClassification_key": "testExisting_sendClassification", + "c__priority": "High", + "r__asset_name_readOnly": "testExisting_asset_message", + "r__asset_key": "testExisting_asset_message" + }, + "applicationExtensionKey": "jb-email-activity" + }, + "metaData": { + "category": "message", + "version": "1.0", + "icon": "https://jb-email-activity.s7.marketingcloudapps.com/img/email-icon.svg", + "iconSmall": "https://jb-email-activity.s7.marketingcloudapps.com/img/email-icon.svg", + "statsContactIcon": null, + "original_icon": "/img/email-icon.svg", + "original_iconSmall": "/img/email-icon.svg", + "sections": {}, + "isConfigured": true + }, + "schema": { + "arguments": { + "requestID": { + "dataType": "Text", + "isNullable": true, + "direction": "Out", + "readOnly": false, + "access": "Hidden" + }, + "messageKey": { + "dataType": "Text", + "isNullable": true, + "direction": "Out", + "readOnly": false, + "access": "Hidden" + }, + "activityId": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "definitionId": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": true, + "access": "Hidden" + }, + "emailSubjectDataBound": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": true, + "access": "Hidden" + }, + "contactId": { + "dataType": "Number", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "contactKey": { + "dataType": "Text", + "isNullable": false, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "emailAddress": { + "dataType": "Text", + "isNullable": false, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "sourceCustomObjectId": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "sourceCustomObjectKey": { + "dataType": "LongNumber", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "fieldType": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "eventData": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "obfuscationProperties": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "customObjectKey": { + "dataType": "LongNumber", + "isNullable": true, + "direction": "In", + "readOnly": true, + "access": "Hidden" + }, + "definitionInstanceId": { + "dataType": "Text", + "isNullable": false, + "direction": "In", + "readOnly": false, + "access": "Hidden" + } + } + } + } + ], + "triggers": [ + { + "key": "TRIGGER", + "name": "TRIGGER", + "description": "", + "type": "EmailAudience", + "outcomes": [], + "arguments": {}, + "configurationArguments": {}, + "metaData": { + "sourceInteractionId": "00000000-0000-0000-0000-000000000000", + "r__event_key": "DEAudience-11be962d-064c-83d9-2804-7d1befc10325", + "chainType": "None", + "configurationRequired": false, + "iconUrl": "/images/icon-data-extension.svg", + "title": "Data Extension", + "entrySourceGroupConfigUrl": "jb:///data/entry/audience/entrysourcegroupconfig.json" + } + } + ], + "goals": [], + "exits": [], + "notifiers": [], + "entryMode": "MultipleEntries", + "definitionType": "Quicksend", + "channel": "email", + "defaults": { + "email": ["{{Event.DEAudience-11be962d-064c-83d9-2804-7d1befc10325.\"Email\"}}"], + "properties": { + "analyticsTracking": { + "enabled": true, + "analyticsType": "google", + "urlDomainsToTrack": [] + } + } + }, + "metaData": { + "dataSource": "ContactsModel", + "isScheduleSet": true, + "highThroughputSending": { "email": false } + }, + "executionMode": "Production", + "status": "Draft", + "scheduledStatus": "Draft", + "r__folder_Path": "my journeys" +} diff --git a/test/resources/9999999/journey/get-quicksend-rcb-id-expected.json b/test/resources/9999999/journey/get-quicksend-rcb-id-expected.json new file mode 100644 index 000000000..9eb1a4bb6 --- /dev/null +++ b/test/resources/9999999/journey/get-quicksend-rcb-id-expected.json @@ -0,0 +1,232 @@ +{ + "key": "testExisting_journey_Quicksend", + "name": "testExisting_journey_Quicksend", + "lastPublishedDate": "0001-01-01T00:00:00", + "description": "", + "version": 1, + "workflowApiVersion": 1, + "createdDate": "2024-04-24T12:18:43.47", + "modifiedDate": "2024-04-24T12:19:12.803", + "activities": [ + { + "key": "EMAILV2-1", + "name": "testExisting_asset_mail", + "description": "", + "type": "EMAILV2", + "outcomes": [ + { + "key": "a6b9c1af-cd89-4ce8-ba4f-bd4289188dc2", + "arguments": {}, + "metaData": { "invalid": false } + } + ], + "arguments": {}, + "configurationArguments": { + "isModified": true, + "googleAnalyticsCampaignName": "", + "triggeredSend": { + "autoAddSubscribers": true, + "autoUpdateSubscribers": true, + "bccEmail": ["%%= ContentBlockById(1295064) =%%"], + "ccEmail": ["%%= ContentBlockById(1295064) =%%"], + "created": {}, + "description": "my activity info text", + "dynamicEmailSubject": "testExisting_ dynamic email subject %%= ContentBlockById(1295064) =%%", + "emailSubject": "testExisting_ email subject %%= ContentBlockById(1295064) =%%", + "exclusionFilter": "/* insert ampscript here */ %%= ContentBlockById(1295064) =%%", + "isSalesforceTracking": false, + "isMultipart": true, + "isSendLogging": true, + "isStoppedOnJobError": false, + "keyword": "", + "modified": {}, + "preHeader": "testExisting_ email preheader %%= ContentBlockById(1295064) =%%", + "suppressTracking": true, + "throttleLimit": 0, + "throttleOpens": "1/1/0001 12:00:00 AM", + "throttleCloses": "1/1/0001 12:00:00 AM", + "isTrackingClicks": true, + "r__list_PathName": { + "publicationList": "my subscribers/All Subscribers", + "suppressionLists": ["Suppression Lists/testExisting_suppressionList"] + }, + "r__dataExtension_key": { + "domainExclusions": ["testExisting_DomainExclusion"] + }, + "r__deliveryProfile_key": "Default", + "r__senderProfile_key": "testExisting_senderProfile", + "r__sendClassification_key": "testExisting_sendClassification", + "c__priority": "High", + "r__asset_name_readOnly": "testExisting_asset_message", + "r__asset_key": "testExisting_asset_message" + }, + "applicationExtensionKey": "jb-email-activity" + }, + "metaData": { + "category": "message", + "version": "1.0", + "icon": "https://jb-email-activity.s7.marketingcloudapps.com/img/email-icon.svg", + "iconSmall": "https://jb-email-activity.s7.marketingcloudapps.com/img/email-icon.svg", + "statsContactIcon": null, + "original_icon": "/img/email-icon.svg", + "original_iconSmall": "/img/email-icon.svg", + "sections": {}, + "isConfigured": true + }, + "schema": { + "arguments": { + "requestID": { + "dataType": "Text", + "isNullable": true, + "direction": "Out", + "readOnly": false, + "access": "Hidden" + }, + "messageKey": { + "dataType": "Text", + "isNullable": true, + "direction": "Out", + "readOnly": false, + "access": "Hidden" + }, + "activityId": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "definitionId": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": true, + "access": "Hidden" + }, + "emailSubjectDataBound": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": true, + "access": "Hidden" + }, + "contactId": { + "dataType": "Number", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "contactKey": { + "dataType": "Text", + "isNullable": false, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "emailAddress": { + "dataType": "Text", + "isNullable": false, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "sourceCustomObjectId": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "sourceCustomObjectKey": { + "dataType": "LongNumber", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "fieldType": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "eventData": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "obfuscationProperties": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "customObjectKey": { + "dataType": "LongNumber", + "isNullable": true, + "direction": "In", + "readOnly": true, + "access": "Hidden" + }, + "definitionInstanceId": { + "dataType": "Text", + "isNullable": false, + "direction": "In", + "readOnly": false, + "access": "Hidden" + } + } + } + } + ], + "triggers": [ + { + "key": "TRIGGER", + "name": "TRIGGER", + "description": "", + "type": "EmailAudience", + "outcomes": [], + "arguments": {}, + "configurationArguments": {}, + "metaData": { + "sourceInteractionId": "00000000-0000-0000-0000-000000000000", + "r__event_key": "DEAudience-11be962d-064c-83d9-2804-7d1befc10325", + "chainType": "None", + "configurationRequired": false, + "iconUrl": "/images/icon-data-extension.svg", + "title": "Data Extension", + "entrySourceGroupConfigUrl": "jb:///data/entry/audience/entrysourcegroupconfig.json" + } + } + ], + "goals": [], + "exits": [], + "notifiers": [], + "entryMode": "MultipleEntries", + "definitionType": "Quicksend", + "channel": "email", + "defaults": { + "email": ["{{Event.DEAudience-11be962d-064c-83d9-2804-7d1befc10325.\"Email\"}}"], + "properties": { + "analyticsTracking": { + "enabled": true, + "analyticsType": "google", + "urlDomainsToTrack": [] + } + } + }, + "metaData": { + "dataSource": "ContactsModel", + "isScheduleSet": true, + "highThroughputSending": { "email": false } + }, + "executionMode": "Production", + "status": "Draft", + "scheduledStatus": "Draft", + "r__folder_Path": "my journeys" +} diff --git a/test/resources/9999999/journey/get-quicksend-rcb-key-expected.json b/test/resources/9999999/journey/get-quicksend-rcb-key-expected.json new file mode 100644 index 000000000..418a8c73f --- /dev/null +++ b/test/resources/9999999/journey/get-quicksend-rcb-key-expected.json @@ -0,0 +1,232 @@ +{ + "key": "testExisting_journey_Quicksend", + "name": "testExisting_journey_Quicksend", + "lastPublishedDate": "0001-01-01T00:00:00", + "description": "", + "version": 1, + "workflowApiVersion": 1, + "createdDate": "2024-04-24T12:18:43.47", + "modifiedDate": "2024-04-24T12:19:12.803", + "activities": [ + { + "key": "EMAILV2-1", + "name": "testExisting_asset_mail", + "description": "", + "type": "EMAILV2", + "outcomes": [ + { + "key": "a6b9c1af-cd89-4ce8-ba4f-bd4289188dc2", + "arguments": {}, + "metaData": { "invalid": false } + } + ], + "arguments": {}, + "configurationArguments": { + "isModified": true, + "googleAnalyticsCampaignName": "", + "triggeredSend": { + "autoAddSubscribers": true, + "autoUpdateSubscribers": true, + "bccEmail": ["%%= ContentBlockByKey(\"testExisting_asset_htmlblock\") =%%"], + "ccEmail": ["%%= ContentBlockByKey(\"testExisting_asset_htmlblock\") =%%"], + "created": {}, + "description": "my activity info text", + "dynamicEmailSubject": "testExisting_ dynamic email subject %%= ContentBlockByKey(\"testExisting_asset_htmlblock\") =%%", + "emailSubject": "testExisting_ email subject %%= ContentBlockByKey(\"testExisting_asset_htmlblock\") =%%", + "exclusionFilter": "/* insert ampscript here */ %%= ContentBlockByKey(\"testExisting_asset_htmlblock\") =%%", + "isSalesforceTracking": false, + "isMultipart": true, + "isSendLogging": true, + "isStoppedOnJobError": false, + "keyword": "", + "modified": {}, + "preHeader": "testExisting_ email preheader %%= ContentBlockByKey(\"testExisting_asset_htmlblock\") =%%", + "suppressTracking": true, + "throttleLimit": 0, + "throttleOpens": "1/1/0001 12:00:00 AM", + "throttleCloses": "1/1/0001 12:00:00 AM", + "isTrackingClicks": true, + "r__list_PathName": { + "publicationList": "my subscribers/All Subscribers", + "suppressionLists": ["Suppression Lists/testExisting_suppressionList"] + }, + "r__dataExtension_key": { + "domainExclusions": ["testExisting_DomainExclusion"] + }, + "r__deliveryProfile_key": "Default", + "r__senderProfile_key": "testExisting_senderProfile", + "r__sendClassification_key": "testExisting_sendClassification", + "c__priority": "High", + "r__asset_name_readOnly": "testExisting_asset_message", + "r__asset_key": "testExisting_asset_message" + }, + "applicationExtensionKey": "jb-email-activity" + }, + "metaData": { + "category": "message", + "version": "1.0", + "icon": "https://jb-email-activity.s7.marketingcloudapps.com/img/email-icon.svg", + "iconSmall": "https://jb-email-activity.s7.marketingcloudapps.com/img/email-icon.svg", + "statsContactIcon": null, + "original_icon": "/img/email-icon.svg", + "original_iconSmall": "/img/email-icon.svg", + "sections": {}, + "isConfigured": true + }, + "schema": { + "arguments": { + "requestID": { + "dataType": "Text", + "isNullable": true, + "direction": "Out", + "readOnly": false, + "access": "Hidden" + }, + "messageKey": { + "dataType": "Text", + "isNullable": true, + "direction": "Out", + "readOnly": false, + "access": "Hidden" + }, + "activityId": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "definitionId": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": true, + "access": "Hidden" + }, + "emailSubjectDataBound": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": true, + "access": "Hidden" + }, + "contactId": { + "dataType": "Number", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "contactKey": { + "dataType": "Text", + "isNullable": false, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "emailAddress": { + "dataType": "Text", + "isNullable": false, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "sourceCustomObjectId": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "sourceCustomObjectKey": { + "dataType": "LongNumber", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "fieldType": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "eventData": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "obfuscationProperties": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "customObjectKey": { + "dataType": "LongNumber", + "isNullable": true, + "direction": "In", + "readOnly": true, + "access": "Hidden" + }, + "definitionInstanceId": { + "dataType": "Text", + "isNullable": false, + "direction": "In", + "readOnly": false, + "access": "Hidden" + } + } + } + } + ], + "triggers": [ + { + "key": "TRIGGER", + "name": "TRIGGER", + "description": "", + "type": "EmailAudience", + "outcomes": [], + "arguments": {}, + "configurationArguments": {}, + "metaData": { + "sourceInteractionId": "00000000-0000-0000-0000-000000000000", + "r__event_key": "DEAudience-11be962d-064c-83d9-2804-7d1befc10325", + "chainType": "None", + "configurationRequired": false, + "iconUrl": "/images/icon-data-extension.svg", + "title": "Data Extension", + "entrySourceGroupConfigUrl": "jb:///data/entry/audience/entrysourcegroupconfig.json" + } + } + ], + "goals": [], + "exits": [], + "notifiers": [], + "entryMode": "MultipleEntries", + "definitionType": "Quicksend", + "channel": "email", + "defaults": { + "email": ["{{Event.DEAudience-11be962d-064c-83d9-2804-7d1befc10325.\"Email\"}}"], + "properties": { + "analyticsTracking": { + "enabled": true, + "analyticsType": "google", + "urlDomainsToTrack": [] + } + } + }, + "metaData": { + "dataSource": "ContactsModel", + "isScheduleSet": true, + "highThroughputSending": { "email": false } + }, + "executionMode": "Production", + "status": "Draft", + "scheduledStatus": "Draft", + "r__folder_Path": "my journeys" +} diff --git a/test/resources/9999999/journey/get-quicksend-rcb-name-expected.json b/test/resources/9999999/journey/get-quicksend-rcb-name-expected.json new file mode 100644 index 000000000..6e6460819 --- /dev/null +++ b/test/resources/9999999/journey/get-quicksend-rcb-name-expected.json @@ -0,0 +1,236 @@ +{ + "key": "testExisting_journey_Quicksend", + "name": "testExisting_journey_Quicksend", + "lastPublishedDate": "0001-01-01T00:00:00", + "description": "", + "version": 1, + "workflowApiVersion": 1, + "createdDate": "2024-04-24T12:18:43.47", + "modifiedDate": "2024-04-24T12:19:12.803", + "activities": [ + { + "key": "EMAILV2-1", + "name": "testExisting_asset_mail", + "description": "", + "type": "EMAILV2", + "outcomes": [ + { + "key": "a6b9c1af-cd89-4ce8-ba4f-bd4289188dc2", + "arguments": {}, + "metaData": { "invalid": false } + } + ], + "arguments": {}, + "configurationArguments": { + "isModified": true, + "googleAnalyticsCampaignName": "", + "triggeredSend": { + "autoAddSubscribers": true, + "autoUpdateSubscribers": true, + "bccEmail": [ + "%%= ContentBlockByName(\"Content Builder\\dont strip non ssjs content\") =%%" + ], + "ccEmail": [ + "%%= ContentBlockByName(\"Content Builder\\dont strip non ssjs content\") =%%" + ], + "created": {}, + "description": "my activity info text", + "dynamicEmailSubject": "testExisting_ dynamic email subject %%= ContentBlockByName(\"Content Builder\\dont strip non ssjs content\") =%%", + "emailSubject": "testExisting_ email subject %%= ContentBlockByName(\"Content Builder\\dont strip non ssjs content\") =%%", + "exclusionFilter": "/* insert ampscript here */ %%= ContentBlockByName(\"Content Builder\\dont strip non ssjs content\") =%%", + "isSalesforceTracking": false, + "isMultipart": true, + "isSendLogging": true, + "isStoppedOnJobError": false, + "keyword": "", + "modified": {}, + "preHeader": "testExisting_ email preheader %%= ContentBlockByName(\"Content Builder\\dont strip non ssjs content\") =%%", + "suppressTracking": true, + "throttleLimit": 0, + "throttleOpens": "1/1/0001 12:00:00 AM", + "throttleCloses": "1/1/0001 12:00:00 AM", + "isTrackingClicks": true, + "r__list_PathName": { + "publicationList": "my subscribers/All Subscribers", + "suppressionLists": ["Suppression Lists/testExisting_suppressionList"] + }, + "r__dataExtension_key": { + "domainExclusions": ["testExisting_DomainExclusion"] + }, + "r__deliveryProfile_key": "Default", + "r__senderProfile_key": "testExisting_senderProfile", + "r__sendClassification_key": "testExisting_sendClassification", + "c__priority": "High", + "r__asset_name_readOnly": "testExisting_asset_message", + "r__asset_key": "testExisting_asset_message" + }, + "applicationExtensionKey": "jb-email-activity" + }, + "metaData": { + "category": "message", + "version": "1.0", + "icon": "https://jb-email-activity.s7.marketingcloudapps.com/img/email-icon.svg", + "iconSmall": "https://jb-email-activity.s7.marketingcloudapps.com/img/email-icon.svg", + "statsContactIcon": null, + "original_icon": "/img/email-icon.svg", + "original_iconSmall": "/img/email-icon.svg", + "sections": {}, + "isConfigured": true + }, + "schema": { + "arguments": { + "requestID": { + "dataType": "Text", + "isNullable": true, + "direction": "Out", + "readOnly": false, + "access": "Hidden" + }, + "messageKey": { + "dataType": "Text", + "isNullable": true, + "direction": "Out", + "readOnly": false, + "access": "Hidden" + }, + "activityId": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "definitionId": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": true, + "access": "Hidden" + }, + "emailSubjectDataBound": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": true, + "access": "Hidden" + }, + "contactId": { + "dataType": "Number", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "contactKey": { + "dataType": "Text", + "isNullable": false, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "emailAddress": { + "dataType": "Text", + "isNullable": false, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "sourceCustomObjectId": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "sourceCustomObjectKey": { + "dataType": "LongNumber", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "fieldType": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "eventData": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "obfuscationProperties": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "customObjectKey": { + "dataType": "LongNumber", + "isNullable": true, + "direction": "In", + "readOnly": true, + "access": "Hidden" + }, + "definitionInstanceId": { + "dataType": "Text", + "isNullable": false, + "direction": "In", + "readOnly": false, + "access": "Hidden" + } + } + } + } + ], + "triggers": [ + { + "key": "TRIGGER", + "name": "TRIGGER", + "description": "", + "type": "EmailAudience", + "outcomes": [], + "arguments": {}, + "configurationArguments": {}, + "metaData": { + "sourceInteractionId": "00000000-0000-0000-0000-000000000000", + "r__event_key": "DEAudience-11be962d-064c-83d9-2804-7d1befc10325", + "chainType": "None", + "configurationRequired": false, + "iconUrl": "/images/icon-data-extension.svg", + "title": "Data Extension", + "entrySourceGroupConfigUrl": "jb:///data/entry/audience/entrysourcegroupconfig.json" + } + } + ], + "goals": [], + "exits": [], + "notifiers": [], + "entryMode": "MultipleEntries", + "definitionType": "Quicksend", + "channel": "email", + "defaults": { + "email": ["{{Event.DEAudience-11be962d-064c-83d9-2804-7d1befc10325.\"Email\"}}"], + "properties": { + "analyticsTracking": { + "enabled": true, + "analyticsType": "google", + "urlDomainsToTrack": [] + } + } + }, + "metaData": { + "dataSource": "ContactsModel", + "isScheduleSet": true, + "highThroughputSending": { "email": false } + }, + "executionMode": "Production", + "status": "Draft", + "scheduledStatus": "Draft", + "r__folder_Path": "my journeys" +} diff --git a/test/resources/9999999/journey/get-transactionalEmail-expected.json b/test/resources/9999999/journey/get-transactionalEmail-expected.json new file mode 100644 index 000000000..7800003b8 --- /dev/null +++ b/test/resources/9999999/journey/get-transactionalEmail-expected.json @@ -0,0 +1,211 @@ +{ + "key": "testExisting_temail", + "name": "testExisting_temail", + "lastPublishedDate": "0001-01-01T00:00:00", + "description": "", + "version": 1, + "workflowApiVersion": 1, + "createdDate": "2022-03-24T02:20:32.74", + "modifiedDate": "2022-03-24T02:20:40.45", + "activities": [ + { + "key": "EMAILV2-4", + "name": "testExisting_temail", + "description": "", + "type": "EMAILV2", + "outcomes": [ + { + "key": "1f44021a-74ac-49be-a07c-67862228214d", + "arguments": {}, + "metaData": { "invalid": false } + } + ], + "arguments": {}, + "configurationArguments": { + "applicationExtensionKey": "jb-email-activity", + "isModified": true, + "triggeredSend": { + "autoAddSubscribers": true, + "autoUpdateSubscribers": true, + "bccEmail": [], + "ccEmail": [], + "created": {}, + "domainExclusions": [], + "dynamicEmailSubject": "test email", + "emailSubject": "test email", + "exclusionFilter": "", + "isSalesforceTracking": true, + "isMultipart": true, + "isSendLogging": false, + "isStoppedOnJobError": false, + "modified": {}, + "preHeader": "", + "throttleOpens": "1/1/0001 12:00:00 AM", + "throttleCloses": "1/1/0001 12:00:00 AM", + "isTrackingClicks": true, + "r__list_PathName": { "publicationList": "my subscribers/All Subscribers" }, + "r__deliveryProfile_key": "Default", + "r__senderProfile_key": "Default", + "r__sendClassification_key": "Default Transactional", + "c__priority": "Medium", + "r__asset_name_readOnly": "testExisting_asset_message", + "r__asset_key": "testExisting_asset_message" + }, + "r__transactionalEmail_key": "testExisting_temail" + }, + "metaData": { + "highThroughput": { "r__dataExtension_key": "testExisting_dataExtension" }, + "sections": {}, + "isConfigured": true + }, + "schema": { + "arguments": { + "requestID": { + "dataType": "Text", + "isNullable": true, + "direction": "Out", + "readOnly": false, + "access": "Hidden" + }, + "messageKey": { + "dataType": "Text", + "isNullable": true, + "direction": "Out", + "readOnly": false, + "access": "Hidden" + }, + "activityId": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "definitionId": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": true, + "access": "Hidden" + }, + "emailSubjectDataBound": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": true, + "access": "Hidden" + }, + "contactId": { + "dataType": "Number", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "contactKey": { + "dataType": "Text", + "isNullable": false, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "emailAddress": { + "dataType": "Text", + "isNullable": false, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "sourceCustomObjectId": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "sourceCustomObjectKey": { + "dataType": "LongNumber", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "fieldType": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "eventData": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "obfuscationProperties": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "customObjectKey": { + "dataType": "LongNumber", + "isNullable": true, + "direction": "In", + "readOnly": true, + "access": "Hidden" + }, + "definitionInstanceId": { + "dataType": "Text", + "isNullable": false, + "direction": "In", + "readOnly": false, + "access": "Hidden" + } + } + } + } + ], + "triggers": [ + { + "key": "TRIGGER", + "name": "TRIGGER", + "description": "", + "type": "transactional-api", + "outcomes": [], + "arguments": {}, + "configurationArguments": {}, + "metaData": { + "chainType": "none", + "configurationRequired": false, + "iconUrl": "/images/icon_journeyBuilder-event-transactional-blue.svg", + "title": "Transactional API Event", + "category": "Transactional", + "entrySourceGroupConfigUrl": "null" + } + } + ], + "goals": [], + "exits": [], + "notifiers": [], + "entryMode": "MultipleEntries", + "definitionType": "Transactional", + "channel": "email", + "defaults": { + "properties": { + "analyticsTracking": { + "enabled": false, + "analyticsType": "google", + "urlDomainsToTrack": [] + } + } + }, + "metaData": {}, + "executionMode": "Production", + "status": "Published", + "scheduledStatus": "Draft", + "r__folder_Path": "my journeys" +} diff --git a/test/resources/9999999/journey/get-updatecontact-expected.json b/test/resources/9999999/journey/get-updatecontact-expected.json new file mode 100644 index 000000000..3af6b5412 --- /dev/null +++ b/test/resources/9999999/journey/get-updatecontact-expected.json @@ -0,0 +1,108 @@ +{ + "key": "testExisting_journey_updatecontact", + "name": "testExisting_journey_updatecontact", + "lastPublishedDate": "0001-01-01T00:00:00", + "description": "", + "version": 1, + "workflowApiVersion": 1, + "createdDate": "2024-05-04T05:54:48.027", + "modifiedDate": "2024-05-04T17:25:57.9", + "activities": [ + { + "key": "UPDATECONTACTDATAV2-1", + "name": "Update Contact - TEST", + "description": "", + "type": "UPDATECONTACTDATA", + "outcomes": [ + { + "key": "9f21d42b-4679-4561-911a-4bccf84672ba", + "arguments": {}, + "metaData": { + "invalid": false + } + } + ], + "arguments": { + "activityData": { + "updateContactFields": [ + { + "r__dataExtensionField_name": "LastName", + "value": "TEST", + "r__dataExtension_key": "testExisting_dataExtension" + } + ] + } + }, + "configurationArguments": {}, + "metaData": { + "isConfigured": true + }, + "schema": { + "arguments": { + "activityData": { + "dataType": "Text", + "isNullable": false, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "contactKey": { + "dataType": "Text", + "isNullable": false, + "direction": "In", + "readOnly": false, + "access": "Hidden" + } + } + } + } + ], + "triggers": [ + { + "key": "TRIGGER", + "name": "TRIGGER", + "description": "", + "type": "EmailAudience", + "outcomes": [], + "arguments": {}, + "configurationArguments": {}, + "metaData": { + "r__event_key": "DEAudience-2e3c73b6-48cc-2ec0-5522-48636e1a236e", + "chainType": "None", + "configurationRequired": false, + "iconUrl": "/images/icon-data-extension.svg", + "title": "Data Extension", + "entrySourceGroupConfigUrl": "jb:///data/entry/audience/entrysourcegroupconfig.json", + "sourceInteractionId": "00000000-0000-0000-0000-000000000000" + } + } + ], + "goals": [], + "exits": [], + "notifiers": [], + "entryMode": "NotSet", + "definitionType": "Multistep", + "channel": "", + "defaults": { + "email": [ + "{{Event.DEAudience-2e3c73b6-48cc-2ec0-5522-48636e1a236e.\"Email\"}}" + ], + "properties": { + "analyticsTracking": { + "enabled": true, + "analyticsType": "google", + "urlDomainsToTrack": [] + } + } + }, + "metaData": { + "dataSource": "ContactsModel", + "highThroughputSending": { + "email": false + } + }, + "executionMode": "Production", + "status": "Draft", + "scheduledStatus": "Draft", + "r__folder_Path": "my journeys" +} \ No newline at end of file diff --git a/test/resources/9999999/journey/post-expected.json b/test/resources/9999999/journey/post-expected.json new file mode 100644 index 000000000..fbd2bfbc2 --- /dev/null +++ b/test/resources/9999999/journey/post-expected.json @@ -0,0 +1,264 @@ +{ + "key": "testNew_interaction", + "name": "testNew_interaction", + "lastPublishedDate": "2017-04-12T08:07:48", + "description": "created on deploy", + "version": 1, + "workflowApiVersion": 1, + "createdDate": "2017-04-12T05:38:05.837", + "modifiedDate": "2017-04-12T08:07:48.333", + "activities": [ + { + "id": "69213026-bd2c-433b-8332-5f52d3e87ca5", + "key": "WAIT-1", + "name": "", + "description": "", + "type": "WAIT", + "outcomes": [ + { + "key": "bd3dff6b-565c-4b56-b9cb-60cd5b6d080b", + "next": "DATAEXTENSIONUPDATE-1", + "arguments": {}, + "metaData": {} + } + ], + "arguments": { + "waitDefinitionId": "546704c0-9384-4a41-b20e-97615cc6cc6a", + "waitForEventId": "", + "executionMode": "{{Context.ExecutionMode}}", + "startActivityKey": "{{Context.StartActivityKey}}", + "waitQueueId": "{{Context.WaitQueueId}}" + }, + "configurationArguments": { + "waitDuration": 1, + "waitUnit": "DAYS", + "specifiedTime": "", + "timeZone": "", + "description": "", + "waitForEventKey": "" + }, + "metaData": { "waitType": "duration" }, + "schema": { + "arguments": { + "endDate": { + "dataType": "Date", + "isNullable": false, + "direction": "Out", + "readOnly": false, + "access": "Hidden" + }, + "waitEndDateAttributeDataBound": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "waitDefinitionId": { + "dataType": "Text", + "isNullable": false, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "waitForEventId": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "executionMode": { + "dataType": "Text", + "isNullable": false, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "startActivityKey": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "waitQueueId": { + "dataType": "LongNumber", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + } + } + } + }, + { + "id": "5d93cda9-2015-4c07-a1db-0d5853d25bf6", + "key": "WAIT-2", + "name": "", + "description": "", + "type": "WAIT", + "outcomes": [ + { + "key": "e3d3258a-891b-4838-b5a6-af37f8cb769a", + "arguments": {}, + "metaData": {} + } + ], + "arguments": { + "waitDefinitionId": "deed4c9d-f487-4371-bfd9-76fca44ec49b", + "waitForEventId": "", + "executionMode": "{{Context.ExecutionMode}}", + "startActivityKey": "{{Context.StartActivityKey}}", + "waitQueueId": "{{Context.WaitQueueId}}" + }, + "configurationArguments": { + "waitDuration": 1, + "waitUnit": "DAYS", + "specifiedTime": "", + "timeZone": "", + "description": "", + "waitForEventKey": "" + }, + "metaData": { "waitType": "duration" }, + "schema": { + "arguments": { + "endDate": { + "dataType": "Date", + "isNullable": false, + "direction": "Out", + "readOnly": false, + "access": "Hidden" + }, + "waitEndDateAttributeDataBound": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "waitDefinitionId": { + "dataType": "Text", + "isNullable": false, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "waitForEventId": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "executionMode": { + "dataType": "Text", + "isNullable": false, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "startActivityKey": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "waitQueueId": { + "dataType": "LongNumber", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + } + } + } + }, + { + "id": "ef4db13e-83f0-4d41-981d-4bf5810c0daa", + "key": "DATAEXTENSIONUPDATE-1", + "name": "", + "description": "", + "type": "DATAEXTENSIONUPDATE", + "outcomes": [ + { + "key": "a49ecf04-4612-4582-85fe-d7193f872fa8", + "next": "WAIT-2", + "arguments": {}, + "metaData": {} + } + ], + "arguments": { "contactKey": "{{Contact.Key}}", "value": "{{DateTime.Now}}" }, + "configurationArguments": { + "dataExtensionId": "ace267f0-b81d-e711-80cc-1402ec7222b4", + "field": "4e875b26-0317-4525-bfa0-50c8d1b7a7b5" + }, + "metaData": { + "dataExtensionName": "test_TestData", + "cachedFieldName": "JourneyConfirmed", + "cachedDisplayValue": "" + }, + "schema": { + "arguments": { + "contactKey": { + "dataType": "Text", + "isNullable": false, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "value": { + "dataType": "Text", + "isNullable": false, + "direction": "In", + "readOnly": false, + "access": "Hidden" + } + } + } + } + ], + "triggers": [ + { + "key": "TRIGGER", + "name": "test_TESTDataentry", + "description": "", + "type": "APIEvent", + "outcomes": [], + "arguments": { + "filterResult": "{{Contact.FilterId.e4ddb887-6f2d-46b1-9f64-9a020f217339}}" + }, + "configurationArguments": { + "schemaVersionId": 133, + "criteria": "<FilterDefinition><ConditionSet Operator=\"AND\" ConditionSetName=\"Individual Filter Grouping\"></ConditionSet></FilterDefinition>", + "filterDefinitionId": "e4ddb887-6f2d-46b1-9f64-9a020f217339" + }, + "metaData": { + "scheduleState": "No Schedule", + "sourceInteractionId": "00000000-0000-0000-0000-000000000000", + "r__event_key": "APIEvent-60130566-e2fe-eb29-4140-15c27093a80b", + "chainType": "None", + "configurationRequired": false, + "iconUrl": "/events/images/icon_journeyBuilder-event-api-blue.svg", + "title": "", + "category": "Event" + } + } + ], + "goals": [], + "exits": [], + "notifiers": [], + "entryMode": "OnceAndDone", + "definitionType": "Multistep", + "channel": "", + "defaults": { + "email": ["{{Event.APIEvent-60130566-e2fe-eb29-4140-15c27093a80b.\"emailAddress\"}}"], + "properties": {} + }, + "metaData": {}, + "executionMode": "Production", + "status": "Draft", + "scheduledStatus": "Draft", + "r__folder_Path": "my journeys" +} diff --git a/test/resources/9999999/journey/publish-callout-expected.json b/test/resources/9999999/journey/publish-callout-expected.json new file mode 100644 index 000000000..0967ef424 --- /dev/null +++ b/test/resources/9999999/journey/publish-callout-expected.json @@ -0,0 +1 @@ +{} diff --git a/test/resources/9999999/journey/put-expected.json b/test/resources/9999999/journey/put-expected.json new file mode 100644 index 000000000..7b2c642a9 --- /dev/null +++ b/test/resources/9999999/journey/put-expected.json @@ -0,0 +1,576 @@ +{ + "key": "testExisting_interaction", + "name": "testExisting_interaction", + "lastPublishedDate": "2017-04-12T08:07:48", + "description": "updated via deploy - test", + "version": 1, + "workflowApiVersion": 1, + "createdDate": "2017-04-12T05:38:05.837", + "modifiedDate": "2017-04-12T08:07:48.333", + "activities": [ + { + "id": "69213026-bd2c-433b-8332-5f52d3e87ca5", + "key": "WAIT-1", + "name": "", + "description": "", + "type": "WAIT", + "outcomes": [ + { + "key": "bd3dff6b-565c-4b56-b9cb-60cd5b6d080b", + "next": "DATAEXTENSIONUPDATE-1", + "arguments": {}, + "metaData": {} + } + ], + "arguments": { + "waitDefinitionId": "546704c0-9384-4a41-b20e-97615cc6cc6a", + "waitForEventId": "", + "executionMode": "{{Context.ExecutionMode}}", + "startActivityKey": "{{Context.StartActivityKey}}", + "waitQueueId": "{{Context.WaitQueueId}}" + }, + "configurationArguments": { + "waitDuration": 1, + "waitUnit": "DAYS", + "specifiedTime": "", + "timeZone": "", + "description": "", + "waitForEventKey": "" + }, + "metaData": { "waitType": "duration" }, + "schema": { + "arguments": { + "endDate": { + "dataType": "Date", + "isNullable": false, + "direction": "Out", + "readOnly": false, + "access": "Hidden" + }, + "waitEndDateAttributeDataBound": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "waitDefinitionId": { + "dataType": "Text", + "isNullable": false, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "waitForEventId": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "executionMode": { + "dataType": "Text", + "isNullable": false, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "startActivityKey": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "waitQueueId": { + "dataType": "LongNumber", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + } + } + } + }, + { + "id": "5d93cda9-2015-4c07-a1db-0d5853d25bf6", + "key": "WAIT-2", + "name": "", + "description": "", + "type": "WAIT", + "outcomes": [ + { + "key": "e3d3258a-891b-4838-b5a6-af37f8cb769a", + "next": "SMSSYNC-1", + "arguments": {}, + "metaData": {} + } + ], + "arguments": { + "waitDefinitionId": "deed4c9d-f487-4371-bfd9-76fca44ec49b", + "waitForEventId": "", + "executionMode": "{{Context.ExecutionMode}}", + "startActivityKey": "{{Context.StartActivityKey}}", + "waitQueueId": "{{Context.WaitQueueId}}" + }, + "configurationArguments": { + "waitDuration": 1, + "waitUnit": "DAYS", + "specifiedTime": "", + "timeZone": "", + "description": "", + "waitForEventKey": "" + }, + "metaData": { "waitType": "duration" }, + "schema": { + "arguments": { + "endDate": { + "dataType": "Date", + "isNullable": false, + "direction": "Out", + "readOnly": false, + "access": "Hidden" + }, + "waitEndDateAttributeDataBound": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "waitDefinitionId": { + "dataType": "Text", + "isNullable": false, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "waitForEventId": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "executionMode": { + "dataType": "Text", + "isNullable": false, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "startActivityKey": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "waitQueueId": { + "dataType": "LongNumber", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + } + } + } + }, + { + "id": "79213026-bd2c-433b-8332-5f52d3e87ca5", + "key": "WAIT-3", + "name": "", + "description": "", + "type": "WAIT", + "outcomes": [ + { + "key": "bd3dff6b-565c-4b56-b9cb-60cd5b6d080b", + "arguments": {}, + "metaData": {} + } + ], + "arguments": { + "waitDefinitionId": "546704c0-9384-4a41-b20e-97615cc6cc6a", + "waitForEventId": "", + "executionMode": "{{Context.ExecutionMode}}", + "startActivityKey": "{{Context.StartActivityKey}}", + "waitQueueId": "{{Context.WaitQueueId}}" + }, + "configurationArguments": { + "waitDuration": 1, + "waitUnit": "DAYS", + "specifiedTime": "", + "timeZone": "", + "description": "", + "waitForEventKey": "" + }, + "metaData": { "waitType": "duration" }, + "schema": { + "arguments": { + "endDate": { + "dataType": "Date", + "isNullable": false, + "direction": "Out", + "readOnly": false, + "access": "Hidden" + }, + "waitEndDateAttributeDataBound": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "waitDefinitionId": { + "dataType": "Text", + "isNullable": false, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "waitForEventId": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "executionMode": { + "dataType": "Text", + "isNullable": false, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "startActivityKey": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "waitQueueId": { + "dataType": "LongNumber", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + } + } + } + }, + { + "id": "ef4db13e-83f0-4d41-981d-4bf5810c0daa", + "key": "DATAEXTENSIONUPDATE-1", + "name": "", + "description": "", + "type": "DATAEXTENSIONUPDATE", + "outcomes": [ + { + "key": "a49ecf04-4612-4582-85fe-d7193f872fa8", + "next": "WAIT-2", + "arguments": {}, + "metaData": {} + } + ], + "arguments": { "contactKey": "{{Contact.Key}}", "value": "{{DateTime.Now}}" }, + "configurationArguments": { + "dataExtensionId": "ace267f0-b81d-e711-80cc-1402ec7222b4", + "field": "4e875b26-0317-4525-bfa0-50c8d1b7a7b5" + }, + "metaData": { + "dataExtensionName": "test_TestData", + "cachedFieldName": "JourneyConfirmed", + "cachedDisplayValue": "" + }, + "schema": { + "arguments": { + "contactKey": { + "dataType": "Text", + "isNullable": false, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "value": { + "dataType": "Text", + "isNullable": false, + "direction": "In", + "readOnly": false, + "access": "Hidden" + } + } + } + }, + { + "id": "cfc3ec53-4314-4504-9f9d-1fe53fdf0bcf", + "key": "SMSSYNC-1", + "name": "Kate Test SMS", + "description": "", + "type": "SMSSYNC", + "outcomes": [ + { + "key": "d4d46c46-bf8c-4c62-bd34-4979548796cd", + "next": "WAIT-3", + "arguments": {}, + "metaData": {} + } + ], + "arguments": { + "contactKey": "{{Contact.Key}}", + "defaultSMSAddress": "{{Contact.Default.SMS}}", + "mobileNumber": "{{InteractionDefaults.MobileNumber}}", + "contactId": "{{Contact.Id}}", + "definitionInstanceId": "{{Context.DefinitionInstanceId}}", + "definitionId": "{{Context.DefinitionId}}" + }, + "configurationArguments": { + "c__mobileMessage_id": "NTIzOjc4OjA", + "r__mobileKeyword_codeKeyword": "4912312345678.TESTEXISTING_KEYWORD", + "isOptIn": false, + "honorBlackoutWindowEnum": 0, + "mobileBlackoutWindowStartTime": "", + "mobileBlackoutWindowEndTime": "", + "applicationExtensionKey": "jb-mobile-connect-send-sms-sync" + }, + "metaData": { + "isConfigured": true + }, + "schema": { + "arguments": { + "smsJobId": { + "dataType": "Text", + "isNullable": true, + "direction": "Out", + "readOnly": false, + "access": "Hidden" + }, + "isAddressCreated": { + "dataType": "Boolean", + "isNullable": true, + "direction": "Out", + "readOnly": false, + "access": "Hidden" + }, + "isSubscriptionCreated": { + "dataType": "Boolean", + "isNullable": true, + "direction": "Out", + "readOnly": false, + "access": "Hidden" + }, + "isTriggeredSend": { + "dataType": "Boolean", + "isNullable": true, + "direction": "Out", + "readOnly": false, + "access": "Hidden" + }, + "isWithinBlackout": { + "dataType": "Boolean", + "isNullable": true, + "direction": "Out", + "readOnly": false, + "access": "Hidden" + }, + "isValidMobileNumber": { + "dataType": "Boolean", + "isNullable": true, + "direction": "Out", + "readOnly": false, + "access": "Hidden" + }, + "outMessageId": { + "dataType": "Text", + "isNullable": true, + "direction": "Out", + "readOnly": false, + "access": "Hidden" + }, + "outKeywordId": { + "dataType": "Text", + "isNullable": true, + "direction": "Out", + "readOnly": false, + "access": "Hidden" + }, + "outIsOptIn": { + "dataType": "Boolean", + "isNullable": true, + "direction": "Out", + "readOnly": false, + "access": "Hidden" + }, + "outHonorBlackoutWindowEnum": { + "dataType": "Number", + "isNullable": true, + "direction": "Out", + "readOnly": false, + "access": "Hidden" + }, + "outMobileBlackoutWindowStartTime": { + "dataType": "Text", + "isNullable": true, + "direction": "Out", + "readOnly": false, + "access": "Hidden" + }, + "outMobileBlackoutWindowEndTime": { + "dataType": "Text", + "isNullable": true, + "direction": "Out", + "readOnly": false, + "access": "Hidden" + }, + "outUtcOffset": { + "dataType": "Text", + "isNullable": true, + "direction": "Out", + "readOnly": false, + "access": "Hidden" + }, + "outWindowStart": { + "dataType": "Text", + "isNullable": true, + "direction": "Out", + "readOnly": false, + "access": "Hidden" + }, + "outWindowEnd": { + "dataType": "Text", + "isNullable": true, + "direction": "Out", + "readOnly": false, + "access": "Hidden" + }, + "outTimeZoneId": { + "dataType": "Number", + "isNullable": true, + "direction": "Out", + "readOnly": false, + "access": "Hidden" + }, + "outIsTZValid": { + "dataType": "Boolean", + "isNullable": true, + "direction": "Out", + "readOnly": false, + "access": "Hidden" + }, + "outIsMobileBlackoutWindowEnabled": { + "dataType": "Boolean", + "isNullable": true, + "direction": "Out", + "readOnly": false, + "access": "Hidden" + }, + "outIsUsingDEAttributesForPersonalization": { + "dataType": "Boolean", + "isNullable": true, + "direction": "Out", + "readOnly": false, + "access": "Hidden" + }, + "outCountProcessedSingletonDuringBatchMethod": { + "dataType": "LongNumber", + "isNullable": true, + "direction": "Out", + "readOnly": false, + "access": "Hidden" + }, + "contactKey": { + "dataType": "Text", + "isNullable": false, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "defaultSMSAddress": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "mobileNumber": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "contactId": { + "dataType": "Text", + "isNullable": false, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "definitionInstanceId": { + "dataType": "Text", + "isNullable": false, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "definitionId": { + "dataType": "Text", + "isNullable": false, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "eventData": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + } + } + } + } + ], + "triggers": [ + { + "key": "TRIGGER", + "name": "test_TESTDataentry", + "description": "", + "type": "APIEvent", + "outcomes": [], + "arguments": { + "filterResult": "{{Contact.FilterId.e4ddb887-6f2d-46b1-9f64-9a020f217339}}" + }, + "configurationArguments": { + "schemaVersionId": 133, + "criteria": "<FilterDefinition><ConditionSet Operator=\"AND\" ConditionSetName=\"Individual Filter Grouping\"></ConditionSet></FilterDefinition>", + "filterDefinitionId": "e4ddb887-6f2d-46b1-9f64-9a020f217339" + }, + "metaData": { + "scheduleState": "No Schedule", + "sourceInteractionId": "00000000-0000-0000-0000-000000000000", + "r__event_key": "APIEvent-60130566-e2fe-eb29-4140-15c27093a80b", + "chainType": "None", + "configurationRequired": false, + "iconUrl": "/events/images/icon_journeyBuilder-event-api-blue.svg", + "title": "", + "category": "Event" + } + } + ], + "goals": [], + "exits": [], + "notifiers": [], + "entryMode": "OnceAndDone", + "definitionType": "Multistep", + "channel": "", + "defaults": { + "email": ["{{Event.APIEvent-60130566-e2fe-eb29-4140-15c27093a80b.\"emailAddress\"}}"], + "properties": {} + }, + "metaData": {}, + "executionMode": "Production", + "status": "Draft", + "scheduledStatus": "Draft", + "r__folder_Path": "my journeys" +} diff --git a/test/resources/9999999/journey/put-updatecontact-expected.json b/test/resources/9999999/journey/put-updatecontact-expected.json new file mode 100644 index 000000000..3af6b5412 --- /dev/null +++ b/test/resources/9999999/journey/put-updatecontact-expected.json @@ -0,0 +1,108 @@ +{ + "key": "testExisting_journey_updatecontact", + "name": "testExisting_journey_updatecontact", + "lastPublishedDate": "0001-01-01T00:00:00", + "description": "", + "version": 1, + "workflowApiVersion": 1, + "createdDate": "2024-05-04T05:54:48.027", + "modifiedDate": "2024-05-04T17:25:57.9", + "activities": [ + { + "key": "UPDATECONTACTDATAV2-1", + "name": "Update Contact - TEST", + "description": "", + "type": "UPDATECONTACTDATA", + "outcomes": [ + { + "key": "9f21d42b-4679-4561-911a-4bccf84672ba", + "arguments": {}, + "metaData": { + "invalid": false + } + } + ], + "arguments": { + "activityData": { + "updateContactFields": [ + { + "r__dataExtensionField_name": "LastName", + "value": "TEST", + "r__dataExtension_key": "testExisting_dataExtension" + } + ] + } + }, + "configurationArguments": {}, + "metaData": { + "isConfigured": true + }, + "schema": { + "arguments": { + "activityData": { + "dataType": "Text", + "isNullable": false, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "contactKey": { + "dataType": "Text", + "isNullable": false, + "direction": "In", + "readOnly": false, + "access": "Hidden" + } + } + } + } + ], + "triggers": [ + { + "key": "TRIGGER", + "name": "TRIGGER", + "description": "", + "type": "EmailAudience", + "outcomes": [], + "arguments": {}, + "configurationArguments": {}, + "metaData": { + "r__event_key": "DEAudience-2e3c73b6-48cc-2ec0-5522-48636e1a236e", + "chainType": "None", + "configurationRequired": false, + "iconUrl": "/images/icon-data-extension.svg", + "title": "Data Extension", + "entrySourceGroupConfigUrl": "jb:///data/entry/audience/entrysourcegroupconfig.json", + "sourceInteractionId": "00000000-0000-0000-0000-000000000000" + } + } + ], + "goals": [], + "exits": [], + "notifiers": [], + "entryMode": "NotSet", + "definitionType": "Multistep", + "channel": "", + "defaults": { + "email": [ + "{{Event.DEAudience-2e3c73b6-48cc-2ec0-5522-48636e1a236e.\"Email\"}}" + ], + "properties": { + "analyticsTracking": { + "enabled": true, + "analyticsType": "google", + "urlDomainsToTrack": [] + } + } + }, + "metaData": { + "dataSource": "ContactsModel", + "highThroughputSending": { + "email": false + } + }, + "executionMode": "Production", + "status": "Draft", + "scheduledStatus": "Draft", + "r__folder_Path": "my journeys" +} \ No newline at end of file diff --git a/test/resources/9999999/journey/template-expected.json b/test/resources/9999999/journey/template-expected.json new file mode 100644 index 000000000..16676f0c6 --- /dev/null +++ b/test/resources/9999999/journey/template-expected.json @@ -0,0 +1,229 @@ +{ + "key": "{{{prefix}}}journey_Quicksend", + "name": "{{{prefix}}}journey_Quicksend", + "description": "", + "workflowApiVersion": 1, + "modifiedDate": "2024-04-24T12:19:12.803", + "activities": [ + { + "key": "EMAILV2-1", + "name": "{{{prefix}}}asset_mail", + "description": "", + "type": "EMAILV2", + "outcomes": [ + { + "key": "a6b9c1af-cd89-4ce8-ba4f-bd4289188dc2", + "arguments": {}, + "metaData": { "invalid": false } + } + ], + "arguments": {}, + "configurationArguments": { + "isModified": true, + "googleAnalyticsCampaignName": "", + "triggeredSend": { + "autoAddSubscribers": true, + "autoUpdateSubscribers": true, + "bccEmail": [ + "%%= ContentBlockByName(\"Content Builder\\dont strip non ssjs content\") =%%" + ], + "ccEmail": ["%%= ContentBlockByKey(\"{{{prefix}}}asset_htmlblock\") =%%"], + "created": {}, + "description": "my activity info text", + "dynamicEmailSubject": "{{{prefix}}} dynamic email subject %%= ContentBlockByKey(\"{{{prefix}}}asset_htmlblock\") =%%", + "emailSubject": "{{{prefix}}} email subject %%= ContentBlockByKey(\"{{{prefix}}}asset_htmlblock\") =%%", + "exclusionFilter": "/* insert ampscript here */ %%= ContentBlockById(1295064) =%%", + "isSalesforceTracking": false, + "isMultipart": true, + "isSendLogging": true, + "isStoppedOnJobError": false, + "keyword": "", + "modified": {}, + "preHeader": "{{{prefix}}} email preheader %%= ContentBlockByKey(\"{{{prefix}}}asset_htmlblock\") =%%", + "suppressTracking": true, + "throttleLimit": 0, + "throttleOpens": "1/1/0001 12:00:00 AM", + "throttleCloses": "1/1/0001 12:00:00 AM", + "isTrackingClicks": true, + "r__list_PathName": { + "publicationList": "my subscribers/All Subscribers", + "suppressionLists": ["Suppression Lists/{{{prefix}}}suppressionList"] + }, + "r__dataExtension_key": { + "domainExclusions": ["{{{prefix}}}DomainExclusion"] + }, + "r__deliveryProfile_key": "Default", + "r__senderProfile_key": "{{{prefix}}}senderProfile", + "r__sendClassification_key": "{{{prefix}}}sendClassification", + "c__priority": "High", + "r__asset_key": "{{{prefix}}}asset_message" + }, + "applicationExtensionKey": "jb-email-activity" + }, + "metaData": { + "category": "message", + "version": "1.0", + "icon": "https://jb-email-activity.s7.marketingcloudapps.com/img/email-icon.svg", + "iconSmall": "https://jb-email-activity.s7.marketingcloudapps.com/img/email-icon.svg", + "statsContactIcon": null, + "original_icon": "/img/email-icon.svg", + "original_iconSmall": "/img/email-icon.svg", + "sections": {}, + "isConfigured": true + }, + "schema": { + "arguments": { + "requestID": { + "dataType": "Text", + "isNullable": true, + "direction": "Out", + "readOnly": false, + "access": "Hidden" + }, + "messageKey": { + "dataType": "Text", + "isNullable": true, + "direction": "Out", + "readOnly": false, + "access": "Hidden" + }, + "activityId": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "definitionId": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": true, + "access": "Hidden" + }, + "emailSubjectDataBound": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": true, + "access": "Hidden" + }, + "contactId": { + "dataType": "Number", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "contactKey": { + "dataType": "Text", + "isNullable": false, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "emailAddress": { + "dataType": "Text", + "isNullable": false, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "sourceCustomObjectId": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "sourceCustomObjectKey": { + "dataType": "LongNumber", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "fieldType": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "eventData": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "obfuscationProperties": { + "dataType": "Text", + "isNullable": true, + "direction": "In", + "readOnly": false, + "access": "Hidden" + }, + "customObjectKey": { + "dataType": "LongNumber", + "isNullable": true, + "direction": "In", + "readOnly": true, + "access": "Hidden" + }, + "definitionInstanceId": { + "dataType": "Text", + "isNullable": false, + "direction": "In", + "readOnly": false, + "access": "Hidden" + } + } + } + } + ], + "triggers": [ + { + "key": "TRIGGER", + "name": "TRIGGER", + "description": "", + "type": "EmailAudience", + "outcomes": [], + "arguments": {}, + "configurationArguments": {}, + "metaData": { + "sourceInteractionId": "00000000-0000-0000-0000-000000000000", + "r__event_key": "DEAudience-11be962d-064c-83d9-2804-7d1befc10325", + "chainType": "None", + "configurationRequired": false, + "iconUrl": "/images/icon-data-extension.svg", + "title": "Data Extension", + "entrySourceGroupConfigUrl": "jb:///data/entry/audience/entrysourcegroupconfig.json" + } + } + ], + "goals": [], + "exits": [], + "notifiers": [], + "entryMode": "MultipleEntries", + "definitionType": "Quicksend", + "channel": "email", + "defaults": { + "email": ["{{Event.DEAudience-11be962d-064c-83d9-2804-7d1befc10325.\"Email\"}}"], + "properties": { + "analyticsTracking": { + "enabled": true, + "analyticsType": "google", + "urlDomainsToTrack": [] + } + } + }, + "metaData": { + "dataSource": "ContactsModel", + "isScheduleSet": true, + "highThroughputSending": { "email": false } + }, + "executionMode": "Production", + "scheduledStatus": "Draft", + "r__folder_Path": "my journeys" +} diff --git a/test/resources/9999999/journey/validate-callout-expected.json b/test/resources/9999999/journey/validate-callout-expected.json new file mode 100644 index 000000000..0967ef424 --- /dev/null +++ b/test/resources/9999999/journey/validate-callout-expected.json @@ -0,0 +1 @@ +{} diff --git a/test/resources/9999999/legacy/v1/beta/automations/notifications/RkpOcE9qSVh2VUdnYTVJbWFfWW14dzoyNTow-PAUSED/get-response.json b/test/resources/9999999/legacy/v1/beta/automations/notifications/RkpOcE9qSVh2VUdnYTVJbWFfWW14dzoyNTow-PAUSED/get-response.json new file mode 100644 index 000000000..d8e6cf368 --- /dev/null +++ b/test/resources/9999999/legacy/v1/beta/automations/notifications/RkpOcE9qSVh2VUdnYTVJbWFfWW14dzoyNTow-PAUSED/get-response.json @@ -0,0 +1,3 @@ +{ + "programId": "ZGQ4N2M2ZjEtYjJlZi00MDljLTg3MDctYzYwNWQ0MzdiYWI4OjI1OjA" +} diff --git a/test/resources/9999999/legacy/v1/beta/automations/notifications/RkpOcE9qSVh2VUdnYTVJbWFfWW14dzoyNTow/get-response.json b/test/resources/9999999/legacy/v1/beta/automations/notifications/RkpOcE9qSVh2VUdnYTVJbWFfWW14dzoyNTow/get-response.json new file mode 100644 index 000000000..02c3b73d1 --- /dev/null +++ b/test/resources/9999999/legacy/v1/beta/automations/notifications/RkpOcE9qSVh2VUdnYTVJbWFfWW14dzoyNTow/get-response.json @@ -0,0 +1,21 @@ +{ + "programId": "ZGQ4N2M2ZjEtYjJlZi00MDljLTg3MDctYzYwNWQ0MzdiYWI4OjI1OjA", + "workers": [ + { + "programId": "ZGQ4N2M2ZjEtYjJlZi00MDljLTg3MDctYzYwNWQ0MzdiYWI4OjI1OjA", + "id": "YjA2NmVlODEtODllOS00NTE4LTkwYzYtMTY4Mzg2ZTk3MGE4OjEyOjA", + "notificationType": "Complete", + "definition": "complete@test.accenture.com", + "body": "", + "channelType": "Account" + }, + { + "programId": "ZGQ4N2M2ZjEtYjJlZi00MDljLTg3MDctYzYwNWQ0MzdiYWI4OjI1OjA", + "id": "NGIzZGQ5N2EtMDI0ZS00MzFiLTg5ZWYtNTdjYTI4ODVjMjQ0OjEyOjA", + "notificationType": "Error", + "definition": "error@test.accenture.com", + "body": "test", + "channelType": "Account" + } + ] +} diff --git a/test/resources/9999999/legacy/v1/beta/automations/notifications/RkpOcE9qSVh2VUdnYTVJbWFfWW14dzoyNTow/post-response.json b/test/resources/9999999/legacy/v1/beta/automations/notifications/RkpOcE9qSVh2VUdnYTVJbWFfWW14dzoyNTow/post-response.json new file mode 100644 index 000000000..e69de29bb diff --git a/test/resources/9999999/legacy/v1/beta/automations/notifications/bHF6Q0Q3b1VXa21OdVQzZFQ0ckVSQToyNTow/get-response.json b/test/resources/9999999/legacy/v1/beta/automations/notifications/bHF6Q0Q3b1VXa21OdVQzZFQ0ckVSQToyNTow/get-response.json new file mode 100644 index 000000000..f6f94e407 --- /dev/null +++ b/test/resources/9999999/legacy/v1/beta/automations/notifications/bHF6Q0Q3b1VXa21OdVQzZFQ0ckVSQToyNTow/get-response.json @@ -0,0 +1,3 @@ +{ + "programId": "MGZjMmFjOTYtMTRiYS00OTVhLThkYjktM2RkZDRmOGFjNDQ0OjI1OjA" +} diff --git a/test/resources/9999999/legacy/v1/beta/automations/notifications/cDhLQ2o2NExxVVc5N3VZeHF5WEExUToyNTow/get-response.json b/test/resources/9999999/legacy/v1/beta/automations/notifications/cDhLQ2o2NExxVVc5N3VZeHF5WEExUToyNTow/get-response.json new file mode 100644 index 000000000..5d5ae6f3d --- /dev/null +++ b/test/resources/9999999/legacy/v1/beta/automations/notifications/cDhLQ2o2NExxVVc5N3VZeHF5WEExUToyNTow/get-response.json @@ -0,0 +1,3 @@ +{ + "programId": "MzIxMjAzMmYtM2Y0OC00ZTdlLWIyODktMzE5YWQyODA2NTc1OjI1OjA" +} diff --git a/test/resources/9999999/legacy/v1/beta/bulk/automations/automation/definition/NewRkpOcE9qSVh2VUdnYTVJbWFfWW14dzoyNTow/get-response.json b/test/resources/9999999/legacy/v1/beta/bulk/automations/automation/definition/NewRkpOcE9qSVh2VUdnYTVJbWFfWW14dzoyNTow/get-response.json new file mode 100644 index 000000000..6daa8976e --- /dev/null +++ b/test/resources/9999999/legacy/v1/beta/bulk/automations/automation/definition/NewRkpOcE9qSVh2VUdnYTVJbWFfWW14dzoyNTow/get-response.json @@ -0,0 +1,29 @@ +{ + "guidId": "a8afb0e2-b00a-4c88-ad2e-1f7f8788c560", + "id": "NewRkpOcE9qSVh2VUdnYTVJbWFfWW14dzoyNTow", + "name": "testNew_automation", + "description": "created on deploy", + "key": "testNew_automation", + "clientId": 9999999, + "lastSavedDate": "2023-07-04T07:49:08.577", + "lastSavedByName": "SFMC DevTools app user", + "createdDate": "2023-07-04T07:49:08.297", + "createdByName": "SFMC DevTools app user", + "updateInProgress": false, + "automationType": "scheduled", + "scheduleObject": { + "id": "WkNtUVIxN21WRTZndGxkTnZIS1JWUTozNjow", + "key": "921", + "createdDate": "2025-03-18T09:57:00Z", + "createdBy": "https://mcxxxxx.rest.marketingcloudapis.com/legacy/v1/beta/organization/user/NzEwNDIwNDMyOjQ6MA", + "lastUpdated": "2025-03-18T09:57:00Z", + "lastUpdatedBy": "https://mcxxxxx.rest.marketingcloudapis.com/legacy/v1/beta/organization/user/NzEwNDIwNDMyOjQ6MA", + "name": "", + "description": "Will run every hour, effective 5-3-2025 at 10:45 through Wednesday 7 June 2079", + "startDate": "2025-03-05T10:45:00", + "iCalRecur": "FREQ=HOURLY;UNTIL=20790607T080000;INTERVAL=1", + "timeZone": "W. Europe Standard Time", + "timeZoneId": 5, + "scheduleStatus": "scheduled" + } +} diff --git a/test/resources/9999999/legacy/v1/beta/bulk/automations/automation/definition/RkpOcE9qSVh2VUdnYTVJbWFfWW14dzoyNTow-PAUSED/get-response.json b/test/resources/9999999/legacy/v1/beta/bulk/automations/automation/definition/RkpOcE9qSVh2VUdnYTVJbWFfWW14dzoyNTow-PAUSED/get-response.json new file mode 100644 index 000000000..ec315e2ee --- /dev/null +++ b/test/resources/9999999/legacy/v1/beta/bulk/automations/automation/definition/RkpOcE9qSVh2VUdnYTVJbWFfWW14dzoyNTow-PAUSED/get-response.json @@ -0,0 +1,51 @@ +{ + "id": "RkpOcE9qSVh2VUdnYTVJbWFfWW14dzoyNTow-PAUSED", + "key": "testExisting_automation_pause", + "createdDate": "2022-01-12T08:41:35.773Z", + "name": "testExisting_automation_pause", + "description": "bla bla", + "clientId": 9999999, + "status": "Scheduled", + "createdBy": { + "id": "NzE3MzUzNDA1OjQ6MA", + "name": "Tom Tester", + "email": "tom.tester@accenture.com" + }, + "modifiedDate": "2022-11-11T16:42:36.513Z", + "modifiedBy": { + "id": "NzE3MzUzNDA1OjQ6MA", + "name": "Tom Tester", + "email": "tom.tester@accenture.com" + }, + "isPlatformObject": false, + "notifications": "https://mcxxxxx.rest.marketingcloudapis.com/legacy/v1/beta/hub/notifications/RkpOcE9qSVh2VUdnYTVJbWFfWW14dzoxMjow", + "automationType": "scheduled", + "lastPausedDate": "2025-03-14T15:21:57.62Z", + "lastPausedBy": { + "id": "NzEwNDIwNDE4OjQ6MA", + "name": "Jörn Berkefeld", + "email": "joern.berkefeld@accenture.com" + }, + "lastSaveDate": "2024-11-04T17:42:13.143Z", + "lastSavedBy": { + "id": "NzEwNDIwNDE4OjQ6MA", + "name": "Jörn Berkefeld", + "email": "joern.berkefeld@accenture.com" + }, + "guidId": "08afb0e2-b00a-4c88-fixKey_pause", + "scheduleObject": { + "id": "WkNtUVIxN21WRTZndGxkTnZIS1JWUTozNjow", + "key": "921", + "createdDate": "2025-03-18T09:57:00Z", + "createdBy": "https://mcxxxxx.rest.marketingcloudapis.com/legacy/v1/beta/organization/user/NzEwNDIwNDMyOjQ6MA", + "lastUpdated": "2025-03-18T09:57:00Z", + "lastUpdatedBy": "https://mcxxxxx.rest.marketingcloudapis.com/legacy/v1/beta/organization/user/NzEwNDIwNDMyOjQ6MA", + "name": "", + "description": "Will run every hour, effective 5-3-2025 at 10:45 through Wednesday 7 June 2079", + "startDate": "2025-03-05T10:45:00", + "iCalRecur": "FREQ=HOURLY;UNTIL=20790607T080000;INTERVAL=1", + "timeZone": "W. Europe Standard Time", + "timeZoneId": 5, + "scheduleStatus": "scheduled" + } +} diff --git a/test/resources/9999999/legacy/v1/beta/bulk/automations/automation/definition/RkpOcE9qSVh2VUdnYTVJbWFfWW14dzoyNTow/get-response.json b/test/resources/9999999/legacy/v1/beta/bulk/automations/automation/definition/RkpOcE9qSVh2VUdnYTVJbWFfWW14dzoyNTow/get-response.json new file mode 100644 index 000000000..450c4b56e --- /dev/null +++ b/test/resources/9999999/legacy/v1/beta/bulk/automations/automation/definition/RkpOcE9qSVh2VUdnYTVJbWFfWW14dzoyNTow/get-response.json @@ -0,0 +1,50 @@ +{ + "id": "RkpOcE9qSVh2VUdnYTVJbWFfWW14dzoyNTow", + "key": "testExisting_automation", + "createdDate": "2022-01-12T08:41:35.773Z", + "name": "testExisting_automation", + "description": "bla bla", + "clientId": 9999999, + "status": "PausedSchedule", + "createdBy": { + "id": "NzE3MzUzNDA1OjQ6MA", + "name": "Tom Tester", + "email": "tom.tester@accenture.com" + }, + "modifiedDate": "2022-11-11T16:42:36.513Z", + "modifiedBy": { + "id": "NzE3MzUzNDA1OjQ6MA", + "name": "Tom Tester", + "email": "tom.tester@accenture.com" + }, + "isPlatformObject": false, + "notifications": "https://mcxxxxx.rest.marketingcloudapis.com/legacy/v1/beta/hub/notifications/RkpOcE9qSVh2VUdnYTVJbWFfWW14dzoxMjow", + "automationType": "scheduled", + "lastPausedDate": "2025-03-14T15:21:57.62Z", + "lastPausedBy": { + "id": "NzEwNDIwNDE4OjQ6MA", + "name": "Jörn Berkefeld", + "email": "joern.berkefeld@accenture.com" + }, + "lastSaveDate": "2024-11-04T17:42:13.143Z", + "lastSavedBy": { + "id": "NzEwNDIwNDE4OjQ6MA", + "name": "Jörn Berkefeld", + "email": "joern.berkefeld@accenture.com" + }, + "scheduleObject": { + "id": "WkNtUVIxN21WRTZndGxkTnZIS1JWUTozNjow", + "key": "921", + "createdDate": "2025-03-18T09:57:00Z", + "createdBy": "https://mcxxxxx.rest.marketingcloudapis.com/legacy/v1/beta/organization/user/NzEwNDIwNDMyOjQ6MA", + "lastUpdated": "2025-03-18T09:57:00Z", + "lastUpdatedBy": "https://mcxxxxx.rest.marketingcloudapis.com/legacy/v1/beta/organization/user/NzEwNDIwNDMyOjQ6MA", + "name": "", + "description": "Will run every hour, effective 5-3-2025 at 10:45 through Wednesday 7 June 2079", + "startDate": "2025-03-05T10:45:00", + "iCalRecur": "FREQ=HOURLY;UNTIL=20790607T080000;INTERVAL=1", + "timeZone": "W. Europe Standard Time", + "timeZoneId": 5, + "scheduleStatus": "paused" + } +} diff --git a/test/resources/9999999/legacy/v1/beta/bulk/automations/automation/definition/bHF6Q0Q3b1VXa21OdVQzZFQ0ckVSQToyNTow/get-response.json b/test/resources/9999999/legacy/v1/beta/bulk/automations/automation/definition/bHF6Q0Q3b1VXa21OdVQzZFQ0ckVSQToyNTow/get-response.json new file mode 100644 index 000000000..e3880cb7e --- /dev/null +++ b/test/resources/9999999/legacy/v1/beta/bulk/automations/automation/definition/bHF6Q0Q3b1VXa21OdVQzZFQ0ckVSQToyNTow/get-response.json @@ -0,0 +1,216 @@ +{ + "id": "bHF6Q0Q3b1VXa21OdVQzZFQ0ckVSQToyNTow", + "key": "testExisting_automation_wait", + "createdDate": "2024-11-04T17:30:12.973Z", + "updateInProgress": false, + "name": "testExisting_automation_wait", + "description": "", + "createdBy": { + "id": "NzEwNDIwNDE4OjQ6MA", + "name": "Jörn Berkefeld", + "email": "joern.berkefeld@accenture.com" + }, + "modifiedDate": "2024-11-04T17:42:13.203Z", + "status": "Ready", + "memberId": 510004860, + "processes": [ + { + "id": "OXJtc2M5STlma3FpVzN3NkF4Y0pWdzoyNzow", + "name": "", + "description": "", + "sequence": 0, + "workers": [ + { + "id": "ZC1YQS1Jd25uMGV6Z1dFRmFiQzFMZzoyOTow", + "key": "07801bb9-0fd1-4ed0-9349-625c5a03b957", + "sequence": 0, + "name": "1 Years", + "description": "", + "activityObjectId": "1bd41a92-2c57-463c-a1e6-6e1549e481a1", + "objectTypeId": 467, + "serializedObject": "{\"duration\":1,\"durationUnits\":\"Years\"}", + "selectedObject": [ + { + "categoryId": -1 + } + ], + "guidId": "f8c0e577-278c-479f-b381-610569b0b52e" + } + ], + "guidId": "73acb9f6-3dd2-4a7e-a25b-7c3a03170957" + }, + { + "id": "YllfOWc3dFVCRXU4RGQxaTRXOUZLZzoyNzow", + "name": "", + "description": "", + "sequence": 1, + "workers": [ + { + "id": "cWZwazAtTUdPRTJmdnBPWWF4MVVIZzoyOTow", + "key": "41fed5be-317a-425a-a81d-94485042ad26", + "sequence": 0, + "name": "1 Months", + "description": "", + "activityObjectId": "76f255e3-1603-4d8b-be59-32ac6fe61e15", + "objectTypeId": 467, + "serializedObject": "{\"duration\":1,\"durationUnits\":\"Months\"}", + "selectedObject": [ + { + "categoryId": -1 + } + ], + "guidId": "d364faa9-06e3-4d38-9fbe-93986b1d541e" + } + ], + "guidId": "83fd8f6d-54bb-4b04-bc0d-dd62e16f452a" + }, + { + "id": "d1VwZGsxN0dwa3V0dEtQSTZOeXlRUToyNzow", + "name": "", + "description": "", + "sequence": 2, + "workers": [ + { + "id": "TnJHdVdodWJIMDJWOHIzWTFTTHdHQToyOTow", + "key": "984a2011-87d9-4219-b609-ee3f13be7520", + "sequence": 0, + "name": "1 Weeks", + "description": "", + "activityObjectId": "85a405e4-e77b-4a2e-8d1b-9ad34244ac10", + "objectTypeId": 467, + "serializedObject": "{\"duration\":1,\"durationUnits\":\"Weeks\"}", + "selectedObject": [ + { + "categoryId": -1 + } + ], + "guidId": "5aaeb136-9b1b-4d1f-95f2-bdd8d522f018" + } + ], + "guidId": "935d4ac1-c65e-4ba6-adb4-a3c8e8dcb241" + }, + { + "id": "cG5GWTY1a1RiRVNnWnpvRDBhUTJmdzoyNzow", + "name": "", + "description": "", + "sequence": 3, + "workers": [ + { + "id": "Tkw0dkFMQVFJVUd4bXVuQWM4dlhBQToyOTow", + "key": "29cc7a78-7a98-49bb-821d-f68f3695f386", + "sequence": 0, + "name": "1 Days", + "description": "", + "activityObjectId": "562cf01a-6cca-4fd9-9d3c-f2649379a282", + "objectTypeId": 467, + "serializedObject": "{\"duration\":1,\"durationUnits\":\"Days\"}", + "selectedObject": [ + { + "categoryId": -1 + } + ], + "guidId": "002fbe34-10b0-4121-b19a-e9c073cbd700" + } + ], + "guidId": "eb5871a6-1399-446c-a067-3a03d1a4367f" + }, + { + "id": "VjFyRUptR0hyRTJSdE1IR1RScG5RUToyNzow", + "name": "", + "description": "", + "sequence": 4, + "workers": [ + { + "id": "endvNktPM1ZOVVdpcHpnLUxJeFIydzoyOTow", + "key": "d83889a8-7d08-4234-979f-e8356ca6a9d2", + "sequence": 0, + "name": "1 Hours", + "description": "", + "activityObjectId": "2722bb7c-2ea2-4cf5-8891-96c5a4362a72", + "objectTypeId": 467, + "serializedObject": "{\"duration\":1,\"durationUnits\":\"Hours\"}", + "selectedObject": [ + { + "categoryId": -1 + } + ], + "guidId": "283a0acf-d5ed-4535-a2a7-383e2c8c51db" + } + ], + "guidId": "26c45a57-8761-4dac-91b4-c1c64d1a6741" + }, + { + "id": "SjFFR2s4eXR5ME93UU85anZpS0Y3QToyNzow", + "name": "", + "description": "", + "sequence": 5, + "workers": [ + { + "id": "R2hCN0ZnbXZBa0NoVF9VMzNpWnM0QToyOTow", + "key": "8c51a35a-65dc-4675-93e5-c30037fc6a77", + "sequence": 0, + "name": "1 Minutes", + "description": "", + "activityObjectId": "5d5f816b-b024-45a9-8ce9-726c6dd61bf4", + "objectTypeId": 467, + "serializedObject": "{\"duration\":1,\"durationUnits\":\"Minutes\"}", + "selectedObject": [ + { + "categoryId": -1 + } + ], + "guidId": "167b101a-af09-4002-a14f-f537de266ce0" + } + ], + "guidId": "93065127-adcc-43cb-b040-ef63be2285ec" + }, + { + "id": "a0JPTkRiNTFmVUtRQ3dyMXlRYWdHdzoyNzow", + "name": "", + "description": "", + "sequence": 6, + "workers": [ + { + "id": "YXBCU1o1bk9fa3V4MVUyNDYwb2tzQToyOTow", + "key": "933b7da5-ef25-4e5a-b92c-ff061d05ba7f", + "sequence": 0, + "name": "03:00 PM", + "description": "", + "activityObjectId": "1c9836b8-0242-4620-9421-21d36a0df751", + "objectTypeId": 467, + "serializedObject": "{\"specifiedTime\":\"15:00\",\"timeZone\":\"GMT Standard Time\"}", + "selectedObject": [ + { + "categoryId": -1 + } + ], + "guidId": "6752906a-ce99-4bfe-b1d5-4db8eb4a24b0" + } + ], + "guidId": "0d8d1390-75be-427d-900b-0af5c906a01b" + } + ], + "isPlatformObject": false, + "notifications": "https://mcxxxxx.rest.marketingcloudapis.com/legacy/v1/beta/hub/notifications/bHF6Q0Q3b1VXa21OdVQzZFQ0ckVSQToxMjow", + "automationType": "unspecified", + "categoryId": 4700, + "folderPath": "my automations", + "lastPausedDate": "2025-03-14T15:21:57.62Z", + "lastPausedBy": { + "id": "NzEwNDIwNDE4OjQ6MA", + "name": "Jörn Berkefeld", + "email": "joern.berkefeld@accenture.com" + }, + "lastSaveDate": "2024-11-04T17:42:13.143Z", + "lastSavedBy": { + "id": "NzEwNDIwNDE4OjQ6MA", + "name": "Jörn Berkefeld", + "email": "joern.berkefeld@accenture.com" + }, + "selectedCategoryId": [ + { + "categoryId": 4700 + } + ], + "guidId": "0fc2ac96-14ba-495a-8db9-3ddd4f8ac444-wait" +} diff --git a/test/resources/9999999/legacy/v1/beta/bulk/automations/automation/definition/cDhLQ2o2NExxVVc5N3VZeHF5WEExUToyNTow/get-response.json b/test/resources/9999999/legacy/v1/beta/bulk/automations/automation/definition/cDhLQ2o2NExxVVc5N3VZeHF5WEExUToyNTow/get-response.json new file mode 100644 index 000000000..be294ab15 --- /dev/null +++ b/test/resources/9999999/legacy/v1/beta/bulk/automations/automation/definition/cDhLQ2o2NExxVVc5N3VZeHF5WEExUToyNTow/get-response.json @@ -0,0 +1,79 @@ +{ + "id": "cDhLQ2o2NExxVVc5N3VZeHF5WEExUToyNTow", + "key": "testExisting_automation_event", + "createdDate": "2024-11-07T10:20:18.877Z", + "name": "testExisting_automation_event", + "description": "", + "clientId": 9999999, + "status": "Scheduled", + "createdBy": { + "id": "NzEwNDIwNDE4OjQ6MA", + "name": "Jörn Berkefeld", + "email": "joern.berkefeld@accenture.com" + }, + "modifiedDate": "2024-11-07T22:17:24.457Z", + "modifiedBy": { + "id": "LTEwMDA6NDow", + "name": "System" + }, + "processes": [ + { + "id": "Q3FPcDlGeGc1VTJHcE9mZmlmNW9oUToyNzow", + "createdDate": "2024-11-07T10:26:58.62Z", + "name": "", + "description": "", + "sequence": 0, + "status": "Complete", + "workerCounts": [ + { + "name": "QueryDefinition", + "objectTypeId": 300, + "count": 1, + "status": "Complete" + } + ], + "instanceId": "aDJvYXJPR2Z5MHVNNHdBVVA0cG5xUToyODow" + }, + { + "id": "UDF0MWd4SlF0RW1CRWdLUnlIbTUxUToyNzow", + "createdDate": "2024-11-07T10:59:15.813Z", + "name": "", + "description": "", + "sequence": 2, + "status": "Complete", + "workerCounts": [ + { + "name": "JourneyBuilderAudience", + "objectTypeId": 952, + "count": 1, + "status": "Complete" + } + ], + "instanceId": "VjBzTVVjZHJja0M3TS12ZlRPMmZ6QToyODow" + } + ], + "schedule": "https://mcxxxxx.rest.marketingcloudapis.com/legacy/v1/beta/automations/schedule/dXZSTUJ0Q2xDa0tLVHlZRldqVlF1ZzozNjow", + "scheduledTime": "2024-11-07T23:15:00Z", + "startTime": "2024-11-07T22:15:19.057Z", + "completedTime": "2024-11-07T22:17:24.453Z", + "lastRunTime": "2024-11-07T22:15:19.057Z", + "lastRunInstance": "https://mcxxxxx.rest.marketingcloudapis.com/legacy/v1/beta/bulk/automations/automation/instance/VEhxcm1sTk5DMEdhZnQ1S0ZsMURIZzoyNjow", + "instanceId": "VEhxcm1sTk5DMEdhZnQ1S0ZsMURIZzoyNjow", + "automationInstance": "https://mcxxxxx.rest.marketingcloudapis.com/legacy/v1/beta/bulk/automations/automation/instance/VEhxcm1sTk5DMEdhZnQ1S0ZsMURIZzoyNjow", + "isPlatformObject": false, + "notifications": "https://mcxxxxx.rest.marketingcloudapis.com/legacy/v1/beta/hub/notifications/cDhLQ2o2NExxVVc5N3VZeHF5WEExUToxMjow", + "automationType": "scheduled", + "lastPausedDate": "2025-03-14T15:21:57.62Z", + "lastPausedBy": { + "id": "NzEwNDIwNDE4OjQ6MA", + "name": "Jörn Berkefeld", + "email": "joern.berkefeld@accenture.com" + }, + "lastSaveDate": "2024-11-04T17:42:13.143Z", + "lastSavedBy": { + "id": "NzEwNDIwNDE4OjQ6MA", + "name": "Jörn Berkefeld", + "email": "joern.berkefeld@accenture.com" + }, + "lastRunStatus": "Complete" +} diff --git a/test/resources/9999999/legacy/v1/beta/bulk/automations/automation/definition/get-response.json b/test/resources/9999999/legacy/v1/beta/bulk/automations/automation/definition/get-response.json new file mode 100644 index 000000000..d0e9c8a53 --- /dev/null +++ b/test/resources/9999999/legacy/v1/beta/bulk/automations/automation/definition/get-response.json @@ -0,0 +1,286 @@ +{ + "startIndex": 0, + "itemsPerPage": 50, + "totalResults": 4, + "entry": [ + { + "id": "cDhLQ2o2NExxVVc5N3VZeHF5WEExUToyNTow", + "key": "testExisting_automation_event", + "createdDate": "2024-11-07T10:20:18.877Z", + "name": "testExisting_automation_event", + "description": "", + "clientId": 9999999, + "status": "Scheduled", + "createdBy": { + "id": "NzEwNDIwNDE4OjQ6MA", + "name": "Jörn Berkefeld", + "email": "joern.berkefeld@accenture.com" + }, + "modifiedDate": "2024-11-07T22:17:24.457Z", + "modifiedBy": { + "id": "LTEwMDA6NDow", + "name": "System" + }, + "processes": [ + { + "id": "Q3FPcDlGeGc1VTJHcE9mZmlmNW9oUToyNzow", + "createdDate": "2024-11-07T10:26:58.62Z", + "name": "", + "description": "", + "sequence": 0, + "status": "Complete", + "workerCounts": [ + { + "name": "QueryDefinition", + "objectTypeId": 300, + "count": 1, + "status": "Complete" + } + ], + "instanceId": "aDJvYXJPR2Z5MHVNNHdBVVA0cG5xUToyODow" + }, + { + "id": "UDF0MWd4SlF0RW1CRWdLUnlIbTUxUToyNzow", + "createdDate": "2024-11-07T10:59:15.813Z", + "name": "", + "description": "", + "sequence": 2, + "status": "Complete", + "workerCounts": [ + { + "name": "JourneyBuilderAudience", + "objectTypeId": 952, + "count": 1, + "status": "Complete" + } + ], + "instanceId": "VjBzTVVjZHJja0M3TS12ZlRPMmZ6QToyODow" + } + ], + "schedule": "https://mcxxxxx.rest.marketingcloudapis.com/legacy/v1/beta/automations/schedule/dXZSTUJ0Q2xDa0tLVHlZRldqVlF1ZzozNjow", + "scheduledTime": "2024-11-07T23:15:00Z", + "startTime": "2024-11-07T22:15:19.057Z", + "completedTime": "2024-11-07T22:17:24.453Z", + "lastRunTime": "2024-11-07T22:15:19.057Z", + "lastRunInstance": "https://mcxxxxx.rest.marketingcloudapis.com/legacy/v1/beta/bulk/automations/automation/instance/VEhxcm1sTk5DMEdhZnQ1S0ZsMURIZzoyNjow", + "instanceId": "VEhxcm1sTk5DMEdhZnQ1S0ZsMURIZzoyNjow", + "automationInstance": "https://mcxxxxx.rest.marketingcloudapis.com/legacy/v1/beta/bulk/automations/automation/instance/VEhxcm1sTk5DMEdhZnQ1S0ZsMURIZzoyNjow", + "isPlatformObject": false, + "notifications": "https://mcxxxxx.rest.marketingcloudapis.com/legacy/v1/beta/hub/notifications/cDhLQ2o2NExxVVc5N3VZeHF5WEExUToxMjow", + "automationType": "scheduled", + "lastRunStatus": "Complete" + }, + { + "id": "RkpOcE9qSVh2VUdnYTVJbWFfWW14dzoyNTow-PAUSED", + "name": "testExisting_automation_pause", + "description": "updated on deploy", + "key": "testExisting_automation_pause", + "typeId": 1, + "statusId": 4, + "status": "Scheduled", + "processes": [ + { + "workerCounts": [ + { + "name": "testExisting_dataExtract", + "objectTypeId": 73, + "count": 1 + }, + { + "name": "testExisting_emailSend", + "objectTypeId": 42, + "count": 2 + }, + { + "name": "testExisting_fileTransfer", + "objectTypeId": 53, + "count": 3 + }, + { + "name": "testExisting_importFile", + "objectTypeId": 43, + "count": 4 + }, + { + "name": "testExisting_query_WRONG_NAME", + "objectTypeId": 300, + "count": 5 + }, + { + "name": "testExisting_script", + "objectTypeId": 423, + "count": 6 + } + ], + "annotation": "", + "stepNumber": 0 + } + ], + "schedule": "https://mcxxxxx.rest.marketingcloudapis.com/legacy/v1/beta/automations/schedule/dXZSTUJ0Q2xDa0tLVHlZRldqVlF1ZzozNjow", + "scheduledTime": "2024-11-07T23:15:00Z", + "startTime": "2024-11-07T22:15:19.057Z", + "completedTime": "2024-11-07T22:17:24.453Z", + "lastRunTime": "2024-11-07T22:15:19.057Z", + "lastRunInstance": "https://mcxxxxx.rest.marketingcloudapis.com/legacy/v1/beta/bulk/automations/automation/instance/VEhxcm1sTk5DMEdhZnQ1S0ZsMURIZzoyNjow", + "instanceId": "VEhxcm1sTk5DMEdhZnQ1S0ZsMURIZzoyNjow", + "automationInstance": "https://mcxxxxx.rest.marketingcloudapis.com/legacy/v1/beta/bulk/automations/automation/instance/VEhxcm1sTk5DMEdhZnQ1S0ZsMURIZzoyNjow", + "isPlatformObject": false, + "notifications": "https://mcxxxxx.rest.marketingcloudapis.com/legacy/v1/beta/hub/notifications/cDhLQ2o2NExxVVc5N3VZeHF5WEExUToxMjow", + "automationType": "scheduled", + "lastRunStatus": "Complete" + }, + { + "id": "RkpOcE9qSVh2VUdnYTVJbWFfWW14dzoyNTow", + "key": "testExisting_automation", + "createdDate": "2022-01-12T08:41:35.773Z", + "name": "testExisting_automation", + "description": "bla bla", + "clientId": 9999999, + "status": "PausedSchedule", + "createdBy": { + "id": "NzE3MzUzNDA1OjQ6MA", + "name": "Tom Tester", + "email": "tom.tester@accenture.com" + }, + "modifiedDate": "2022-11-11T16:42:36.513Z", + "modifiedBy": { + "id": "NzE3MzUzNDA1OjQ6MA", + "name": "Tom Tester", + "email": "tom.tester@accenture.com" + }, + "isPlatformObject": false, + "notifications": "https://mcxxxxx.rest.marketingcloudapis.com/legacy/v1/beta/hub/notifications/RkpOcE9qSVh2VUdnYTVJbWFfWW14dzoxMjow", + "automationType": "scheduled" + }, + { + "id": "bHF6Q0Q3b1VXa21OdVQzZFQ0ckVSQToyNTow", + "key": "testExisting_automation_wait", + "createdDate": "2024-11-04T17:30:12.973Z", + "name": "testExisting_automation_wait", + "description": "", + "clientId": 9999999, + "status": "Ready", + "createdBy": { + "id": "NzEwNDIwNDE4OjQ6MA", + "name": "Jörn Berkefeld", + "email": "joern.berkefeld@accenture.com" + }, + "modifiedDate": "2024-11-04T17:42:13.203Z", + "modifiedBy": { + "id": "NzEwNDIwNDE4OjQ6MA", + "name": "Jörn Berkefeld", + "email": "joern.berkefeld@accenture.com" + }, + "processes": [ + { + "id": "OXJtc2M5STlma3FpVzN3NkF4Y0pWdzoyNzow", + "createdDate": "2024-11-04T17:42:13.167Z", + "name": "", + "description": "", + "sequence": 0, + "status": "Initialized", + "workerCounts": [ + { + "name": "ProgramWait", + "objectTypeId": 467, + "count": 1 + } + ] + }, + { + "id": "YllfOWc3dFVCRXU4RGQxaTRXOUZLZzoyNzow", + "createdDate": "2024-11-04T17:42:13.17Z", + "name": "", + "description": "", + "sequence": 1, + "status": "Initialized", + "workerCounts": [ + { + "name": "ProgramWait", + "objectTypeId": 467, + "count": 1 + } + ] + }, + { + "id": "d1VwZGsxN0dwa3V0dEtQSTZOeXlRUToyNzow", + "createdDate": "2024-11-04T17:42:13.177Z", + "name": "", + "description": "", + "sequence": 2, + "status": "Initialized", + "workerCounts": [ + { + "name": "ProgramWait", + "objectTypeId": 467, + "count": 1 + } + ] + }, + { + "id": "cG5GWTY1a1RiRVNnWnpvRDBhUTJmdzoyNzow", + "createdDate": "2024-11-04T17:42:13.18Z", + "name": "", + "description": "", + "sequence": 3, + "status": "Initialized", + "workerCounts": [ + { + "name": "ProgramWait", + "objectTypeId": 467, + "count": 1 + } + ] + }, + { + "id": "VjFyRUptR0hyRTJSdE1IR1RScG5RUToyNzow", + "createdDate": "2024-11-04T17:42:13.183Z", + "name": "", + "description": "", + "sequence": 4, + "status": "Initialized", + "workerCounts": [ + { + "name": "ProgramWait", + "objectTypeId": 467, + "count": 1 + } + ] + }, + { + "id": "SjFFR2s4eXR5ME93UU85anZpS0Y3QToyNzow", + "createdDate": "2024-11-04T17:42:13.187Z", + "name": "", + "description": "", + "sequence": 5, + "status": "Initialized", + "workerCounts": [ + { + "name": "ProgramWait", + "objectTypeId": 467, + "count": 1 + } + ] + }, + { + "id": "a0JPTkRiNTFmVUtRQ3dyMXlRYWdHdzoyNzow", + "createdDate": "2024-11-04T17:42:13.19Z", + "name": "", + "description": "", + "sequence": 6, + "status": "Initialized", + "workerCounts": [ + { + "name": "ProgramWait", + "objectTypeId": 467, + "count": 1 + } + ] + } + ], + "isPlatformObject": false, + "notifications": "https://mcxxxxx.rest.marketingcloudapis.com/legacy/v1/beta/hub/notifications/bHF6Q0Q3b1VXa21OdVQzZFQ0ckVSQToxMjow", + "automationType": "unspecified" + } + ] +} diff --git a/test/resources/9999999/legacy/v1/beta/bulk/automations/automation/definition/post-response-pauseSchedule.json b/test/resources/9999999/legacy/v1/beta/bulk/automations/automation/definition/post-response-pauseSchedule.json new file mode 100644 index 000000000..400082eb8 --- /dev/null +++ b/test/resources/9999999/legacy/v1/beta/bulk/automations/automation/definition/post-response-pauseSchedule.json @@ -0,0 +1 @@ +{ "id": "RkpOcE9qSVh2VUdnYTVJbWFfWW14dzoyNTow-PAUSED" } diff --git a/test/resources/9999999/legacy/v1/beta/bulk/automations/automation/definition/post-response-schedule.json b/test/resources/9999999/legacy/v1/beta/bulk/automations/automation/definition/post-response-schedule.json new file mode 100644 index 000000000..ebf236d2a --- /dev/null +++ b/test/resources/9999999/legacy/v1/beta/bulk/automations/automation/definition/post-response-schedule.json @@ -0,0 +1 @@ +{ "id": "RkpOcE9qSVh2VUdnYTVJbWFfWW14dzoyNTow" } diff --git a/test/resources/9999999/legacy/v1/beta/messaging/deliverypolicy/get-response.json b/test/resources/9999999/legacy/v1/beta/messaging/deliverypolicy/get-response.json new file mode 100644 index 000000000..39ebac4f0 --- /dev/null +++ b/test/resources/9999999/legacy/v1/beta/messaging/deliverypolicy/get-response.json @@ -0,0 +1,15 @@ +{ + "startIndex": 0, + "itemsPerPage": 50, + "totalResults": 1, + "entry": [ + { + "id": "ejQ1Y2Q5SzVFZXU0UHZRRFE4bFptQTo0ODow", + "key": "Default", + "createdDate": "2021-06-21T17:55:00Z", + "lastUpdated": "2021-06-21T17:55:00Z", + "name": "Default", + "description": "Account defaults" + } + ] +} diff --git a/test/resources/9999999/legacy/v1/beta/mobile/code/get-response.json b/test/resources/9999999/legacy/v1/beta/mobile/code/get-response.json new file mode 100644 index 000000000..5c6222f44 --- /dev/null +++ b/test/resources/9999999/legacy/v1/beta/mobile/code/get-response.json @@ -0,0 +1,32 @@ +{ + "startIndex": 0, + "itemsPerPage": 50, + "totalResults": 1, + "entry": [ + { + "id": "RXBwc0JoNk9jVTY0YWJNWFZDaGxvdzo4MTow", + "createdDate": "2017-05-05T10:33:15.953Z", + "lastUpdated": "2022-11-25T15:51:14.225Z", + "code": "4912312345678", + "countryCode": "HK", + "startDate": "2017-05-05T06:00:00Z", + "endDate": "2047-05-05T06:00:00Z", + "keywordLimit": "Unlimited", + "keywordsUsed": "0", + "codeType": "PRIVATE", + "isShortCode": false, + "keywordsUsedOther": "0", + "isGsmCharacterSetOnly": false, + "isMms": false, + "isStackIndependant": false, + "dipSwitches": 1, + "moEngineVersion": 1, + "sendableCountries": [ + { "countryCode": "HK", "vendor": "CLX", "fromNameSupported": true } + ], + "supportsConcatenation": true, + "isClientOwned": false, + "isOwner": false + } + ] +} diff --git a/test/resources/9999999/legacy/v1/beta/mobile/imports/get-response.json b/test/resources/9999999/legacy/v1/beta/mobile/imports/get-response.json new file mode 100644 index 000000000..cb63280f6 --- /dev/null +++ b/test/resources/9999999/legacy/v1/beta/mobile/imports/get-response.json @@ -0,0 +1,112 @@ +{ + "startIndex": 0, + "itemsPerPage": 50, + "totalResults": 3, + "entry": [ + { + "id": "ZTFXX0hpNDNFZXU0RzBqZk45SGIxdzo0MTow", + "name": "testExisting_importFileSMS", + "sourceFile": "_CustomObject", + "audience": { + "id": "QUFBQUFBQUFBQUFBQUFBQUFBQUFBQTo2Mzow", + "name": "testExisting_importFileSMS", + "description": "" + }, + "code": { + "id": "RXBwc0JoNk9jVTY0YWJNWFZDaGxvdzo4MTow", + "code": "4912312345678", + "codeType": "PRIVATE", + "isShortCode": false, + "isGsmCharacterSetOnly": false, + "isMms": false, + "isStackIndependant": false, + "dipSwitches": 0, + "moEngineVersion": 0, + "supportsConcatenation": false, + "isClientOwned": false, + "isOwner": false + }, + "keyword": { + "id": "cTVJaG5oSDJPVUNHcUh6Z3pQT2tVdzo4Njow", + "keyword": "TESTEXISTING_KEYWORD", + "restriction": "NONE", + "isInherited": false, + "isLinkShorteningEnabled": false, + "isSubscriberTrackingEnabled": false, + "shortenerType": "BitLy" + }, + "sourceObjectId": "NWQwdnhEU3dFZWVBekJRQzdISWl0QTo0NTow", + "sourceObjectName": "testExisting_dataExtension" + }, + { + "id": "MVZtWUtidEVFZWlpdnhRQzdKVHM4UTo0MTow", + "name": "ContactSMS_DEV", + "sourceFile": "_CustomObject", + "audience": { + "id": "QUFBQUFBQUFBQUFBQUFBQUFBQUFBQTo2Mzow", + "name": "ContactSMS_DEV", + "description": "" + }, + "code": { + "id": "RXBwc0JoNk9jVTY0YWJNWFZDaGxvdzo4MTow", + "code": "4912312345678", + "codeType": "PRIVATE", + "isShortCode": false, + "isGsmCharacterSetOnly": false, + "isMms": false, + "isStackIndependant": false, + "dipSwitches": 0, + "moEngineVersion": 0, + "supportsConcatenation": false, + "isClientOwned": false, + "isOwner": false + }, + "keyword": { + "id": "X2RqemdvVHFja1dpTzlKcERRQ25MZzo4Njow", + "keyword": "COMMUNITYCLOUD_DEV", + "restriction": "NONE", + "isInherited": false, + "isLinkShorteningEnabled": false, + "isSubscriberTrackingEnabled": false, + "shortenerType": "BitLy" + }, + "sourceObjectId": "NWQwdnhEU3dFZWVBekJRQzdISWl0QTo0NTow", + "sourceObjectName": "testExisting_dataExtension" + }, + { + "id": "NHNwUFR5YTdFZTY0WVVqZk45SGNlUTo0MTow", + "name": "ContactSMS_DEV3", + "sourceFile": "_CustomObject", + "audience": { + "id": "QUFBQUFBQUFBQUFBQUFBQUFBQUFBQTo2Mzow", + "name": "ContactSMS_DEV3", + "description": "" + }, + "code": { + "id": "RXBwc0JoNk9jVTY0YWJNWFZDaGxvdzo4MTow", + "code": "4912312345678", + "codeType": "PRIVATE", + "isShortCode": false, + "isGsmCharacterSetOnly": false, + "isMms": false, + "isStackIndependant": false, + "dipSwitches": 0, + "moEngineVersion": 0, + "supportsConcatenation": false, + "isClientOwned": false, + "isOwner": false + }, + "keyword": { + "id": "X2RqemdvVHFja1dpTzlKcERRQ25MZzo4Njow", + "keyword": "COMMUNITYCLOUD_DEV", + "restriction": "NONE", + "isInherited": false, + "isLinkShorteningEnabled": false, + "isSubscriberTrackingEnabled": false, + "shortenerType": "BitLy" + }, + "sourceObjectId": "NWQwdnhEU3dFZWVBekJRQzdISWl0QTo0NTow", + "sourceObjectName": "testExisting_dataExtension" + } + ] +} diff --git a/test/resources/9999999/legacy/v1/beta/mobile/keyword/NXV4ZFMwTEFwRVczd3RaLUF5X3p5dzo4Njow/get-response.json b/test/resources/9999999/legacy/v1/beta/mobile/keyword/NXV4ZFMwTEFwRVczd3RaLUF5X3p5dzo4Njow/get-response.json new file mode 100644 index 000000000..cde6ad4a1 --- /dev/null +++ b/test/resources/9999999/legacy/v1/beta/mobile/keyword/NXV4ZFMwTEFwRVczd3RaLUF5X3p5dzo4Njow/get-response.json @@ -0,0 +1,42 @@ +{ + "id": "NXV4ZFMwTEFwRVczd3RaLUF5X3p5dzo4Njow", + "createdDate": "2023-03-30T14:00:11.907Z", + "lastUpdated": "2023-03-30T14:00:12.295Z", + "code": { + "id": "RXBwc0JoNk9jVTY0YWJNWFZDaGxvdzo4MTow", + "createdDate": "2017-05-05T10:33:15.953Z", + "lastUpdated": "2022-11-25T15:51:14.225Z", + "code": "4912312345678", + "countryCode": "HK", + "startDate": "2017-05-05T06:00:00Z", + "endDate": "2047-05-05T06:00:00Z", + "keywordLimit": "Unlimited", + "keywordsUsed": "0", + "codeType": "PRIVATE", + "isShortCode": false, + "keywordsUsedOther": "0", + "isGsmCharacterSetOnly": false, + "isMms": false, + "isStackIndependant": false, + "dipSwitches": 1, + "moEngineVersion": 1, + "sendableCountries": [{ "countryCode": "HK", "vendor": "CLX", "fromNameSupported": true }], + "supportsConcatenation": true, + "isClientOwned": false, + "isOwner": false + }, + "keyword": "TESTNEW_KEYWORD", + "startDate": "2023-03-30T14:00:11.843Z", + "endDate": "2043-03-30T14:00:11.843Z", + "status": "Active", + "createdBy": { + "id": "NzE3NDkxNDI2OjQ6MA", + "lastUpdated": "2023-03-30T14:00:12.733Z", + "name": "API_JornBerkefeld app user" + }, + "restriction": "NONE", + "keywordType": "NORMAL", + "responseMessage": "line1\nline2", + "isInherited": false, + "dipSwitches": 0 +} diff --git a/test/resources/9999999/legacy/v1/beta/mobile/keyword/cTVJaG5oSDJPVUNHcUh6Z3pQT2tVdzo4Njow/delete-response.json b/test/resources/9999999/legacy/v1/beta/mobile/keyword/cTVJaG5oSDJPVUNHcUh6Z3pQT2tVdzo4Njow/delete-response.json new file mode 100644 index 000000000..e69de29bb diff --git a/test/resources/9999999/legacy/v1/beta/mobile/keyword/get-response.json b/test/resources/9999999/legacy/v1/beta/mobile/keyword/get-response.json new file mode 100644 index 000000000..8b716a497 --- /dev/null +++ b/test/resources/9999999/legacy/v1/beta/mobile/keyword/get-response.json @@ -0,0 +1,47 @@ +{ + "startIndex": 0, + "itemsPerPage": 50, + "totalResults": 1, + "entry": [ + { + "id": "cTVJaG5oSDJPVUNHcUh6Z3pQT2tVdzo4Njow", + "createdDate": "2018-03-27T12:37:18.12Z", + "lastUpdated": "2018-03-27T12:37:18.167Z", + "code": { + "id": "RXBwc0JoNk9jVTY0YWJNWFZDaGxvdzo4MTow", + "createdDate": "2017-05-05T10:33:15.953Z", + "lastUpdated": "2022-11-25T15:51:14.225Z", + "code": "4912312345678", + "countryCode": "HK", + "startDate": "2017-05-05T06:00:00Z", + "endDate": "2047-05-05T06:00:00Z", + "keywordLimit": "Unlimited", + "keywordsUsed": "0", + "codeType": "PRIVATE", + "isShortCode": false, + "keywordsUsedOther": "0", + "isGsmCharacterSetOnly": false, + "isMms": false, + "isStackIndependant": false, + "dipSwitches": 1, + "moEngineVersion": 1, + "sendableCountries": [ + { "countryCode": "HK", "vendor": "CLX", "fromNameSupported": true } + ], + "supportsConcatenation": true, + "isClientOwned": false, + "isOwner": false + }, + "keyword": "TESTEXISTING_KEYWORD", + "startDate": "2018-03-27T12:37:18.197Z", + "endDate": "2038-03-27T12:37:18.197Z", + "status": "Active", + "createdBy": { "id": "abcabcabc", "name": "xyz app user" }, + "restriction": "NONE", + "keywordType": "NORMAL", + "responseMessage": "line1 %%[ SET @test='bla bla' ]%% line2 %%= v(@test) =%% still line2\nline3", + "isInherited": false, + "decodedId": "9e2192ab-f611-4039-86a8-7ce0ccf3a453" + } + ] +} diff --git a/test/resources/9999999/legacy/v1/beta/mobile/keyword/post-response.json b/test/resources/9999999/legacy/v1/beta/mobile/keyword/post-response.json new file mode 100644 index 000000000..d63848705 --- /dev/null +++ b/test/resources/9999999/legacy/v1/beta/mobile/keyword/post-response.json @@ -0,0 +1,3 @@ +{ + "id": "NXV4ZFMwTEFwRVczd3RaLUF5X3p5dzo4Njow" +} diff --git a/test/resources/9999999/legacy/v1/beta/mobile/message/NTIzOjc4OjA/delete-response.json b/test/resources/9999999/legacy/v1/beta/mobile/message/NTIzOjc4OjA/delete-response.json new file mode 100644 index 000000000..e69de29bb diff --git a/test/resources/9999999/legacy/v1/beta/mobile/message/NTIzOjc4OjA/get-response.json b/test/resources/9999999/legacy/v1/beta/mobile/message/NTIzOjc4OjA/get-response.json new file mode 100644 index 000000000..5e69ccee8 --- /dev/null +++ b/test/resources/9999999/legacy/v1/beta/mobile/message/NTIzOjc4OjA/get-response.json @@ -0,0 +1,106 @@ +{ + "id": "NTIzOjc4OjA", + "lastUpdated": "2023-03-08T16:30:00Z", + "type": "ExactTarget.Mobile.Sms.Core.Entities.SmsMessageEntity", + "name": "testExisting_mobileMessage", + "text": "test message jb new", + "origin": "SMS Send", + "code": { + "id": "RXBwc0JoNk9jVTY0YWJNWFZDaGxvdzo4MTow", + "code": "4912312345678", + "codeType": "PRIVATE", + "isShortCode": false, + "isGsmCharacterSetOnly": false, + "isMms": false, + "isStackIndependant": false, + "dipSwitches": 0, + "moEngineVersion": 0, + "sendableCountries": [{ "countryCode": "HK", "vendor": "CLX", "fromNameSupported": true }], + "supportsConcatenation": true, + "isClientOwned": false, + "isOwner": false + }, + "campaigns": [ + { + "id": "MjMxOjQ2OjA", + "name": "testExisting_campaign", + "display": { + "name": "color", + "value": "f6efb6" + } + } + ], + + "mtSendDate": "2020-07-16T22:46:00Z", + "template": { + "id": "Mzo4MDow", + "name": "Outbound" + }, + "status": "Active/Scheduled", + "invalidMessage": "", + "responseMessage": "", + "publishedMessage": "Text '<keyword>' to 4912312345678.", + "nextJob": { + "id": "MjY3Ojc5OjA", + "type": "ExactTarget.Mobile.Sms.Core.Entities.SmsJobEntity", + "isTest": false, + "sendDate": "2020-07-16T22:46:00Z" + }, + "isTest": false, + "currentEditStep": 13, + "moTimezone": { + "offset": 1, + "name": "(GMT+01:00) Amsterdam, Berlin, Bern, Rome, Stockholm, Vienna *" + }, + "optinType": "NO_OPTIN", + "doubleOptinInitialMessage": "", + "doubleOptinConfirmMessage": "", + "optinMinimumAge": 0, + "optinInvalidAgeMessage": "", + "numberMessagesPerPeriod": 0, + "periodType": "NO_PERIOD", + "optinErrorMessage": "", + "triggeredSendId": "00000000-0000-0000-0000-000000000000", + "isDuplicationAllowed": true, + "triggeredSendName": "DEV_InformUserAboutProposal - 267", + "isTimeZoneBased": false, + "surveyType": "NO_SURVEY", + "surveyCorrectResponseMessage": "", + "surveyTooManyEntriesMessage": "", + "isExpireSet": false, + "expireHours": 0, + "surveyIncorrectResponseMessage": "", + "statistics": { + "outbound": { + "sent": 45, + "delivered": 33, + "undelivered": 0, + "unknown": 0 + } + }, + "statusId": 2, + "doubleOptinValidResponses": "y|yes", + "messagesPerPeriod": 0, + "minutesPerPeriod": 0, + "subscriberResponseMessage": "", + "isSubscriberResponseToAnySubscriptionForShortCode": false, + "sendMethod": "API", + "messageObjectId": "MzN3MUV5YVpmRVMtV1R1UXJUR3NzUTo2MjU6MA", + "allowSingleOptin": false, + "isSentImmediately": true, + "nextKeyword": { + "id": "cTVJaG5oSDJPVUNHcUh6Z3pQT2tVdzo4Njow", + "keyword": "TESTEXISTING_KEYWORD", + "restriction": "NONE", + "isInherited": false + }, + "isSuppressMt": false, + "smsTriggeredSendDefinitionId": "39d0e022-b6c7-ea11-a2e9-1402ec938719", + "fromName": "4912312345678", + "concatenateMessage": true, + "isFromNameCertificationAccepted": false, + "isCertified": false, + "outboundSendTypeFlag": "Audience", + "programId": "00000000-0000-0000-0000-000000000000", + "outboundSendBehaviorFlag": "AutoAddSubscribers" +} diff --git a/test/resources/9999999/legacy/v1/beta/mobile/message/NTIzOjc4OjA/post-response.json b/test/resources/9999999/legacy/v1/beta/mobile/message/NTIzOjc4OjA/post-response.json new file mode 100644 index 000000000..e69de29bb diff --git a/test/resources/9999999/legacy/v1/beta/mobile/message/NTQ3Ojc4OjA/get-response.json b/test/resources/9999999/legacy/v1/beta/mobile/message/NTQ3Ojc4OjA/get-response.json new file mode 100644 index 000000000..61417f3ae --- /dev/null +++ b/test/resources/9999999/legacy/v1/beta/mobile/message/NTQ3Ojc4OjA/get-response.json @@ -0,0 +1,127 @@ +{ + "id": "NTQ3Ojc4OjA", + "lastUpdated": "2023-03-28T13:16:00Z", + "type": "ExactTarget.Mobile.Sms.Core.Entities.SmsMessageEntity", + "name": "jb test 3", + "text": "New Task Available", + "origin": "SMS Send", + "code": { + "id": "RXBwc0JoNk9jVTY0YWJNWFZDaGxvdzo4MTow", + "code": "4912312345678", + "codeType": "PRIVATE", + "isShortCode": false, + "isGsmCharacterSetOnly": false, + "isMms": false, + "isStackIndependant": false, + "dipSwitches": 0, + "moEngineVersion": 0, + "sendableCountries": [{ "countryCode": "HK", "vendor": "CLX", "fromNameSupported": true }], + "supportsConcatenation": true, + "isClientOwned": false, + "isOwner": false + }, + "mtSendDate": "2017-07-03T14:03:00Z", + "template": { + "id": "Mzo4MDow", + "lastUpdated": "2023-03-28T13:15:58.354Z", + "name": "Outbound", + "description": "Send a SMS message to your subscribers", + "icon": "outbound.png" + }, + "status": "Active/Scheduled", + "invalidMessage": "", + "responseMessage": "", + "publishedMessage": "Text '<keyword>' to 4912312345678.", + "nextJob": { + "id": "NTQ3Ojc5OjA", + "lastUpdated": "2023-03-28T13:15:58.323Z", + "type": "ExactTarget.Mobile.Sms.Core.Entities.SmsJobEntity", + "message": { + "id": "NTQ3Ojc4OjA", + "lastUpdated": "2023-03-28T13:15:58.323Z", + "type": "ExactTarget.Mobile.Sms.Core.Entities.SmsMessageEntity", + "isTest": false, + "optinType": "NO_OPTIN", + "doubleOptinInitialMessage": "", + "doubleOptinConfirmMessage": "", + "optinMinimumAge": 0, + "optinInvalidAgeMessage": "", + "numberMessagesPerPeriod": 0, + "periodType": "NO_PERIOD", + "optinErrorMessage": "", + "triggeredSendId": "00000000-0000-0000-0000-000000000000", + "isDuplicationAllowed": false, + "triggeredSendName": "", + "isTimeZoneBased": false, + "surveyType": "NO_SURVEY", + "surveyCorrectResponseMessage": "", + "surveyTooManyEntriesMessage": "", + "isExpireSet": false, + "expireHours": 0, + "surveyIncorrectResponseMessage": "", + "statusId": 1, + "doubleOptinValidResponses": "", + "messagesPerPeriod": 0, + "minutesPerPeriod": 0, + "subscriberResponseMessage": "", + "isSubscriberResponseToAnySubscriptionForShortCode": false, + "sendMethod": "USER", + "allowSingleOptin": false, + "isSentImmediately": false, + "isSuppressMt": false, + "smsTriggeredSendDefinitionId": "00000000-0000-0000-0000-000000000000", + "fromName": "", + "concatenateMessage": false, + "isFromNameCertificationAccepted": false, + "isCertified": false, + "outboundSendTypeFlag": "Audience", + "programId": "00000000-0000-0000-0000-000000000000", + "outboundSendBehaviorFlag": "AutoAddSubscribers" + }, + "isTest": false + }, + "isTest": false, + "currentEditStep": 0, + "moTimezone": { + "offset": 1, + "name": "(GMT+01:00) Amsterdam, Berlin, Bern, Rome, Stockholm, Vienna *" + }, + "optinType": "NO_OPTIN", + "doubleOptinInitialMessage": "", + "doubleOptinConfirmMessage": "", + "optinMinimumAge": 0, + "optinInvalidAgeMessage": "", + "numberMessagesPerPeriod": 0, + "periodType": "NO_PERIOD", + "optinErrorMessage": "", + "triggeredSendId": "00000000-0000-0000-0000-000000000000", + "isDuplicationAllowed": true, + "triggeredSendName": "OneUserOneDevice_DEV - 93", + "isTimeZoneBased": false, + "surveyType": "NO_SURVEY", + "surveyCorrectResponseMessage": "", + "surveyTooManyEntriesMessage": "", + "isExpireSet": false, + "expireHours": 0, + "surveyIncorrectResponseMessage": "", + "statusId": 2, + "doubleOptinValidResponses": "y|yes", + "messagesPerPeriod": 0, + "minutesPerPeriod": 0, + "subscriberResponseMessage": "", + "isSubscriberResponseToAnySubscriptionForShortCode": false, + "sendMethod": "API", + "messageObjectId": "X1pERmhqajlVMGkzMEdtVTJPYUxVZzo2MjU6MA", + "allowSingleOptin": false, + "duplicateOptInResponseMessage": "", + "isSentImmediately": true, + "isSuppressMt": false, + "smsTriggeredSendDefinitionId": "58d59e53-f85f-e711-80cc-1402ec7222b4", + "fromName": "PMI_DEV", + "concatenateMessage": false, + "isFromNameCertificationAccepted": false, + "isCertified": false, + "outboundSendTypeFlag": "Audience", + "programId": "00000000-0000-0000-0000-000000000000", + "outboundSendBehaviorFlag": "AutoAddSubscribers" +} diff --git a/test/resources/9999999/legacy/v1/beta/mobile/message/get-response.json b/test/resources/9999999/legacy/v1/beta/mobile/message/get-response.json new file mode 100644 index 000000000..ff19924a8 --- /dev/null +++ b/test/resources/9999999/legacy/v1/beta/mobile/message/get-response.json @@ -0,0 +1,129 @@ +{ + "startIndex": 0, + "itemsPerPage": 50, + "totalResults": 1, + "entry": [ + { + "id": "NTIzOjc4OjA", + "lastUpdated": "2023-03-08T16:30:00Z", + "type": "ExactTarget.Mobile.Sms.Core.Entities.SmsMessageEntity", + "name": "testExisting_mobileMessage", + "text": "line1 %%[ SET @test='bla bla' ]%% line2 %%= v(@test) =%% still line2\nline3", + "origin": "SMS Send", + "code": { + "id": "RXBwc0JoNk9jVTY0YWJNWFZDaGxvdzo4MTow", + "code": "4912312345678", + "codeType": "PRIVATE", + "isShortCode": false, + "isGsmCharacterSetOnly": false, + "isMms": false, + "isStackIndependant": false, + "dipSwitches": 0, + "moEngineVersion": 0, + "sendableCountries": [ + { + "countryCode": "AE", + "vendor": "CLX", + "fromNameSupported": true + }, + { + "countryCode": "AL", + "vendor": "CLX", + "fromNameSupported": true + }, + { + "countryCode": "AM", + "vendor": "CLX", + "fromNameSupported": true + } + ], + "supportsConcatenation": true, + "isClientOwned": false, + "isOwner": false + }, + "campaigns": [ + { + "id": "MjMxOjQ2OjA", + "name": "testExisting_campaign", + "display": { + "name": "color", + "value": "f6efb6" + } + } + ], + + "mtSendDate": "2020-07-16T22:46:00Z", + "template": { + "id": "Mzo4MDow", + "name": "Outbound" + }, + "status": "Active/Scheduled", + "invalidMessage": "", + "responseMessage": "bla bla", + "publishedMessage": "Text '<keyword>' to 4912312345678.", + "nextJob": { + "id": "MjY3Ojc5OjA", + "type": "ExactTarget.Mobile.Sms.Core.Entities.SmsJobEntity", + "isTest": false, + "sendDate": "2020-07-16T22:46:00Z" + }, + "isTest": false, + "currentEditStep": 13, + "moTimezone": { + "offset": 1, + "name": "(GMT+01:00) Amsterdam, Berlin, Bern, Rome, Stockholm, Vienna *" + }, + "optinType": "NO_OPTIN", + "doubleOptinInitialMessage": "", + "doubleOptinConfirmMessage": "", + "optinMinimumAge": 0, + "optinInvalidAgeMessage": "", + "numberMessagesPerPeriod": 0, + "periodType": "NO_PERIOD", + "optinErrorMessage": "", + "triggeredSendId": "00000000-0000-0000-0000-000000000000", + "isDuplicationAllowed": true, + "triggeredSendName": "DEV_InformUserAboutProposal - 267", + "isTimeZoneBased": false, + "surveyType": "NO_SURVEY", + "surveyCorrectResponseMessage": "", + "surveyTooManyEntriesMessage": "", + "isExpireSet": false, + "expireHours": 0, + "surveyIncorrectResponseMessage": "", + "statistics": { + "outbound": { + "sent": 45, + "delivered": 33, + "undelivered": 0, + "unknown": 0 + } + }, + "statusId": 2, + "doubleOptinValidResponses": "y|yes", + "messagesPerPeriod": 0, + "minutesPerPeriod": 0, + "subscriberResponseMessage": "", + "isSubscriberResponseToAnySubscriptionForShortCode": false, + "sendMethod": "API", + "messageObjectId": "MzN3MUV5YVpmRVMtV1R1UXJUR3NzUTo2MjU6MA", + "allowSingleOptin": false, + "isSentImmediately": true, + "nextKeyword": { + "id": "cTVJaG5oSDJPVUNHcUh6Z3pQT2tVdzo4Njow", + "keyword": "TESTEXISTING_KEYWORD", + "restriction": "NONE", + "isInherited": false + }, + "isSuppressMt": false, + "smsTriggeredSendDefinitionId": "39d0e022-b6c7-ea11-a2e9-1402ec938719", + "fromName": "4912312345678", + "concatenateMessage": true, + "isFromNameCertificationAccepted": false, + "isCertified": false, + "outboundSendTypeFlag": "Audience", + "programId": "00000000-0000-0000-0000-000000000000", + "outboundSendBehaviorFlag": "AutoAddSubscribers" + } + ] +} diff --git a/test/resources/9999999/legacy/v1/beta/mobile/message/post-response.json b/test/resources/9999999/legacy/v1/beta/mobile/message/post-response.json new file mode 100644 index 000000000..70bd1372e --- /dev/null +++ b/test/resources/9999999/legacy/v1/beta/mobile/message/post-response.json @@ -0,0 +1,3 @@ +{ + "id": "NTQ3Ojc4OjA" +} diff --git a/test/resources/9999999/legacy/v1/beta/object/NWQwdnhEU3dFZWVBekJRQzdISWl0QTo0NTow/get-response.json b/test/resources/9999999/legacy/v1/beta/object/NWQwdnhEU3dFZWVBekJRQzdISWl0QTo0NTow/get-response.json new file mode 100644 index 000000000..2af253c3f --- /dev/null +++ b/test/resources/9999999/legacy/v1/beta/object/NWQwdnhEU3dFZWVBekJRQzdISWl0QTo0NTow/get-response.json @@ -0,0 +1,12 @@ +{ + "id": "NWQwdnhEU3dFZWVBekJRQzdISWl0QTo0NTow", + "key": "testExisting_dataExtension", + "dataExtensionName": "testExisting_dataExtension", + "description": "", + "isSendable": true, + "sendableDataExtensionField": "ContactKey", + "sendableSubscriberField": "_SubscriberKey", + "isTestable": false, + "isPublic": false, + "isPlatformObject": false +} diff --git a/test/resources/9999999/legacy/v1/beta2/data/campaign/get-response.json b/test/resources/9999999/legacy/v1/beta2/data/campaign/get-response.json new file mode 100644 index 000000000..7bd06569b --- /dev/null +++ b/test/resources/9999999/legacy/v1/beta2/data/campaign/get-response.json @@ -0,0 +1,29 @@ +{ + "startIndex": 0, + "itemsPerPage": 50, + "totalResults": 1, + "entry": [ + { + "id": "MjMxOjQ2OjA", + "type": "Campaign", + "createdDate": "2021-05-17T11:52:40Z", + "lastUpdated": "2023-03-28T14:35:34.213Z", + "createdBy": "https://mcabcdefghijkl-mnopqrs.rest.marketingcloudapis.com/legacy/v1/beta/organization/user/Nzc1MTU2ODo0OjA", + "name": "testExisting_campaign", + "description": "Test Campaign", + "externalKey": "TEST CAMPAIGN", + "campaignCode": "", + "ownerId": "https://mcabcdefghijkl-mnopqrs.rest.marketingcloudapis.com/legacy/v1/beta/organization/user/NzI5NzMwMTo0OjA", + "display": { + "name": "color", + "value": "f6efb6" + }, + "isFavorite": false, + "plannedDeploymentDate": "2021-05-16T22:00:00Z", + "campaignOwnerName": "Jörn Berkefeld", + "campaignId": 231, + "campaignStatus": "InProcess", + "campaignOwner": "MDo0OjE" + } + ] +} diff --git a/test/resources/9999999/list/retrieve-response.xml b/test/resources/9999999/list/retrieve-response.xml new file mode 100644 index 000000000..2cfa2a4c9 --- /dev/null +++ b/test/resources/9999999/list/retrieve-response.xml @@ -0,0 +1,91 @@ +<?xml version="1.0" encoding="utf-8"?> +<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:xsd="http://www.w3.org/2001/XMLSchema" + xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing" + xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" + xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"> + <soap:Header> + <wsa:Action>RetrieveResponse</wsa:Action> + <wsa:MessageID>urn:uuid:fc7c8368-c8f0-4b86-a4ac-c420bb2517cf</wsa:MessageID> + <wsa:RelatesTo>urn:uuid:eaad475d-1129-4cf5-bbe6-a1d90a80f6da</wsa:RelatesTo> + <wsa:To>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</wsa:To> + <wsse:Security> + <wsu:Timestamp wsu:Id="Timestamp-e7686d6f-36cb-4c39-b845-f4a4ae521504"> + <wsu:Created>2022-11-29T19:42:18Z</wsu:Created> + <wsu:Expires>2022-11-29T19:47:18Z</wsu:Expires> + </wsu:Timestamp> + </wsse:Security> + </soap:Header> + <soap:Body> + <RetrieveResponseMsg xmlns="http://exacttarget.com/wsdl/partnerAPI"> + <OverallStatus>OK</OverallStatus> + <RequestID>e5b8151e-8780-4543-9856-971f3023769f</RequestID> + <Results xsi:type="List"> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2017-02-16T01:59:27.29</CreatedDate> + <ModifiedDate>2017-02-16T01:59:27.29</ModifiedDate> + <ID>23</ID> + <ObjectID>95e7f560-dca9-4ad2-8bc6-850ea7506e88</ObjectID> + <CustomerKey>All Subscribers - 412</CustomerKey> + <ListName>All Subscribers</ListName> + <Category>412</Category> + <Type>Private</Type> + <Description>Contains all subscribers</Description> + <ListClassification>ExactTargetList</ListClassification> + </Results> + <Results xsi:type="List"> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2017-06-13T06:03:10.8</CreatedDate> + <ModifiedDate>2017-06-13T06:03:10.8</ModifiedDate> + <ID>109</ID> + <ObjectID>3d03a584-453e-41e0-9ed7-3ef418d5f79c</ObjectID> + <CustomerKey>Test_List - 404</CustomerKey> + <ListName>Test_List</ListName> + <Category>404</Category> + <Type>Private</Type> + <Description>Test_List</Description> + <ListClassification>ExactTargetList</ListClassification> + </Results> + <Results xsi:type="List"> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2017-06-26T04:46:40.887</CreatedDate> + <ModifiedDate>2017-06-26T04:46:40.887</ModifiedDate> + <ID>114</ID> + <ObjectID>b3e9f648-0588-4cc4-90a5-26624cdd2e1e</ObjectID> + <CustomerKey>Demo Publication List - 424</CustomerKey> + <ListName>Demo Publication List</ListName> + <Category>424</Category> + <Type>Public</Type> + <Description /> + <ListClassification>PublicationList</ListClassification> + </Results> + <Results xsi:type="List"> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2022-02-17T11:58:08.273</CreatedDate> + <ModifiedDate>2022-02-17T11:59:40.01</ModifiedDate> + <ID>1120</ID> + <ObjectID>ebe40007-8776-46d7-9c9f-dc4578ac08b7</ObjectID> + <CustomerKey>sfmcTest - 419</CustomerKey> + <ListName>sfmcTest</ListName> + <Category>419</Category> + <Type>Private</Type> + <Description /> + <ListClassification>SuppressionList</ListClassification> + </Results> + <Results xsi:type="List"> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2024-04-24T12:17:15.423</CreatedDate> + <ModifiedDate>2024-04-24T12:17:15.423</ModifiedDate> + <ID>75520</ID> + <ObjectID>97382359-b292-49aa-97a1-e53cedc18911</ObjectID> + <CustomerKey>testExisting_suppressionList - 419</CustomerKey> + <ListName>testExisting_suppressionList</ListName> + <Category>419</Category> + <Type>Public</Type> + <Description>blabla</Description> + <ListClassification>SuppressionList</ListClassification> + </Results> + </RetrieveResponseMsg> + </soap:Body> +</soap:Envelope> diff --git a/test/resources/9999999/messaging/v1/domainverification/delete/post-response.txt b/test/resources/9999999/messaging/v1/domainverification/delete/post-response.txt new file mode 100644 index 000000000..fae79c4e7 --- /dev/null +++ b/test/resources/9999999/messaging/v1/domainverification/delete/post-response.txt @@ -0,0 +1 @@ +1 records successfully updated! \ No newline at end of file diff --git a/test/resources/9999999/messaging/v1/domainverification/get-response.json b/test/resources/9999999/messaging/v1/domainverification/get-response.json new file mode 100644 index 000000000..1fa228e22 --- /dev/null +++ b/test/resources/9999999/messaging/v1/domainverification/get-response.json @@ -0,0 +1,52 @@ +{ + "page": 1, + "pageSize": 500, + "count": 5, + "items": [ + { + "enterpriseId": 1111111, + "domain": "joern.berkefeld@accenture.com", + "status": "Verified", + "domainType": "UserDomain", + "isSendable": true, + "memberId": 9999999, + "emailSendTime": "2024-05-15T08:37:08.587" + }, + { + "enterpriseId": 1111111, + "domain": "joern.berkefeld+test@accenture.com", + "status": "Verified", + "domainType": "UserDomain", + "isSendable": true, + "memberId": 9999999, + "emailSendTime": "2024-05-15T08:37:08.587" + }, + { + "enterpriseId": 1111111, + "domain": "mcdev.accenture.com", + "status": "Verified", + "domainType": "SAP", + "isSendable": true, + "memberId": 9999999, + "emailSendTime": "2023-06-19T11:11:17.32" + }, + { + "enterpriseId": 1111111, + "domain": "adhoc.accenture.com", + "status": "Verified", + "domainType": "PrivateDomain", + "isSendable": true, + "memberId": 9999999, + "emailSendTime": "2024-07-18T06:42:09.943" + }, + { + "enterpriseId": 1111111, + "domain": "mcdev-transferrable.accenture.com", + "status": "Verified", + "domainType": "RegisteredDomain", + "isSendable": true, + "memberId": 9999999, + "emailSendTime": "2023-09-20T06:05:53.873" + } + ] +} diff --git a/test/resources/9999999/messaging/v1/domainverification/post-response.txt b/test/resources/9999999/messaging/v1/domainverification/post-response.txt new file mode 100644 index 000000000..080faeed6 --- /dev/null +++ b/test/resources/9999999/messaging/v1/domainverification/post-response.txt @@ -0,0 +1 @@ +joern.berkefeld.New@accenture.com successfully added. \ No newline at end of file diff --git a/test/resources/9999999/messaging/v1/domainverification/update/post-response.txt b/test/resources/9999999/messaging/v1/domainverification/update/post-response.txt new file mode 100644 index 000000000..fae79c4e7 --- /dev/null +++ b/test/resources/9999999/messaging/v1/domainverification/update/post-response.txt @@ -0,0 +1 @@ +1 records successfully updated! \ No newline at end of file diff --git a/test/resources/9999999/messaging/v1/email/definitions/get-response.json b/test/resources/9999999/messaging/v1/email/definitions/get-response.json new file mode 100644 index 000000000..84b1a2586 --- /dev/null +++ b/test/resources/9999999/messaging/v1/email/definitions/get-response.json @@ -0,0 +1,29 @@ +{ + "requestId": "b0a6c5aa-83fa-43c2-a6a8-1e2055c85a43", + "definitions": [ + { + "name": "testExisting_temail", + "definitionKey": "testExisting_temail", + "status": "Active", + "createdDate": "2020-08-17T01:37:00", + "modifiedDate": "2020-08-17T01:37:00" + }, + { + "name": "testExisting_temail_notPublished", + "definitionKey": "testExisting_temail_notPublished", + "status": "Active", + "createdDate": "2020-08-17T01:37:00", + "modifiedDate": "2020-08-17T01:37:00" + }, + { + "name": "testNew_temail_notPublished", + "definitionKey": "testNew_temail_notPublished", + "status": "Active", + "createdDate": "2020-08-17T01:37:00", + "modifiedDate": "2020-08-17T01:37:00" + } + ], + "count": 1, + "page": 1, + "pageSize": 50 +} diff --git a/test/resources/9999999/messaging/v1/email/definitions/post-response.json b/test/resources/9999999/messaging/v1/email/definitions/post-response.json new file mode 100644 index 000000000..080bde8b5 --- /dev/null +++ b/test/resources/9999999/messaging/v1/email/definitions/post-response.json @@ -0,0 +1,19 @@ +{ + "requestId": "51f09ca1-1e5e-444a-8ddc-8e4ff80a9fa1", + "name": "testNew_temail", + "definitionKey": "testNew_temail", + "description": "created on deploy", + "classification": "Default Transactional", + "status": "Active", + "createdDate": "2022-12-06T06:08:00", + "modifiedDate": "2022-12-06T06:08:00", + "content": { "customerKey": "testExisting_asset_message" }, + "subscriptions": { + "dataExtension": "testExisting_dataExtension", + "list": "All Subscribers - 277", + "autoAddSubscriber": true, + "updateSubscriber": true + }, + "options": { "trackLinks": true }, + "journey": { "interactionKey": "testNew_RANDOM_interaction" } +} diff --git a/test/resources/9999999/messaging/v1/email/definitions/testExisting_temail/delete-response.json b/test/resources/9999999/messaging/v1/email/definitions/testExisting_temail/delete-response.json new file mode 100644 index 000000000..37a29e379 --- /dev/null +++ b/test/resources/9999999/messaging/v1/email/definitions/testExisting_temail/delete-response.json @@ -0,0 +1,6 @@ +{ + "requestId": "b6ad9f29-1ea4-486d-b826-e3dda072bbcd", + "message": "Success", + "deletedDefinitionKey": "1b24da84-7e55-47cb-a190-585a3b49da20", + "journey": {} +} diff --git a/test/resources/9999999/messaging/v1/email/definitions/testExisting_temail/get-response.json b/test/resources/9999999/messaging/v1/email/definitions/testExisting_temail/get-response.json new file mode 100644 index 000000000..f24ad6578 --- /dev/null +++ b/test/resources/9999999/messaging/v1/email/definitions/testExisting_temail/get-response.json @@ -0,0 +1,26 @@ +{ + "requestId": "ae8511d0-9bf0-42d0-af4f-bd9c1218c812", + "name": "testExisting_temail", + "definitionKey": "testExisting_temail", + "definitionId": "0a650d90-755e-ed11-b852-48df37d1df5b", + "description": "bla bla", + "classification": "Default Transactional", + "status": "Active", + "createdDate": "2020-09-10T03:29:00", + "modifiedDate": "2020-09-10T03:29:00", + "content": { + "customerKey": "testExisting_asset_message" + }, + "subscriptions": { + "list": "All Subscribers - 277", + "dataExtension": "testExisting_dataExtension", + "autoAddSubscriber": true, + "updateSubscriber": true + }, + "options": { + "trackLinks": true + }, + "journey": { + "interactionKey": "testExisting_temail" + } +} diff --git a/test/resources/9999999/messaging/v1/email/definitions/testExisting_temail/patch-response.json b/test/resources/9999999/messaging/v1/email/definitions/testExisting_temail/patch-response.json new file mode 100644 index 000000000..f961f6385 --- /dev/null +++ b/test/resources/9999999/messaging/v1/email/definitions/testExisting_temail/patch-response.json @@ -0,0 +1,26 @@ +{ + "requestId": "ae8511d0-9bf0-42d0-af4f-bd9c1218c812", + "name": "testExisting_temail", + "definitionKey": "testExisting_temail", + "definitionId": "0a650d90-755e-ed11-b852-48df37d1df5b", + "description": "updated via deploy", + "classification": "Default Transactional", + "status": "Active", + "createdDate": "2020-09-10T03:29:00", + "modifiedDate": "2020-09-10T03:29:00", + "content": { + "customerKey": "testExisting_asset_message" + }, + "subscriptions": { + "list": "All Subscribers - 277", + "dataExtension": "testExisting_dataExtension", + "autoAddSubscriber": true, + "updateSubscriber": true + }, + "options": { + "trackLinks": true + }, + "journey": { + "interactionKey": "testExisting_temail" + } +} diff --git a/test/resources/9999999/messaging/v1/email/definitions/testExisting_temail_notPublished/get-response.json b/test/resources/9999999/messaging/v1/email/definitions/testExisting_temail_notPublished/get-response.json new file mode 100644 index 000000000..f02866bdd --- /dev/null +++ b/test/resources/9999999/messaging/v1/email/definitions/testExisting_temail_notPublished/get-response.json @@ -0,0 +1,26 @@ +{ + "requestId": "37ef06bd-4790-40c2-809f-41d0a8f1b068", + "name": "testExisting_temail_notPublis - 754cc4a10da14f538ecbd5470d771eaf", + "definitionKey": "testExisting_temail_notPublished", + "definitionId": "6a2f70c5-2561-ef11-b876-f40343c95928", + "description": "testExisting_temail_notPublis - 754cc4a10da14f538ecbd5470d771eaf", + "classification": "Default Transactional", + "status": "Active", + "createdDate": "2024-08-23T02:01:00", + "modifiedDate": "2024-08-23T02:01:00", + "content": { + "customerKey": "testExisting_asset_message" + }, + "subscriptions": { + "dataExtension": "testExisting_temail_notPublished", + "list": "All Subscribers - 277", + "autoAddSubscriber": true, + "updateSubscriber": true + }, + "options": { + "trackLinks": true + }, + "journey": { + "interactionKey": "testExisting_temail_notPublished" + } +} diff --git a/test/resources/9999999/messaging/v1/email/definitions/testNew_temail_notPublished/get-response.json b/test/resources/9999999/messaging/v1/email/definitions/testNew_temail_notPublished/get-response.json new file mode 100644 index 000000000..366016332 --- /dev/null +++ b/test/resources/9999999/messaging/v1/email/definitions/testNew_temail_notPublished/get-response.json @@ -0,0 +1,26 @@ +{ + "requestId": "37ef06bd-4790-40c2-809f-41d0a8f1b068", + "name": "testNew_temail_notPublis - 754cc4a10da14f538ecbd5470d771eaf", + "definitionKey": "testNew_temail_notPublished", + "definitionId": "6a2f70c5-2561-ef11-b876-f40343c95929", + "description": "testNew_temail_notPublis - 754cc4a10da14f538ecbd5470d771eaf", + "classification": "testExisting_sendClassification", + "status": "Active", + "createdDate": "2024-08-23T02:01:00", + "modifiedDate": "2024-08-23T02:01:00", + "content": { + "customerKey": "testExisting_asset_message" + }, + "subscriptions": { + "dataExtension": "testExisting_dataExtension", + "list": "All Subscribers - 277", + "autoAddSubscriber": true, + "updateSubscriber": true + }, + "options": { + "trackLinks": true + }, + "journey": { + "interactionKey": "testNew_temail_notPublished" + } +} diff --git a/test/resources/9999999/messaging/v1/push/definitions/get-response.json b/test/resources/9999999/messaging/v1/push/definitions/get-response.json new file mode 100644 index 000000000..2ee2ff921 --- /dev/null +++ b/test/resources/9999999/messaging/v1/push/definitions/get-response.json @@ -0,0 +1,15 @@ +{ + "requestId": "4a89b42d-9e71-4ddd-9b4e-a3b00edbfdfb", + "definitions": [ + { + "name": "testExisting_tpush", + "definitionKey": "testExisting_tpush", + "status": "Active", + "createdDate": "2022-12-07T02:56:00", + "modifiedDate": "2022-12-07T02:56:00" + } + ], + "count": 1, + "page": 1, + "pageSize": 50 +} diff --git a/test/resources/9999999/messaging/v1/push/definitions/post-response.json b/test/resources/9999999/messaging/v1/push/definitions/post-response.json new file mode 100644 index 000000000..fcb7834ce --- /dev/null +++ b/test/resources/9999999/messaging/v1/push/definitions/post-response.json @@ -0,0 +1,13 @@ +{ + "requestId": "ee81df03-ab61-454d-a54a-025675cf2b41", + "name": "testNew_tpush", + "definitionKey": "testNew_tpush", + "definitionId": "2106d3f9-0c76-ed11-b849-48df37d1de8b", + "description": "created on deploy; note that applicationId can only be manually set up in Setup - Mobile Push", + "applicationId": "ffbab4c9-fbf6-4b87-9c9a-10c6ce86e81d", + "status": "Active", + "createdDate": "2022-12-07T02:56:00", + "modifiedDate": "2022-12-07T03:26:00", + "content": { "customerKey": "mobileMessage_test" }, + "options": { "sound": "temp.wmv", "badge": "1" } +} diff --git a/test/resources/9999999/messaging/v1/push/definitions/testExisting_tpush/get-response.json b/test/resources/9999999/messaging/v1/push/definitions/testExisting_tpush/get-response.json new file mode 100644 index 000000000..bb588cc0f --- /dev/null +++ b/test/resources/9999999/messaging/v1/push/definitions/testExisting_tpush/get-response.json @@ -0,0 +1,13 @@ +{ + "requestId": "64dac58f-f6d0-4bea-9489-eb058c491a87", + "name": "testExisting_tpush", + "definitionKey": "testExisting_tpush", + "definitionId": "2106d3f9-0c76-ed11-b849-48df37d1de8b", + "description": "bla bla. note that applicationId can only be manually set up in Setup - Mobile Push", + "applicationId": "ffbab4c9-fbf6-4b87-9c9a-10c6ce86e81d", + "status": "Active", + "createdDate": "2022-12-07T02:56:00", + "modifiedDate": "2022-12-07T02:56:00", + "content": { "customerKey": "mobileMessage_test" }, + "options": { "sound": "temp.wmv", "badge": "1" } +} diff --git a/test/resources/9999999/messaging/v1/push/definitions/testExisting_tpush/patch-response.json b/test/resources/9999999/messaging/v1/push/definitions/testExisting_tpush/patch-response.json new file mode 100644 index 000000000..8565f8f97 --- /dev/null +++ b/test/resources/9999999/messaging/v1/push/definitions/testExisting_tpush/patch-response.json @@ -0,0 +1,13 @@ +{ + "requestId": "6d796b32-dff3-4564-ae36-f51edb0e5ec6", + "name": "testExisting_tpush", + "definitionKey": "testExisting_tpush", + "definitionId": "2106d3f9-0c76-ed11-b849-48df37d1de8b", + "description": "updated via deploy; note that applicationId can only be manually set up in Setup - Mobile Push", + "applicationId": "ffbab4c9-fbf6-4b87-9c9a-10c6ce86e81d", + "status": "Active", + "createdDate": "2022-12-07T02:56:00", + "modifiedDate": "2022-12-07T03:26:00", + "content": { "customerKey": "mobileMessage_test" }, + "options": { "sound": "temp.wmv", "badge": "1" } +} diff --git a/test/resources/9999999/messaging/v1/sms/definitions/get-response.json b/test/resources/9999999/messaging/v1/sms/definitions/get-response.json new file mode 100644 index 000000000..8e4f28a3f --- /dev/null +++ b/test/resources/9999999/messaging/v1/sms/definitions/get-response.json @@ -0,0 +1,15 @@ +{ + "requestId": "60c26a29-e1b0-4952-a566-476a937e4a5d", + "definitions": [ + { + "name": "testExisting_tsms", + "definitionKey": "testExisting_tsms", + "status": "Active", + "createdDate": "2022-11-23T02:50:00", + "modifiedDate": "2022-11-25T08:01:00" + } + ], + "count": 1, + "page": 1, + "pageSize": 50 +} diff --git a/test/resources/9999999/messaging/v1/sms/definitions/post-response.json b/test/resources/9999999/messaging/v1/sms/definitions/post-response.json new file mode 100644 index 000000000..6067d13eb --- /dev/null +++ b/test/resources/9999999/messaging/v1/sms/definitions/post-response.json @@ -0,0 +1,19 @@ +{ + "requestId": "582bec09-6d04-4222-bbba-cea616495596", + "name": "testNew_tsms", + "definitionKey": "testNew_tsms", + "description": "created on deploy", + "status": "Active", + "createdDate": "2022-11-07T02:24:00", + "modifiedDate": "2022-11-07T02:25:00", + "content": { + "message": "\n%%[\n SET @key = 'new secret'\n]%%\n%%[\n\nSET @unsubMessages = 'UnsubscribeSMSMessages_DEV'\nSET @unsubEvents = 'UnsubscribeSMS_DEV'\n\nSET @num = concat('+',[MOBILE_NUMBER])\nSET @rs= RetrieveSalesforceObjects('Contact','Id,et4ae5__HasOptedOutOfMobile__c', 'MobilePhone', '=',@num) \nSET @count = rowCount(@rs)\nVAR @response\nSET @rx = '^\\+((?:9[679]\\d8[035789]\\d|6[789]\\d|5[90]\\d|42\\d|3[578]\\d|2[1-689]\\d)|9[0-58]|8[1246]|6[0-6]|5[1-8]|4[013-9]|3[0-469]|2[70]|7|1)'\nSET @prefix = concat('+',RegExMatch(@num, @rx, 1))\nIF @count>0 THEN\n\tFOR @i = 1 TO @count DO\n\t\tSET @sk = Field(Row(@rs,@i),'Id')\n\t\tIF Field(Row(@rs,1),'et4ae5__HasOptedOutOfMobile__c') == 'false' THEN\n\t\t\tSET @result = UpdateSingleSalesforceObject('Contact',@sk,'et4ae5__HasOptedOutOfMobile__c','true')\n\t\t\tIF @result == 0 THEN \n\t\t\t\tInsertData(@unsubEvents,'MobileNumber',@num,'Message',[MSG(0).NOUNS],'ContactId',@sk,'Status', 'Error Updating')\n\t\t\tELSE \n\t\t\t\tInsertData(@unsubEvents,'MobileNumber',@num,'Message',[MSG(0).NOUNS],'ContactId',@sk,'Status', 'Successfully Unsubscribed')\n\t\t\tENDIF\n\t\tELSE \n\t\t\tInsertData(@unsubEvents,'MobileNumber',@num,'Message',[MSG(0).NOUNS],'ContactId',@sk,'Status', 'Already Unsubscribed')\n\t\tENDIF\n\n\tNEXT @i\n\n\tSET @msg = Lookup(@unsubMessages,'Message','Prefix',@prefix,'Type', 'Found')\n\tIF Length(@msg) == 0 THEN\n\t\tSET @response ='You have unsubscribed and will no longer receive any messages.|'\n\tELSE \n\t\tSET @response = @msg\n\tENDIF\nELSE \n\tInsertData(@unsubEvents,'MobileNumber',@num,'Message',[MSG(0).NOUNS],'Status', 'Not Found') \n\tSET @msg = Lookup(@unsubMessages,'Message','Prefix',@prefix,'Type', 'NotFound')\n\tIF Length(@msg) == 0 THEN\n\t\tSET @response ='Sorry, we could not find you'\n\tELSE \n\t\tSET @response = @msg\n\tENDIF\nENDIF\n]%%\n%%=v(@response)=%%" + }, + "subscriptions": { + "shortCode": "4912312345678", + "countryCode": "", + "autoAddSubscriber": true, + "updateSubscriber": true, + "keyword": "TESTEXISTING_KEYWORD" + } +} diff --git a/test/resources/9999999/messaging/v1/sms/definitions/testExisting_tsms/get-response.json b/test/resources/9999999/messaging/v1/sms/definitions/testExisting_tsms/get-response.json new file mode 100644 index 000000000..4a154f3d0 --- /dev/null +++ b/test/resources/9999999/messaging/v1/sms/definitions/testExisting_tsms/get-response.json @@ -0,0 +1,20 @@ +{ + "requestId": "ae8511d0-9bf0-42d0-af4f-bd9c1218c812", + "name": "testExisting_tsms", + "definitionKey": "testExisting_tsms", + "definitionId": "0a650d90-755e-ed11-b852-48df37d1df5b", + "description": "bla bla", + "status": "Active", + "createdDate": "2022-11-07T02:24:00", + "modifiedDate": "2022-11-07T02:25:00", + "content": { + "message": "line1 %%[ SET @test='bla bla' ]%% line2 %%= v(@test) =%% still line2\nline3 %%[ SET @key = 'secret' ]%%\n%%[\n\nSET @unsubMessages = 'UnsubscribeSMSMessages_DEV'\nSET @unsubEvents = 'UnsubscribeSMS_DEV'\n\nSET @num = concat('+',[MOBILE_NUMBER])\nSET @rs= RetrieveSalesforceObjects('Contact','Id,et4ae5__HasOptedOutOfMobile__c', 'MobilePhone', '=',@num) \nSET @count = rowCount(@rs)\nVAR @response\nSET @rx = '^\\+((?:9[679]\\d8[035789]\\d|6[789]\\d|5[90]\\d|42\\d|3[578]\\d|2[1-689]\\d)|9[0-58]|8[1246]|6[0-6]|5[1-8]|4[013-9]|3[0-469]|2[70]|7|1)'\nSET @prefix = concat('+',RegExMatch(@num, @rx, 1))\nIF @count>0 THEN\n\tFOR @i = 1 TO @count DO\n\t\tSET @sk = Field(Row(@rs,@i),'Id')\n\t\tIF Field(Row(@rs,1),'et4ae5__HasOptedOutOfMobile__c') == 'false' THEN\n\t\t\tSET @result = UpdateSingleSalesforceObject('Contact',@sk,'et4ae5__HasOptedOutOfMobile__c','true')\n\t\t\tIF @result == 0 THEN \n\t\t\t\tInsertData(@unsubEvents,'MobileNumber',@num,'Message',[MSG(0).NOUNS],'ContactId',@sk,'Status', 'Error Updating')\n\t\t\tELSE \n\t\t\t\tInsertData(@unsubEvents,'MobileNumber',@num,'Message',[MSG(0).NOUNS],'ContactId',@sk,'Status', 'Successfully Unsubscribed')\n\t\t\tENDIF\n\t\tELSE \n\t\t\tInsertData(@unsubEvents,'MobileNumber',@num,'Message',[MSG(0).NOUNS],'ContactId',@sk,'Status', 'Already Unsubscribed')\n\t\tENDIF\n\n\tNEXT @i\n\n\tSET @msg = Lookup(@unsubMessages,'Message','Prefix',@prefix,'Type', 'Found')\n\tIF Length(@msg) == 0 THEN\n\t\tSET @response ='You have unsubscribed and will no longer receive any messages.|'\n\tELSE \n\t\tSET @response = @msg\n\tENDIF\nELSE \n\tInsertData(@unsubEvents,'MobileNumber',@num,'Message',[MSG(0).NOUNS],'Status', 'Not Found') \n\tSET @msg = Lookup(@unsubMessages,'Message','Prefix',@prefix,'Type', 'NotFound')\n\tIF Length(@msg) == 0 THEN\n\t\tSET @response ='Sorry, we could not find you'\n\tELSE \n\t\tSET @response = @msg\n\tENDIF\nENDIF\n]%%\n%%=v(@response)=%%" + }, + "subscriptions": { + "shortCode": "4912312345678", + "countryCode": "", + "autoAddSubscriber": true, + "updateSubscriber": true, + "keyword": "TESTEXISTING_KEYWORD" + } +} diff --git a/test/resources/9999999/messaging/v1/sms/definitions/testExisting_tsms/patch-response.json b/test/resources/9999999/messaging/v1/sms/definitions/testExisting_tsms/patch-response.json new file mode 100644 index 000000000..75fb1c122 --- /dev/null +++ b/test/resources/9999999/messaging/v1/sms/definitions/testExisting_tsms/patch-response.json @@ -0,0 +1,20 @@ +{ + "requestId": "ae8511d0-9bf0-42d0-af4f-bd9c1218c812", + "name": "testExisting_tsms", + "definitionKey": "testExisting_tsms", + "definitionId": "0a650d90-755e-ed11-b852-48df37d1df5b", + "description": "bla bla", + "status": "Active", + "createdDate": "2022-11-07T02:24:00", + "modifiedDate": "2022-11-07T02:25:00", + "content": { + "message": "%%[ SET @key = 'secret' ]%%\n%%[\n\nSET @unsubMessages = 'UnsubscribeSMSMessages_DEV'\nSET @unsubEvents = 'UnsubscribeSMS_DEV'\n\nSET @num = concat('+',[MOBILE_NUMBER])\nSET @rs= RetrieveSalesforceObjects('Contact','Id,et4ae5__HasOptedOutOfMobile__c', 'MobilePhone', '=',@num) \nSET @count = rowCount(@rs)\nVAR @response\nSET @rx = '^\\+((?:9[679]\\d8[035789]\\d|6[789]\\d|5[90]\\d|42\\d|3[578]\\d|2[1-689]\\d)|9[0-58]|8[1246]|6[0-6]|5[1-8]|4[013-9]|3[0-469]|2[70]|7|1)'\nSET @prefix = concat('+',RegExMatch(@num, @rx, 1))\nIF @count>0 THEN\n\tFOR @i = 1 TO @count DO\n\t\tSET @sk = Field(Row(@rs,@i),'Id')\n\t\tIF Field(Row(@rs,1),'et4ae5__HasOptedOutOfMobile__c') == 'false' THEN\n\t\t\tSET @result = UpdateSingleSalesforceObject('Contact',@sk,'et4ae5__HasOptedOutOfMobile__c','true')\n\t\t\tIF @result == 0 THEN \n\t\t\t\tInsertData(@unsubEvents,'MobileNumber',@num,'Message',[MSG(0).NOUNS],'ContactId',@sk,'Status', 'Error Updating')\n\t\t\tELSE \n\t\t\t\tInsertData(@unsubEvents,'MobileNumber',@num,'Message',[MSG(0).NOUNS],'ContactId',@sk,'Status', 'Successfully Unsubscribed')\n\t\t\tENDIF\n\t\tELSE \n\t\t\tInsertData(@unsubEvents,'MobileNumber',@num,'Message',[MSG(0).NOUNS],'ContactId',@sk,'Status', 'Already Unsubscribed')\n\t\tENDIF\n\n\tNEXT @i\n\n\tSET @msg = Lookup(@unsubMessages,'Message','Prefix',@prefix,'Type', 'Found')\n\tIF Length(@msg) == 0 THEN\n\t\tSET @response ='You have unsubscribed and will no longer receive any messages.|'\n\tELSE \n\t\tSET @response = @msg\n\tENDIF\nELSE \n\tInsertData(@unsubEvents,'MobileNumber',@num,'Message',[MSG(0).NOUNS],'Status', 'Not Found') \n\tSET @msg = Lookup(@unsubMessages,'Message','Prefix',@prefix,'Type', 'NotFound')\n\tIF Length(@msg) == 0 THEN\n\t\tSET @response ='Sorry, we could not find you'\n\tELSE \n\t\tSET @response = @msg\n\tENDIF\nENDIF\n]%%\n%%=v(@response)=%%" + }, + "subscriptions": { + "shortCode": "4912312345678", + "countryCode": "", + "autoAddSubscriber": true, + "updateSubscriber": true, + "keyword": "TESTEXISTING_KEYWORD" + } +} diff --git a/test/resources/9999999/mobileKeyword/build-expected.amp b/test/resources/9999999/mobileKeyword/build-expected.amp new file mode 100644 index 000000000..d5ac0a44d --- /dev/null +++ b/test/resources/9999999/mobileKeyword/build-expected.amp @@ -0,0 +1,6 @@ +line1 +%%[ + SET @test = 'foobar' +]%% +line2 %%= v(@test) =%% still line2 +line3 diff --git a/test/resources/9999999/mobileKeyword/build-expected.json b/test/resources/9999999/mobileKeyword/build-expected.json new file mode 100644 index 000000000..37dd1d327 --- /dev/null +++ b/test/resources/9999999/mobileKeyword/build-expected.json @@ -0,0 +1,7 @@ +{ + "c__codeKeyword": "4912312345678.TESTTEMPLATED_KEYWORD", + "r__mobileCode_key": "4912312345678", + "keywordType": "NORMAL", + "isInherited": false, + "restriction": "NONE" +} diff --git a/test/resources/9999999/mobileKeyword/get-expected.amp b/test/resources/9999999/mobileKeyword/get-expected.amp new file mode 100644 index 000000000..f525314af --- /dev/null +++ b/test/resources/9999999/mobileKeyword/get-expected.amp @@ -0,0 +1,6 @@ +line1 +%%[ + SET @test = 'bla bla' +]%% +line2 %%= v(@test) =%% still line2 +line3 diff --git a/test/resources/9999999/mobileKeyword/get-expected.json b/test/resources/9999999/mobileKeyword/get-expected.json new file mode 100644 index 000000000..77c3815a8 --- /dev/null +++ b/test/resources/9999999/mobileKeyword/get-expected.json @@ -0,0 +1,13 @@ +{ + "createdDate": "2018-03-27T12:37:18.12Z", + "lastUpdated": "2018-03-27T12:37:18.167Z", + "c__codeKeyword": "4912312345678.TESTEXISTING_KEYWORD", + "r__mobileCode_key": "4912312345678", + "startDate": "2018-03-27T12:37:18.197Z", + "endDate": "2038-03-27T12:37:18.197Z", + "status": "Active", + "createdBy": { "name": "xyz app user" }, + "restriction": "NONE", + "keywordType": "NORMAL", + "isInherited": false +} diff --git a/test/resources/9999999/mobileKeyword/post-create-expected.amp b/test/resources/9999999/mobileKeyword/post-create-expected.amp new file mode 100644 index 000000000..c0d0fb45c --- /dev/null +++ b/test/resources/9999999/mobileKeyword/post-create-expected.amp @@ -0,0 +1,2 @@ +line1 +line2 diff --git a/test/resources/9999999/mobileKeyword/post-create-expected.json b/test/resources/9999999/mobileKeyword/post-create-expected.json new file mode 100644 index 000000000..ac4587484 --- /dev/null +++ b/test/resources/9999999/mobileKeyword/post-create-expected.json @@ -0,0 +1,15 @@ +{ + "createdBy": { + "name": "API_JornBerkefeld app user" + }, + "createdDate": "2023-03-30T14:00:11.907Z", + "endDate": "2043-03-30T14:00:11.843Z", + "isInherited": false, + "c__codeKeyword": "4912312345678.TESTNEW_KEYWORD", + "r__mobileCode_key": "4912312345678", + "keywordType": "NORMAL", + "lastUpdated": "2023-03-30T14:00:12.295Z", + "restriction": "NONE", + "startDate": "2023-03-30T14:00:11.843Z", + "status": "Active" +} diff --git a/test/resources/9999999/mobileKeyword/template-expected.amp b/test/resources/9999999/mobileKeyword/template-expected.amp new file mode 100644 index 000000000..936f8c5c5 --- /dev/null +++ b/test/resources/9999999/mobileKeyword/template-expected.amp @@ -0,0 +1,6 @@ +line1 +%%[ + SET @test = '{{{description}}}' +]%% +line2 %%= v(@test) =%% still line2 +line3 diff --git a/test/resources/9999999/mobileKeyword/template-expected.json b/test/resources/9999999/mobileKeyword/template-expected.json new file mode 100644 index 000000000..26aab6317 --- /dev/null +++ b/test/resources/9999999/mobileKeyword/template-expected.json @@ -0,0 +1,7 @@ +{ + "c__codeKeyword": "4912312345678.{{{prefixUpper}}}KEYWORD", + "r__mobileCode_key": "4912312345678", + "keywordType": "NORMAL", + "isInherited": false, + "restriction": "NONE" +} diff --git a/test/resources/9999999/mobileMessage/build-expected.amp b/test/resources/9999999/mobileMessage/build-expected.amp new file mode 100644 index 000000000..d5ac0a44d --- /dev/null +++ b/test/resources/9999999/mobileMessage/build-expected.amp @@ -0,0 +1,6 @@ +line1 +%%[ + SET @test = 'foobar' +]%% +line2 %%= v(@test) =%% still line2 +line3 diff --git a/test/resources/9999999/mobileMessage/build-expected.json b/test/resources/9999999/mobileMessage/build-expected.json new file mode 100644 index 000000000..a2d036815 --- /dev/null +++ b/test/resources/9999999/mobileMessage/build-expected.json @@ -0,0 +1,57 @@ +{ + "id": "NTIzOjc4OjA", + "type": "ExactTarget.Mobile.Sms.Core.Entities.SmsMessageEntity", + "name": "testTemplated_mobileMessage", + "origin": "SMS Send", + "r__mobileCode_key": "4912312345678", + "r__campaign_key": ["testTemplated_campaign"], + "mtSendDate": "2020-07-16T22:46:00Z", + "template": { + "id": "Mzo4MDow", + "name": "Outbound" + }, + "status": "Active/Scheduled", + "invalidMessage": "", + "responseMessage": "foobar", + "publishedMessage": "Text '<keyword>' to 4912312345678.", + "isTest": false, + "moTimezone": { + "offset": 1, + "name": "(GMT+01:00) Amsterdam, Berlin, Bern, Rome, Stockholm, Vienna *" + }, + "optinType": "NO_OPTIN", + "doubleOptinInitialMessage": "", + "doubleOptinConfirmMessage": "", + "optinMinimumAge": 0, + "optinInvalidAgeMessage": "", + "numberMessagesPerPeriod": 0, + "periodType": "NO_PERIOD", + "optinErrorMessage": "", + "isDuplicationAllowed": true, + "triggeredSendName": "DEV_InformUserAboutProposal - 267", + "isTimeZoneBased": false, + "surveyType": "NO_SURVEY", + "surveyCorrectResponseMessage": "", + "surveyTooManyEntriesMessage": "", + "isExpireSet": false, + "expireHours": 0, + "surveyIncorrectResponseMessage": "", + "statusId": 2, + "doubleOptinValidResponses": "y|yes", + "messagesPerPeriod": 0, + "minutesPerPeriod": 0, + "subscriberResponseMessage": "", + "isSubscriberResponseToAnySubscriptionForShortCode": false, + "sendMethod": "API", + "messageObjectId": "MzN3MUV5YVpmRVMtV1R1UXJUR3NzUTo2MjU6MA", + "allowSingleOptin": false, + "isSentImmediately": true, + "isSuppressMt": false, + "smsTriggeredSendDefinitionId": "39d0e022-b6c7-ea11-a2e9-1402ec938719", + "fromName": "4912312345678", + "concatenateMessage": true, + "isFromNameCertificationAccepted": false, + "isCertified": false, + "outboundSendTypeFlag": "Audience", + "outboundSendBehaviorFlag": "AutoAddSubscribers" +} diff --git a/test/resources/9999999/mobileMessage/get-expected.amp b/test/resources/9999999/mobileMessage/get-expected.amp new file mode 100644 index 000000000..f525314af --- /dev/null +++ b/test/resources/9999999/mobileMessage/get-expected.amp @@ -0,0 +1,6 @@ +line1 +%%[ + SET @test = 'bla bla' +]%% +line2 %%= v(@test) =%% still line2 +line3 diff --git a/test/resources/9999999/mobileMessage/get-expected.json b/test/resources/9999999/mobileMessage/get-expected.json new file mode 100644 index 000000000..54e5b7398 --- /dev/null +++ b/test/resources/9999999/mobileMessage/get-expected.json @@ -0,0 +1,58 @@ +{ + "id": "NTIzOjc4OjA", + "lastUpdated": "2023-03-08T16:30:00Z", + "type": "ExactTarget.Mobile.Sms.Core.Entities.SmsMessageEntity", + "name": "testExisting_mobileMessage", + "origin": "SMS Send", + "r__mobileCode_key": "4912312345678", + "r__campaign_key": ["testExisting_campaign"], + "mtSendDate": "2020-07-16T22:46:00Z", + "template": { + "id": "Mzo4MDow", + "name": "Outbound" + }, + "status": "Active/Scheduled", + "invalidMessage": "", + "responseMessage": "bla bla", + "publishedMessage": "Text '<keyword>' to 4912312345678.", + "isTest": false, + "moTimezone": { + "offset": 1, + "name": "(GMT+01:00) Amsterdam, Berlin, Bern, Rome, Stockholm, Vienna *" + }, + "optinType": "NO_OPTIN", + "doubleOptinInitialMessage": "", + "doubleOptinConfirmMessage": "", + "optinMinimumAge": 0, + "optinInvalidAgeMessage": "", + "numberMessagesPerPeriod": 0, + "periodType": "NO_PERIOD", + "optinErrorMessage": "", + "isDuplicationAllowed": true, + "triggeredSendName": "DEV_InformUserAboutProposal - 267", + "isTimeZoneBased": false, + "surveyType": "NO_SURVEY", + "surveyCorrectResponseMessage": "", + "surveyTooManyEntriesMessage": "", + "isExpireSet": false, + "expireHours": 0, + "surveyIncorrectResponseMessage": "", + "statusId": 2, + "doubleOptinValidResponses": "y|yes", + "messagesPerPeriod": 0, + "minutesPerPeriod": 0, + "subscriberResponseMessage": "", + "isSubscriberResponseToAnySubscriptionForShortCode": false, + "sendMethod": "API", + "messageObjectId": "MzN3MUV5YVpmRVMtV1R1UXJUR3NzUTo2MjU6MA", + "allowSingleOptin": false, + "isSentImmediately": true, + "isSuppressMt": false, + "smsTriggeredSendDefinitionId": "39d0e022-b6c7-ea11-a2e9-1402ec938719", + "fromName": "4912312345678", + "concatenateMessage": true, + "isFromNameCertificationAccepted": false, + "isCertified": false, + "outboundSendTypeFlag": "Audience", + "outboundSendBehaviorFlag": "AutoAddSubscribers" +} diff --git a/test/resources/9999999/mobileMessage/post-create-expected.amp b/test/resources/9999999/mobileMessage/post-create-expected.amp new file mode 100644 index 000000000..3e5727b71 --- /dev/null +++ b/test/resources/9999999/mobileMessage/post-create-expected.amp @@ -0,0 +1 @@ +New Task Available diff --git a/test/resources/9999999/mobileMessage/post-create-expected.json b/test/resources/9999999/mobileMessage/post-create-expected.json new file mode 100644 index 000000000..b87f2b8fa --- /dev/null +++ b/test/resources/9999999/mobileMessage/post-create-expected.json @@ -0,0 +1,61 @@ +{ + "id": "NTQ3Ojc4OjA", + "lastUpdated": "2023-03-28T13:16:00Z", + "type": "ExactTarget.Mobile.Sms.Core.Entities.SmsMessageEntity", + "name": "jb test 3", + "origin": "SMS Send", + "r__mobileCode_key": "4912312345678", + "mtSendDate": "2017-07-03T14:03:00Z", + "template": { + "id": "Mzo4MDow", + "lastUpdated": "2023-03-28T13:15:58.354Z", + "name": "Outbound", + "description": "Send a SMS message to your subscribers", + "icon": "outbound.png" + }, + "status": "Active/Scheduled", + "invalidMessage": "", + "responseMessage": "", + "publishedMessage": "Text '<keyword>' to 4912312345678.", + "isTest": false, + "moTimezone": { + "offset": 1, + "name": "(GMT+01:00) Amsterdam, Berlin, Bern, Rome, Stockholm, Vienna *" + }, + "optinType": "NO_OPTIN", + "doubleOptinInitialMessage": "", + "doubleOptinConfirmMessage": "", + "optinMinimumAge": 0, + "optinInvalidAgeMessage": "", + "numberMessagesPerPeriod": 0, + "periodType": "NO_PERIOD", + "optinErrorMessage": "", + "isDuplicationAllowed": true, + "triggeredSendName": "OneUserOneDevice_DEV - 93", + "isTimeZoneBased": false, + "surveyType": "NO_SURVEY", + "surveyCorrectResponseMessage": "", + "surveyTooManyEntriesMessage": "", + "isExpireSet": false, + "expireHours": 0, + "surveyIncorrectResponseMessage": "", + "statusId": 2, + "doubleOptinValidResponses": "y|yes", + "messagesPerPeriod": 0, + "minutesPerPeriod": 0, + "subscriberResponseMessage": "", + "isSubscriberResponseToAnySubscriptionForShortCode": false, + "sendMethod": "API", + "messageObjectId": "X1pERmhqajlVMGkzMEdtVTJPYUxVZzo2MjU6MA", + "allowSingleOptin": false, + "duplicateOptInResponseMessage": "", + "isSentImmediately": true, + "isSuppressMt": false, + "smsTriggeredSendDefinitionId": "58d59e53-f85f-e711-80cc-1402ec7222b4", + "fromName": "PMI_DEV", + "concatenateMessage": false, + "isFromNameCertificationAccepted": false, + "isCertified": false, + "outboundSendTypeFlag": "Audience", + "outboundSendBehaviorFlag": "AutoAddSubscribers" +} diff --git a/test/resources/9999999/mobileMessage/post-update-expected.amp b/test/resources/9999999/mobileMessage/post-update-expected.amp new file mode 100644 index 000000000..d389984de --- /dev/null +++ b/test/resources/9999999/mobileMessage/post-update-expected.amp @@ -0,0 +1 @@ +test message jb new diff --git a/test/resources/9999999/mobileMessage/post-update-expected.json b/test/resources/9999999/mobileMessage/post-update-expected.json new file mode 100644 index 000000000..ab279adad --- /dev/null +++ b/test/resources/9999999/mobileMessage/post-update-expected.json @@ -0,0 +1,58 @@ +{ + "id": "NTIzOjc4OjA", + "lastUpdated": "2023-03-08T16:30:00Z", + "type": "ExactTarget.Mobile.Sms.Core.Entities.SmsMessageEntity", + "name": "testExisting_mobileMessage", + "origin": "SMS Send", + "r__mobileCode_key": "4912312345678", + "r__campaign_key": ["testExisting_campaign"], + "mtSendDate": "2020-07-16T22:46:00Z", + "template": { + "id": "Mzo4MDow", + "name": "Outbound" + }, + "status": "Active/Scheduled", + "invalidMessage": "", + "responseMessage": "", + "publishedMessage": "Text '<keyword>' to 4912312345678.", + "isTest": false, + "moTimezone": { + "offset": 1, + "name": "(GMT+01:00) Amsterdam, Berlin, Bern, Rome, Stockholm, Vienna *" + }, + "optinType": "NO_OPTIN", + "doubleOptinInitialMessage": "", + "doubleOptinConfirmMessage": "", + "optinMinimumAge": 0, + "optinInvalidAgeMessage": "", + "numberMessagesPerPeriod": 0, + "periodType": "NO_PERIOD", + "optinErrorMessage": "", + "isDuplicationAllowed": true, + "triggeredSendName": "DEV_InformUserAboutProposal - 267", + "isTimeZoneBased": false, + "surveyType": "NO_SURVEY", + "surveyCorrectResponseMessage": "", + "surveyTooManyEntriesMessage": "", + "isExpireSet": false, + "expireHours": 0, + "surveyIncorrectResponseMessage": "", + "statusId": 2, + "doubleOptinValidResponses": "y|yes", + "messagesPerPeriod": 0, + "minutesPerPeriod": 0, + "subscriberResponseMessage": "", + "isSubscriberResponseToAnySubscriptionForShortCode": false, + "sendMethod": "API", + "messageObjectId": "MzN3MUV5YVpmRVMtV1R1UXJUR3NzUTo2MjU6MA", + "allowSingleOptin": false, + "isSentImmediately": true, + "isSuppressMt": false, + "smsTriggeredSendDefinitionId": "39d0e022-b6c7-ea11-a2e9-1402ec938719", + "fromName": "4912312345678", + "concatenateMessage": true, + "isFromNameCertificationAccepted": false, + "isCertified": false, + "outboundSendTypeFlag": "Audience", + "outboundSendBehaviorFlag": "AutoAddSubscribers" +} diff --git a/test/resources/9999999/mobileMessage/template-expected.amp b/test/resources/9999999/mobileMessage/template-expected.amp new file mode 100644 index 000000000..936f8c5c5 --- /dev/null +++ b/test/resources/9999999/mobileMessage/template-expected.amp @@ -0,0 +1,6 @@ +line1 +%%[ + SET @test = '{{{description}}}' +]%% +line2 %%= v(@test) =%% still line2 +line3 diff --git a/test/resources/9999999/mobileMessage/template-expected.json b/test/resources/9999999/mobileMessage/template-expected.json new file mode 100644 index 000000000..395ac4db5 --- /dev/null +++ b/test/resources/9999999/mobileMessage/template-expected.json @@ -0,0 +1,57 @@ +{ + "id": "NTIzOjc4OjA", + "type": "ExactTarget.Mobile.Sms.Core.Entities.SmsMessageEntity", + "name": "{{{prefix}}}mobileMessage", + "origin": "SMS Send", + "r__mobileCode_key": "4912312345678", + "r__campaign_key": ["{{{prefix}}}campaign"], + "mtSendDate": "2020-07-16T22:46:00Z", + "template": { + "id": "Mzo4MDow", + "name": "Outbound" + }, + "status": "Active/Scheduled", + "invalidMessage": "", + "responseMessage": "{{{description}}}", + "publishedMessage": "Text '<keyword>' to 4912312345678.", + "isTest": false, + "moTimezone": { + "offset": 1, + "name": "(GMT+01:00) Amsterdam, Berlin, Bern, Rome, Stockholm, Vienna *" + }, + "optinType": "NO_OPTIN", + "doubleOptinInitialMessage": "", + "doubleOptinConfirmMessage": "", + "optinMinimumAge": 0, + "optinInvalidAgeMessage": "", + "numberMessagesPerPeriod": 0, + "periodType": "NO_PERIOD", + "optinErrorMessage": "", + "isDuplicationAllowed": true, + "triggeredSendName": "DEV_InformUserAboutProposal - 267", + "isTimeZoneBased": false, + "surveyType": "NO_SURVEY", + "surveyCorrectResponseMessage": "", + "surveyTooManyEntriesMessage": "", + "isExpireSet": false, + "expireHours": 0, + "surveyIncorrectResponseMessage": "", + "statusId": 2, + "doubleOptinValidResponses": "y|yes", + "messagesPerPeriod": 0, + "minutesPerPeriod": 0, + "subscriberResponseMessage": "", + "isSubscriberResponseToAnySubscriptionForShortCode": false, + "sendMethod": "API", + "messageObjectId": "MzN3MUV5YVpmRVMtV1R1UXJUR3NzUTo2MjU6MA", + "allowSingleOptin": false, + "isSentImmediately": true, + "isSuppressMt": false, + "smsTriggeredSendDefinitionId": "39d0e022-b6c7-ea11-a2e9-1402ec938719", + "fromName": "4912312345678", + "concatenateMessage": true, + "isFromNameCertificationAccepted": false, + "isCertified": false, + "outboundSendTypeFlag": "Audience", + "outboundSendBehaviorFlag": "AutoAddSubscribers" +} diff --git a/test/resources/9999999/program/retrieve-CustomerKey=testExisting_automation-response.xml b/test/resources/9999999/program/retrieve-CustomerKey=testExisting_automation-response.xml new file mode 100644 index 000000000..16ba379bd --- /dev/null +++ b/test/resources/9999999/program/retrieve-CustomerKey=testExisting_automation-response.xml @@ -0,0 +1,30 @@ +<?xml version="1.0" encoding="utf-8"?> +<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:xsd="http://www.w3.org/2001/XMLSchema" + xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing" + xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" + xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"> + <soap:Header> + <wsa:Action>RetrieveResponse</wsa:Action> + <wsa:MessageID>urn:uuid:60a72d4a-847e-4d9b-a4eb-a42951078298</wsa:MessageID> + <wsa:RelatesTo>urn:uuid:0b59ed53-72ec-4481-ae06-4ee78912aef2</wsa:RelatesTo> + <wsa:To>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</wsa:To> + <wsse:Security> + <wsu:Timestamp wsu:Id="Timestamp-f95f3fd3-c763-4e2c-929f-33611e9d2eba"> + <wsu:Created>2023-06-01T12:04:20Z</wsu:Created> + <wsu:Expires>2023-06-01T12:09:20Z</wsu:Expires> + </wsu:Timestamp> + </wsse:Security> + </soap:Header> + <soap:Body> + <RetrieveResponseMsg xmlns="http://exacttarget.com/wsdl/partnerAPI"> + <OverallStatus>OK</OverallStatus> + <RequestID>3b1c8cee-b270-49cb-b77b-e7b33934d1b6</RequestID> + <Results xsi:type="Program"> + <PartnerKey xsi:nil="true" /> + <ObjectID>08afb0e2-b00a-4c88-ad2e-1f7f8788c560</ObjectID> + </Results> + </RetrieveResponseMsg> + </soap:Body> +</soap:Envelope> \ No newline at end of file diff --git a/test/resources/9999999/program/retrieve-CustomerKey=testExisting_automation_fixKey_pause-response.xml b/test/resources/9999999/program/retrieve-CustomerKey=testExisting_automation_fixKey_pause-response.xml new file mode 100644 index 000000000..b5b72f81b --- /dev/null +++ b/test/resources/9999999/program/retrieve-CustomerKey=testExisting_automation_fixKey_pause-response.xml @@ -0,0 +1,32 @@ +<?xml version="1.0" encoding="utf-8"?> +<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:xsd="http://www.w3.org/2001/XMLSchema" + xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing" + xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" + xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"> + <soap:Header> + <wsa:Action>RetrieveResponse</wsa:Action> + <wsa:MessageID>urn:uuid:60a72d4a-847e-4d9b-a4eb-a42951078298</wsa:MessageID> + <wsa:RelatesTo>urn:uuid:0b59ed53-72ec-4481-ae06-4ee78912aef2</wsa:RelatesTo> + <wsa:To>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</wsa:To> + <wsse:Security> + <wsu:Timestamp wsu:Id="Timestamp-f95f3fd3-c763-4e2c-929f-33611e9d2eba"> + <wsu:Created>2023-06-01T12:04:20Z</wsu:Created> + <wsu:Expires>2023-06-01T12:09:20Z</wsu:Expires> + </wsu:Timestamp> + </wsse:Security> + </soap:Header> + <soap:Body> + <RetrieveResponseMsg xmlns="http://exacttarget.com/wsdl/partnerAPI"> + <OverallStatus>OK</OverallStatus> + <RequestID>3b1c8cee-b270-49cb-b77b-e7b33934d1b6</RequestID> + <Results xsi:type="Program"> + <PartnerKey xsi:nil="true" /> + <ObjectID>08afb0e2-b00a-4c88-fixKey_pause</ObjectID> + <Name>testExisting_automation_fixedKey_paused</Name> <!--only retrieved for cache--> + <CustomerKey>testExisting_automation_fixKey_pause</CustomerKey> <!--only retrieved for cache--> + </Results> + </RetrieveResponseMsg> + </soap:Body> +</soap:Envelope> diff --git a/test/resources/9999999/program/retrieve-CustomerKey=testExisting_automation_fixKey_schedule-response.xml b/test/resources/9999999/program/retrieve-CustomerKey=testExisting_automation_fixKey_schedule-response.xml new file mode 100644 index 000000000..86773f622 --- /dev/null +++ b/test/resources/9999999/program/retrieve-CustomerKey=testExisting_automation_fixKey_schedule-response.xml @@ -0,0 +1,32 @@ +<?xml version="1.0" encoding="utf-8"?> +<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:xsd="http://www.w3.org/2001/XMLSchema" + xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing" + xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" + xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"> + <soap:Header> + <wsa:Action>RetrieveResponse</wsa:Action> + <wsa:MessageID>urn:uuid:60a72d4a-847e-4d9b-a4eb-a42951078298</wsa:MessageID> + <wsa:RelatesTo>urn:uuid:0b59ed53-72ec-4481-ae06-4ee78912aef2</wsa:RelatesTo> + <wsa:To>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</wsa:To> + <wsse:Security> + <wsu:Timestamp wsu:Id="Timestamp-f95f3fd3-c763-4e2c-929f-33611e9d2eba"> + <wsu:Created>2023-06-01T12:04:20Z</wsu:Created> + <wsu:Expires>2023-06-01T12:09:20Z</wsu:Expires> + </wsu:Timestamp> + </wsse:Security> + </soap:Header> + <soap:Body> + <RetrieveResponseMsg xmlns="http://exacttarget.com/wsdl/partnerAPI"> + <OverallStatus>OK</OverallStatus> + <RequestID>3b1c8cee-b270-49cb-b77b-e7b33934d1b6</RequestID> + <Results xsi:type="Program"> + <PartnerKey xsi:nil="true" /> + <ObjectID>08afb0e2-b00a-4c88-fixKey_schedule</ObjectID> + <Name>testExisting_automation_fixedKey_scheduled</Name> <!--only retrieved for cache--> + <CustomerKey>testExisting_automation_fixKey_schedule</CustomerKey> <!--only retrieved for cache--> + </Results> + </RetrieveResponseMsg> + </soap:Body> +</soap:Envelope> diff --git a/test/resources/9999999/program/retrieve-CustomerKey=testExisting_automation_fixedKey_paused-response.xml b/test/resources/9999999/program/retrieve-CustomerKey=testExisting_automation_fixedKey_paused-response.xml new file mode 100644 index 000000000..ce6885409 --- /dev/null +++ b/test/resources/9999999/program/retrieve-CustomerKey=testExisting_automation_fixedKey_paused-response.xml @@ -0,0 +1,32 @@ +<?xml version="1.0" encoding="utf-8"?> +<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:xsd="http://www.w3.org/2001/XMLSchema" + xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing" + xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" + xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"> + <soap:Header> + <wsa:Action>RetrieveResponse</wsa:Action> + <wsa:MessageID>urn:uuid:60a72d4a-847e-4d9b-a4eb-a42951078298</wsa:MessageID> + <wsa:RelatesTo>urn:uuid:0b59ed53-72ec-4481-ae06-4ee78912aef2</wsa:RelatesTo> + <wsa:To>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</wsa:To> + <wsse:Security> + <wsu:Timestamp wsu:Id="Timestamp-f95f3fd3-c763-4e2c-929f-33611e9d2eba"> + <wsu:Created>2023-06-01T12:04:20Z</wsu:Created> + <wsu:Expires>2023-06-01T12:09:20Z</wsu:Expires> + </wsu:Timestamp> + </wsse:Security> + </soap:Header> + <soap:Body> + <RetrieveResponseMsg xmlns="http://exacttarget.com/wsdl/partnerAPI"> + <OverallStatus>OK</OverallStatus> + <RequestID>3b1c8cee-b270-49cb-b77b-e7b33934d1b6</RequestID> + <Results xsi:type="Program"> + <PartnerKey xsi:nil="true" /> + <ObjectID>08afb0e2-b00a-4c88-fixKey_pause</ObjectID> + <Name>testExisting_automation_fixedKey_paused</Name> <!--only retrieved for cache--> + <CustomerKey>testExisting_automation_fixedKey_paused</CustomerKey> <!--only retrieved for cache--> + </Results> + </RetrieveResponseMsg> + </soap:Body> +</soap:Envelope> diff --git a/test/resources/9999999/program/retrieve-CustomerKey=testExisting_automation_fixedKey_scheduled-response.xml b/test/resources/9999999/program/retrieve-CustomerKey=testExisting_automation_fixedKey_scheduled-response.xml new file mode 100644 index 000000000..a1517f9db --- /dev/null +++ b/test/resources/9999999/program/retrieve-CustomerKey=testExisting_automation_fixedKey_scheduled-response.xml @@ -0,0 +1,32 @@ +<?xml version="1.0" encoding="utf-8"?> +<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:xsd="http://www.w3.org/2001/XMLSchema" + xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing" + xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" + xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"> + <soap:Header> + <wsa:Action>RetrieveResponse</wsa:Action> + <wsa:MessageID>urn:uuid:60a72d4a-847e-4d9b-a4eb-a42951078298</wsa:MessageID> + <wsa:RelatesTo>urn:uuid:0b59ed53-72ec-4481-ae06-4ee78912aef2</wsa:RelatesTo> + <wsa:To>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</wsa:To> + <wsse:Security> + <wsu:Timestamp wsu:Id="Timestamp-f95f3fd3-c763-4e2c-929f-33611e9d2eba"> + <wsu:Created>2023-06-01T12:04:20Z</wsu:Created> + <wsu:Expires>2023-06-01T12:09:20Z</wsu:Expires> + </wsu:Timestamp> + </wsse:Security> + </soap:Header> + <soap:Body> + <RetrieveResponseMsg xmlns="http://exacttarget.com/wsdl/partnerAPI"> + <OverallStatus>OK</OverallStatus> + <RequestID>3b1c8cee-b270-49cb-b77b-e7b33934d1b6</RequestID> + <Results xsi:type="Program"> + <PartnerKey xsi:nil="true" /> + <ObjectID>08afb0e2-b00a-4c88-fixKey_schedule</ObjectID> + <Name>testExisting_automation_fixedKey_scheduled</Name> <!--only retrieved for cache--> + <CustomerKey>testExisting_automation_fixedKey_scheduled</CustomerKey> <!--only retrieved for cache--> + </Results> + </RetrieveResponseMsg> + </soap:Body> +</soap:Envelope> diff --git a/test/resources/9999999/program/retrieve-CustomerKey=testExisting_automation_pause-response.xml b/test/resources/9999999/program/retrieve-CustomerKey=testExisting_automation_pause-response.xml new file mode 100644 index 000000000..6d33a7bfc --- /dev/null +++ b/test/resources/9999999/program/retrieve-CustomerKey=testExisting_automation_pause-response.xml @@ -0,0 +1,30 @@ +<?xml version="1.0" encoding="utf-8"?> +<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:xsd="http://www.w3.org/2001/XMLSchema" + xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing" + xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" + xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"> + <soap:Header> + <wsa:Action>RetrieveResponse</wsa:Action> + <wsa:MessageID>urn:uuid:60a72d4a-847e-4d9b-a4eb-a42951078298</wsa:MessageID> + <wsa:RelatesTo>urn:uuid:0b59ed53-72ec-4481-ae06-4ee78912aef2</wsa:RelatesTo> + <wsa:To>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</wsa:To> + <wsse:Security> + <wsu:Timestamp wsu:Id="Timestamp-f95f3fd3-c763-4e2c-929f-33611e9d2eba"> + <wsu:Created>2023-06-01T12:04:20Z</wsu:Created> + <wsu:Expires>2023-06-01T12:09:20Z</wsu:Expires> + </wsu:Timestamp> + </wsse:Security> + </soap:Header> + <soap:Body> + <RetrieveResponseMsg xmlns="http://exacttarget.com/wsdl/partnerAPI"> + <OverallStatus>OK</OverallStatus> + <RequestID>3b1c8cee-b270-49cb-b77b-e7b33934d1b6</RequestID> + <Results xsi:type="Program"> + <PartnerKey xsi:nil="true" /> + <ObjectID>08afb0e2-b00a-4c88-ad2e-pause</ObjectID> + </Results> + </RetrieveResponseMsg> + </soap:Body> +</soap:Envelope> diff --git a/test/resources/9999999/program/retrieve-CustomerKey=testNew_automation-response.xml b/test/resources/9999999/program/retrieve-CustomerKey=testNew_automation-response.xml new file mode 100644 index 000000000..db925e143 --- /dev/null +++ b/test/resources/9999999/program/retrieve-CustomerKey=testNew_automation-response.xml @@ -0,0 +1,30 @@ +<?xml version="1.0" encoding="utf-8"?> +<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:xsd="http://www.w3.org/2001/XMLSchema" + xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing" + xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" + xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"> + <soap:Header> + <wsa:Action>RetrieveResponse</wsa:Action> + <wsa:MessageID>urn:uuid:60a72d4a-847e-4d9b-a4eb-a42951078298</wsa:MessageID> + <wsa:RelatesTo>urn:uuid:0b59ed53-72ec-4481-ae06-4ee78912aef2</wsa:RelatesTo> + <wsa:To>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</wsa:To> + <wsse:Security> + <wsu:Timestamp wsu:Id="Timestamp-f95f3fd3-c763-4e2c-929f-33611e9d2eba"> + <wsu:Created>2023-06-01T12:04:20Z</wsu:Created> + <wsu:Expires>2023-06-01T12:09:20Z</wsu:Expires> + </wsu:Timestamp> + </wsse:Security> + </soap:Header> + <soap:Body> + <RetrieveResponseMsg xmlns="http://exacttarget.com/wsdl/partnerAPI"> + <OverallStatus>OK</OverallStatus> + <RequestID>3b1c8cee-b270-49cb-b77b-e7b33934d1b6</RequestID> + <Results xsi:type="Program"> + <PartnerKey xsi:nil="true" /> + <ObjectID>a8afb0e2-b00a-4c88-ad2e-1f7f8788c560</ObjectID> + </Results> + </RetrieveResponseMsg> + </soap:Body> +</soap:Envelope> \ No newline at end of file diff --git a/test/resources/9999999/program/retrieve-Name=testExisting_automation-response.xml b/test/resources/9999999/program/retrieve-Name=testExisting_automation-response.xml new file mode 100644 index 000000000..6d1b57ef2 --- /dev/null +++ b/test/resources/9999999/program/retrieve-Name=testExisting_automation-response.xml @@ -0,0 +1,31 @@ +<?xml version="1.0" encoding="utf-8"?> +<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:xsd="http://www.w3.org/2001/XMLSchema" + xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing" + xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" + xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"> + <soap:Header> + <wsa:Action>RetrieveResponse</wsa:Action> + <wsa:MessageID>urn:uuid:60a72d4a-847e-4d9b-a4eb-a42951078298</wsa:MessageID> + <wsa:RelatesTo>urn:uuid:0b59ed53-72ec-4481-ae06-4ee78912aef2</wsa:RelatesTo> + <wsa:To>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</wsa:To> + <wsse:Security> + <wsu:Timestamp wsu:Id="Timestamp-f95f3fd3-c763-4e2c-929f-33611e9d2eba"> + <wsu:Created>2023-06-01T12:04:20Z</wsu:Created> + <wsu:Expires>2023-06-01T12:09:20Z</wsu:Expires> + </wsu:Timestamp> + </wsse:Security> + </soap:Header> + <soap:Body> + <RetrieveResponseMsg xmlns="http://exacttarget.com/wsdl/partnerAPI"> + <OverallStatus>OK</OverallStatus> + <RequestID>3b1c8cee-b270-49cb-b77b-e7b33934d1b6</RequestID> + <Results xsi:type="Program"> + <PartnerKey xsi:nil="true" /> + <ObjectID>08afb0e2-b00a-4c88-ad2e-1f7f8788c560</ObjectID> + <Name>testExisting_automation</Name> + </Results> + </RetrieveResponseMsg> + </soap:Body> +</soap:Envelope> \ No newline at end of file diff --git a/test/resources/9999999/program/retrieve-response.xml b/test/resources/9999999/program/retrieve-response.xml new file mode 100644 index 000000000..039b6316d --- /dev/null +++ b/test/resources/9999999/program/retrieve-response.xml @@ -0,0 +1,62 @@ +<?xml version="1.0" encoding="utf-8"?> +<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:xsd="http://www.w3.org/2001/XMLSchema" + xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing" + xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" + xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"> + <soap:Header> + <wsa:Action>RetrieveResponse</wsa:Action> + <wsa:MessageID>urn:uuid:60a72d4a-847e-4d9b-a4eb-a42951078298</wsa:MessageID> + <wsa:RelatesTo>urn:uuid:0b59ed53-72ec-4481-ae06-4ee78912aef2</wsa:RelatesTo> + <wsa:To>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</wsa:To> + <wsse:Security> + <wsu:Timestamp wsu:Id="Timestamp-f95f3fd3-c763-4e2c-929f-33611e9d2eba"> + <wsu:Created>2023-06-01T12:04:20Z</wsu:Created> + <wsu:Expires>2023-06-01T12:09:20Z</wsu:Expires> + </wsu:Timestamp> + </wsse:Security> + </soap:Header> + <soap:Body> + <RetrieveResponseMsg xmlns="http://exacttarget.com/wsdl/partnerAPI"> + <OverallStatus>OK</OverallStatus> + <RequestID>3b1c8cee-b270-49cb-b77b-e7b33934d1b6</RequestID> + <Results xsi:type="Program"> + <PartnerKey xsi:nil="true" /> + <ObjectID>08afb0e2-b00a-4c88-ad2e-1f7f8788c560</ObjectID> + <Name>testExisting_automation</Name> <!--only retrieved for cache--> + <CustomerKey>testExisting_automation</CustomerKey> <!--only retrieved for cache--> + </Results> + <Results xsi:type="Program"> + <PartnerKey xsi:nil="true" /> + <ObjectID>08afb0e2-b00a-4c88-ad2e-pause</ObjectID> + <Name>testExisting_automation_pause</Name> <!--only retrieved for cache--> + <CustomerKey>testExisting_automation_pause</CustomerKey> <!--only retrieved for cache--> + </Results> + <Results xsi:type="Program"> + <PartnerKey xsi:nil="true" /> + <ObjectID>08afb0e2-b00a-4c88-fixKey_schedule</ObjectID> + <Name>testExisting_automation_fixedKey_scheduled</Name> <!--only retrieved for cache--> + <CustomerKey>testExisting_automation_fixKey_schedule</CustomerKey> <!--only retrieved for cache--> + </Results> + <Results xsi:type="Program"> + <PartnerKey xsi:nil="true" /> + <ObjectID>08afb0e2-b00a-4c88-fixKey_pause</ObjectID> + <Name>testExisting_automation_fixedKey_paused</Name> <!--only retrieved for cache--> + <CustomerKey>testExisting_automation_fixKey_pause</CustomerKey> <!--only retrieved for cache--> + </Results> + <Results xsi:type="Program"> + <PartnerKey xsi:nil="true" /> + <ObjectID>0fc2ac96-14ba-495a-8db9-3ddd4f8ac444-wait</ObjectID> + <Name>testExisting_automation_wait</Name> <!--only retrieved for cache--> + <CustomerKey>testExisting_automation_wait</CustomerKey> <!--only retrieved for cache--> + </Results> + <Results xsi:type="Program"> + <PartnerKey xsi:nil="true" /> + <ObjectID>8f82c2a7-0bae-45a9-bdee-e631ab25c0d5</ObjectID> + <CustomerKey>testExisting_automation_event</CustomerKey> + <Name>testExisting_automation_event</Name> + </Results> + </RetrieveResponseMsg> + </soap:Body> +</soap:Envelope> diff --git a/test/resources/9999999/query/build-expected.json b/test/resources/9999999/query/build-expected.json new file mode 100644 index 000000000..52f2eb855 --- /dev/null +++ b/test/resources/9999999/query/build-expected.json @@ -0,0 +1,8 @@ +{ + "name": "testTemplated_query", + "key": "testTemplated_query", + "description": "foobar", + "r__dataExtension_key": "testTemplated_dataExtension", + "targetUpdateTypeName": "Overwrite", + "r__folder_Path": "Query" +} diff --git a/test/resources/9999999/query/build-expected.sql b/test/resources/9999999/query/build-expected.sql new file mode 100644 index 000000000..d1cba0e90 --- /dev/null +++ b/test/resources/9999999/query/build-expected.sql @@ -0,0 +1,7 @@ +SELECT + SubscriberKey AS testField, + TRIM(last_name) AS name +FROM + _Subscribers +WHERE + country IN ('testTarget') diff --git a/test/resources/9999999/query/clone-expected.json b/test/resources/9999999/query/clone-expected.json new file mode 100644 index 000000000..76e823ad2 --- /dev/null +++ b/test/resources/9999999/query/clone-expected.json @@ -0,0 +1,8 @@ +{ + "name": "testExisting_query", + "key": "testExisting_query", + "description": "bla bla", + "targetUpdateTypeName": "Overwrite", + "r__dataExtension_key": "testExisting_dataExtension", + "r__folder_Path": "Query" +} diff --git a/test/resources/9999999/query/clone-expected.sql b/test/resources/9999999/query/clone-expected.sql new file mode 100644 index 000000000..c6da62468 --- /dev/null +++ b/test/resources/9999999/query/clone-expected.sql @@ -0,0 +1,7 @@ +SELECT + SubscriberKey AS testField, + TRIM(last_name) AS name +FROM + _Subscribers +WHERE + country IN ('test') diff --git a/test/resources/9999999/query/get-expected.json b/test/resources/9999999/query/get-expected.json new file mode 100644 index 000000000..095a95795 --- /dev/null +++ b/test/resources/9999999/query/get-expected.json @@ -0,0 +1,11 @@ +{ + "name": "testExisting_query", + "key": "testExisting_query", + "description": "bla bla", + "r__dataExtension_key": "testExisting_dataExtension", + "createdDate": "2022-04-26T15:21:16.453", + "modifiedDate": "2022-04-26T16:02:44.01", + "targetUpdateTypeName": "Overwrite", + "r__folder_Path": "Query", + "isFrozen": false +} diff --git a/test/resources/9999999/query/get-expected.sql b/test/resources/9999999/query/get-expected.sql new file mode 100644 index 000000000..c6da62468 --- /dev/null +++ b/test/resources/9999999/query/get-expected.sql @@ -0,0 +1,7 @@ +SELECT + SubscriberKey AS testField, + TRIM(last_name) AS name +FROM + _Subscribers +WHERE + country IN ('test') diff --git a/test/resources/9999999/query/get2-expected.json b/test/resources/9999999/query/get2-expected.json new file mode 100644 index 000000000..7202dfafd --- /dev/null +++ b/test/resources/9999999/query/get2-expected.json @@ -0,0 +1,11 @@ +{ + "name": "testExisting_query2", + "key": "testExisting_query2", + "description": "bla bla", + "r__dataExtension_key": "testExisting_dataExtension", + "createdDate": "2022-04-26T15:21:16.453", + "modifiedDate": "2022-04-26T16:02:44.01", + "targetUpdateTypeName": "Overwrite", + "r__folder_Path": "Query", + "isFrozen": false +} diff --git a/test/resources/9999999/query/patch-expected.json b/test/resources/9999999/query/patch-expected.json new file mode 100644 index 000000000..bb96f9b40 --- /dev/null +++ b/test/resources/9999999/query/patch-expected.json @@ -0,0 +1,11 @@ +{ + "name": "testExisting_query", + "key": "testExisting_query", + "description": "updated on deploy", + "r__dataExtension_key": "testExisting_dataExtension", + "createdDate": "2022-04-26T15:21:16.453", + "modifiedDate": "2022-04-26T16:04:15.88", + "targetUpdateTypeName": "Overwrite", + "isFrozen": false, + "r__folder_Path": "Query" +} diff --git a/test/resources/9999999/query/patch-expected.sql b/test/resources/9999999/query/patch-expected.sql new file mode 100644 index 000000000..e78525408 --- /dev/null +++ b/test/resources/9999999/query/patch-expected.sql @@ -0,0 +1,6 @@ +SELECT + SubscriberKey as testField +FROM + _Subscribers +WHERE + country IN ('test') diff --git a/test/resources/9999999/query/patch_fixKeys-expected.json b/test/resources/9999999/query/patch_fixKeys-expected.json new file mode 100644 index 000000000..f832f198f --- /dev/null +++ b/test/resources/9999999/query/patch_fixKeys-expected.json @@ -0,0 +1,11 @@ +{ + "name": "testExisting_query_fixedKeys", + "key": "testExisting_query_fixedKeys", + "description": "updated on deploy", + "r__dataExtension_key": "testExisting_dataExtension", + "createdDate": "2022-04-26T15:21:16.453", + "modifiedDate": "2022-04-26T16:04:15.88", + "targetUpdateTypeName": "Overwrite", + "isFrozen": false, + "r__folder_Path": "Query" +} diff --git a/test/resources/9999999/query/patch_fixKeys-expected.sql b/test/resources/9999999/query/patch_fixKeys-expected.sql new file mode 100644 index 000000000..2a32f5fad --- /dev/null +++ b/test/resources/9999999/query/patch_fixKeys-expected.sql @@ -0,0 +1,6 @@ +SELECT + SubscriberKey AS testField +FROM + _Subscribers +WHERE + country IN ('test') diff --git a/test/resources/9999999/query/patch_fixKeysSuffix-expected.json b/test/resources/9999999/query/patch_fixKeysSuffix-expected.json new file mode 100644 index 000000000..fed822d43 --- /dev/null +++ b/test/resources/9999999/query/patch_fixKeysSuffix-expected.json @@ -0,0 +1,11 @@ +{ + "name": "testExisting_query_fixedKeysSuffix", + "key": "testExisting_query_fixedKeysSuff_DEV", + "description": "updated on deploy", + "r__dataExtension_key": "testExisting_dataExtension", + "createdDate": "2022-04-26T15:21:16.453", + "modifiedDate": "2022-04-26T16:04:15.88", + "targetUpdateTypeName": "Overwrite", + "isFrozen": false, + "r__folder_Path": "Query" +} diff --git a/test/resources/9999999/query/patch_fixKeysSuffix-expected.sql b/test/resources/9999999/query/patch_fixKeysSuffix-expected.sql new file mode 100644 index 000000000..2a32f5fad --- /dev/null +++ b/test/resources/9999999/query/patch_fixKeysSuffix-expected.sql @@ -0,0 +1,6 @@ +SELECT + SubscriberKey AS testField +FROM + _Subscribers +WHERE + country IN ('test') diff --git a/test/resources/9999999/query/post-expected.json b/test/resources/9999999/query/post-expected.json new file mode 100644 index 000000000..bc06864f0 --- /dev/null +++ b/test/resources/9999999/query/post-expected.json @@ -0,0 +1,11 @@ +{ + "name": "testNew_query", + "key": "testNew_query", + "description": "created on deploy", + "r__dataExtension_key": "testExisting_dataExtension", + "createdDate": "2022-04-26T15:21:16.453", + "modifiedDate": "2022-04-26T16:04:15.88", + "targetUpdateTypeName": "Overwrite", + "isFrozen": false, + "r__folder_Path": "Query" +} diff --git a/test/resources/9999999/query/post-expected.sql b/test/resources/9999999/query/post-expected.sql new file mode 100644 index 000000000..8020314ea --- /dev/null +++ b/test/resources/9999999/query/post-expected.sql @@ -0,0 +1,4 @@ +SELECT + SubscriberKey as testField +FROM + _Subscribers diff --git a/test/resources/9999999/query/template-expected.json b/test/resources/9999999/query/template-expected.json new file mode 100644 index 000000000..f8b37fc59 --- /dev/null +++ b/test/resources/9999999/query/template-expected.json @@ -0,0 +1,8 @@ +{ + "name": "{{{prefix}}}query", + "key": "{{{prefix}}}query", + "description": "{{{description}}}", + "r__dataExtension_key": "{{{prefix}}}dataExtension", + "targetUpdateTypeName": "Overwrite", + "r__folder_Path": "Query" +} diff --git a/test/resources/9999999/query/template-expected.sql b/test/resources/9999999/query/template-expected.sql new file mode 100644 index 000000000..a1210ae9f --- /dev/null +++ b/test/resources/9999999/query/template-expected.sql @@ -0,0 +1,7 @@ +SELECT + SubscriberKey AS testField, + TRIM(last_name) AS name +FROM + _Subscribers +WHERE + country IN ({{{countryCodeIn}}}) diff --git a/test/resources/9999999/queryDefinition/retrieve-CustomerKey=badANDStatus=Active-response.xml b/test/resources/9999999/queryDefinition/retrieve-CustomerKey=badANDStatus=Active-response.xml new file mode 100644 index 000000000..b250a34db --- /dev/null +++ b/test/resources/9999999/queryDefinition/retrieve-CustomerKey=badANDStatus=Active-response.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="utf-8"?> +<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:xsd="http://www.w3.org/2001/XMLSchema" + xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing" + xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" + xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"> + <soap:Header> + <wsa:Action>RetrieveResponse</wsa:Action> + <wsa:MessageID>urn:uuid:ed6a40f5-98ec-48e9-a059-2a4b7254448b</wsa:MessageID> + <wsa:RelatesTo>urn:uuid:1b00729b-19f9-4eae-b856-f5ce837ec0c8</wsa:RelatesTo> + <wsa:To>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</wsa:To> + <wsse:Security> + <wsu:Timestamp wsu:Id="Timestamp-cd3b3dcd-ad61-43ad-9b80-3934f420befd"> + <wsu:Created>2024-07-12T09:24:49Z</wsu:Created> + <wsu:Expires>2024-07-12T09:29:49Z</wsu:Expires> + </wsu:Timestamp> + </wsse:Security> + </soap:Header> + <soap:Body> + <RetrieveResponseMsg xmlns="http://exacttarget.com/wsdl/partnerAPI"> + <OverallStatus>OK</OverallStatus> + <RequestID>57658276-aab0-4312-b305-3b7e9911817f</RequestID> + </RetrieveResponseMsg> + </soap:Body> +</soap:Envelope> \ No newline at end of file diff --git a/test/resources/9999999/queryDefinition/retrieve-CustomerKey=testExisting_query2ANDStatus=Active-response.xml b/test/resources/9999999/queryDefinition/retrieve-CustomerKey=testExisting_query2ANDStatus=Active-response.xml new file mode 100644 index 000000000..d0132b483 --- /dev/null +++ b/test/resources/9999999/queryDefinition/retrieve-CustomerKey=testExisting_query2ANDStatus=Active-response.xml @@ -0,0 +1,30 @@ +<?xml version="1.0" encoding="utf-8"?> +<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:xsd="http://www.w3.org/2001/XMLSchema" + xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing" + xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" + xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"> + <soap:Header> + <wsa:Action>RetrieveResponse</wsa:Action> + <wsa:MessageID>urn:uuid:7ef0345e-b559-4fc4-8986-47e54e1a8a58</wsa:MessageID> + <wsa:RelatesTo>urn:uuid:b2e814a6-517c-4882-9bbb-238bfce951ce</wsa:RelatesTo> + <wsa:To>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</wsa:To> + <wsse:Security> + <wsu:Timestamp wsu:Id="Timestamp-dfc4ae59-8642-4432-b505-554669b47186"> + <wsu:Created>2023-04-11T16:33:48Z</wsu:Created> + <wsu:Expires>2023-04-11T16:38:48Z</wsu:Expires> + </wsu:Timestamp> + </wsse:Security> + </soap:Header> + <soap:Body> + <RetrieveResponseMsg xmlns="http://exacttarget.com/wsdl/partnerAPI"> + <OverallStatus>OK</OverallStatus> + <RequestID>e8eb2988-2f43-4243-a6b0-6ab6b841a6ac</RequestID> + <Results xsi:type="QueryDefinition"> + <PartnerKey xsi:nil="true" /> + <ObjectID>abcde-607c-4940-afef-437965094dat</ObjectID> + </Results> + </RetrieveResponseMsg> + </soap:Body> +</soap:Envelope> diff --git a/test/resources/9999999/queryDefinition/retrieve-CustomerKey=testExisting_queryANDStatus=Active-response.xml b/test/resources/9999999/queryDefinition/retrieve-CustomerKey=testExisting_queryANDStatus=Active-response.xml new file mode 100644 index 000000000..db31d8288 --- /dev/null +++ b/test/resources/9999999/queryDefinition/retrieve-CustomerKey=testExisting_queryANDStatus=Active-response.xml @@ -0,0 +1,30 @@ +<?xml version="1.0" encoding="utf-8"?> +<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:xsd="http://www.w3.org/2001/XMLSchema" + xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing" + xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" + xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"> + <soap:Header> + <wsa:Action>RetrieveResponse</wsa:Action> + <wsa:MessageID>urn:uuid:7ef0345e-b559-4fc4-8986-47e54e1a8a58</wsa:MessageID> + <wsa:RelatesTo>urn:uuid:b2e814a6-517c-4882-9bbb-238bfce951ce</wsa:RelatesTo> + <wsa:To>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</wsa:To> + <wsse:Security> + <wsu:Timestamp wsu:Id="Timestamp-dfc4ae59-8642-4432-b505-554669b47186"> + <wsu:Created>2023-04-11T16:33:48Z</wsu:Created> + <wsu:Expires>2023-04-11T16:38:48Z</wsu:Expires> + </wsu:Timestamp> + </wsse:Security> + </soap:Header> + <soap:Body> + <RetrieveResponseMsg xmlns="http://exacttarget.com/wsdl/partnerAPI"> + <OverallStatus>OK</OverallStatus> + <RequestID>e8eb2988-2f43-4243-a6b0-6ab6b841a6ab</RequestID> + <Results xsi:type="QueryDefinition"> + <PartnerKey xsi:nil="true" /> + <ObjectID>549f0568-607c-4940-afef-437965094dat</ObjectID> + </Results> + </RetrieveResponseMsg> + </soap:Body> +</soap:Envelope> \ No newline at end of file diff --git a/test/resources/9999999/queryDefinition/retrieve-CustomerKey=testExisting_query_fixKeysANDStatus=Active-response.xml b/test/resources/9999999/queryDefinition/retrieve-CustomerKey=testExisting_query_fixKeysANDStatus=Active-response.xml new file mode 100644 index 000000000..d816ae0d9 --- /dev/null +++ b/test/resources/9999999/queryDefinition/retrieve-CustomerKey=testExisting_query_fixKeysANDStatus=Active-response.xml @@ -0,0 +1,30 @@ +<?xml version="1.0" encoding="utf-8"?> +<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:xsd="http://www.w3.org/2001/XMLSchema" + xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing" + xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" + xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"> + <soap:Header> + <wsa:Action>RetrieveResponse</wsa:Action> + <wsa:MessageID>urn:uuid:7ef0345e-b559-4fc4-8986-47e54e1a8a58</wsa:MessageID> + <wsa:RelatesTo>urn:uuid:b2e814a6-517c-4882-9bbb-238bfce951ce</wsa:RelatesTo> + <wsa:To>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</wsa:To> + <wsse:Security> + <wsu:Timestamp wsu:Id="Timestamp-dfc4ae59-8642-4432-b505-554669b47186"> + <wsu:Created>2023-04-11T16:33:48Z</wsu:Created> + <wsu:Expires>2023-04-11T16:38:48Z</wsu:Expires> + </wsu:Timestamp> + </wsse:Security> + </soap:Header> + <soap:Body> + <RetrieveResponseMsg xmlns="http://exacttarget.com/wsdl/partnerAPI"> + <OverallStatus>OK</OverallStatus> + <RequestID>e8eb2988-2f43-4243-a6b0-6ab6b841a6ab</RequestID> + <Results xsi:type="QueryDefinition"> + <PartnerKey xsi:nil="true" /> + <ObjectID>549f0568-607c-4940-afef-437965094dat_fixKeys</ObjectID> + </Results> + </RetrieveResponseMsg> + </soap:Body> +</soap:Envelope> diff --git a/test/resources/9999999/queryDefinition/retrieve-CustomerKey=testExisting_query_fixKeysSuffixANDStatus=Active-response.xml b/test/resources/9999999/queryDefinition/retrieve-CustomerKey=testExisting_query_fixKeysSuffixANDStatus=Active-response.xml new file mode 100644 index 000000000..af515b27e --- /dev/null +++ b/test/resources/9999999/queryDefinition/retrieve-CustomerKey=testExisting_query_fixKeysSuffixANDStatus=Active-response.xml @@ -0,0 +1,30 @@ +<?xml version="1.0" encoding="utf-8"?> +<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:xsd="http://www.w3.org/2001/XMLSchema" + xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing" + xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" + xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"> + <soap:Header> + <wsa:Action>RetrieveResponse</wsa:Action> + <wsa:MessageID>urn:uuid:7ef0345e-b559-4fc4-8986-47e54e1a8a58</wsa:MessageID> + <wsa:RelatesTo>urn:uuid:b2e814a6-517c-4882-9bbb-238bfce951ce</wsa:RelatesTo> + <wsa:To>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</wsa:To> + <wsse:Security> + <wsu:Timestamp wsu:Id="Timestamp-dfc4ae59-8642-4432-b505-554669b47186"> + <wsu:Created>2023-04-11T16:33:48Z</wsu:Created> + <wsu:Expires>2023-04-11T16:38:48Z</wsu:Expires> + </wsu:Timestamp> + </wsse:Security> + </soap:Header> + <soap:Body> + <RetrieveResponseMsg xmlns="http://exacttarget.com/wsdl/partnerAPI"> + <OverallStatus>OK</OverallStatus> + <RequestID>e8eb2988-2f43-4243-a6b0-6ab6b841a6ab</RequestID> + <Results xsi:type="QueryDefinition"> + <PartnerKey xsi:nil="true" /> + <ObjectID>549f0568-607c-4940-afef-437965094dat_fixKeysSuffix</ObjectID> + </Results> + </RetrieveResponseMsg> + </soap:Body> +</soap:Envelope> diff --git a/test/resources/9999999/queryDefinition/retrieve-CustomerKey=testExisting_query_fixedKeysANDStatus=Active-response.xml b/test/resources/9999999/queryDefinition/retrieve-CustomerKey=testExisting_query_fixedKeysANDStatus=Active-response.xml new file mode 100644 index 000000000..db31d8288 --- /dev/null +++ b/test/resources/9999999/queryDefinition/retrieve-CustomerKey=testExisting_query_fixedKeysANDStatus=Active-response.xml @@ -0,0 +1,30 @@ +<?xml version="1.0" encoding="utf-8"?> +<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:xsd="http://www.w3.org/2001/XMLSchema" + xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing" + xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" + xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"> + <soap:Header> + <wsa:Action>RetrieveResponse</wsa:Action> + <wsa:MessageID>urn:uuid:7ef0345e-b559-4fc4-8986-47e54e1a8a58</wsa:MessageID> + <wsa:RelatesTo>urn:uuid:b2e814a6-517c-4882-9bbb-238bfce951ce</wsa:RelatesTo> + <wsa:To>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</wsa:To> + <wsse:Security> + <wsu:Timestamp wsu:Id="Timestamp-dfc4ae59-8642-4432-b505-554669b47186"> + <wsu:Created>2023-04-11T16:33:48Z</wsu:Created> + <wsu:Expires>2023-04-11T16:38:48Z</wsu:Expires> + </wsu:Timestamp> + </wsse:Security> + </soap:Header> + <soap:Body> + <RetrieveResponseMsg xmlns="http://exacttarget.com/wsdl/partnerAPI"> + <OverallStatus>OK</OverallStatus> + <RequestID>e8eb2988-2f43-4243-a6b0-6ab6b841a6ab</RequestID> + <Results xsi:type="QueryDefinition"> + <PartnerKey xsi:nil="true" /> + <ObjectID>549f0568-607c-4940-afef-437965094dat</ObjectID> + </Results> + </RetrieveResponseMsg> + </soap:Body> +</soap:Envelope> \ No newline at end of file diff --git a/test/resources/9999999/queryDefinition/retrieve-CustomerKey=testNew_queryANDStatus=Active-response.xml b/test/resources/9999999/queryDefinition/retrieve-CustomerKey=testNew_queryANDStatus=Active-response.xml new file mode 100644 index 000000000..ad6aad842 --- /dev/null +++ b/test/resources/9999999/queryDefinition/retrieve-CustomerKey=testNew_queryANDStatus=Active-response.xml @@ -0,0 +1,30 @@ +<?xml version="1.0" encoding="utf-8"?> +<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:xsd="http://www.w3.org/2001/XMLSchema" + xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing" + xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" + xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"> + <soap:Header> + <wsa:Action>RetrieveResponse</wsa:Action> + <wsa:MessageID>urn:uuid:7ef0345e-b559-4fc4-8986-47e54e1a8a58</wsa:MessageID> + <wsa:RelatesTo>urn:uuid:b2e814a6-517c-4882-9bbb-238bfce951ce</wsa:RelatesTo> + <wsa:To>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</wsa:To> + <wsse:Security> + <wsu:Timestamp wsu:Id="Timestamp-dfc4ae59-8642-4432-b505-554669b47186"> + <wsu:Created>2023-04-11T16:33:48Z</wsu:Created> + <wsu:Expires>2023-04-11T16:38:48Z</wsu:Expires> + </wsu:Timestamp> + </wsse:Security> + </soap:Header> + <soap:Body> + <RetrieveResponseMsg xmlns="http://exacttarget.com/wsdl/partnerAPI"> + <OverallStatus>OK</OverallStatus> + <RequestID>e8eb2988-2f43-4243-a6b0-6ab6b841a6ab</RequestID> + <Results xsi:type="QueryDefinition"> + <PartnerKey xsi:nil="true" /> + <ObjectID>549f0568-607c-4940-afef-437965094dae</ObjectID> + </Results> + </RetrieveResponseMsg> + </soap:Body> +</soap:Envelope> \ No newline at end of file diff --git a/test/resources/9999999/script/build-expected.json b/test/resources/9999999/script/build-expected.json new file mode 100644 index 000000000..6daa00403 --- /dev/null +++ b/test/resources/9999999/script/build-expected.json @@ -0,0 +1,6 @@ +{ + "description": "", + "key": "testTemplated_script", + "name": "testTemplated_script", + "r__folder_Path": "Scripts" +} diff --git a/test/resources/9999999/script/build-expected.ssjs b/test/resources/9999999/script/build-expected.ssjs new file mode 100644 index 000000000..27c4b7e5c --- /dev/null +++ b/test/resources/9999999/script/build-expected.ssjs @@ -0,0 +1 @@ +//dummy diff --git a/test/resources/9999999/script/get-expected.json b/test/resources/9999999/script/get-expected.json new file mode 100644 index 000000000..6572bab64 --- /dev/null +++ b/test/resources/9999999/script/get-expected.json @@ -0,0 +1,8 @@ +{ + "createdDate": "2022-10-20T00:41:26.163", + "description": "", + "key": "testExisting_script", + "modifiedDate": "2022-10-20T00:41:26.163", + "name": "testExisting_script", + "r__folder_Path": "Scripts" +} diff --git a/test/resources/9999999/script/get-expected.ssjs b/test/resources/9999999/script/get-expected.ssjs new file mode 100644 index 000000000..27c4b7e5c --- /dev/null +++ b/test/resources/9999999/script/get-expected.ssjs @@ -0,0 +1 @@ +//dummy diff --git a/test/resources/9999999/script/get_ampincluded-expected.html b/test/resources/9999999/script/get_ampincluded-expected.html new file mode 100644 index 000000000..cd0777f11 --- /dev/null +++ b/test/resources/9999999/script/get_ampincluded-expected.html @@ -0,0 +1,5 @@ + <script runat="server">line1 %%[ SET @test='bla bla' ]%% line2 %%= ContentBlockById(1295064) =%% still line2 +line3 +</script> +<script runat="server"> +Platform.Function.ContentBlockById(1295064);</script> \ No newline at end of file diff --git a/test/resources/9999999/script/get_ampincluded-expected.json b/test/resources/9999999/script/get_ampincluded-expected.json new file mode 100644 index 000000000..b801f5140 --- /dev/null +++ b/test/resources/9999999/script/get_ampincluded-expected.json @@ -0,0 +1,8 @@ +{ + "createdDate": "2022-10-20T00:41:26.163", + "description": "", + "key": "testExisting_script_ampincluded", + "modifiedDate": "2022-10-20T00:41:26.163", + "name": "testExisting_script_ampincluded", + "r__folder_Path": "Scripts" +} diff --git a/test/resources/9999999/script/get_ampincluded-rcb-id-expected.html b/test/resources/9999999/script/get_ampincluded-rcb-id-expected.html new file mode 100644 index 000000000..cd0777f11 --- /dev/null +++ b/test/resources/9999999/script/get_ampincluded-rcb-id-expected.html @@ -0,0 +1,5 @@ + <script runat="server">line1 %%[ SET @test='bla bla' ]%% line2 %%= ContentBlockById(1295064) =%% still line2 +line3 +</script> +<script runat="server"> +Platform.Function.ContentBlockById(1295064);</script> \ No newline at end of file diff --git a/test/resources/9999999/script/get_ampincluded-rcb-key-expected.html b/test/resources/9999999/script/get_ampincluded-rcb-key-expected.html new file mode 100644 index 000000000..fb3c33fd6 --- /dev/null +++ b/test/resources/9999999/script/get_ampincluded-rcb-key-expected.html @@ -0,0 +1,5 @@ + <script runat="server">line1 %%[ SET @test='bla bla' ]%% line2 %%= ContentBlockByKey("testExisting_asset_htmlblock") =%% still line2 +line3 +</script> +<script runat="server"> +Platform.Function.ContentBlockByKey("testExisting_asset_htmlblock");</script> \ No newline at end of file diff --git a/test/resources/9999999/script/get_ampincluded-rcb-name-expected.html b/test/resources/9999999/script/get_ampincluded-rcb-name-expected.html new file mode 100644 index 000000000..79e3ce357 --- /dev/null +++ b/test/resources/9999999/script/get_ampincluded-rcb-name-expected.html @@ -0,0 +1,5 @@ + <script runat="server">line1 %%[ SET @test='bla bla' ]%% line2 %%= ContentBlockByName("Content Builder\dont strip non ssjs content") =%% still line2 +line3 +</script> +<script runat="server"> +Platform.Function.ContentBlockByName("Content Builder\\dont strip non ssjs content");</script> \ No newline at end of file diff --git a/test/resources/9999999/script/get_ampscript-expected.html b/test/resources/9999999/script/get_ampscript-expected.html new file mode 100644 index 000000000..57288c629 --- /dev/null +++ b/test/resources/9999999/script/get_ampscript-expected.html @@ -0,0 +1,11 @@ +line1 +%%[ + SET @test = 'bla bla' +]%% +line2 %%= ContentBlockByName("Content Builder\dont strip non ssjs content") =%% still line2 line3 +<script runat="server"> + Platform.Function.ContentBlockByName( + "Content Builder\\dont strip non ssjs content" + ); + Platform.Function.ContentBlockByKey("testExisting_htmlblock1"); +</script> diff --git a/test/resources/9999999/script/get_ampscript-expected.json b/test/resources/9999999/script/get_ampscript-expected.json new file mode 100644 index 000000000..949cbc253 --- /dev/null +++ b/test/resources/9999999/script/get_ampscript-expected.json @@ -0,0 +1,8 @@ +{ + "createdDate": "2022-10-20T00:41:26.163", + "description": "", + "key": "testExisting_script_ampscript", + "modifiedDate": "2022-10-20T00:41:26.163", + "name": "testExisting_script_ampscript", + "r__folder_Path": "Scripts" +} diff --git a/test/resources/9999999/script/get_ampscript-rcb-id-expected.html b/test/resources/9999999/script/get_ampscript-rcb-id-expected.html new file mode 100644 index 000000000..66556e42e --- /dev/null +++ b/test/resources/9999999/script/get_ampscript-rcb-id-expected.html @@ -0,0 +1,9 @@ +line1 +%%[ + SET @test = 'bla bla' +]%% +line2 %%= ContentBlockById(1295064) =%% still line2 line3 +<script runat="server"> + Platform.Function.ContentBlockById(1295064); + Platform.Function.ContentBlockById(1295065); +</script> diff --git a/test/resources/9999999/script/get_ampscript-rcb-key-expected.html b/test/resources/9999999/script/get_ampscript-rcb-key-expected.html new file mode 100644 index 000000000..3ca32a318 --- /dev/null +++ b/test/resources/9999999/script/get_ampscript-rcb-key-expected.html @@ -0,0 +1,9 @@ +line1 +%%[ + SET @test = 'bla bla' +]%% +line2 %%= ContentBlockByKey("testExisting_asset_htmlblock") =%% still line2 line3 +<script runat="server"> + Platform.Function.ContentBlockByKey("testExisting_asset_htmlblock"); + Platform.Function.ContentBlockByKey("testExisting_htmlblock1"); +</script> diff --git a/test/resources/9999999/script/get_ampscript-rcb-name-expected.html b/test/resources/9999999/script/get_ampscript-rcb-name-expected.html new file mode 100644 index 000000000..bc84391ac --- /dev/null +++ b/test/resources/9999999/script/get_ampscript-rcb-name-expected.html @@ -0,0 +1,13 @@ +line1 +%%[ + SET @test = 'bla bla' +]%% +line2 %%= ContentBlockByName("Content Builder\dont strip non ssjs content") =%% still line2 line3 +<script runat="server"> + Platform.Function.ContentBlockByName( + "Content Builder\\dont strip non ssjs content" + ); + Platform.Function.ContentBlockByName( + "Content Builder\\testExisting_htmlblock1" + ); +</script> diff --git a/test/resources/9999999/script/get_mixed-expected.html b/test/resources/9999999/script/get_mixed-expected.html new file mode 100644 index 000000000..465a06695 --- /dev/null +++ b/test/resources/9999999/script/get_mixed-expected.html @@ -0,0 +1,12 @@ +<script runat="server"> + //dummy +</script> +line1 +%%[ + SET @test = 'bla bla' +]%% +line2 %%= ContentBlockByKey("testExisting_asset_htmlblock") =%% still line2; collapsed to line2 because it's assumed +HTML +<script runat="server"> + Platform.Function.ContentBlockByKey("testExisting_asset_htmlblock"); +</script> diff --git a/test/resources/9999999/script/get_mixed-expected.json b/test/resources/9999999/script/get_mixed-expected.json new file mode 100644 index 000000000..c217d3cb1 --- /dev/null +++ b/test/resources/9999999/script/get_mixed-expected.json @@ -0,0 +1,8 @@ +{ + "createdDate": "2022-10-20T00:41:26.163", + "description": "", + "key": "testExisting_script_mixed", + "modifiedDate": "2022-10-20T00:41:26.163", + "name": "testExisting_script_mixed", + "r__folder_Path": "Scripts" +} diff --git a/test/resources/9999999/script/get_mixed-rcb-id-expected.html b/test/resources/9999999/script/get_mixed-rcb-id-expected.html new file mode 100644 index 000000000..bf9e6e0c9 --- /dev/null +++ b/test/resources/9999999/script/get_mixed-rcb-id-expected.html @@ -0,0 +1,12 @@ +<script runat="server"> + //dummy +</script> +line1 +%%[ + SET @test = 'bla bla' +]%% +line2 %%= ContentBlockById(1295064) =%% still line2; collapsed to line2 because it's assumed +HTML +<script runat="server"> + Platform.Function.ContentBlockById(1295064); +</script> diff --git a/test/resources/9999999/script/get_mixed-rcb-key-expected.html b/test/resources/9999999/script/get_mixed-rcb-key-expected.html new file mode 100644 index 000000000..465a06695 --- /dev/null +++ b/test/resources/9999999/script/get_mixed-rcb-key-expected.html @@ -0,0 +1,12 @@ +<script runat="server"> + //dummy +</script> +line1 +%%[ + SET @test = 'bla bla' +]%% +line2 %%= ContentBlockByKey("testExisting_asset_htmlblock") =%% still line2; collapsed to line2 because it's assumed +HTML +<script runat="server"> + Platform.Function.ContentBlockByKey("testExisting_asset_htmlblock"); +</script> diff --git a/test/resources/9999999/script/get_mixed-rcb-name-expected.html b/test/resources/9999999/script/get_mixed-rcb-name-expected.html new file mode 100644 index 000000000..3b8fbff2c --- /dev/null +++ b/test/resources/9999999/script/get_mixed-rcb-name-expected.html @@ -0,0 +1,14 @@ +<script runat="server"> + //dummy +</script> +line1 +%%[ + SET @test = 'bla bla' +]%% +line2 %%= ContentBlockByName("Content Builder\dont strip non ssjs content") =%% still line2; collapsed to line2 because it's assumed +HTML +<script runat="server"> + Platform.Function.ContentBlockByName( + "Content Builder\\dont strip non ssjs content" + ); +</script> diff --git a/test/resources/9999999/script/get_noScriptTag-expected.html b/test/resources/9999999/script/get_noScriptTag-expected.html new file mode 100644 index 000000000..634388fcc --- /dev/null +++ b/test/resources/9999999/script/get_noScriptTag-expected.html @@ -0,0 +1 @@ +// no script tag diff --git a/test/resources/9999999/script/get_noScriptTag-expected.json b/test/resources/9999999/script/get_noScriptTag-expected.json new file mode 100644 index 000000000..f6090804f --- /dev/null +++ b/test/resources/9999999/script/get_noScriptTag-expected.json @@ -0,0 +1,8 @@ +{ + "createdDate": "2022-10-20T00:41:26.163", + "description": "", + "key": "testExisting_script_noScriptTag", + "modifiedDate": "2022-10-20T00:41:26.163", + "name": "testExisting_script_noScriptTag", + "r__folder_Path": "Scripts" +} diff --git a/test/resources/9999999/script/patch-expected.json b/test/resources/9999999/script/patch-expected.json new file mode 100644 index 000000000..81f145a49 --- /dev/null +++ b/test/resources/9999999/script/patch-expected.json @@ -0,0 +1,8 @@ +{ + "createdDate": "2022-10-20T00:41:26.163", + "description": "updated on deploy", + "key": "testExisting_script", + "modifiedDate": "2022-10-20T00:41:26.163", + "name": "testExisting_script", + "r__folder_Path": "Scripts" +} diff --git a/test/resources/9999999/script/patch-expected.ssjs b/test/resources/9999999/script/patch-expected.ssjs new file mode 100644 index 000000000..0b0aa34ae --- /dev/null +++ b/test/resources/9999999/script/patch-expected.ssjs @@ -0,0 +1,2 @@ + +// dummy updated diff --git a/test/resources/9999999/script/post-expected.json b/test/resources/9999999/script/post-expected.json new file mode 100644 index 000000000..a2389daac --- /dev/null +++ b/test/resources/9999999/script/post-expected.json @@ -0,0 +1,8 @@ +{ + "createdDate": "2022-10-20T00:41:26.163", + "description": "created on deploy", + "key": "testNew_script", + "modifiedDate": "2022-10-20T00:41:26.163", + "name": "testNew_script", + "r__folder_Path": "Scripts" +} diff --git a/test/resources/9999999/script/post-expected.ssjs b/test/resources/9999999/script/post-expected.ssjs new file mode 100644 index 000000000..bbfd28311 --- /dev/null +++ b/test/resources/9999999/script/post-expected.ssjs @@ -0,0 +1 @@ +// dummy created diff --git a/test/resources/9999999/script/template-expected.json b/test/resources/9999999/script/template-expected.json new file mode 100644 index 000000000..bd3ae9904 --- /dev/null +++ b/test/resources/9999999/script/template-expected.json @@ -0,0 +1,6 @@ +{ + "description": "", + "key": "{{{prefix}}}script", + "name": "{{{prefix}}}script", + "r__folder_Path": "Scripts" +} diff --git a/test/resources/9999999/script/template-expected.ssjs b/test/resources/9999999/script/template-expected.ssjs new file mode 100644 index 000000000..27c4b7e5c --- /dev/null +++ b/test/resources/9999999/script/template-expected.ssjs @@ -0,0 +1 @@ +//dummy diff --git a/test/resources/9999999/sendClassification/build-expected.json b/test/resources/9999999/sendClassification/build-expected.json new file mode 100644 index 000000000..9f1f723f0 --- /dev/null +++ b/test/resources/9999999/sendClassification/build-expected.json @@ -0,0 +1,8 @@ +{ + "CustomerKey": "testTemplated_sendClassification", + "Description": "", + "Name": "testTemplated_sendClassification", + "c__classification": "Commercial", + "r__deliveryProfile_key": "Default", + "r__senderProfile_key": "testTemplated_senderProfile" +} diff --git a/test/resources/9999999/sendClassification/create-response.xml b/test/resources/9999999/sendClassification/create-response.xml new file mode 100644 index 000000000..a6789e5c3 --- /dev/null +++ b/test/resources/9999999/sendClassification/create-response.xml @@ -0,0 +1,51 @@ +<?xml version="1.0" encoding="utf-8"?> +<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:xsd="http://www.w3.org/2001/XMLSchema" + xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing" + xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" + xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"> + <soap:Header> + <wsa:Action>CreateResponse</wsa:Action> + <wsa:MessageID>urn:uuid:bb642235-9021-414c-8f0e-31d693a573e8</wsa:MessageID> + <wsa:RelatesTo>urn:uuid:b49d6c14-33d7-4ba8-8aea-0fe3282fdbfd</wsa:RelatesTo> + <wsa:To>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</wsa:To> + <wsse:Security> + <wsu:Timestamp wsu:Id="Timestamp-3e603e14-dc4c-4733-be8a-e2d8d3e205cb"> + <wsu:Created>2024-04-15T21:38:02Z</wsu:Created> + <wsu:Expires>2024-04-15T21:43:02Z</wsu:Expires> + </wsu:Timestamp> + </wsse:Security> + </soap:Header> + <soap:Body> + <CreateResponse xmlns="http://exacttarget.com/wsdl/partnerAPI"> + <Results> + <StatusCode>OK</StatusCode> + <StatusMessage>SendClassification created</StatusMessage> + <OrdinalID>0</OrdinalID> + <NewID>0</NewID> + <NewObjectID>07cf2a6e-70fb-ee11-a5c8-5cba2c6fc270</NewObjectID> + <Object xsi:type="SendClassification"> + <PartnerKey xsi:nil="true" /> + <ObjectID>07cf2a6e-70fb-ee11-a5c8-5cba2c6fc270</ObjectID> + <CustomerKey>testNew_sendClassification</CustomerKey> + <SendClassificationType>Operational</SendClassificationType> + <Name>testNew_sendClassification</Name> + <Description>created on deploy</Description> + <SenderProfile> + <PartnerKey xsi:nil="true" /> + <ObjectID>a75d452b-7ef4-eb11-b82d-48df37d1da95</ObjectID> + <CustomerKey>testExisting_senderProfile</CustomerKey> + </SenderProfile> + <DeliveryProfile> + <PartnerKey xsi:nil="true" /> + <ObjectID xsi:nil="true" /> + <CustomerKey>Default</CustomerKey> + </DeliveryProfile> + </Object> + </Results> + <RequestID>d5f798f9-02eb-4b76-a4b4-90cfee939ce2</RequestID> + <OverallStatus>OK</OverallStatus> + </CreateResponse> + </soap:Body> +</soap:Envelope> diff --git a/test/resources/9999999/sendClassification/delete-response.xml b/test/resources/9999999/sendClassification/delete-response.xml new file mode 100644 index 000000000..b42fd3fbe --- /dev/null +++ b/test/resources/9999999/sendClassification/delete-response.xml @@ -0,0 +1,36 @@ +<?xml version="1.0" encoding="utf-8"?> +<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:xsd="http://www.w3.org/2001/XMLSchema" + xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing" + xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" + xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"> + <soap:Header> + <wsa:Action>DeleteResponse</wsa:Action> + <wsa:MessageID>urn:uuid:51ac7e8d-3d31-425c-8899-7ba4b2b09626</wsa:MessageID> + <wsa:RelatesTo>urn:uuid:9ee7419c-06be-4dcd-b386-5b64df545f2c</wsa:RelatesTo> + <wsa:To>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</wsa:To> + <wsse:Security> + <wsu:Timestamp wsu:Id="Timestamp-9ce349c8-ba3c-450a-b67f-f190a29fc100"> + <wsu:Created>2024-04-15T21:53:10Z</wsu:Created> + <wsu:Expires>2024-04-15T21:58:10Z</wsu:Expires> + </wsu:Timestamp> + </wsse:Security> + </soap:Header> + <soap:Body> + <DeleteResponse xmlns="http://exacttarget.com/wsdl/partnerAPI"> + <Results> + <StatusCode>OK</StatusCode> + <StatusMessage>SendClassification deleted</StatusMessage> + <OrdinalID>0</OrdinalID> + <Object xsi:type="SendClassification"> + <PartnerKey xsi:nil="true" /> + <ObjectID xsi:nil="true" /> + <CustomerKey>testExisting_sendClassification</CustomerKey> + </Object> + </Results> + <RequestID>0451cd2c-ab68-4e1c-9ded-d67003287283</RequestID> + <OverallStatus>OK</OverallStatus> + </DeleteResponse> + </soap:Body> +</soap:Envelope> diff --git a/test/resources/9999999/sendClassification/get-expected.json b/test/resources/9999999/sendClassification/get-expected.json new file mode 100644 index 000000000..e53df9bc3 --- /dev/null +++ b/test/resources/9999999/sendClassification/get-expected.json @@ -0,0 +1,10 @@ +{ + "CreatedDate": "2016-08-31T11:29:00", + "ModifiedDate": "2024-04-15T15:33:00", + "CustomerKey": "testExisting_sendClassification", + "Name": "testExisting_sendClassification", + "Description": "", + "c__classification": "Commercial", + "r__senderProfile_key": "testExisting_senderProfile", + "r__deliveryProfile_key": "Default" +} diff --git a/test/resources/9999999/sendClassification/patch-expected.json b/test/resources/9999999/sendClassification/patch-expected.json new file mode 100644 index 000000000..e53df9bc3 --- /dev/null +++ b/test/resources/9999999/sendClassification/patch-expected.json @@ -0,0 +1,10 @@ +{ + "CreatedDate": "2016-08-31T11:29:00", + "ModifiedDate": "2024-04-15T15:33:00", + "CustomerKey": "testExisting_sendClassification", + "Name": "testExisting_sendClassification", + "Description": "", + "c__classification": "Commercial", + "r__senderProfile_key": "testExisting_senderProfile", + "r__deliveryProfile_key": "Default" +} diff --git a/test/resources/9999999/sendClassification/post-expected.json b/test/resources/9999999/sendClassification/post-expected.json new file mode 100644 index 000000000..c7a7bb807 --- /dev/null +++ b/test/resources/9999999/sendClassification/post-expected.json @@ -0,0 +1,8 @@ +{ + "CustomerKey": "testNew_sendClassification", + "Name": "testNew_sendClassification", + "Description": "created on deploy", + "c__classification": "Transactional", + "r__senderProfile_key": "testExisting_senderProfile", + "r__deliveryProfile_key": "Default" +} diff --git a/test/resources/9999999/sendClassification/retrieve-response.xml b/test/resources/9999999/sendClassification/retrieve-response.xml new file mode 100644 index 000000000..83c023bfc --- /dev/null +++ b/test/resources/9999999/sendClassification/retrieve-response.xml @@ -0,0 +1,86 @@ +<?xml version="1.0" encoding="utf-8"?> +<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:xsd="http://www.w3.org/2001/XMLSchema" + xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing" + xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" + xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"> + <soap:Header> + <wsa:Action>RetrieveResponse</wsa:Action> + <wsa:MessageID>urn:uuid:31b53ebd-b853-4f8c-b952-f176aed80aa9</wsa:MessageID> + <wsa:RelatesTo>urn:uuid:cac816ee-0b59-4748-b629-4475b198708f</wsa:RelatesTo> + <wsa:To>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</wsa:To> + <wsse:Security> + <wsu:Timestamp wsu:Id="Timestamp-94d58fe7-c739-4593-b44e-86af9511d712"> + <wsu:Created>2024-04-15T21:11:54Z</wsu:Created> + <wsu:Expires>2024-04-15T21:16:54Z</wsu:Expires> + </wsu:Timestamp> + </wsse:Security> + </soap:Header> + <soap:Body> + <RetrieveResponseMsg xmlns="http://exacttarget.com/wsdl/partnerAPI"> + <OverallStatus>OK</OverallStatus> + <RequestID>e7197c3d-0483-44fd-93ad-d7dd2e0cfb56</RequestID> + <Results xsi:type="SendClassification"> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2016-07-22T11:53:00</CreatedDate> + <ModifiedDate>2016-07-22T11:53:00</ModifiedDate> + <ObjectID>8ecfb80f-3550-e611-96fe-38eaa7142c61</ObjectID> + <CustomerKey>Default Commercial</CustomerKey> + <SendClassificationType>Marketing</SendClassificationType> + <Name>Default Commercial</Name> + <Description>Default Commercial Send Classification</Description> + <SenderProfile> + <PartnerKey xsi:nil="true" /> + <ObjectID>7acfb80f-3550-e611-96fe-38eaa7142c61</ObjectID> + <CustomerKey>Default</CustomerKey> + </SenderProfile> + <DeliveryProfile> + <PartnerKey xsi:nil="true" /> + <ObjectID>163f8417-13f7-e911-a2d8-1402ec938a35</ObjectID> + <CustomerKey>Default</CustomerKey> + </DeliveryProfile> + </Results> + <Results xsi:type="SendClassification"> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2016-07-22T11:53:00</CreatedDate> + <ModifiedDate>2016-07-22T11:53:00</ModifiedDate> + <ObjectID>90cfb80f-3550-e611-96fe-38eaa7142c61</ObjectID> + <CustomerKey>Default Transactional</CustomerKey> + <SendClassificationType>Operational</SendClassificationType> + <Name>Default Transactional</Name> + <Description>Default Transactional Send Classification</Description> + <SenderProfile> + <PartnerKey xsi:nil="true" /> + <ObjectID>7acfb80f-3550-e611-96fe-38eaa7142c61</ObjectID> + <CustomerKey>Default</CustomerKey> + </SenderProfile> + <DeliveryProfile> + <PartnerKey xsi:nil="true" /> + <ObjectID>163f8417-13f7-e911-a2d8-1402ec938a35</ObjectID> + <CustomerKey>Default</CustomerKey> + </DeliveryProfile> + </Results> + <Results xsi:type="SendClassification"> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2016-08-31T11:29:00</CreatedDate> + <ModifiedDate>2024-04-15T15:33:00</ModifiedDate> + <ObjectID>95da425b-a06f-e611-96fe-38eaa7142c61</ObjectID> + <CustomerKey>testExisting_sendClassification</CustomerKey> + <SendClassificationType>Marketing</SendClassificationType> + <Name>testExisting_sendClassification</Name> + <Description /> + <SenderProfile> + <PartnerKey xsi:nil="true" /> + <ObjectID>a75d452b-7ef4-eb11-b82d-48df37d1da95</ObjectID> + <CustomerKey>testExisting_senderProfile</CustomerKey> + </SenderProfile> + <DeliveryProfile> + <PartnerKey xsi:nil="true" /> + <ObjectID>163f8417-13f7-e911-a2d8-1402ec938a35</ObjectID> + <CustomerKey>Default</CustomerKey> + </DeliveryProfile> + </Results> + </RetrieveResponseMsg> + </soap:Body> +</soap:Envelope> diff --git a/test/resources/9999999/sendClassification/template-expected.json b/test/resources/9999999/sendClassification/template-expected.json new file mode 100644 index 000000000..c7d069e6b --- /dev/null +++ b/test/resources/9999999/sendClassification/template-expected.json @@ -0,0 +1,8 @@ +{ + "CustomerKey": "{{{prefix}}}sendClassification", + "Description": "", + "Name": "{{{prefix}}}sendClassification", + "c__classification": "Commercial", + "r__deliveryProfile_key": "Default", + "r__senderProfile_key": "{{{prefix}}}senderProfile" +} diff --git a/test/resources/9999999/sendClassification/update-response.xml b/test/resources/9999999/sendClassification/update-response.xml new file mode 100644 index 000000000..4259753b6 --- /dev/null +++ b/test/resources/9999999/sendClassification/update-response.xml @@ -0,0 +1,49 @@ +<?xml version="1.0" encoding="utf-8"?> +<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:xsd="http://www.w3.org/2001/XMLSchema" + xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing" + xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" + xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"> + <soap:Header> + <wsa:Action>UpdateResponse</wsa:Action> + <wsa:MessageID>urn:uuid:76f29c30-cfd5-41b5-8c8f-d58a7ce82964</wsa:MessageID> + <wsa:RelatesTo>urn:uuid:e05b39ff-7e0b-4c3e-811d-362ee08f48f4</wsa:RelatesTo> + <wsa:To>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</wsa:To> + <wsse:Security> + <wsu:Timestamp wsu:Id="Timestamp-9d056168-651a-486b-b817-2a0caa906180"> + <wsu:Created>2024-04-15T21:32:54Z</wsu:Created> + <wsu:Expires>2024-04-15T21:37:54Z</wsu:Expires> + </wsu:Timestamp> + </wsse:Security> + </soap:Header> + <soap:Body> + <UpdateResponse xmlns="http://exacttarget.com/wsdl/partnerAPI"> + <Results> + <StatusCode>OK</StatusCode> + <StatusMessage>SendClassification updated</StatusMessage> + <OrdinalID>0</OrdinalID> + <Object xsi:type="SendClassification"> + <PartnerKey xsi:nil="true" /> + <ObjectID>95da425b-a06f-e611-96fe-38eaa7142c61</ObjectID> + <CustomerKey>testExisting_sendClassification</CustomerKey> + <SendClassificationType>Marketing</SendClassificationType> + <Name>testExisting_sendClassification</Name> + <Description>updated on deploy</Description> + <SenderProfile> + <PartnerKey xsi:nil="true" /> + <ObjectID>a75d452b-7ef4-eb11-b82d-48df37d1da95</ObjectID> + <CustomerKey>testExisting_senderProfile</CustomerKey> + </SenderProfile> + <DeliveryProfile> + <PartnerKey xsi:nil="true" /> + <ObjectID xsi:nil="true" /> + <CustomerKey>Default</CustomerKey> + </DeliveryProfile> + </Object> + </Results> + <RequestID>0ff3e991-df4f-4206-b8e1-bdccf95d3931</RequestID> + <OverallStatus>OK</OverallStatus> + </UpdateResponse> + </soap:Body> +</soap:Envelope> diff --git a/test/resources/9999999/senderProfile/build-expected.json b/test/resources/9999999/senderProfile/build-expected.json new file mode 100644 index 000000000..94cebe962 --- /dev/null +++ b/test/resources/9999999/senderProfile/build-expected.json @@ -0,0 +1,15 @@ +{ + "FallbackFromAddress": "joern.berkefeld+test@accenture.com", + "AutoForwardToEmailAddress": "", + "AutoForwardToName": "", + "AutoReply": false, + "CustomerKey": "testTemplated_senderProfile", + "Description": "Send from joern.berkefeld@accenture.com", + "DirectForward": false, + "FromAddress": "joern.berkefeld@accenture.com", + "FromName": "Jörn Berkefeld", + "Name": "testTemplated_senderProfile", + "SenderHeaderEmailAddress": "", + "SenderHeaderName": "", + "UseDefaultRMMRules": true +} diff --git a/test/resources/9999999/senderProfile/create-response.xml b/test/resources/9999999/senderProfile/create-response.xml new file mode 100644 index 000000000..eed10292c --- /dev/null +++ b/test/resources/9999999/senderProfile/create-response.xml @@ -0,0 +1,50 @@ +<?xml version="1.0" encoding="utf-8"?> +<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:xsd="http://www.w3.org/2001/XMLSchema" + xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing" + xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" + xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"> + <soap:Header> + <wsa:Action>CreateResponse</wsa:Action> + <wsa:MessageID>urn:uuid:da5fb2ee-2ca9-4f56-a9e8-2b98d43379f7</wsa:MessageID> + <wsa:RelatesTo>urn:uuid:3cbd2577-f0e6-4593-8657-e1f48d94624c</wsa:RelatesTo> + <wsa:To>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</wsa:To> + <wsse:Security> + <wsu:Timestamp wsu:Id="Timestamp-8768684a-59c7-44f4-977e-3a4e44db441d"> + <wsu:Created>2024-04-12T12:53:28Z</wsu:Created> + <wsu:Expires>2024-04-12T12:58:28Z</wsu:Expires> + </wsu:Timestamp> + </wsse:Security> + </soap:Header> + <soap:Body> + <CreateResponse xmlns="http://exacttarget.com/wsdl/partnerAPI"> + <Results> + <StatusCode>OK</StatusCode> + <StatusMessage>SenderProfile created</StatusMessage> + <OrdinalID>0</OrdinalID> + <NewID>0</NewID> + <NewObjectID>70accba4-cbf8-ee11-a5c8-5cba2c6fc270</NewObjectID> + <Object xsi:type="SenderProfile"> + <PartnerKey xsi:nil="true" /> + <ObjectID>70accba4-cbf8-ee11-a5c8-5cba2c6fc270</ObjectID> + <CustomerKey>testNew_senderProfile</CustomerKey> + <Name>testNew_senderProfile</Name> + <Description>created on deploy</Description> + <FromName>Jörn Berkefeld</FromName> + <FromAddress>joern.berkefeld@accenture.com</FromAddress> + <UseDefaultRMMRules>false</UseDefaultRMMRules> + <AutoForwardToEmailAddress>joern.berkefeld@accenture.com</AutoForwardToEmailAddress> + <AutoForwardToName>Jörn Berkefeld</AutoForwardToName> + <DirectForward>false</DirectForward> + <AutoReply>false</AutoReply> + <SenderHeaderEmailAddress /> + <SenderHeaderName /> + <FallbackFromAddress>joern.berkefeld.New@accenture.com</FallbackFromAddress> + </Object> + </Results> + <RequestID>b6be1480-01a4-4e48-9f47-06bf51a301c1</RequestID> + <OverallStatus>OK</OverallStatus> + </CreateResponse> + </soap:Body> +</soap:Envelope> diff --git a/test/resources/9999999/senderProfile/delete-response.xml b/test/resources/9999999/senderProfile/delete-response.xml new file mode 100644 index 000000000..2be198379 --- /dev/null +++ b/test/resources/9999999/senderProfile/delete-response.xml @@ -0,0 +1,36 @@ +<?xml version="1.0" encoding="utf-8"?> +<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:xsd="http://www.w3.org/2001/XMLSchema" + xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing" + xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" + xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"> + <soap:Header> + <wsa:Action>DeleteResponse</wsa:Action> + <wsa:MessageID>urn:uuid:9d089538-9132-421c-b905-827dc760447b</wsa:MessageID> + <wsa:RelatesTo>urn:uuid:2dbd051c-b714-4302-bb66-53d0916620ed</wsa:RelatesTo> + <wsa:To>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</wsa:To> + <wsse:Security> + <wsu:Timestamp wsu:Id="Timestamp-c7ba7ffe-ac41-4cb7-a0a1-471df321d8a6"> + <wsu:Created>2024-04-12T13:05:55Z</wsu:Created> + <wsu:Expires>2024-04-12T13:10:55Z</wsu:Expires> + </wsu:Timestamp> + </wsse:Security> + </soap:Header> + <soap:Body> + <DeleteResponse xmlns="http://exacttarget.com/wsdl/partnerAPI"> + <Results> + <StatusCode>OK</StatusCode> + <StatusMessage>SenderProfile deleted</StatusMessage> + <OrdinalID>0</OrdinalID> + <Object xsi:type="SenderProfile"> + <PartnerKey xsi:nil="true" /> + <ObjectID xsi:nil="true" /> + <CustomerKey>testExisting_senderProfile</CustomerKey> + </Object> + </Results> + <RequestID>0387ba17-c330-4239-a2dd-c0e15f968476</RequestID> + <OverallStatus>OK</OverallStatus> + </DeleteResponse> + </soap:Body> +</soap:Envelope> diff --git a/test/resources/9999999/senderProfile/get-expected.json b/test/resources/9999999/senderProfile/get-expected.json new file mode 100644 index 000000000..3077c0735 --- /dev/null +++ b/test/resources/9999999/senderProfile/get-expected.json @@ -0,0 +1,19 @@ +{ + "FallbackFromAddress": "joern.berkefeld+test@accenture.com", + "CreatedDate": "2021-08-03T11:14:00", + "ModifiedDate": "2021-08-03T11:14:00", + "CustomerKey": "testExisting_senderProfile", + "Name": "testExisting_senderProfile", + "Description": "Send from joern.berkefeld@accenture.com", + "FromName": "Jörn Berkefeld", + "FromAddress": "joern.berkefeld@accenture.com", + "UseDefaultRMMRules": true, + "AutoForwardToEmailAddress": "", + "AutoForwardToName": "", + "DirectForward": false, + "AutoReply": false, + "SenderHeaderEmailAddress": "", + "SenderHeaderName": "", + "createdBy": "Jörn Berkefeld", + "modifiedBy": "Jörn Berkefeld" +} diff --git a/test/resources/9999999/senderProfile/get-rcb-id-expected.json b/test/resources/9999999/senderProfile/get-rcb-id-expected.json new file mode 100644 index 000000000..ca842db58 --- /dev/null +++ b/test/resources/9999999/senderProfile/get-rcb-id-expected.json @@ -0,0 +1,19 @@ +{ + "FallbackFromAddress": "", + "createdBy": "Jörn Berkefeld", + "modifiedBy": "Jörn Berkefeld", + "CreatedDate": "2021-08-03T11:14:00", + "ModifiedDate": "2021-08-03T11:14:00", + "CustomerKey": "testExisting_senderProfile_rcb", + "Name": "testExisting_senderProfile_rcb", + "Description": "Send from joern.berkefeld@accenture.com", + "FromName": "%%= ContentBlockById(1295064) =%%", + "FromAddress": "%%= ContentBlockById(1295064) =%%", + "UseDefaultRMMRules": true, + "AutoForwardToEmailAddress": "%%= ContentBlockById(1295064) =%%", + "AutoForwardToName": "%%= ContentBlockById(1295064) =%%", + "DirectForward": false, + "AutoReply": false, + "SenderHeaderEmailAddress": "", + "SenderHeaderName": "" +} diff --git a/test/resources/9999999/senderProfile/get-rcb-key-expected.json b/test/resources/9999999/senderProfile/get-rcb-key-expected.json new file mode 100644 index 000000000..8f77617bf --- /dev/null +++ b/test/resources/9999999/senderProfile/get-rcb-key-expected.json @@ -0,0 +1,19 @@ +{ + "FallbackFromAddress": "", + "createdBy": "Jörn Berkefeld", + "modifiedBy": "Jörn Berkefeld", + "CreatedDate": "2021-08-03T11:14:00", + "ModifiedDate": "2021-08-03T11:14:00", + "CustomerKey": "testExisting_senderProfile_rcb", + "Name": "testExisting_senderProfile_rcb", + "Description": "Send from joern.berkefeld@accenture.com", + "FromName": "%%= ContentBlockByKey(\"testExisting_asset_htmlblock\") =%%", + "FromAddress": "%%= ContentBlockByKey(\"testExisting_asset_htmlblock\") =%%", + "UseDefaultRMMRules": true, + "AutoForwardToEmailAddress": "%%= ContentBlockByKey(\"testExisting_asset_htmlblock\") =%%", + "AutoForwardToName": "%%= ContentBlockByKey(\"testExisting_asset_htmlblock\") =%%", + "DirectForward": false, + "AutoReply": false, + "SenderHeaderEmailAddress": "", + "SenderHeaderName": "" +} diff --git a/test/resources/9999999/senderProfile/get-rcb-name-expected.json b/test/resources/9999999/senderProfile/get-rcb-name-expected.json new file mode 100644 index 000000000..b1e61103d --- /dev/null +++ b/test/resources/9999999/senderProfile/get-rcb-name-expected.json @@ -0,0 +1,19 @@ +{ + "FallbackFromAddress": "", + "createdBy": "Jörn Berkefeld", + "modifiedBy": "Jörn Berkefeld", + "CreatedDate": "2021-08-03T11:14:00", + "ModifiedDate": "2021-08-03T11:14:00", + "CustomerKey": "testExisting_senderProfile_rcb", + "Name": "testExisting_senderProfile_rcb", + "Description": "Send from joern.berkefeld@accenture.com", + "FromName": "%%= ContentBlockByName(\"Content Builder\\dont strip non ssjs content\") =%%", + "FromAddress": "%%= ContentBlockByName(\"Content Builder\\dont strip non ssjs content\") =%%", + "UseDefaultRMMRules": true, + "AutoForwardToEmailAddress": "%%= ContentBlockByName(\"Content Builder\\dont strip non ssjs content\") =%%", + "AutoForwardToName": "%%= ContentBlockByName(\"Content Builder\\dont strip non ssjs content\") =%%", + "DirectForward": false, + "AutoReply": false, + "SenderHeaderEmailAddress": "", + "SenderHeaderName": "" +} diff --git a/test/resources/9999999/senderProfile/patch-expected.json b/test/resources/9999999/senderProfile/patch-expected.json new file mode 100644 index 000000000..3077c0735 --- /dev/null +++ b/test/resources/9999999/senderProfile/patch-expected.json @@ -0,0 +1,19 @@ +{ + "FallbackFromAddress": "joern.berkefeld+test@accenture.com", + "CreatedDate": "2021-08-03T11:14:00", + "ModifiedDate": "2021-08-03T11:14:00", + "CustomerKey": "testExisting_senderProfile", + "Name": "testExisting_senderProfile", + "Description": "Send from joern.berkefeld@accenture.com", + "FromName": "Jörn Berkefeld", + "FromAddress": "joern.berkefeld@accenture.com", + "UseDefaultRMMRules": true, + "AutoForwardToEmailAddress": "", + "AutoForwardToName": "", + "DirectForward": false, + "AutoReply": false, + "SenderHeaderEmailAddress": "", + "SenderHeaderName": "", + "createdBy": "Jörn Berkefeld", + "modifiedBy": "Jörn Berkefeld" +} diff --git a/test/resources/9999999/senderProfile/post-expected.json b/test/resources/9999999/senderProfile/post-expected.json new file mode 100644 index 000000000..0665c2790 --- /dev/null +++ b/test/resources/9999999/senderProfile/post-expected.json @@ -0,0 +1,15 @@ +{ + "FallbackFromAddress": "joern.berkefeld.New@accenture.com", + "AutoForwardToEmailAddress": "joern.berkefeld@accenture.com", + "AutoForwardToName": "Jörn Berkefeld", + "AutoReply": false, + "CustomerKey": "testNew_senderProfile", + "Description": "created on deploy", + "DirectForward": false, + "FromAddress": "joern.berkefeld@accenture.com", + "FromName": "Jörn Berkefeld", + "Name": "testNew_senderProfile", + "SenderHeaderEmailAddress": "", + "SenderHeaderName": "", + "UseDefaultRMMRules": false +} diff --git a/test/resources/9999999/senderProfile/retrieve-CustomerKey=Default-response.xml b/test/resources/9999999/senderProfile/retrieve-CustomerKey=Default-response.xml new file mode 100644 index 000000000..a4c1bbee7 --- /dev/null +++ b/test/resources/9999999/senderProfile/retrieve-CustomerKey=Default-response.xml @@ -0,0 +1,49 @@ +<?xml version="1.0" encoding="utf-8"?> +<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:xsd="http://www.w3.org/2001/XMLSchema" + xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing" + xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" + xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"> + <soap:Header> + <wsa:Action>RetrieveResponse</wsa:Action> + <wsa:MessageID>urn:uuid:cbecb68a-7bdf-417e-8fce-bef6c72febbd</wsa:MessageID> + <wsa:RelatesTo>urn:uuid:2e88f8d2-82e7-4e2d-b780-b885a2205a0f</wsa:RelatesTo> + <wsa:To>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</wsa:To> + <wsse:Security> + <wsu:Timestamp wsu:Id="Timestamp-ed420673-a71e-47b4-a2f4-4d4399b7e6a9"> + <wsu:Created>2024-04-12T12:20:37Z</wsu:Created> + <wsu:Expires>2024-04-12T12:25:37Z</wsu:Expires> + </wsu:Timestamp> + </wsse:Security> + </soap:Header> + <soap:Body> + <RetrieveResponseMsg xmlns="http://exacttarget.com/wsdl/partnerAPI"> + <OverallStatus>OK</OverallStatus> + <RequestID>4c6f37a1-7ab4-47a1-b341-f9912462ee97</RequestID> + <Results xsi:type="SenderProfile"> + <Client> + <CreatedBy>700301950</CreatedBy> + <ModifiedBy>700301950</ModifiedBy> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2016-07-22T11:53:00</CreatedDate> + <ModifiedDate>2016-07-22T11:53:00</ModifiedDate> + <ObjectID>7acfb80f-3550-e611-96fe-38eaa7142c61</ObjectID> + <CustomerKey>Default</CustomerKey> + <Name>Default</Name> + <Description>Account defaults</Description> + <FromName>Accenture</FromName> + <FromAddress>joern.berkefeld@accenture.com</FromAddress> + <UseDefaultRMMRules>true</UseDefaultRMMRules> + <AutoForwardToEmailAddress /> + <AutoForwardToName /> + <DirectForward>false</DirectForward> + <AutoReply>false</AutoReply> + <SenderHeaderEmailAddress /> + <SenderHeaderName /> + <FallbackFromAddress /> + </Results> + </RetrieveResponseMsg> + </soap:Body> +</soap:Envelope> diff --git a/test/resources/9999999/senderProfile/retrieve-CustomerKey=wrong-key-response.xml b/test/resources/9999999/senderProfile/retrieve-CustomerKey=wrong-key-response.xml new file mode 100644 index 000000000..e85b1c7a7 --- /dev/null +++ b/test/resources/9999999/senderProfile/retrieve-CustomerKey=wrong-key-response.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="utf-8"?> +<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:xsd="http://www.w3.org/2001/XMLSchema" + xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing" + xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" + xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"> + <soap:Header> + <wsa:Action>RetrieveResponse</wsa:Action> + <wsa:MessageID>urn:uuid:d88db970-f769-4bf0-b883-e019d4324499</wsa:MessageID> + <wsa:RelatesTo>urn:uuid:044b42db-b7c3-4286-be0c-b3420efb6c3a</wsa:RelatesTo> + <wsa:To>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</wsa:To> + <wsse:Security> + <wsu:Timestamp wsu:Id="Timestamp-346c69ce-29e8-4171-bb12-69bdd2a5c775"> + <wsu:Created>2024-04-23T16:10:56Z</wsu:Created> + <wsu:Expires>2024-04-23T16:15:56Z</wsu:Expires> + </wsu:Timestamp> + </wsse:Security> + </soap:Header> + <soap:Body> + <RetrieveResponseMsg xmlns="http://exacttarget.com/wsdl/partnerAPI"> + <OverallStatus>OK</OverallStatus> + <RequestID>4e5087e1-0ee3-4e6a-bd6f-76824abe451f</RequestID> + </RetrieveResponseMsg> + </soap:Body> +</soap:Envelope> diff --git a/test/resources/9999999/senderProfile/retrieve-response.xml b/test/resources/9999999/senderProfile/retrieve-response.xml new file mode 100644 index 000000000..80d34c5c1 --- /dev/null +++ b/test/resources/9999999/senderProfile/retrieve-response.xml @@ -0,0 +1,95 @@ +<?xml version="1.0" encoding="utf-8"?> +<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:xsd="http://www.w3.org/2001/XMLSchema" + xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing" + xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" + xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"> + <soap:Header> + <wsa:Action>RetrieveResponse</wsa:Action> + <wsa:MessageID>urn:uuid:cbecb68a-7bdf-417e-8fce-bef6c72febbd</wsa:MessageID> + <wsa:RelatesTo>urn:uuid:2e88f8d2-82e7-4e2d-b780-b885a2205a0f</wsa:RelatesTo> + <wsa:To>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</wsa:To> + <wsse:Security> + <wsu:Timestamp wsu:Id="Timestamp-ed420673-a71e-47b4-a2f4-4d4399b7e6a9"> + <wsu:Created>2024-04-12T12:20:37Z</wsu:Created> + <wsu:Expires>2024-04-12T12:25:37Z</wsu:Expires> + </wsu:Timestamp> + </wsse:Security> + </soap:Header> + <soap:Body> + <RetrieveResponseMsg xmlns="http://exacttarget.com/wsdl/partnerAPI"> + <OverallStatus>OK</OverallStatus> + <RequestID>4c6f37a1-7ab4-47a1-b341-f9912462ee97</RequestID> + <Results xsi:type="SenderProfile"> + <Client> + <CreatedBy>700301950</CreatedBy> + <ModifiedBy>700301950</ModifiedBy> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2016-07-22T11:53:00</CreatedDate> + <ModifiedDate>2016-07-22T11:53:00</ModifiedDate> + <ObjectID>7acfb80f-3550-e611-96fe-38eaa7142c61</ObjectID> + <CustomerKey>Default</CustomerKey> + <Name>Default</Name> + <Description>Account defaults</Description> + <FromName>Accenture</FromName> + <FromAddress>joern.berkefeld@accenture.com</FromAddress> + <UseDefaultRMMRules>true</UseDefaultRMMRules> + <AutoForwardToEmailAddress /> + <AutoForwardToName /> + <DirectForward>false</DirectForward> + <AutoReply>false</AutoReply> + <SenderHeaderEmailAddress /> + <SenderHeaderName /> + <FallbackFromAddress /> + </Results> + <Results xsi:type="SenderProfile"> + <Client> + <CreatedBy>700301950</CreatedBy> + <ModifiedBy>700301950</ModifiedBy> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2021-08-03T11:14:00</CreatedDate> + <ModifiedDate>2021-08-03T11:14:00</ModifiedDate> + <ObjectID>a75d452b-7ef4-eb11-b82d-48df37d1da95</ObjectID> + <CustomerKey>testExisting_senderProfile</CustomerKey> + <Name>testExisting_senderProfile</Name> + <Description>Send from joern.berkefeld@accenture.com</Description> + <FromName>Jörn Berkefeld</FromName> + <FromAddress>joern.berkefeld@accenture.com</FromAddress> + <UseDefaultRMMRules>true</UseDefaultRMMRules> + <AutoForwardToEmailAddress /> + <AutoForwardToName /> + <DirectForward>false</DirectForward> + <AutoReply>false</AutoReply> + <SenderHeaderEmailAddress /> + <SenderHeaderName /> + <FallbackFromAddress>joern.berkefeld+test@accenture.com</FallbackFromAddress> + </Results> + <Results xsi:type="SenderProfile"> + <Client> + <CreatedBy>700301950</CreatedBy> + <ModifiedBy>700301950</ModifiedBy> + </Client> + <PartnerKey xsi:nil="true" /> + <CreatedDate>2021-08-03T11:14:00</CreatedDate> + <ModifiedDate>2021-08-03T11:14:00</ModifiedDate> + <ObjectID>a75d452b-7ef4-eb11-b82d-48df37d1da99</ObjectID> + <CustomerKey>testExisting_senderProfile_rcb</CustomerKey> + <Name>testExisting_senderProfile_rcb</Name> + <Description>Send from joern.berkefeld@accenture.com</Description> + <FromName>%%= ContentBlockByName("Content Builder\dont strip non ssjs content") =%%</FromName> + <FromAddress>%%= ContentBlockByKey("testExisting_asset_htmlblock") =%%</FromAddress> + <UseDefaultRMMRules>true</UseDefaultRMMRules> + <AutoForwardToEmailAddress>%%= ContentBlockById(1295064) =%%</AutoForwardToEmailAddress> + <AutoForwardToName>%%= ContentBlockById(1295064) =%%</AutoForwardToName> + <DirectForward>false</DirectForward> + <AutoReply>false</AutoReply> + <SenderHeaderEmailAddress /> + <SenderHeaderName /> + <FallbackFromAddress /> + </Results> + </RetrieveResponseMsg> + </soap:Body> +</soap:Envelope> diff --git a/test/resources/9999999/senderProfile/template-expected.json b/test/resources/9999999/senderProfile/template-expected.json new file mode 100644 index 000000000..c113a3a7f --- /dev/null +++ b/test/resources/9999999/senderProfile/template-expected.json @@ -0,0 +1,15 @@ +{ + "FallbackFromAddress": "joern.berkefeld+test@accenture.com", + "AutoForwardToEmailAddress": "", + "AutoForwardToName": "", + "AutoReply": false, + "CustomerKey": "{{{prefix}}}senderProfile", + "Description": "Send from joern.berkefeld@accenture.com", + "DirectForward": false, + "FromAddress": "joern.berkefeld@accenture.com", + "FromName": "Jörn Berkefeld", + "Name": "{{{prefix}}}senderProfile", + "SenderHeaderEmailAddress": "", + "SenderHeaderName": "", + "UseDefaultRMMRules": true +} diff --git a/test/resources/9999999/senderProfile/update-response.xml b/test/resources/9999999/senderProfile/update-response.xml new file mode 100644 index 000000000..3f34d69f6 --- /dev/null +++ b/test/resources/9999999/senderProfile/update-response.xml @@ -0,0 +1,48 @@ +<?xml version="1.0" encoding="utf-8"?> +<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:xsd="http://www.w3.org/2001/XMLSchema" + xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing" + xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" + xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"> + <soap:Header> + <wsa:Action>UpdateResponse</wsa:Action> + <wsa:MessageID>urn:uuid:4ba5314f-13c0-4fcf-a193-f6160531acd6</wsa:MessageID> + <wsa:RelatesTo>urn:uuid:4f56d229-63e7-4d8b-9bfe-1ace0c596056</wsa:RelatesTo> + <wsa:To>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</wsa:To> + <wsse:Security> + <wsu:Timestamp wsu:Id="Timestamp-224bd293-15f1-40fb-8a6f-f4ed6e2d6b16"> + <wsu:Created>2022-04-19T20:03:41Z</wsu:Created> + <wsu:Expires>2024-04-12T12:58:29Z</wsu:Expires> + </wsu:Timestamp> + </wsse:Security> + </soap:Header> + <soap:Body> + <UpdateResponse xmlns="http://exacttarget.com/wsdl/partnerAPI"> + <Results> + <StatusCode>OK</StatusCode> + <StatusMessage>SenderProfile updated</StatusMessage> + <OrdinalID>0</OrdinalID> + <Object xsi:type="SenderProfile"> + <PartnerKey xsi:nil="true" /> + <ObjectID xsi:nil="true" /> + <CustomerKey>testExisting_senderProfile</CustomerKey> + <Name>testExisting_senderProfile</Name> + <Description>updated via deploy</Description> + <FromName>Jörn Berkefeld</FromName> + <FromAddress>joern.berkefeld@accenture.com</FromAddress> + <UseDefaultRMMRules>false</UseDefaultRMMRules> + <AutoForwardToEmailAddress>joern.berkefeld@accenture.com</AutoForwardToEmailAddress> + <AutoForwardToName>Jörn Berkefeld</AutoForwardToName> + <DirectForward>false</DirectForward> + <AutoReply>false</AutoReply> + <SenderHeaderEmailAddress /> + <SenderHeaderName /> + <FallbackFromAddress /> + </Object> + </Results> + <RequestID>ef6e2933-b767-47ea-a1c4-d3dc44674a56</RequestID> + <OverallStatus>OK</OverallStatus> + </UpdateResponse> + </soap:Body> +</soap:Envelope> diff --git a/test/resources/9999999/transactionalEmail/build-expected.json b/test/resources/9999999/transactionalEmail/build-expected.json new file mode 100644 index 000000000..6204a7878 --- /dev/null +++ b/test/resources/9999999/transactionalEmail/build-expected.json @@ -0,0 +1,18 @@ +{ + "name": "testTemplated_temail", + "definitionKey": "testTemplated_temail", + "description": "foobar", + "status": "Active", + "subscriptions": { + "r__dataExtension_key": "testTemplated_dataExtension", + "autoAddSubscriber": true, + "updateSubscriber": true, + "r__list_PathName": "my subscribers/All Subscribers" + }, + "options": { + "trackLinks": true + }, + "r__asset_key": "testTemplated_asset_message", + "r__journey_key": "testTemplated_temail", + "r__sendClassification_key": "Default Transactional" +} diff --git a/test/resources/9999999/transactionalEmail/create-publish-expected.json b/test/resources/9999999/transactionalEmail/create-publish-expected.json new file mode 100644 index 000000000..4d74a6c6b --- /dev/null +++ b/test/resources/9999999/transactionalEmail/create-publish-expected.json @@ -0,0 +1,20 @@ +{ + "createdDate": "2024-08-23T02:01:00", + "definitionKey": "testNew_temail_notPublished", + "description": "testNew_temail_notPublis - 754cc4a10da14f538ecbd5470d771eaf", + "modifiedDate": "2024-08-23T02:01:00", + "name": "testNew_temail_notPublis - 754cc4a10da14f538ecbd5470d771eaf", + "options": { + "trackLinks": true + }, + "r__asset_key": "testExisting_asset_message", + "r__journey_key": "testNew_temail_notPublished", + "r__sendClassification_key": "testExisting_sendClassification", + "status": "Active", + "subscriptions": { + "autoAddSubscriber": true, + "r__dataExtension_key": "testExisting_dataExtension", + "r__list_PathName": "my subscribers/All Subscribers", + "updateSubscriber": true + } +} diff --git a/test/resources/9999999/transactionalEmail/get-expected.json b/test/resources/9999999/transactionalEmail/get-expected.json new file mode 100644 index 000000000..d6d1fef32 --- /dev/null +++ b/test/resources/9999999/transactionalEmail/get-expected.json @@ -0,0 +1,20 @@ +{ + "name": "testExisting_temail", + "definitionKey": "testExisting_temail", + "description": "bla bla", + "status": "Active", + "createdDate": "2020-09-10T03:29:00", + "modifiedDate": "2020-09-10T03:29:00", + "subscriptions": { + "r__dataExtension_key": "testExisting_dataExtension", + "autoAddSubscriber": true, + "updateSubscriber": true, + "r__list_PathName": "my subscribers/All Subscribers" + }, + "options": { + "trackLinks": true + }, + "r__asset_key": "testExisting_asset_message", + "r__journey_key": "testExisting_temail", + "r__sendClassification_key": "Default Transactional" +} diff --git a/test/resources/9999999/transactionalEmail/get-published-expected.json b/test/resources/9999999/transactionalEmail/get-published-expected.json new file mode 100644 index 000000000..099ebf484 --- /dev/null +++ b/test/resources/9999999/transactionalEmail/get-published-expected.json @@ -0,0 +1,20 @@ +{ + "createdDate": "2024-08-23T02:01:00", + "definitionKey": "testExisting_temail_notPublished", + "description": "testExisting_temail_notPublis - 754cc4a10da14f538ecbd5470d771eaf", + "modifiedDate": "2024-08-23T02:01:00", + "name": "testExisting_temail_notPublis - 754cc4a10da14f538ecbd5470d771eaf", + "options": { + "trackLinks": true + }, + "r__asset_key": "testExisting_asset_message", + "r__journey_key": "testExisting_temail_notPublished", + "r__sendClassification_key": "Default Transactional", + "status": "Active", + "subscriptions": { + "autoAddSubscriber": true, + "r__dataExtension_key": "testExisting_temail_notPublished", + "r__list_PathName": "my subscribers/All Subscribers", + "updateSubscriber": true + } +} diff --git a/test/resources/9999999/transactionalEmail/patch-expected.json b/test/resources/9999999/transactionalEmail/patch-expected.json new file mode 100644 index 000000000..cba7dd41c --- /dev/null +++ b/test/resources/9999999/transactionalEmail/patch-expected.json @@ -0,0 +1,20 @@ +{ + "name": "testExisting_temail", + "definitionKey": "testExisting_temail", + "description": "updated via deploy", + "status": "Active", + "createdDate": "2020-09-10T03:29:00", + "modifiedDate": "2020-09-10T03:29:00", + "subscriptions": { + "r__dataExtension_key": "testExisting_dataExtension", + "autoAddSubscriber": true, + "updateSubscriber": true, + "r__list_PathName": "my subscribers/All Subscribers" + }, + "options": { + "trackLinks": true + }, + "r__asset_key": "testExisting_asset_message", + "r__journey_key": "testExisting_temail", + "r__sendClassification_key": "Default Transactional" +} diff --git a/test/resources/9999999/transactionalEmail/post-expected.json b/test/resources/9999999/transactionalEmail/post-expected.json new file mode 100644 index 000000000..5316962fc --- /dev/null +++ b/test/resources/9999999/transactionalEmail/post-expected.json @@ -0,0 +1,20 @@ +{ + "name": "testNew_temail", + "definitionKey": "testNew_temail", + "description": "created on deploy", + "status": "Active", + "createdDate": "2022-12-06T06:08:00", + "modifiedDate": "2022-12-06T06:08:00", + "subscriptions": { + "r__dataExtension_key": "testExisting_dataExtension", + "autoAddSubscriber": true, + "updateSubscriber": true, + "r__list_PathName": "my subscribers/All Subscribers" + }, + "options": { + "trackLinks": true + }, + "r__asset_key": "testExisting_asset_message", + "r__journey_key": "testNew_RANDOM_interaction", + "r__sendClassification_key": "Default Transactional" +} diff --git a/test/resources/9999999/transactionalEmail/template-expected.json b/test/resources/9999999/transactionalEmail/template-expected.json new file mode 100644 index 000000000..37b397bb2 --- /dev/null +++ b/test/resources/9999999/transactionalEmail/template-expected.json @@ -0,0 +1,18 @@ +{ + "name": "{{{prefix}}}temail", + "definitionKey": "{{{prefix}}}temail", + "description": "{{{description}}}", + "status": "Active", + "subscriptions": { + "r__dataExtension_key": "{{{prefix}}}dataExtension", + "autoAddSubscriber": true, + "updateSubscriber": true, + "r__list_PathName": "my subscribers/All Subscribers" + }, + "options": { + "trackLinks": true + }, + "r__asset_key": "{{{prefix}}}asset_message", + "r__journey_key": "{{{prefix}}}temail", + "r__sendClassification_key": "Default Transactional" +} diff --git a/test/resources/9999999/transactionalPush/build-expected.json b/test/resources/9999999/transactionalPush/build-expected.json new file mode 100644 index 000000000..3397223c9 --- /dev/null +++ b/test/resources/9999999/transactionalPush/build-expected.json @@ -0,0 +1,8 @@ +{ + "name": "testTemplated_tpush", + "definitionKey": "testTemplated_tpush", + "description": "foobar. note that applicationId can only be manually set up in Setup - Mobile Push", + "applicationId": "ffbab4c9-fbf6-4b87-9c9a-10c6ce86e81d", + "r__asset_key": "mobileMessage_testTarget", + "options": { "sound": "temp.wmv", "badge": "1" } +} diff --git a/test/resources/9999999/transactionalPush/get-expected.json b/test/resources/9999999/transactionalPush/get-expected.json new file mode 100644 index 000000000..443dd8e0f --- /dev/null +++ b/test/resources/9999999/transactionalPush/get-expected.json @@ -0,0 +1,11 @@ +{ + "name": "testExisting_tpush", + "definitionKey": "testExisting_tpush", + "description": "bla bla. note that applicationId can only be manually set up in Setup - Mobile Push", + "applicationId": "ffbab4c9-fbf6-4b87-9c9a-10c6ce86e81d", + "status": "Active", + "createdDate": "2022-12-07T02:56:00", + "modifiedDate": "2022-12-07T02:56:00", + "r__asset_key": "mobileMessage_test", + "options": { "sound": "temp.wmv", "badge": "1" } +} diff --git a/test/resources/9999999/transactionalPush/patch-expected.json b/test/resources/9999999/transactionalPush/patch-expected.json new file mode 100644 index 000000000..c36cff58b --- /dev/null +++ b/test/resources/9999999/transactionalPush/patch-expected.json @@ -0,0 +1,14 @@ +{ + "definitionKey": "testExisting_tpush", + "name": "testExisting_tpush", + "status": "Active", + "applicationId": "ffbab4c9-fbf6-4b87-9c9a-10c6ce86e81d", + "description": "updated via deploy; note that applicationId can only be manually set up in Setup - Mobile Push", + "createdDate": "2022-12-07T02:56:00", + "modifiedDate": "2022-12-07T03:26:00", + "r__asset_key": "mobileMessage_test", + "options": { + "sound": "temp.wmv", + "badge": "1" + } +} diff --git a/test/resources/9999999/transactionalPush/post-expected.json b/test/resources/9999999/transactionalPush/post-expected.json new file mode 100644 index 000000000..5f662aff8 --- /dev/null +++ b/test/resources/9999999/transactionalPush/post-expected.json @@ -0,0 +1,14 @@ +{ + "definitionKey": "testNew_tpush", + "name": "testNew_tpush", + "status": "Active", + "applicationId": "ffbab4c9-fbf6-4b87-9c9a-10c6ce86e81d", + "description": "created on deploy; note that applicationId can only be manually set up in Setup - Mobile Push", + "createdDate": "2022-12-07T02:56:00", + "modifiedDate": "2022-12-07T03:26:00", + "r__asset_key": "mobileMessage_test", + "options": { + "sound": "temp.wmv", + "badge": "1" + } +} diff --git a/test/resources/9999999/transactionalPush/template-expected.json b/test/resources/9999999/transactionalPush/template-expected.json new file mode 100644 index 000000000..526267021 --- /dev/null +++ b/test/resources/9999999/transactionalPush/template-expected.json @@ -0,0 +1,8 @@ +{ + "name": "{{{prefix}}}tpush", + "definitionKey": "{{{prefix}}}tpush", + "description": "{{{description}}}. note that applicationId can only be manually set up in Setup - Mobile Push", + "applicationId": "ffbab4c9-fbf6-4b87-9c9a-10c6ce86e81d", + "r__asset_key": "mobileMessage{{{suffix}}}", + "options": { "sound": "temp.wmv", "badge": "1" } +} diff --git a/test/resources/9999999/transactionalSMS/build-expected.amp b/test/resources/9999999/transactionalSMS/build-expected.amp new file mode 100644 index 000000000..cdf0c6b39 --- /dev/null +++ b/test/resources/9999999/transactionalSMS/build-expected.amp @@ -0,0 +1,108 @@ +line1 +%%[ + SET @test = 'foobar' +]%% +line2 %%= v(@test) =%% still line2 +line3 +%%[ + SET @key = 'target secret' +]%% + +%%[ + SET @unsubMessages = 'UnsubscribeSMSMessages_DEV' + SET @unsubEvents = 'UnsubscribeSMS_DEV' + SET @num = concat('+', [MOBILE_NUMBER]) + SET @rs = RetrieveSalesforceObjects( + 'Contact', + 'Id,et4ae5__HasOptedOutOfMobile__c', + 'MobilePhone', + '=', + @num + ) + SET @count = rowCount(@rs) + VAR @response + SET @rx = '^\+((?:9[679]\d8[035789]\d|6[789]\d|5[90]\d|42\d|3[578]\d|2[1-689]\d)|9[0-58]|8[1246]|6[0-6]|5[1-8]|4[013-9]|3[0-469]|2[70]|7|1)' + SET @prefix = concat('+', RegExMatch(@num, @rx, 1)) + IF @count>0 THEN + FOR @i = 1 TO @count DO + SET @sk = Field(Row(@rs, @i), 'Id') + IF Field(Row(@rs, 1), 'et4ae5__HasOptedOutOfMobile__c') == 'false' THEN + SET @result = UpdateSingleSalesforceObject('Contact', @sk, 'et4ae5__HasOptedOutOfMobile__c', 'true') + IF @result == 0 THEN + InsertData( + @unsubEvents, + 'MobileNumber', + @num, + 'Message', + [MSG(0).NOUNS], + 'ContactId', + @sk, + 'Status', + 'Error Updating' + ) + ELSE + InsertData( + @unsubEvents, + 'MobileNumber', + @num, + 'Message', + [MSG(0).NOUNS], + 'ContactId', + @sk, + 'Status', + 'Successfully Unsubscribed' + ) + ENDIF + ELSE + InsertData( + @unsubEvents, + 'MobileNumber', + @num, + 'Message', + [MSG(0).NOUNS], + 'ContactId', + @sk, + 'Status', + 'Already Unsubscribed' + ) + ENDIF + NEXT @i + SET @msg = Lookup( + @unsubMessages, + 'Message', + 'Prefix', + @prefix, + 'Type', + 'Found' + ) + IF Length(@msg) == 0 THEN + SET @response = 'You have unsubscribed and will no longer receive any messages.|' + ELSE + SET @response = @msg + ENDIF + ELSE + InsertData( + @unsubEvents, + 'MobileNumber', + @num, + 'Message', + [MSG(0).NOUNS], + 'Status', + 'Not Found' + ) + SET @msg = Lookup( + @unsubMessages, + 'Message', + 'Prefix', + @prefix, + 'Type', + 'NotFound' + ) + IF Length(@msg) == 0 THEN + SET @response = 'Sorry, we could not find you' + ELSE + SET @response = @msg + ENDIF + ENDIF +]%% +%%=v(@response)=%% diff --git a/test/resources/9999999/transactionalSMS/build-expected.json b/test/resources/9999999/transactionalSMS/build-expected.json new file mode 100644 index 000000000..813e86ab5 --- /dev/null +++ b/test/resources/9999999/transactionalSMS/build-expected.json @@ -0,0 +1,12 @@ +{ + "name": "testTemplated_tsms", + "definitionKey": "testTemplated_tsms", + "description": "foobar", + "status": "Active", + "subscriptions": { + "countryCode": "", + "autoAddSubscriber": true, + "updateSubscriber": true, + "r__mobileKeyword_key": "4912312345678.TESTTEMPLATED_KEYWORD" + } +} diff --git a/test/resources/9999999/transactionalSMS/get-expected.amp b/test/resources/9999999/transactionalSMS/get-expected.amp new file mode 100644 index 000000000..47307e6c5 --- /dev/null +++ b/test/resources/9999999/transactionalSMS/get-expected.amp @@ -0,0 +1,108 @@ +line1 +%%[ + SET @test = 'bla bla' +]%% +line2 %%= v(@test) =%% still line2 +line3 +%%[ + SET @key = 'secret' +]%% + +%%[ + SET @unsubMessages = 'UnsubscribeSMSMessages_DEV' + SET @unsubEvents = 'UnsubscribeSMS_DEV' + SET @num = concat('+', [MOBILE_NUMBER]) + SET @rs = RetrieveSalesforceObjects( + 'Contact', + 'Id,et4ae5__HasOptedOutOfMobile__c', + 'MobilePhone', + '=', + @num + ) + SET @count = rowCount(@rs) + VAR @response + SET @rx = '^\+((?:9[679]\d8[035789]\d|6[789]\d|5[90]\d|42\d|3[578]\d|2[1-689]\d)|9[0-58]|8[1246]|6[0-6]|5[1-8]|4[013-9]|3[0-469]|2[70]|7|1)' + SET @prefix = concat('+', RegExMatch(@num, @rx, 1)) + IF @count>0 THEN + FOR @i = 1 TO @count DO + SET @sk = Field(Row(@rs, @i), 'Id') + IF Field(Row(@rs, 1), 'et4ae5__HasOptedOutOfMobile__c') == 'false' THEN + SET @result = UpdateSingleSalesforceObject('Contact', @sk, 'et4ae5__HasOptedOutOfMobile__c', 'true') + IF @result == 0 THEN + InsertData( + @unsubEvents, + 'MobileNumber', + @num, + 'Message', + [MSG(0).NOUNS], + 'ContactId', + @sk, + 'Status', + 'Error Updating' + ) + ELSE + InsertData( + @unsubEvents, + 'MobileNumber', + @num, + 'Message', + [MSG(0).NOUNS], + 'ContactId', + @sk, + 'Status', + 'Successfully Unsubscribed' + ) + ENDIF + ELSE + InsertData( + @unsubEvents, + 'MobileNumber', + @num, + 'Message', + [MSG(0).NOUNS], + 'ContactId', + @sk, + 'Status', + 'Already Unsubscribed' + ) + ENDIF + NEXT @i + SET @msg = Lookup( + @unsubMessages, + 'Message', + 'Prefix', + @prefix, + 'Type', + 'Found' + ) + IF Length(@msg) == 0 THEN + SET @response = 'You have unsubscribed and will no longer receive any messages.|' + ELSE + SET @response = @msg + ENDIF + ELSE + InsertData( + @unsubEvents, + 'MobileNumber', + @num, + 'Message', + [MSG(0).NOUNS], + 'Status', + 'Not Found' + ) + SET @msg = Lookup( + @unsubMessages, + 'Message', + 'Prefix', + @prefix, + 'Type', + 'NotFound' + ) + IF Length(@msg) == 0 THEN + SET @response = 'Sorry, we could not find you' + ELSE + SET @response = @msg + ENDIF + ENDIF +]%% +%%=v(@response)=%% diff --git a/test/resources/9999999/transactionalSMS/get-expected.json b/test/resources/9999999/transactionalSMS/get-expected.json new file mode 100644 index 000000000..5d2a9a074 --- /dev/null +++ b/test/resources/9999999/transactionalSMS/get-expected.json @@ -0,0 +1,14 @@ +{ + "name": "testExisting_tsms", + "definitionKey": "testExisting_tsms", + "description": "bla bla", + "status": "Active", + "createdDate": "2022-11-07T02:24:00", + "modifiedDate": "2022-11-07T02:25:00", + "subscriptions": { + "countryCode": "", + "autoAddSubscriber": true, + "updateSubscriber": true, + "r__mobileKeyword_key": "4912312345678.TESTEXISTING_KEYWORD" + } +} diff --git a/test/resources/9999999/transactionalSMS/patch-expected.amp b/test/resources/9999999/transactionalSMS/patch-expected.amp new file mode 100644 index 000000000..9c94b4199 --- /dev/null +++ b/test/resources/9999999/transactionalSMS/patch-expected.amp @@ -0,0 +1,102 @@ +%%[ + SET @key = 'secret' +]%% + +%%[ + SET @unsubMessages = 'UnsubscribeSMSMessages_DEV' + SET @unsubEvents = 'UnsubscribeSMS_DEV' + SET @num = concat('+', [MOBILE_NUMBER]) + SET @rs = RetrieveSalesforceObjects( + 'Contact', + 'Id,et4ae5__HasOptedOutOfMobile__c', + 'MobilePhone', + '=', + @num + ) + SET @count = rowCount(@rs) + VAR @response + SET @rx = '^\+((?:9[679]\d8[035789]\d|6[789]\d|5[90]\d|42\d|3[578]\d|2[1-689]\d)|9[0-58]|8[1246]|6[0-6]|5[1-8]|4[013-9]|3[0-469]|2[70]|7|1)' + SET @prefix = concat('+', RegExMatch(@num, @rx, 1)) + IF @count>0 THEN + FOR @i = 1 TO @count DO + SET @sk = Field(Row(@rs, @i), 'Id') + IF Field(Row(@rs, 1), 'et4ae5__HasOptedOutOfMobile__c') == 'false' THEN + SET @result = UpdateSingleSalesforceObject('Contact', @sk, 'et4ae5__HasOptedOutOfMobile__c', 'true') + IF @result == 0 THEN + InsertData( + @unsubEvents, + 'MobileNumber', + @num, + 'Message', + [MSG(0).NOUNS], + 'ContactId', + @sk, + 'Status', + 'Error Updating' + ) + ELSE + InsertData( + @unsubEvents, + 'MobileNumber', + @num, + 'Message', + [MSG(0).NOUNS], + 'ContactId', + @sk, + 'Status', + 'Successfully Unsubscribed' + ) + ENDIF + ELSE + InsertData( + @unsubEvents, + 'MobileNumber', + @num, + 'Message', + [MSG(0).NOUNS], + 'ContactId', + @sk, + 'Status', + 'Already Unsubscribed' + ) + ENDIF + NEXT @i + SET @msg = Lookup( + @unsubMessages, + 'Message', + 'Prefix', + @prefix, + 'Type', + 'Found' + ) + IF Length(@msg) == 0 THEN + SET @response = 'You have unsubscribed and will no longer receive any messages.|' + ELSE + SET @response = @msg + ENDIF + ELSE + InsertData( + @unsubEvents, + 'MobileNumber', + @num, + 'Message', + [MSG(0).NOUNS], + 'Status', + 'Not Found' + ) + SET @msg = Lookup( + @unsubMessages, + 'Message', + 'Prefix', + @prefix, + 'Type', + 'NotFound' + ) + IF Length(@msg) == 0 THEN + SET @response = 'Sorry, we could not find you' + ELSE + SET @response = @msg + ENDIF + ENDIF +]%% +%%=v(@response)=%% diff --git a/test/resources/9999999/transactionalSMS/patch-expected.json b/test/resources/9999999/transactionalSMS/patch-expected.json new file mode 100644 index 000000000..5d2a9a074 --- /dev/null +++ b/test/resources/9999999/transactionalSMS/patch-expected.json @@ -0,0 +1,14 @@ +{ + "name": "testExisting_tsms", + "definitionKey": "testExisting_tsms", + "description": "bla bla", + "status": "Active", + "createdDate": "2022-11-07T02:24:00", + "modifiedDate": "2022-11-07T02:25:00", + "subscriptions": { + "countryCode": "", + "autoAddSubscriber": true, + "updateSubscriber": true, + "r__mobileKeyword_key": "4912312345678.TESTEXISTING_KEYWORD" + } +} diff --git a/test/resources/9999999/transactionalSMS/post-expected.amp b/test/resources/9999999/transactionalSMS/post-expected.amp new file mode 100644 index 000000000..a211011bd --- /dev/null +++ b/test/resources/9999999/transactionalSMS/post-expected.amp @@ -0,0 +1,102 @@ +%%[ + SET @key = 'new secret' +]%% + +%%[ + SET @unsubMessages = 'UnsubscribeSMSMessages_DEV' + SET @unsubEvents = 'UnsubscribeSMS_DEV' + SET @num = concat('+', [MOBILE_NUMBER]) + SET @rs = RetrieveSalesforceObjects( + 'Contact', + 'Id,et4ae5__HasOptedOutOfMobile__c', + 'MobilePhone', + '=', + @num + ) + SET @count = rowCount(@rs) + VAR @response + SET @rx = '^\+((?:9[679]\d8[035789]\d|6[789]\d|5[90]\d|42\d|3[578]\d|2[1-689]\d)|9[0-58]|8[1246]|6[0-6]|5[1-8]|4[013-9]|3[0-469]|2[70]|7|1)' + SET @prefix = concat('+', RegExMatch(@num, @rx, 1)) + IF @count>0 THEN + FOR @i = 1 TO @count DO + SET @sk = Field(Row(@rs, @i), 'Id') + IF Field(Row(@rs, 1), 'et4ae5__HasOptedOutOfMobile__c') == 'false' THEN + SET @result = UpdateSingleSalesforceObject('Contact', @sk, 'et4ae5__HasOptedOutOfMobile__c', 'true') + IF @result == 0 THEN + InsertData( + @unsubEvents, + 'MobileNumber', + @num, + 'Message', + [MSG(0).NOUNS], + 'ContactId', + @sk, + 'Status', + 'Error Updating' + ) + ELSE + InsertData( + @unsubEvents, + 'MobileNumber', + @num, + 'Message', + [MSG(0).NOUNS], + 'ContactId', + @sk, + 'Status', + 'Successfully Unsubscribed' + ) + ENDIF + ELSE + InsertData( + @unsubEvents, + 'MobileNumber', + @num, + 'Message', + [MSG(0).NOUNS], + 'ContactId', + @sk, + 'Status', + 'Already Unsubscribed' + ) + ENDIF + NEXT @i + SET @msg = Lookup( + @unsubMessages, + 'Message', + 'Prefix', + @prefix, + 'Type', + 'Found' + ) + IF Length(@msg) == 0 THEN + SET @response = 'You have unsubscribed and will no longer receive any messages.|' + ELSE + SET @response = @msg + ENDIF + ELSE + InsertData( + @unsubEvents, + 'MobileNumber', + @num, + 'Message', + [MSG(0).NOUNS], + 'Status', + 'Not Found' + ) + SET @msg = Lookup( + @unsubMessages, + 'Message', + 'Prefix', + @prefix, + 'Type', + 'NotFound' + ) + IF Length(@msg) == 0 THEN + SET @response = 'Sorry, we could not find you' + ELSE + SET @response = @msg + ENDIF + ENDIF +]%% +%%=v(@response)=%% diff --git a/test/resources/9999999/transactionalSMS/post-expected.json b/test/resources/9999999/transactionalSMS/post-expected.json new file mode 100644 index 000000000..196a92a35 --- /dev/null +++ b/test/resources/9999999/transactionalSMS/post-expected.json @@ -0,0 +1,14 @@ +{ + "name": "testNew_tsms", + "definitionKey": "testNew_tsms", + "description": "created on deploy", + "status": "Active", + "createdDate": "2022-11-07T02:24:00", + "modifiedDate": "2022-11-07T02:25:00", + "subscriptions": { + "countryCode": "", + "autoAddSubscriber": true, + "updateSubscriber": true, + "r__mobileKeyword_key": "4912312345678.TESTEXISTING_KEYWORD" + } +} diff --git a/test/resources/9999999/transactionalSMS/template-expected.amp b/test/resources/9999999/transactionalSMS/template-expected.amp new file mode 100644 index 000000000..d5aa49c01 --- /dev/null +++ b/test/resources/9999999/transactionalSMS/template-expected.amp @@ -0,0 +1,108 @@ +line1 +%%[ + SET @test = '{{{description}}}' +]%% +line2 %%= v(@test) =%% still line2 +line3 +%%[ + SET @key = '{{{secret}}}' +]%% + +%%[ + SET @unsubMessages = 'UnsubscribeSMSMessages_DEV' + SET @unsubEvents = 'UnsubscribeSMS_DEV' + SET @num = concat('+', [MOBILE_NUMBER]) + SET @rs = RetrieveSalesforceObjects( + 'Contact', + 'Id,et4ae5__HasOptedOutOfMobile__c', + 'MobilePhone', + '=', + @num + ) + SET @count = rowCount(@rs) + VAR @response + SET @rx = '^\+((?:9[679]\d8[035789]\d|6[789]\d|5[90]\d|42\d|3[578]\d|2[1-689]\d)|9[0-58]|8[1246]|6[0-6]|5[1-8]|4[013-9]|3[0-469]|2[70]|7|1)' + SET @prefix = concat('+', RegExMatch(@num, @rx, 1)) + IF @count>0 THEN + FOR @i = 1 TO @count DO + SET @sk = Field(Row(@rs, @i), 'Id') + IF Field(Row(@rs, 1), 'et4ae5__HasOptedOutOfMobile__c') == 'false' THEN + SET @result = UpdateSingleSalesforceObject('Contact', @sk, 'et4ae5__HasOptedOutOfMobile__c', 'true') + IF @result == 0 THEN + InsertData( + @unsubEvents, + 'MobileNumber', + @num, + 'Message', + [MSG(0).NOUNS], + 'ContactId', + @sk, + 'Status', + 'Error Updating' + ) + ELSE + InsertData( + @unsubEvents, + 'MobileNumber', + @num, + 'Message', + [MSG(0).NOUNS], + 'ContactId', + @sk, + 'Status', + 'Successfully Unsubscribed' + ) + ENDIF + ELSE + InsertData( + @unsubEvents, + 'MobileNumber', + @num, + 'Message', + [MSG(0).NOUNS], + 'ContactId', + @sk, + 'Status', + 'Already Unsubscribed' + ) + ENDIF + NEXT @i + SET @msg = Lookup( + @unsubMessages, + 'Message', + 'Prefix', + @prefix, + 'Type', + 'Found' + ) + IF Length(@msg) == 0 THEN + SET @response = 'You have unsubscribed and will no longer receive any messages.|' + ELSE + SET @response = @msg + ENDIF + ELSE + InsertData( + @unsubEvents, + 'MobileNumber', + @num, + 'Message', + [MSG(0).NOUNS], + 'Status', + 'Not Found' + ) + SET @msg = Lookup( + @unsubMessages, + 'Message', + 'Prefix', + @prefix, + 'Type', + 'NotFound' + ) + IF Length(@msg) == 0 THEN + SET @response = 'Sorry, we could not find you' + ELSE + SET @response = @msg + ENDIF + ENDIF +]%% +%%=v(@response)=%% diff --git a/test/resources/9999999/transactionalSMS/template-expected.json b/test/resources/9999999/transactionalSMS/template-expected.json new file mode 100644 index 000000000..8c2f3b9e0 --- /dev/null +++ b/test/resources/9999999/transactionalSMS/template-expected.json @@ -0,0 +1,12 @@ +{ + "name": "{{{prefix}}}tsms", + "definitionKey": "{{{prefix}}}tsms", + "description": "{{{description}}}", + "status": "Active", + "subscriptions": { + "countryCode": "", + "autoAddSubscriber": true, + "updateSubscriber": true, + "r__mobileKeyword_key": "4912312345678.{{{prefixUpper}}}KEYWORD" + } +} diff --git a/test/resources/9999999/triggeredSend/build-expected.json b/test/resources/9999999/triggeredSend/build-expected.json new file mode 100644 index 000000000..aad4d3b25 --- /dev/null +++ b/test/resources/9999999/triggeredSend/build-expected.json @@ -0,0 +1,28 @@ +{ + "AllowedSlots": 0, + "AutoAddSubscribers": false, + "AutoUpdateSubscribers": false, + "BatchInterval": 0, + "CreatedDate": "2018-06-25T05:58:00", + "CustomerKey": "testTemplated_triggeredSend", + "Description": "Unsubscribe_Email", + "DynamicEmailSubject": "You are successfully unsubscribed", + "EmailSubject": "You are successfully unsubscribed", + "FromAddress": "unsubscribe@emails.mcdev.accenture.com", + "FromName": "unsubscribe", + "IsMultipart": false, + "IsWrapped": true, + "Keyword": "", + "ModifiedDate": "2018-06-25T05:58:00", + "Name": "testTemplated_triggeredSend", + "NewSlotTrigger": 0, + "c__priority": "Medium", + "SuppressTracking": false, + "TriggeredSendStatus": "New", + "TriggeredSendType": "Continuous", + "r__asset_key": "testTemplated_asset_message", + "r__asset_name_readOnly": "testTemplated_asset_message", + "r__folder_Path": "Triggered Sends", + "r__sendClassification_key": "testTemplated_sendClassification", + "r__senderProfile_key": "testTemplated_senderProfile" +} diff --git a/test/resources/9999999/triggeredSend/get-expected.json b/test/resources/9999999/triggeredSend/get-expected.json new file mode 100644 index 000000000..691f8834e --- /dev/null +++ b/test/resources/9999999/triggeredSend/get-expected.json @@ -0,0 +1,28 @@ +{ + "AllowedSlots": 0, + "AutoAddSubscribers": false, + "AutoUpdateSubscribers": false, + "BatchInterval": 0, + "CreatedDate": "2018-06-25T05:58:00", + "CustomerKey": "testExisting_triggeredSend", + "Description": "Unsubscribe_Email", + "DynamicEmailSubject": "You are successfully unsubscribed", + "EmailSubject": "You are successfully unsubscribed", + "FromAddress": "unsubscribe@emails.mcdev.accenture.com", + "FromName": "unsubscribe", + "IsMultipart": false, + "IsWrapped": true, + "Keyword": "", + "ModifiedDate": "2018-06-25T05:58:00", + "Name": "testExisting_triggeredSend", + "NewSlotTrigger": 0, + "c__priority": "Medium", + "SuppressTracking": false, + "TriggeredSendStatus": "New", + "TriggeredSendType": "Continuous", + "r__asset_key": "testExisting_asset_message", + "r__asset_name_readOnly": "testExisting_asset_message", + "r__folder_Path": "Triggered Sends", + "r__sendClassification_key": "testExisting_sendClassification", + "r__senderProfile_key": "testExisting_senderProfile" +} diff --git a/test/resources/9999999/triggeredSend/get-rcb-id-expected.json b/test/resources/9999999/triggeredSend/get-rcb-id-expected.json new file mode 100644 index 000000000..0027f7542 --- /dev/null +++ b/test/resources/9999999/triggeredSend/get-rcb-id-expected.json @@ -0,0 +1,28 @@ +{ + "AllowedSlots": 0, + "AutoAddSubscribers": false, + "AutoUpdateSubscribers": false, + "BatchInterval": 0, + "CreatedDate": "2018-06-25T05:58:00", + "CustomerKey": "testExisting_triggeredSend_rcb", + "Description": "Unsubscribe_Email", + "DynamicEmailSubject": "%%= ContentBlockById(1295064) =%%", + "EmailSubject": "%%= ContentBlockById(1295064) =%%", + "FromAddress": "%%= ContentBlockById(1295064) =%%", + "FromName": "%%= ContentBlockById(1295064) =%%", + "IsMultipart": false, + "IsWrapped": true, + "Keyword": "", + "ModifiedDate": "2018-06-25T05:58:00", + "Name": "testExisting_triggeredSend_rcb", + "NewSlotTrigger": 0, + "c__priority": "Medium", + "SuppressTracking": false, + "TriggeredSendStatus": "New", + "TriggeredSendType": "Continuous", + "r__asset_key": "testExisting_asset_message", + "r__asset_name_readOnly": "testExisting_asset_message", + "r__folder_Path": "Triggered Sends", + "r__sendClassification_key": "testExisting_sendClassification", + "r__senderProfile_key": "testExisting_senderProfile_rcb" +} diff --git a/test/resources/9999999/triggeredSend/get-rcb-key-expected.json b/test/resources/9999999/triggeredSend/get-rcb-key-expected.json new file mode 100644 index 000000000..2305179cd --- /dev/null +++ b/test/resources/9999999/triggeredSend/get-rcb-key-expected.json @@ -0,0 +1,28 @@ +{ + "AllowedSlots": 0, + "AutoAddSubscribers": false, + "AutoUpdateSubscribers": false, + "BatchInterval": 0, + "CreatedDate": "2018-06-25T05:58:00", + "CustomerKey": "testExisting_triggeredSend_rcb", + "Description": "Unsubscribe_Email", + "DynamicEmailSubject": "%%= ContentBlockByKey(\"testExisting_asset_htmlblock\") =%%", + "EmailSubject": "%%= ContentBlockByKey(\"testExisting_asset_htmlblock\") =%%", + "FromAddress": "%%= ContentBlockByKey(\"testExisting_asset_htmlblock\") =%%", + "FromName": "%%= ContentBlockByKey(\"testExisting_asset_htmlblock\") =%%", + "IsMultipart": false, + "IsWrapped": true, + "Keyword": "", + "ModifiedDate": "2018-06-25T05:58:00", + "Name": "testExisting_triggeredSend_rcb", + "NewSlotTrigger": 0, + "c__priority": "Medium", + "SuppressTracking": false, + "TriggeredSendStatus": "New", + "TriggeredSendType": "Continuous", + "r__asset_key": "testExisting_asset_message", + "r__asset_name_readOnly": "testExisting_asset_message", + "r__folder_Path": "Triggered Sends", + "r__sendClassification_key": "testExisting_sendClassification", + "r__senderProfile_key": "testExisting_senderProfile_rcb" +} diff --git a/test/resources/9999999/triggeredSend/get-rcb-name-expected.json b/test/resources/9999999/triggeredSend/get-rcb-name-expected.json new file mode 100644 index 000000000..22bc65d1e --- /dev/null +++ b/test/resources/9999999/triggeredSend/get-rcb-name-expected.json @@ -0,0 +1,28 @@ +{ + "AllowedSlots": 0, + "AutoAddSubscribers": false, + "AutoUpdateSubscribers": false, + "BatchInterval": 0, + "CreatedDate": "2018-06-25T05:58:00", + "CustomerKey": "testExisting_triggeredSend_rcb", + "Description": "Unsubscribe_Email", + "DynamicEmailSubject": "%%= ContentBlockByName(\"Content Builder\\dont strip non ssjs content\") =%%", + "EmailSubject": "%%= ContentBlockByName(\"Content Builder\\dont strip non ssjs content\") =%%", + "FromAddress": "%%= ContentBlockByName(\"Content Builder\\dont strip non ssjs content\") =%%", + "FromName": "%%= ContentBlockByName(\"Content Builder\\dont strip non ssjs content\") =%%", + "IsMultipart": false, + "IsWrapped": true, + "Keyword": "", + "ModifiedDate": "2018-06-25T05:58:00", + "Name": "testExisting_triggeredSend_rcb", + "NewSlotTrigger": 0, + "c__priority": "Medium", + "SuppressTracking": false, + "TriggeredSendStatus": "New", + "TriggeredSendType": "Continuous", + "r__asset_key": "testExisting_asset_message", + "r__asset_name_readOnly": "testExisting_asset_message", + "r__folder_Path": "Triggered Sends", + "r__sendClassification_key": "testExisting_sendClassification", + "r__senderProfile_key": "testExisting_senderProfile_rcb" +} diff --git a/test/resources/9999999/triggeredSend/patch-expected.json b/test/resources/9999999/triggeredSend/patch-expected.json new file mode 100644 index 000000000..505fb7863 --- /dev/null +++ b/test/resources/9999999/triggeredSend/patch-expected.json @@ -0,0 +1,27 @@ +{ + "AllowedSlots": 0, + "AutoAddSubscribers": false, + "AutoUpdateSubscribers": false, + "BatchInterval": 0, + "CreatedDate": "2018-06-25T05:58:00", + "CustomerKey": "testExisting_triggeredSend", + "Description": "updated on deploy", + "DynamicEmailSubject": "You are successfully unsubscribed", + "EmailSubject": "You are successfully unsubscribed", + "FromAddress": "unsubscribe@emails.mcdev.accenture.com", + "FromName": "unsubscribe", + "IsMultipart": false, + "IsWrapped": true, + "Keyword": "", + "ModifiedDate": "2018-06-25T05:58:00", + "Name": "testExisting_triggeredSend", + "NewSlotTrigger": 0, + "c__priority": "Medium", + "SuppressTracking": false, + "TriggeredSendStatus": "New", + "TriggeredSendType": "Continuous", + "r__email_name": "Sporting Goods for September", + "r__folder_Path": "Triggered Sends", + "r__sendClassification_key": "testExisting_sendClassification", + "r__senderProfile_key": "testExisting_senderProfile" +} diff --git a/test/resources/9999999/triggeredSend/post-expected.json b/test/resources/9999999/triggeredSend/post-expected.json new file mode 100644 index 000000000..26dade668 --- /dev/null +++ b/test/resources/9999999/triggeredSend/post-expected.json @@ -0,0 +1,27 @@ +{ + "AllowedSlots": 0, + "AutoAddSubscribers": false, + "AutoUpdateSubscribers": false, + "BatchInterval": 0, + "CreatedDate": "2018-06-25T05:58:00", + "CustomerKey": "testNew_triggeredSend", + "Description": "created on deploy", + "DynamicEmailSubject": "You are successfully unsubscribed", + "EmailSubject": "You are successfully unsubscribed", + "FromAddress": "unsubscribe@emails.mcdev.accenture.com", + "FromName": "unsubscribe", + "IsMultipart": false, + "IsWrapped": true, + "Keyword": "", + "ModifiedDate": "2018-06-25T05:58:00", + "Name": "testNew_triggeredSend", + "NewSlotTrigger": 0, + "c__priority": "Medium", + "SuppressTracking": false, + "TriggeredSendStatus": "New", + "TriggeredSendType": "Continuous", + "r__email_name": "Sporting Goods for September", + "r__folder_Path": "Triggered Sends", + "r__sendClassification_key": "testExisting_sendClassification", + "r__senderProfile_key": "testExisting_senderProfile" +} diff --git a/test/resources/9999999/triggeredSend/template-expected.json b/test/resources/9999999/triggeredSend/template-expected.json new file mode 100644 index 000000000..dfb54d6fd --- /dev/null +++ b/test/resources/9999999/triggeredSend/template-expected.json @@ -0,0 +1,28 @@ +{ + "AllowedSlots": 0, + "AutoAddSubscribers": false, + "AutoUpdateSubscribers": false, + "BatchInterval": 0, + "CreatedDate": "2018-06-25T05:58:00", + "CustomerKey": "{{{prefix}}}triggeredSend", + "Description": "Unsubscribe_Email", + "DynamicEmailSubject": "You are successfully unsubscribed", + "EmailSubject": "You are successfully unsubscribed", + "FromAddress": "unsubscribe@emails.mcdev.accenture.com", + "FromName": "unsubscribe", + "IsMultipart": false, + "IsWrapped": true, + "Keyword": "", + "ModifiedDate": "2018-06-25T05:58:00", + "Name": "{{{prefix}}}triggeredSend", + "NewSlotTrigger": 0, + "c__priority": "Medium", + "SuppressTracking": false, + "TriggeredSendStatus": "New", + "TriggeredSendType": "Continuous", + "r__asset_key": "{{{prefix}}}asset_message", + "r__asset_name_readOnly": "{{{prefix}}}asset_message", + "r__folder_Path": "Triggered Sends", + "r__sendClassification_key": "{{{prefix}}}sendClassification", + "r__senderProfile_key": "{{{prefix}}}senderProfile" +} diff --git a/test/resources/9999999/triggeredSendDefinition/create-response.xml b/test/resources/9999999/triggeredSendDefinition/create-response.xml new file mode 100644 index 000000000..11fd90e5e --- /dev/null +++ b/test/resources/9999999/triggeredSendDefinition/create-response.xml @@ -0,0 +1,79 @@ +<?xml version="1.0" encoding="utf-8"?> +<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:xsd="http://www.w3.org/2001/XMLSchema" + xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing" + xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" + xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"> + <soap:Header> + <wsa:Action>CreateResponse</wsa:Action> + <wsa:MessageID>urn:uuid:9d4bb477-f79f-4f3f-8304-5c0dcd0e5b66</wsa:MessageID> + <wsa:RelatesTo>urn:uuid:dd06e2ef-2adc-4227-b872-1fc34e48a984</wsa:RelatesTo> + <wsa:To>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</wsa:To> + <wsse:Security> + <wsu:Timestamp wsu:Id="Timestamp-f09d192c-466f-410c-9cd4-dabfba315ec4"> + <wsu:Created>2023-08-08T13:42:51Z</wsu:Created> + <wsu:Expires>2023-08-08T13:47:51Z</wsu:Expires> + </wsu:Timestamp> + </wsse:Security> + </soap:Header> + <soap:Body> + <CreateResponse xmlns="http://exacttarget.com/wsdl/partnerAPI"> + <Results xsi:type="TriggeredSendDefinition"> + <StatusCode>OK</StatusCode> + <StatusMessage>TriggeredSendDefinition created</StatusMessage> + <OrdinalID>0</OrdinalID> + <NewID>0</NewID> + <NewObjectID>6cfadead-f635-ee11-b85a-48df37d1de8a</NewObjectID> + <Object xsi:type="TriggeredSendDefinition"> + <PartnerKey xsi:nil="true" /> + <PartnerProperties> + <Name>TestEmailAddr</Name> + <Value /> + </PartnerProperties> + <CreatedDate>2018-06-25T05:58:00</CreatedDate> + <ModifiedDate>2018-06-25T05:58:00</ModifiedDate> + <ObjectID>6cfadead-f635-ee11-b85a-48df37d1de8a</ObjectID> + <CustomerKey>testNew_triggeredSend</CustomerKey> + <IsPlatformObject>false</IsPlatformObject> + <Name>testNew_triggeredSend</Name> + <Description>created on deploy</Description> + <Keyword /> + <CategoryID>89348</CategoryID> + <SendClassification> + <PartnerKey xsi:nil="true" /> + <ObjectID>95da425b-a06f-e611-96fe-38eaa7142c61</ObjectID> + <CustomerKey>testExisting_sendClassification</CustomerKey> + </SendClassification> + <SenderProfile> + <PartnerKey xsi:nil="true" /> + <ObjectID>a75d452b-7ef4-eb11-b82d-48df37d1da95</ObjectID> + <CustomerKey>testExisting_senderProfile</CustomerKey> + </SenderProfile> + <FromName>unsubscribe</FromName> + <FromAddress>unsubscribe@emails.mcdev.accenture.com</FromAddress> + <SuppressTracking>false</SuppressTracking> + <TriggeredSendType>Continuous</TriggeredSendType> + <TriggeredSendStatus>New</TriggeredSendStatus> + <Email> + <PartnerKey xsi:nil="true" /> + <ID>483943</ID> + <ObjectID xsi:nil="true" /> + </Email> + <AutoAddSubscribers>false</AutoAddSubscribers> + <AutoUpdateSubscribers>false</AutoUpdateSubscribers> + <BatchInterval>0</BatchInterval> + <EmailSubject>You are successfully unsubscribed</EmailSubject> + <DynamicEmailSubject>You are successfully unsubscribed</DynamicEmailSubject> + <IsMultipart>false</IsMultipart> + <IsWrapped>true</IsWrapped> + <AllowedSlots>0</AllowedSlots> + <NewSlotTrigger>0</NewSlotTrigger> + <Priority>4</Priority> + </Object> + </Results> + <RequestID>25fe1ec4-1204-42fd-9f0e-32166b82a5a5</RequestID> + <OverallStatus>OK</OverallStatus> + </CreateResponse> + </soap:Body> +</soap:Envelope> diff --git a/test/resources/9999999/triggeredSendDefinition/delete-response.xml b/test/resources/9999999/triggeredSendDefinition/delete-response.xml new file mode 100644 index 000000000..712935560 --- /dev/null +++ b/test/resources/9999999/triggeredSendDefinition/delete-response.xml @@ -0,0 +1,36 @@ +<?xml version="1.0" encoding="utf-8"?> +<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:xsd="http://www.w3.org/2001/XMLSchema" + xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing" + xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" + xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"> + <soap:Header> + <wsa:Action>DeleteResponse</wsa:Action> + <wsa:MessageID>urn:uuid:9b7ec2d4-b9cf-4443-aa99-7d790b0d8ed9</wsa:MessageID> + <wsa:RelatesTo>urn:uuid:b9274179-8dba-4434-9f06-7e3f5dcc5d36</wsa:RelatesTo> + <wsa:To>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</wsa:To> + <wsse:Security> + <wsu:Timestamp wsu:Id="Timestamp-0f3617a8-995a-43fc-a31c-984f314be995"> + <wsu:Created>2023-08-08T13:33:37Z</wsu:Created> + <wsu:Expires>2023-08-08T13:38:37Z</wsu:Expires> + </wsu:Timestamp> + </wsse:Security> + </soap:Header> + <soap:Body> + <DeleteResponse xmlns="http://exacttarget.com/wsdl/partnerAPI"> + <Results> + <StatusCode>OK</StatusCode> + <StatusMessage>TriggeredSendDefinition deleted</StatusMessage> + <OrdinalID>0</OrdinalID> + <Object xsi:type="TriggeredSendDefinition"> + <PartnerKey xsi:nil="true" /> + <ObjectID xsi:nil="true" /> + <CustomerKey>TestKey-419705</CustomerKey> + </Object> + </Results> + <RequestID>e63109fe-085f-4d9d-950b-05d827c74b0e</RequestID> + <OverallStatus>OK</OverallStatus> + </DeleteResponse> + </soap:Body> +</soap:Envelope> diff --git a/test/resources/9999999/triggeredSendDefinition/retrieve-CustomerKey=testExisting_triggeredSend-response.xml b/test/resources/9999999/triggeredSendDefinition/retrieve-CustomerKey=testExisting_triggeredSend-response.xml new file mode 100644 index 000000000..2c06c6bb6 --- /dev/null +++ b/test/resources/9999999/triggeredSendDefinition/retrieve-CustomerKey=testExisting_triggeredSend-response.xml @@ -0,0 +1,72 @@ +<?xml version="1.0" encoding="utf-8"?> +<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:xsd="http://www.w3.org/2001/XMLSchema" + xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing" + xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" + xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"> + <soap:Header> + <wsa:Action>RetrieveResponse</wsa:Action> + <wsa:MessageID>urn:uuid:8fe86c01-56d5-4c56-8ac2-991578c79485</wsa:MessageID> + <wsa:RelatesTo>urn:uuid:592f71ac-78a0-45a2-8cfe-37a91fc6cfd5</wsa:RelatesTo> + <wsa:To>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</wsa:To> + <wsse:Security> + <wsu:Timestamp wsu:Id="Timestamp-675af14a-b6a1-44a5-b7e7-4a76c6d18424"> + <wsu:Created>2023-02-01T10:29:21Z</wsu:Created> + <wsu:Expires>2023-02-01T10:34:21Z</wsu:Expires> + </wsu:Timestamp> + </wsse:Security> + </soap:Header> + <soap:Body> + <RetrieveResponseMsg xmlns="http://exacttarget.com/wsdl/partnerAPI"> + <OverallStatus>OK</OverallStatus> + <RequestID>a90dda5e-aeba-440a-82ce-74fb2abf5eb2</RequestID> + <Results xsi:type="TriggeredSendDefinition"> + <PartnerKey xsi:nil="true" /> + <PartnerProperties> + <Name>TestEmailAddr</Name> + <Value /> + </PartnerProperties> + <CreatedDate>2018-06-25T05:58:00</CreatedDate> + <ModifiedDate>2018-06-25T05:58:00</ModifiedDate> + <ObjectID>b3150cf0-6e78-e811-80d4-1402ec721c9d</ObjectID> + <CustomerKey>testExisting_triggeredSend</CustomerKey> + <IsPlatformObject>false</IsPlatformObject> + <Name>testExisting_triggeredSend</Name> + <Description>Unsubscribe_Email</Description> + <Keyword /> + <CategoryID>89348</CategoryID> + <SendClassification> + <PartnerKey xsi:nil="true" /> + <ObjectID>95da425b-a06f-e611-96fe-38eaa7142c61</ObjectID> + <CustomerKey>testExisting_sendClassification</CustomerKey> + </SendClassification> + <SenderProfile> + <PartnerKey xsi:nil="true" /> + <ObjectID>a75d452b-7ef4-eb11-b82d-48df37d1da95</ObjectID> + <CustomerKey>testExisting_senderProfile</CustomerKey> + </SenderProfile> + <FromName>unsubscribe</FromName> + <FromAddress>unsubscribe@emails.mcdev.accenture.com</FromAddress> + <SuppressTracking>false</SuppressTracking> + <TriggeredSendType>Continuous</TriggeredSendType> + <TriggeredSendStatus>Active</TriggeredSendStatus> + <Email> + <PartnerKey xsi:nil="true" /> + <ID>531213</ID> + <ObjectID xsi:nil="true" /> + </Email> + <AutoAddSubscribers>false</AutoAddSubscribers> + <AutoUpdateSubscribers>false</AutoUpdateSubscribers> + <BatchInterval>0</BatchInterval> + <EmailSubject>You are successfully unsubscribed</EmailSubject> + <DynamicEmailSubject>You are successfully unsubscribed</DynamicEmailSubject> + <IsMultipart>false</IsMultipart> + <IsWrapped>true</IsWrapped> + <AllowedSlots>0</AllowedSlots> + <NewSlotTrigger>0</NewSlotTrigger> + <Priority>4</Priority> + </Results> + </RetrieveResponseMsg> + </soap:Body> +</soap:Envelope> diff --git a/test/resources/9999999/triggeredSendDefinition/retrieve-CustomerKey=testExisting_triggeredSend_rcb-response.xml b/test/resources/9999999/triggeredSendDefinition/retrieve-CustomerKey=testExisting_triggeredSend_rcb-response.xml new file mode 100644 index 000000000..205725c6b --- /dev/null +++ b/test/resources/9999999/triggeredSendDefinition/retrieve-CustomerKey=testExisting_triggeredSend_rcb-response.xml @@ -0,0 +1,72 @@ +<?xml version="1.0" encoding="utf-8"?> +<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:xsd="http://www.w3.org/2001/XMLSchema" + xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing" + xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" + xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"> + <soap:Header> + <wsa:Action>RetrieveResponse</wsa:Action> + <wsa:MessageID>urn:uuid:8fe86c01-56d5-4c56-8ac2-991578c79485</wsa:MessageID> + <wsa:RelatesTo>urn:uuid:592f71ac-78a0-45a2-8cfe-37a91fc6cfd5</wsa:RelatesTo> + <wsa:To>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</wsa:To> + <wsse:Security> + <wsu:Timestamp wsu:Id="Timestamp-675af14a-b6a1-44a5-b7e7-4a76c6d18424"> + <wsu:Created>2023-02-01T10:29:21Z</wsu:Created> + <wsu:Expires>2023-02-01T10:34:21Z</wsu:Expires> + </wsu:Timestamp> + </wsse:Security> + </soap:Header> + <soap:Body> + <RetrieveResponseMsg xmlns="http://exacttarget.com/wsdl/partnerAPI"> + <OverallStatus>OK</OverallStatus> + <RequestID>a90dda5e-aeba-440a-82ce-74fb2abf5eb2</RequestID> + <Results xsi:type="TriggeredSendDefinition"> + <PartnerKey xsi:nil="true" /> + <PartnerProperties> + <Name>TestEmailAddr</Name> + <Value /> + </PartnerProperties> + <CreatedDate>2018-06-25T05:58:00</CreatedDate> + <ModifiedDate>2018-06-25T05:58:00</ModifiedDate> + <ObjectID>b3150cf0-6e78-e811-80d4-1402ec721c9a</ObjectID> + <CustomerKey>testExisting_triggeredSend_rcb</CustomerKey> + <IsPlatformObject>false</IsPlatformObject> + <Name>testExisting_triggeredSend_rcb</Name> + <Description>Unsubscribe_Email</Description> + <Keyword /> + <CategoryID>89348</CategoryID> + <SendClassification> + <PartnerKey xsi:nil="true" /> + <ObjectID>95da425b-a06f-e611-96fe-38eaa7142c61</ObjectID> + <CustomerKey>testExisting_sendClassification</CustomerKey> + </SendClassification> + <SenderProfile> + <PartnerKey xsi:nil="true" /> + <ObjectID>a75d452b-7ef4-eb11-b82d-48df37d1da99</ObjectID> + <CustomerKey>testExisting_senderProfile_rcb</CustomerKey> + </SenderProfile> + <FromName>%%= ContentBlockByName("Content Builder\dont strip non ssjs content") =%%</FromName> + <FromAddress>%%= ContentBlockByKey("testExisting_asset_htmlblock") =%%</FromAddress> + <SuppressTracking>false</SuppressTracking> + <TriggeredSendType>Continuous</TriggeredSendType> + <TriggeredSendStatus>Active</TriggeredSendStatus> + <Email> + <PartnerKey xsi:nil="true" /> + <ID>531213</ID> + <ObjectID xsi:nil="true" /> + </Email> + <AutoAddSubscribers>false</AutoAddSubscribers> + <AutoUpdateSubscribers>false</AutoUpdateSubscribers> + <BatchInterval>0</BatchInterval> + <EmailSubject>%%= ContentBlockById(1295064) =%%</EmailSubject> + <DynamicEmailSubject>%%= ContentBlockById(1295064) =%%</DynamicEmailSubject> + <IsMultipart>false</IsMultipart> + <IsWrapped>true</IsWrapped> + <AllowedSlots>0</AllowedSlots> + <NewSlotTrigger>0</NewSlotTrigger> + <Priority>4</Priority> + </Results> + </RetrieveResponseMsg> + </soap:Body> +</soap:Envelope> diff --git a/test/resources/9999999/triggeredSendDefinition/retrieve-TriggeredSendStatusINNew,Active,Inactive,Moved,Canceled-response.xml b/test/resources/9999999/triggeredSendDefinition/retrieve-TriggeredSendStatusINNew,Active,Inactive,Moved,Canceled-response.xml new file mode 100644 index 000000000..6d597dd14 --- /dev/null +++ b/test/resources/9999999/triggeredSendDefinition/retrieve-TriggeredSendStatusINNew,Active,Inactive,Moved,Canceled-response.xml @@ -0,0 +1,118 @@ +<?xml version="1.0" encoding="utf-8"?> +<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:xsd="http://www.w3.org/2001/XMLSchema" + xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing" + xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" + xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"> + <soap:Header> + <wsa:Action>RetrieveResponse</wsa:Action> + <wsa:MessageID>urn:uuid:8fe86c01-56d5-4c56-8ac2-991578c79485</wsa:MessageID> + <wsa:RelatesTo>urn:uuid:592f71ac-78a0-45a2-8cfe-37a91fc6cfd5</wsa:RelatesTo> + <wsa:To>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</wsa:To> + <wsse:Security> + <wsu:Timestamp wsu:Id="Timestamp-675af14a-b6a1-44a5-b7e7-4a76c6d18424"> + <wsu:Created>2023-02-01T10:29:21Z</wsu:Created> + <wsu:Expires>2023-02-01T10:34:21Z</wsu:Expires> + </wsu:Timestamp> + </wsse:Security> + </soap:Header> + <soap:Body> + <RetrieveResponseMsg xmlns="http://exacttarget.com/wsdl/partnerAPI"> + <OverallStatus>OK</OverallStatus> + <RequestID>a90dda5e-aeba-440a-82ce-74fb2abf5eb2</RequestID> + <Results xsi:type="TriggeredSendDefinition"> + <PartnerKey xsi:nil="true" /> + <PartnerProperties> + <Name>TestEmailAddr</Name> + <Value /> + </PartnerProperties> + <CreatedDate>2018-06-25T05:58:00</CreatedDate> + <ModifiedDate>2018-06-25T05:58:00</ModifiedDate> + <ObjectID>b3150cf0-6e78-e811-80d4-1402ec721c9d</ObjectID> + <CustomerKey>testExisting_triggeredSend</CustomerKey> + <IsPlatformObject>false</IsPlatformObject> + <Name>testExisting_triggeredSend</Name> + <Description>Unsubscribe_Email</Description> + <Keyword /> + <CategoryID>89348</CategoryID> + <SendClassification> + <PartnerKey xsi:nil="true" /> + <ObjectID>95da425b-a06f-e611-96fe-38eaa7142c61</ObjectID> + <CustomerKey>testExisting_sendClassification</CustomerKey> + </SendClassification> + <SenderProfile> + <PartnerKey xsi:nil="true" /> + <ObjectID>a75d452b-7ef4-eb11-b82d-48df37d1da95</ObjectID> + <CustomerKey>testExisting_senderProfile</CustomerKey> + </SenderProfile> + <FromName>unsubscribe</FromName> + <FromAddress>unsubscribe@emails.mcdev.accenture.com</FromAddress> + <SuppressTracking>false</SuppressTracking> + <TriggeredSendType>Continuous</TriggeredSendType> + <TriggeredSendStatus>New</TriggeredSendStatus> + <Email> + <PartnerKey xsi:nil="true" /> + <ID>531213</ID> + <ObjectID xsi:nil="true" /> + </Email> + <AutoAddSubscribers>false</AutoAddSubscribers> + <AutoUpdateSubscribers>false</AutoUpdateSubscribers> + <BatchInterval>0</BatchInterval> + <EmailSubject>You are successfully unsubscribed</EmailSubject> + <DynamicEmailSubject>You are successfully unsubscribed</DynamicEmailSubject> + <IsMultipart>false</IsMultipart> + <IsWrapped>true</IsWrapped> + <AllowedSlots>0</AllowedSlots> + <NewSlotTrigger>0</NewSlotTrigger> + <Priority>4</Priority> + </Results> + <Results xsi:type="TriggeredSendDefinition"> + <PartnerKey xsi:nil="true" /> + <PartnerProperties> + <Name>TestEmailAddr</Name> + <Value /> + </PartnerProperties> + <CreatedDate>2018-06-25T05:58:00</CreatedDate> + <ModifiedDate>2018-06-25T05:58:00</ModifiedDate> + <ObjectID>b3150cf0-6e78-e811-80d4-1402ec721c9a</ObjectID> + <CustomerKey>testExisting_triggeredSend_rcb</CustomerKey> + <IsPlatformObject>false</IsPlatformObject> + <Name>testExisting_triggeredSend_rcb</Name> + <Description>Unsubscribe_Email</Description> + <Keyword /> + <CategoryID>89348</CategoryID> + <SendClassification> + <PartnerKey xsi:nil="true" /> + <ObjectID>95da425b-a06f-e611-96fe-38eaa7142c61</ObjectID> + <CustomerKey>testExisting_sendClassification</CustomerKey> + </SendClassification> + <SenderProfile> + <PartnerKey xsi:nil="true" /> + <ObjectID>a75d452b-7ef4-eb11-b82d-48df37d1da99</ObjectID> + <CustomerKey>testExisting_senderProfile_rcb</CustomerKey> + </SenderProfile> + <FromName>%%= ContentBlockByName("Content Builder\dont strip non ssjs content") =%%</FromName> + <FromAddress>%%= ContentBlockByKey("testExisting_asset_htmlblock") =%%</FromAddress> + <SuppressTracking>false</SuppressTracking> + <TriggeredSendType>Continuous</TriggeredSendType> + <TriggeredSendStatus>New</TriggeredSendStatus> + <Email> + <PartnerKey xsi:nil="true" /> + <ID>531213</ID> + <ObjectID xsi:nil="true" /> + </Email> + <AutoAddSubscribers>false</AutoAddSubscribers> + <AutoUpdateSubscribers>false</AutoUpdateSubscribers> + <BatchInterval>0</BatchInterval> + <EmailSubject>%%= ContentBlockById(1295064) =%%</EmailSubject> + <DynamicEmailSubject>%%= ContentBlockById(1295064) =%%</DynamicEmailSubject> + <IsMultipart>false</IsMultipart> + <IsWrapped>true</IsWrapped> + <AllowedSlots>0</AllowedSlots> + <NewSlotTrigger>0</NewSlotTrigger> + <Priority>4</Priority> + </Results> + </RetrieveResponseMsg> + </soap:Body> +</soap:Envelope> diff --git a/test/resources/9999999/triggeredSendDefinition/retrieve-TriggeredSendStatusINdummy,Active-response.xml b/test/resources/9999999/triggeredSendDefinition/retrieve-TriggeredSendStatusINdummy,Active-response.xml new file mode 100644 index 000000000..80b956623 --- /dev/null +++ b/test/resources/9999999/triggeredSendDefinition/retrieve-TriggeredSendStatusINdummy,Active-response.xml @@ -0,0 +1,118 @@ +<?xml version="1.0" encoding="utf-8"?> +<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:xsd="http://www.w3.org/2001/XMLSchema" + xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing" + xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" + xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"> + <soap:Header> + <wsa:Action>RetrieveResponse</wsa:Action> + <wsa:MessageID>urn:uuid:8fe86c01-56d5-4c56-8ac2-991578c79485</wsa:MessageID> + <wsa:RelatesTo>urn:uuid:592f71ac-78a0-45a2-8cfe-37a91fc6cfd5</wsa:RelatesTo> + <wsa:To>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</wsa:To> + <wsse:Security> + <wsu:Timestamp wsu:Id="Timestamp-675af14a-b6a1-44a5-b7e7-4a76c6d18424"> + <wsu:Created>2023-02-01T10:29:21Z</wsu:Created> + <wsu:Expires>2023-02-01T10:34:21Z</wsu:Expires> + </wsu:Timestamp> + </wsse:Security> + </soap:Header> + <soap:Body> + <RetrieveResponseMsg xmlns="http://exacttarget.com/wsdl/partnerAPI"> + <OverallStatus>OK</OverallStatus> + <RequestID>a90dda5e-aeba-440a-82ce-74fb2abf5eb2</RequestID> + <Results xsi:type="TriggeredSendDefinition"> + <PartnerKey xsi:nil="true" /> + <PartnerProperties> + <Name>TestEmailAddr</Name> + <Value /> + </PartnerProperties> + <CreatedDate>2018-06-25T05:58:00</CreatedDate> + <ModifiedDate>2018-06-25T05:58:00</ModifiedDate> + <ObjectID>b3150cf0-6e78-e811-80d4-1402ec721c9d</ObjectID> + <CustomerKey>testExisting_triggeredSend</CustomerKey> + <IsPlatformObject>false</IsPlatformObject> + <Name>testExisting_triggeredSend</Name> + <Description>Unsubscribe_Email</Description> + <Keyword /> + <CategoryID>89348</CategoryID> + <SendClassification> + <PartnerKey xsi:nil="true" /> + <ObjectID>95da425b-a06f-e611-96fe-38eaa7142c61</ObjectID> + <CustomerKey>testExisting_sendClassification</CustomerKey> + </SendClassification> + <SenderProfile> + <PartnerKey xsi:nil="true" /> + <ObjectID>a75d452b-7ef4-eb11-b82d-48df37d1da95</ObjectID> + <CustomerKey>testExisting_senderProfile</CustomerKey> + </SenderProfile> + <FromName>unsubscribe</FromName> + <FromAddress>unsubscribe@emails.mcdev.accenture.com</FromAddress> + <SuppressTracking>false</SuppressTracking> + <TriggeredSendType>Continuous</TriggeredSendType> + <TriggeredSendStatus>Active</TriggeredSendStatus> + <Email> + <PartnerKey xsi:nil="true" /> + <ID>531213</ID> + <ObjectID xsi:nil="true" /> + </Email> + <AutoAddSubscribers>false</AutoAddSubscribers> + <AutoUpdateSubscribers>false</AutoUpdateSubscribers> + <BatchInterval>0</BatchInterval> + <EmailSubject>You are successfully unsubscribed</EmailSubject> + <DynamicEmailSubject>You are successfully unsubscribed</DynamicEmailSubject> + <IsMultipart>false</IsMultipart> + <IsWrapped>true</IsWrapped> + <AllowedSlots>0</AllowedSlots> + <NewSlotTrigger>0</NewSlotTrigger> + <Priority>4</Priority> + </Results> + <Results xsi:type="TriggeredSendDefinition"> + <PartnerKey xsi:nil="true" /> + <PartnerProperties> + <Name>TestEmailAddr</Name> + <Value /> + </PartnerProperties> + <CreatedDate>2018-06-25T05:58:00</CreatedDate> + <ModifiedDate>2018-06-25T05:58:00</ModifiedDate> + <ObjectID>b3150cf0-6e78-e811-80d4-1402ec721c9a</ObjectID> + <CustomerKey>testExisting_triggeredSend_rcb</CustomerKey> + <IsPlatformObject>false</IsPlatformObject> + <Name>testExisting_triggeredSend_rcb</Name> + <Description>Unsubscribe_Email</Description> + <Keyword /> + <CategoryID>89348</CategoryID> + <SendClassification> + <PartnerKey xsi:nil="true" /> + <ObjectID>95da425b-a06f-e611-96fe-38eaa7142c61</ObjectID> + <CustomerKey>testExisting_sendClassification</CustomerKey> + </SendClassification> + <SenderProfile> + <PartnerKey xsi:nil="true" /> + <ObjectID>a75d452b-7ef4-eb11-b82d-48df37d1da99</ObjectID> + <CustomerKey>testExisting_senderProfile_rcb</CustomerKey> + </SenderProfile> + <FromName>%%= ContentBlockByName("Content Builder\dont strip non ssjs content") =%%</FromName> + <FromAddress>%%= ContentBlockByKey("testExisting_asset_htmlblock") =%%</FromAddress> + <SuppressTracking>false</SuppressTracking> + <TriggeredSendType>Continuous</TriggeredSendType> + <TriggeredSendStatus>Active</TriggeredSendStatus> + <Email> + <PartnerKey xsi:nil="true" /> + <ID>531213</ID> + <ObjectID xsi:nil="true" /> + </Email> + <AutoAddSubscribers>false</AutoAddSubscribers> + <AutoUpdateSubscribers>false</AutoUpdateSubscribers> + <BatchInterval>0</BatchInterval> + <EmailSubject>%%= ContentBlockById(1295064) =%%</EmailSubject> + <DynamicEmailSubject>%%= ContentBlockById(1295064) =%%</DynamicEmailSubject> + <IsMultipart>false</IsMultipart> + <IsWrapped>true</IsWrapped> + <AllowedSlots>0</AllowedSlots> + <NewSlotTrigger>0</NewSlotTrigger> + <Priority>4</Priority> + </Results> + </RetrieveResponseMsg> + </soap:Body> +</soap:Envelope> diff --git a/test/resources/9999999/triggeredSendDefinition/update-response.xml b/test/resources/9999999/triggeredSendDefinition/update-response.xml new file mode 100644 index 000000000..2eb67f139 --- /dev/null +++ b/test/resources/9999999/triggeredSendDefinition/update-response.xml @@ -0,0 +1,78 @@ +<?xml version="1.0" encoding="utf-8"?> +<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:xsd="http://www.w3.org/2001/XMLSchema" + xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing" + xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" + xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"> + <soap:Header> + <wsa:Action>UpdateResponse</wsa:Action> + <wsa:MessageID>urn:uuid:9d4bb477-f79f-4f3f-8304-5c0dcd0e5b66</wsa:MessageID> + <wsa:RelatesTo>urn:uuid:dd06e2ef-2adc-4227-b872-1fc34e48a984</wsa:RelatesTo> + <wsa:To>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</wsa:To> + <wsse:Security> + <wsu:Timestamp wsu:Id="Timestamp-f09d192c-466f-410c-9cd4-dabfba315ec4"> + <wsu:Created>2023-08-08T13:42:51Z</wsu:Created> + <wsu:Expires>2023-08-08T13:47:51Z</wsu:Expires> + </wsu:Timestamp> + </wsse:Security> + </soap:Header> + <soap:Body> + <UpdateResponse xmlns="http://exacttarget.com/wsdl/partnerAPI"> + <Results xsi:type="TriggeredSendDefinition"> + + <StatusCode>OK</StatusCode> + <StatusMessage>TriggeredSendDefinition updated</StatusMessage> + <OrdinalID>0</OrdinalID> + <Object xsi:type="TriggeredSendDefinition"> + <PartnerKey xsi:nil="true" /> + <PartnerProperties> + <Name>TestEmailAddr</Name> + <Value /> + </PartnerProperties> + <CreatedDate>2018-06-25T05:58:00</CreatedDate> + <ModifiedDate>2018-06-25T05:58:00</ModifiedDate> + <ObjectID>b3150cf0-6e78-e811-80d4-1402ec721c9d</ObjectID> + <CustomerKey>testExisting_triggeredSend</CustomerKey> + <IsPlatformObject>false</IsPlatformObject> + <Name>testExisting_triggeredSend</Name> + <Description>updated on deploy</Description> + <Keyword /> + <CategoryID>89348</CategoryID> + <SendClassification> + <PartnerKey xsi:nil="true" /> + <ObjectID>95da425b-a06f-e611-96fe-38eaa7142c61</ObjectID> + <CustomerKey>testExisting_sendClassification</CustomerKey> + </SendClassification> + <SenderProfile> + <PartnerKey xsi:nil="true" /> + <ObjectID>a75d452b-7ef4-eb11-b82d-48df37d1da95</ObjectID> + <CustomerKey>testExisting_senderProfile</CustomerKey> + </SenderProfile> + <FromName>unsubscribe</FromName> + <FromAddress>unsubscribe@emails.mcdev.accenture.com</FromAddress> + <SuppressTracking>false</SuppressTracking> + <TriggeredSendType>Continuous</TriggeredSendType> + <TriggeredSendStatus>New</TriggeredSendStatus> + <Email> + <PartnerKey xsi:nil="true" /> + <ID>483943</ID> + <ObjectID xsi:nil="true" /> + </Email> + <AutoAddSubscribers>false</AutoAddSubscribers> + <AutoUpdateSubscribers>false</AutoUpdateSubscribers> + <BatchInterval>0</BatchInterval> + <EmailSubject>You are successfully unsubscribed</EmailSubject> + <DynamicEmailSubject>You are successfully unsubscribed</DynamicEmailSubject> + <IsMultipart>false</IsMultipart> + <IsWrapped>true</IsWrapped> + <AllowedSlots>0</AllowedSlots> + <NewSlotTrigger>0</NewSlotTrigger> + <Priority>4</Priority> + </Object> + </Results> + <RequestID>25fe1ec4-1204-42fd-9f0e-32166b82a5a5</RequestID> + <OverallStatus>OK</OverallStatus> + </UpdateResponse> + </soap:Body> +</soap:Envelope> diff --git a/test/resources/9999999/triggeredSendSummary/get-expected.json b/test/resources/9999999/triggeredSendSummary/get-expected.json new file mode 100644 index 000000000..99808b75e --- /dev/null +++ b/test/resources/9999999/triggeredSendSummary/get-expected.json @@ -0,0 +1,24 @@ +{ + "CustomerKey": "testExisting_triggeredSend", + "Sent": 10, + "NotSentDueToOptOut": 0, + "NotSentDueToUndeliverable": 0, + "Bounces": 0, + "Opens": 0, + "Clicks": 0, + "UniqueOpens": 0, + "UniqueClicks": 0, + "OptOuts": 0, + "SurveyResponses": 0, + "FTAFRequests": 0, + "FTAFEmailsSent": 0, + "FTAFOptIns": 0, + "Conversions": 0, + "UniqueConversions": 0, + "InProcess": 0, + "NotSentDueToError": 0, + "Queued": 0, + "r__folder_Path": "Triggered Sends", + "r__triggeredSend_name": "testExisting_triggeredSend", + "r__triggeredSend_key": "testExisting_triggeredSend" +} \ No newline at end of file diff --git a/test/resources/9999999/triggeredSendSummary/retrieve-response.xml b/test/resources/9999999/triggeredSendSummary/retrieve-response.xml new file mode 100644 index 000000000..83b05d267 --- /dev/null +++ b/test/resources/9999999/triggeredSendSummary/retrieve-response.xml @@ -0,0 +1,49 @@ +<?xml version="1.0" encoding="utf-8"?> +<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:xsd="http://www.w3.org/2001/XMLSchema" + xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing" + xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" + xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"> + <soap:Header> + <wsa:Action>RetrieveResponse</wsa:Action> + <wsa:MessageID>urn:uuid:8fe86c01-56d5-4c56-8ac2-991578c79485</wsa:MessageID> + <wsa:RelatesTo>urn:uuid:592f71ac-78a0-45a2-8cfe-37a91fc6cfd5</wsa:RelatesTo> + <wsa:To>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</wsa:To> + <wsse:Security> + <wsu:Timestamp wsu:Id="Timestamp-675af14a-b6a1-44a5-b7e7-4a76c6d18424"> + <wsu:Created>2023-02-01T10:29:21Z</wsu:Created> + <wsu:Expires>2023-02-01T10:34:21Z</wsu:Expires> + </wsu:Timestamp> + </wsse:Security> + </soap:Header> + <soap:Body> + <RetrieveResponseMsg xmlns="http://exacttarget.com/wsdl/partnerAPI"> + <OverallStatus>OK</OverallStatus> + <RequestID>a90dda5e-aeba-440a-82ce-74fb2abf5eb2</RequestID> + <Results xsi:type="TriggeredSendSummary"> + <PartnerKey xsi:nil="true" /> + <ObjectID>b3150cf0-6e78-e811-80d4-1402ec721c9d</ObjectID> + <CustomerKey>testExisting_triggeredSend</CustomerKey> + <Sent>10</Sent> + <NotSentDueToOptOut>0</NotSentDueToOptOut> + <NotSentDueToUndeliverable>0</NotSentDueToUndeliverable> + <Bounces>0</Bounces> + <Opens>0</Opens> + <Clicks>0</Clicks> + <UniqueOpens>0</UniqueOpens> + <UniqueClicks>0</UniqueClicks> + <OptOuts>0</OptOuts> + <SurveyResponses>0</SurveyResponses> + <FTAFRequests>0</FTAFRequests> + <FTAFEmailsSent>0</FTAFEmailsSent> + <FTAFOptIns>0</FTAFOptIns> + <Conversions>0</Conversions> + <UniqueConversions>0</UniqueConversions> + <InProcess>0</InProcess> + <NotSentDueToError>0</NotSentDueToError> + <Queued>0</Queued> + </Results> + </RetrieveResponseMsg> + </soap:Body> +</soap:Envelope> diff --git a/test/resources/9999999/verification/build-expected.json b/test/resources/9999999/verification/build-expected.json new file mode 100644 index 000000000..f7b3e2454 --- /dev/null +++ b/test/resources/9999999/verification/build-expected.json @@ -0,0 +1,11 @@ +{ + "c__automation_step": "testTemplated_automation__s1.7", + "notificationEmailAddress": "", + "notificationEmailMessage": "", + "r__dataExtension_key": "testTemplated_dataExtension", + "shouldEmailOnFailure": false, + "shouldStopOnFailure": true, + "value1": 1, + "value2": 0, + "verificationType": "IsEqualTo" +} diff --git a/test/resources/9999999/verification/get-expected.json b/test/resources/9999999/verification/get-expected.json new file mode 100644 index 000000000..e5346295a --- /dev/null +++ b/test/resources/9999999/verification/get-expected.json @@ -0,0 +1,12 @@ +{ + "c__automation_step": "testExisting_automation__s1.7", + "createdBy": "Jörn Berkefeld", + "notificationEmailAddress": "", + "notificationEmailMessage": "", + "r__dataExtension_key": "testExisting_dataExtension", + "shouldEmailOnFailure": false, + "shouldStopOnFailure": true, + "value1": 1, + "value2": 0, + "verificationType": "IsEqualTo" +} diff --git a/test/resources/9999999/verification/patch-expected.json b/test/resources/9999999/verification/patch-expected.json new file mode 100644 index 000000000..89387a627 --- /dev/null +++ b/test/resources/9999999/verification/patch-expected.json @@ -0,0 +1,12 @@ +{ + "createdBy": "Jörn Berkefeld", + "c__automation_step": "testExisting_automation__s1.7", + "notificationEmailAddress": "test@accenture.com", + "notificationEmailMessage": "", + "r__dataExtension_key": "testExisting_dataExtension", + "shouldEmailOnFailure": true, + "shouldStopOnFailure": true, + "value1": 1, + "value2": 0, + "verificationType": "IsEqualTo" +} diff --git a/test/resources/9999999/verification/post-expected.json b/test/resources/9999999/verification/post-expected.json new file mode 100644 index 000000000..1aaf67ad0 --- /dev/null +++ b/test/resources/9999999/verification/post-expected.json @@ -0,0 +1,12 @@ +{ + "createdBy": "Jörn Berkefeld", + "c__automation_step": "testNew_automation__s1.7", + "r__dataExtension_key": "testExisting_dataExtension", + "verificationType": "IsEqualTo", + "value1": 2, + "value2": 0, + "shouldStopOnFailure": false, + "shouldEmailOnFailure": false, + "notificationEmailAddress": "", + "notificationEmailMessage": "" +} diff --git a/test/resources/9999999/verification/template-expected.json b/test/resources/9999999/verification/template-expected.json new file mode 100644 index 000000000..16a7f4e51 --- /dev/null +++ b/test/resources/9999999/verification/template-expected.json @@ -0,0 +1,11 @@ +{ + "c__automation_step": "{{{prefix}}}automation__s1.7", + "notificationEmailAddress": "", + "notificationEmailMessage": "", + "r__dataExtension_key": "{{{prefix}}}dataExtension", + "shouldEmailOnFailure": false, + "shouldStopOnFailure": true, + "value1": 1, + "value2": 0, + "verificationType": "IsEqualTo" +} diff --git a/test/resources/auth.json b/test/resources/auth.json new file mode 100644 index 000000000..ed759adb7 --- /dev/null +++ b/test/resources/auth.json @@ -0,0 +1,32 @@ +{ + "success": { + "url": "https://mct0l7nxfq2r988t1kxfy8sc4xxx.auth.marketingcloudapis.com/v2/token", + "response": { + "access_token": "eyJhbGciOiJIUzI1NiIsImtpZCI6IjQiLCJ2ZXIiOiIxIiwidHlwIjoiSldUIn0.eyJhY2Nlc3NfdG9rZW4iOiI3UU9IYmJTd3JFOXRTYkdlTTQ4ZktXTXgiLCJjbGllbnRfaWQiOiIwbTBoZXQ2bXFrbnp2MHVlYnFsdm9vNDEiLCJlaWQiOjcyODE2OTgsInN0YWNrX2tleSI6IlM3IiwicGxhdGZvcm1fdmVyc2lvbiI6MiwiY2xpZW50X3R5cGUiOiJTZXJ2ZXJUb1NlcnZlciJ9.5TciRkgyCXpV232vUowRvGCR03-zT5d1NRBcZrIn1Z8.8_hnocm2nm2WkEu4KHNpyFrG60_TQ52XAVYmYSU8yyd452YL3Mzb6k_ieT9B2CWRI3dSvDARFK9bz59yjz1HWsUjP0ENXeyO6wEA8MpeVSkxlD6u6Q73ZtK2sAwsaFoSmx96HpjjhMWKxNEuESTl_Hp2Qfv_mXC2LNluVq3fYYKn7VSr4zaRTRB", + "token_type": "Bearer", + "expires_in": 1079, + "scope": "offline documents_and_images_read documents_and_images_write saved_content_read saved_content_write automations_execute automations_read automations_write journeys_execute journeys_read journeys_write email_read email_send email_write push_read push_send push_write sms_read sms_send sms_write social_post social_publish social_read social_write web_publish web_read web_write audiences_read audiences_write list_and_subscribers_read list_and_subscribers_write data_extensions_read data_extensions_write file_locations_read file_locations_write tracking_events_read calendar_read calendar_write campaign_read campaign_write accounts_read accounts_write users_read users_write webhooks_read webhooks_write workflows_write approvals_write tags_write approvals_read tags_read workflows_read ott_chat_messaging_read ott_chat_messaging_send ott_channels_read ott_channels_write marketing_cloud_connect_read marketing_cloud_connect_write marketing_cloud_connect_send event_notification_callback_create event_notification_callback_read event_notification_callback_update event_notification_callback_delete event_notification_subscription_create event_notification_subscription_read event_notification_subscription_update event_notification_subscription_delete tracking_events_write key_manage_view key_manage_rotate key_manage_revoke dfu_configure journeys_aspr journeys_delete package_manager_package package_manager_deploy deep_linking_asset_read deep_linking_asset_write deep_linking_asset_delete deep_linking_settings_read deep_linking_settings_write", + "soap_instance_url": "https://mct0l7nxfq2r988t1kxfy8sc4xxx.soap.marketingcloudapis.com/", + "rest_instance_url": "https://mct0l7nxfq2r988t1kxfy8sc4xxx.rest.marketingcloudapis.com/" + }, + "status": 200 + }, + "unauthorized": { + "url": "https://mct0l7nxfq2r988t1kxfy8sc47ma.auth.marketingcloudapis.com/v2/token", + "response": { + "error": "invalid_client", + "error_description": "Client authentication failed. Make sure that the client ID and client secret are valid and that the package is installed and enabled.", + "error_uri": "https://developer.salesforce.com/docs" + }, + "status": 401 + }, + "expired": { + "url": "https://mct0l7nxfq2r988t1kxfy8sc47ma.auth.marketingcloudapis.com/v2/token", + "response": { + "documentation": "https://developer.salesforce.com/docs/atlas.en-us.mc-apis.meta/mc-apis/error-handling.htm", + "errorcode": 0, + "message": "Not Authorized" + }, + "status": 401 + } +} diff --git a/test/resources/rest404-response.json b/test/resources/rest404-response.json new file mode 100644 index 000000000..7fddcdbd8 --- /dev/null +++ b/test/resources/rest404-response.json @@ -0,0 +1,5 @@ +{ + "documentation": "https://developer.salesforce.com/docs/atlas.en-us.mc-apis.meta/mc-apis/error-handling.htm", + "errorcode": 404, + "message": "Not Found" +} diff --git a/test/resources/retrieve-response.xml b/test/resources/retrieve-response.xml new file mode 100644 index 000000000..7045654e4 --- /dev/null +++ b/test/resources/retrieve-response.xml @@ -0,0 +1,21 @@ +<?xml version="1.0" encoding="utf-8"?> +<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing" xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"> + <soap:Header> + <wsa:Action>RetrieveResponse</wsa:Action> + <wsa:MessageID>urn:uuid:f36f3303-3b5a-4641-8109-b26447634d91</wsa:MessageID> + <wsa:RelatesTo>urn:uuid:33983968-28c4-4379-bb5f-f80ae32eb988</wsa:RelatesTo> + <wsa:To>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</wsa:To> + <wsse:Security> + <wsu:Timestamp wsu:Id="Timestamp-32ecc81b-6020-473c-9e99-4b5338921220"> + <wsu:Created>2022-04-19T20:03:41Z</wsu:Created> + <wsu:Expires>2022-04-19T20:08:41Z</wsu:Expires> + </wsu:Timestamp> + </wsse:Security> + </soap:Header> + <soap:Body> + <RetrieveResponseMsg xmlns="http://exacttarget.com/wsdl/partnerAPI"> + <OverallStatus>OK</OverallStatus> + <RequestID>02cd5ccb-8f84-4651-826f-71169eeecf05</RequestID> + </RetrieveResponseMsg> + </soap:Body> +</soap:Envelope> \ No newline at end of file diff --git a/test/type.asset.test.js b/test/type.asset.test.js new file mode 100644 index 000000000..aeeb133dc --- /dev/null +++ b/test/type.asset.test.js @@ -0,0 +1,1432 @@ +import File from '../lib/util/file.js'; + +import * as chai from 'chai'; +const assert = chai.assert; +const expect = chai.expect; + +import chaiFiles from 'chai-files'; +import cache from '../lib/util/cache.js'; +import * as testUtils from './utils.js'; +import handler from '../lib/index.js'; +chai.use(chaiFiles); + +/** + * gets file from Retrieve folder + * + * @param {string} customerKey of metadata + * @param {string} type of metadata + * @param {string} subtype of metadata + * @param {string} [buName] used when we need to test on ParentBU + * @returns {Promise.<string>} file in string form + */ +async function getActualJson(customerKey, type, subtype, buName = 'testBU') { + try { + return await File.readJSON( + `./retrieve/testInstance/${buName}/${type}/${subtype}/${customerKey}.${type}-${subtype}-meta.json` + ); + } catch { + return await File.readJSON( + `./retrieve/testInstance/${buName}/${type}/${subtype}/${customerKey}/${customerKey}.${type}-${subtype}-meta.json` + ); + } +} + +/** + * gets file from Retrieve folder + * + * @param {string} customerKey of metadata + * @param {string} type of metadata + * @param {string} subtype of metadata + * @param {string} ext file extension + * @param {string} [filename] optional fileprefix that differs from customerKey + * @param {string} [buName] used when we need to test on ParentBU + * @returns {Promise.<string | null>} file path + */ +async function getActualFile(customerKey, type, subtype, ext, filename, buName = 'testBU') { + const path = `./retrieve/testInstance/${buName}/${type}/${subtype}/${customerKey}.${type}-${subtype}-meta.${ext}`; + const pathSub = `./retrieve/testInstance/${buName}/${type}/${subtype}/${customerKey}/${filename}.${type}-${subtype}-meta.${ext}`; + + try { + return await File.readFile(filename ? pathSub : path, 'utf8'); + } catch { + console.log(`File not found: ${filename ? pathSub : path}`); // eslint-disable-line no-console + return null; + } +} + +/** + * gets file from Template folder + * + * @param {string} customerKey of metadata + * @param {string} type of metadata + * @param {string} subtype of metadata + * @returns {Promise.<string>} file in string form + */ +async function getActualTemplateJson(customerKey, type, subtype) { + try { + return await File.readJSON( + `./template/${type}/${subtype}/${customerKey}.${type}-${subtype}-meta.json` + ); + } catch { + return await File.readJSON( + `./template/${type}/${subtype}/${customerKey}/${customerKey}.${type}-${subtype}-meta.json` + ); + } +} + +/** + * gets file from Template folder + * + * @param {string} customerKey of metadata + * @param {string} type of metadata + * @param {string} subtype of metadata + * @param {string} ext file extension + * @param {string} [filename] optional fileprefix that differs from customerKey + * @returns {Promise.<string | undefined>} file + */ +async function getActualTemplateFile(customerKey, type, subtype, ext, filename) { + const path = `./template/${type}/${subtype}/${customerKey}.${type}-${subtype}-meta.${ext}`; + const pathSub = `./template/${type}/${subtype}/${customerKey}/${filename}.${type}-${subtype}-meta.${ext}`; + + try { + return File.readFile(filename ? pathSub : path, 'utf8'); + } catch { + console.log(`File not found: ${filename ? pathSub : path}`); // eslint-disable-line no-console + return; + } +} + +/** + * gets file from Deploy folder + * + * @param {string} customerKey of metadata + * @param {string} type of metadata + * @param {string} subtype of metadata + * @param {string} [buName] used when we need to test on ParentBU + * @returns {Promise.<string>} file in string form + */ +async function getActualDeployJson(customerKey, type, subtype, buName = 'testBU') { + try { + return await File.readJSON( + `./deploy/testInstance/${buName}/${type}/${subtype}/${customerKey}.${type}-${subtype}-meta.json` + ); + } catch { + return await File.readJSON( + `./deploy/testInstance/${buName}/${type}/${subtype}/${customerKey}/${customerKey}.${type}-${subtype}-meta.json` + ); + } +} + +/** + * gets file from Deploy folder + * + * @param {string} customerKey of metadata + * @param {string} type of metadata + * @param {string} subtype of metadata + * @param {string} ext file extension + * @param {string} [filename] optional fileprefix that differs from customerKey + * @param {string} [buName] used when we need to test on ParentBU + * @returns {Promise.<string | undefined>} file content + */ +async function getActualDeployFile(customerKey, type, subtype, ext, filename, buName = 'testBU') { + const path = `./deploy/testInstance/${buName}/${type}/${subtype}/${customerKey}.${type}-${subtype}-meta.${ext}`; + const pathSub = `./deploy/testInstance/${buName}/${type}/${subtype}/${customerKey}/${filename}.${type}-${subtype}-meta.${ext}`; + + try { + return File.readFile(filename ? pathSub : path, 'utf8'); + } catch { + console.log(`File not found: ${filename ? pathSub : path}`); // eslint-disable-line no-console + return; + } +} + +describe('type: asset', () => { + beforeEach(() => { + testUtils.mockSetup(); + }); + + afterEach(() => { + testUtils.mockReset(); + }); + + describe('Retrieve ================', () => { + it('Should retrieve a asset & ensure non-ssjs code is not removed', async () => { + // WHEN + const retrieve = await handler.retrieve('testInstance/testBU', ['asset']); + // THEN + assert.equal(process.exitCode, 0, 'retrieve should not have thrown an error'); + assert.equal( + retrieve['testInstance/testBU'].asset + ? Object.keys(retrieve['testInstance/testBU'].asset).length + : 0, + 12, + 'Unexpected number of assets in retrieve response' + ); + // get results from cache + const result = cache.getCache(); + assert.equal( + result.asset ? Object.keys(result.asset).length : 0, + 15, + 'Unexpected number of assets in cache' + ); + + assert.deepEqual( + await getActualJson('testExisting_asset_htmlblock', 'asset', 'block'), + await testUtils.getExpectedJson( + '9999999', + 'asset', + 'testExisting_asset_htmlblock-retrieve' + ), + 'returned metadata was not equal expected' + ); + expect( + await getActualFile('testExisting_asset_htmlblock', 'asset', 'block', 'html') + ).to.equal( + await testUtils.getExpectedFile( + '9999999', + 'asset', + 'testExisting_asset_htmlblock-retrieve', + 'html' + ) + ); + + assert.deepEqual( + await getActualJson('testExisting_asset_templatebasedemail', 'asset', 'message'), + await testUtils.getExpectedJson('9999999', 'asset', 'retrieve-templatebasedemail'), + 'returned metadata was not equal expected' + ); + expect( + await getActualFile( + 'testExisting_asset_templatebasedemail', + 'asset', + 'message', + 'html', + 'views.html.content' + ) + ).to.equal( + await testUtils.getExpectedFile( + '9999999', + 'asset', + 'retrieve-templatebasedemail-html', + 'html' + ) + ); + expect( + await getActualFile( + 'testExisting_asset_templatebasedemail', + 'asset', + 'message', + 'amp', + 'views.preheader.content' + ) + ).to.equal( + await testUtils.getExpectedFile( + '9999999', + 'asset', + 'retrieve-templatebasedemail-preheader', + 'amp' + ) + ); + + assert.deepEqual( + await getActualJson('test_coderesource_js', 'asset', 'coderesource'), + await testUtils.getExpectedJson( + '9999999', + 'asset', + 'test_coderesource_js-retrieve' + ), + 'returned metadata was not equal expected' + ); + expect( + await getActualFile('test_coderesource_js', 'asset', 'coderesource', 'js') + ).to.equal( + await testUtils.getExpectedFile( + '9999999', + 'asset', + 'test_coderesource_js-retrieve', + 'js' + ) + ); + + assert.deepEqual( + await getActualJson('test_coderesource_json', 'asset', 'coderesource'), + await testUtils.getExpectedJson( + '9999999', + 'asset', + 'test_coderesource_json-retrieve' + ), + 'returned metadata was not equal expected' + ); + expect( + await getActualFile('test_coderesource_json', 'asset', 'coderesource', 'jsonc') + ).to.equal( + await testUtils.getExpectedFile( + '9999999', + 'asset', + 'test_coderesource_json-retrieve', + 'jsonc' + ) + ); + + assert.deepEqual( + await getActualJson('test_coderesource_xml', 'asset', 'coderesource'), + await testUtils.getExpectedJson( + '9999999', + 'asset', + 'test_coderesource_xml-retrieve' + ), + 'returned metadata was not equal expected' + ); + expect( + await getActualFile('test_coderesource_xml', 'asset', 'coderesource', 'xml') + ).to.equal( + await testUtils.getExpectedFile( + '9999999', + 'asset', + 'test_coderesource_xml-retrieve', + 'xml' + ) + ); + + assert.equal( + testUtils.getAPIHistoryLength(), + 26, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + return; + }); + + it('Should retrieve asset-cloudpage', async () => { + // WHEN + const retrieve = await handler.retrieve('testInstance/testBU', ['asset-cloudpage']); + + // THEN + assert.equal(process.exitCode, 0, 'retrieve should not have thrown an error'); + assert.equal( + retrieve['testInstance/testBU'].asset + ? Object.keys(retrieve['testInstance/testBU'].asset).length + : 0, + 3, + 'Unexpected number of assets in retrieve response' + ); + // get results from cache + const result = cache.getCache(); + assert.equal( + result.asset ? Object.keys(result.asset).length : 0, + 13, + 'Unexpected number of assets in cache' + ); + + assert.deepEqual( + await getActualJson('test_landingpage', 'asset', 'cloudpage'), + await testUtils.getExpectedJson('9999999', 'asset', 'test_landingpage-retrieve'), + 'returned metadata was not equal expected' + ); + + assert.deepEqual( + await getActualJson('test_microsite', 'asset', 'cloudpage'), + await testUtils.getExpectedJson('9999999', 'asset', 'test_microsite-retrieve'), + 'returned metadata was not equal expected' + ); + + assert.deepEqual( + await getActualJson('test_interactivecontent', 'asset', 'cloudpage'), + await testUtils.getExpectedJson( + '9999999', + 'asset', + 'test_interactivecontent-retrieve' + ), + 'returned metadata was not equal expected' + ); + + assert.equal( + testUtils.getAPIHistoryLength(), + 10, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + return; + }); + + it('Should retrieve a asset by key', async () => { + // WHEN + const retrieve = await handler.retrieve( + 'testInstance/testBU', + ['asset'], + ['testExisting_asset_htmlblock'] + ); + + // THEN + assert.equal(process.exitCode, 0, 'retrieve should not have thrown an error'); + assert.equal( + retrieve['testInstance/testBU'].asset + ? Object.keys(retrieve['testInstance/testBU'].asset).length + : 0, + 1, + 'Unexpected number of assets in retrieve response' + ); + // get results from cache + const result = cache.getCache(); + assert.equal( + result.asset ? Object.keys(result.asset).length : 0, + 10, + 'Unexpected number of assets in cache' + ); + + assert.deepEqual( + await getActualJson('testExisting_asset_htmlblock', 'asset', 'block'), + await testUtils.getExpectedJson( + '9999999', + 'asset', + 'testExisting_asset_htmlblock-retrieve' + ), + 'returned metadata was not equal expected' + ); + + assert.equal( + testUtils.getAPIHistoryLength(), + 8, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + return; + }); + }); + + describe('Deploy ================', () => { + beforeEach(() => { + testUtils.mockSetup(true); + }); + + it('Should create an asset with mis-matching memberId, automatically adding the MID suffix', async () => { + handler.setOptions({ autoMidSuffix: true }); + // WHEN + const deployResult = await handler.deploy( + 'testInstance/testBU', + ['asset'], + ['testNew_asset'] + ); + // THEN + assert.equal(process.exitCode, 0, 'deploy should not have thrown an error'); + + // check how many items were deployed + assert.equal( + deployResult['testInstance/testBU']?.asset + ? Object.keys(deployResult['testInstance/testBU']?.asset).length + : 0, + 1, + 'Unexpected number of assets deployed' + ); + const upsertCallout = testUtils.getRestCallout('post', '/asset/v1/content/assets/'); + assert.equal( + upsertCallout?.customerKey, + 'testNew_asset-9999999', + 'customerKey should be testNew_asset-9999999 due to --autoMidSuffix' + ); + + // insert + assert.deepEqual( + await getActualJson('testNew_asset-9999999', 'asset', 'block'), + await testUtils.getExpectedJson('9999999', 'asset', 'create'), + 'returned metadata was not equal expected for create' + ); + + assert.equal( + testUtils.getAPIHistoryLength(), + 5, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + return; + }); + + it('Should update an asset with --matchName', async () => { + handler.setOptions({ matchName: true }); + // WHEN + const deployResult = await handler.deploy( + 'testInstance/testBU', + ['asset'], + ['testExisting_asset_html-matchName'] + ); + // THEN + assert.equal(process.exitCode, 0, 'deploy should not have thrown an error'); + + // check how many items were deployed + assert.equal( + deployResult['testInstance/testBU']?.asset + ? Object.keys(deployResult['testInstance/testBU']?.asset).length + : 0, + 1, + 'Unexpected number of assets deployed' + ); + const currentCache = cache.getCache(); + + const upsertCallout = testUtils.getRestCallout( + 'patch', + '/asset/v1/content/assets/1295064' + ); + assert.equal( + upsertCallout?.customerKey, + 'testExisting_asset_html-matchName', + 'customerKey should be testExisting_asset_html-matchName' + ); + assert.equal( + upsertCallout?.id, + currentCache.asset['testExisting_asset_htmlblock'].id, + 'id should be that of the existing testExisting_asset_htmlblock' + ); + + assert.equal( + testUtils.getAPIHistoryLength(), + 5, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + return; + }); + + it('Should not update an asset with --matchName due to multiple potential matches', async () => { + handler.setOptions({ matchName: true }); + // WHEN + const deployResult = await handler.deploy( + 'testInstance/testBU', + ['asset'], + ['testExisting_asset_html-matchNamFail'] + ); + // THEN + assert.equal(process.exitCode, 1, 'deploy should have thrown an error'); + + // check how many items were deployed + assert.equal( + deployResult['testInstance/testBU']?.asset + ? Object.keys(deployResult['testInstance/testBU']?.asset).length + : 0, + 0, + 'Unexpected number of assets deployed' + ); + + const upsertCallout = testUtils.getRestCallout('patch', '/asset/v1/content/assets/%'); + assert.equal(upsertCallout, null, 'there should have been no patch'); + + assert.equal( + testUtils.getAPIHistoryLength(), + 4, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + return; + }); + + it('Should create an asset with --matchName because it found no match', async () => { + handler.setOptions({ matchName: true }); + // WHEN + const deployResult = await handler.deploy( + 'testInstance/testBU', + ['asset'], + ['testExisting_asset_html-matchNameAdd'] + ); + // THEN + assert.equal(process.exitCode, 0, 'deploy should not have thrown an error'); + + // check how many items were deployed + assert.equal( + deployResult['testInstance/testBU']?.asset + ? Object.keys(deployResult['testInstance/testBU']?.asset).length + : 0, + 1, + 'Unexpected number of assets deployed' + ); + + const upsertCallout = testUtils.getRestCallout('post', '/asset/v1/content/assets/'); + assert.equal( + upsertCallout?.customerKey, + 'testExisting_asset_html-matchNameAdd', + 'asset.customerKey should be testExisting_asset_html-matchNameAdd' + ); + assert.equal( + upsertCallout?.id, + undefined, + 'asset.id should not be set as we are in a create call' + ); + + assert.equal( + testUtils.getAPIHistoryLength(), + 5, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + return; + }); + + it('Should create an asset with mis-matching memberId and --keySuffix', async () => { + handler.setOptions({ keySuffix: '_DEV' }); + // WHEN + const deployResult = await handler.deploy( + 'testInstance/testBU', + ['asset'], + ['testNew_asset'] + ); + // THEN + assert.equal(process.exitCode, 0, 'deploy should not have thrown an error'); + + // check how many items were deployed + assert.equal( + deployResult['testInstance/testBU']?.asset + ? Object.keys(deployResult['testInstance/testBU']?.asset).length + : 0, + 1, + 'Unexpected number of assets deployed' + ); + const upsertCallout = testUtils.getRestCallout('post', '/asset/v1/content/assets/'); + assert.equal( + upsertCallout?.customerKey, + 'testNew_asset_DEV', + 'customerKey should be testNew_asset_DEV due to --keySuffix' + ); + + assert.equal( + testUtils.getAPIHistoryLength(), + 5, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + return; + }); + + it('Should create an asset with mis-matching memberId', async () => { + // WHEN + const deployResult = await handler.deploy( + 'testInstance/testBU', + ['asset'], + ['testNew_asset'] + ); + // THEN + assert.equal(process.exitCode, 0, 'deploy should not have thrown an error'); + + // check how many items were deployed + assert.equal( + deployResult['testInstance/testBU']?.asset + ? Object.keys(deployResult['testInstance/testBU']?.asset).length + : 0, + 1, + 'Unexpected number of assets deployed' + ); + const upsertCallout = testUtils.getRestCallout('post', '/asset/v1/content/assets/'); + assert.equal( + upsertCallout?.customerKey, + 'testNew_asset', + 'customerKey should be testNew_asset' + ); + + assert.equal( + testUtils.getAPIHistoryLength(), + 5, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + return; + }); + + it('Should create an asset that loads a pre-existing content block via CBBK', async () => { + // WHEN + const deployResult = await handler.deploy('testInstance/testBU', { + asset: ['testNew_asset_withCBBK_preexisting'], + }); + // THEN + assert.equal(process.exitCode, 0, 'deploy should not have thrown an error'); + + // check how many items were deployed + assert.equal( + deployResult['testInstance/testBU']?.asset + ? Object.keys(deployResult['testInstance/testBU']?.asset).length + : 0, + 1, + 'Unexpected number of assets deployed' + ); + const upsertCallout = testUtils.getRestCallout('post', '/asset/v1/content/assets/'); + assert.equal( + upsertCallout?.customerKey, + 'testNew_asset_withCBBK_preexisting', + 'customerKey should be testNew_asset' + ); + + assert.equal( + testUtils.getAPIHistoryLength(), + 5, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + return; + }); + + it('Should not create an asset that attempts to load a non-existent content block via CBBK', async () => { + // WHEN + const deployResult = await handler.deploy('testInstance/testBU', { + asset: ['testNew_asset_withCBBK_notexisting'], + }); + // THEN + assert.equal(process.exitCode, 1, 'deploy should have thrown an error'); + + // check how many items were deployed + assert.equal( + deployResult['testInstance/testBU']?.asset + ? Object.keys(deployResult['testInstance/testBU']?.asset).length + : 0, + 0, + 'Unexpected number of assets deployed' + ); + + assert.equal( + testUtils.getAPIHistoryLength(), + 4, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + return; + }); + + it('Should create an asset that loads a content block via CBBK that is also created in the same package', async () => { + // WHEN + const deployResult = await handler.deploy('testInstance/testBU', { + asset: ['testNew_asset_withCBBK_notexisting', 'testNew_asset_htmlblock'], + }); + // THEN + assert.equal(process.exitCode, 0, 'deploy should not have thrown an error'); + + // check how many items were deployed + assert.deepEqual( + deployResult['testInstance/testBU']?.asset + ? Object.keys(deployResult['testInstance/testBU']?.asset) + : [], + ['testNew_asset_htmlblock', 'testNew_asset_withCBBK_notexisting'], + 'unexpected assets deployed' + ); + + // check if we really issued callouts for those 2 blocks AND if they were run in the right order despite the key list for deploy() getting it in the wrong order + const upsertCallouts = testUtils.getRestCallout( + 'post', + '/asset/v1/content/assets/', + true + ); + assert.equal( + upsertCallouts[0]?.customerKey, + 'testNew_asset_htmlblock', + 'first create callout not for expected asset' + ); + assert.equal( + upsertCallouts[1]?.customerKey, + 'testNew_asset_withCBBK_notexisting', + 'second create callout not for expected asset' + ); + + assert.equal( + testUtils.getAPIHistoryLength(), + 6, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + return; + }); + + it('Should not create an asset that attempts to load a non-existent content block via r__asset_key', async () => { + // WHEN + const deployResult = await handler.deploy('testInstance/testBU', { + asset: ['testNew_assetMessage'], + }); + // THEN + assert.equal(process.exitCode, 1, 'deploy should have thrown an error'); + + // check how many items were deployed + assert.equal( + deployResult['testInstance/testBU']?.asset + ? Object.keys(deployResult['testInstance/testBU']?.asset).length + : 0, + 0, + 'Unexpected number of assets deployed' + ); + + assert.equal( + testUtils.getAPIHistoryLength(), + 4, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + return; + }); + + it('Should create an asset that loads a content block via r__asset_key that is also created in the same package', async () => { + // WHEN + const deployResult = await handler.deploy('testInstance/testBU', { + asset: ['testNew_assetMessage', 'testNew_asset_htmlblock'], + }); + // THEN + assert.equal(process.exitCode, 0, 'deploy should not have thrown an error'); + + // check how many items were deployed + assert.deepEqual( + deployResult['testInstance/testBU']?.asset + ? Object.keys(deployResult['testInstance/testBU']?.asset) + : [], + ['testNew_asset_htmlblock', 'testNew_assetMessage'], + 'unexpected assets deployed' + ); + + // check if we really issued callouts for those 2 blocks AND if they were run in the right order despite the key list for deploy() getting it in the wrong order + const upsertCallouts = testUtils.getRestCallout( + 'post', + '/asset/v1/content/assets/', + true + ); + assert.equal( + upsertCallouts[0]?.customerKey, + 'testNew_asset_htmlblock', + 'first create callout not for expected asset' + ); + assert.equal( + upsertCallouts[1]?.customerKey, + 'testNew_assetMessage', + 'second create callout not for expected asset' + ); + + assert.equal( + testUtils.getAPIHistoryLength(), + 6, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + return; + }); + + it('Should create a templatebased email and its template connected via r__asset_key', async () => { + // WHEN + const deployResult = await handler.deploy('testInstance/testBU', { + asset: ['testNew_asset_templatebasedemail', 'testNew_asset_template'], + }); + // THEN + assert.equal(process.exitCode, 0, 'deploy should not have thrown an error'); + + // check how many items were deployed + assert.deepEqual( + deployResult['testInstance/testBU']?.asset + ? Object.keys(deployResult['testInstance/testBU']?.asset) + : [], + ['testNew_asset_template', 'testNew_asset_templatebasedemail'], + 'unexpected assets deployed' + ); + + // check if we really issued callouts for those 2 blocks AND if they were run in the right order despite the key list for deploy() getting it in the wrong order + const upsertCallouts = testUtils.getRestCallout( + 'post', + '/asset/v1/content/assets/', + true + ); + assert.equal( + upsertCallouts[0]?.customerKey, + 'testNew_asset_template', + 'first create callout not for expected asset' + ); + assert.equal( + upsertCallouts[1]?.customerKey, + 'testNew_asset_templatebasedemail', + 'second create callout not for expected asset' + ); + + assert.equal( + testUtils.getAPIHistoryLength(), + 6, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + return; + }); + }); + + describe('Templating ================', () => { + it('Should create a asset template via buildTemplate and build it', async () => { + // download first before we test buildTemplate + await handler.retrieve('testInstance/testBU', ['asset']); + + const expectedApiCallsRetrieve = 26; + assert.equal( + testUtils.getAPIHistoryLength(), + expectedApiCallsRetrieve, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + + // GIVEN there is a template + const result = await handler.buildTemplate( + 'testInstance/testBU', + 'asset', + ['testExisting_asset_templatebasedemail', 'testExisting_asset_htmlblock'], + ['testSourceMarket'] + ); + // WHEN + assert.equal(process.exitCode, 0, 'buildTemplate should not have thrown an error'); + assert.equal( + result.asset ? Object.keys(result.asset).length : 0, + 2, + 'unexpected number of assets templated' + ); + + // testExisting_asset_templatebasedemail + assert.deepEqual( + await getActualTemplateJson( + 'testExisting_asset_templatebasedemail', + 'asset', + 'message' + ), + await testUtils.getExpectedJson('9999999', 'asset', 'template-templatebasedemail'), + 'returned template JSON of buildTemplate was not equal expected' + ); + expect( + await getActualTemplateFile( + 'testExisting_asset_templatebasedemail', + 'asset', + 'message', + 'html', + 'views.html.content' + ) + ).to.equal( + await testUtils.getExpectedFile( + '9999999', + 'asset', + 'template-templatebasedemail-html', + 'html' + ) + ); + expect( + await getActualTemplateFile( + 'testExisting_asset_templatebasedemail', + 'asset', + 'message', + 'amp', + 'views.preheader.content' + ) + ).to.equal( + await testUtils.getExpectedFile( + '9999999', + 'asset', + 'template-templatebasedemail-preheader', + 'amp' + ) + ); + + const definitions = await handler.buildDefinition( + 'testInstance/testBU', + 'asset', + ['testExisting_asset_templatebasedemail', 'testExisting_asset_htmlblock'], + ['testTargetMarket'] + ); + assert.equal(process.exitCode, 0, 'buildDefinition should not have thrown an error'); + assert.equal( + definitions.asset ? Object.keys(definitions.asset).length : 0, + 2, + 'unexpected number of assets templated' + ); + + // testTemplated_asset_templatebasedemail + assert.deepEqual( + await getActualDeployJson( + 'testTemplated_asset_templatebasedemail', + 'asset', + 'message' + ), + await testUtils.getExpectedJson('9999999', 'asset', 'build-templatebasedemail'), + 'returned deployment JSON was not equal expected' + ); + expect( + await getActualDeployFile( + 'testTemplated_asset_templatebasedemail', + 'asset', + 'message', + 'html', + 'views.html.content' + ) + ).to.equal( + await testUtils.getExpectedFile( + '9999999', + 'asset', + 'build-templatebasedemail-html', + 'html' + ) + ); + expect( + await getActualDeployFile( + 'testTemplated_asset_templatebasedemail', + 'asset', + 'message', + 'amp', + 'views.preheader.content' + ) + ).to.equal( + await testUtils.getExpectedFile( + '9999999', + 'asset', + 'build-templatebasedemail-preheader', + 'amp' + ) + ); + + // testTemplated_asset_htmlblock + assert.deepEqual( + await getActualDeployJson('testTemplated_asset_htmlblock', 'asset', 'block'), + await testUtils.getExpectedJson('9999999', 'asset', 'build-asset_htmlblock'), + 'returned deployment JSON was not equal expected' + ); + expect( + await getActualDeployFile('testTemplated_asset_htmlblock', 'asset', 'block', 'html') + ).to.equal( + await testUtils.getExpectedFile('9999999', 'asset', 'build-asset_htmlblock', 'html') + ); + + assert.equal( + testUtils.getAPIHistoryLength() - expectedApiCallsRetrieve, + 0, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + return; + }); + + it('Should create a asset template via buildTemplate with --dependencies', async () => { + // download first before we test buildTemplate + await handler.retrieve('testInstance/testBU', ['asset']); + + const expectedApiCallsRetrieve = 26; + assert.equal( + testUtils.getAPIHistoryLength(), + expectedApiCallsRetrieve, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + handler.setOptions({ dependencies: true, skipInteraction: true }); + + // GIVEN there is a template + const templatedItems = await handler.buildTemplate( + 'testInstance/testBU', + 'asset', + ['testExisting_asset_templatebasedemail'], + ['testSourceMarket'] + ); + // WHEN + assert.equal(process.exitCode, 0, 'buildTemplate should not have thrown an error'); + assert.equal( + templatedItems.asset ? templatedItems.asset.length : 0, + 6, + 'Unexpted number of assets templated' + ); + assert.deepEqual( + templatedItems.asset.map((item) => item.customerKey), + [ + '{{{prefix}}}asset_htmlblock', + '{{{prefix}}}asset_template', + '{{{prefix}}}asset_templatebasedemail', + '{{{prefix}}}htmlblock 3 spaces', + '{{{prefix}}}htmlblock1', + '{{{prefix}}}htmlblock2', + ], + 'expected specific assets to be templated' + ); + + // testExisting_asset_templatebasedemail + assert.deepEqual( + await getActualTemplateJson( + 'testExisting_asset_templatebasedemail', + 'asset', + 'message' + ), + await testUtils.getExpectedJson('9999999', 'asset', 'template-templatebasedemail'), + 'returned template JSON of buildTemplate was not equal expected' + ); + + expect( + await getActualTemplateFile( + 'testExisting_asset_templatebasedemail', + 'asset', + 'message', + 'html', + 'views.html.content' + ) + ).to.equal( + await testUtils.getExpectedFile( + '9999999', + 'asset', + 'template-templatebasedemail-html', + 'html' + ) + ); + expect( + await getActualTemplateFile( + 'testExisting_asset_templatebasedemail', + 'asset', + 'message', + 'amp', + 'views.preheader.content' + ) + ).to.equal( + await testUtils.getExpectedFile( + '9999999', + 'asset', + 'template-templatebasedemail-preheader', + 'amp' + ) + ); + + // testExisting_asset_template + assert.deepEqual( + await getActualTemplateJson('testExisting_asset_template', 'asset', 'template'), + await testUtils.getExpectedJson('9999999', 'asset', 'template-emailTemplate'), + 'returned template JSON of buildTemplate was not equal expected' + ); + + // testExisting_asset_htmlblock + assert.deepEqual( + await getActualTemplateJson('testExisting_asset_htmlblock', 'asset', 'block'), + await testUtils.getExpectedJson( + '9999999', + 'asset', + 'template-testExisting_asset_htmlblock' + ), + 'returned template JSON of buildTemplate was not equal expected' + ); + + assert.equal( + testUtils.getAPIHistoryLength() - expectedApiCallsRetrieve, + 4, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + return; + }); + }); + + describe('Delete ================', () => { + it('Should delete the item', async () => { + // WHEN + const isDeleted = await handler.deleteByKey( + 'testInstance/testBU', + 'asset', + 'testExisting_asset' + ); + // THEN + assert.equal(process.exitCode, 0, 'deleteByKey should not have thrown an error'); + assert.equal(isDeleted, true, 'deleteByKey should have returned true'); + return; + }); + }); + + describe('ResolveID ================', () => { + it('Should resolve the id of the item but NOT find the asset locally', async () => { + // WHEN + const resolveIdJson = await handler.resolveId( + 'testInstance/testBU', + 'asset', + '1295064' + ); + // THEN + assert.equal(process.exitCode, 0, 'resolveId should not have thrown an error'); + assert.deepEqual( + resolveIdJson, + await testUtils.getExpectedJson('9999999', 'asset', 'resolveId-1295064-noPath'), + 'returned response was not equal expected' + ); + return; + }); + + it('Should resolve the id with --json option enabled', async () => { + handler.setOptions({ json: true }); + // WHEN + await handler.resolveId('testInstance/testBU', 'asset', '1295064'); + // THEN + assert.equal(process.exitCode, 0, 'resolveId should not have thrown an error'); + return; + }); + + it('Should resolve the id of the item AND find the asset locally', async () => { + // prep test by retrieving the file + await handler.retrieve( + 'testInstance/testBU', + ['asset-block'], + ['testExisting_asset_htmlblock'] + ); + // WHEN + const resolveIdJson = await handler.resolveId( + 'testInstance/testBU', + 'asset', + '1295064' + ); + // THEN + assert.equal(process.exitCode, 0, 'resolveId should not have thrown an error'); + assert.deepEqual( + resolveIdJson, + await testUtils.getExpectedJson('9999999', 'asset', 'resolveId-1295064-withPath'), + 'returned response was not equal expected' + ); + return; + }); + + it('Should NOT resolve the id of the item', async () => { + // WHEN + const resolveIdJson = await handler.resolveId('testInstance/testBU', 'asset', '-1234'); + // THEN + assert.equal(process.exitCode, 404, 'resolveId should have thrown an error'); + // IMPORTANT: this will throw a false "TEST-ERROR" but our testing framework currently needs to not find the file to throw a 404 + assert.deepEqual( + resolveIdJson, + await testUtils.getExpectedJson('9999999', 'asset', 'resolveId-1234-notFound'), + 'returned response was not equal expected' + ); + return; + }); + }); + + describe('ReplaceContentBlockByX ================', () => { + it('Should replace references with ContentBlockByName w/o deploy', async () => { + handler.setOptions({ skipDeploy: true }); + + // WHEN + const replace = await handler.replaceCbReference( + 'testInstance/testBU', + { + asset: null, + }, + 'name' + ); + // THEN + assert.equal(process.exitCode, 0, 'retrieve should not have thrown an error'); + // retrieve result + assert.deepEqual( + replace['testInstance/testBU'].asset, + [ + 'testExisting_asset_htmlblock', + 'testExisting_htmlblock1', + 'testExisting_htmlblock 3 spaces', + 'testExisting_asset_message', + ], + 'should have found the right assets that need updating' + ); + // get results from cache + const result = cache.getCache(); + assert.equal( + result.asset ? Object.keys(result.asset).length : 0, + 12, + 'Unexpected number of assets in cache' + ); + // check if conversions happened + expect( + await getActualFile( + 'testExisting_asset_message', + 'asset', + 'message', + 'html', + 'views.html.content' + ) + ).to.equal( + await testUtils.getExpectedFile( + '9999999', + 'asset', + 'testExisting_asset_message-html-rcb-name', + 'html' + ) + ); + expect( + await getActualFile( + 'testExisting_asset_message', + 'asset', + 'message', + 'amp', + 'views.preheader.content' + ) + ).to.equal( + await testUtils.getExpectedFile( + '9999999', + 'asset', + 'testExisting_asset_message-preheader-rcb-name', + 'amp' + ) + ); + expect( + await getActualFile( + 'testExisting_asset_message', + 'asset', + 'message', + 'amp', + 'views.text.content' + ) + ).to.equal( + await testUtils.getExpectedFile( + '9999999', + 'asset', + 'testExisting_asset_message-text-rcb-name', + 'amp' + ) + ); + + assert.equal( + testUtils.getAPIHistoryLength(), + 28, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + return; + }); + + it('Should replace references with ContentBlockById w/o deploy', async () => { + handler.setOptions({ skipDeploy: true }); + + // WHEN + const replace = await handler.replaceCbReference( + 'testInstance/testBU', + { + asset: null, + }, + 'id' + ); + // THEN + assert.equal(process.exitCode, 0, 'retrieve should not have thrown an error'); + // retrieve result + assert.deepEqual( + replace['testInstance/testBU'].asset, + [ + 'testExisting_htmlblock1', + 'testExisting_htmlblock 3 spaces', + 'testExisting_asset_message', + ], + 'should have found the right assets that need updating' + ); + // get results from cache + const result = cache.getCache(); + assert.equal( + result.asset ? Object.keys(result.asset).length : 0, + 12, + 'Unexpected number of assets in cache' + ); + // check if conversions happened + expect( + await getActualFile( + 'testExisting_asset_message', + 'asset', + 'message', + 'html', + 'views.html.content' + ) + ).to.equal( + await testUtils.getExpectedFile( + '9999999', + 'asset', + 'testExisting_asset_message-html-rcb-id', + 'html' + ) + ); + expect( + await getActualFile( + 'testExisting_asset_message', + 'asset', + 'message', + 'amp', + 'views.preheader.content' + ) + ).to.equal( + await testUtils.getExpectedFile( + '9999999', + 'asset', + 'testExisting_asset_message-preheader-rcb-id', + 'amp' + ) + ); + expect( + await getActualFile( + 'testExisting_asset_message', + 'asset', + 'message', + 'amp', + 'views.text.content' + ) + ).to.equal( + await testUtils.getExpectedFile( + '9999999', + 'asset', + 'testExisting_asset_message-text-rcb-id', + 'amp' + ) + ); + + assert.equal( + testUtils.getAPIHistoryLength(), + 28, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + return; + }); + + it('Should replace references with ContentBlockByKey w/o deploy', async () => { + handler.setOptions({ skipDeploy: true }); + + // WHEN + const replace = await handler.replaceCbReference( + 'testInstance/testBU', + { + asset: null, + }, + 'key' + ); + // THEN + assert.equal(process.exitCode, 0, 'retrieve should not have thrown an error'); + // retrieve result + assert.deepEqual( + replace['testInstance/testBU'].asset, + [ + 'testExisting_asset_htmlblock', + 'testExisting_htmlblock1', + 'testExisting_asset_message', + ], + 'should have found the right assets that need updating' + ); + // get results from cache + const result = cache.getCache(); + assert.equal( + result.asset ? Object.keys(result.asset).length : 0, + 12, + 'Unexpected number of assets in cache' + ); + // check if conversions happened + expect( + await getActualFile( + 'testExisting_asset_message', + 'asset', + 'message', + 'html', + 'views.html.content' + ) + ).to.equal( + await testUtils.getExpectedFile( + '9999999', + 'asset', + 'testExisting_asset_message-html-rcb-key', + 'html' + ) + ); + expect( + await getActualFile( + 'testExisting_asset_message', + 'asset', + 'message', + 'amp', + 'views.preheader.content' + ) + ).to.equal( + await testUtils.getExpectedFile( + '9999999', + 'asset', + 'testExisting_asset_message-preheader-rcb-key', + 'amp' + ) + ); + expect( + await getActualFile( + 'testExisting_asset_message', + 'asset', + 'message', + 'amp', + 'views.text.content' + ) + ).to.equal( + await testUtils.getExpectedFile( + '9999999', + 'asset', + 'testExisting_asset_message-text-rcb-key', + 'amp' + ) + ); + + assert.equal( + testUtils.getAPIHistoryLength(), + 28, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + return; + }); + }); +}); diff --git a/test/type.attributeGroup.test.js b/test/type.attributeGroup.test.js new file mode 100644 index 000000000..57c0ad955 --- /dev/null +++ b/test/type.attributeGroup.test.js @@ -0,0 +1,56 @@ +import * as chai from 'chai'; +const assert = chai.assert; + +import chaiFiles from 'chai-files'; +import cache from '../lib/util/cache.js'; +import * as testUtils from './utils.js'; +import handler from '../lib/index.js'; +chai.use(chaiFiles); + +describe('type: attributeGroup', () => { + beforeEach(() => { + testUtils.mockSetup(); + }); + + afterEach(() => { + testUtils.mockReset(); + }); + + describe('Retrieve ================', () => { + it('Should retrieve a attributeGroup', async () => { + // WHEN + const retrieve = await handler.retrieve('testInstance/testBU', ['attributeGroup']); + + // THEN + assert.equal(process.exitCode, 0, 'retrieve should not have thrown an error'); + assert.equal( + retrieve['testInstance/testBU'].attributeGroup + ? Object.keys(retrieve['testInstance/testBU'].attributeGroup).length + : 0, + 8, + 'only 8 attributeGroups expected in retrieve response' + ); + + // get results from cache + const result = cache.getCache(); + assert.equal( + result.attributeGroup ? Object.keys(result.attributeGroup).length : 0, + 8, + 'only 8 attributeGroups expected in cache' + ); + assert.deepEqual( + await testUtils.getActualJson('ETMobileConnect', 'attributeGroup'), + await testUtils.getExpectedJson('9999999', 'attributeGroup', 'retrieve'), + + 'returned metadata was not equal expected' + ); + + assert.equal( + testUtils.getAPIHistoryLength(), + 2, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + return; + }); + }); +}); diff --git a/test/type.attributeSet.test.js b/test/type.attributeSet.test.js new file mode 100644 index 000000000..08c1302e8 --- /dev/null +++ b/test/type.attributeSet.test.js @@ -0,0 +1,56 @@ +import * as chai from 'chai'; +const assert = chai.assert; + +import chaiFiles from 'chai-files'; +import cache from '../lib/util/cache.js'; +import * as testUtils from './utils.js'; +import handler from '../lib/index.js'; +chai.use(chaiFiles); + +describe('type: attributeSet', () => { + beforeEach(() => { + testUtils.mockSetup(); + }); + + afterEach(() => { + testUtils.mockReset(); + }); + + describe('Retrieve ================', () => { + it('Should retrieve a attributeSet', async () => { + // WHEN + const retrieve = await handler.retrieve('testInstance/testBU', ['attributeSet']); + + // THEN + assert.equal(process.exitCode, 0, 'retrieve should not have thrown an error'); + assert.equal( + retrieve['testInstance/testBU'].attributeSet + ? Object.keys(retrieve['testInstance/testBU'].attributeSet).length + : 0, + 28, + 'only 28 attributeSets expected in retrieve response' + ); + // get results from cache + const result = cache.getCache(); + assert.equal( + result.attributeSet ? Object.keys(result.attributeSet).length : 0, + 28, + 'only 28 attributeSets expected in cache' + ); + + assert.deepEqual( + await testUtils.getActualJson('testExisting_dataExtensionShared', 'attributeSet'), + await testUtils.getExpectedJson('9999999', 'attributeSet', 'retrieve'), + + 'returned metadata was not equal expected' + ); + + assert.equal( + testUtils.getAPIHistoryLength(), + 7, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + return; + }); + }); +}); diff --git a/test/type.automation.test.js b/test/type.automation.test.js new file mode 100644 index 000000000..d2205f81d --- /dev/null +++ b/test/type.automation.test.js @@ -0,0 +1,1003 @@ +import * as chai from 'chai'; +const assert = chai.assert; +const expect = chai.expect; + +import chaiFiles from 'chai-files'; +import cache from '../lib/util/cache.js'; +import * as testUtils from './utils.js'; +import handler from '../lib/index.js'; +chai.use(chaiFiles); + +describe('type: automation', () => { + beforeEach(() => { + testUtils.mockSetup(); + }); + + afterEach(() => { + testUtils.mockReset(); + }); + + describe('Retrieve ================', () => { + it('Should retrieve a automation', async () => { + // WHEN + await handler.retrieve('testInstance/testBU', ['automation']); + // THEN + assert.equal(process.exitCode, 0, 'retrieve should not have thrown an error'); + // get results from cache + const result = cache.getCache(); + assert.equal( + result.automation ? Object.keys(result.automation).length : 0, + 6, + 'unexpected number of automations' + ); + assert.deepEqual( + await testUtils.getActualJson('testExisting_automation', 'automation'), + await testUtils.getExpectedJson('9999999', 'automation', 'retrieve'), + + 'returned metadata was not equal expected' + ); + // check if MD file was created and equals expectations + expect(await testUtils.getActualDoc('testExisting_automation', 'automation')).to.equal( + await testUtils.getExpectedFile( + '9999999', + 'automation', + 'retrieve-testExisting_automation', + 'md' + ) + ); + assert.deepEqual( + await testUtils.getActualJson('testExisting_automation_wait', 'automation'), + await testUtils.getExpectedJson('9999999', 'automation', 'retrieve-wait'), + + 'returned metadata was not equal expected' + ); + expect( + await testUtils.getActualDoc('testExisting_automation_wait', 'automation') + ).to.equal( + await testUtils.getExpectedFile('9999999', 'automation', 'retrieve-wait', 'md') + ); + assert.equal( + testUtils.getAPIHistoryLength(), + 34, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + return; + }); + }); + + describe('Deploy ================', () => { + beforeEach(() => { + testUtils.mockSetup(true); + }); + + it('Should create & update a automation', async () => { + // WHEN + const deployResult = await handler.deploy( + 'testInstance/testBU', + ['automation', 'verification'], + ['testExisting_automation', 'testNew_automation', 'testNew_automation__s1.7'] + ); + // THEN + assert.equal(process.exitCode, 0, 'deploy should not have thrown an error'); + + // check how many items were deployed + assert.equal( + deployResult['testInstance/testBU']?.automation + ? Object.keys(deployResult['testInstance/testBU']?.automation).length + : 0, + 2, + 'two automations to be deployed' + ); + + // get results from cache + const cacheResult = cache.getCache(); + assert.equal( + cacheResult.automation ? Object.keys(cacheResult.automation).length : 0, + 7, + 'unexpected number of automations in cache' + ); + // get what was sent to the server API + const createCallout = testUtils.getRestCallout('post', '/automation/v1/automations/%'); + const updateCallout = testUtils.getRestCallout('patch', '/automation/v1/automations/%'); + + // insert + assert.deepEqual( + createCallout, + await testUtils.getExpectedJson('9999999', 'automation', 'create-callout'), + 'sent metadata was not equal expected for create' + ); + assert.deepEqual( + await testUtils.getActualJson('testNew_automation', 'automation'), + await testUtils.getExpectedJson('9999999', 'automation', 'create'), + 'returned metadata was not equal expected for create' + ); + // update + assert.deepEqual( + updateCallout, + await testUtils.getExpectedJson('9999999', 'automation', 'update-callout'), + 'sent metadata was not equal expected for create' + ); + assert.deepEqual( + await testUtils.getActualJson('testExisting_automation', 'automation'), + await testUtils.getExpectedJson('9999999', 'automation', 'update'), + 'returned metadata was not equal expected for update' + ); + // check if MD file was created and equals expectations + expect(await testUtils.getActualDoc('testExisting_automation', 'automation')).to.equal( + await testUtils.getExpectedFile( + '9999999', + 'automation', + 'update-testExisting_automation', + 'md' + ) + ); + + // check if MD file was created and equals expectations + expect(await testUtils.getActualDoc('testNew_automation', 'automation')).to.equal( + await testUtils.getExpectedFile( + '9999999', + 'automation', + 'create-testNew_automation', + 'md' + ) + ); + + assert.equal( + testUtils.getAPIHistoryLength(), + 52, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + return; + }); + + it('Should update & schedule an automation with --schedule option', async () => { + // WHEN + handler.setOptions({ schedule: true }); + const deployed = await handler.deploy( + 'testInstance/testBU', + ['automation', 'verification'], + ['testExisting_automation', 'testNew_automation', 'testNew_automation__s1.7'] + ); + // THEN + assert.equal( + process.exitCode, + 0, + 'deploy with --execute should not have thrown an error' + ); + + // get results from cache + const cached = cache.getCache(); + assert.equal( + cached.automation ? Object.keys(cached.automation).length : 0, + 7, + 'unexpected number of automations in cache' + ); + + assert.equal( + deployed['testInstance/testBU'].automation + ? Object.keys(deployed['testInstance/testBU'].automation).length + : 0, + 2, + 'two deployed automation expected' + ); + assert.equal( + deployed['testInstance/testBU'].automation + ? Object.keys(deployed['testInstance/testBU'].automation)[0] + : null, + 'testNew_automation', + 'expected specific automation to have been deployed' + ); + assert.equal( + deployed['testInstance/testBU'].automation + ? Object.keys(deployed['testInstance/testBU'].automation)[1] + : null, + 'testExisting_automation', + 'expected specific automation to have been deployed' + ); + + assert.deepEqual( + await testUtils.getActualJson('testExisting_automation', 'automation'), + await testUtils.getExpectedJson('9999999', 'automation', 'update'), + 'returned metadata was not equal expected for update' + ); + // check if MD file was created and equals expectations + expect(await testUtils.getActualDoc('testExisting_automation', 'automation')).to.equal( + await testUtils.getExpectedFile( + '9999999', + 'automation', + 'update-testExisting_automation', + 'md' + ) + ); + + assert.equal( + testUtils.getAPIHistoryLength(), + 56, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + return; + }); + + it('Should update & runOnce an automation with --execute option', async () => { + // WHEN + handler.setOptions({ execute: true }); + const deployed = await handler.deploy( + 'testInstance/testBU', + ['automation', 'verification'], + ['testExisting_automation', 'testNew_automation', 'testNew_automation__s1.7'] + ); + // THEN + assert.equal( + process.exitCode, + 0, + 'deploy with --execute should not have thrown an error' + ); + + // get results from cache + const cached = cache.getCache(); + assert.equal( + cached.automation ? Object.keys(cached.automation).length : 0, + 7, + 'unexpected number of automations in cache' + ); + assert.equal( + deployed['testInstance/testBU'].automation + ? Object.keys(deployed['testInstance/testBU'].automation).length + : 0, + 2, + 'two deployed automation expected' + ); + assert.equal( + deployed['testInstance/testBU'].automation + ? Object.keys(deployed['testInstance/testBU'].automation)[0] + : null, + 'testNew_automation', + 'expected specific automation to have been deployed' + ); + assert.equal( + deployed['testInstance/testBU'].automation + ? Object.keys(deployed['testInstance/testBU'].automation)[1] + : null, + 'testExisting_automation', + 'expected specific automation to have been deployed' + ); + // update + assert.deepEqual( + await testUtils.getActualJson('testExisting_automation', 'automation'), + await testUtils.getExpectedJson('9999999', 'automation', 'update'), + 'returned metadata was not equal expected for update' + ); + // check if MD file was created and equals expectations + expect(await testUtils.getActualDoc('testExisting_automation', 'automation')).to.equal( + await testUtils.getExpectedFile( + '9999999', + 'automation', + 'update-testExisting_automation', + 'md' + ) + ); + + assert.equal( + testUtils.getAPIHistoryLength(), + 56, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + return; + }); + }); + + describe('FixKeys ================', () => { + beforeEach(() => { + testUtils.mockSetup(true); + }); + + it('Should run fixKeys but not find fixable keys and hence stop', async () => { + // WHEN + handler.setOptions({ skipInteraction: { fixKeysReretrieve: false } }); + const resultFixKeys = await handler.fixKeys( + 'testInstance/testBU', + ['automation'], + ['testExisting_automation'] + ); + // THEN + assert.equal(process.exitCode, 0, 'fixKeys should not have thrown an error'); + // check which keys were fixed + assert.equal( + resultFixKeys['testInstance/testBU']['automation'].length, + 0, + 'expected to find no keys to be fixed' + ); + + // get results from cache + const result = cache.getCache(); + assert.equal( + result.automation ? Object.keys(result.automation).length : 0, + 1, + 'one automation expected' + ); + // check number of API calls + assert.equal( + testUtils.getAPIHistoryLength(), + 28, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + return; + }); + + it('Should fixKeys by key w/o re-retrieving, auto-schedule', async () => { + // WHEN + handler.setOptions({ skipInteraction: { fixKeysReretrieve: false } }); + const resultFixKeys = await handler.fixKeys( + 'testInstance/testBU', + ['automation'], + ['testExisting_automation_fixKey_schedule', 'testExisting_automation'] + ); + assert.equal( + resultFixKeys['testInstance/testBU']['automation'].length, + 1, + 'returned number of keys does not correspond to number of expected fixed keys' + ); + assert.equal( + resultFixKeys['testInstance/testBU']['automation'][0], + 'testExisting_automation_fixedKey_scheduled', + 'returned keys do not correspond to expected fixed keys' + ); + // THEN + assert.equal(process.exitCode, 0, 'fixKeys should not have thrown an error'); + // confirm updated item + assert.deepEqual( + await testUtils.getActualJson( + 'testExisting_automation_fixedKey_scheduled', + 'automation' + ), + await testUtils.getExpectedJson('9999999', 'automation', 'patch_fixKeys-schedule'), + 'returned metadata was not equal expected for update automation' + ); + expect( + await testUtils.getActualDoc( + 'testExisting_automation_fixedKey_scheduled', + 'automation' + ) + ).to.exist; + // check number of API calls + assert.equal( + testUtils.getAPIHistoryLength(), + 74, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + return; + }); + + it('Should fixKeys by key w/o re-retrieving, auto-schedule and then --execute', async () => { + // WHEN + handler.setOptions({ skipInteraction: { fixKeysReretrieve: false }, execute: true }); + const resultFixKeys = await handler.fixKeys( + 'testInstance/testBU', + ['automation'], + ['testExisting_automation_fixKey_schedule', 'testExisting_automation'] + ); + assert.equal( + resultFixKeys['testInstance/testBU']['automation'].length, + 1, + 'returned number of keys does not correspond to number of expected fixed keys' + ); + assert.equal( + resultFixKeys['testInstance/testBU']['automation'][0], + 'testExisting_automation_fixedKey_scheduled', + 'returned keys do not correspond to expected fixed keys' + ); + // THEN + assert.equal(process.exitCode, 0, 'fixKeys should not have thrown an error'); + // confirm updated item + assert.deepEqual( + await testUtils.getActualJson( + 'testExisting_automation_fixedKey_scheduled', + 'automation' + ), + await testUtils.getExpectedJson('9999999', 'automation', 'patch_fixKeys-schedule'), + 'returned metadata was not equal expected for update automation' + ); + expect( + await testUtils.getActualDoc( + 'testExisting_automation_fixedKey_scheduled', + 'automation' + ) + ).to.exist; + // check number of API calls + assert.equal( + testUtils.getAPIHistoryLength(), + 76, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + return; + }); + + it('Should fixKeys by key w/o re-retrieving, auto-schedule and then --schedule', async () => { + // WHEN + handler.setOptions({ skipInteraction: { fixKeysReretrieve: false }, schedule: true }); + const resultFixKeys = await handler.fixKeys( + 'testInstance/testBU', + ['automation'], + ['testExisting_automation_fixKey_schedule', 'testExisting_automation'] + ); + assert.equal( + resultFixKeys['testInstance/testBU']['automation'].length, + 1, + 'returned number of keys does not correspond to number of expected fixed keys' + ); + assert.equal( + resultFixKeys['testInstance/testBU']['automation'][0], + 'testExisting_automation_fixedKey_scheduled', + 'returned keys do not correspond to expected fixed keys' + ); + // THEN + assert.equal(process.exitCode, 0, 'fixKeys should not have thrown an error'); + // confirm updated item + assert.deepEqual( + await testUtils.getActualJson( + 'testExisting_automation_fixedKey_scheduled', + 'automation' + ), + await testUtils.getExpectedJson('9999999', 'automation', 'patch_fixKeys-schedule'), + 'returned metadata was not equal expected for update automation' + ); + expect( + await testUtils.getActualDoc( + 'testExisting_automation_fixedKey_scheduled', + 'automation' + ) + ).to.exist; + // check number of API calls + assert.equal( + testUtils.getAPIHistoryLength(), + 76, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + return; + }); + + it('Should fixKeys by key w/o re-retrieving, deploy paused', async () => { + // WHEN + handler.setOptions({ skipInteraction: { fixKeysReretrieve: false } }); + const resultFixKeys = await handler.fixKeys( + 'testInstance/testBU', + ['automation'], + ['testExisting_automation_fixKey_pause'] + ); + assert.equal( + resultFixKeys['testInstance/testBU']['automation'].length, + 1, + 'returned number of keys does not correspond to number of expected fixed keys' + ); + assert.equal( + resultFixKeys['testInstance/testBU']['automation'][0], + 'testExisting_automation_fixedKey_paused', + 'returned keys do not correspond to expected fixed keys' + ); + // THEN + assert.equal(process.exitCode, 0, 'fixKeys should not have thrown an error'); + // confirm updated item + assert.deepEqual( + await testUtils.getActualJson( + 'testExisting_automation_fixedKey_paused', + 'automation' + ), + await testUtils.getExpectedJson('9999999', 'automation', 'patch_fixKeys-pause'), + 'returned metadata was not equal expected for update automation' + ); + expect( + await testUtils.getActualDoc( + 'testExisting_automation_fixedKey_paused', + 'automation' + ) + ).to.exist; + // check number of API calls + assert.equal( + testUtils.getAPIHistoryLength(), + 69, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + return; + }); + + it('Should fixKeys by key w/o re-retrieving, deploy paused and then --execute', async () => { + // WHEN + handler.setOptions({ skipInteraction: { fixKeysReretrieve: false }, execute: true }); + const resultFixKeys = await handler.fixKeys( + 'testInstance/testBU', + ['automation'], + ['testExisting_automation_fixKey_pause', 'testExisting_automation'] + ); + assert.equal( + resultFixKeys['testInstance/testBU']['automation'].length, + 1, + 'returned number of keys does not correspond to number of expected fixed keys' + ); + assert.equal( + resultFixKeys['testInstance/testBU']['automation'][0], + 'testExisting_automation_fixedKey_paused', + 'returned keys do not correspond to expected fixed keys' + ); + // THEN + assert.equal(process.exitCode, 0, 'fixKeys should not have thrown an error'); + // confirm updated item + assert.deepEqual( + await testUtils.getActualJson( + 'testExisting_automation_fixedKey_paused', + 'automation' + ), + await testUtils.getExpectedJson('9999999', 'automation', 'patch_fixKeys-pause'), + 'returned metadata was not equal expected for update automation' + ); + expect( + await testUtils.getActualDoc( + 'testExisting_automation_fixedKey_paused', + 'automation' + ) + ).to.exist; + // check number of API calls + assert.equal( + testUtils.getAPIHistoryLength(), + 76, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + return; + }); + + it('Should fixKeys by key w/o re-retrieving, deploy paused and then --schedule', async () => { + // WHEN + handler.setOptions({ skipInteraction: { fixKeysReretrieve: false }, schedule: true }); + const resultFixKeys = await handler.fixKeys( + 'testInstance/testBU', + ['automation'], + ['testExisting_automation_fixKey_pause', 'testExisting_automation'] + ); + assert.equal( + resultFixKeys['testInstance/testBU']['automation'].length, + 1, + 'returned number of keys does not correspond to number of expected fixed keys' + ); + assert.equal( + resultFixKeys['testInstance/testBU']['automation'][0], + 'testExisting_automation_fixedKey_paused', + 'returned keys do not correspond to expected fixed keys' + ); + // THEN + assert.equal(process.exitCode, 0, 'fixKeys should not have thrown an error'); + // confirm updated item + assert.deepEqual( + await testUtils.getActualJson( + 'testExisting_automation_fixedKey_paused', + 'automation' + ), + await testUtils.getExpectedJson('9999999', 'automation', 'patch_fixKeys-pause'), + 'returned metadata was not equal expected for update automation' + ); + expect( + await testUtils.getActualDoc( + 'testExisting_automation_fixedKey_paused', + 'automation' + ) + ).to.exist; + // check number of API calls + assert.equal( + testUtils.getAPIHistoryLength(), + 76, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + return; + }); + }); + + describe('Templating ================', () => { + it('Should create a automation template via retrieveAsTemplate and build it', async () => { + // GIVEN there is a template + const result = await handler.retrieveAsTemplate( + 'testInstance/testBU', + 'automation', + ['testExisting_automation'], + 'testSourceMarket' + ); + assert.equal(process.exitCode, 0, 'retrieveAsTemplate should not have thrown an error'); + + // WHEN + assert.equal( + result.automation ? Object.keys(result.automation).length : 0, + 1, + 'only one automation expected' + ); + assert.deepEqual( + await testUtils.getActualTemplateJson('testExisting_automation', 'automation'), + await testUtils.getExpectedJson('9999999', 'automation', 'template'), + 'returned template was not equal expected' + ); + // THEN + await handler.buildDefinition( + 'testInstance/testBU', + 'automation', + ['testExisting_automation'], + ['testTargetMarket'] + ); + assert.equal(process.exitCode, 0, 'buildDefinition should not have thrown an error'); + assert.deepEqual( + await testUtils.getActualDeployJson('testTemplated_automation', 'automation'), + await testUtils.getExpectedJson('9999999', 'automation', 'build'), + 'returned deployment file was not equal expected' + ); + assert.equal( + testUtils.getAPIHistoryLength(), + 30, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + return; + }); + + it('Should create a automation template via buildTemplate and build it', async () => { + // download first before we test buildTemplate + await handler.retrieve('testInstance/testBU', ['automation']); + // GIVEN there is a template + const result = await handler.buildTemplate( + 'testInstance/testBU', + 'automation', + ['testExisting_automation'], + ['testSourceMarket'] + ); + assert.equal(process.exitCode, 0, 'buildTemplate should not have thrown an error'); + // WHEN + assert.equal( + result.automation ? Object.keys(result.automation).length : 0, + 1, + 'only one automation expected' + ); + assert.deepEqual( + await testUtils.getActualTemplateJson('testExisting_automation', 'automation'), + await testUtils.getExpectedJson('9999999', 'automation', 'template'), + 'returned template was not equal expected' + ); + // THEN + await handler.buildDefinition( + 'testInstance/testBU', + 'automation', + ['testExisting_automation'], + ['testTargetMarket'] + ); + assert.equal(process.exitCode, 0, 'buildDefinition should not have thrown an error'); + + assert.deepEqual( + await testUtils.getActualDeployJson('testTemplated_automation', 'automation'), + await testUtils.getExpectedJson('9999999', 'automation', 'build'), + 'returned deployment file was not equal expected' + ); + assert.equal( + testUtils.getAPIHistoryLength(), + 34, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + return; + }); + + it('Should create a automation template via buildTemplate with --dependencies', async () => { + // download first before we test buildTemplate + await handler.retrieve('testInstance/testBU'); + assert.equal(process.exitCode, 0, 'retrieve should not have thrown an error'); + + const expectedApiCallsRetrieve = 109; + assert.equal( + testUtils.getAPIHistoryLength(), + expectedApiCallsRetrieve, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + + // preparation + // set skipInteraction to true to skip re-retrieving question + handler.setOptions({ dependencies: true, skipInteraction: true }); + + // GIVEN there is a template + const templateResult = await handler.buildTemplate( + 'testInstance/testBU', + 'automation', + ['testExisting_automation'], + ['testSourceMarket'] + ); + assert.equal(process.exitCode, 0, 'buildTemplate should not have thrown an error'); + // WHEN + // check type list + assert.deepEqual( + Object.keys(templateResult), + [ + 'automation', + 'dataExtension', + 'dataExtract', + 'domainVerification', + 'emailSend', + 'fileTransfer', + 'importFile', + 'query', + 'script', + 'sendClassification', + 'senderProfile', + 'verification', + ], + 'did not create deployment packages for all relevant types' + ); + + assert.equal( + templateResult.automation ? Object.keys(templateResult.automation).length : 0, + 1, + 'only one automation expected' + ); + assert.deepEqual( + await testUtils.getActualTemplateJson('testExisting_automation', 'automation'), + await testUtils.getExpectedJson('9999999', 'automation', 'template'), + 'returned template was not equal expected' + ); + assert.equal( + testUtils.getAPIHistoryLength() - expectedApiCallsRetrieve, + 4, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + return; + }); + }); + + describe('Delete ================', () => { + it('Should delete the item', async () => { + // WHEN + const isDeleted = await handler.deleteByKey( + 'testInstance/testBU', + 'automation', + 'testExisting_automation' + ); + // THEN + assert.equal(process.exitCode, 0, 'delete should not have thrown an error'); + + assert.equal(isDeleted, true, 'should have deleted the item'); + return; + }); + }); + + describe('CI/CD ================', () => { + it('Should return a list of files based on their type and key', async () => { + // WHEN + const fileList = await handler.getFilesToCommit('testInstance/testBU', 'automation', [ + 'testExisting_automation', + ]); + // THEN + assert.equal(process.exitCode, 0, 'getFilesToCommit should not have thrown an error'); + assert.equal(fileList.length, 2, 'expected only 2 file paths'); + + assert.equal( + fileList[0].split('\\').join('/'), + 'retrieve/testInstance/testBU/automation/testExisting_automation.automation-meta.json', + 'wrong JSON path' + ); + assert.equal( + fileList[1].split('\\').join('/'), + 'retrieve/testInstance/testBU/automation/testExisting_automation.automation-doc.md', + 'wrong MD path' + ); + return; + }); + }); + + describe('Schedule ================', () => { + it('Should schedule an automation by key', async () => { + const scheduled = await handler.schedule( + 'testInstance/testBU', + ['automation'], + ['testExisting_automation'] + ); + assert.equal(process.exitCode, 0, 'execute should not have thrown an error'); + assert.equal( + scheduled['testInstance/testBU']?.automation?.length, + 1, + 'returned number of keys does not correspond to number of expected fixed keys' + ); + assert.equal( + scheduled['testInstance/testBU']?.automation[0], + 'testExisting_automation', + 'returned keys do not correspond to expected fixed keys' + ); + return; + }); + + it('Should schedule an automation selected via --like', async () => { + handler.setOptions({ like: { key: 'testExist%automation' } }); + const scheduled = await handler.schedule('testInstance/testBU', ['automation']); + assert.equal(process.exitCode, 0, 'execute should not have thrown an error'); + assert.equal( + scheduled['testInstance/testBU']?.automation?.length, + 1, + 'returned number of keys does not correspond to number of expected fixed keys' + ); + assert.equal( + scheduled['testInstance/testBU']?.automation[0], + 'testExisting_automation', + 'returned keys do not correspond to expected fixed keys' + ); + return; + }); + + it('Should not schedule executing an automation because key and --like was specified', async () => { + handler.setOptions({ like: { key: 'testExisting%' } }); + const scheduled = await handler.schedule( + 'testInstance/testBU', + ['automation'], + ['testExisting_automation'] + ); + assert.equal(process.exitCode, 1, 'execute should have thrown an error'); + assert.equal( + Object.keys(scheduled).length, + 0, + 'automation was not supposed to be executed' + ); + return; + }); + }); + + describe('Execute ================', () => { + it('Should execute --schedule an automation by key', async () => { + handler.setOptions({ schedule: true }); + const executedKeys = await handler.execute( + 'testInstance/testBU', + ['automation'], + ['testExisting_automation'] + ); + assert.equal(process.exitCode, 0, 'execute should not have thrown an error'); + assert.equal( + executedKeys['testInstance/testBU']?.automation?.length, + 1, + 'returned number of keys does not correspond to number of expected fixed keys' + ); + assert.equal( + executedKeys['testInstance/testBU']?.automation[0], + 'testExisting_automation', + 'returned keys do not correspond to expected fixed keys' + ); + return; + }); + + it('Should execute --schedule an automation selected via --like', async () => { + handler.setOptions({ like: { key: 'testExist%automation' }, schedule: true }); + const executedKeys = await handler.execute('testInstance/testBU', ['automation']); + assert.equal(process.exitCode, 0, 'execute should not have thrown an error'); + assert.equal( + executedKeys['testInstance/testBU']?.automation?.length, + 1, + 'returned number of keys does not correspond to number of expected fixed keys' + ); + assert.equal( + executedKeys['testInstance/testBU']?.automation[0], + 'testExisting_automation', + 'returned keys do not correspond to expected fixed keys' + ); + return; + }); + + it('Should not execute --schedule executing an automation because key and --like was specified', async () => { + handler.setOptions({ like: { key: 'testExisting%' }, schedule: true }); + const executedKeys = await handler.execute( + 'testInstance/testBU', + ['automation'], + ['testExisting_automation'] + ); + assert.equal(process.exitCode, 1, 'execute should have thrown an error'); + assert.equal( + Object.keys(executedKeys).length, + 0, + 'automation was not supposed to be executed' + ); + return; + }); + + it('Should runOnce an automation by key', async () => { + const executedKeys = await handler.execute( + 'testInstance/testBU', + ['automation'], + ['testExisting_automation'] + ); + assert.equal(process.exitCode, 0, 'execute should not have thrown an error'); + assert.equal( + executedKeys['testInstance/testBU']?.automation?.length, + 1, + 'automation was supposed to be executed' + ); + assert.equal( + executedKeys['testInstance/testBU']?.automation[0], + 'testExisting_automation', + 'returned keys do not correspond to expected fixed keys' + ); + return; + }); + + it('Should runOnce an automation selected via --like', async () => { + handler.setOptions({ like: { key: 'testExist%automation' } }); + const executedKeys = await handler.execute('testInstance/testBU', ['automation']); + assert.equal(process.exitCode, 0, 'execute should not have thrown an error'); + assert.equal( + executedKeys['testInstance/testBU']?.automation?.length, + 1, + 'automation was supposed to be executed' + ); + assert.equal( + executedKeys['testInstance/testBU']?.automation[0], + 'testExisting_automation', + 'returned keys do not correspond to expected fixed keys' + ); + + return; + }); + + it('Should not runOnce executing an automation because key and --like was specified', async () => { + handler.setOptions({ like: { key: 'testExisting%' } }); + const executedKeys = await handler.execute( + 'testInstance/testBU', + ['automation'], + ['testExisting_automation'] + ); + assert.equal(process.exitCode, 1, 'execute should have thrown an error'); + assert.equal( + Object.keys(executedKeys).length, + 0, + 'automation was not supposed to be executed' + ); + + return; + }); + }); + + describe('Pause ================', () => { + it('Should pause a automation by key', async () => { + const pausedKeys = await handler.pause( + 'testInstance/testBU', + ['automation'], + ['testExisting_automation_pause'] + ); + assert.equal(process.exitCode, 0, 'pause should not have thrown an error'); + assert.equal( + pausedKeys['testInstance/testBU']?.automation?.length, + 1, + 'returned number of keys does not correspond to number of expected fixed keys' + ); + assert.equal( + pausedKeys['testInstance/testBU']?.automation[0], + 'testExisting_automation_pause', + 'returned keys do not correspond to expected fixed keys' + ); + return; + }); + + it('Should pause a automation selected via --like', async () => { + handler.setOptions({ like: { key: 'testExisting_a%n_pause' } }); + const pausedKeys = await handler.pause('testInstance/testBU', ['automation']); + assert.equal(process.exitCode, 0, 'pause should not have thrown an error'); + assert.equal( + pausedKeys['testInstance/testBU']?.automation?.length, + 1, + 'returned number of keys does not correspond to number of expected fixed keys' + ); + assert.equal( + pausedKeys['testInstance/testBU']?.automation[0], + 'testExisting_automation_pause', + 'returned keys do not correspond to expected fixed keys' + ); + return; + }); + + it('Should not pause automation because key and --like was specified', async () => { + handler.setOptions({ like: { key: 'testExisting_a%n_pause' } }); + const pausedKeys = await handler.pause( + 'testInstance/testBU', + ['automation'], + ['testExisting_automation_pause'] + ); + assert.equal(process.exitCode, 1, 'pause should have thrown an error'); + assert.equal( + Object.keys(pausedKeys).length, + 0, + 'returned number of keys does not correspond to number of expected fixed keys' + ); + return; + }); + }); +}); diff --git a/test/type.dataExtension.test.js b/test/type.dataExtension.test.js new file mode 100644 index 000000000..7fd95951a --- /dev/null +++ b/test/type.dataExtension.test.js @@ -0,0 +1,419 @@ +import * as chai from 'chai'; +const assert = chai.assert; +const expect = chai.expect; + +import chaiFiles from 'chai-files'; +import cache from '../lib/util/cache.js'; +import * as testUtils from './utils.js'; +import handler from '../lib/index.js'; +chai.use(chaiFiles); + +describe('type: dataExtension', () => { + beforeEach(() => { + testUtils.mockSetup(); + }); + + afterEach(() => { + testUtils.mockReset(); + }); + + describe('Retrieve ================', () => { + it('Should retrieve a dataExtension', async () => { + // WHEN + await handler.retrieve('testInstance/testBU', ['dataExtension']); + // THEN + assert.equal(process.exitCode, 0, 'retrieve should not have thrown an error'); + // get results from cache + const result = cache.getCache(); + assert.equal( + result.dataExtension ? Object.keys(result.dataExtension).length : 0, + 8, + 'unexpected number of dataExtension' + ); + assert.deepEqual( + await testUtils.getActualJson('testExisting_dataExtension', 'dataExtension'), + await testUtils.getExpectedJson('9999999', 'dataExtension', 'retrieve'), + + 'returned metadata was not equal expected' + ); + // check if MD file was created and equals expectations + expect( + await testUtils.getActualDoc('testExisting_dataExtension', 'dataExtension') + ).to.equal( + await testUtils.getExpectedFile('9999999', 'dataExtension', 'retrieve', 'md') + ); + + assert.equal( + testUtils.getAPIHistoryLength(), + 5, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + return; + }); + + it('Should retrieve a shared dataExtension', async () => { + // WHEN + await handler.retrieve('testInstance/_ParentBU_', ['dataExtension']); + // THEN + assert.equal(process.exitCode, 0, 'retrieve should not have thrown an error'); + // get results from cache + const result = cache.getCache(); + assert.equal( + result.dataExtension ? Object.keys(result.dataExtension).length : 0, + 1, + 'only one dataExtension expected' + ); + assert.deepEqual( + await testUtils.getActualJson( + 'testExisting_dataExtensionShared', + 'dataExtension', + '_ParentBU_' + ), + await testUtils.getExpectedJson('1111111', 'dataExtension', 'retrieve'), + + 'returned metadata was not equal expected' + ); + // check if MD file was created and equals expectations + expect( + await testUtils.getActualDoc( + 'testExisting_dataExtensionShared', + 'dataExtension', + '_ParentBU_' + ) + ).to.equal( + await testUtils.getExpectedFile('1111111', 'dataExtension', 'retrieve', 'md') + ); + + assert.equal( + testUtils.getAPIHistoryLength(), + 4, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + return; + }); + + it('Should not fail if shared dataExtension cannot be retrieved', async () => { + // WHEN + await handler.retrieve('testInstance/_ParentBU_', ['dataExtension', 'query']); + // THEN + assert.equal(process.exitCode, 0, 'retrieve should not have thrown an error'); + // get results from cache + const result = cache.getCache(); + assert.equal( + result.dataExtension ? Object.keys(result.dataExtension).length : 0, + 1, + 'only one dataExtension expected' + ); + assert.deepEqual( + await testUtils.getActualJson( + 'testExisting_dataExtensionShared', + 'dataExtension', + '_ParentBU_' + ), + await testUtils.getExpectedJson('1111111', 'dataExtension', 'retrieve'), + + 'returned metadata was not equal expected' + ); + // check if MD file was created and equals expectations + expect( + await testUtils.getActualDoc( + 'testExisting_dataExtensionShared', + 'dataExtension', + '_ParentBU_' + ) + ).to.equal( + await testUtils.getExpectedFile('1111111', 'dataExtension', 'retrieve', 'md') + ); + + assert.equal( + testUtils.getAPIHistoryLength(), + 7, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + return; + }); + }); + + describe('Deploy ================', () => { + beforeEach(() => { + testUtils.mockSetup(true); + }); + + it('Should create & update a dataExtension including a field rename', async () => { + // WHEN + const deployResult = await handler.deploy('testInstance/testBU', ['dataExtension']); + // THEN + assert.equal(process.exitCode, 0, 'deploy should not have thrown an error'); + + assert.equal( + deployResult['testInstance/testBU']?.dataExtension + ? Object.keys(deployResult['testInstance/testBU']?.dataExtension).length + : 0, + 2, + 'two dataExtensions to be deployed' + ); + + // get results from cache + const result = cache.getCache(); + assert.equal( + result.dataExtension ? Object.keys(result.dataExtension).length : 0, + 10, + 'unexpected number of dataExtensions' + ); + // insert + assert.deepEqual( + await testUtils.getActualJson('testNew_dataExtension', 'dataExtension'), + await testUtils.getExpectedJson('9999999', 'dataExtension', 'create'), + 'returned metadata was not equal expected for create' + ); + // update + assert.deepEqual( + await testUtils.getActualJson('testExisting_dataExtension', 'dataExtension'), + await testUtils.getExpectedJson('9999999', 'dataExtension', 'update'), + 'returned metadata was not equal expected for update' + ); + assert.equal( + testUtils.getAPIHistoryLength(), + 10, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + return; + }); + + it('Should create & update a shared dataExtension', async () => { + // WHEN + const deployResult = await handler.deploy('testInstance/_ParentBU_', ['dataExtension']); + // THEN + assert.equal(process.exitCode, 0, 'deploy should not have thrown an error'); + + assert.equal( + deployResult['testInstance/_ParentBU_']?.dataExtension + ? Object.keys(deployResult['testInstance/_ParentBU_']?.dataExtension).length + : 0, + 2, + 'two dataExtensions to be deployed' + ); + + // get results from cache + const result = cache.getCache(); + assert.equal( + result.dataExtension ? Object.keys(result.dataExtension).length : 0, + 2, + 'two dataExtensions expected' + ); + // insert + assert.deepEqual( + await testUtils.getActualJson( + 'testNew_dataExtensionShared', + 'dataExtension', + '_ParentBU_' + ), + await testUtils.getExpectedJson('1111111', 'dataExtension', 'create'), + 'returned metadata was not equal expected for create' + ); + // update + assert.deepEqual( + await testUtils.getActualJson( + 'testExisting_dataExtensionShared', + 'dataExtension', + '_ParentBU_' + ), + await testUtils.getExpectedJson('1111111', 'dataExtension', 'update'), + 'returned metadata was not equal expected for update' + ); + assert.equal( + testUtils.getAPIHistoryLength(), + 7, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + return; + }); + + it('Should create & update a shared dataExtension with --fixShared & --skipInteraction', async () => { + // WHEN + handler.setOptions({ fixShared: 'testBU', skipInteraction: true, _runningTest: true }); + + const deployResult = await handler.deploy('testInstance/_ParentBU_', ['dataExtension']); + // THEN + assert.equal(process.exitCode, 0, 'deploy should not have thrown an error'); + + assert.equal( + deployResult['testInstance/_ParentBU_']?.dataExtension + ? Object.keys(deployResult['testInstance/_ParentBU_']?.dataExtension).length + : 0, + 2, + 'two dataExtensions to be deployed' + ); + + // get results from cache + const result = cache.getCache(); + assert.equal( + result.dataExtension ? Object.keys(result.dataExtension).length : 0, + 2, + 'two dataExtensions expected' + ); + // insert + assert.deepEqual( + await testUtils.getActualJson( + 'testNew_dataExtensionShared', + 'dataExtension', + '_ParentBU_' + ), + await testUtils.getExpectedJson('1111111', 'dataExtension', 'create'), + 'returned metadata was not equal expected for create' + ); + // update + assert.deepEqual( + await testUtils.getActualJson( + 'testExisting_dataExtensionShared', + 'dataExtension', + '_ParentBU_' + ), + await testUtils.getExpectedJson('1111111', 'dataExtension', 'update'), + 'returned metadata was not equal expected for update' + ); + assert.equal( + testUtils.getAPIHistoryLength(), + 11, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + return; + }); + }); + + describe('Templating ================', () => { + it('Should create a dataExtension template via retrieveAsTemplate and build it', async () => { + // GIVEN there is a template + const result = await handler.retrieveAsTemplate( + 'testInstance/testBU', + 'dataExtension', + ['testExisting_dataExtension'], + 'testSourceMarket' + ); + assert.equal(process.exitCode, 0, 'retrieveAsTemplate should not have thrown an error'); + + // WHEN + assert.equal( + result.dataExtension ? Object.keys(result.dataExtension).length : 0, + 1, + 'only one dataExtension expected' + ); + assert.deepEqual( + await testUtils.getActualTemplateJson( + 'testExisting_dataExtension', + 'dataExtension' + ), + await testUtils.getExpectedJson('9999999', 'dataExtension', 'template'), + 'returned template was not equal expected' + ); + // THEN + await handler.buildDefinition( + 'testInstance/testBU', + 'dataExtension', + ['testExisting_dataExtension'], + ['testTargetMarket'] + ); + assert.equal(process.exitCode, 0, 'buildDefinition should not have thrown an error'); + assert.deepEqual( + await testUtils.getActualDeployJson('testTemplated_dataExtension', 'dataExtension'), + await testUtils.getExpectedJson('9999999', 'dataExtension', 'build'), + 'returned deployment file was not equal expected' + ); + assert.equal( + testUtils.getAPIHistoryLength(), + 5, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + return; + }); + + it('Should create a dataExtension template via buildTemplate and build it', async () => { + // download first before we test buildTemplate + await handler.retrieve('testInstance/testBU', ['dataExtension']); + // GIVEN there is a template + const result = await handler.buildTemplate( + 'testInstance/testBU', + 'dataExtension', + ['testExisting_dataExtension'], + ['testSourceMarket'] + ); + assert.equal(process.exitCode, 0, 'buildTemplate should not have thrown an error'); + // WHEN + assert.equal( + result.dataExtension ? Object.keys(result.dataExtension).length : 0, + 1, + 'only one dataExtension expected' + ); + assert.deepEqual( + await testUtils.getActualTemplateJson( + 'testExisting_dataExtension', + 'dataExtension' + ), + await testUtils.getExpectedJson('9999999', 'dataExtension', 'template'), + 'returned template was not equal expected' + ); + // THEN + await handler.buildDefinition( + 'testInstance/testBU', + 'dataExtension', + ['testExisting_dataExtension'], + ['testTargetMarket'] + ); + assert.equal(process.exitCode, 0, 'buildDefinition should not have thrown an error'); + + assert.deepEqual( + await testUtils.getActualDeployJson('testTemplated_dataExtension', 'dataExtension'), + await testUtils.getExpectedJson('9999999', 'dataExtension', 'build'), + 'returned deployment file was not equal expected' + ); + assert.equal( + testUtils.getAPIHistoryLength(), + 5, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + return; + }); + }); + + describe('Delete ================', () => { + it('Should delete the dataExtension', async () => { + // WHEN + const isDeleted = await handler.deleteByKey( + 'testInstance/testBU', + 'dataExtension', + 'testExisting_dataExtension' + ); + // THEN + assert.equal(process.exitCode, 0, 'delete should not have thrown an error'); + + assert.equal(isDeleted, true, 'should have deleted the item'); + return; + }); + }); + + describe('CI/CD ================', () => { + it('Should return a list of files based on their type and key', async () => { + // WHEN + const fileList = await handler.getFilesToCommit( + 'testInstance/testBU', + 'dataExtension', + ['testExisting_dataExtension'] + ); + // THEN + assert.equal(process.exitCode, 0, 'getFilesToCommit should not have thrown an error'); + assert.equal(fileList.length, 2, 'expected only 2 file paths (json, md)'); + + assert.equal( + fileList[0].split('\\').join('/'), + 'retrieve/testInstance/testBU/dataExtension/testExisting_dataExtension.dataExtension-meta.json', + 'wrong JSON path' + ); + assert.equal( + fileList[1].split('\\').join('/'), + 'retrieve/testInstance/testBU/dataExtension/testExisting_dataExtension.dataExtension-doc.md', + 'wrong MD path' + ); + return; + }); + }); +}); diff --git a/test/type.dataExtensionField.test.js b/test/type.dataExtensionField.test.js new file mode 100644 index 000000000..67b959763 --- /dev/null +++ b/test/type.dataExtensionField.test.js @@ -0,0 +1,81 @@ +import * as chai from 'chai'; +const assert = chai.assert; + +import chaiFiles from 'chai-files'; +import * as testUtils from './utils.js'; +import handler from '../lib/index.js'; +chai.use(chaiFiles); + +describe('type: dataExtensionField', () => { + beforeEach(() => { + testUtils.mockSetup(); + }); + + afterEach(() => { + testUtils.mockReset(); + }); + + describe('Delete ================', () => { + it('Should delete the dataExtensionField', async () => { + // WHEN + const isDeleted = await handler.deleteByKey( + 'testInstance/testBU', + 'dataExtensionField', + 'testExisting_dataExtension.LastName' + ); + // THEN + assert.equal(process.exitCode, 0, 'delete should not have thrown an error'); + + assert.equal(isDeleted, true, 'should have deleted the item'); + + assert.equal( + testUtils.getAPIHistoryLength(), + 2, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + return; + }); + + it('Should mass-delete the dataExtensionField across all dataExtensions', async () => { + handler.setOptions({ skipInteraction: true }); + // WHEN + const isDeleted = await handler.deleteByKey( + 'testInstance/testBU', + 'dataExtensionField', + '*.LastName' + ); + // THEN + assert.equal(process.exitCode, 0, 'delete should not have thrown an error'); + + assert.equal(isDeleted, true, 'should have deleted the item'); + + assert.equal( + testUtils.getAPIHistoryLength(), + 4, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + return; + }); + + it('Should mass-delete multiple dataExtensionFields across all dataExtensions', async () => { + handler.setOptions({ skipInteraction: true }); + // WHEN + const isDeleted = await handler.deleteByKey( + 'testInstance/testBU', + 'dataExtensionField', + ['*.FirstName', '*.LastName'] + ); + // THEN + assert.equal(process.exitCode, 0, 'delete should not have thrown an error'); + + assert.equal(isDeleted, true, 'should have deleted the item'); + + assert.equal( + testUtils.getAPIHistoryLength(), + 8, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + return; + }); + }); +}); diff --git a/test/type.dataExtract.test.js b/test/type.dataExtract.test.js new file mode 100644 index 000000000..183336a89 --- /dev/null +++ b/test/type.dataExtract.test.js @@ -0,0 +1,186 @@ +import * as chai from 'chai'; +const assert = chai.assert; + +import chaiFiles from 'chai-files'; +import cache from '../lib/util/cache.js'; +import * as testUtils from './utils.js'; +import handler from '../lib/index.js'; +chai.use(chaiFiles); + +describe('type: dataExtract', () => { + beforeEach(() => { + testUtils.mockSetup(); + }); + + afterEach(() => { + testUtils.mockReset(); + }); + + describe('Retrieve ================', () => { + it('Should retrieve a dataExtract', async () => { + // WHEN + await handler.retrieve('testInstance/testBU', ['dataExtract']); + // THEN + assert.equal(process.exitCode, 0, 'retrieve should not have thrown an error'); + // get results from cache + const result = cache.getCache(); + assert.equal( + result.dataExtract ? Object.keys(result.dataExtract).length : 0, + 1, + 'only one dataExtract expected' + ); + assert.deepEqual( + await testUtils.getActualJson('testExisting_dataExtract', 'dataExtract'), + await testUtils.getExpectedJson('9999999', 'dataExtract', 'get'), + 'returned JSON was not equal expected' + ); + assert.equal( + testUtils.getAPIHistoryLength(), + 9, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + return; + }); + }); + + describe('Deploy ================', () => { + beforeEach(() => { + testUtils.mockSetup(true); + }); + + it('Should create & upsert a dataExtract', async () => { + // WHEN + + await handler.deploy('testInstance/testBU', ['dataExtract']); + // THEN + assert.equal(process.exitCode, 0, 'deploy should not have thrown an error'); + // get results from cache + const result = cache.getCache(); + assert.equal( + result.dataExtract ? Object.keys(result.dataExtract).length : 0, + 2, + 'two dataExtracts expected' + ); + // confirm created item + assert.deepEqual( + await testUtils.getActualJson('testNew_dataExtract', 'dataExtract'), + await testUtils.getExpectedJson('9999999', 'dataExtract', 'post'), + 'returned new-JSON was not equal expected for insert dataExtract' + ); + // confirm updated item + assert.deepEqual( + await testUtils.getActualJson('testExisting_dataExtract', 'dataExtract'), + await testUtils.getExpectedJson('9999999', 'dataExtract', 'patch'), + 'returned existing-JSON was not equal expected for update dataExtract' + ); + // check number of API calls + assert.equal( + testUtils.getAPIHistoryLength(), + 13, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + return; + }); + + it('Should change the key during update via --changeKeyValue '); + }); + + describe('Templating ================', () => { + it('Should create a dataExtract template via retrieveAsTemplate and build it', async () => { + // buildTemplate + const result = await handler.retrieveAsTemplate( + 'testInstance/testBU', + 'dataExtract', + ['testExisting_dataExtract'], + 'testSourceMarket' + ); + assert.equal(process.exitCode, 0, 'buildTemplate should not have thrown an error'); + assert.equal( + result.dataExtract ? Object.keys(result.dataExtract).length : 0, + 1, + 'only one dataExtract expected' + ); + assert.deepEqual( + await testUtils.getActualTemplateJson('testExisting_dataExtract', 'dataExtract'), + await testUtils.getExpectedJson('9999999', 'dataExtract', 'template'), + 'returned template JSON was not equal expected' + ); + // buildDefinition + await handler.buildDefinition( + 'testInstance/testBU', + 'dataExtract', + ['testExisting_dataExtract'], + ['testTargetMarket'] + ); + assert.equal(process.exitCode, 0, 'buildDefinition should not have thrown an error'); + assert.deepEqual( + await testUtils.getActualDeployJson('testTemplated_dataExtract', 'dataExtract'), + await testUtils.getExpectedJson('9999999', 'dataExtract', 'build'), + 'returned deployment JSON was not equal expected' + ); + assert.equal( + testUtils.getAPIHistoryLength(), + 9, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + return; + }); + + it('Should create a dataExtract template via buildTemplate and build it', async () => { + // download first before we test buildTemplate + await handler.retrieve('testInstance/testBU', ['dataExtract']); + // buildTemplate + const result = await handler.buildTemplate( + 'testInstance/testBU', + 'dataExtract', + ['testExisting_dataExtract'], + ['testSourceMarket'] + ); + assert.equal(process.exitCode, 0, 'buildTemplate should not have thrown an error'); + assert.equal( + result.dataExtract ? Object.keys(result.dataExtract).length : 0, + 1, + 'only one dataExtract expected' + ); + assert.deepEqual( + await testUtils.getActualTemplateJson('testExisting_dataExtract', 'dataExtract'), + await testUtils.getExpectedJson('9999999', 'dataExtract', 'template'), + 'returned template JSON was not equal expected' + ); + // buildDefinition + await handler.buildDefinition( + 'testInstance/testBU', + 'dataExtract', + ['testExisting_dataExtract'], + ['testTargetMarket'] + ); + assert.equal(process.exitCode, 0, 'buildDefinition should not have thrown an error'); + assert.deepEqual( + await testUtils.getActualDeployJson('testTemplated_dataExtract', 'dataExtract'), + await testUtils.getExpectedJson('9999999', 'dataExtract', 'build'), + 'returned deployment JSON was not equal expected' + ); + assert.equal( + testUtils.getAPIHistoryLength(), + 9, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + return; + }); + }); + + describe('Delete ================', () => { + it('Should delete the item', async () => { + // WHEN + const isDeleted = await handler.deleteByKey( + 'testInstance/testBU', + 'dataExtract', + 'testExisting_dataExtract' + ); + // THEN + assert.equal(process.exitCode, 0, 'deleteByKey should not have thrown an error'); + assert.equal(isDeleted, true, 'deleteByKey should have returned true'); + return; + }); + }); +}); diff --git a/test/type.dataFilter.test.js b/test/type.dataFilter.test.js new file mode 100644 index 000000000..098ba85d7 --- /dev/null +++ b/test/type.dataFilter.test.js @@ -0,0 +1,182 @@ +import * as chai from 'chai'; +const assert = chai.assert; + +import chaiFiles from 'chai-files'; +import cache from '../lib/util/cache.js'; +import * as testUtils from './utils.js'; +import handler from '../lib/index.js'; +chai.use(chaiFiles); + +describe('type: dataFilter', () => { + beforeEach(() => { + testUtils.mockSetup(); + }); + + afterEach(() => { + testUtils.mockReset(); + }); + + describe('Retrieve ================', () => { + it('Should retrieve a dataFilter', async () => { + // WHEN + await handler.retrieve('testInstance/testBU', ['dataFilter']); + // THEN + assert.equal(process.exitCode, 0, 'retrieve should not have thrown an error'); + // get results from cache + const result = cache.getCache(); + assert.equal( + result.dataFilter ? Object.keys(result.dataFilter).length : 0, + 1, + 'unexpected number of items retrieved' + ); + assert.deepEqual( + await testUtils.getActualJson('testExisting_dataFilter', 'dataFilter'), + await testUtils.getExpectedJson('9999999', 'dataFilter', 'get'), + 'returned JSON was not equal expected' + ); + + assert.equal( + testUtils.getAPIHistoryLength(), + 6, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + return; + }); + + it('Should retrieve a dataFilter by key', async () => { + // WHEN + await handler.retrieve( + 'testInstance/testBU', + ['dataFilter'], + ['testExisting_dataFilter'] + ); + // THEN + assert.equal(process.exitCode, 0, 'retrieve should not have thrown an error'); + // get results from cache + const result = cache.getCache(); + assert.equal( + result.dataFilter ? Object.keys(result.dataFilter).length : 0, + 1, + 'only one dataFilter expected' + ); + assert.deepEqual( + await testUtils.getActualJson('testExisting_dataFilter', 'dataFilter'), + await testUtils.getExpectedJson('9999999', 'dataFilter', 'get'), + 'returned JSON was not equal expected' + ); + assert.equal( + testUtils.getAPIHistoryLength(), + 7, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + return; + }); + }); + + describe('Deploy ================', () => { + beforeEach(() => { + testUtils.mockSetup(true); + }); + + it('Should create & upsert a dataFilter', async () => { + // WHEN + + const deployed = await handler.deploy('testInstance/testBU', ['dataFilter']); + // THEN + assert.equal(process.exitCode, 0, 'deploy should not have thrown an error'); + // get results from cache + const result = cache.getCache(); + assert.equal( + result.dataFilter ? Object.keys(result.dataFilter).length : 0, + 2, + 'unexpected number of dataFilters in cache' + ); + assert.equal( + deployed?.['testInstance/testBU']?.dataFilter + ? Object.keys(deployed['testInstance/testBU'].dataFilter).length + : 0, + 2, + 'unexpected number of dataFilters deployed' + ); + + // confirm created item + assert.deepEqual( + await testUtils.getActualJson('testNew_dataFilter', 'dataFilter'), + await testUtils.getExpectedJson('9999999', 'dataFilter', 'post'), + 'returned new-JSON was not equal expected for insert dataFilter' + ); + // confirm updated item + assert.deepEqual( + await testUtils.getActualJson('testExisting_dataFilter', 'dataFilter'), + await testUtils.getExpectedJson('9999999', 'dataFilter', 'patch'), + 'returned existing-JSON was not equal expected for update dataFilter' + ); + // check number of API calls + assert.equal( + testUtils.getAPIHistoryLength(), + 8, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + return; + }); + }); + + describe('Templating ================', () => { + it('Should create a dataFilter template via buildTemplate and build it', async () => { + // download first before we test buildTemplate + await handler.retrieve('testInstance/testBU', ['dataFilter']); + // buildTemplate + const result = await handler.buildTemplate( + 'testInstance/testBU', + 'dataFilter', + ['testExisting_dataFilter'], + ['testSourceMarket'] + ); + assert.equal(process.exitCode, 0, 'buildTemplate should not have thrown an error'); + assert.equal( + result.dataFilter ? Object.keys(result.dataFilter).length : 0, + 1, + 'only one dataFilter expected' + ); + assert.deepEqual( + await testUtils.getActualTemplateJson('testExisting_dataFilter', 'dataFilter'), + await testUtils.getExpectedJson('9999999', 'dataFilter', 'template'), + 'returned template JSON was not equal expected' + ); + // buildDefinition + await handler.buildDefinition( + 'testInstance/testBU', + 'dataFilter', + ['testExisting_dataFilter'], + ['testTargetMarket'] + ); + assert.equal(process.exitCode, 0, 'buildDefinition should not have thrown an error'); + assert.deepEqual( + await testUtils.getActualDeployJson('testTemplated_dataFilter', 'dataFilter'), + await testUtils.getExpectedJson('9999999', 'dataFilter', 'build'), + 'returned deployment JSON was not equal expected' + ); + assert.equal( + testUtils.getAPIHistoryLength(), + 6, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + return; + }); + }); + + describe('Delete ================', () => { + it('Should delete the item', async () => { + // WHEN + const isDeleted = await handler.deleteByKey( + 'testInstance/testBU', + 'dataFilter', + 'testExisting_dataFilter' + ); + // THEN + assert.equal(process.exitCode, 0, 'deleteByKey should not have thrown an error'); + assert.equal(isDeleted, true, 'deleteByKey should have returned true'); + return; + }); + }); +}); diff --git a/test/type.deliveryProfile.test.js b/test/type.deliveryProfile.test.js new file mode 100644 index 000000000..8a38f7711 --- /dev/null +++ b/test/type.deliveryProfile.test.js @@ -0,0 +1,45 @@ +import * as chai from 'chai'; +const assert = chai.assert; + +import chaiFiles from 'chai-files'; +import cache from '../lib/util/cache.js'; +import * as testUtils from './utils.js'; +import handler from '../lib/index.js'; +chai.use(chaiFiles); + +describe('type: deliveryProfile', () => { + beforeEach(() => { + testUtils.mockSetup(); + }); + + afterEach(() => { + testUtils.mockReset(); + }); + + describe('Retrieve ================', () => { + it('Should retrieve a deliveryProfile', async () => { + // WHEN + await handler.retrieve('testInstance/testBU', ['deliveryProfile']); + // THEN + assert.equal(process.exitCode, 0, 'retrieve should not have thrown an error'); + // get results from cache + const result = cache.getCache(); + assert.equal( + result.deliveryProfile ? Object.keys(result.deliveryProfile).length : 0, + 1, + 'only one deliveryProfile expected' + ); + assert.deepEqual( + await testUtils.getActualJson('Default', 'deliveryProfile'), + await testUtils.getExpectedJson('9999999', 'deliveryProfile', 'get'), + 'returned JSON was not equal expected' + ); + assert.equal( + testUtils.getAPIHistoryLength(), + 1, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + return; + }); + }); +}); diff --git a/test/type.domainVerification.test.js b/test/type.domainVerification.test.js new file mode 100644 index 000000000..412f8ae53 --- /dev/null +++ b/test/type.domainVerification.test.js @@ -0,0 +1,169 @@ +import * as chai from 'chai'; +const assert = chai.assert; + +import chaiFiles from 'chai-files'; +import cache from '../lib/util/cache.js'; +import * as testUtils from './utils.js'; +import handler from '../lib/index.js'; +chai.use(chaiFiles); + +describe('type: domainVerification', () => { + beforeEach(() => { + testUtils.mockSetup(); + }); + + afterEach(() => { + testUtils.mockReset(); + }); + + describe('Retrieve ================', () => { + it('Should retrieve a domainVerification', async () => { + // WHEN + const retrieve = await handler.retrieve('testInstance/testBU', { + domainVerification: null, + }); + // THEN + assert.equal(process.exitCode, 0, 'retrieve should not have thrown an error'); + // get results from cache + assert.equal( + retrieve['testInstance/testBU'].domainVerification + ? Object.keys(retrieve['testInstance/testBU'].domainVerification).length + : 0, + 5, + 'Unexpected number of assets in retrieve response' + ); + const typeCache = cache.getCache()?.domainVerification; + assert.equal( + typeCache ? Object.keys(typeCache).length : 0, + 5, + 'unexpected number of domainVerifications' + ); + assert.deepEqual( + await testUtils.getActualJson('mcdev.accenture.com', 'domainVerification'), + await testUtils.getExpectedJson('9999999', 'domainVerification', 'get-sap'), + 'returned JSON was not equal expected' + ); + assert.equal( + testUtils.getAPIHistoryLength(), + 1, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + return; + }); + }); + + describe('Deploy ================', () => { + beforeEach(() => { + testUtils.mockSetup(true); + }); + + it('Should create & upsert domainVerifications', async () => { + // WHEN + + const deployed = await handler.deploy('testInstance/testBU', { + domainVerification: [ + 'joern.berkefeld@accenture.com', + 'joern.berkefeld.New@accenture.com', + ], + }); + // THEN + assert.equal(process.exitCode, 0, 'deploy should not have thrown an error'); + // get results from cache + const cached = cache.getCache(); + assert.equal( + cached.domainVerification ? Object.keys(cached.domainVerification).length : 0, + 6, + 'unexpected number of domainVerifications in cache' + ); + assert.deepEqual( + Object.keys(deployed['testInstance/testBU']?.domainVerification), + ['joern.berkefeld.New@accenture.com', 'joern.berkefeld@accenture.com'], + 'unexpected domainVerifications deployed' + ); + + // check callouts + const createCallout = testUtils.getRestCallout( + 'post', + '/messaging/v1/domainverification/' + ); + assert.deepEqual( + createCallout, + { domain: 'joern.berkefeld.New@accenture.com' }, + 'unexecpted payload for create callout' + ); + const updateCallout = testUtils.getRestCallout( + 'post', + '/messaging/v1/domainverification/update' + ); + assert.deepEqual( + updateCallout, + [{ emailAddress: 'joern.berkefeld@accenture.com', isSendable: true }], + 'unexecpted payload for update callout' + ); + + // confirm created item + assert.deepEqual( + await testUtils.getActualJson( + 'joern.berkefeld.New@accenture.com', + 'domainVerification' + ), + await testUtils.getExpectedJson('9999999', 'domainVerification', 'create'), + 'returned new-JSON was not equal expected for insert domainVerification' + ); + // confirm updated item + assert.deepEqual( + await testUtils.getActualJson( + 'joern.berkefeld@accenture.com', + 'domainVerification' + ), + await testUtils.getExpectedJson('9999999', 'domainVerification', 'update'), + 'returned existing-JSON was not equal expected for update domainVerification' + ); + // check number of API calls + assert.equal( + testUtils.getAPIHistoryLength(), + 4, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + return; + }); + }); + + describe('Delete ================', () => { + it('Should delete the item', async () => { + // WHEN + const isDeleted = await handler.deleteByKey('testInstance/testBU', { + domainVerification: ['joern.berkefeld@accenture.com'], + }); + // THEN + assert.equal(process.exitCode, 0, 'deleteByKey should not have thrown an error'); + assert.equal(isDeleted, true, 'deleteByKey should have returned true'); + assert.equal( + testUtils.getAPIHistoryLength(), + 2, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + return; + }); + + it('Should not delete the items with wrong domainType', async () => { + // WHEN + const isDeleted = await handler.deleteByKey('testInstance/testBU', { + domainVerification: [ + 'mcdev.accenture.com', + 'adhoc.accenture.com', + 'mcdev-transferrable.accenture.com', + ], + }); + // THEN + assert.equal(process.exitCode, 1, 'deleteByKey should have thrown an error'); + assert.equal(isDeleted, false, 'deleteByKey should have returned false'); + assert.equal( + testUtils.getAPIHistoryLength(), + 1, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + return; + }); + }); +}); diff --git a/test/type.emailSend.test.js b/test/type.emailSend.test.js new file mode 100644 index 000000000..64fc7f209 --- /dev/null +++ b/test/type.emailSend.test.js @@ -0,0 +1,144 @@ +import * as chai from 'chai'; +const assert = chai.assert; + +import chaiFiles from 'chai-files'; +import cache from '../lib/util/cache.js'; +import * as testUtils from './utils.js'; +import handler from '../lib/index.js'; +chai.use(chaiFiles); + +describe('type: emailSend', () => { + beforeEach(() => { + testUtils.mockSetup(); + }); + + afterEach(() => { + testUtils.mockReset(); + }); + + describe('Retrieve ================', () => { + it('Should retrieve a emailSend', async () => { + // WHEN + await handler.retrieve('testInstance/testBU', ['emailSend']); + // THEN + assert.equal(process.exitCode, 0, 'retrieve should not have thrown an error'); + // get results from cache + const result = cache.getCache(); + assert.equal( + result.emailSend ? Object.keys(result.emailSend).length : 0, + 1, + 'only 1 emailSend expected' + ); + assert.deepEqual( + await testUtils.getActualJson('testExisting_emailSend', 'emailSend'), + await testUtils.getExpectedJson('9999999', 'emailSend', 'get'), + 'returned JSON was not equal expected' + ); + assert.equal( + testUtils.getAPIHistoryLength(), + 14, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + return; + }); + }); + + describe('Deploy ================', () => { + beforeEach(() => { + testUtils.mockSetup(true); + }); + + it('Should create & upsert a emailSend', async () => { + // WHEN + + await handler.deploy('testInstance/testBU', ['emailSend']); + // THEN + assert.equal(process.exitCode, 0, 'deploy should not have thrown an error'); + // get results from cache + const result = cache.getCache(); + assert.equal( + result.emailSend ? Object.keys(result.emailSend).length : 0, + 2, + '2 emailSends expected' + ); + // confirm created item + assert.deepEqual( + await testUtils.getActualJson('testNew_emailSend', 'emailSend'), + await testUtils.getExpectedJson('9999999', 'emailSend', 'post'), + 'returned new-JSON was not equal expected for insert emailSend' + ); + // confirm updated item + assert.deepEqual( + await testUtils.getActualJson('testExisting_emailSend', 'emailSend'), + await testUtils.getExpectedJson('9999999', 'emailSend', 'patch'), + 'returned existing-JSON was not equal expected for update emailSend' + ); + // check number of API calls + assert.equal( + testUtils.getAPIHistoryLength(), + 16, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + return; + }); + }); + + describe('Templating ================', () => { + it('Should create a emailSend template via buildTemplate and build it', async () => { + // download first before we test buildTemplate + await handler.retrieve('testInstance/testBU', ['emailSend']); + // buildTemplate + const result = await handler.buildTemplate( + 'testInstance/testBU', + 'emailSend', + ['testExisting_emailSend'], + ['testSourceMarket'] + ); + assert.equal(process.exitCode, 0, 'buildTemplate should not have thrown an error'); + assert.equal( + result.emailSend ? Object.keys(result.emailSend).length : 0, + 1, + 'only one emailSend expected' + ); + assert.deepEqual( + await testUtils.getActualTemplateJson('testExisting_emailSend', 'emailSend'), + await testUtils.getExpectedJson('9999999', 'emailSend', 'template'), + 'returned template JSON was not equal expected' + ); + // buildDefinition + await handler.buildDefinition( + 'testInstance/testBU', + 'emailSend', + ['testExisting_emailSend'], + ['testTargetMarket'] + ); + assert.equal(process.exitCode, 0, 'buildDefinition should not have thrown an error'); + assert.deepEqual( + await testUtils.getActualDeployJson('testTemplated_emailSend', 'emailSend'), + await testUtils.getExpectedJson('9999999', 'emailSend', 'build'), + 'returned deployment JSON was not equal expected' + ); + assert.equal( + testUtils.getAPIHistoryLength(), + 14, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + return; + }); + }); + + describe('Delete ================', () => { + it('Should delete the item', async () => { + // WHEN + const isDeleted = await handler.deleteByKey( + 'testInstance/testBU', + 'emailSend', + 'testExisting_emailSend' + ); + // THEN + assert.equal(process.exitCode, 0, 'deleteByKey should not have thrown an error'); + assert.equal(isDeleted, true, 'deleteByKey should have returned true'); + return; + }); + }); +}); diff --git a/test/type.event.test.js b/test/type.event.test.js new file mode 100644 index 000000000..495b9fddd --- /dev/null +++ b/test/type.event.test.js @@ -0,0 +1,346 @@ +import * as chai from 'chai'; +const assert = chai.assert; +const expect = chai.expect; + +import chaiFiles from 'chai-files'; +import cache from '../lib/util/cache.js'; +import * as testUtils from './utils.js'; +import handler from '../lib/index.js'; +chai.use(chaiFiles); + +describe('type: event', () => { + beforeEach(() => { + testUtils.mockSetup(); + }); + + afterEach(() => { + testUtils.mockReset(); + }); + + describe('Retrieve ================', () => { + it('Should retrieve a event', async () => { + // WHEN + await handler.retrieve('testInstance/testBU', ['event']); + // THEN + assert.equal(process.exitCode, 0, 'retrieve should not have thrown an error'); + // get results from cache + const result = cache.getCache(); + assert.equal( + result.event ? Object.keys(result.event).length : 0, + 5, + 'unexpected amount of events' + ); + assert.deepEqual( + await testUtils.getActualJson('testExisting_event', 'event'), + await testUtils.getExpectedJson('9999999', 'event', 'get'), + 'returned JSON was not equal expected' + ); + assert.deepEqual( + await testUtils.getActualJson('testExisting_event_automation', 'event'), + await testUtils.getExpectedJson('9999999', 'event', 'get-automation'), + 'returned JSON was not equal expected' + ); + assert.equal( + testUtils.getAPIHistoryLength(), + 10, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + return; + }); + }); + + describe('Deploy ================', () => { + beforeEach(() => { + testUtils.mockSetup(true); + }); + + it('Should create an event & dataExtension via schema', async () => { + // prepare + await testUtils.copyFile( + 'interaction/v1/eventDefinitions/post_withSchema-response.json', + 'interaction/v1/eventDefinitions/post-response.json' + ); + await testUtils.copyFile( + 'dataExtension/retrieve-createdViaEvent-response.xml', + 'dataExtension/retrieve-response.xml' + ); + await testUtils.copyFile( + 'dataExtension/update-afterCreatedViaEvent-response.xml', + 'dataExtension/update-response.xml' + ); + + await handler.deploy('testInstance/testBU', ['event'], ['testNew_event_withSchema']); + // THEN + assert.equal(process.exitCode, 0, 'deploy should not have thrown an error'); + // get results from cache + const result = cache.getCache(); + assert.equal( + result.event ? Object.keys(result.event).length : 0, + 6, + 'unexpected number of events' + ); + // get callouts + const createCallout = testUtils.getRestCallout( + 'post', + '/interaction/v1/eventDefinitions/' + ); + // confirm created item + assert.deepEqual( + createCallout, + await testUtils.getExpectedJson('9999999', 'event', 'post_withSchema-callout'), + 'create-payload JSON was not equal expected' + ); + assert.deepEqual( + await testUtils.getActualJson('testNew_event_withSchema', 'event'), + await testUtils.getExpectedJson('9999999', 'event', 'post_withSchema'), + 'returned new-JSON was not equal expected for insert event' + ); + // confirm we changed the dataExtension key correctly + const updateCalloutDE = testUtils.getSoapCallouts('Update', 'DataExtension'); + expect(updateCalloutDE[0]).to.equal( + await testUtils.getExpectedFile( + '9999999', + 'dataExtension', + 'update-callout-afterCreatedViaEvent', + 'xml' + ) + ); + + // confirm created dataExtension + assert.deepEqual( + await testUtils.getActualJson('testNew_event_withSchema', 'dataExtension'), + await testUtils.getExpectedJson( + '9999999', + 'dataExtension', + 'retrieve_event_withSchema' + ), + + 'returned metadata was not equal expected' + ); + + // check number of API calls + assert.equal( + testUtils.getAPIHistoryLength(), + 21, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + return; + }); + + it('Should create an event with pre-Existing dataExtension', async () => { + // prepare + await testUtils.copyFile( + 'interaction/v1/eventDefinitions/post_withExistingDE-response.json', + 'interaction/v1/eventDefinitions/post-response.json' + ); + + await handler.deploy( + 'testInstance/testBU', + ['event'], + ['testNew_event_withExistingDE'] + ); + // THEN + assert.equal(process.exitCode, 0, 'deploy should not have thrown an error'); + // get results from cache + const result = cache.getCache(); + assert.equal( + result.event ? Object.keys(result.event).length : 0, + 6, + 'unexpected number of events' + ); + // get callouts + const createCallout = testUtils.getRestCallout( + 'post', + '/interaction/v1/eventDefinitions/' + ); + // confirm created item + assert.deepEqual( + createCallout, + await testUtils.getExpectedJson('9999999', 'event', 'post_withExistingDE-callout'), + 'create-payload JSON was not equal expected' + ); + assert.deepEqual( + await testUtils.getActualJson('testNew_event_withExistingDE', 'event'), + await testUtils.getExpectedJson('9999999', 'event', 'post_withExistingDE'), + 'returned new-JSON was not equal expected for insert event' + ); + // check number of API calls + assert.equal( + testUtils.getAPIHistoryLength(), + 12, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + return; + }); + + it('Should update an event', async () => { + await handler.deploy('testInstance/testBU', ['event'], ['testExisting_event']); + // THEN + assert.equal(process.exitCode, 0, 'deploy should not have thrown an error'); + // get results from cache + const result = cache.getCache(); + assert.equal( + result.event ? Object.keys(result.event).length : 0, + 5, + 'unexpected number of events' + ); + // get callouts + const updateCallout = testUtils.getRestCallout( + 'put', + '/interaction/v1/eventDefinitions/%' + ); + // confirm updated item + assert.deepEqual( + updateCallout, + await testUtils.getExpectedJson('9999999', 'event', 'put-callout'), + 'update-payload JSON was not equal expected' + ); + assert.deepEqual( + await testUtils.getActualJson('testExisting_event', 'event'), + await testUtils.getExpectedJson('9999999', 'event', 'put'), + 'returned existing-JSON was not equal expected for update event' + ); + // check number of API calls + assert.equal( + testUtils.getAPIHistoryLength(), + 12, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + return; + }); + }); + + describe('FixKeys ================', () => { + beforeEach(() => { + testUtils.mockSetup(true); + }); + + it('Should exit fixKeys because event is not supported intentionally', async () => { + // WHEN + handler.setOptions({ skipInteraction: { fixKeysReretrieve: false } }); + const resultFixKeys = await handler.fixKeys('testInstance/testBU', ['event']); + // THEN + assert.equal(process.exitCode, 0, 'fixKeys should not have thrown an error'); + // check which keys were fixed + assert.equal( + resultFixKeys['testInstance/testBU'], + undefined, + 'expected to find no keys to be fixed' + ); + + // check number of API calls + assert.equal( + testUtils.getAPIHistoryLength(), + 0, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + return; + }); + }); + + describe('Templating ================', () => { + it('Should create a event template via retrieveAsTemplate and build it', async () => { + // GIVEN there is a template + const result = await handler.retrieveAsTemplate( + 'testInstance/testBU', + 'event', + ['testExisting_event'], + 'testSourceMarket' + ); + // WHEN + assert.equal(process.exitCode, 0, 'retrieveAsTemplate should not have thrown an error'); + assert.equal( + result.event ? Object.keys(result.event).length : 0, + 1, + 'only one event expected' + ); + assert.deepEqual( + await testUtils.getActualTemplateJson('testExisting_event', 'event'), + await testUtils.getExpectedJson('9999999', 'event', 'template'), + 'returned template JSON of retrieveAsTemplate was not equal expected' + ); + // THEN + await handler.buildDefinition( + 'testInstance/testBU', + 'event', + ['testExisting_event'], + ['testTargetMarket'] + ); + assert.equal(process.exitCode, 0, 'buildDefinition should not have thrown an error'); + + assert.deepEqual( + await testUtils.getActualDeployJson('testTemplated_event', 'event'), + await testUtils.getExpectedJson('9999999', 'event', 'build'), + 'returned deployment JSON was not equal expected' + ); + + assert.equal( + testUtils.getAPIHistoryLength(), + 10, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + return; + }); + + it('Should create a event template via buildTemplate and build it', async () => { + // download first before we test buildTemplate + await handler.retrieve('testInstance/testBU', ['event']); + // GIVEN there is a template + const result = await handler.buildTemplate( + 'testInstance/testBU', + 'event', + ['testExisting_event'], + ['testSourceMarket'] + ); + // WHEN + assert.equal(process.exitCode, 0, 'buildTemplate should not have thrown an error'); + + assert.equal( + result.event ? Object.keys(result.event).length : 0, + 1, + 'only one event expected' + ); + assert.deepEqual( + await testUtils.getActualTemplateJson('testExisting_event', 'event'), + await testUtils.getExpectedJson('9999999', 'event', 'template'), + 'returned template JSON of buildTemplate was not equal expected' + ); + // THEN + await handler.buildDefinition( + 'testInstance/testBU', + 'event', + ['testExisting_event'], + ['testTargetMarket'] + ); + assert.equal(process.exitCode, 0, 'buildDefinition should not have thrown an error'); + + assert.deepEqual( + await testUtils.getActualDeployJson('testTemplated_event', 'event'), + await testUtils.getExpectedJson('9999999', 'event', 'build'), + 'returned deployment JSON was not equal expected' + ); + + assert.equal( + testUtils.getAPIHistoryLength(), + 10, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + return; + }); + }); + + describe('Delete ================', () => { + it('Should delete the item', async () => { + // WHEN + const isDeleted = await handler.deleteByKey( + 'testInstance/testBU', + 'event', + 'testExisting_event' + ); + // THEN + assert.equal(process.exitCode, 0, 'deleteByKey should not have thrown an error'); + assert.equal(isDeleted, true, 'deleteByKey should have returned true'); + return; + }); + }); +}); diff --git a/test/type.fileLocation.test.js b/test/type.fileLocation.test.js new file mode 100644 index 000000000..8df4d3864 --- /dev/null +++ b/test/type.fileLocation.test.js @@ -0,0 +1,279 @@ +import * as chai from 'chai'; +const assert = chai.assert; + +import chaiFiles from 'chai-files'; +import cache from '../lib/util/cache.js'; +import * as testUtils from './utils.js'; +import handler from '../lib/index.js'; +chai.use(chaiFiles); + +describe('type: fileLocation', () => { + beforeEach(() => { + testUtils.mockSetup(); + }); + + afterEach(() => { + testUtils.mockReset(); + }); + + describe('Retrieve ================', () => { + it('Should retrieve a fileLocation', async () => { + // WHEN + await handler.retrieve('testInstance/testBU', ['fileLocation']); + // THEN + assert.equal(process.exitCode, 0, 'retrieve should not have thrown an error'); + // get results from cache + const result = cache.getCache(); + assert.equal( + result.fileLocation ? Object.keys(result.fileLocation).length : 0, + 6, + 'unexpected number of fileLocations' + ); + assert.deepEqual( + await testUtils.getActualJson('Salesforce Objects %26 Reports', 'fileLocation'), + await testUtils.getExpectedJson('9999999', 'fileLocation', 'get-sor'), + 'returned JSON was not equal expected' + ); + assert.deepEqual( + await testUtils.getActualJson('ExactTarget Enhanced FTP', 'fileLocation'), + await testUtils.getExpectedJson('9999999', 'fileLocation', 'get-eftp'), + 'returned JSON was not equal expected' + ); + assert.deepEqual( + await testUtils.getActualJson('testExisting_fileLocation_gcp', 'fileLocation'), + await testUtils.getExpectedJson('9999999', 'fileLocation', 'get-gcp'), + 'returned JSON was not equal expected' + ); + assert.deepEqual( + await testUtils.getActualJson('testExisting_fileLocation_azure', 'fileLocation'), + await testUtils.getExpectedJson('9999999', 'fileLocation', 'get-azure'), + 'returned JSON was not equal expected' + ); + assert.deepEqual( + await testUtils.getActualJson('testExisting_fileLocation_aws', 'fileLocation'), + await testUtils.getExpectedJson('9999999', 'fileLocation', 'get-aws'), + 'returned JSON was not equal expected' + ); + assert.deepEqual( + await testUtils.getActualJson('testExisting_fileLocation_exsftp', 'fileLocation'), + await testUtils.getExpectedJson('9999999', 'fileLocation', 'get-exsftp'), + 'returned JSON was not equal expected' + ); + assert.equal( + testUtils.getAPIHistoryLength(), + 2, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + return; + }); + + it('Should retrieve an old fileLocation by key', async () => { + // WHEN + await handler.retrieve( + 'testInstance/testBU', + ['fileLocation'], + ['Salesforce Objects & Reports'] + ); + // THEN + assert.equal(process.exitCode, 0, 'retrieve should not have thrown an error'); + // get results from cache + const result = cache.getCache(); + assert.equal( + result.fileLocation ? Object.keys(result.fileLocation).length : 0, + 1, + 'unexpected number of fileLocations' + ); + assert.deepEqual( + await testUtils.getActualJson('Salesforce Objects %26 Reports', 'fileLocation'), + await testUtils.getExpectedJson('9999999', 'fileLocation', 'get-sor'), + 'returned JSON was not equal expected' + ); + assert.equal( + testUtils.getAPIHistoryLength(), + 2, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + return; + }); + + it('Should retrieve a new fileLocation by key', async () => { + // WHEN + await handler.retrieve( + 'testInstance/testBU', + ['fileLocation'], + ['testExisting_fileLocation_azure'] + ); + // THEN + assert.equal(process.exitCode, 0, 'retrieve should not have thrown an error'); + // get results from cache + const result = cache.getCache(); + assert.equal( + result.fileLocation ? Object.keys(result.fileLocation).length : 0, + 1, + 'unexpected number of fileLocations' + ); + assert.deepEqual( + await testUtils.getActualJson('testExisting_fileLocation_azure', 'fileLocation'), + await testUtils.getExpectedJson('9999999', 'fileLocation', 'get-azure'), + 'returned JSON was not equal expected' + ); + assert.equal( + testUtils.getAPIHistoryLength(), + 2, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + return; + }); + }); + + describe('Deploy ================', () => { + beforeEach(() => { + testUtils.mockSetup(true); + }); + + it('Should update fileLocations', async () => { + // WHEN + const deployed = await handler.deploy( + 'testInstance/testBU', + ['fileLocation'], + ['testExisting_fileLocation_exsftp', 'testExisting_fileLocation_aws'] + ); + // THEN + assert.equal(process.exitCode, 0, 'deploy should not have thrown an error'); + // get results from cache + const result = cache.getCache(); + assert.equal( + result.fileLocation ? Object.keys(result.fileLocation).length : 0, + 6, + 'unexpected number of fileLocations in cache' + ); + assert.equal( + deployed?.['testInstance/testBU']?.fileLocation + ? Object.keys(deployed['testInstance/testBU'].fileLocation).length + : 0, + 2, + 'unexpected number of fileLocations deployed' + ); + // confirm created item + // TODO + + // confirm updated item + assert.deepEqual( + await testUtils.getActualJson('testExisting_fileLocation_exsftp', 'fileLocation'), + await testUtils.getExpectedJson('9999999', 'fileLocation', 'patch-exsftp'), + 'returned JSON was not equal expected for insert fileLocation' + ); + // confirm updated item + assert.deepEqual( + await testUtils.getActualJson('testExisting_fileLocation_aws', 'fileLocation'), + await testUtils.getExpectedJson('9999999', 'fileLocation', 'patch-aws'), + 'returned JSON was not equal expected for update fileLocation' + ); + // check number of API calls + assert.equal( + testUtils.getAPIHistoryLength(), + 4, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + return; + }); + + it('Should not update fileLocations', async () => { + // WHEN + const deployed = await handler.deploy( + 'testInstance/testBU', + ['fileLocation'], + ['ExactTarget Enhanced FTP'] + ); + // THEN + assert.equal(process.exitCode, 1, 'deploy should have thrown an error'); + // get results from cache + const result = cache.getCache(); + assert.equal( + result.fileLocation ? Object.keys(result.fileLocation).length : 0, + 6, + 'unexpected number of fileLocations in cache' + ); + assert.equal( + deployed?.['testInstance/testBU']?.fileLocation + ? Object.keys(deployed['testInstance/testBU'].fileLocation).length + : 0, + 0, + 'unexpected number of fileLocations deployed' + ); + + // check number of API calls + assert.equal( + testUtils.getAPIHistoryLength(), + 2, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + return; + }); + }); + + describe('Templating ================', () => { + it('Should create a fileLocation template via buildTemplate and build it', async () => { + // download first before we test buildTemplate + await handler.retrieve('testInstance/testBU', ['fileLocation']); + // buildTemplate + const result = await handler.buildTemplate( + 'testInstance/testBU', + 'fileLocation', + ['testExisting_fileLocation_azure'], + ['testSourceMarket'] + ); + assert.equal(process.exitCode, 0, 'buildTemplate should not have thrown an error'); + assert.equal( + result.fileLocation ? Object.keys(result.fileLocation).length : 0, + 1, + 'only one fileLocation expected' + ); + assert.deepEqual( + await testUtils.getActualTemplateJson( + 'testExisting_fileLocation_azure', + 'fileLocation' + ), + await testUtils.getExpectedJson('9999999', 'fileLocation', 'template'), + 'returned template JSON was not equal expected' + ); + // buildDefinition + await handler.buildDefinition( + 'testInstance/testBU', + 'fileLocation', + ['testExisting_fileLocation_azure'], + ['testTargetMarket'] + ); + assert.equal(process.exitCode, 0, 'buildDefinition should not have thrown an error'); + assert.deepEqual( + await testUtils.getActualDeployJson( + 'testTemplated_fileLocation_azure', + 'fileLocation' + ), + await testUtils.getExpectedJson('9999999', 'fileLocation', 'build'), + 'returned deployment JSON was not equal expected' + ); + assert.equal( + testUtils.getAPIHistoryLength(), + 2, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + return; + }); + }); + + describe('Delete ================', () => { + it('Should delete the item', async () => { + // WHEN + const isDeleted = await handler.deleteByKey( + 'testInstance/testBU', + 'fileLocation', + 'testExisting_fileLocation_azure' + ); + // THEN + assert.equal(process.exitCode, 0, 'deleteByKey should not have thrown an error'); + assert.equal(isDeleted, true, 'deleteByKey should have returned true'); + return; + }); + }); +}); diff --git a/test/type.fileTransfer.test.js b/test/type.fileTransfer.test.js new file mode 100644 index 000000000..846a415ac --- /dev/null +++ b/test/type.fileTransfer.test.js @@ -0,0 +1,183 @@ +import * as chai from 'chai'; +const assert = chai.assert; + +import chaiFiles from 'chai-files'; +import cache from '../lib/util/cache.js'; +import * as testUtils from './utils.js'; +import handler from '../lib/index.js'; +chai.use(chaiFiles); + +describe('type: fileTransfer', () => { + beforeEach(() => { + testUtils.mockSetup(); + }); + + afterEach(() => { + testUtils.mockReset(); + }); + + describe('Retrieve ================', () => { + it('Should retrieve a fileTransfer', async () => { + // WHEN + await handler.retrieve('testInstance/testBU', ['fileTransfer']); + // THEN + assert.equal(process.exitCode, 0, 'retrieve should not have thrown an error'); + // get results from cache + const result = cache.getCache(); + assert.equal( + result.fileTransfer ? Object.keys(result.fileTransfer).length : 0, + 1, + 'only one fileTransfer expected' + ); + assert.deepEqual( + await testUtils.getActualJson('testExisting_fileTransfer', 'fileTransfer'), + await testUtils.getExpectedJson('9999999', 'fileTransfer', 'get'), + 'returned JSON was not equal expected' + ); + assert.equal( + testUtils.getAPIHistoryLength(), + 4, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + return; + }); + }); + + describe('Deploy ================', () => { + beforeEach(() => { + testUtils.mockSetup(true); + }); + + it('Should create & upsert a fileTransfer', async () => { + // WHEN + await handler.deploy('testInstance/testBU', ['fileTransfer']); + // THEN + assert.equal(process.exitCode, 0, 'deploy should not have thrown an error'); + // get results from cache + const result = cache.getCache(); + assert.equal( + result.fileTransfer ? Object.keys(result.fileTransfer).length : 0, + 2, + 'two fileTransfers expected' + ); + // confirm created item + assert.deepEqual( + await testUtils.getActualJson('testNew_fileTransfer', 'fileTransfer'), + await testUtils.getExpectedJson('9999999', 'fileTransfer', 'post'), + 'returned JSON was not equal expected for insert fileTransfer' + ); + // confirm updated item + assert.deepEqual( + await testUtils.getActualJson('testExisting_fileTransfer', 'fileTransfer'), + await testUtils.getExpectedJson('9999999', 'fileTransfer', 'patch'), + 'returned JSON was not equal expected for update fileTransfer' + ); + // check number of API calls + assert.equal( + testUtils.getAPIHistoryLength(), + 6, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + return; + }); + }); + + describe('Templating ================', () => { + it('Should create a fileTransfer template via retrieveAsTemplate and build it', async () => { + // buildTemplate + const result = await handler.retrieveAsTemplate( + 'testInstance/testBU', + 'fileTransfer', + ['testExisting_fileTransfer'], + 'testSourceMarket' + ); + assert.equal(process.exitCode, 0, 'buildTemplate should not have thrown an error'); + assert.equal( + result.fileTransfer ? Object.keys(result.fileTransfer).length : 0, + 1, + 'only one fileTransfer expected' + ); + assert.deepEqual( + await testUtils.getActualTemplateJson('testExisting_fileTransfer', 'fileTransfer'), + await testUtils.getExpectedJson('9999999', 'fileTransfer', 'template'), + 'returned template JSON was not equal expected' + ); + // buildDefinition + await handler.buildDefinition( + 'testInstance/testBU', + 'fileTransfer', + ['testExisting_fileTransfer'], + ['testTargetMarket'] + ); + assert.equal(process.exitCode, 0, 'buildDefinition should not have thrown an error'); + assert.deepEqual( + await testUtils.getActualDeployJson('testTemplated_fileTransfer', 'fileTransfer'), + await testUtils.getExpectedJson('9999999', 'fileTransfer', 'build'), + 'returned deployment JSON was not equal expected' + ); + assert.equal( + testUtils.getAPIHistoryLength(), + 4, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + return; + }); + + it('Should create a fileTransfer template via buildTemplate and build it', async () => { + // download first before we test buildTemplate + await handler.retrieve('testInstance/testBU', ['fileTransfer']); + // buildTemplate + const result = await handler.buildTemplate( + 'testInstance/testBU', + 'fileTransfer', + ['testExisting_fileTransfer'], + ['testSourceMarket'] + ); + assert.equal(process.exitCode, 0, 'buildTemplate should not have thrown an error'); + assert.equal( + result.fileTransfer ? Object.keys(result.fileTransfer).length : 0, + 1, + 'only one fileTransfer expected' + ); + assert.deepEqual( + await testUtils.getActualTemplateJson('testExisting_fileTransfer', 'fileTransfer'), + await testUtils.getExpectedJson('9999999', 'fileTransfer', 'template'), + 'returned template JSON was not equal expected' + ); + // buildDefinition + await handler.buildDefinition( + 'testInstance/testBU', + 'fileTransfer', + ['testExisting_fileTransfer'], + ['testTargetMarket'] + ); + assert.equal(process.exitCode, 0, 'buildDefinition should not have thrown an error'); + assert.deepEqual( + await testUtils.getActualDeployJson('testTemplated_fileTransfer', 'fileTransfer'), + await testUtils.getExpectedJson('9999999', 'fileTransfer', 'build'), + 'returned deployment JSON was not equal expected' + ); + assert.equal( + testUtils.getAPIHistoryLength(), + 4, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + return; + }); + }); + + describe('Delete ================', () => { + it('Should delete the item', async () => { + // WHEN + const isDeleted = await handler.deleteByKey( + 'testInstance/testBU', + 'fileTransfer', + 'testExisting_fileTransfer' + ); + // THEN + assert.equal(process.exitCode, 0, 'deleteByKey should not have thrown an error'); + assert.equal(isDeleted, true, 'deleteByKey should have returned true'); + return; + }); + }); +}); diff --git a/test/type.filter.test.js b/test/type.filter.test.js new file mode 100644 index 000000000..56b6499ce --- /dev/null +++ b/test/type.filter.test.js @@ -0,0 +1,177 @@ +import * as chai from 'chai'; +const assert = chai.assert; + +import chaiFiles from 'chai-files'; +import cache from '../lib/util/cache.js'; +import * as testUtils from './utils.js'; +import handler from '../lib/index.js'; +chai.use(chaiFiles); + +describe('type: filter', () => { + beforeEach(() => { + testUtils.mockSetup(); + }); + + afterEach(() => { + testUtils.mockReset(); + }); + + describe('Retrieve ================', () => { + it('Should retrieve a filter', async () => { + // WHEN + await handler.retrieve('testInstance/testBU', ['filter']); + // THEN + assert.equal(process.exitCode, 0, 'retrieve should not have thrown an error'); + // get results from cache + const result = cache.getCache(); + assert.equal( + result.filter ? Object.keys(result.filter).length : 0, + 1, + 'unexpected number of items retrieved' + ); + assert.deepEqual( + await testUtils.getActualJson('testExisting_filter', 'filter'), + await testUtils.getExpectedJson('9999999', 'filter', 'get'), + 'returned JSON was not equal expected' + ); + + assert.equal( + testUtils.getAPIHistoryLength(), + 14, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + return; + }); + + it('Should retrieve a filter by key', async () => { + // WHEN + await handler.retrieve('testInstance/testBU', ['filter'], ['testExisting_filter']); + // THEN + assert.equal(process.exitCode, 0, 'retrieve should not have thrown an error'); + // get results from cache + const result = cache.getCache(); + assert.equal( + result.filter ? Object.keys(result.filter).length : 0, + 1, + 'only one filter expected' + ); + assert.deepEqual( + await testUtils.getActualJson('testExisting_filter', 'filter'), + await testUtils.getExpectedJson('9999999', 'filter', 'get'), + 'returned JSON was not equal expected' + ); + assert.equal( + testUtils.getAPIHistoryLength(), + 15, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + return; + }); + }); + + describe('Deploy ================', () => { + beforeEach(() => { + testUtils.mockSetup(true); + }); + + it('Should create & upsert a filter', async () => { + // WHEN + + const deployed = await handler.deploy('testInstance/testBU', ['filter']); + // THEN + assert.equal(process.exitCode, 0, 'deploy should not have thrown an error'); + // get results from cache + const result = cache.getCache(); + assert.equal( + result.filter ? Object.keys(result.filter).length : 0, + 2, + 'unexpected number of filters in cache' + ); + assert.equal( + deployed?.['testInstance/testBU']?.filter + ? Object.keys(deployed['testInstance/testBU'].filter).length + : 0, + 2, + 'unexpected number of filters deployed' + ); + // confirm created item + assert.deepEqual( + await testUtils.getActualJson('testNew_filter', 'filter'), + await testUtils.getExpectedJson('9999999', 'filter', 'post'), + 'returned new-JSON was not equal expected for insert filter' + ); + // confirm updated item + assert.deepEqual( + await testUtils.getActualJson('testExisting_filter', 'filter'), + await testUtils.getExpectedJson('9999999', 'filter', 'patch'), + 'returned existing-JSON was not equal expected for update filter' + ); + // check number of API calls + assert.equal( + testUtils.getAPIHistoryLength(), + 17, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + return; + }); + }); + + describe('Templating ================', () => { + it('Should create a filter template via buildTemplate and build it', async () => { + // download first before we test buildTemplate + await handler.retrieve('testInstance/testBU', ['filter']); + // buildTemplate + const result = await handler.buildTemplate( + 'testInstance/testBU', + 'filter', + ['testExisting_filter'], + ['testSourceMarket'] + ); + assert.equal(process.exitCode, 0, 'buildTemplate should not have thrown an error'); + assert.equal( + result.filter ? Object.keys(result.filter).length : 0, + 1, + 'only one filter expected' + ); + assert.deepEqual( + await testUtils.getActualTemplateJson('testExisting_filter', 'filter'), + await testUtils.getExpectedJson('9999999', 'filter', 'template'), + 'returned template JSON was not equal expected' + ); + // buildDefinition + await handler.buildDefinition( + 'testInstance/testBU', + 'filter', + ['testExisting_filter'], + ['testTargetMarket'] + ); + assert.equal(process.exitCode, 0, 'buildDefinition should not have thrown an error'); + assert.deepEqual( + await testUtils.getActualDeployJson('testTemplated_filter', 'filter'), + await testUtils.getExpectedJson('9999999', 'filter', 'build'), + 'returned deployment JSON was not equal expected' + ); + assert.equal( + testUtils.getAPIHistoryLength(), + 14, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + return; + }); + }); + + describe('Delete ================', () => { + it('Should delete the item', async () => { + // WHEN + const isDeleted = await handler.deleteByKey( + 'testInstance/testBU', + 'filter', + 'testExisting_filter' + ); + // THEN + assert.equal(process.exitCode, 0, 'deleteByKey should not have thrown an error'); + assert.equal(isDeleted, true, 'deleteByKey should have returned true'); + return; + }); + }); +}); diff --git a/test/type.folder.test.js b/test/type.folder.test.js new file mode 100644 index 000000000..92226e8bd --- /dev/null +++ b/test/type.folder.test.js @@ -0,0 +1,264 @@ +import * as chai from 'chai'; +const assert = chai.assert; +// const expect = chai.expect; + +import chaiFiles from 'chai-files'; +import cache from '../lib/util/cache.js'; +import * as testUtils from './utils.js'; +import handler from '../lib/index.js'; +import { Util } from '../lib/util/util.js'; +chai.use(chaiFiles); + +describe('type: folder', () => { + beforeEach(() => { + testUtils.mockSetup(); + }); + + afterEach(() => { + testUtils.mockReset(); + }); + + describe('Retrieve ================', () => { + it('Should retrieve an asset whose folder name contains a slash and escape the slash in r__folder_Path', async () => { + // GIVEN the SFMC folder "bla/blub" (child of Content Builder) and an asset in that folder + await testUtils.copyFile( + 'dataFolder/+retrieve-ContentTypeINasset,asset-shared,cloudpages-slashfolder-response.xml', + 'dataFolder/retrieve-ContentTypeINasset,asset-shared,cloudpages-response.xml' + ); + await testUtils.copyFile( + 'asset/v1/content/assets/query/+post-response-assetType.idIN3,195,196,197,198,199,200,201,202,203,210,211,212,213-slashfolder.json', + 'asset/v1/content/assets/query/post-response-assetType.idIN3,195,196,197,198,199,200,201,202,203,210,211,212,213.json' + ); + + const retrieve = await handler.retrieve('testInstance/testBU', ['asset-block']); + // THEN + assert.equal(process.exitCode, 0, 'retrieve should not have thrown an error'); + assert.equal( + retrieve['testInstance/testBU'].asset + ? Object.keys(retrieve['testInstance/testBU'].asset).length + : 0, + 5, + 'five assets expected in retrieve response (4 existing + 1 new test_slash)' + ); + // Verify the retrieved asset has the escape char (∕) in r__folder_Path, not a real slash + assert.equal( + retrieve['testInstance/testBU'].asset?.test_slash?.r__folder_Path, + 'Content Builder/bla' + Util.folderNameSlashEscapeChar + 'blub', + 'r__folder_Path should use ∕ (U+2215) to escape the slash in the folder name' + ); + return; + }); + }); + + describe('Deploy ================', () => { + it('Should create automation & dataExtension folders', async () => { + // prepare + testUtils.copyToDeploy('folder-deploy', 'folder'); + await testUtils.copyFile( + 'dataFolder/+retrieve-response.xml', + 'dataFolder/retrieve-response.xml' + ); + await testUtils.copyFile( + 'dataFolder/+retrieve-QAA-response.xml', + 'dataFolder/retrieve-QAA-response.xml' + ); + + const deployed = await handler.deploy('testInstance/testBU', ['folder']); + // THEN + assert.equal(process.exitCode, 0, 'deploy should not have thrown an error'); + // get results from cache + const cached = cache.getCache(); + assert.equal( + cached.folder ? Object.keys(cached.folder).length : 0, + 40, + 'unexpected number of folders in cache' + ); + + // check what was deployed + assert.deepEqual( + deployed['testInstance/testBU']?.folder + ? Object.values(deployed['testInstance/testBU']?.folder).map((f) => f.Path) + : null, + [ + 'Data Extensions/my', + 'Data Extensions/testExisting_folder', + 'Data Extensions/my/sub', + 'Data Extensions/my/sub/path', + 'Data Extensions/my/sub/path/subpath', + 'my automations/my', + 'my automations/my/sub', + 'my automations/my/sub/path', + 'my automations/my/sub/path/subpath', + ], + 'unexpected deployed folders' + ); + // get callouts + const createRestCallouts = testUtils.getRestCallout('post', '/email/v1/category', true); + // confirm created item + assert.deepEqual( + createRestCallouts, + [ + { parentCatId: 290937, name: 'my', catType: 'automations' }, + { parentCatId: 862100, name: 'sub', catType: 'automations' }, + { parentCatId: 862101, name: 'path', catType: 'automations' }, + { parentCatId: 862102, name: 'subpath', catType: 'automations' }, + ], + 'create-payload JSON was not equal expected' + ); + + const createSoapCallouts = testUtils.getSoapCallouts('Create', 'DataFolder'); + const updateSoapCallouts = testUtils.getSoapCallouts('Update', 'DataFolder'); + // confirm created item + assert.deepEqual( + createSoapCallouts, + [ + '<Envelope xmlns="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"><Body><CreateRequest xmlns="http://exacttarget.com/wsdl/partnerAPI"><Objects xsi:type="DataFolder"><Name>my</Name><Description></Description><ContentType>dataextension</ContentType><IsActive>true</IsActive><IsEditable>true</IsEditable><AllowChildren>true</AllowChildren><ParentFolder><ID>2</ID></ParentFolder></Objects></CreateRequest></Body><Header><fueloauth xmlns="http://exacttarget.com">9999999</fueloauth></Header></Envelope>', + '<Envelope xmlns="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"><Body><CreateRequest xmlns="http://exacttarget.com/wsdl/partnerAPI"><Objects xsi:type="DataFolder"><Name>sub</Name><Description></Description><ContentType>dataextension</ContentType><IsActive>true</IsActive><IsEditable>true</IsEditable><AllowChildren>true</AllowChildren><ParentFolder><ID>862001</ID></ParentFolder></Objects></CreateRequest></Body><Header><fueloauth xmlns="http://exacttarget.com">9999999</fueloauth></Header></Envelope>', + '<Envelope xmlns="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"><Body><CreateRequest xmlns="http://exacttarget.com/wsdl/partnerAPI"><Objects xsi:type="DataFolder"><Name>path</Name><Description></Description><ContentType>dataextension</ContentType><IsActive>true</IsActive><IsEditable>true</IsEditable><AllowChildren>true</AllowChildren><ParentFolder><ID>862002</ID></ParentFolder></Objects></CreateRequest></Body><Header><fueloauth xmlns="http://exacttarget.com">9999999</fueloauth></Header></Envelope>', + '<Envelope xmlns="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"><Body><CreateRequest xmlns="http://exacttarget.com/wsdl/partnerAPI"><Objects xsi:type="DataFolder"><Name>subpath</Name><Description></Description><ContentType>dataextension</ContentType><IsActive>true</IsActive><IsEditable>true</IsEditable><AllowChildren>true</AllowChildren><ParentFolder><ID>862003</ID></ParentFolder></Objects></CreateRequest></Body><Header><fueloauth xmlns="http://exacttarget.com">9999999</fueloauth></Header></Envelope>', + ], + 'create-payload XL was not equal expected' + ); + // confirm updated item - this should have updated despite the folder name being different (changed case). The server compares folders case insensitively + assert.deepEqual( + updateSoapCallouts, + [ + '<Envelope xmlns="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"><Body><UpdateRequest xmlns="http://exacttarget.com/wsdl/partnerAPI"><Objects xsi:type="DataFolder"><Name>testExisting_folder</Name><IsActive>true</IsActive><IsEditable>true</IsEditable><AllowChildren>true</AllowChildren><ParentFolder><ID>2</ID></ParentFolder><ID>66666</ID></Objects></UpdateRequest></Body><Header><fueloauth xmlns="http://exacttarget.com">9999999</fueloauth></Header></Envelope>', + ], + 'update-payload XL was not equal expected' + ); + + // check number of API calls + assert.equal( + testUtils.getAPIHistoryLength(), + 11, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + return; + }); + + it('Should create folder when same path exists in another Business Unit', async () => { + // prepare + // Use folder deploy data with an asset folder path + testUtils.copyToDeploy('folder-deploy-samepath', 'folder'); + // Use a modified retrieve response that includes 'Content Builder/testFolder_samePath' + // from a different BU (Client.ID=1111111). ContentType 'asset' is in folderTypesFromParent + // so it will be cached even though it belongs to another BU - simulating the bug scenario + await testUtils.copyFile( + 'dataFolder/retrieve-samePathOtherBU-response.xml', + 'dataFolder/retrieve-response.xml' + ); + + const deployed = await handler.deploy('testInstance/testBU', ['folder']); + // THEN + assert.equal(process.exitCode, 0, 'deploy should not have thrown an error'); + + // check what was deployed - 'Content Builder/testFolder_samePath' should be created + // even though it exists in another BU (1111111) + const deployedFolderPaths = deployed['testInstance/testBU']?.folder + ? Object.values(deployed['testInstance/testBU']?.folder).map((f) => f.Path) + : []; + assert.include( + deployedFolderPaths, + 'Content Builder/testFolder_samePath', + "'Content Builder/testFolder_samePath' should have been created in current BU, not skipped because it exists in another BU" + ); + + const createRestCallouts = testUtils.getRestCallout( + 'post', + '/asset/v1/content/categories', + true + ); + // 'Content Builder/testFolder_samePath' must be created in current BU via REST + // (not skipped due to same path in other BU) + assert.ok( + createRestCallouts?.some( + (c) => c.name === 'testFolder_samePath' && c.parentId === 89397 + ), + "'Content Builder/testFolder_samePath' folder creation callout not found - folder was incorrectly skipped" + ); + return; + }); + + it('Should create a folder whose name contains a slash character (direct folder deploy)', async () => { + // GIVEN a folder deploy file named Headers%2FFolders.folder-meta.json with Name "Headers/Folders" + // (the % encoding represents the actual '/' in the SFMC folder name) + testUtils.copyToDeploy('folder-deploy-slash', 'folder'); + + const deployed = await handler.deploy('testInstance/testBU', ['folder']); + // THEN + assert.equal(process.exitCode, 0, 'deploy should not have thrown an error'); + + // Verify the deployed path uses the escape char (∕) not the real slash + const deployedFolderPaths = deployed['testInstance/testBU']?.folder + ? Object.values(deployed['testInstance/testBU']?.folder).map((f) => f.Path) + : []; + assert.include( + deployedFolderPaths, + 'Content Builder/Headers' + Util.folderNameSlashEscapeChar + 'Folders', + 'deployed folder path should use escape char for the slash in folder name' + ); + + // Verify that the REST Create callout uses the REAL slash character in the name field + // (not the escape character), so that SFMC creates a folder named "Headers/Folders" + const createRestCallouts = testUtils.getRestCallout( + 'post', + '/asset/v1/content/categories', + true + ); + assert.ok( + createRestCallouts?.some( + (c) => c.name === 'Headers/Folders' && c.parentId === 89397 + ), + "REST create for 'Headers/Folders' should use the real slash in name, not the escape char" + ); + // Verify the escape char was NOT sent as the folder name + assert.ok( + !createRestCallouts?.some( + (c) => c.name === 'Headers' + Util.folderNameSlashEscapeChar + 'Folders' + ), + 'REST create should NOT use the escape char in the name field' + ); + return; + }); + + it('Should create a folder whose name contains a slash when triggered via r__folder_Path from an asset', async () => { + // GIVEN an asset deploy with r__folder_Path pointing to a subfolder whose name contains a slash + // The escape char (∕) in r__folder_Path separates the slash-in-name from path separators + testUtils.copyToDeploy('asset-slashfolder-deploy', 'asset'); + + const deployed = await handler.deploy('testInstance/testBU', ['asset']); + // THEN + assert.equal(process.exitCode, 0, 'deploy should not have thrown an error'); + + // Verify the asset was deployed + assert.equal( + deployed['testInstance/testBU']?.asset + ? Object.keys(deployed['testInstance/testBU']?.asset).length + : 0, + 1, + 'one asset should have been deployed' + ); + + // Verify the auto-generated folder was created via REST with the REAL slash in the name field + // (not the escape char), so SFMC creates a folder named "bla/blub" + const createRestCallouts = testUtils.getRestCallout( + 'post', + '/asset/v1/content/categories', + true + ); + assert.ok( + createRestCallouts?.some((c) => c.name === 'bla/blub' && c.parentId === 89397), + "REST create for 'Content Builder/bla∕blub' should send name 'bla/blub' with real slash" + ); + // Verify the escape char was NOT sent as the folder name + assert.ok( + !createRestCallouts?.some( + (c) => c.name === 'bla' + Util.folderNameSlashEscapeChar + 'blub' + ), + 'REST create should NOT use the escape char in the name field' + ); + return; + }); + }); +}); diff --git a/test/type.importFile.test.js b/test/type.importFile.test.js new file mode 100644 index 000000000..ed6e70aa1 --- /dev/null +++ b/test/type.importFile.test.js @@ -0,0 +1,223 @@ +import * as chai from 'chai'; +const assert = chai.assert; + +import chaiFiles from 'chai-files'; +import cache from '../lib/util/cache.js'; +import * as testUtils from './utils.js'; +import handler from '../lib/index.js'; +chai.use(chaiFiles); + +describe('type: importFile', () => { + beforeEach(() => { + testUtils.mockSetup(); + }); + + afterEach(() => { + testUtils.mockReset(); + }); + + describe('Retrieve ================', () => { + it('Should retrieve a importFile', async () => { + // WHEN + await handler.retrieve('testInstance/testBU', ['importFile']); + // THEN + assert.equal(process.exitCode, 0, 'retrieve should not have thrown an error'); + // get results from cache + const result = cache.getCache(); + assert.equal( + result.importFile ? Object.keys(result.importFile).length : 0, + 3, + 'unexpected number of items retrieved' + ); + assert.deepEqual( + await testUtils.getActualJson('testExisting_importFile', 'importFile'), + await testUtils.getExpectedJson('9999999', 'importFile', 'get'), + 'returned JSON was not equal expected' + ); + assert.deepEqual( + await testUtils.getActualJson('testExisting_importFileSMS', 'importFile'), + await testUtils.getExpectedJson('9999999', 'importFile', 'get-sms'), + 'returned JSON was not equal expected' + ); + assert.deepEqual( + await testUtils.getActualJson('testExisting_importFileDataImport', 'importFile'), + await testUtils.getExpectedJson('9999999', 'importFile', 'get-dataImport'), + 'returned JSON was not equal expected' + ); + assert.equal( + testUtils.getAPIHistoryLength(), + 16, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + return; + }); + + it('Should retrieve a importFile by key', async () => { + // WHEN + await handler.retrieve( + 'testInstance/testBU', + ['importFile'], + ['testExisting_importFile'] + ); + // THEN + assert.equal(process.exitCode, 0, 'retrieve should not have thrown an error'); + // get results from cache + const result = cache.getCache(); + assert.equal( + result.importFile ? Object.keys(result.importFile).length : 0, + 1, + 'only one importFile expected' + ); + assert.deepEqual( + await testUtils.getActualJson('testExisting_importFile', 'importFile'), + await testUtils.getExpectedJson('9999999', 'importFile', 'get'), + 'returned JSON was not equal expected' + ); + assert.equal( + testUtils.getAPIHistoryLength(), + 14, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + return; + }); + }); + + describe('Deploy ================', () => { + beforeEach(() => { + testUtils.mockSetup(true); + }); + + it('Should create & upsert a importFile', async () => { + // WHEN + + await handler.deploy('testInstance/testBU', ['importFile']); + // THEN + assert.equal(process.exitCode, 0, 'deploy should not have thrown an error'); + // get results from cache + const result = cache.getCache(); + assert.equal( + result.importFile ? Object.keys(result.importFile).length : 0, + 4, + 'unexptected number of importFiles in cache' + ); + // confirm created item + assert.deepEqual( + await testUtils.getActualJson('testNew_importFile', 'importFile'), + await testUtils.getExpectedJson('9999999', 'importFile', 'post'), + 'returned new-JSON was not equal expected for insert importFile' + ); + // confirm updated item + assert.deepEqual( + await testUtils.getActualJson('testExisting_importFile', 'importFile'), + await testUtils.getExpectedJson('9999999', 'importFile', 'patch'), + 'returned existing-JSON was not equal expected for update importFile' + ); + // check number of API calls + assert.equal( + testUtils.getAPIHistoryLength(), + 18, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + return; + }); + }); + + describe('Templating ================', () => { + it('Should create a importFile template via retrieveAsTemplate and build it', async () => { + // buildTemplate + const result = await handler.retrieveAsTemplate( + 'testInstance/testBU', + 'importFile', + ['testExisting_importFile'], + 'testSourceMarket' + ); + assert.equal(process.exitCode, 0, 'buildTemplate should not have thrown an error'); + assert.equal( + result.importFile ? Object.keys(result.importFile).length : 0, + 1, + 'only one importFile expected' + ); + assert.deepEqual( + await testUtils.getActualTemplateJson('testExisting_importFile', 'importFile'), + await testUtils.getExpectedJson('9999999', 'importFile', 'template'), + 'returned template JSON was not equal expected' + ); + // buildDefinition + await handler.buildDefinition( + 'testInstance/testBU', + 'importFile', + ['testExisting_importFile'], + ['testTargetMarket'] + ); + assert.equal(process.exitCode, 0, 'buildDefinition should not have thrown an error'); + assert.deepEqual( + await testUtils.getActualDeployJson('testTemplated_importFile', 'importFile'), + await testUtils.getExpectedJson('9999999', 'importFile', 'build'), + 'returned deployment JSON was not equal expected' + ); + assert.equal( + testUtils.getAPIHistoryLength(), + 14, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + return; + }); + + it('Should create a importFile template via buildTemplate and build it', async () => { + // download first before we test buildTemplate + await handler.retrieve('testInstance/testBU', ['importFile']); + // buildTemplate + const result = await handler.buildTemplate( + 'testInstance/testBU', + 'importFile', + ['testExisting_importFile'], + ['testSourceMarket'] + ); + assert.equal(process.exitCode, 0, 'buildTemplate should not have thrown an error'); + assert.equal( + result.importFile ? Object.keys(result.importFile).length : 0, + 1, + 'only one importFile expected' + ); + assert.deepEqual( + await testUtils.getActualTemplateJson('testExisting_importFile', 'importFile'), + await testUtils.getExpectedJson('9999999', 'importFile', 'template'), + 'returned template JSON was not equal expected' + ); + // buildDefinition + await handler.buildDefinition( + 'testInstance/testBU', + 'importFile', + ['testExisting_importFile'], + ['testTargetMarket'] + ); + assert.equal(process.exitCode, 0, 'buildDefinition should not have thrown an error'); + assert.deepEqual( + await testUtils.getActualDeployJson('testTemplated_importFile', 'importFile'), + await testUtils.getExpectedJson('9999999', 'importFile', 'build'), + 'returned deployment JSON was not equal expected' + ); + assert.equal( + testUtils.getAPIHistoryLength(), + 16, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + return; + }); + }); + + describe('Delete ================', () => { + it('Should delete the item', async () => { + // WHEN + const isDeleted = await handler.deleteByKey( + 'testInstance/testBU', + 'importFile', + 'testExisting_importFile' + ); + // THEN + assert.equal(process.exitCode, 0, 'deleteByKey should not have thrown an error'); + assert.equal(isDeleted, true, 'deleteByKey should have returned true'); + return; + }); + }); +}); diff --git a/test/type.journey.test.js b/test/type.journey.test.js new file mode 100644 index 000000000..54ff45e0c --- /dev/null +++ b/test/type.journey.test.js @@ -0,0 +1,1547 @@ +import * as chai from 'chai'; +const assert = chai.assert; + +import chaiFiles from 'chai-files'; +import cache from '../lib/util/cache.js'; +import * as testUtils from './utils.js'; +import handler from '../lib/index.js'; +chai.use(chaiFiles); + +describe('type: journey', () => { + beforeEach(() => { + testUtils.mockSetup(); + }); + + afterEach(() => { + testUtils.mockReset(); + }); + + describe('Retrieve ================', () => { + it('Should retrieve a journey w/o keys', async () => { + // WHEN + await handler.retrieve('testInstance/testBU', ['journey']); + // THEN + assert.equal(process.exitCode, 0, 'retrieve should not have thrown an error'); + // get results from cache + const result = cache.getCache(); + assert.equal( + result.journey ? Object.keys(result.journey).length : 0, + 5, + 'unexpected number of journeys' + ); + assert.deepEqual( + await testUtils.getActualJson('testExisting_journey_Quicksend', 'journey'), + await testUtils.getExpectedJson('9999999', 'journey', 'get-quicksend'), + 'returned JSON was not equal expected' + ); + assert.deepEqual( + await testUtils.getActualJson('testExisting_journey_Multistep', 'journey'), + await testUtils.getExpectedJson('9999999', 'journey', 'get-multistep'), + 'returned JSON was not equal expected' + ); + assert.deepEqual( + await testUtils.getActualJson('testExisting_temail', 'journey'), + await testUtils.getExpectedJson('9999999', 'journey', 'get-transactionalEmail'), + 'returned JSON was not equal expected' + ); + assert.equal( + testUtils.getAPIHistoryLength(), + 29, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + return; + }); + + it('Should retrieve only published journeys', async () => { + handler.setOptions({ onlyPublished: true }); + // WHEN + await handler.retrieve('testInstance/testBU', ['journey']); + // THEN + assert.equal(process.exitCode, 0, 'retrieve should not have thrown an error'); + // get results from cache + const result = cache.getCache(); + assert.equal( + result.journey ? Object.keys(result.journey).length : 0, + 1, + 'unexpected number of journeys' + ); + assert.deepEqual( + await testUtils.getActualJson('testExisting_temail', 'journey'), + await testUtils.getExpectedJson('9999999', 'journey', 'get-transactionalEmail'), + 'returned JSON was not equal expected' + ); + assert.equal( + testUtils.getAPIHistoryLength(), + 24, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + return; + }); + + it('Should retrieve a Quicksend journey with key', async () => { + // WHEN + await handler.retrieve( + 'testInstance/testBU', + ['journey'], + ['testExisting_journey_Quicksend'] + ); + // THEN + assert.equal(process.exitCode, 0, 'retrieve should not have thrown an error'); + // get results from cache + const result = cache.getCache(); + assert.equal( + result.journey ? Object.keys(result.journey).length : 0, + 1, + 'only 1 journeys expected' + ); + assert.deepEqual( + await testUtils.getActualJson('testExisting_journey_Quicksend', 'journey'), + await testUtils.getExpectedJson('9999999', 'journey', 'get-quicksend'), + 'returned JSON was not equal expected' + ); + assert.equal( + testUtils.getAPIHistoryLength(), + 19, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + return; + }); + + it('Should retrieve a Multistep journey with key', async () => { + // WHEN + await handler.retrieve( + 'testInstance/testBU', + ['journey'], + ['testExisting_journey_Multistep'] + ); + // THEN + assert.equal(process.exitCode, 0, 'retrieve should not have thrown an error'); + // get results from cache + const result = cache.getCache(); + assert.equal( + result.journey ? Object.keys(result.journey).length : 0, + 1, + 'only 1 journeys expected' + ); + + assert.deepEqual( + await testUtils.getActualJson('testExisting_journey_Multistep', 'journey'), + await testUtils.getExpectedJson('9999999', 'journey', 'get-multistep'), + 'returned JSON was not equal expected' + ); + assert.equal( + testUtils.getAPIHistoryLength(), + 19, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + return; + }); + + it('Should retrieve a journey containing an UPDATECONTACTDATA activity with key', async () => { + // WHEN + await handler.retrieve( + 'testInstance/testBU', + ['journey'], + ['testExisting_journey_updatecontact'] + ); + // THEN + assert.equal(process.exitCode, 0, 'retrieve should not have thrown an error'); + // get results from cache + const result = cache.getCache(); + assert.equal( + result.journey ? Object.keys(result.journey).length : 0, + 1, + 'only 1 journeys expected' + ); + + assert.deepEqual( + await testUtils.getActualJson('testExisting_journey_updatecontact', 'journey'), + await testUtils.getExpectedJson('9999999', 'journey', 'get-updatecontact'), + 'returned JSON was not equal expected' + ); + assert.equal( + testUtils.getAPIHistoryLength(), + 20, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + return; + }); + + it('Should retrieve a Transactional Email journey with key', async () => { + // WHEN + await handler.retrieve('testInstance/testBU', ['journey'], ['testExisting_temail']); + // THEN + assert.equal(process.exitCode, 0, 'retrieve should not have thrown an error'); + // get results from cache + const result = cache.getCache(); + assert.equal( + result.journey ? Object.keys(result.journey).length : 0, + 1, + 'only 1 journeys expected' + ); + + assert.deepEqual( + await testUtils.getActualJson('testExisting_temail', 'journey'), + await testUtils.getExpectedJson('9999999', 'journey', 'get-transactionalEmail'), + 'returned JSON was not equal expected' + ); + assert.equal( + testUtils.getAPIHistoryLength(), + 23, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + return; + }); + + it('Should retrieve a journey with id', async () => { + // WHEN + await handler.retrieve( + 'testInstance/testBU', + ['journey'], + ['id:3c3f4112-9b43-43ca-8a89-aa0375b2c1a2'] + ); + // THEN + assert.equal(process.exitCode, 0, 'retrieve should not have thrown an error'); + // get results from cache + const result = cache.getCache(); + assert.equal( + result.journey ? Object.keys(result.journey).length : 0, + 1, + 'only 1 journeys expected' + ); + assert.deepEqual( + await testUtils.getActualJson('testExisting_journey_Quicksend', 'journey'), + await testUtils.getExpectedJson('9999999', 'journey', 'get-quicksend'), + 'returned JSON was not equal expected' + ); + assert.equal( + testUtils.getAPIHistoryLength(), + 19, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + return; + }); + + it('Should retrieve a journey with name', async () => { + // WHEN + await handler.retrieve( + 'testInstance/testBU', + ['journey'], + ['name:testExisting_journey_Quicksend'] + ); + // THEN + assert.equal(process.exitCode, 0, 'retrieve should not have thrown an error'); + // get results from cache + const result = cache.getCache(); + assert.equal( + result.journey ? Object.keys(result.journey).length : 0, + 1, + 'only 1 journeys expected' + ); + assert.deepEqual( + await testUtils.getActualJson('testExisting_journey_Quicksend', 'journey'), + await testUtils.getExpectedJson('9999999', 'journey', 'get-quicksend'), + 'returned JSON was not equal expected' + ); + assert.equal( + testUtils.getAPIHistoryLength(), + 20, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + return; + }); + }); + + describe('Deploy ================', () => { + beforeEach(() => { + testUtils.mockSetup(true); + }); + + it('Should NOT change the key during update with --changeKeyValue and instead fail due to missing support', async () => { + // WHEN + handler.setOptions({ changeKeyValue: 'updatedKey' }); + await handler.deploy( + 'testInstance/testBU', + ['journey'], + ['testExisting_journey_Quicksend'] + ); + // THEN + assert.equal( + process.exitCode, + 1, + 'deploy should have thrown an error due to lack of support' + ); + return; + }); + + it('Should deploy --publish an already published transactional journey by first pausing it', async () => { + await testUtils.copyFile( + 'interaction/v1/interactions/key_testExisting_temail/put-response-paused.json', + 'interaction/v1/interactions/key_testExisting_temail/put-response.json' + ); + // WHEN + handler.setOptions({ skipStatusCheck: true, publish: true }); + const deploy = await handler.deploy( + 'testInstance/testBU', + ['journey'], + ['testExisting_temail'] + ); + + // THEN + assert.equal(process.exitCode, 0, 'deploy --publish should not have thrown an error'); + // retrieve result + assert.deepEqual( + Object.keys(deploy['testInstance/testBU']?.journey), + ['testExisting_temail'], + 'should have published the right journey' + ); + + const pauseCallout = testUtils.getRestCallout( + 'post', + '/interaction/v1/interactions/transactional/pause' + ); + const resumeCallout = testUtils.getRestCallout( + 'post', + '/interaction/v1/interactions/transactional/resume' + ); + + // confirm callouts + assert.deepEqual( + pauseCallout, + { + definitionId: 'dsfdsafdsa-922c-4568-85a5-e5cc77efc3be', + }, + 'pauseCallout-payload JSON was not equal expected' + ); + assert.deepEqual( + resumeCallout, + { + definitionId: 'dsfdsafdsa-922c-4568-85a5-e5cc77efc3be', + }, + 'resumeCallout-payload JSON was not equal expected' + ); + + assert.equal( + testUtils.getAPIHistoryLength(), + 60, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + return; + }); + + it('Should update and publish a transactional journey', async () => { + // WHEN + handler.setOptions({ skipStatusCheck: true, publish: true }); + const deploy = await handler.deploy( + 'testInstance/testBU', + ['journey'], + ['testExisting_temail_notPublished'] + ); + + // THEN + assert.equal(process.exitCode, 0, 'deploy --publish should not have thrown an error'); + // retrieve result + assert.deepEqual( + Object.keys(deploy['testInstance/testBU']?.journey), + ['testExisting_temail_notPublished'], + 'should have published the right journey' + ); + + // get callouts + const publishCallout = testUtils.getRestCallout( + 'post', + '/interaction/v1/interactions/transactional/create' + ); + // confirm callouts + assert.deepEqual( + publishCallout, + { + definitionId: 'd4a900fe-3a8f-4cc5-9a49-81286e3e2cd2', + }, + 'publish-payload JSON was not equal expected' + ); + + // confirm transactionalEmail was downloaded + assert.deepEqual( + await testUtils.getActualJson( + 'testExisting_temail_notPublished', + 'transactionalEmail' + ), + await testUtils.getExpectedJson('9999999', 'transactionalEmail', 'get-published'), + 'returned JSON was not equal expected' + ); + + assert.equal( + testUtils.getAPIHistoryLength(), + 59, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + return; + }); + + it('Should create and publish a transactional journey', async () => { + // WHEN + handler.setOptions({ skipStatusCheck: true, publish: true }); + const deploy = await handler.deploy( + 'testInstance/testBU', + ['journey'], + ['testNew_temail_notPublished'] + ); + + // THEN + assert.equal(process.exitCode, 0, 'deploy --publish should not have thrown an error'); + // retrieve result + assert.deepEqual( + Object.keys(deploy['testInstance/testBU']?.journey), + ['testNew_temail_notPublished'], + 'should have published the right journey' + ); + + // get callouts + const publishCallout = testUtils.getRestCallout( + 'post', + '/interaction/v1/interactions/transactional/create' + ); + // confirm callouts + assert.deepEqual( + publishCallout, + { + definitionId: '4c39662b-7c47-4df4-8bd6-65f01c313e8c', + }, + 'publish-payload JSON was not equal expected' + ); + + // confirm transactionalEmail was downloaded + assert.deepEqual( + await testUtils.getActualJson('testNew_temail_notPublished', 'transactionalEmail'), + await testUtils.getExpectedJson('9999999', 'transactionalEmail', 'create-publish'), + 'returned JSON was not equal expected' + ); + // confirm journey was downloaded + assert.deepEqual( + await testUtils.getActualJson('testNew_temail_notPublished', 'journey'), + await testUtils.getExpectedJson( + '9999999', + 'journey', + 'create-transactionaEmail-publish' + ), + 'returned JSON was not equal expected' + ); + + assert.equal( + testUtils.getAPIHistoryLength(), + 59, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + return; + }); + + it('Should update & publish a multi-step journey by key (auto-picks latest version)', async () => { + handler.setOptions({ skipStatusCheck: true, publish: true }); + // WHEN + const deploy = await handler.deploy( + 'testInstance/testBU', + ['journey'], + ['testExisting_journey_Multistep'] + ); + // THEN + assert.equal(process.exitCode, 0, 'publish should not have thrown an error'); + // retrieve result + assert.deepEqual( + Object.keys(deploy['testInstance/testBU']?.journey), + ['testExisting_journey_Multistep'], + 'should have published the right journey' + ); + + // get callouts + const publishCallout = testUtils.getRestCallout( + 'post', + '/interaction/v1/interactions/publishAsync/%' + ); + // confirm created item + assert.deepEqual( + publishCallout, + await testUtils.getExpectedJson('9999999', 'journey', 'publish-callout'), + 'publish-payload JSON was not equal expected' + ); + // confirm event was downloaded + assert.deepEqual( + await testUtils.getActualJson( + 'DEAudience-2e3c73b6-48cc-2ec0-5522-48636e1a236e', + 'event' + ), + await testUtils.getExpectedJson('9999999', 'event', 'get-published'), + 'returned JSON was not equal expected' + ); + + assert.equal( + testUtils.getAPIHistoryLength(), + 50, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + return; + }); + + it('Should update a journey with UPDATECONTACT activity', async () => { + // WHEN + await handler.deploy( + 'testInstance/testBU', + ['journey'], + ['testExisting_journey_updatecontact'] + ); + // THEN + assert.equal(process.exitCode, 0, 'deploy should not have thrown an error'); + // // confirm updated item + assert.deepEqual( + await testUtils.getActualJson('testExisting_journey_updatecontact', 'journey'), + await testUtils.getExpectedJson('9999999', 'journey', 'put-updatecontact'), + 'returned metadata was not equal expected for update journey with updatecontact activity' + ); + assert.equal( + testUtils.getAPIHistoryLength(), + 22, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + return; + }); + }); + + describe('Templating ================', () => { + it('Should create a journey template via buildTemplate and build it', async () => { + // download first before we test buildTemplate + await handler.retrieve('testInstance/testBU', ['journey']); + // buildTemplate + const result = await handler.buildTemplate( + 'testInstance/testBU', + 'journey', + ['testExisting_journey_Quicksend'], + ['testSourceMarket'] + ); + assert.equal(process.exitCode, 0, 'buildTemplate should not have thrown an error'); + assert.equal( + result.journey ? Object.keys(result.journey).length : 0, + 1, + 'only one journey expected' + ); + assert.deepEqual( + await testUtils.getActualTemplateJson('testExisting_journey_Quicksend', 'journey'), + await testUtils.getExpectedJson('9999999', 'journey', 'template'), + 'returned template JSON was not equal expected' + ); + + // buildDefinition + await handler.buildDefinition( + 'testInstance/testBU', + 'journey', + ['testExisting_journey_Quicksend'], + ['testTargetMarket'] + ); + assert.equal(process.exitCode, 0, 'buildDefinition should not have thrown an error'); + assert.deepEqual( + await testUtils.getActualDeployJson('testTemplated_journey_Quicksend', 'journey'), + await testUtils.getExpectedJson('9999999', 'journey', 'build'), + 'returned deployment JSON was not equal expected' + ); + + assert.equal( + testUtils.getAPIHistoryLength(), + 29, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + return; + }); + + it('Should create a journey template via buildTemplate with --dependencies', async () => { + // download first before we test buildTemplate + await handler.retrieve('testInstance/testBU', ['journey', 'asset']); + assert.equal(process.exitCode, 0, 'retrieve should not have thrown an error'); + + handler.setOptions({ dependencies: true, retrieve: true }); + + // GIVEN there is a template + const templatedItems = await handler.buildTemplate( + 'testInstance/testBU', + 'journey', + ['testExisting_journey_Quicksend', 'testExisting_journey_Multistep'], + ['testSourceMarket'] + ); + // WHEN + assert.equal(process.exitCode, 0, 'buildTemplate should not have thrown an error'); + + assert.deepEqual( + Object.keys(templatedItems), + [ + 'asset', + 'dataExtension', + 'domainVerification', + 'event', + 'journey', + 'sendClassification', + 'senderProfile', + ], + 'expected specific types to be templated' + ); + + // journey + assert.deepEqual( + templatedItems.journey.map((item) => item.key), + ['{{{prefix}}}journey_Multistep', '{{{prefix}}}journey_Quicksend'], + 'expected specific journeys to be templated' + ); + // event + assert.deepEqual( + templatedItems.event.map((item) => item.eventDefinitionKey), + [ + 'DEAudience-11be962d-064c-83d9-2804-7d1befc10325', + 'DEAudience-2e3c73b6-48cc-2ec0-5522-48636e1a236e', + ], + 'expected specific events to be templated' + ); + // dataExtension + assert.deepEqual( + templatedItems.dataExtension.map((item) => item.CustomerKey), + [ + '{{{prefix}}}DomainExclusion', + '{{{prefix}}}journey_Multistep', + '{{{prefix}}}journey_Quicksend', + ], + 'expected specific dataExtensions to be templated' + ); + // domainVerification + assert.deepEqual( + templatedItems.domainVerification.map((item) => item.domain), + ['joern.berkefeld+test@accenture.com', 'joern.berkefeld@accenture.com'], + 'expected specific domainVerifications to be templated' + ); + // senderProfile + assert.deepEqual( + templatedItems.senderProfile.map((item) => item.CustomerKey), + ['{{{prefix}}}senderProfile'], + 'expected specific assets to be templated' + ); + // sendClassification + assert.deepEqual( + templatedItems.sendClassification.map((item) => item.CustomerKey), + ['{{{prefix}}}sendClassification'], + 'expected specific sendClassifications to be templated' + ); + // asset + assert.deepEqual( + templatedItems.asset.map((item) => item.customerKey), + [ + '{{{prefix}}}asset_htmlblock', + '{{{prefix}}}htmlblock 3 spaces', + '{{{prefix}}}htmlblock1', + '{{{prefix}}}htmlblock2', + ], + 'expected specific assets to be templated' + ); + }); + }); + + describe('Delete ================', () => { + it('Should NOT delete the item due to missing version', async () => { + // WHEN + const isDeleted = await handler.deleteByKey( + 'testInstance/testBU', + 'journey', + 'testExisting_journey_Multistep' + ); + // THEN + assert.equal(process.exitCode, 1, 'delete should have thrown an error'); + + assert.equal(isDeleted, false, 'should not have deleted the item'); + return; + }); + + it('Should NOT delete the item due to unknown version', async () => { + // WHEN + const isDeleted = await handler.deleteByKey( + 'testInstance/testBU', + 'journey', + 'testExisting_journey_Multistep/2' + ); + // THEN + assert.equal(process.exitCode, 1, 'delete should have thrown an error'); + + assert.equal(isDeleted, false, 'should not have deleted the item'); + return; + }); + + it('Should delete the item with exact version', async () => { + // WHEN + const isDeleted = await handler.deleteByKey( + 'testInstance/testBU', + 'journey', + 'testExisting_journey_Multistep/1' + ); + // THEN + assert.equal(process.exitCode, 0, 'delete should not have thrown an error'); + + assert.equal(isDeleted, true, 'should have deleted the item'); + return; + }); + + it('Should delete the item with all versions', async () => { + // WHEN + const isDeleted = await handler.deleteByKey( + 'testInstance/testBU', + 'journey', + 'testExisting_journey_Multistep/*' + ); + // THEN + assert.equal(process.exitCode, 0, 'delete should not have thrown an error'); + + assert.equal(isDeleted, true, 'should have deleted the item'); + return; + }); + + it('Should delete 2 items with exact version', async () => { + // WHEN + const isDeleted = await handler.deleteByKey('testInstance/testBU', 'journey', [ + 'testExisting_journey_Quicksend', + 'testExisting_temail', + 'testExisting_journey_Multistep/1', + ]); + // THEN + assert.equal(process.exitCode, 0, 'delete should not have thrown an error'); + + assert.equal(isDeleted, true, 'should have deleted the item'); + return; + }); + }); + + describe('ReplaceContentBlockByX ================', () => { + it('Should replace references with ContentBlockByName w/o deploy', async () => { + handler.setOptions({ skipDeploy: true }); + + // WHEN + const replace = await handler.replaceCbReference( + 'testInstance/testBU', + { + journey: null, + }, + 'name' + ); + // THEN + assert.equal(process.exitCode, 0, 'retrieve should not have thrown an error'); + // retrieve result + assert.deepEqual( + replace['testInstance/testBU'].journey, + ['testExisting_journey_Quicksend'], + 'should have found the right journeys that need updating' + ); + + // check if conversions happened + assert.deepEqual( + await testUtils.getActualJson('testExisting_journey_Quicksend', 'journey'), + await testUtils.getExpectedJson('9999999', 'journey', 'get-quicksend-rcb-name'), + 'returned JSON was not equal expected' + ); + + assert.equal( + testUtils.getAPIHistoryLength(), + 35, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + return; + }); + + it('Should replace references with ContentBlockById w/o deploy', async () => { + handler.setOptions({ skipDeploy: true }); + + // WHEN + const replace = await handler.replaceCbReference( + 'testInstance/testBU', + { + journey: null, + }, + 'id' + ); + // THEN + assert.equal(process.exitCode, 0, 'retrieve should not have thrown an error'); + // retrieve result + assert.deepEqual( + replace['testInstance/testBU'].journey, + ['testExisting_journey_Quicksend'], + 'should have found the right journeys that need updating' + ); + + // check if conversions happened + assert.deepEqual( + await testUtils.getActualJson('testExisting_journey_Quicksend', 'journey'), + await testUtils.getExpectedJson('9999999', 'journey', 'get-quicksend-rcb-id'), + 'returned JSON was not equal expected' + ); + + assert.equal( + testUtils.getAPIHistoryLength(), + 35, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + return; + }); + + it('Should replace references with ContentBlockByKey w/o deploy', async () => { + handler.setOptions({ skipDeploy: true }); + + // WHEN + const replace = await handler.replaceCbReference( + 'testInstance/testBU', + { + journey: null, + }, + 'key' + ); + // THEN + assert.equal(process.exitCode, 0, 'retrieve should not have thrown an error'); + // retrieve result + assert.deepEqual( + replace['testInstance/testBU'].journey, + ['testExisting_journey_Quicksend'], + 'should have found the right assets that need updating' + ); + + // check if conversions happened + assert.deepEqual( + await testUtils.getActualJson('testExisting_journey_Quicksend', 'journey'), + await testUtils.getExpectedJson('9999999', 'journey', 'get-quicksend-rcb-key'), + 'returned JSON was not equal expected' + ); + + assert.equal( + testUtils.getAPIHistoryLength(), + 35, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + return; + }); + }); + + describe('Publish ================', () => { + it(`Should not publish a transactional journey by key that is already published but instead trigger a refresh`, async () => { + handler.setOptions({ skipStatusCheck: true }); + // WHEN + const publish = await handler.publish( + 'testInstance/testBU', + ['journey'], + ['testExisting_temail'] + ); + // THEN + assert.equal(process.exitCode, 0, 'publish should not have thrown an error'); + + assert.deepEqual( + publish['testInstance/testBU']?.journey, + ['testExisting_temail'], + 'should not have published any journey but instead triggered a refresh' + ); + + // get callouts + const pauseCallout = testUtils.getRestCallout( + 'post', + '/interaction/v1/interactions/transactional/pause' + ); + const resumeCallout = testUtils.getRestCallout( + 'post', + '/interaction/v1/interactions/transactional/resume' + ); + const pauseResumeResponse = { + definitionId: 'dsfdsafdsa-922c-4568-85a5-e5cc77efc3be', + }; + // confirm responses + assert.deepEqual( + pauseCallout, + pauseResumeResponse, + 'pause-payload JSON was not equal expected' + ); + assert.deepEqual( + resumeCallout, + pauseResumeResponse, + 'resume-payload JSON was not equal expected' + ); + + // confirm transactionalEmail was downloaded + assert.deepEqual( + await testUtils.getActualJson('testExisting_temail', 'journey'), + await testUtils.getExpectedJson('9999999', 'journey', 'get-transactionalEmail'), + 'returned JSON was not equal expected' + ); + assert.deepEqual( + await testUtils.getActualJson('testExisting_temail', 'transactionalEmail'), + await testUtils.getExpectedJson('9999999', 'transactionalEmail', 'get'), + 'returned JSON was not equal expected' + ); + + assert.equal( + testUtils.getAPIHistoryLength(), + 38, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + return; + }); + + it('Should publish a transactional journey by key', async () => { + handler.setOptions({ skipStatusCheck: true }); + // WHEN + const publish = await handler.publish( + 'testInstance/testBU', + ['journey'], + ['testExisting_temail_notPublished'] + ); + // THEN + assert.equal(process.exitCode, 0, 'publish should not have thrown an error'); + // retrieve result + assert.deepEqual( + publish['testInstance/testBU']?.journey, + ['testExisting_temail_notPublished'], + 'should have published the right journey' + ); + + // get callouts + const publishCallout = testUtils.getRestCallout( + 'post', + '/interaction/v1/interactions/transactional/create' + ); + // confirm callouts + assert.deepEqual( + publishCallout, + { + definitionId: 'd4a900fe-3a8f-4cc5-9a49-81286e3e2cd2', + }, + 'publish-payload JSON was not equal expected' + ); + assert.deepEqual( + await testUtils.getActualJson('testExisting_temail_notPublished', 'journey'), + await testUtils.getExpectedJson('9999999', 'journey', 'get-published'), + 'returned JSON was not equal expected' + ); + + // confirm transactionalEmail was downloaded + assert.deepEqual( + await testUtils.getActualJson( + 'testExisting_temail_notPublished', + 'transactionalEmail' + ), + await testUtils.getExpectedJson('9999999', 'transactionalEmail', 'get-published'), + 'returned JSON was not equal expected' + ); + + assert.equal( + testUtils.getAPIHistoryLength(), + 36, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + return; + }); + + it('Should publish a journey by key (auto-picks latest version)', async () => { + handler.setOptions({ skipStatusCheck: true }); + // WHEN + const publish = await handler.publish( + 'testInstance/testBU', + ['journey'], + ['testExisting_journey_Multistep'] + ); + // THEN + assert.equal(process.exitCode, 0, 'publish should not have thrown an error'); + // retrieve result + assert.deepEqual( + publish['testInstance/testBU']?.journey, + ['testExisting_journey_Multistep'], + 'should have published the right journey' + ); + + // get callouts + const publishCallout = testUtils.getRestCallout( + 'post', + '/interaction/v1/interactions/publishAsync/%' + ); + // confirm created item + assert.deepEqual( + publishCallout, + await testUtils.getExpectedJson('9999999', 'journey', 'publish-callout'), + 'publish-payload JSON was not equal expected' + ); + // confirm event was downloaded + assert.deepEqual( + await testUtils.getActualJson( + 'DEAudience-2e3c73b6-48cc-2ec0-5522-48636e1a236e', + 'event' + ), + await testUtils.getExpectedJson('9999999', 'event', 'get-published'), + 'returned JSON was not equal expected' + ); + + assert.equal( + testUtils.getAPIHistoryLength(), + 31, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + return; + }); + + it('Should publish a journey by id w/ version', async () => { + handler.setOptions({ skipStatusCheck: true }); + // WHEN + const publish = await handler.publish( + 'testInstance/testBU', + ['journey'], + ['id:0175b971-71a3-4d8e-98ac-48121f3fbf4f/1'] + ); + // THEN + assert.equal(process.exitCode, 0, 'publish should not have thrown an error'); + // retrieve result + assert.deepEqual( + publish['testInstance/testBU']?.journey, + ['id:0175b971-71a3-4d8e-98ac-48121f3fbf4f/1'], + 'should have published the right journey' + ); + + // get callouts + const publishCallout = testUtils.getRestCallout( + 'post', + '/interaction/v1/interactions/publishAsync/%' + ); + // confirm created item + assert.deepEqual( + publishCallout, + await testUtils.getExpectedJson('9999999', 'journey', 'publish-callout'), + 'publish-payload JSON was not equal expected' + ); + // confirm event was downloaded + assert.deepEqual( + await testUtils.getActualJson( + 'DEAudience-2e3c73b6-48cc-2ec0-5522-48636e1a236e', + 'event' + ), + await testUtils.getExpectedJson('9999999', 'event', 'get-published'), + 'returned JSON was not equal expected' + ); + assert.equal( + testUtils.getAPIHistoryLength(), + 31, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + return; + }); + + it('Should publish a journey by id but w/o version (auto-picks latest version)', async () => { + handler.setOptions({ skipStatusCheck: true }); + // WHEN + const publish = await handler.publish( + 'testInstance/testBU', + ['journey'], + ['id:0175b971-71a3-4d8e-98ac-48121f3fbf4f'] + ); + // THEN + assert.equal(process.exitCode, 0, 'publish should not have thrown an error'); + // retrieve result + assert.deepEqual( + publish['testInstance/testBU']?.journey, + ['id:0175b971-71a3-4d8e-98ac-48121f3fbf4f'], + 'should have published the right journey' + ); + + // get callouts + const publishCallout = testUtils.getRestCallout( + 'post', + '/interaction/v1/interactions/publishAsync/%' + ); + // confirm created item + assert.deepEqual( + publishCallout, + await testUtils.getExpectedJson('9999999', 'journey', 'publish-callout'), + 'publish-payload JSON was not equal expected' + ); + + assert.equal( + testUtils.getAPIHistoryLength(), + 31, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + return; + }); + + it('Should publish a journey by id w/ version with failing status check', async () => { + await testUtils.copyFile( + 'interaction/v1/interactions/publishStatus/45f06c0a-3ed2-48b2-a6a8-b5119253f01c/get-response-failed.json', + 'interaction/v1/interactions/publishStatus/45f06c0a-3ed2-48b2-a6a8-b5119253f01c/get-response.json' + ); + + handler.setOptions({ skipStatusCheck: false, _runningTest: true }); + // WHEN + const publish = await handler.publish( + 'testInstance/testBU', + ['journey'], + ['id:0175b971-71a3-4d8e-98ac-48121f3fbf4f/1'] + ); + // THEN + assert.equal(process.exitCode, 1, 'publish should have thrown an error'); + // retrieve result + assert.equal( + publish['testInstance/testBU']?.journey.length, + 0, + 'should have not published the journey' + ); + + // get callouts + const publishCallout = testUtils.getRestCallout( + 'post', + '/interaction/v1/interactions/publishAsync/%' + ); + // confirm created item + assert.deepEqual( + publishCallout, + await testUtils.getExpectedJson('9999999', 'journey', 'publish-callout'), + 'publish-payload JSON was not equal expected' + ); + + assert.equal( + testUtils.getAPIHistoryLength(), + 3, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + return; + }); + + it('Should publish a journey by id w/ version with successful status check but with warnings', async () => { + await testUtils.copyFile( + 'interaction/v1/interactions/publishStatus/45f06c0a-3ed2-48b2-a6a8-b5119253f01c/get-response-successWarnings.json', + 'interaction/v1/interactions/publishStatus/45f06c0a-3ed2-48b2-a6a8-b5119253f01c/get-response.json' + ); + + handler.setOptions({ skipStatusCheck: false, _runningTest: true }); + // WHEN + const publish = await handler.publish( + 'testInstance/testBU', + ['journey'], + ['id:0175b971-71a3-4d8e-98ac-48121f3fbf4f/1'] + ); + // THEN + assert.equal(process.exitCode, 0, 'publish should not have thrown an error'); + // retrieve result + assert.deepEqual( + publish['testInstance/testBU']?.journey, + ['testExisting_journey_Multistep'], + 'should have published the journey' + ); + + // get callouts + const publishCallout = testUtils.getRestCallout( + 'post', + '/interaction/v1/interactions/publishAsync/%' + ); + // confirm created item + assert.deepEqual( + publishCallout, + await testUtils.getExpectedJson('9999999', 'journey', 'publish-callout'), + 'publish-payload JSON was not equal expected' + ); + // confirm event was downloaded + assert.deepEqual( + await testUtils.getActualJson( + 'DEAudience-2e3c73b6-48cc-2ec0-5522-48636e1a236e', + 'event' + ), + await testUtils.getExpectedJson('9999999', 'event', 'get-published'), + 'returned JSON was not equal expected' + ); + + assert.equal( + testUtils.getAPIHistoryLength(), + 32, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + return; + }); + + it('Should publish a journey by id w/ version with successful status check', async () => { + await testUtils.copyFile( + 'interaction/v1/interactions/publishStatus/45f06c0a-3ed2-48b2-a6a8-b5119253f01c/get-response-success.json', + 'interaction/v1/interactions/publishStatus/45f06c0a-3ed2-48b2-a6a8-b5119253f01c/get-response.json' + ); + + handler.setOptions({ skipStatusCheck: false, _runningTest: true }); + // WHEN + const publish = await handler.publish( + 'testInstance/testBU', + ['journey'], + ['id:0175b971-71a3-4d8e-98ac-48121f3fbf4f/1'] + ); + // THEN + assert.equal(process.exitCode, 0, 'publish should not have thrown an error'); + // retrieve result + assert.deepEqual( + publish['testInstance/testBU']?.journey, + ['testExisting_journey_Multistep'], + 'should have published the journey' + ); + + // get callouts + const publishCallout = testUtils.getRestCallout( + 'post', + '/interaction/v1/interactions/publishAsync/%' + ); + // confirm created item + assert.deepEqual( + publishCallout, + await testUtils.getExpectedJson('9999999', 'journey', 'publish-callout'), + 'publish-payload JSON was not equal expected' + ); + // confirm event was downloaded + assert.deepEqual( + await testUtils.getActualJson( + 'DEAudience-2e3c73b6-48cc-2ec0-5522-48636e1a236e', + 'event' + ), + await testUtils.getExpectedJson('9999999', 'event', 'get-published'), + 'returned JSON was not equal expected' + ); + + assert.equal( + testUtils.getAPIHistoryLength(), + 32, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + return; + }); + }); + + describe('Validate ================', () => { + it('Should not validate a transactional journey by key', async () => { + handler.setOptions({ skipStatusCheck: true }); + // WHEN + const validate = await handler.validate( + 'testInstance/testBU', + ['journey'], + ['testExisting_temail_notPublished'] + ); + // THEN + assert.equal(process.exitCode, 0, 'validate should not have thrown an error'); + // retrieve result + assert.deepEqual( + validate['testInstance/testBU']?.journey, + [], + 'should not have validated any journey' + ); + + assert.equal( + testUtils.getAPIHistoryLength(), + 1, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + return; + }); + + it('Should validate a multi-step journey but not the transactional journey by key', async () => { + await testUtils.copyFile( + 'interaction/v1/interactions/validateStatus/45f06c0a-3ed2-48b2-a6a8-b5119253f01c/get-response-success.json', + 'interaction/v1/interactions/validateStatus/45f06c0a-3ed2-48b2-a6a8-b5119253f01c/get-response.json' + ); + handler.setOptions({ skipStatusCheck: true }); + // WHEN + const validate = await handler.validate( + 'testInstance/testBU', + ['journey'], + ['testExisting_temail_notPublished', 'testExisting_journey_Multistep'] + ); + // THEN + assert.equal(process.exitCode, 0, 'validate should not have thrown an error'); + // retrieve result + assert.deepEqual( + validate['testInstance/testBU']?.journey, + ['testExisting_journey_Multistep'], + 'should not have validated any journey' + ); + + assert.equal( + testUtils.getAPIHistoryLength(), + 3, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + return; + }); + + it('Should validate a journey by id but w/o version (auto-picks latest version)', async () => { + await testUtils.copyFile( + 'interaction/v1/interactions/validateStatus/45f06c0a-3ed2-48b2-a6a8-b5119253f01c/get-response-success.json', + 'interaction/v1/interactions/validateStatus/45f06c0a-3ed2-48b2-a6a8-b5119253f01c/get-response.json' + ); + // WHEN + const validate = await handler.validate( + 'testInstance/testBU', + ['journey'], + ['id:0175b971-71a3-4d8e-98ac-48121f3fbf4f'] + ); + // THEN + assert.equal(process.exitCode, 0, 'validate should not have thrown an error'); + // retrieve result + assert.deepEqual( + validate['testInstance/testBU']?.journey, + ['testExisting_journey_Multistep'], + 'should have validateed the right journey' + ); + + // get callouts + const validateCallout = testUtils.getRestCallout( + 'post', + '/interaction/v1/interactions/validateAsync/%' + ); + // confirm created item + assert.deepEqual( + validateCallout, + await testUtils.getExpectedJson('9999999', 'journey', 'validate-callout'), + 'validate-payload JSON was not equal expected' + ); + + assert.equal( + testUtils.getAPIHistoryLength(), + 3, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + return; + }); + + it('Should validate a journey by id w/ version with failing status check', async () => { + await testUtils.copyFile( + 'interaction/v1/interactions/publishStatus/45f06c0a-3ed2-48b2-a6a8-b5119253f01c/get-response-failed.json', + 'interaction/v1/interactions/validateStatus/45f06c0a-3ed2-48b2-a6a8-b5119253f01c/get-response.json' + ); + + handler.setOptions({ _runningTest: true }); + // WHEN + const validate = await handler.validate( + 'testInstance/testBU', + ['journey'], + ['id:0175b971-71a3-4d8e-98ac-48121f3fbf4f/1'] + ); + // THEN + assert.equal(process.exitCode, 1, 'validate should have thrown an error'); + // retrieve result + assert.equal( + validate['testInstance/testBU']?.journey.length, + 0, + 'should have not validated the journey' + ); + + // get callouts + const validateCallout = testUtils.getRestCallout( + 'post', + '/interaction/v1/interactions/validateAsync/%' + ); + // confirm created item + assert.deepEqual( + validateCallout, + await testUtils.getExpectedJson('9999999', 'journey', 'validate-callout'), + 'validate-payload JSON was not equal expected' + ); + + assert.equal( + testUtils.getAPIHistoryLength(), + 3, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + return; + }); + }); + + describe('Refresh ================', () => { + it('Should refresh all active journeys'); + + it('Should refresh a specifc multi-step journey by key', async () => { + // WHEN + const replace = await handler.refresh('testInstance/testBU', { + journey: ['testExisting_journey_Multistep'], + }); + // THEN + assert.equal(process.exitCode, 0, 'refresh should not have thrown an error'); + // retrieve result + + assert.deepEqual( + replace['testInstance/testBU'].journey, + ['testExisting_journey_Multistep'], + 'should have found the right journeys that need updating' + ); + + assert.equal( + testUtils.getAPIHistoryLength(), + 6, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + return; + }); + + it('Should refresh a specifc transactional send journey by key', async () => { + // WHEN + const replace = await handler.refresh('testInstance/testBU', { + journey: ['testExisting_temail'], + }); + // THEN + assert.equal(process.exitCode, 0, 'refresh should not have thrown an error'); + // retrieve result + + assert.deepEqual( + replace['testInstance/testBU'].journey, + ['testExisting_temail'], + 'should have found the right journeys that need updating' + ); + + assert.equal( + testUtils.getAPIHistoryLength(), + 37, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + return; + }); + + it('Should refresh a specifc cross type journeys by key', async () => { + // WHEN + const replace = await handler.refresh('testInstance/testBU', { + journey: ['testExisting_temail', 'testExisting_journey_Multistep'], + }); + // THEN + assert.equal(process.exitCode, 0, 'refresh should not have thrown an error'); + // retrieve result + + assert.deepEqual( + replace['testInstance/testBU'].journey, + ['testExisting_temail', 'testExisting_journey_Multistep'], + 'should have found the right journeys that need updating' + ); + assert.equal( + testUtils.getAPIHistoryLength(), + 42, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + return; + }); + }); + + describe('Audit ================', () => { + it('Should show audit log of a transactional journey and version', async () => { + const audit = await handler.audit('testInstance/testBU', { + journey: ['testExisting_temail/2'], + }); + // THEN + assert.equal(process.exitCode, 0, 'audit should not have thrown an error'); + + assert.deepEqual( + audit['testInstance/testBU'].journey, + ['testExisting_temail'], + 'should have returned the right journeys' + ); + assert.equal( + testUtils.getAPIHistoryLength(), + 2, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + + return; + }); + + it('Should show audit log of a transactional journey with all its versions', async () => { + const audit = await handler.audit('testInstance/testBU', { + journey: ['testExisting_temail'], + }); + // THEN + assert.equal(process.exitCode, 0, 'audit should not have thrown an error'); + + assert.deepEqual( + audit['testInstance/testBU'].journey, + ['testExisting_temail'], + 'should have returned the right journeys' + ); + assert.equal( + testUtils.getAPIHistoryLength(), + 3, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + + return; + }); + + it('Should not show audit log of a transactional journey with a too high version', async () => { + const audit = await handler.audit('testInstance/testBU', { + journey: ['testExisting_temail/99'], + }); + // THEN + assert.equal(process.exitCode, 404, 'audit should have thrown an error'); + + assert.deepEqual( + audit['testInstance/testBU'].journey, + [], + 'should have returned the right journeys' + ); + assert.equal( + testUtils.getAPIHistoryLength(), + 2, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + + return; + }); + + it('Should show audit log of a multi-step journey and version', async () => { + const audit = await handler.audit('testInstance/testBU', { + journey: ['testExisting_journey_Multistep/1'], + }); + // THEN + assert.equal(process.exitCode, 0, 'audit should not have thrown an error'); + + assert.deepEqual( + audit['testInstance/testBU'].journey, + ['testExisting_journey_Multistep'], + 'should have returned the right journeys' + ); + assert.equal( + testUtils.getAPIHistoryLength(), + 2, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + + return; + }); + + it('Should show audit log of a multi-step journey with all its versions', async () => { + const audit = await handler.audit('testInstance/testBU', { + journey: ['testExisting_journey_Multistep'], + }); + // THEN + assert.equal(process.exitCode, 0, 'audit should not have thrown an error'); + + assert.deepEqual( + audit['testInstance/testBU'].journey, + ['testExisting_journey_Multistep'], + 'should have returned the right journeys' + ); + assert.equal( + testUtils.getAPIHistoryLength(), + 4, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + + return; + }); + + it('Should show audit log of a multi-step journey with all its versions via /*', async () => { + const audit = await handler.audit('testInstance/testBU', { + journey: ['testExisting_journey_Multistep'], + }); + // THEN + assert.equal(process.exitCode, 0, 'audit should not have thrown an error'); + + assert.deepEqual( + audit['testInstance/testBU'].journey, + ['testExisting_journey_Multistep'], + 'should have returned the right journeys' + ); + assert.equal( + testUtils.getAPIHistoryLength(), + 4, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + + return; + }); + }); +}); diff --git a/test/type.mobileKeyword.test.js b/test/type.mobileKeyword.test.js new file mode 100644 index 000000000..5c66f978b --- /dev/null +++ b/test/type.mobileKeyword.test.js @@ -0,0 +1,279 @@ +import * as chai from 'chai'; +const assert = chai.assert; +const expect = chai.expect; + +import chaiFiles from 'chai-files'; +import cache from '../lib/util/cache.js'; +import * as testUtils from './utils.js'; +import handler from '../lib/index.js'; +chai.use(chaiFiles); + +describe('type: mobileKeyword', () => { + beforeEach(() => { + testUtils.mockSetup(); + }); + + afterEach(() => { + testUtils.mockReset(); + }); + + describe('Retrieve ================', () => { + it('Should retrieve a mobileKeyword', async () => { + // WHEN + await handler.retrieve('testInstance/testBU', ['mobileKeyword']); + // THEN + assert.equal(process.exitCode, 0, 'retrieve should not have thrown an error'); + // get results from cache + const result = cache.getCache(); + assert.equal( + result.mobileKeyword ? Object.keys(result.mobileKeyword).length : 0, + 1, + 'only 1 mobileKeywords expected' + ); + assert.deepEqual( + await testUtils.getActualJson( + '4912312345678.TESTEXISTING_KEYWORD', + 'mobileKeyword' + ), + await testUtils.getExpectedJson('9999999', 'mobileKeyword', 'get'), + 'saved JSON was not equal expected' + ); + expect( + await testUtils.getActualFile( + '4912312345678.TESTEXISTING_KEYWORD', + 'mobileKeyword', + 'amp' + ) + ).to.equal(await testUtils.getExpectedFile('9999999', 'mobileKeyword', 'get', 'amp')); + assert.equal( + testUtils.getAPIHistoryLength(), + 2, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + return; + }); + }); + + describe('Deploy ================', () => { + beforeEach(() => { + testUtils.mockSetup(true); + }); + + it('Should create (but not update) a mobileKeyword', async () => { + // WHEN + await handler.deploy( + 'testInstance/testBU', + ['mobileKeyword'], + ['4912312345678.TESTNEW_KEYWORD'] + ); + // THEN + assert.equal(process.exitCode, 0, 'deploy should not have thrown an error'); + // get results from cache + const result = cache.getCache(); + assert.equal( + result.mobileKeyword ? Object.keys(result.mobileKeyword).length : 0, + 2, + '2 mobileKeywords expected' + ); + // confirm created item + assert.deepEqual( + await testUtils.getActualJson('4912312345678.TESTNEW_KEYWORD', 'mobileKeyword'), + await testUtils.getExpectedJson('9999999', 'mobileKeyword', 'post-create'), + 'returned JSON was not equal expected for insert mobileKeyword' + ); + expect( + await testUtils.getActualFile( + '4912312345678.TESTNEW_KEYWORD', + 'mobileKeyword', + 'amp' + ) + ).to.equal( + await testUtils.getExpectedFile('9999999', 'mobileKeyword', 'post-create', 'amp') + ); + + // confirm updated item + // eslint-disable-next-line no-console + console.log( + 'Not testing UPDATE because the API only responds with an empty body unless there are errors in the request body' + ); + + // check number of API calls + assert.equal( + testUtils.getAPIHistoryLength(), + 4, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + return; + }); + + it('Should not create a mobileKeyword with wrong type', async () => { + // WHEN + await handler.deploy( + 'testInstance/testBU', + ['mobileKeyword'], + ['4912312345678.TESTNEW_KEYWORD_BLOCKED'] + ); + // THEN + assert.equal(process.exitCode, 1, 'deploy should have thrown an error'); + + // check number of API calls + assert.equal( + testUtils.getAPIHistoryLength(), + 2, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + return; + }); + }); + + describe('Templating ================', () => { + it('Should create a mobileKeyword template via retrieveAsTemplate and build it', async () => { + // GIVEN there is a template + const result = await handler.retrieveAsTemplate( + 'testInstance/testBU', + 'mobileKeyword', + ['4912312345678.TESTEXISTING_KEYWORD'], + 'testSourceMarket' + ); + // WHEN + assert.equal(process.exitCode, 0, 'retrieveAsTemplate should not have thrown an error'); + assert.equal( + result.mobileKeyword ? Object.keys(result.mobileKeyword).length : 0, + 1, + 'only one item expected' + ); + assert.deepEqual( + await testUtils.getActualTemplateJson( + '4912312345678.TESTEXISTING_KEYWORD', + 'mobileKeyword' + ), + await testUtils.getExpectedJson('9999999', 'mobileKeyword', 'template'), + 'returned template JSON was not equal expected' + ); + expect( + await testUtils.getActualTemplateFile( + '4912312345678.TESTEXISTING_KEYWORD', + 'mobileKeyword', + 'amp' + ) + ).to.equal( + await testUtils.getExpectedFile('9999999', 'mobileKeyword', 'template', 'amp') + ); + assert.equal( + testUtils.getAPIHistoryLength(), + 2, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + return; + }); + + it('Should create a mobileKeyword template via buildTemplate and build it', async () => { + // download first before we test buildTemplate + await handler.retrieve('testInstance/testBU', ['mobileKeyword']); + // buildTemplate + const result = await handler.buildTemplate( + 'testInstance/testBU', + 'mobileKeyword', + ['4912312345678.TESTEXISTING_KEYWORD'], + ['testSourceMarket'] + ); + assert.equal(process.exitCode, 0, 'buildTemplate should not have thrown an error'); + + assert.equal( + result.mobileKeyword ? Object.keys(result.mobileKeyword).length : 0, + 1, + 'only one mobileKeyword expected' + ); + assert.deepEqual( + await testUtils.getActualTemplateJson( + '4912312345678.TESTEXISTING_KEYWORD', + 'mobileKeyword' + ), + await testUtils.getExpectedJson('9999999', 'mobileKeyword', 'template'), + 'returned template JSON was not equal expected' + ); + expect( + await testUtils.getActualTemplateFile( + '4912312345678.TESTEXISTING_KEYWORD', + 'mobileKeyword', + 'amp' + ) + ).to.equal( + await testUtils.getExpectedFile('9999999', 'mobileKeyword', 'template', 'amp') + ); + + // buildDefinition + await handler.buildDefinition( + 'testInstance/testBU', + 'mobileKeyword', + ['4912312345678.TESTEXISTING_KEYWORD'], + ['testTargetMarket'] + ); + assert.equal(process.exitCode, 0, 'buildDefinition should not have thrown an error'); + assert.deepEqual( + await testUtils.getActualDeployJson( + '4912312345678.TESTTEMPLATED_KEYWORD', + 'mobileKeyword' + ), + await testUtils.getExpectedJson('9999999', 'mobileKeyword', 'build'), + 'returned deployment JSON was not equal expected' + ); + expect( + await testUtils.getActualDeployFile( + '4912312345678.TESTTEMPLATED_KEYWORD', + 'mobileKeyword', + 'amp' + ) + ).to.equal(await testUtils.getExpectedFile('9999999', 'mobileKeyword', 'build', 'amp')); + + assert.equal( + testUtils.getAPIHistoryLength(), + 2, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + return; + }); + }); + + describe('Delete ================', () => { + it('Should delete the item', async () => { + // WHEN + const isDeleted = await handler.deleteByKey( + 'testInstance/testBU', + 'mobileKeyword', + '4912312345678.TESTEXISTING_KEYWORD' + ); + // THEN + assert.equal(process.exitCode, 0, 'delete should not have thrown an error'); + + assert.equal(isDeleted, true, 'should have deleted the item'); + return; + }); + }); + + describe('CI/CD ================', () => { + it('Should return a list of files based on their type and key', async () => { + // WHEN + const fileList = await handler.getFilesToCommit( + 'testInstance/testBU', + 'mobileKeyword', + ['4912312345678.TESTEXISTING_KEYWORD'] + ); + // THEN + assert.equal(process.exitCode, 0, 'getFilesToCommit should not have thrown an error'); + assert.equal(fileList.length, 2, 'expected only 2 file paths'); + + assert.equal( + fileList[0].split('\\').join('/'), + 'retrieve/testInstance/testBU/mobileKeyword/4912312345678.TESTEXISTING_KEYWORD.mobileKeyword-meta.json', + 'wrong JSON path' + ); + assert.equal( + fileList[1].split('\\').join('/'), + 'retrieve/testInstance/testBU/mobileKeyword/4912312345678.TESTEXISTING_KEYWORD.mobileKeyword-meta.amp', + 'wrong AMP path' + ); + return; + }); + }); +}); diff --git a/test/type.mobileMessage.test.js b/test/type.mobileMessage.test.js new file mode 100644 index 000000000..d8a2ff86b --- /dev/null +++ b/test/type.mobileMessage.test.js @@ -0,0 +1,206 @@ +import * as chai from 'chai'; +const assert = chai.assert; +const expect = chai.expect; + +import chaiFiles from 'chai-files'; +import cache from '../lib/util/cache.js'; +import * as testUtils from './utils.js'; +import handler from '../lib/index.js'; +chai.use(chaiFiles); + +describe('type: mobileMessage', () => { + beforeEach(() => { + testUtils.mockSetup(); + }); + + afterEach(() => { + testUtils.mockReset(); + }); + + describe('Retrieve ================', () => { + it('Should retrieve a mobileMessage', async () => { + // WHEN + await handler.retrieve('testInstance/testBU', ['mobileMessage']); + // THEN + assert.equal(process.exitCode, 0, 'retrieve should not have thrown an error'); + // get results from cache + const result = cache.getCache(); + assert.equal( + result.mobileMessage ? Object.keys(result.mobileMessage).length : 0, + 1, + 'only 1 mobileMessages expected' + ); + assert.deepEqual( + await testUtils.getActualJson('NTIzOjc4OjA', 'mobileMessage'), + await testUtils.getExpectedJson('9999999', 'mobileMessage', 'get'), + 'saved JSON was not equal expected' + ); + expect(await testUtils.getActualFile('NTIzOjc4OjA', 'mobileMessage', 'amp')).to.equal( + await testUtils.getExpectedFile('9999999', 'mobileMessage', 'get', 'amp') + ); + assert.equal( + testUtils.getAPIHistoryLength(), + 4, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + return; + }); + }); + + describe('Deploy ================', () => { + beforeEach(() => { + testUtils.mockSetup(true); + }); + + it('Should create & update items', async () => { + // WHEN + await handler.deploy('testInstance/testBU', ['mobileMessage']); + // THEN + assert.equal(process.exitCode, 0, 'deploy should not have thrown an error'); + // get results from cache + const result = cache.getCache(); + assert.equal( + result.mobileMessage ? Object.keys(result.mobileMessage).length : 0, + 2, + '2 mobileMessages expected' + ); + // confirm created item + assert.deepEqual( + await testUtils.getActualJson('NTQ3Ojc4OjA', 'mobileMessage'), + await testUtils.getExpectedJson('9999999', 'mobileMessage', 'post-create'), + 'returned JSON was not equal expected for insert mobileMessage' + ); + expect(await testUtils.getActualFile('NTQ3Ojc4OjA', 'mobileMessage', 'amp')).to.equal( + await testUtils.getExpectedFile('9999999', 'mobileMessage', 'post-create', 'amp') + ); + + // confirm updated item + assert.deepEqual( + await testUtils.getActualJson('NTIzOjc4OjA', 'mobileMessage'), + await testUtils.getExpectedJson('9999999', 'mobileMessage', 'post-update'), // watch out - mobileMessage api wants put instead of patch for updates + 'returned JSON was not equal expected for update mobileMessage' + ); + expect(await testUtils.getActualFile('NTIzOjc4OjA', 'mobileMessage', 'amp')).to.equal( + await testUtils.getExpectedFile('9999999', 'mobileMessage', 'post-update', 'amp') + ); + + // check number of API calls + assert.equal( + testUtils.getAPIHistoryLength(), + 8, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + return; + }); + + it('Should NOT change the key during update with --changeKeyValue and instead fail due to missing support', async () => { + // WHEN + handler.setOptions({ changeKeyValue: 'updatedKey' }); + await handler.deploy('testInstance/testBU', ['mobileMessage'], ['NTIzOjc4OjA']); + // THEN + assert.equal( + process.exitCode, + 1, + 'deploy should have thrown an error due to lack of support' + ); + return; + }); + }); + + describe('Templating ================', () => { + it('Should create a mobileMessage template via buildTemplate and build it', async () => { + // download first before we test buildTemplate + await handler.retrieve('testInstance/testBU', ['mobileMessage']); + // buildTemplate + const result = await handler.buildTemplate( + 'testInstance/testBU', + 'mobileMessage', + ['NTIzOjc4OjA'], + ['testSourceMarket'] + ); + assert.equal(process.exitCode, 0, 'buildTemplate should not have thrown an error'); + + assert.equal( + result.mobileMessage ? Object.keys(result.mobileMessage).length : 0, + 1, + 'only one mobileMessage expected' + ); + assert.deepEqual( + await testUtils.getActualTemplateJson('NTIzOjc4OjA', 'mobileMessage'), + await testUtils.getExpectedJson('9999999', 'mobileMessage', 'template'), + 'returned template JSON was not equal expected' + ); + expect( + await testUtils.getActualTemplateFile('NTIzOjc4OjA', 'mobileMessage', 'amp') + ).to.equal( + await testUtils.getExpectedFile('9999999', 'mobileMessage', 'template', 'amp') + ); + + // buildDefinition + await handler.buildDefinition( + 'testInstance/testBU', + 'mobileMessage', + ['NTIzOjc4OjA'], + ['testTargetMarket'] + ); + assert.equal(process.exitCode, 0, 'buildDefinition should not have thrown an error'); + assert.deepEqual( + await testUtils.getActualDeployJson('NTIzOjc4OjA', 'mobileMessage'), + await testUtils.getExpectedJson('9999999', 'mobileMessage', 'build'), + 'returned deployment JSON was not equal expected' + ); + expect( + await testUtils.getActualDeployFile('NTIzOjc4OjA', 'mobileMessage', 'amp') + ).to.equal(await testUtils.getExpectedFile('9999999', 'mobileMessage', 'build', 'amp')); + + assert.equal( + testUtils.getAPIHistoryLength(), + 4, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + return; + }); + }); + + describe('Delete ================', () => { + it('Should delete the item', async () => { + // WHEN + const isDeleted = await handler.deleteByKey( + 'testInstance/testBU', + 'mobileMessage', + 'NTIzOjc4OjA' + ); + // THEN + assert.equal(process.exitCode, 0, 'delete should not have thrown an error'); + + assert.equal(isDeleted, true, 'should have deleted the item'); + return; + }); + }); + + describe('CI/CD ================', () => { + it('Should return a list of files based on their type and key', async () => { + // WHEN + const fileList = await handler.getFilesToCommit( + 'testInstance/testBU', + 'mobileMessage', + ['NTIzOjc4OjA'] + ); + // THEN + assert.equal(process.exitCode, 0, 'getFilesToCommit should not have thrown an error'); + assert.equal(fileList.length, 2, 'expected only 2 file paths'); + + assert.equal( + fileList[0].split('\\').join('/'), + 'retrieve/testInstance/testBU/mobileMessage/NTIzOjc4OjA.mobileMessage-meta.json', + 'wrong JSON path' + ); + assert.equal( + fileList[1].split('\\').join('/'), + 'retrieve/testInstance/testBU/mobileMessage/NTIzOjc4OjA.mobileMessage-meta.amp', + 'wrong AMP path' + ); + return; + }); + }); +}); diff --git a/test/type.query.test.js b/test/type.query.test.js new file mode 100644 index 000000000..9848483aa --- /dev/null +++ b/test/type.query.test.js @@ -0,0 +1,934 @@ +import * as chai from 'chai'; +const assert = chai.assert; +const expect = chai.expect; + +import chaiFiles from 'chai-files'; +import cache from '../lib/util/cache.js'; +import * as testUtils from './utils.js'; +import handler from '../lib/index.js'; +chai.use(chaiFiles); + +describe('type: query', () => { + beforeEach(() => { + testUtils.mockSetup(); + }); + + afterEach(() => { + testUtils.mockReset(); + }); + + describe('Retrieve ================', () => { + it('Should retrieve all queries', async () => { + // WHEN + await handler.retrieve('testInstance/testBU', ['query']); + // THEN + assert.equal(process.exitCode, 0, 'retrieve should not have thrown an error'); + // get results from cache + const result = cache.getCache(); + assert.equal( + result.query ? Object.keys(result.query).length : 0, + 4, + 'only 4 queries expected' + ); + // normal test + assert.deepEqual( + await testUtils.getActualJson('testExisting_query', 'query'), + await testUtils.getExpectedJson('9999999', 'query', 'get'), + 'returned metadata with correct key was not equal expected' + ); + expect(await testUtils.getActualFile('testExisting_query', 'query', 'sql')).to.equal( + await testUtils.getExpectedFile('9999999', 'query', 'get', 'sql') + ); + // check if r__dataExtension_key was overwritten + assert.deepEqual( + await testUtils.getActualJson('testExisting_query2', 'query'), + await testUtils.getExpectedJson('9999999', 'query', 'get2'), + 'returned metadata with wrong key was not equal expected' + ); + + assert.equal( + testUtils.getAPIHistoryLength(), + 5, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + return; + }); + + it('Should retrieve one specific query by key', async () => { + // WHEN + await handler.retrieve('testInstance/testBU', ['query'], ['testExisting_query']); + // THEN + assert.equal(process.exitCode, 0, 'retrieve should not have thrown an error'); + // get results from cache + const result = cache.getCache(); + assert.equal( + result.query ? Object.keys(result.query).length : 0, + 1, + 'only one query expected' + ); + assert.deepEqual( + await testUtils.getActualJson('testExisting_query', 'query'), + await testUtils.getExpectedJson('9999999', 'query', 'get'), + 'returned metadata was not equal expected' + ); + expect(await testUtils.getActualFile('testExisting_query', 'query', 'sql')).to.equal( + await testUtils.getExpectedFile('9999999', 'query', 'get', 'sql') + ); + assert.equal( + testUtils.getAPIHistoryLength(), + 6, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + return; + }); + + it('Should retrieve one specific query via --like', async () => { + // WHEN + handler.setOptions({ like: { key: '%Existing_query' } }); + await handler.retrieve('testInstance/testBU', ['query']); + // THEN + assert.equal(process.exitCode, 0, 'retrieve should not have thrown an error'); + // get results from cache + const result = cache.getCache(); + assert.equal( + result.query ? Object.keys(result.query).length : 0, + 4, + '4 queries in cache expected' + ); + assert.deepEqual( + await testUtils.getActualJson('testExisting_query', 'query'), + await testUtils.getExpectedJson('9999999', 'query', 'get'), + 'returned metadata was not equal expected' + ); + expect(await testUtils.getActualFile('testExisting_query', 'query', 'sql')).to.equal( + await testUtils.getExpectedFile('9999999', 'query', 'get', 'sql') + ); + expect(await testUtils.getActualFile('testExisting_query2', 'query', 'sql')).to.not + .exist; + assert.equal( + testUtils.getAPIHistoryLength(), + 5, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + return; + }); + + it('Should not retrieve any query via --like and key due to a mismatching filter', async () => { + // WHEN + handler.setOptions({ like: { key: 'NotExisting_query' } }); + await handler.retrieve('testInstance/testBU', ['query']); + // THEN + assert.equal(process.exitCode, 0, 'retrieve should not have thrown an error'); + // get results from cache + const result = cache.getCache(); + assert.equal( + result.query ? Object.keys(result.query).length : 0, + 4, + '4 queries in cache expected' + ); + + expect(await testUtils.getActualFile('testExisting_query', 'query', 'sql')).to.not + .exist; + expect(await testUtils.getActualFile('testExisting_query2', 'query', 'sql')).to.not + .exist; + assert.equal( + testUtils.getAPIHistoryLength(), + 5, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + return; + }); + }); + + describe('Deploy ================', () => { + beforeEach(() => { + testUtils.mockSetup(true); + }); + + it('Should create & upsert a query', async () => { + // WHEN + const resultDeploy = await handler.deploy( + 'testInstance/testBU', + ['query'], + ['testNew_query', 'testExisting_query'] + ); + // THEN + assert.equal(process.exitCode, 0, 'deploy should not have thrown an error'); + assert.equal( + resultDeploy['testInstance/testBU']?.query + ? Object.keys(resultDeploy['testInstance/testBU']?.query).length + : 0, + 2, + 'two queries to be deployed' + ); + // get results from cache + const result = cache.getCache(); + assert.equal( + result.query ? Object.keys(result.query).length : 0, + 5, + '5 queries expected in cache' + ); + // confirm created item + assert.deepEqual( + await testUtils.getActualJson('testNew_query', 'query'), + await testUtils.getExpectedJson('9999999', 'query', 'post'), + 'returned metadata was not equal expected for insert query' + ); + expect(await testUtils.getActualFile('testNew_query', 'query', 'sql')).to.equal( + await testUtils.getExpectedFile('9999999', 'query', 'post', 'sql') + ); + // confirm updated item + assert.deepEqual( + await testUtils.getActualJson('testExisting_query', 'query'), + await testUtils.getExpectedJson('9999999', 'query', 'patch'), + 'returned metadata was not equal expected for insert query' + ); + expect(await testUtils.getActualFile('testExisting_query', 'query', 'sql')).to.equal( + await testUtils.getExpectedFile('9999999', 'query', 'patch', 'sql') + ); + // check number of API calls + assert.equal( + testUtils.getAPIHistoryLength(), + 7, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + return; + }); + + it('Should deploy and execute with --execute', async () => { + handler.setOptions({ execute: true }); + // WHEN + await handler.deploy( + 'testInstance/testBU', + ['query'], + ['testExisting_query', 'testNew_query'] + ); + // THEN + assert.equal( + process.exitCode, + 0, + 'deploy with --execute should not have thrown an error' + ); + // confirm updated item + assert.deepEqual( + await testUtils.getActualJson('testExisting_query', 'query'), + await testUtils.getExpectedJson('9999999', 'query', 'patch'), + 'returned metadata was not equal expected for insert query' + ); + expect(await testUtils.getActualFile('testExisting_query', 'query', 'sql')).to.equal( + await testUtils.getExpectedFile('9999999', 'query', 'patch', 'sql') + ); + // check number of API calls + assert.equal( + testUtils.getAPIHistoryLength(), + 11, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + return; + }); + }); + + describe('FixKeys ================', () => { + beforeEach(() => { + testUtils.mockSetup(true); + }); + + it('Should change the key during update with --changeKeyValue', async () => { + // WHEN + await handler.retrieve( + 'testInstance/testBU', + ['query'], + ['testExisting_query_fixKeys'] + ); + handler.setOptions({ + changeKeyValue: 'testExisting_query_fixedKeys', + fromRetrieve: true, + }); + const deployed = await handler.deploy( + 'testInstance/testBU', + ['query'], + ['testExisting_query_fixKeys'] + ); + // THEN + assert.equal( + process.exitCode, + 0, + 'deploy --changeKeyValue should not have thrown an error' + ); + const upsertCallout = testUtils.getRestCallout('patch', '/automation/v1/queries/%'); + assert.equal( + upsertCallout?.key, + 'testExisting_query_fixedKeys', + 'key in create callout was not as expected' + ); + + assert.equal( + Object.keys(deployed['testInstance/testBU'].query).length, + 1, + 'returned number of keys does not correspond to number of expected fixed keys' + ); + assert.equal( + Object.keys(deployed['testInstance/testBU'].query)[0], + 'testExisting_query_fixedKeys', + 'returned keys do not correspond to expected fixed keys' + ); + + // confirm updated item + assert.deepEqual( + await testUtils.getActualJson('testExisting_query_fixedKeys', 'query'), + await testUtils.getExpectedJson('9999999', 'query', 'patch_fixKeys'), + 'returned metadata was not equal expected for update query' + ); + expect( + await testUtils.getActualFile('testExisting_query_fixedKeys', 'query', 'sql') + ).to.equal(await testUtils.getExpectedFile('9999999', 'query', 'patch_fixKeys', 'sql')); + // check number of API calls + assert.equal( + testUtils.getAPIHistoryLength(), + 12, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + return; + }); + + it('Should change the key during update with --changeKeyField', async () => { + // WHEN + await handler.retrieve( + 'testInstance/testBU', + ['query'], + ['testExisting_query_fixKeys'] + ); + handler.setOptions({ changeKeyField: 'name', fromRetrieve: true }); + const deployed = await handler.deploy( + 'testInstance/testBU', + ['query'], + ['testExisting_query_fixKeys'] + ); + // THEN + assert.equal( + process.exitCode, + 0, + 'deploy --changeKeyValue should not have thrown an error' + ); + const upsertCallout = testUtils.getRestCallout('patch', '/automation/v1/queries/%'); + assert.equal( + upsertCallout?.key, + 'testExisting_query_fixedKeys', + 'key in create callout was not as expected' + ); + + assert.equal( + Object.keys(deployed['testInstance/testBU'].query).length, + 1, + 'returned number of keys does not correspond to number of expected fixed keys' + ); + assert.equal( + Object.keys(deployed['testInstance/testBU'].query)[0], + 'testExisting_query_fixedKeys', + 'returned keys do not correspond to expected fixed keys' + ); + // confirm updated item + assert.deepEqual( + await testUtils.getActualJson('testExisting_query_fixedKeys', 'query'), + await testUtils.getExpectedJson('9999999', 'query', 'patch_fixKeys'), + 'returned metadata was not equal expected for update query' + ); + expect( + await testUtils.getActualFile('testExisting_query_fixedKeys', 'query', 'sql') + ).to.equal(await testUtils.getExpectedFile('9999999', 'query', 'patch_fixKeys', 'sql')); + // check number of API calls + assert.equal( + testUtils.getAPIHistoryLength(), + 12, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + return; + }); + + it('Should change the key during update with --changeKeyField and --keySuffix', async () => { + // WHEN + await handler.retrieve( + 'testInstance/testBU', + ['query'], + ['testExisting_query_fixKeysSuffix'] + ); + handler.setOptions({ changeKeyField: 'name', keySuffix: '_DEV', fromRetrieve: true }); + const deployed = await handler.deploy( + 'testInstance/testBU', + ['query'], + ['testExisting_query_fixKeysSuffix'] + ); + // THEN + assert.equal( + process.exitCode, + 0, + 'deploy --changeKeyValue --keySuffix should not have thrown an error' + ); + assert.equal( + Object.keys(deployed['testInstance/testBU'].query).length, + 1, + 'returned number of keys does not correspond to number of expected fixed keys' + ); + const upsertCallout = testUtils.getRestCallout('patch', '/automation/v1/queries/%'); + + assert.equal( + upsertCallout?.key, + 'testExisting_query_fixedKeysSuff_DEV', + 'key in create callout was not as expected' + ); + assert.equal( + Object.keys(deployed['testInstance/testBU'].query)[0], + 'testExisting_query_fixedKeysSuff_DEV', + 'returned keys do not correspond to expected fixed keys' + ); + // confirm updated item + assert.deepEqual( + await testUtils.getActualJson('testExisting_query_fixedKeysSuff_DEV', 'query'), + await testUtils.getExpectedJson('9999999', 'query', 'patch_fixKeysSuffix'), + 'returned metadata was not equal expected for update query' + ); + expect( + await testUtils.getActualFile( + 'testExisting_query_fixedKeysSuff_DEV', + 'query', + 'sql' + ) + ).to.equal( + await testUtils.getExpectedFile('9999999', 'query', 'patch_fixKeysSuffix', 'sql') + ); + // check number of API calls + assert.equal( + testUtils.getAPIHistoryLength(), + 12, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + return; + }); + + it('Should change the key during create with and --keySuffix', async () => { + handler.setOptions({ keySuffix: '_DEV' }); + const deployed = await handler.deploy( + 'testInstance/_ParentBU_', + ['query'], + ['testNew_query'] + ); + // THEN + assert.equal(process.exitCode, 0, 'deploy --keySuffix should not have thrown an error'); + assert.equal( + Object.keys(deployed['testInstance/_ParentBU_'].query).length, + 1, + 'returned number of keys does not correspond to number of expected fixed keys' + ); + assert.equal( + Object.keys(deployed['testInstance/_ParentBU_'].query)[0], + 'testNew_query_DEV', + 'returned keys do not correspond to expected fixed keys' + ); + + const createCallout = testUtils.getRestCallout('post', '/automation/v1/queries/'); + assert.equal( + createCallout?.key, + 'testNew_query_DEV', + 'key in create callout was not as expected' + ); + + // confirm updated item + assert.deepEqual( + await testUtils.getActualJson('testNew_query_DEV', 'query', '_ParentBU_'), + await testUtils.getExpectedJson('1111111', 'query', 'patch_keySuffix'), + 'returned metadata was not equal expected for update query' + ); + + // check number of API calls + assert.equal( + testUtils.getAPIHistoryLength(), + 4, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + return; + }); + + it('Should run fixKeys but not find fixable keys and hence stop', async () => { + // WHEN + handler.setOptions({ skipInteraction: { fixKeysReretrieve: false } }); + const resultFixKeys = await handler.fixKeys( + 'testInstance/testBU', + ['query'], + ['testExisting_query'] + ); + // THEN + assert.equal(process.exitCode, 0, 'fixKeys should not have thrown an error'); + // check which keys were fixed + assert.equal( + resultFixKeys['testInstance/testBU']['query'].length, + 0, + 'expected to find no keys to be fixed' + ); + + // get results from cache + const result = cache.getCache(); + assert.equal( + result.query ? Object.keys(result.query).length : 0, + 1, + 'one query expected' + ); + // check number of API calls + assert.equal( + testUtils.getAPIHistoryLength(), + 6, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + return; + }); + + it('Should fixKeys by key WITHOUT re-retrieving dependent types', async () => { + // WHEN + handler.setOptions({ skipInteraction: { fixKeysReretrieve: false } }); + const resultFixKeys = await handler.fixKeys( + 'testInstance/testBU', + ['query'], + ['testExisting_query_fixKeys', 'testExisting_query'] + ); + assert.equal( + resultFixKeys['testInstance/testBU']['query'].length, + 1, + 'returned number of keys does not correspond to number of expected fixed keys' + ); + assert.equal( + resultFixKeys['testInstance/testBU']['query'][0], + 'testExisting_query_fixedKeys', + 'returned keys do not correspond to expected fixed keys' + ); + // THEN + assert.equal(process.exitCode, 0, 'fixKeys should not have thrown an error'); + // confirm updated item + assert.deepEqual( + await testUtils.getActualJson('testExisting_query_fixedKeys', 'query'), + await testUtils.getExpectedJson('9999999', 'query', 'patch_fixKeys'), + 'returned metadata was not equal expected for update query' + ); + expect( + await testUtils.getActualFile('testExisting_query_fixedKeys', 'query', 'sql') + ).to.equal(await testUtils.getExpectedFile('9999999', 'query', 'patch_fixKeys', 'sql')); + // check number of API calls + assert.equal( + testUtils.getAPIHistoryLength(), + 14, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + return; + }); + + it('Should fixKeys by key with --keySuffix WITHOUT re-retrieving dependent types', async () => { + // WHEN + handler.setOptions({ + keySuffix: '_DEV', + skipInteraction: { fixKeysReretrieve: false }, + }); + const resultFixKeys = await handler.fixKeys( + 'testInstance/testBU', + ['query'], + ['testExisting_query_fixKeysSuffix', 'testExisting_query'] + ); + // THEN + assert.equal(process.exitCode, 0, 'fixKeys should not have thrown an error'); + + const upsertCallout = testUtils.getRestCallout('patch', '/automation/v1/queries/%'); + assert.equal( + upsertCallout?.key, + 'testExisting_query_fixedKeysSuff_DEV', + 'key in create callout was not as expected' + ); + + assert.equal( + resultFixKeys['testInstance/testBU']['query'].length, + 1, + 'returned number of keys does not correspond to number of expected fixed keys' + ); + assert.equal( + resultFixKeys['testInstance/testBU']['query'][0], + 'testExisting_query_fixedKeysSuff_DEV', + 'returned keys do not correspond to expected fixed keys' + ); + // confirm updated item + assert.deepEqual( + await testUtils.getActualJson('testExisting_query_fixedKeysSuff_DEV', 'query'), + await testUtils.getExpectedJson('9999999', 'query', 'patch_fixKeysSuffix'), + 'returned metadata was not equal expected for update query' + ); + expect( + await testUtils.getActualFile( + 'testExisting_query_fixedKeysSuff_DEV', + 'query', + 'sql' + ) + ).to.equal( + await testUtils.getExpectedFile('9999999', 'query', 'patch_fixKeysSuffix', 'sql') + ); + // check number of API calls + assert.equal( + testUtils.getAPIHistoryLength(), + 14, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + return; + }); + + it('Should fixKeys by key WITHOUT re-retrieving dependent types and then --execute', async () => { + // WHEN + handler.setOptions({ skipInteraction: { fixKeysReretrieve: false }, execute: true }); + const resultFixKeys = await handler.fixKeys( + 'testInstance/testBU', + ['query'], + ['testExisting_query_fixKeys', 'testExisting_query'] + ); + assert.equal( + resultFixKeys['testInstance/testBU']['query'].length, + 1, + 'returned number of keys does not correspond to number of expected fixed keys' + ); + assert.equal( + resultFixKeys['testInstance/testBU']['query'][0], + 'testExisting_query_fixedKeys', + 'returned keys do not correspond to expected fixed keys' + ); + // THEN + assert.equal( + process.exitCode, + 0, + 'fixKeys with --execute should not have thrown an error' + ); + // confirm updated item + assert.deepEqual( + await testUtils.getActualJson('testExisting_query_fixedKeys', 'query'), + await testUtils.getExpectedJson('9999999', 'query', 'patch_fixKeys'), + 'returned metadata was not equal expected for update query' + ); + expect( + await testUtils.getActualFile('testExisting_query_fixedKeys', 'query', 'sql') + ).to.equal(await testUtils.getExpectedFile('9999999', 'query', 'patch_fixKeys', 'sql')); + // check number of API calls + assert.equal( + testUtils.getAPIHistoryLength(), + 16, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + return; + }); + + it('Should fixKeys by key AND re-retrieve dependent types', async () => { + // WHEN + handler.setOptions({ skipInteraction: { fixKeysReretrieve: true } }); + const resultFixKeys = await handler.fixKeys( + 'testInstance/testBU', + ['query'], + ['testExisting_query_fixKeys', 'testExisting_query'] + ); + assert.equal( + resultFixKeys['testInstance/testBU']['query'].length, + 1, + 'returned number of keys does not correspond to number of expected fixed keys' + ); + assert.equal( + resultFixKeys['testInstance/testBU']['query'][0], + 'testExisting_query_fixedKeys', + 'returned keys do not correspond to expected fixed keys' + ); + // THEN + assert.equal(process.exitCode, 0, 'fixKeys should not have thrown an error'); + // confirm updated item + assert.deepEqual( + await testUtils.getActualJson('testExisting_query_fixedKeys', 'query'), + await testUtils.getExpectedJson('9999999', 'query', 'patch_fixKeys'), + 'returned metadata was not equal expected for update query' + ); + expect( + await testUtils.getActualFile('testExisting_query_fixedKeys', 'query', 'sql') + ).to.equal(await testUtils.getExpectedFile('9999999', 'query', 'patch_fixKeys', 'sql')); + // check number of API calls + assert.equal( + testUtils.getAPIHistoryLength(), + 48, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + return; + }); + + it('Should fixKeys by key AND re-retrieve dependent types and then --execute', async () => { + // WHEN + handler.setOptions({ skipInteraction: { fixKeysReretrieve: true }, execute: true }); + const resultFixKeys = await handler.fixKeys( + 'testInstance/testBU', + ['query'], + ['testExisting_query_fixKeys', 'testExisting_query'] + ); + assert.equal( + resultFixKeys['testInstance/testBU']['query'].length, + 1, + 'returned number of keys does not correspond to number of expected fixed keys' + ); + assert.equal( + resultFixKeys['testInstance/testBU']['query'][0], + 'testExisting_query_fixedKeys', + 'returned keys do not correspond to expected fixed keys' + ); + // THEN + assert.equal( + process.exitCode, + 0, + 'fixKeys with --execute should not have thrown an error' + ); + // confirm updated item + assert.deepEqual( + await testUtils.getActualJson('testExisting_query_fixedKeys', 'query'), + await testUtils.getExpectedJson('9999999', 'query', 'patch_fixKeys'), + 'returned metadata was not equal expected for update query' + ); + expect( + await testUtils.getActualFile('testExisting_query_fixedKeys', 'query', 'sql') + ).to.equal(await testUtils.getExpectedFile('9999999', 'query', 'patch_fixKeys', 'sql')); + // check number of API calls + assert.equal( + testUtils.getAPIHistoryLength(), + 50, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + return; + }); + + it('Should fixKeys via --like WITHOUT re-retrieving dependent types', async () => { + // WHEN + handler.setOptions({ + like: { key: 'testExisting_query_f%' }, + skipInteraction: { fixKeysReretrieve: false }, + }); + const resultFixKeys = await handler.fixKeys('testInstance/testBU', ['query']); + assert.equal( + resultFixKeys['testInstance/testBU']['query'].length, + 2, + 'returned number of keys does not correspond to number of expected fixed keys' + ); + assert.equal( + resultFixKeys['testInstance/testBU']['query'][0], + 'testExisting_query_fixedKeys', + 'returned keys do not correspond to expected fixed keys' + ); + // THEN + assert.equal(process.exitCode, 0, 'fixKeys should not have thrown an error'); + // confirm updated item + assert.deepEqual( + await testUtils.getActualJson('testExisting_query_fixedKeys', 'query'), + await testUtils.getExpectedJson('9999999', 'query', 'patch_fixKeys'), + 'returned metadata was not equal expected for update query' + ); + expect( + await testUtils.getActualFile('testExisting_query_fixedKeys', 'query', 'sql') + ).to.equal(await testUtils.getExpectedFile('9999999', 'query', 'patch_fixKeys', 'sql')); + // check number of API calls + assert.equal( + testUtils.getAPIHistoryLength(), + 12, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + return; + }); + }); + + describe('Templating ================', () => { + it('Should create a query template via retrieveAsTemplate and build it', async () => { + // GIVEN there is a template + const result = await handler.retrieveAsTemplate( + 'testInstance/testBU', + 'query', + ['testExisting_query'], + 'testSourceMarket' + ); + // WHEN + assert.equal(process.exitCode, 0, 'retrieveAsTemplate should not have thrown an error'); + assert.equal( + result.query ? Object.keys(result.query).length : 0, + 1, + 'only one query expected' + ); + assert.deepEqual( + await testUtils.getActualTemplateJson('testExisting_query', 'query'), + await testUtils.getExpectedJson('9999999', 'query', 'template'), + 'returned template JSON of retrieveAsTemplate was not equal expected' + ); + expect( + await testUtils.getActualTemplateFile('testExisting_query', 'query', 'sql') + ).to.equal(await testUtils.getExpectedFile('9999999', 'query', 'template', 'sql')); + // THEN + await handler.buildDefinition( + 'testInstance/testBU', + 'query', + ['testExisting_query'], + ['testTargetMarket'] + ); + assert.equal(process.exitCode, 0, 'buildDefinition should not have thrown an error'); + + assert.deepEqual( + await testUtils.getActualDeployJson('testTemplated_query', 'query'), + await testUtils.getExpectedJson('9999999', 'query', 'build'), + 'returned deployment JSON was not equal expected' + ); + expect( + await testUtils.getActualDeployFile('testTemplated_query', 'query', 'sql') + ).to.equal(await testUtils.getExpectedFile('9999999', 'query', 'build', 'sql')); + + assert.equal( + testUtils.getAPIHistoryLength(), + 5, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + return; + }); + + it('Should create a query template via buildTemplate and build it', async () => { + // download first before we test buildTemplate + await handler.retrieve('testInstance/testBU', ['query']); + // GIVEN there is a template + const result = await handler.buildTemplate( + 'testInstance/testBU', + 'query', + ['testExisting_query'], + ['testSourceMarket'] + ); + // WHEN + assert.equal(process.exitCode, 0, 'buildTemplate should not have thrown an error'); + + assert.equal( + result.query ? Object.keys(result.query).length : 0, + 1, + 'only one query expected' + ); + assert.deepEqual( + await testUtils.getActualTemplateJson('testExisting_query', 'query'), + await testUtils.getExpectedJson('9999999', 'query', 'template'), + 'returned template JSON of buildTemplate was not equal expected' + ); + expect( + await testUtils.getActualTemplateFile('testExisting_query', 'query', 'sql') + ).to.equal(await testUtils.getExpectedFile('9999999', 'query', 'template', 'sql')); + // THEN + await handler.buildDefinition( + 'testInstance/testBU', + 'query', + ['testExisting_query'], + ['testTargetMarket'] + ); + assert.equal(process.exitCode, 0, 'buildDefinition should not have thrown an error'); + + assert.deepEqual( + await testUtils.getActualDeployJson('testTemplated_query', 'query'), + await testUtils.getExpectedJson('9999999', 'query', 'build'), + 'returned deployment JSON was not equal expected' + ); + expect( + await testUtils.getActualDeployFile('testTemplated_query', 'query', 'sql') + ).to.equal(await testUtils.getExpectedFile('9999999', 'query', 'build', 'sql')); + + assert.equal( + testUtils.getAPIHistoryLength(), + 5, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + return; + }); + }); + + describe('Delete ================', () => { + it('Should delete the item', async () => { + // WHEN + const isDeleted = await handler.deleteByKey( + 'testInstance/testBU', + 'query', + 'testExisting_query' + ); + // THEN + assert.equal(process.exitCode, 0, 'delete should not have thrown an error'); + + assert.equal(isDeleted, true, 'should have deleted the item'); + return; + }); + }); + + describe('CI/CD ================', () => { + it('Should return a list of files based on their type and key', async () => { + // WHEN + const fileList = await handler.getFilesToCommit('testInstance/testBU', 'query', [ + 'testExisting_query', + ]); + // THEN + assert.equal(process.exitCode, 0, 'getFilesToCommit should not have thrown an error'); + assert.equal(fileList.length, 2, 'expected only 2 file paths'); + + assert.equal( + fileList[0].split('\\').join('/'), + 'retrieve/testInstance/testBU/query/testExisting_query.query-meta.json', + 'wrong JSON path' + ); + assert.equal( + fileList[1].split('\\').join('/'), + 'retrieve/testInstance/testBU/query/testExisting_query.query-meta.sql', + 'wrong JSON path' + ); + return; + }); + }); + + describe('Execute ================', () => { + it('Should start a query by key', async () => { + const executedKeys = await handler.execute( + 'testInstance/testBU', + ['query'], + ['testExisting_query'] + ); + assert.equal(process.exitCode, 0, 'execute should not have thrown an error'); + assert.equal( + executedKeys['testInstance/testBU']?.query?.length, + 1, + 'returned number of keys does not correspond to number of expected fixed keys' + ); + assert.equal( + executedKeys['testInstance/testBU']?.query[0], + 'testExisting_query', + 'returned keys do not correspond to expected fixed keys' + ); + return; + }); + + it('Should start a query selected via --like', async () => { + handler.setOptions({ like: { key: 'testExist%query' } }); + const executedKeys = await handler.execute('testInstance/testBU', ['query']); + assert.equal(process.exitCode, 0, 'execute should not have thrown an error'); + assert.equal( + executedKeys['testInstance/testBU']?.query?.length, + 1, + 'returned number of keys does not correspond to number of expected fixed keys' + ); + assert.equal( + executedKeys['testInstance/testBU']?.query[0], + 'testExisting_query', + 'returned keys do not correspond to expected fixed keys' + ); + return; + }); + + it('Should not start executing a query because key and --like was specified', async () => { + handler.setOptions({ like: { key: 'testExisting%' } }); + const executedKeys = await handler.execute( + 'testInstance/testBU', + ['query'], + ['testExisting_query'] + ); + assert.equal(process.exitCode, 1, 'execute should have thrown an error'); + assert.equal( + Object.keys(executedKeys).length, + 0, + 'query was not supposed to be executed' + ); + return; + }); + }); +}); diff --git a/test/type.script.test.js b/test/type.script.test.js new file mode 100644 index 000000000..4663e0f2c --- /dev/null +++ b/test/type.script.test.js @@ -0,0 +1,674 @@ +import * as chai from 'chai'; +const assert = chai.assert; +const expect = chai.expect; + +import chaiFiles from 'chai-files'; +import cache from '../lib/util/cache.js'; +import * as testUtils from './utils.js'; +import handler from '../lib/index.js'; +chai.use(chaiFiles); + +describe('type: script', () => { + beforeEach(() => { + testUtils.mockSetup(); + }); + + afterEach(() => { + testUtils.mockReset(); + }); + + describe('Retrieve ================', () => { + it('Should retrieve all scripts', async () => { + // WHEN + const retrieve = await handler.retrieve('testInstance/testBU', ['script']); + // THEN + assert.equal(process.exitCode, 0, 'retrieve should not have thrown an error'); + // retrieve result + assert.equal( + retrieve['testInstance/testBU'].script + ? Object.keys(retrieve['testInstance/testBU'].script).length + : 0, + 5, + 'only 5 scripts expected in retrieve response' + ); + + // get results from cache + const result = cache.getCache(); + assert.equal( + result.script ? Object.keys(result.script).length : 0, + 5, + 'only 5 scripts expected' + ); + // normal test + assert.deepEqual( + await testUtils.getActualJson('testExisting_script', 'script'), + await testUtils.getExpectedJson('9999999', 'script', 'get'), + 'returned metadata with correct key was not equal expected' + ); + expect(await testUtils.getActualFile('testExisting_script', 'script', 'html')).to.not + .exist; + expect(await testUtils.getActualFile('testExisting_script', 'script', 'ssjs')).to.equal( + await testUtils.getExpectedFile('9999999', 'script', 'get', 'ssjs') + ); + + // test with no script tag + assert.deepEqual( + await testUtils.getActualJson('testExisting_script_noScriptTag', 'script'), + await testUtils.getExpectedJson('9999999', 'script', 'get_noScriptTag'), + 'returned metadata was not equal expected' + ); + expect( + await testUtils.getActualFile('testExisting_script_noScriptTag', 'script', 'html') + ).to.equal( + await testUtils.getExpectedFile('9999999', 'script', 'get_noScriptTag', 'html') + ); + expect( + await testUtils.getActualFile('testExisting_script_noScriptTag', 'script', 'ssjs') + ).to.not.exist; + + // test with ampscript + assert.deepEqual( + await testUtils.getActualJson('testExisting_script_ampscript', 'script'), + await testUtils.getExpectedJson('9999999', 'script', 'get_ampscript'), + 'returned metadata was not equal expected' + ); + expect( + await testUtils.getActualFile('testExisting_script_ampscript', 'script', 'html') + ).to.equal( + await testUtils.getExpectedFile('9999999', 'script', 'get_ampscript', 'html') + ); + expect(await testUtils.getActualFile('testExisting_script_ampscript', 'script', 'ssjs')) + .to.not.exist; + + // test with mixed code (ampscript inside of ssjs) + assert.deepEqual( + await testUtils.getActualJson('testExisting_script_ampincluded', 'script'), + await testUtils.getExpectedJson('9999999', 'script', 'get_ampincluded'), + 'returned metadata was not equal expected' + ); + expect( + await testUtils.getActualFile('testExisting_script_ampincluded', 'script', 'ssjs') + ).to.not.exist; + expect( + await testUtils.getActualFile('testExisting_script_ampincluded', 'script', 'html') + ).to.equal( + await testUtils.getExpectedFile('9999999', 'script', 'get_ampincluded', 'html') + ); + + // test with mixed code (ssjs and ampscript side-by-side) + assert.deepEqual( + await testUtils.getActualJson('testExisting_script_mixed', 'script'), + await testUtils.getExpectedJson('9999999', 'script', 'get_mixed'), + 'returned metadata was not equal expected' + ); + expect( + await testUtils.getActualFile('testExisting_script_mixed', 'script', 'html') + ).to.equal(await testUtils.getExpectedFile('9999999', 'script', 'get_mixed', 'html')); + expect(await testUtils.getActualFile('testExisting_script_mixed', 'script', 'ssjs')).to + .not.exist; + + assert.equal( + testUtils.getAPIHistoryLength(), + 2, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + return; + }); + + it('Should retrieve one specific script by key', async () => { + // WHEN + await handler.retrieve('testInstance/testBU', ['script'], ['testExisting_script']); + // THEN + assert.equal(process.exitCode, 0, 'retrieve should not have thrown an error'); + // get results from cache + const result = cache.getCache(); + assert.equal( + result.script ? Object.keys(result.script).length : 0, + 1, + 'only one script expected' + ); + assert.deepEqual( + await testUtils.getActualJson('testExisting_script', 'script'), + await testUtils.getExpectedJson('9999999', 'script', 'get'), + 'returned metadata was not equal expected' + ); + expect(await testUtils.getActualFile('testExisting_script', 'script', 'html')).to.not + .exist; + expect(await testUtils.getActualFile('testExisting_script', 'script', 'ssjs')).to.equal( + await testUtils.getExpectedFile('9999999', 'script', 'get', 'ssjs') + ); + + expect( + await testUtils.getActualFile('testExisting_script_noScriptTag', 'script', 'json') + ).to.not.exist; + expect( + await testUtils.getActualFile('testExisting_script_noScriptTag', 'script', 'ssjs') + ).to.not.exist; + expect( + await testUtils.getActualFile('testExisting_script_noScriptTag', 'script', 'html') + ).to.not.exist; + + assert.equal( + testUtils.getAPIHistoryLength(), + 2, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + return; + }); + + it('Should retrieve one specific script via --like', async () => { + // WHEN + handler.setOptions({ like: { key: '%Existing_script' } }); + await handler.retrieve('testInstance/testBU', ['script']); + + // THEN + assert.equal(process.exitCode, 0, 'retrieve should not have thrown an error'); + + // get results from cache + const result = cache.getCache(); + assert.equal( + result.script ? Object.keys(result.script).length : 0, + 5, + '5 scripts in cache expected' + ); + assert.deepEqual( + await testUtils.getActualJson('testExisting_script', 'script'), + await testUtils.getExpectedJson('9999999', 'script', 'get'), + 'returned metadata was not equal expected' + ); + expect(await testUtils.getActualFile('testExisting_script', 'script', 'ssjs')).to.equal( + await testUtils.getExpectedFile('9999999', 'script', 'get', 'ssjs') + ); + + expect( + await testUtils.getActualFile('testExisting_script_noScriptTag', 'script', 'json') + ).to.not.exist; + expect( + await testUtils.getActualFile('testExisting_script_noScriptTag', 'script', 'ssjs') + ).to.not.exist; + expect( + await testUtils.getActualFile('testExisting_script_noScriptTag', 'script', 'html') + ).to.not.exist; + + assert.equal( + testUtils.getAPIHistoryLength(), + 2, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + return; + }); + + it('Should not retrieve any script via --like and key due to a mismatching filter', async () => { + // WHEN + handler.setOptions({ like: { key: 'NotExisting_script' } }); + await handler.retrieve('testInstance/testBU', ['script']); + // THEN + assert.equal(process.exitCode, 0, 'retrieve should not have thrown an error'); + + // get results from cache + const result = cache.getCache(); + assert.equal( + result.script ? Object.keys(result.script).length : 0, + 5, + '5 scripts in cache expected' + ); + + expect(await testUtils.getActualFile('testExisting_script', 'script', 'ssjs')).to.not + .exist; + assert.equal( + testUtils.getAPIHistoryLength(), + 2, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + return; + }); + }); + + describe('Deploy ================', () => { + beforeEach(() => { + testUtils.mockSetup(true); + }); + + it('Should create & upsert a script', async () => { + // WHEN + await handler.deploy('testInstance/testBU', ['script']); + // THEN + assert.equal(process.exitCode, 0, 'deploy should not have thrown an error'); + // get results from cache + const result = cache.getCache(); + assert.equal( + result.script ? Object.keys(result.script).length : 0, + 6, + '6 scripts expected' + ); + // confirm created item + assert.deepEqual( + await testUtils.getActualJson('testNew_script', 'script'), + await testUtils.getExpectedJson('9999999', 'script', 'post'), + 'returned metadata was not equal expected for insert script' + ); + // confirm updated item + assert.deepEqual( + await testUtils.getActualJson('testExisting_script', 'script'), + await testUtils.getExpectedJson('9999999', 'script', 'patch'), + 'returned metadata was not equal expected for insert script' + ); + expect(await testUtils.getActualFile('testExisting_script', 'script', 'html')).to.not + .exist; + expect(await testUtils.getActualFile('testExisting_script', 'script', 'ssjs')).to.equal( + await testUtils.getExpectedFile('9999999', 'script', 'patch', 'ssjs') + ); + // check number of API calls + assert.equal( + testUtils.getAPIHistoryLength(), + 5, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + return; + }); + }); + + describe('Templating ================', () => { + it('Should create a script template via retrieveAsTemplate and build it', async () => { + // GIVEN there is a template + const result = await handler.retrieveAsTemplate( + 'testInstance/testBU', + 'script', + ['testExisting_script'], + 'testSourceMarket' + ); + // WHEN + assert.equal(process.exitCode, 0, 'retrieveAsTemplate should not have thrown an error'); + assert.equal( + result.script ? Object.keys(result.script).length : 0, + 1, + 'only one script expected' + ); + assert.deepEqual( + await testUtils.getActualTemplateJson('testExisting_script', 'script'), + await testUtils.getExpectedJson('9999999', 'script', 'template'), + 'returned template JSON of retrieveAsTemplate was not equal expected' + ); + expect( + await testUtils.getActualTemplateFile('testExisting_script', 'script', 'ssjs') + ).to.equal(await testUtils.getExpectedFile('9999999', 'script', 'template', 'ssjs')); + // THEN + await handler.buildDefinition( + 'testInstance/testBU', + 'script', + ['testExisting_script'], + ['testTargetMarket'] + ); + assert.equal(process.exitCode, 0, 'buildDefinition should not have thrown an error'); + + assert.deepEqual( + await testUtils.getActualDeployJson('testTemplated_script', 'script'), + await testUtils.getExpectedJson('9999999', 'script', 'build'), + 'returned deployment JSON was not equal expected' + ); + expect( + await testUtils.getActualDeployFile('testTemplated_script', 'script', 'ssjs') + ).to.equal(await testUtils.getExpectedFile('9999999', 'script', 'build', 'ssjs')); + + assert.equal( + testUtils.getAPIHistoryLength(), + 2, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + return; + }); + + it('Should create a script template via buildTemplate and build it', async () => { + // download first before we test buildTemplate + await handler.retrieve('testInstance/testBU', ['script']); + // GIVEN there is a template + const result = await handler.buildTemplate( + 'testInstance/testBU', + 'script', + ['testExisting_script'], + ['testSourceMarket'] + ); + // WHEN + assert.equal(process.exitCode, 0, 'buildTemplate should not have thrown an error'); + + assert.equal( + result.script ? Object.keys(result.script).length : 0, + 1, + 'only one script expected' + ); + assert.deepEqual( + await testUtils.getActualTemplateJson('testExisting_script', 'script'), + await testUtils.getExpectedJson('9999999', 'script', 'template'), + 'returned template JSON of buildTemplate was not equal expected' + ); + expect( + await testUtils.getActualTemplateFile('testExisting_script', 'script', 'ssjs') + ).to.equal(await testUtils.getExpectedFile('9999999', 'script', 'template', 'ssjs')); + // THEN + await handler.buildDefinition( + 'testInstance/testBU', + 'script', + ['testExisting_script'], + ['testTargetMarket'] + ); + assert.equal(process.exitCode, 0, 'buildDefinition should not have thrown an error'); + + assert.deepEqual( + await testUtils.getActualDeployJson('testTemplated_script', 'script'), + await testUtils.getExpectedJson('9999999', 'script', 'build'), + 'returned deployment JSON was not equal expected' + ); + expect( + await testUtils.getActualDeployFile('testTemplated_script', 'script', 'ssjs') + ).to.equal(await testUtils.getExpectedFile('9999999', 'script', 'build', 'ssjs')); + + assert.equal( + testUtils.getAPIHistoryLength(), + 2, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + return; + }); + + it('Should create a script template via buildTemplate with --dependencies', async () => { + // download first before we test buildTemplate + await handler.retrieve('testInstance/testBU', ['script', 'asset']); + assert.equal(process.exitCode, 0, 'retrieve should not have thrown an error'); + + handler.setOptions({ dependencies: true, skipInteraction: true }); + + // GIVEN there is a template + const templatedItems = await handler.buildTemplate( + 'testInstance/testBU', + 'script', + ['testExisting_script_ampscript'], + ['testSourceMarket'] + ); + // WHEN + assert.equal(process.exitCode, 0, 'buildTemplate should not have thrown an error'); + + assert.deepEqual( + Object.keys(templatedItems), + ['asset', 'script'], + 'expected specific types to be templated' + ); + + // script + assert.deepEqual( + templatedItems.script.map((item) => item.key), + ['{{{prefix}}}script_ampscript'], + 'expected specific scripts to be templated' + ); + // asset + assert.deepEqual( + templatedItems.asset.map((item) => item.customerKey), + [ + '{{{prefix}}}asset_htmlblock', + '{{{prefix}}}htmlblock 3 spaces', + '{{{prefix}}}htmlblock1', + '{{{prefix}}}htmlblock2', + ], + 'expected specific assets to be templated' + ); + }); + }); + + describe('Delete ================', () => { + it('Should delete the item', async () => { + // WHEN + const isDeleted = await handler.deleteByKey( + 'testInstance/testBU', + 'script', + 'testExisting_script' + ); + // THEN + assert.equal(process.exitCode, 0, 'deleteByKey should not have thrown an error'); + assert.equal(isDeleted, true, 'deleteByKey should have returned true'); + return; + }); + }); + + describe('CI/CD ================', () => { + it('Should return a list of files based on their type and key', async () => { + // WHEN + const fileList = await handler.getFilesToCommit('testInstance/testBU', 'script', [ + 'testExisting_script', + ]); + // THEN + assert.equal(process.exitCode, 0, 'getFilesToCommit should not have thrown an error'); + assert.equal(fileList.length, 3, 'expected only 3 file paths (html, json, ssjs)'); + + assert.equal( + fileList[0].split('\\').join('/'), + 'retrieve/testInstance/testBU/script/testExisting_script.script-meta.json', + 'wrong JSON path' + ); + assert.equal( + fileList[1].split('\\').join('/'), + 'retrieve/testInstance/testBU/script/testExisting_script.script-meta.ssjs', + 'wrong SSJS path' + ); + assert.equal( + fileList[2].split('\\').join('/'), + 'retrieve/testInstance/testBU/script/testExisting_script.script-meta.html', + 'wrong HTML path' + ); + return; + }); + }); + + describe('Execute ================', () => {}); + + describe('ReplaceContentBlockByX ================', () => { + it('Should replace references with ContentBlockByName w/o deploy', async () => { + handler.setOptions({ skipDeploy: true }); + + // WHEN + const replace = await handler.replaceCbReference( + 'testInstance/testBU', + { + script: null, + }, + 'name' + ); + // THEN + assert.equal(process.exitCode, 0, 'retrieve should not have thrown an error'); + // retrieve result + assert.deepEqual( + replace['testInstance/testBU'].script, + [ + 'testExisting_script_ampscript', + 'testExisting_script_ampincluded', + 'testExisting_script_mixed', + ], + 'should have found the right scripts that need updating' + ); + // get results from cache + const result = cache.getCache(); + assert.equal( + result.script ? Object.keys(result.script).length : 0, + 5, + 'only 5 scripts expected' + ); + // check if conversions happened + expect( + await testUtils.getActualFile('testExisting_script_ampscript', 'script', 'html') + ).to.equal( + await testUtils.getExpectedFile( + '9999999', + 'script', + 'get_ampscript-rcb-name', + 'html' + ) + ); + expect(await testUtils.getActualFile('testExisting_script_ampscript', 'script', 'ssjs')) + .to.not.exist; + + expect( + await testUtils.getActualFile('testExisting_script_ampincluded', 'script', 'html') + ).to.equal( + await testUtils.getExpectedFile( + '9999999', + 'script', + 'get_ampincluded-rcb-name', + 'html' + ) + ); + expect( + await testUtils.getActualFile('testExisting_script_ampincluded', 'script', 'ssjs') + ).to.not.exist; + + expect( + await testUtils.getActualFile('testExisting_script_mixed', 'script', 'html') + ).to.equal( + await testUtils.getExpectedFile('9999999', 'script', 'get_mixed-rcb-name', 'html') + ); + expect(await testUtils.getActualFile('testExisting_script_mixed', 'script', 'ssjs')).to + .not.exist; + + assert.equal( + testUtils.getAPIHistoryLength(), + 8, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + return; + }); + + it('Should replace references with ContentBlockById w/o deploy', async () => { + handler.setOptions({ skipDeploy: true }); + + // WHEN + const replace = await handler.replaceCbReference( + 'testInstance/testBU', + { + script: null, + }, + 'id' + ); + // THEN + assert.equal(process.exitCode, 0, 'retrieve should not have thrown an error'); + // retrieve result + assert.deepEqual( + replace['testInstance/testBU'].script, + ['testExisting_script_ampscript', 'testExisting_script_mixed'], + 'should have found the right scripts that need updating' + ); + + // get results from cache + const result = cache.getCache(); + assert.equal( + result.script ? Object.keys(result.script).length : 0, + 5, + 'only 5 scripts expected' + ); + // check if conversions happened + expect( + await testUtils.getActualFile('testExisting_script_ampscript', 'script', 'html') + ).to.equal( + await testUtils.getExpectedFile('9999999', 'script', 'get_ampscript-rcb-id', 'html') + ); + expect(await testUtils.getActualFile('testExisting_script_ampscript', 'script', 'ssjs')) + .to.not.exist; + + expect( + await testUtils.getActualFile('testExisting_script_ampincluded', 'script', 'html') + ).to.equal( + await testUtils.getExpectedFile( + '9999999', + 'script', + 'get_ampincluded-rcb-id', + 'html' + ) + ); + expect( + await testUtils.getActualFile('testExisting_script_ampincluded', 'script', 'ssjs') + ).to.not.exist; + + expect( + await testUtils.getActualFile('testExisting_script_mixed', 'script', 'html') + ).to.equal( + await testUtils.getExpectedFile('9999999', 'script', 'get_mixed-rcb-id', 'html') + ); + expect(await testUtils.getActualFile('testExisting_script_mixed', 'script', 'ssjs')).to + .not.exist; + + assert.equal( + testUtils.getAPIHistoryLength(), + 8, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + return; + }); + + it('Should replace references with ContentBlockByKey w/o deploy', async () => { + handler.setOptions({ skipDeploy: true }); + + // WHEN + const replace = await handler.replaceCbReference( + 'testInstance/testBU', + { + script: null, + }, + 'key' + ); + // THEN + assert.equal(process.exitCode, 0, 'retrieve should not have thrown an error'); + // retrieve result + assert.deepEqual( + replace['testInstance/testBU'].script, + ['testExisting_script_ampscript', 'testExisting_script_ampincluded'], + 'should have found the right scripts that need updating' + ); + + // get results from cache + const result = cache.getCache(); + assert.equal( + result.script ? Object.keys(result.script).length : 0, + 5, + 'only 5 scripts expected' + ); + // check if conversions happened + expect( + await testUtils.getActualFile('testExisting_script_ampscript', 'script', 'html') + ).to.equal( + await testUtils.getExpectedFile( + '9999999', + 'script', + 'get_ampscript-rcb-key', + 'html' + ) + ); + expect(await testUtils.getActualFile('testExisting_script_ampscript', 'script', 'ssjs')) + .to.not.exist; + + expect( + await testUtils.getActualFile('testExisting_script_ampincluded', 'script', 'html') + ).to.equal( + await testUtils.getExpectedFile( + '9999999', + 'script', + 'get_ampincluded-rcb-key', + 'html' + ) + ); + expect( + await testUtils.getActualFile('testExisting_script_ampincluded', 'script', 'ssjs') + ).to.not.exist; + + expect( + await testUtils.getActualFile('testExisting_script_mixed', 'script', 'html') + ).to.equal( + await testUtils.getExpectedFile('9999999', 'script', 'get_mixed-rcb-key', 'html') + ); + expect(await testUtils.getActualFile('testExisting_script_mixed', 'script', 'ssjs')).to + .not.exist; + + assert.equal( + testUtils.getAPIHistoryLength(), + 8, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + return; + }); + }); +}); diff --git a/test/type.sendClassification.test.js b/test/type.sendClassification.test.js new file mode 100644 index 000000000..77a188bb6 --- /dev/null +++ b/test/type.sendClassification.test.js @@ -0,0 +1,156 @@ +import * as chai from 'chai'; +const assert = chai.assert; + +import chaiFiles from 'chai-files'; +import cache from '../lib/util/cache.js'; +import * as testUtils from './utils.js'; +import handler from '../lib/index.js'; +chai.use(chaiFiles); + +describe('type: sendClassification', () => { + beforeEach(() => { + testUtils.mockSetup(); + }); + + afterEach(() => { + testUtils.mockReset(); + }); + + describe('Retrieve ================', () => { + it('Should retrieve a sendClassification', async () => { + // WHEN + await handler.retrieve('testInstance/testBU', ['sendClassification']); + // THEN + assert.equal(process.exitCode, 0, 'retrieve should not have thrown an error'); + // get results from cache + const result = cache.getCache(); + assert.equal( + result.sendClassification ? Object.keys(result.sendClassification).length : 0, + 3, + 'only 3 sendClassifications expected' + ); + assert.deepEqual( + await testUtils.getActualJson( + 'testExisting_sendClassification', + 'sendClassification' + ), + await testUtils.getExpectedJson('9999999', 'sendClassification', 'get'), + 'returned JSON was not equal expected' + ); + assert.equal( + testUtils.getAPIHistoryLength(), + 4, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + return; + }); + }); + + describe('Deploy ================', () => { + beforeEach(() => { + testUtils.mockSetup(true); + }); + + it('Should create & upsert a sendClassification', async () => { + // WHEN + + await handler.deploy('testInstance/testBU', ['sendClassification']); + // THEN + assert.equal(process.exitCode, 0, 'deploy should not have thrown an error'); + // get results from cache + const result = cache.getCache(); + assert.equal( + result.sendClassification ? Object.keys(result.sendClassification).length : 0, + 4, + 'two sendClassifications expected' + ); + // confirm created item + assert.deepEqual( + await testUtils.getActualJson('testNew_sendClassification', 'sendClassification'), + await testUtils.getExpectedJson('9999999', 'sendClassification', 'post'), + 'returned new-JSON was not equal expected for insert sendClassification' + ); + // confirm updated item + assert.deepEqual( + await testUtils.getActualJson( + 'testExisting_sendClassification', + 'sendClassification' + ), + await testUtils.getExpectedJson('9999999', 'sendClassification', 'patch'), + 'returned existing-JSON was not equal expected for update sendClassification' + ); + // check number of API calls + assert.equal( + testUtils.getAPIHistoryLength(), + 7, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + return; + }); + }); + + describe('Templating ================', () => { + it('Should create a sendClassification template via buildTemplate and build it', async () => { + // download first before we test buildTemplate + await handler.retrieve('testInstance/testBU', ['sendClassification']); + // buildTemplate + const result = await handler.buildTemplate( + 'testInstance/testBU', + 'sendClassification', + ['testExisting_sendClassification'], + ['testSourceMarket'] + ); + assert.equal(process.exitCode, 0, 'buildTemplate should not have thrown an error'); + assert.equal( + result.sendClassification ? Object.keys(result.sendClassification).length : 0, + 1, + 'only one sendClassification expected' + ); + assert.deepEqual( + await testUtils.getActualTemplateJson( + 'testExisting_sendClassification', + 'sendClassification' + ), + await testUtils.getExpectedJson('9999999', 'sendClassification', 'template'), + 'returned template JSON was not equal expected' + ); + // buildDefinition + await handler.buildDefinition( + 'testInstance/testBU', + 'sendClassification', + ['testExisting_sendClassification'], + ['testTargetMarket'] + ); + assert.equal(process.exitCode, 0, 'buildDefinition should not have thrown an error'); + assert.deepEqual( + await testUtils.getActualDeployJson( + 'testTemplated_sendClassification', + 'sendClassification' + ), + await testUtils.getExpectedJson('9999999', 'sendClassification', 'build'), + 'returned deployment JSON was not equal expected' + ); + assert.equal( + testUtils.getAPIHistoryLength(), + 4, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + return; + }); + }); + + describe('Delete ================', () => { + it('Should delete the item', async () => { + // WHEN + const isDeleted = await handler.deleteByKey( + 'testInstance/testBU', + 'sendClassification', + 'testExisting_sendClassification' + ); + // THEN + assert.equal(process.exitCode, 0, 'deleteByKey should not have thrown an error'); + assert.equal(isDeleted, true, 'deleteByKey should have returned true'); + return; + }); + }); +}); diff --git a/test/type.senderProfile.test.js b/test/type.senderProfile.test.js new file mode 100644 index 000000000..d29ac08ee --- /dev/null +++ b/test/type.senderProfile.test.js @@ -0,0 +1,320 @@ +import * as chai from 'chai'; +const assert = chai.assert; + +import chaiFiles from 'chai-files'; +import cache from '../lib/util/cache.js'; +import * as testUtils from './utils.js'; +import handler from '../lib/index.js'; +chai.use(chaiFiles); + +describe('type: senderProfile', () => { + beforeEach(() => { + testUtils.mockSetup(); + }); + + afterEach(() => { + testUtils.mockReset(); + }); + + describe('Retrieve ================', () => { + it('Should retrieve a senderProfile', async () => { + // WHEN + await handler.retrieve('testInstance/testBU', ['senderProfile']); + // THEN + assert.equal(process.exitCode, 0, 'retrieve should not have thrown an error'); + // get results from cache + const result = cache.getCache(); + assert.equal( + result.senderProfile ? Object.keys(result.senderProfile).length : 0, + 3, + '3 senderProfiles expected' + ); + assert.deepEqual( + await testUtils.getActualJson('testExisting_senderProfile', 'senderProfile'), + await testUtils.getExpectedJson('9999999', 'senderProfile', 'get'), + 'returned JSON was not equal expected' + ); + assert.equal( + testUtils.getAPIHistoryLength(), + 5, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + return; + }); + }); + + describe('Deploy ================', () => { + beforeEach(() => { + testUtils.mockSetup(true); + }); + + it('Should create & upsert a senderProfile', async () => { + // WHEN + + await handler.deploy('testInstance/testBU', ['senderProfile']); + // THEN + assert.equal(process.exitCode, 0, 'deploy should not have thrown an error'); + // get results from cache + const result = cache.getCache(); + assert.equal( + result.senderProfile ? Object.keys(result.senderProfile).length : 0, + 4, + '4 senderProfiles expected' + ); + // check callouts + const createCallout = testUtils.getRestCallout( + 'post', + '/messaging/v1/domainverification/' + ); + assert.deepEqual( + createCallout, + { domain: 'joern.berkefeld.New@accenture.com' }, + 'unexecpted payload for create callout' + ); + // confirm created domainVerification item + assert.deepEqual( + await testUtils.getActualJson( + 'joern.berkefeld.New@accenture.com', + 'domainVerification' + ), + await testUtils.getExpectedJson('9999999', 'domainVerification', 'create'), + 'returned new-JSON was not equal expected for insert domainVerification' + ); + + // confirm created item + assert.deepEqual( + await testUtils.getActualJson('testNew_senderProfile', 'senderProfile'), + await testUtils.getExpectedJson('9999999', 'senderProfile', 'post'), + 'returned new-JSON was not equal expected for insert senderProfile' + ); + // confirm updated item + assert.deepEqual( + await testUtils.getActualJson('testExisting_senderProfile', 'senderProfile'), + await testUtils.getExpectedJson('9999999', 'senderProfile', 'patch'), + 'returned existing-JSON was not equal expected for update senderProfile' + ); + // check number of API calls + assert.equal( + testUtils.getAPIHistoryLength(), + 10, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + return; + }); + }); + + describe('Templating ================', () => { + it('Should create a senderProfile template via buildTemplate and build it', async () => { + // download first before we test buildTemplate + await handler.retrieve('testInstance/testBU', ['senderProfile']); + // buildTemplate + const result = await handler.buildTemplate( + 'testInstance/testBU', + 'senderProfile', + ['testExisting_senderProfile'], + ['testSourceMarket'] + ); + assert.equal(process.exitCode, 0, 'buildTemplate should not have thrown an error'); + assert.equal( + result.senderProfile ? Object.keys(result.senderProfile).length : 0, + 1, + 'only one senderProfile expected' + ); + assert.deepEqual( + await testUtils.getActualTemplateJson( + 'testExisting_senderProfile', + 'senderProfile' + ), + await testUtils.getExpectedJson('9999999', 'senderProfile', 'template'), + 'returned template JSON was not equal expected' + ); + // buildDefinition + await handler.buildDefinition( + 'testInstance/testBU', + 'senderProfile', + ['testExisting_senderProfile'], + ['testTargetMarket'] + ); + assert.equal(process.exitCode, 0, 'buildDefinition should not have thrown an error'); + assert.deepEqual( + await testUtils.getActualDeployJson('testTemplated_senderProfile', 'senderProfile'), + await testUtils.getExpectedJson('9999999', 'senderProfile', 'build'), + 'returned deployment JSON was not equal expected' + ); + assert.equal( + testUtils.getAPIHistoryLength(), + 5, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + return; + }); + + it('Should create a senderProfile template via buildTemplate with --dependencies', async () => { + // download first before we test buildTemplate + handler.setOptions({ dependencies: true, retrieve: true }); + assert.equal(process.exitCode, 0, 'retrieve should not have thrown an error'); + + // GIVEN there is a template + const templatedItems = await handler.buildTemplate( + 'testInstance/testBU', + 'senderProfile', + ['Default', 'testExisting_senderProfile', 'testExisting_senderProfile_rcb'], + ['testSourceMarket'] + ); + // WHEN + assert.equal(process.exitCode, 0, 'buildTemplate should not have thrown an error'); + + assert.deepEqual( + Object.keys(templatedItems), + ['asset', 'domainVerification', 'senderProfile'], + 'expected specific types to be templated' + ); + + // asset + assert.deepEqual( + templatedItems.asset.map((item) => item.customerKey), + [ + '{{{prefix}}}asset_htmlblock', + '{{{prefix}}}htmlblock 3 spaces', + '{{{prefix}}}htmlblock1', + '{{{prefix}}}htmlblock2', + ], + 'expected specific assets to be templated' + ); + // domainVerification + assert.deepEqual( + templatedItems.domainVerification.map((item) => item.domain), + ['joern.berkefeld+test@accenture.com', 'joern.berkefeld@accenture.com'], + 'expected specific domainVerifications to be templated' + ); + // senderProfile + assert.deepEqual( + templatedItems.senderProfile.map((item) => item.CustomerKey), + ['Default', '{{{prefix}}}senderProfile', '{{{prefix}}}senderProfile_rcb'], + 'expected specific senderProfiles to be templated' + ); + }); + }); + + describe('Delete ================', () => { + it('Should delete the item', async () => { + // WHEN + const isDeleted = await handler.deleteByKey( + 'testInstance/testBU', + 'senderProfile', + 'testExisting_senderProfile' + ); + // THEN + assert.equal(process.exitCode, 0, 'deleteByKey should not have thrown an error'); + assert.equal(isDeleted, true, 'deleteByKey should have returned true'); + return; + }); + }); + + describe('ReplaceContentBlockByX ================', () => { + it('Should replace references with ContentBlockByName w/o deploy', async () => { + handler.setOptions({ skipDeploy: true }); + + // WHEN + const replace = await handler.replaceCbReference( + 'testInstance/testBU', + { + senderProfile: null, + }, + 'name' + ); + // THEN + assert.equal(process.exitCode, 0, 'retrieve should not have thrown an error'); + // retrieve result + assert.deepEqual( + replace['testInstance/testBU'].senderProfile, + ['testExisting_senderProfile_rcb'], + 'should have found the right senderProfiles that need updating' + ); + + // check if conversions happened + assert.deepEqual( + await testUtils.getActualJson('testExisting_senderProfile_rcb', 'senderProfile'), + await testUtils.getExpectedJson('9999999', 'senderProfile', 'get-rcb-name'), + 'returned JSON was not equal expected' + ); + + assert.equal( + testUtils.getAPIHistoryLength(), + 11, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + return; + }); + + it('Should replace references with ContentBlockById w/o deploy', async () => { + handler.setOptions({ skipDeploy: true }); + + // WHEN + const replace = await handler.replaceCbReference( + 'testInstance/testBU', + { + senderProfile: null, + }, + 'id' + ); + // THEN + assert.equal(process.exitCode, 0, 'retrieve should not have thrown an error'); + // retrieve result + assert.deepEqual( + replace['testInstance/testBU'].senderProfile, + ['testExisting_senderProfile_rcb'], + 'should have found the right senderProfiles that need updating' + ); + + // check if conversions happened + assert.deepEqual( + await testUtils.getActualJson('testExisting_senderProfile_rcb', 'senderProfile'), + await testUtils.getExpectedJson('9999999', 'senderProfile', 'get-rcb-id'), + 'returned JSON was not equal expected' + ); + + assert.equal( + testUtils.getAPIHistoryLength(), + 11, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + return; + }); + + it('Should replace references with ContentBlockByKey w/o deploy', async () => { + handler.setOptions({ skipDeploy: true }); + + // WHEN + const replace = await handler.replaceCbReference( + 'testInstance/testBU', + { + senderProfile: null, + }, + 'key' + ); + // THEN + assert.equal(process.exitCode, 0, 'retrieve should not have thrown an error'); + // retrieve result + assert.deepEqual( + replace['testInstance/testBU'].senderProfile, + ['testExisting_senderProfile_rcb'], + 'should have found the right assets that need updating' + ); + + // check if conversions happened + assert.deepEqual( + await testUtils.getActualJson('testExisting_senderProfile_rcb', 'senderProfile'), + await testUtils.getExpectedJson('9999999', 'senderProfile', 'get-rcb-key'), + 'returned JSON was not equal expected' + ); + + assert.equal( + testUtils.getAPIHistoryLength(), + 11, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + return; + }); + }); +}); diff --git a/test/type.transactionalEmail.test.js b/test/type.transactionalEmail.test.js new file mode 100644 index 000000000..3ec8f942d --- /dev/null +++ b/test/type.transactionalEmail.test.js @@ -0,0 +1,162 @@ +import * as chai from 'chai'; +const assert = chai.assert; + +import chaiFiles from 'chai-files'; +import cache from '../lib/util/cache.js'; +import * as testUtils from './utils.js'; +import handler from '../lib/index.js'; +chai.use(chaiFiles); + +describe('type: transactionalEmail', () => { + beforeEach(() => { + testUtils.mockSetup(); + }); + + afterEach(() => { + testUtils.mockReset(); + }); + + describe('Retrieve ================', () => { + it('Should retrieve a transactionalEmail', async () => { + // WHEN + await handler.retrieve('testInstance/testBU', ['transactionalEmail']); + // THEN + assert.equal(process.exitCode, 0, 'retrieve should not have thrown an error'); + // get results from cache + const result = cache.getCache(); + assert.equal( + result.transactionalEmail ? Object.keys(result.transactionalEmail).length : 0, + 3, + 'unexpected number of transactionalEmail' + ); + assert.deepEqual( + await testUtils.getActualJson('testExisting_temail', 'transactionalEmail'), + await testUtils.getExpectedJson('9999999', 'transactionalEmail', 'get'), + 'returned JSON was not equal expected' + ); + assert.equal( + testUtils.getAPIHistoryLength(), + 14, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + return; + }); + }); + + describe('Deploy ================', () => { + beforeEach(() => { + testUtils.mockSetup(true); + }); + + it('Should create & upsert a transactionalEmail', async () => { + // WHEN + await handler.deploy('testInstance/testBU', ['transactionalEmail']); + // THEN + assert.equal(process.exitCode, 0, 'deploy should not have thrown an error'); + // get results from cache + const result = cache.getCache(); + assert.equal( + result.transactionalEmail ? Object.keys(result.transactionalEmail).length : 0, + 4, + 'unexpected number of transactionalEmails' + ); + // confirm created item + assert.deepEqual( + await testUtils.getActualJson('testNew_temail', 'transactionalEmail'), + await testUtils.getExpectedJson('9999999', 'transactionalEmail', 'post'), + 'returned JSON was not equal expected for insert transactionalEmail' + ); + // confirm updated item + assert.deepEqual( + await testUtils.getActualJson('testExisting_temail', 'transactionalEmail'), + await testUtils.getExpectedJson('9999999', 'transactionalEmail', 'patch'), + 'returned JSON was not equal expected for update transactionalEmail' + ); + // check number of API calls + assert.equal( + testUtils.getAPIHistoryLength(), + 16, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + return; + }); + + it('Should NOT change the key during update with --changeKeyValue and instead fail due to missing support', async () => { + // WHEN + handler.setOptions({ changeKeyValue: 'updatedKey' }); + await handler.deploy( + 'testInstance/testBU', + ['transactionalEmail'], + ['testExisting_temail'] + ); + // THEN + assert.equal( + process.exitCode, + 1, + 'deploy should have thrown an error due to lack of support' + ); + return; + }); + }); + + describe('Templating ================', () => { + // it.skip('Should create a transactionalEmail template via retrieveAsTemplate and build it'); + it('Should create a transactionalEmail template via buildTemplate and build it', async () => { + // download first before we test buildTemplate + await handler.retrieve('testInstance/testBU', ['transactionalEmail']); + // buildTemplate + const result = await handler.buildTemplate( + 'testInstance/testBU', + 'transactionalEmail', + ['testExisting_temail'], + ['testSourceMarket'] + ); + assert.equal(process.exitCode, 0, 'buildTemplate should not have thrown an error'); + assert.equal( + result.transactionalEmail ? Object.keys(result.transactionalEmail).length : 0, + 1, + 'only one transactionalEmail expected' + ); + assert.deepEqual( + await testUtils.getActualTemplateJson('testExisting_temail', 'transactionalEmail'), + await testUtils.getExpectedJson('9999999', 'transactionalEmail', 'template'), + 'returned template JSON was not equal expected' + ); + // buildDefinition + await handler.buildDefinition( + 'testInstance/testBU', + 'transactionalEmail', + ['testExisting_temail'], + ['testTargetMarket'] + ); + assert.equal(process.exitCode, 0, 'buildDefinition should not have thrown an error'); + assert.deepEqual( + await testUtils.getActualDeployJson('testTemplated_temail', 'transactionalEmail'), + await testUtils.getExpectedJson('9999999', 'transactionalEmail', 'build'), + 'returned deployment JSON was not equal expected' + ); + assert.equal( + testUtils.getAPIHistoryLength(), + 14, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + return; + }); + }); + + describe('Delete ================', () => { + it('Should delete the item', async () => { + // WHEN + const isDeleted = await handler.deleteByKey( + 'testInstance/testBU', + 'transactionalEmail', + 'testExisting_temail' + ); + // THEN + assert.equal(process.exitCode, 0, 'delete should not have thrown an error'); + + assert.equal(isDeleted, true, 'should have deleted the item'); + return; + }); + }); +}); diff --git a/test/type.transactionalPush.test.js b/test/type.transactionalPush.test.js new file mode 100644 index 000000000..ef85b9420 --- /dev/null +++ b/test/type.transactionalPush.test.js @@ -0,0 +1,160 @@ +import * as chai from 'chai'; +const assert = chai.assert; + +import chaiFiles from 'chai-files'; +import cache from '../lib/util/cache.js'; +import * as testUtils from './utils.js'; +import handler from '../lib/index.js'; +chai.use(chaiFiles); + +describe('type: transactionalPush', () => { + beforeEach(() => { + testUtils.mockSetup(); + }); + + afterEach(() => { + testUtils.mockReset(); + }); + + describe('Retrieve ================', () => { + it('Should retrieve a transactionalPush', async () => { + // WHEN + await handler.retrieve('testInstance/testBU', ['transactionalPush']); + // THEN + assert.equal(process.exitCode, 0, 'retrieve should not have thrown an error'); + // get results from cache + const result = cache.getCache(); + assert.equal( + result.transactionalPush ? Object.keys(result.transactionalPush).length : 0, + 1, + 'only one transactionalPush expected' + ); + assert.deepEqual( + await testUtils.getActualJson('testExisting_tpush', 'transactionalPush'), + await testUtils.getExpectedJson('9999999', 'transactionalPush', 'get'), + 'returned JSON was not equal expected' + ); + assert.equal( + testUtils.getAPIHistoryLength(), + 3, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + return; + }); + }); + + describe('Deploy ================', () => { + beforeEach(() => { + testUtils.mockSetup(true); + }); + + it('Should create & upsert a transactionalPush', async () => { + // WHEN + await handler.deploy('testInstance/testBU', ['transactionalPush']); + // THEN + assert.equal(process.exitCode, 0, 'deploy should not have thrown an error'); + // get results from cache + const result = cache.getCache(); + assert.equal( + result.transactionalPush ? Object.keys(result.transactionalPush).length : 0, + 2, + 'two transactionalPushs expected' + ); + // confirm created item + assert.deepEqual( + await testUtils.getActualJson('testNew_tpush', 'transactionalPush'), + await testUtils.getExpectedJson('9999999', 'transactionalPush', 'post'), + 'returned JSON was not equal expected for insert transactionalPush' + ); + // confirm updated item + assert.deepEqual( + await testUtils.getActualJson('testExisting_tpush', 'transactionalPush'), + await testUtils.getExpectedJson('9999999', 'transactionalPush', 'patch'), + 'returned JSON was not equal expected for update transactionalPush' + ); + // check number of API calls + assert.equal( + testUtils.getAPIHistoryLength(), + 5, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + return; + }); + + it('Should NOT change the key during update with --changeKeyValue and instead fail due to missing support', async () => { + // WHEN + handler.setOptions({ changeKeyValue: 'updatedKey' }); + await handler.deploy( + 'testInstance/testBU', + ['transactionalPush'], + ['testExisting_tpush'] + ); + // THEN + assert.equal( + process.exitCode, + 1, + 'deploy should have thrown an error due to lack of support' + ); + return; + }); + }); + + describe('Templating ================', () => { + // it.skip('Should create a transactionalPush template via retrieveAsTemplate and build it'); + it('Should create a transactionalPush template via buildTemplate and build it', async () => { + // download first before we test buildTemplate + await handler.retrieve('testInstance/testBU', ['transactionalPush']); + // buildTemplate + const result = await handler.buildTemplate( + 'testInstance/testBU', + 'transactionalPush', + ['testExisting_tpush'], + ['testSourceMarket'] + ); + assert.equal(process.exitCode, 0, 'buildTemplate should not have thrown an error'); + assert.equal( + result.transactionalPush ? Object.keys(result.transactionalPush).length : 0, + 1, + 'only one transactionalPush expected' + ); + assert.deepEqual( + await testUtils.getActualTemplateJson('testExisting_tpush', 'transactionalPush'), + await testUtils.getExpectedJson('9999999', 'transactionalPush', 'template'), + 'returned template JSON was not equal expected' + ); + // buildDefinition + await handler.buildDefinition( + 'testInstance/testBU', + 'transactionalPush', + ['testExisting_tpush'], + ['testTargetMarket'] + ); + assert.equal(process.exitCode, 0, 'buildDefinition should not have thrown an error'); + + assert.deepEqual( + await testUtils.getActualDeployJson('testTemplated_tpush', 'transactionalPush'), + await testUtils.getExpectedJson('9999999', 'transactionalPush', 'build'), + 'returned deployment JSON was not equal expected' + ); + assert.equal( + testUtils.getAPIHistoryLength(), + 3, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + return; + }); + }); + + describe('Delete ================', () => { + // TODO: add this test + it('Should delete the item'); // , async () => { + // // WHEN + // const isDeleted = await handler.deleteByKey('testInstance/testBU', 'mobileKeyword', 'testExisting_keyword'); + // // THEN + // assert.equal(process.exitCode, 0, 'delete should not have thrown an error'); + + // assert.equal(isDeleted, true, 'should have deleted the item'); + // return; + // }); + }); +}); diff --git a/test/type.transactionalSMS.test.js b/test/type.transactionalSMS.test.js new file mode 100644 index 000000000..d57abfe3b --- /dev/null +++ b/test/type.transactionalSMS.test.js @@ -0,0 +1,222 @@ +import * as chai from 'chai'; +const assert = chai.assert; +const expect = chai.expect; + +import chaiFiles from 'chai-files'; +import cache from '../lib/util/cache.js'; +import * as testUtils from './utils.js'; +import handler from '../lib/index.js'; +chai.use(chaiFiles); + +describe('type: transactionalSMS', () => { + beforeEach(() => { + testUtils.mockSetup(); + }); + + afterEach(() => { + testUtils.mockReset(); + }); + + describe('Retrieve ================', () => { + it('Should retrieve a transactionalSMS', async () => { + // WHEN + await handler.retrieve('testInstance/testBU', ['transactionalSMS']); + // THEN + assert.equal(process.exitCode, 0, 'retrieve should not have thrown an error'); + // get results from cache + const result = cache.getCache(); + assert.equal( + result.transactionalSMS ? Object.keys(result.transactionalSMS).length : 0, + 1, + 'only one transactionalSMS expected' + ); + assert.deepEqual( + await testUtils.getActualJson('testExisting_tsms', 'transactionalSMS'), + await testUtils.getExpectedJson('9999999', 'transactionalSMS', 'get'), + 'returned JSON was not equal expected' + ); + expect( + await testUtils.getActualFile('testExisting_tsms', 'transactionalSMS', 'amp') + ).to.equal( + await testUtils.getExpectedFile('9999999', 'transactionalSMS', 'get', 'amp') + ); + assert.equal( + testUtils.getAPIHistoryLength(), + 4, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + return; + }); + }); + + describe('Deploy ================', () => { + beforeEach(() => { + testUtils.mockSetup(true); + }); + + it('Should create & upsert a transactionalSMS', async () => { + // WHEN + await handler.deploy('testInstance/testBU', ['transactionalSMS']); + // THEN + assert.equal(process.exitCode, 0, 'deploy should not have thrown an error'); + // get results from cache + const result = cache.getCache(); + assert.equal( + result.transactionalSMS ? Object.keys(result.transactionalSMS).length : 0, + 2, + 'two transactionalSMSs expected' + ); + // confirm created item + assert.deepEqual( + await testUtils.getActualJson('testNew_tsms', 'transactionalSMS'), + await testUtils.getExpectedJson('9999999', 'transactionalSMS', 'post'), + 'returned JSON was not equal expected for insert transactionalSMS' + ); + expect( + await testUtils.getActualFile('testNew_tsms', 'transactionalSMS', 'amp') + ).to.equal( + await testUtils.getExpectedFile('9999999', 'transactionalSMS', 'post', 'amp') + ); + // confirm updated item + assert.deepEqual( + await testUtils.getActualJson('testExisting_tsms', 'transactionalSMS'), + await testUtils.getExpectedJson('9999999', 'transactionalSMS', 'patch'), + 'returned JSON was not equal expected for update transactionalSMS' + ); + expect( + await testUtils.getActualFile('testExisting_tsms', 'transactionalSMS', 'amp') + ).to.equal( + await testUtils.getExpectedFile('9999999', 'transactionalSMS', 'patch', 'amp') + ); + // check number of API calls + assert.equal( + testUtils.getAPIHistoryLength(), + 6, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + return; + }); + + it('Should NOT change the key during update with --changeKeyValue and instead fail due to missing support', async () => { + // WHEN + handler.setOptions({ changeKeyValue: 'updatedKey' }); + await handler.deploy( + 'testInstance/testBU', + ['transactionalSMS'], + ['testExisting_tsms'] + ); + // THEN + assert.equal( + process.exitCode, + 1, + 'deploy should have thrown an error due to lack of support' + ); + return; + }); + }); + + describe('Templating ================', () => { + // it.skip('Should create a transactionalSMS template via retrieveAsTemplate and build it'); + it('Should create a transactionalSMS template via buildTemplate and build it', async () => { + // download first before we test buildTemplate + await handler.retrieve('testInstance/testBU', ['transactionalSMS']); + // buildTemplate + const result = await handler.buildTemplate( + 'testInstance/testBU', + 'transactionalSMS', + ['testExisting_tsms'], + ['testSourceMarket'] + ); + assert.equal(process.exitCode, 0, 'buildTemplate should not have thrown an error'); + + assert.equal( + result.transactionalSMS ? Object.keys(result.transactionalSMS).length : 0, + 1, + 'only one transactionalSMS expected' + ); + assert.deepEqual( + await testUtils.getActualTemplateJson('testExisting_tsms', 'transactionalSMS'), + await testUtils.getExpectedJson('9999999', 'transactionalSMS', 'template'), + 'returned template JSON was not equal expected' + ); + expect( + await testUtils.getActualTemplateFile( + 'testExisting_tsms', + 'transactionalSMS', + 'amp' + ) + ).to.equal( + await testUtils.getExpectedFile('9999999', 'transactionalSMS', 'template', 'amp') + ); + // buildDefinition + await handler.buildDefinition( + 'testInstance/testBU', + 'transactionalSMS', + ['testExisting_tsms'], + ['testTargetMarket'] + ); + assert.equal(process.exitCode, 0, 'buildDefinition should not have thrown an error'); + + assert.deepEqual( + await testUtils.getActualDeployJson('testTemplated_tsms', 'transactionalSMS'), + await testUtils.getExpectedJson('9999999', 'transactionalSMS', 'build'), + 'returned deployment JSON was not equal expected' + ); + expect( + await testUtils.getActualDeployFile('testTemplated_tsms', 'transactionalSMS', 'amp') + ).to.equal( + await testUtils.getExpectedFile('9999999', 'transactionalSMS', 'build', 'amp') + ); + assert.equal( + testUtils.getAPIHistoryLength(), + 4, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + return; + }); + }); + + describe('Delete ================', () => { + // TODO: add this test + it('Should delete the item'); // , async () => { + // // WHEN + // const isDeleted = await handler.deleteByKey('testInstance/testBU', 'mobileKeyword', 'testExisting_keyword'); + // // THEN + // assert.equal(process.exitCode, 0, 'delete should not have thrown an error'); + + // assert.equal(isDeleted, true, 'should have deleted the item'); + // return; + // }); + }); + + describe('CI/CD ================', () => { + // TODO: add this test + it('Should return a list of files based on their type and key'); // , async () => { + // // WHEN + // const fileList = await handler.getFilesToCommit( + // 'testInstance/testBU', + // 'mobileKeyword', + // ['testExisting_keyword'] + // ); + // // THEN + // assert.equal( + // process.exitCode, + // false, + // 'getFilesToCommit should not have thrown an error' + // ); + // assert.equal(fileList.length, 2, 'expected only 2 file paths'); + + // assert.equal( + // fileList[0].split('\\').join('/'), + // 'retrieve/testInstance/testBU/mobileKeyword/testExisting_keyword.mobileKeyword-meta.json', + // 'wrong JSON path' + // ); + // assert.equal( + // fileList[1].split('\\').join('/'), + // 'retrieve/testInstance/testBU/mobileKeyword/testExisting_keyword.mobileKeyword-meta.amp', + // 'wrong AMP path' + // ); + // return; + // }); + }); +}); diff --git a/test/type.triggeredSend.test.js b/test/type.triggeredSend.test.js new file mode 100644 index 000000000..fd3b2e7c5 --- /dev/null +++ b/test/type.triggeredSend.test.js @@ -0,0 +1,397 @@ +import * as chai from 'chai'; +const assert = chai.assert; + +import chaiFiles from 'chai-files'; +import cache from '../lib/util/cache.js'; +import * as testUtils from './utils.js'; +import handler from '../lib/index.js'; +chai.use(chaiFiles); + +describe('type: triggeredSend', () => { + beforeEach(() => { + testUtils.mockSetup(); + }); + + afterEach(() => { + testUtils.mockReset(); + }); + + describe('Retrieve ================', () => { + it('Should retrieve a triggeredSend', async () => { + // WHEN + await handler.retrieve('testInstance/testBU', ['triggeredSend']); + // THEN + assert.equal(process.exitCode, 0, 'retrieve should not have thrown an error'); + // get results from cache + const result = cache.getCache(); + assert.equal( + result.triggeredSend ? Object.keys(result.triggeredSend).length : 0, + 2, + 'only 2 triggeredSend expected' + ); + assert.deepEqual( + await testUtils.getActualJson('testExisting_triggeredSend', 'triggeredSend'), + await testUtils.getExpectedJson('9999999', 'triggeredSend', 'get'), + 'returned JSON was not equal expected' + ); + assert.equal( + testUtils.getAPIHistoryLength(), + 10, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + return; + }); + }); + + describe('Deploy ================', () => { + beforeEach(() => { + testUtils.mockSetup(true); + }); + + it('Should create & upsert a triggeredSend', async () => { + // WHEN + await handler.deploy('testInstance/testBU', ['triggeredSend']); + // THEN + assert.equal(process.exitCode, 0, 'deploy should not have thrown an error'); + // get results from cache + const result = cache.getCache(); + assert.equal( + result.triggeredSend ? Object.keys(result.triggeredSend).length : 0, + 3, + 'two triggeredSends expected' + ); + // confirm created item + assert.deepEqual( + await testUtils.getActualJson('testNew_triggeredSend', 'triggeredSend'), + await testUtils.getExpectedJson('9999999', 'triggeredSend', 'post'), + 'returned JSON was not equal expected for insert triggeredSend' + ); + // confirm updated item + assert.deepEqual( + await testUtils.getActualJson('testExisting_triggeredSend', 'triggeredSend'), + await testUtils.getExpectedJson('9999999', 'triggeredSend', 'patch'), + 'returned JSON was not equal expected for update triggeredSend' + ); + // check number of API calls + assert.equal( + testUtils.getAPIHistoryLength(), + 12, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + return; + }); + }); + + describe('Templating ================', () => { + it('Should create a triggeredSend template via buildTemplate and build it', async () => { + // download first before we test buildTemplate + await handler.retrieve('testInstance/testBU', ['triggeredSend']); + // buildTemplate + const result = await handler.buildTemplate( + 'testInstance/testBU', + 'triggeredSend', + ['testExisting_triggeredSend'], + ['testSourceMarket'] + ); + assert.equal(process.exitCode, 0, 'buildTemplate should not have thrown an error'); + assert.equal( + result.triggeredSend ? Object.keys(result.triggeredSend).length : 0, + 1, + 'only one triggeredSend expected' + ); + assert.deepEqual( + await testUtils.getActualTemplateJson( + 'testExisting_triggeredSend', + 'triggeredSend' + ), + await testUtils.getExpectedJson('9999999', 'triggeredSend', 'template'), + 'returned template JSON was not equal expected' + ); + // buildDefinition + await handler.buildDefinition( + 'testInstance/testBU', + 'triggeredSend', + ['testExisting_triggeredSend'], + ['testTargetMarket'] + ); + assert.equal(process.exitCode, 0, 'buildDefinition should not have thrown an error'); + assert.deepEqual( + await testUtils.getActualDeployJson('testTemplated_triggeredSend', 'triggeredSend'), + await testUtils.getExpectedJson('9999999', 'triggeredSend', 'build'), + 'returned deployment JSON was not equal expected' + ); + assert.equal( + testUtils.getAPIHistoryLength(), + 10, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + return; + }); + + it('Should create a script template via buildTemplate with --dependencies', async () => { + // download first before we test buildTemplate + + handler.setOptions({ dependencies: true, retrieve: true }); + + // GIVEN there is a template + const templatedItems = await handler.buildTemplate( + 'testInstance/testBU', + 'triggeredSend', + ['testExisting_triggeredSend', 'testExisting_triggeredSend_rcb'], + ['testSourceMarket'] + ); + // WHEN + assert.equal(process.exitCode, 0, 'buildTemplate should not have thrown an error'); + + assert.deepEqual( + Object.keys(templatedItems), + [ + 'asset', + 'domainVerification', + 'sendClassification', + 'senderProfile', + 'triggeredSend', + ], + 'expected specific types to be templated' + ); + + // triggeredSend + assert.deepEqual( + templatedItems.triggeredSend.map((item) => item.CustomerKey), + ['{{{prefix}}}triggeredSend', '{{{prefix}}}triggeredSend_rcb'], + 'expected specific triggeredSends to be templated' + ); + // sendClassification + assert.deepEqual( + templatedItems.sendClassification.map((item) => item.CustomerKey), + ['{{{prefix}}}sendClassification'], + 'expected specific sendClassifications to be templated' + ); + // senderProfile + assert.deepEqual( + templatedItems.senderProfile.map((item) => item.CustomerKey), + ['{{{prefix}}}senderProfile', '{{{prefix}}}senderProfile_rcb'], + 'expected specific senderProfiles to be templated' + ); + // domainVerification + assert.deepEqual( + templatedItems.domainVerification.map((item) => item.domain), + ['joern.berkefeld+test@accenture.com', 'joern.berkefeld@accenture.com'], + 'expected specific domainVerification to be templated' + ); + // asset + assert.deepEqual( + templatedItems.asset.map((item) => item.customerKey), + [ + '{{{prefix}}}asset_htmlblock', + '{{{prefix}}}htmlblock 3 spaces', + '{{{prefix}}}htmlblock1', + '{{{prefix}}}htmlblock2', + ], + 'expected specific assets to be templated' + ); + }); + }); + + describe('Delete ================', () => { + it('Should delete the item', async () => { + // WHEN + const isDeleted = await handler.deleteByKey( + 'testInstance/testBU', + 'triggeredSend', + 'testExisting_triggeredSend' + ); + // THEN + assert.equal(process.exitCode, 0, 'delete should not have thrown an error'); + + assert.equal(isDeleted, true, 'should have deleted the item'); + return; + }); + }); + + describe('Refresh ================', () => { + it('Should refresh all active triggeredSend', async () => { + // WHEN + const replace = await handler.refresh('testInstance/testBU', { + triggeredSend: null, + }); + // THEN + assert.equal(process.exitCode, 0, 'refresh should not have thrown an error'); + // retrieve result + + assert.deepEqual( + replace['testInstance/testBU'].triggeredSend, + ['testExisting_triggeredSend', 'testExisting_triggeredSend_rcb'], + 'should have found the right triggeredSends that need updating' + ); + + assert.equal( + testUtils.getAPIHistoryLength(), + 15, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + return; + }); + + it('Should refresh a specifc triggeredSend by key', async () => { + // WHEN + const replace = await handler.refresh('testInstance/testBU', { + triggeredSend: ['testExisting_triggeredSend'], + }); + // THEN + assert.equal(process.exitCode, 0, 'refresh should not have thrown an error'); + // retrieve result + + assert.deepEqual( + replace['testInstance/testBU'].triggeredSend, + ['testExisting_triggeredSend'], + 'should have found the right triggeredSends that need updating' + ); + + assert.equal( + testUtils.getAPIHistoryLength(), + 4, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + return; + }); + + it('Should refresh 2 triggeredSend by key', async () => { + // WHEN + const replace = await handler.refresh('testInstance/testBU', { + triggeredSend: ['testExisting_triggeredSend', 'testExisting_triggeredSend_rcb'], + }); + // THEN + assert.equal(process.exitCode, 0, 'refresh should not have thrown an error'); + // retrieve result + + assert.deepEqual( + replace['testInstance/testBU'].triggeredSend, + ['testExisting_triggeredSend', 'testExisting_triggeredSend_rcb'], + 'should have found the right triggeredSends that need updating' + ); + + assert.equal( + testUtils.getAPIHistoryLength(), + 8, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + return; + }); + }); + + describe('Start (Execute) ================', () => { + it('Should start a triggeredSend by key'); + }); + + describe('Pause ================', () => { + it('Should pause a triggeredSend by key'); + }); + + describe('ReplaceContentBlockByX ================', () => { + it('Should replace references with ContentBlockByName w/o deploy', async () => { + handler.setOptions({ skipDeploy: true }); + + // WHEN + const replace = await handler.replaceCbReference( + 'testInstance/testBU', + { + triggeredSend: null, + }, + 'name' + ); + // THEN + assert.equal(process.exitCode, 0, 'retrieve should not have thrown an error'); + // retrieve result + assert.deepEqual( + replace['testInstance/testBU'].triggeredSend, + ['testExisting_triggeredSend_rcb'], + 'should have found the right triggeredSends that need updating' + ); + + // check if conversions happened + assert.deepEqual( + await testUtils.getActualJson('testExisting_triggeredSend_rcb', 'triggeredSend'), + await testUtils.getExpectedJson('9999999', 'triggeredSend', 'get-rcb-name'), + 'returned JSON was not equal expected' + ); + + assert.equal( + testUtils.getAPIHistoryLength(), + 16, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + return; + }); + + it('Should replace references with ContentBlockById w/o deploy', async () => { + handler.setOptions({ skipDeploy: true }); + + // WHEN + const replace = await handler.replaceCbReference( + 'testInstance/testBU', + { + triggeredSend: null, + }, + 'id' + ); + // THEN + assert.equal(process.exitCode, 0, 'retrieve should not have thrown an error'); + // retrieve result + assert.deepEqual( + replace['testInstance/testBU'].triggeredSend, + ['testExisting_triggeredSend_rcb'], + 'should have found the right triggeredSends that need updating' + ); + + // check if conversions happened + assert.deepEqual( + await testUtils.getActualJson('testExisting_triggeredSend_rcb', 'triggeredSend'), + await testUtils.getExpectedJson('9999999', 'triggeredSend', 'get-rcb-id'), + 'returned JSON was not equal expected' + ); + + assert.equal( + testUtils.getAPIHistoryLength(), + 16, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + return; + }); + + it('Should replace references with ContentBlockByKey w/o deploy', async () => { + handler.setOptions({ skipDeploy: true }); + + // WHEN + const replace = await handler.replaceCbReference( + 'testInstance/testBU', + { + triggeredSend: null, + }, + 'key' + ); + // THEN + assert.equal(process.exitCode, 0, 'retrieve should not have thrown an error'); + // retrieve result + assert.deepEqual( + replace['testInstance/testBU'].triggeredSend, + ['testExisting_triggeredSend_rcb'], + 'should have found the right assets that need updating' + ); + + // check if conversions happened + assert.deepEqual( + await testUtils.getActualJson('testExisting_triggeredSend_rcb', 'triggeredSend'), + await testUtils.getExpectedJson('9999999', 'triggeredSend', 'get-rcb-key'), + 'returned JSON was not equal expected' + ); + + assert.equal( + testUtils.getAPIHistoryLength(), + 16, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + return; + }); + }); +}); diff --git a/test/type.triggeredSendSummary.test.js b/test/type.triggeredSendSummary.test.js new file mode 100644 index 000000000..5681924bb --- /dev/null +++ b/test/type.triggeredSendSummary.test.js @@ -0,0 +1,45 @@ +import * as chai from 'chai'; +const assert = chai.assert; + +import chaiFiles from 'chai-files'; +import cache from '../lib/util/cache.js'; +import * as testUtils from './utils.js'; +import handler from '../lib/index.js'; +chai.use(chaiFiles); + +describe('type: triggeredSendSummary', () => { + beforeEach(() => { + testUtils.mockSetup(); + }); + + afterEach(() => { + testUtils.mockReset(); + }); + + describe('Retrieve ================', () => { + it('Should retrieve a triggeredSendSummary', async () => { + // WHEN + await handler.retrieve('testInstance/testBU', ['triggeredSendSummary']); + // THEN + assert.equal(process.exitCode, 0, 'retrieve should not have thrown an error'); + // get results from cache + const result = cache.getCache(); + assert.equal( + result.triggeredSendSummary ? Object.keys(result.triggeredSendSummary).length : 0, + 1, + 'only 1 triggeredSendSummary expected' + ); + assert.deepEqual( + await testUtils.getActualJson('testExisting_triggeredSend', 'triggeredSendSummary'), + await testUtils.getExpectedJson('9999999', 'triggeredSendSummary', 'get'), + 'returned JSON was not equal expected' + ); + assert.equal( + testUtils.getAPIHistoryLength(), + 3, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + return; + }); + }); +}); diff --git a/test/type.user.test.js b/test/type.user.test.js new file mode 100644 index 000000000..c80f9724b --- /dev/null +++ b/test/type.user.test.js @@ -0,0 +1,221 @@ +import * as chai from 'chai'; +const assert = chai.assert; +const expect = chai.expect; + +import chaiFiles from 'chai-files'; +import cache from '../lib/util/cache.js'; +import * as testUtils from './utils.js'; +import handler from '../lib/index.js'; +chai.use(chaiFiles); +const file = chaiFiles.file; +import File from '../lib/util/file.js'; + +describe('type: user', () => { + beforeEach(() => { + testUtils.mockSetup(); + }); + + afterEach(() => { + testUtils.mockReset(); + }); + + describe('Retrieve ================', () => { + it('Should retrieve a user', async () => { + // WHEN + await handler.retrieve('testInstance/_ParentBU_', ['user']); + // THEN + assert.equal(process.exitCode, 0, 'retrieve should not have thrown an error'); + // get results from cache + const result = cache.getCache(); + assert.equal( + result.user ? Object.keys(result.user).length : 0, + 3, + 'only three users expected' + ); + assert.deepEqual( + await testUtils.getActualJson('testExisting_user', 'user', '_ParentBU_'), + await testUtils.getExpectedJson('1111111', 'user', 'retrieve'), + + 'returned metadata was not equal expected' + ); + // check if MD file was created and equals expectations + // ! this test needs to update the lastLoginDate counter because it changes with every passing day + const expectedFile = await testUtils.getExpectedFile( + '1111111', + 'user', + 'retrieve', + 'md' + ); + const regexFindDaysSinceLogin = + /\| (\d*) (seconds|minutes|days|weeks|months|years){1} \|/g; + // fetch expected time since last login + const expectedDaysSinceLogin = expectedFile.match(regexFindDaysSinceLogin); + // load actual file and replace days since last login with expected value + const actualFile = ( + await File.readFile(`./docs/user/testInstance.users.md`, { + encoding: 'utf8', + }) + ).replaceAll(regexFindDaysSinceLogin, expectedDaysSinceLogin[0]); + expect(actualFile).to.equal(expectedFile); + + assert.equal( + testUtils.getAPIHistoryLength(), + 6, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + return; + }); + + it('Should retrieve a specific user but not run document', async () => { + // WHEN + await handler.retrieve('testInstance/_ParentBU_', ['user'], ['testExisting_user']); + // THEN + assert.equal(process.exitCode, 0, 'retrieve should not have thrown an error'); + + // because user is single-document-type we would not want to find an md file when we retrieve specific keys. only the generic retrieve updates it + expect(file(`./docs/user/testInstance.users.md`)).to.not.exist; + + assert.equal( + testUtils.getAPIHistoryLength(), + 4, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + return; + }); + }); + + describe('Deploy ================', () => { + beforeEach(() => { + testUtils.mockSetup(true); + }); + + it('Should create & upsert a user', async () => { + // WHEN + const expectedCache = [ + 'testExisting_user', + 'testExisting_user_inactive', + '45372cbb-06e0-438e-88d8-008981f7a18b', + 'testNew_user', + ]; + await handler.deploy('testInstance/_ParentBU_', ['user'], expectedCache); + // THEN + assert.equal(process.exitCode, 0, 'deploy should not have thrown an error'); + + // get results from cache + const result = cache.getCache(); + assert.equal( + result.user ? Object.keys(result.user).length : 0, + 4, + 'four users expected' + ); + // confirm if result.user only includes values from expectedCache + assert.deepEqual( + Object.keys(result.user), + expectedCache, + 'returned user keys were not equal expected' + ); + + // insert + assert.deepEqual( + await testUtils.getActualJson('testNew_user', 'user', '_ParentBU_'), + await testUtils.getExpectedJson('1111111', 'user', 'create'), + 'returned metadata was not equal expected for create' + ); + // update + assert.deepEqual( + await testUtils.getActualJson('testExisting_user', 'user', '_ParentBU_'), + await testUtils.getExpectedJson('1111111', 'user', 'update'), + 'returned metadata was not equal expected for update' + ); + // because user is single-document-type we would not want to find an md file getting created by deploy. only retrieve updates it + expect(file(`./docs/user/testInstance.users.md`)).to.not.exist; + + assert.equal( + testUtils.getAPIHistoryLength(), + 8, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + return; + }); + + it('Should not deploy user with Marketing Cloud role', async () => { + // WHEN + const expectedCache = [ + 'testExisting_user', + 'testExisting_user_inactive', + '45372cbb-06e0-438e-88d8-008981f7a18b', + ]; + await handler.deploy('testInstance/_ParentBU_', ['user'], ['testBlocked_user']); + // THEN + assert.equal(process.exitCode, 1, 'Deployment should have thrown an error'); + + // get results from cache + const result = cache.getCache(); + assert.equal( + result.user ? Object.keys(result.user).length : 0, + 3, + 'three users expected' + ); + // confirm if result.user only includes values from expectedCache + assert.deepEqual( + Object.keys(result.user), + expectedCache, + 'returned user keys were not equal expected' + ); + + assert.equal( + testUtils.getAPIHistoryLength(), + 5, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + return; + }); + }); + + describe('Templating ================', () => { + // it('Should create a user template via retrieveAsTemplate and build it', async () => {}); + it('Should create a user template via buildTemplate and build it', async () => { + // download first before we test buildTemplate + await handler.retrieve('testInstance/_ParentBU_', ['user']); + // GIVEN there is a template + const result = await handler.buildTemplate( + 'testInstance/_ParentBU_', + 'user', + ['testExisting_user'], + ['testSourceMarket'] + ); + assert.equal(process.exitCode, 0, 'buildTemplate should not have thrown an error'); + // WHEN + assert.equal( + result.user ? Object.keys(result.user).length : 0, + 1, + 'only one user expected' + ); + assert.deepEqual( + await testUtils.getActualTemplateJson('testExisting_user', 'user'), + await testUtils.getExpectedJson('1111111', 'user', 'template'), + 'returned template was not equal expected' + ); + // THEN + await handler.buildDefinition( + 'testInstance/_ParentBU_', + 'user', + ['testExisting_user'], + ['testTargetMarket'] + ); + assert.equal(process.exitCode, 0, 'buildDefinition should not have thrown an error'); + + assert.deepEqual( + await testUtils.getActualDeployJson('testTemplated_user', 'user', '_ParentBU_'), + await testUtils.getExpectedJson('1111111', 'user', 'build'), + 'returned deployment file was not equal expected' + ); + assert.equal( + testUtils.getAPIHistoryLength(), + 6, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + return; + }); + }); +}); diff --git a/test/type.verification.test.js b/test/type.verification.test.js new file mode 100644 index 000000000..7a62ea52f --- /dev/null +++ b/test/type.verification.test.js @@ -0,0 +1,169 @@ +import * as chai from 'chai'; +const assert = chai.assert; + +import chaiFiles from 'chai-files'; +import cache from '../lib/util/cache.js'; +import * as testUtils from './utils.js'; +import handler from '../lib/index.js'; +chai.use(chaiFiles); + +describe('type: verification', () => { + beforeEach(() => { + testUtils.mockSetup(); + }); + + afterEach(() => { + testUtils.mockReset(); + }); + + describe('Retrieve ================', () => { + it('Should retrieve a verification', async () => { + // WHEN + const retrieved = await handler.retrieve('testInstance/testBU', ['verification']); + // THEN + assert.equal(process.exitCode, 0, 'retrieve should not have thrown an error'); + // get results from cache + const result = cache.getCache(); + assert.equal( + result.verification ? Object.keys(result.verification).length : 0, + 1, + 'only one verification expected' + ); + assert.equal( + retrieved['testInstance/testBU']?.verification + ? Object.keys(retrieved['testInstance/testBU']?.verification).length + : 0, + 1, + 'one verifications to be retrieved' + ); + + assert.deepEqual( + await testUtils.getActualJson('testExisting_automation__s1.7', 'verification'), + await testUtils.getExpectedJson('9999999', 'verification', 'get'), + 'returned JSON was not equal expected' + ); + assert.equal( + testUtils.getAPIHistoryLength(), + 14, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + return; + }); + }); + + describe('Deploy ================', () => { + beforeEach(() => { + testUtils.mockSetup(true); + }); + + it('Should create & upsert a verification', async () => { + // WHEN + + const deployed = await handler.deploy('testInstance/testBU', ['verification']); + // THEN + assert.equal(process.exitCode, 0, 'deploy should not have thrown an error'); + // get results from cache + const result = cache.getCache(); + assert.equal( + result.verification ? Object.keys(result.verification).length : 0, + 2, + 'two verifications expected' + ); + assert.equal( + deployed['testInstance/testBU']?.verification + ? Object.keys(deployed['testInstance/testBU']?.verification).length + : 0, + 2, + 'two verifications to be deployed' + ); + // confirm created item + assert.deepEqual( + await testUtils.getActualJson('testNew_automation__s1.7', 'verification'), + await testUtils.getExpectedJson('9999999', 'verification', 'post'), + 'returned new-JSON was not equal expected for insert verification' + ); + // confirm updated item + assert.deepEqual( + await testUtils.getActualJson('testExisting_automation__s1.7', 'verification'), + await testUtils.getExpectedJson('9999999', 'verification', 'patch'), + 'returned existing-JSON was not equal expected for update verification' + ); + // check number of API calls + assert.equal( + testUtils.getAPIHistoryLength(), + 16, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + return; + }); + }); + + describe('Templating ================', () => { + it('Should create a verification template via buildTemplate and build it', async () => { + // download first before we test buildTemplate + await handler.retrieve('testInstance/testBU', ['verification']); + // buildTemplate + const result = await handler.buildTemplate( + 'testInstance/testBU', + 'verification', + ['testExisting_automation__s1.7'], + ['testSourceMarket'] + ); + assert.equal(process.exitCode, 0, 'buildTemplate should not have thrown an error'); + assert.equal( + result.verification ? Object.keys(result.verification).length : 0, + 1, + 'only one verification expected' + ); + assert.deepEqual( + await testUtils.getActualTemplateJson( + 'testExisting_automation__s1.7', + 'verification' + ), + await testUtils.getExpectedJson('9999999', 'verification', 'template'), + 'returned template JSON was not equal expected' + ); + // buildDefinition + await handler.buildDefinition( + 'testInstance/testBU', + 'verification', + ['testExisting_automation__s1.7'], + ['testTargetMarket'] + ); + assert.equal(process.exitCode, 0, 'buildDefinition should not have thrown an error'); + assert.deepEqual( + await testUtils.getActualDeployJson( + 'testTemplated_automation__s1.7', + 'verification' + ), + await testUtils.getExpectedJson('9999999', 'verification', 'build'), + 'returned deployment JSON was not equal expected' + ); + assert.equal( + testUtils.getAPIHistoryLength(), + 14, + 'Unexpected number of requests made. Run testUtils.logAPIHistoryDebug() to see the requests' + ); + return; + }); + }); + + describe('Delete ================', () => { + it('Should delete the item', async () => { + // WHEN + const isDeleted = await handler.deleteByKey( + 'testInstance/testBU', + 'verification', + 'testExisting_39f6a488-20eb-4ba0-b0b9' + ); + // THEN + assert.equal( + process.exitCode, + 0, + 'deleteByKey should have thrown an error due to lack of support' + ); + assert.equal(isDeleted, true, 'deleteByKey should have returned true for success'); + return; + }); + }); +}); diff --git a/test/util/file.js b/test/util/file.js deleted file mode 100644 index 9360222db..000000000 --- a/test/util/file.js +++ /dev/null @@ -1,51 +0,0 @@ -const assert = require('chai').assert; -const File = require('../../lib/util/file'); -const fs = require('fs-extra'); -const path = require('path'); - -const dataDir = 'test_tmp/file/'; - -describe('File', () => { - after(() => { - fs.removeSync(dataDir); - }); - describe('#writeJSONToFile()', () => { - it('should create json file and directory', async () => { - assert.strictEqual(fs.existsSync(dataDir + 'test1.json'), false); - const jsonContent = { - string: 'abc', - boolean: true, - number: 5, - array: ['asd', 4, 'asdf'], - obj: { - name: 'object', - }, - }; - await File.writeJSONToFile(dataDir, 'test1', jsonContent); - assert.deepEqual(fs.readJSONSync(dataDir + 'test1.json'), jsonContent); - }); - }); - describe('#copyFile()', () => { - it('should copy file from one path to another', async () => { - const source = path.join(dataDir, 'sourceFile.txt'); - const target = path.join(dataDir, 'targetFile.txt'); - fs.writeFileSync(source, 'filecontent'); - assert.strictEqual(fs.existsSync(source), true); - await File.copyFile(source, target); - assert.strictEqual(fs.existsSync(target), true); - assert.deepEqual(fs.readFileSync(source), fs.readFileSync(target)); - }); - it("should skip copy if source file doesn't exist", async () => { - const source = path.join(dataDir, 'doesnt_exist_source.txt'); - const target = path.join(dataDir, 'doesnt_exist_target.txt'); - assert.strictEqual(fs.existsSync(source), false); - const result = await File.copyFile(source, target); - assert.strictEqual(fs.existsSync(target), false); - assert.deepEqual(result, { - status: 'skipped', - statusMessage: 'deleted from repository', - file: source, - }); - }); - }); -}); diff --git a/test/utils.js b/test/utils.js new file mode 100644 index 000000000..198cd3459 --- /dev/null +++ b/test/utils.js @@ -0,0 +1,426 @@ +import File from '../lib/util/file.js'; +import path from 'node:path'; +import MockAdapter from 'axios-mock-adapter'; +import { axiosInstance } from '../node_modules/sfmc-sdk/lib/util.js'; +import handler from '../lib/index.js'; +import auth from '../lib/util/auth.js'; +import { Util } from '../lib/util/util.js'; +import cache from '../lib/util/cache.js'; +import ReplaceContentBlockReference from '../lib/util/replaceContentBlockReference.js'; +import MetadataTypes from '../lib/MetadataTypeInfo.js'; + +import { fileURLToPath } from 'node:url'; +const __dirname = path.dirname(fileURLToPath(import.meta.url)); + +// for some reason doesnt realize below reference + +import fsmock from 'mock-fs'; + +let apimock; +import { + handleSOAPRequest, + handleRESTRequest, + soapUrl, + restUrl, + tWarn, +} from './resourceFactory.js'; +const authResources = File.readJsonSync(path.join(__dirname, './resources/auth.json')); + +const loadingFile = 'loading expected file:///' + __dirname.split(path.sep).join('/'); + +/** + * gets file from Retrieve folder + * + * @param {string} from source path (starting in bu folder) + * @param {string} to target path (starting in bu folder) + * @param {string} [mid] used when we need to test on ParentBU + * @returns {Promise.<{status:'ok'|'skipped'|'failed', statusMessage:string, file:string}>} - + */ +export async function copyFile(from, to, mid = '9999999') { + return File.copyFileSimple(`./test/resources/${mid}/${from}`, `./test/resources/${mid}/${to}`); +} + +/** + * gets file from Retrieve folder + * + * @param {string} from source path (starting in bu folder) + * @param {string} to target path (starting in bu folder) + * @param {string} [mid] used when we need to test on ParentBU + * @param {string} [buName] used when we need to test on ParentBU + * @returns {void} - + */ +export function copyToDeploy(from, to, mid = '9999999', buName = 'testBU') { + console.log(`Copying ${from} to deploy folder`); // eslint-disable-line no-console + File.copySync(`./test/resources/${mid}/${from}`, `./deploy/testInstance/${buName}/${to}`); +} + +/** + * gets file from Retrieve folder + * + * @param {string} customerKey of metadata + * @param {string} type of metadata + * @param {string} [buName] used when we need to test on ParentBU + * @returns {Promise.<string>} file in string form + */ +export function getActualJson(customerKey, type, buName = 'testBU') { + return File.readJSON( + `./retrieve/testInstance/${buName}/${type}/${customerKey}.${type}-meta.json` + ); +} + +/** + * gets file from Retrieve folder + * + * @param {string} customerKey of metadata + * @param {string} type of metadata + * @param {string} [buName] used when we need to test on ParentBU + * @returns {Promise.<string>} file path + */ +export function getActualDoc(customerKey, type, buName = 'testBU') { + return File.readFile( + `./retrieve/testInstance/${buName}/${type}/${customerKey}.${type}-doc.md`, + 'utf8' + ); +} + +/** + * gets file from Retrieve folder + * + * @param {string} customerKey of metadata + * @param {string} type of metadata + * @param {string} ext file extension + * @param {string} [buName] used when we need to test on ParentBU + * @returns {Promise.<string | null>} file in string form, null if not found + */ +export async function getActualFile(customerKey, type, ext, buName = 'testBU') { + const path = `./retrieve/testInstance/${buName}/${type}/${customerKey}.${type}-meta.${ext}`; + try { + return await File.readFile(path, 'utf8'); + } catch { + console.log(`File not found: ${path}`); // eslint-disable-line no-console + return null; + } +} + +/** + * gets file from Deploy folder + * + * @param {string} customerKey of metadata + * @param {string} type of metadata + * @param {string} [buName] used when we need to test on ParentBU + * @returns {Promise.<string>} file in JSON form + */ +export function getActualDeployJson(customerKey, type, buName = 'testBU') { + return File.readJSON( + `./deploy/testInstance/${buName}/${type}/${customerKey}.${type}-meta.json` + ); +} + +/** + * gets file from Deploy folder + * + * @param {string} customerKey of metadata + * @param {string} type of metadata + * @param {string} ext file extension + * @param {string} [buName] used when we need to test on ParentBU + * @returns {Promise.<string>} file in string form + */ +export function getActualDeployFile(customerKey, type, ext, buName = 'testBU') { + return File.readFile( + `./deploy/testInstance/${buName}/${type}/${customerKey}.${type}-meta.${ext}`, + 'utf8' + ); +} + +/** + * gets file from Template folder + * + * @param {string} customerKey of metadata + * @param {string} type of metadata + * @returns {Promise.<string>} file in JSON form + */ +export function getActualTemplateJson(customerKey, type) { + return File.readJSON(`./template/${type}/${customerKey}.${type}-meta.json`); +} + +/** + * gets file from Template folder + * + * @param {string} customerKey of metadata + * @param {string} type of metadata + * @param {string} ext file extension + * @returns {Promise.<string>} file in string form + */ +export function getActualTemplateFile(customerKey, type, ext) { + return File.readFile(`./template/${type}/${customerKey}.${type}-meta.${ext}`, 'utf8'); +} + +/** + * gets file from resources folder which should be used for comparison + * + * @param {string} mid of Business Unit + * @param {string} type of metadata + * @param {string} action of SOAP request + * @returns {Promise.<string>} file in JSON form + */ +export function getExpectedJson(mid, type, action) { + const path = `/resources/${mid}/${type}/${action}-expected.json`; + console.log(loadingFile + path); // eslint-disable-line no-console + return File.readJSON(`./test` + path); +} + +/** + * gets file from resources folder which should be used for comparison + * + * @param {string} mid of Business Unit + * @param {string} type of metadata + * @param {string} action of SOAP request + * @param {string} ext file extension + * @returns {Promise.<string>} file in string form + */ +export function getExpectedFile(mid, type, action, ext) { + const path = `/resources/${mid}/${type}/${action}-expected.${ext}`; + console.log(loadingFile + path); // eslint-disable-line no-console + return File.readFile(`./test` + path, 'utf8'); +} + +/** + * setup mocks for API and FS + * + * @param {boolean} [isDeploy] if true, will mock deploy folder + * @returns {void} + */ +export function mockSetup(isDeploy) { + cache.clearCache(); + // clear local caches + for (const type of Object.keys(MetadataTypes)) { + if (MetadataTypes[type].cache) { + // we rarely use a local cache in types which also needs to be reset + MetadataTypes[type].cache = {}; + } + } + // no need to execute this again if we ran it a 2nd time for deploy - already done in standard setup + if (!isDeploy) { + // reset all options to default + const resetOptions = {}; + // get known options and make sure none are set + for (const option in handler.knownOptions) { + resetOptions[option] = undefined; + } + // test config + resetOptions.debug = true; + resetOptions.noLogFile = true; + + handler.setOptions(resetOptions); + } + File.prettierConfig = null; + + apimock = new MockAdapter(axiosInstance, { onNoMatch: 'throwException' }); + // set access_token to mid to allow for autorouting of mock to correct resources + apimock.onPost(authResources.success.url).reply((config) => { + authResources.success.response.access_token = JSON.parse(config.data).account_id; + return [authResources.success.status, authResources.success.response]; + }); + apimock.onPost(soapUrl).reply((config) => handleSOAPRequest(config)); + apimock + .onAny(new RegExp(`^${escapeRegExp(restUrl)}`)) + .reply((config) => handleRESTRequest(config)); + const fsMockConf = { + '.beautyamp.json': fsmock.load( + path.resolve(__dirname, '../boilerplate/files/.beautyamp.json') + ), + '.prettierrc': fsmock.load(path.resolve(__dirname, '../boilerplate/files/.prettierrc')), + 'eslint.config.js': fsmock.load( + path.resolve(__dirname, '../boilerplate/files/eslint.config.js') + ), + '.mcdevrc.json': fsmock.load(path.resolve(__dirname, 'mockRoot/.mcdevrc.json')), + '.mcdev-auth.json': fsmock.load(path.resolve(__dirname, 'mockRoot/.mcdev-auth.json')), + '.mcdev-validations.js': fsmock.load( + path.resolve(__dirname, 'mockRoot/.mcdev-validations.js') + ), + 'boilerplate/config.json': fsmock.load( + path.resolve(__dirname, '../boilerplate/config.json') + ), + test: fsmock.load(path.resolve(__dirname)), + // the following node_modules are required for prettier's SQL parser to work + 'node_modules/prettier': fsmock.load(path.resolve(__dirname, '../node_modules/prettier')), + 'node_modules/prettier-plugin-sql': fsmock.load( + path.resolve(__dirname, '../node_modules/prettier-plugin-sql') + ), + 'node_modules/beauty-amp-core2': fsmock.load( + path.resolve(__dirname, '../node_modules/beauty-amp-core2') + ), + 'node_modules/node-sql-parser': fsmock.load( + path.resolve(__dirname, '../node_modules/node-sql-parser') + ), + 'node_modules/big-integer': fsmock.load( + path.resolve(__dirname, '../node_modules/big-integer') + ), + 'node_modules/sql-formatter': fsmock.load( + path.resolve(__dirname, '../node_modules/sql-formatter') + ), + 'node_modules/jsox': fsmock.load(path.resolve(__dirname, '../node_modules/jsox')), + 'node_modules/nearley': fsmock.load(path.resolve(__dirname, '../node_modules/nearley')), + }; + if (isDeploy) { + // load files we manually prepared for a direct test of `deploy` command + fsMockConf.deploy = fsmock.load(path.resolve(__dirname, 'mockRoot/deploy')); + } + fsmock(fsMockConf); + + // ! reset exitCode or else tests could influence each other; do this in mockSetup to to ensure correct starting value + process.exitCode = 0; +} + +/** + * resets mocks for API and FS + * + * @returns {void} + */ +export function mockReset() { + // remove all options that might have been set by previous tests + for (const key in Util.OPTIONS) { + if (Object.prototype.hasOwnProperty.call(Util.OPTIONS, key)) { + delete Util.OPTIONS[key]; + } + } + // avoid spillover from other tests + ReplaceContentBlockReference.resetCacheMap(); + // reset sfmc login + auth.clearSessions(); + fsmock.restore(); + apimock.restore(); +} + +/** + * helper to return amount of api callouts + * + * @param {boolean} [includeToken] if true, will include token calls in count + * @returns {object} of API history + */ +export function getAPIHistoryLength(includeToken) { + const historyArr = Object.values(apimock.history).flat(); + if (includeToken) { + return historyArr.length; + } + return historyArr.filter((item) => item.url !== '/v2/token').length; +} + +/** + * helper to return api history + * + * @returns {object} of API history + */ +export function getAPIHistory() { + return apimock.history; +} + +/** + * + * @param {'patch'|'delete'|'post'|'get'|'put'} method http method + * @param {string} url url without domain, end on % if you want to search with startsWith() + * @param {boolean} returnAll useful for post requests that often have multiple callouts with the same url + * @returns {object} json payload of the request + */ +export function getRestCallout(method, url, returnAll = false) { + if (!apimock.history[method]?.length) { + console.log(`${tWarn} No history for method ${method}.`); // eslint-disable-line no-console + const methods = Object.keys(apimock.history) + .filter((el) => apimock.history[el]?.length) + .join(', '); + console.error(`Available methods: ${methods}`); // eslint-disable-line no-console + return null; + } + const subset = apimock.history[method]; + + /** + * helper for filter/find + * + * @param {any} item history item + * @returns {boolean} if item matches + */ + function findCallout(item) { + return url.endsWith('%') ? item.url.startsWith(url.slice(0, -1)) : item.url === url; + } + + const myCallout = returnAll ? subset.filter(findCallout) : subset.find(findCallout); + if (!myCallout) { + console.error(`${tWarn} No callout found for ${method} ${url}`); // eslint-disable-line no-console + const urls = [...new Set(subset.map((el) => el.url))].join('\n- '); + const methods = Object.keys(apimock.history) + .filter((el) => apimock.history[el]?.length) + .join(', '); + console.error(`Available methods: ${methods}`); // eslint-disable-line no-console + console.error(`Available unique urls in method ${method}:\n- ${urls}`); // eslint-disable-line no-console + return null; + } + return returnAll ? myCallout.map((el) => JSON.parse(el.data)) : JSON.parse(myCallout.data); +} + +/** + * + * @param {'Schedule'|'Retrieve'|'Create'|'Update'|'Delete'|'Describe'|'Execute'} requestAction soap request types + * @param {string} [objectType] optionall filter requests by object + * @returns {object[]} json payload of the requests + */ +export function getSoapCallouts(requestAction, objectType) { + const method = 'post'; + const url = '/Service.asmx'; + const subset = apimock.history[method]; + const myCallout = subset + // find soap requests + .filter((item) => item.url === url) + // find soap requestst of the correct request type + .filter((item) => item.headers.SOAPAction === requestAction) + // find soap requestst of the correct request type + .filter((item) => + !objectType || item.data.includes('<ObjectType') + ? item.data.split('<ObjectType>')[1].split('</ObjectType>')[0] === objectType + : item.data.includes('<Objects xsi:type="') + ? item.data.split('<Objects xsi:type="')[1].split('">')[0] === objectType + : false + ) + .map((item) => item.data); + if (!myCallout) { + console.error(`${tWarn} No callout found for ${requestAction} ${objectType || ''}`); // eslint-disable-line no-console + return null; + } + return myCallout; +} + +/** + * helper to return most important fields for each api call + * + * @returns {object} of API history + */ +export function getAPIHistoryDebug() { + const historyArr = Object.values(apimock.history) + .flat() + .map((item) => { + const log = { method: item.method, url: item.url }; + if (item.data) { + log.body = item.data; + } + return log; + }); + return historyArr; +} + +/** + * helper to return most important fields for each api call + * + * @returns {void} of API history + */ +export function logAPIHistoryDebug() { + console.log(getAPIHistoryDebug()); // eslint-disable-line no-console +} + +/** + * escapes string for regex + * + * @param {string} str to escape + * @returns {string} escaped string + */ +function escapeRegExp(str) { + return str.replaceAll(/[.*+?^${}()|[\]\\]/g, String.raw`\$&`); // $& means the whole matched string +} diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 000000000..a3d6c6a40 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,26 @@ +{ + // Change this to match your project + "include": ["lib/**/*.js", "types/**/*.js", "test/**/*.js"], + "compilerOptions": { + "module": "nodenext", + "moduleResolution": "nodenext", + "checkJs": true, + "skipLibCheck": true, + "target": "es2023", + // Tells TypeScript to read JS files, as + // normally they are ignored as source files + "allowJs": true, + // Generate d.ts files + "declaration": true, + // This compiler run should + // only output d.ts files + "emitDeclarationOnly": true, + // Types should go into this directory. + // Removing this would place the .d.ts files + // next to the .js files + "outDir": "@types", + // go to js file when using IDE functions like + // "Go to Definition" in VSCode + "declarationMap": true + } +} diff --git a/tsconfig.npmScripts.json b/tsconfig.npmScripts.json new file mode 100644 index 000000000..350156668 --- /dev/null +++ b/tsconfig.npmScripts.json @@ -0,0 +1,12 @@ +{ + "include": ["lib/**/*.js", "types/**/*.js", "test/**/*.js"], + "exclude": ["node_modules"], + "compilerOptions": { + "module": "nodenext", + "moduleResolution": "nodenext", + "target": "es2023", + "checkJs": true, + "skipLibCheck": true, + "noEmit": true + } +} diff --git a/tsconfig.precommit.json b/tsconfig.precommit.json new file mode 100644 index 000000000..539d2c528 --- /dev/null +++ b/tsconfig.precommit.json @@ -0,0 +1,26 @@ +{ + // Change this to match your project + "include": ["lib/**/*.js"], + "compilerOptions": { + "module": "nodenext", + "moduleResolution": "nodenext", + "target": "es2023", + "checkJs": true, + "skipLibCheck": true, + // Tells TypeScript to read JS files, as + // normally they are ignored as source files + "allowJs": true, + // Generate d.ts files + "declaration": true, + // This compiler run should + // only output d.ts files + "emitDeclarationOnly": true, + // Types should go into this directory. + // Removing this would place the .d.ts files + // next to the .js files + "outDir": "@types", + // go to js file when using IDE functions like + // "Go to Definition" in VSCode + "declarationMap": true + } +} diff --git a/types/mcdev.d.js b/types/mcdev.d.js new file mode 100644 index 000000000..3e5cfdeda --- /dev/null +++ b/types/mcdev.d.js @@ -0,0 +1,777 @@ +/** + * @typedef {object} BuObject + * @property {string} [clientId] installed package client id + * @property {string} [clientSecret] installed package client secret + * @property {string} [tenant] subdomain part of Authentication Base Uri + * @property {number} [eid] Enterprise ID = MID of the parent BU + * @property {number} [mid] MID of the BU to work with + * @property {string} [businessUnit] name of the BU to interact with + * @property {string} [credential] name of the credential to interact with + */ + +/** + * @typedef {Object.<string, string>} TemplateMap + * @typedef {'asset'|'asset-archive'|'asset-asset'|'asset-audio'|'asset-block'|'asset-code'|'asset-document'|'asset-image'|'asset-message'|'asset-other'|'asset-rawimage'|'asset-template'|'asset-textfile'|'asset-video'|'attributeGroup'|'attributeSet'|'automation'|'campaign'|'contentArea'|'dataExtension'|'dataExtensionField'|'dataExtensionTemplate'|'dataExtract'|'dataExtractType'|'discovery'|'deliveryProfile'|'email'|'emailSend'|'event'|'fileLocation'|'fileTransfer'|'filter'|'folder'|'importFile'|'journey'|'list'|'mobileCode'|'mobileKeyword'|'mobileMessage'|'query'|'role'|'script'|'sendClassification'|'senderProfile'|'transactionalEmail'|'transactionalPush'|'transactionalSMS'|'triggeredSend'|'user'|'verification'} SupportedMetadataTypes + * @typedef {Object.<string, string[] | null>} TypeKeyCombo object-key=SupportedMetadataTypes, value=array of external keys + */ + +/** + * @typedef {Object.<any, any>} MetadataTypeItem generic metadata item + * @typedef {Object.<string, MetadataTypeItem>} MetadataTypeMap key=customer key + * @typedef {Object.<string, MetadataTypeMap>} MultiMetadataTypeMap key=Supported MetadataType + * @typedef {Object.<string, MetadataTypeItem[]>} MultiMetadataTypeList key=Supported MetadataType + * @typedef {{metadata: MetadataTypeMap, type: string}} MetadataTypeMapObj + * @typedef {{metadata: MetadataTypeItem, type: string}} MetadataTypeItemObj + * @typedef {Object.<number, MultiMetadataTypeMap>} Cache key=MID + * @typedef {{before: MetadataTypeItem, after: MetadataTypeItem}} MetadataTypeItemDiff used during update + */ + +/** + * @typedef {object} CodeExtractItem + * @property {MetadataTypeItem} json metadata of one item w/o code + * @property {CodeExtract[]} codeArr list of code snippets in this item + * @property {string[]} subFolder mostly set to null, otherwise list of subfolders + */ + +/** + * @typedef {object} CodeExtract + * @property {string[]} subFolder mostly set to null, otherwise subfolders path split into elements + * @property {string} fileName name of file w/o extension + * @property {string} fileExt file extension + * @property {string} content file content + * @property {'base64'} [encoding] optional for binary files + */ + +/** + * @typedef {object} QueryItem + * @property {string} name name + * @property {string} key key + * @property {string} description - + * @property {string} [targetId] Object ID of DE (removed before save) + * @property {string} targetKey key of target data extension + * @property {string} r__dataExtension_key key of target data extension + * @property {string} createdDate e.g. "2020-09-14T01:42:03.017" + * @property {string} modifiedDate e.g. "2020-09-14T01:42:03.017" + * @property {'Overwrite'|'Update'|'Append'} targetUpdateTypeName defines how the query writes into the target data extension + * @property {number} [targetUpdateTypeId] 0|1|2, mapped to targetUpdateTypeName via this.definition.targetUpdateTypeMapping + * @property {string} [targetDescription] Description DE (removed before save) + * @property {boolean} isFrozen looks like this is always set to false + * @property {string} [queryText] contains SQL query with line breaks converted to '\n'. The content is extracted during retrieval and written into a separate *.sql file + * @property {string} [categoryId] holds folder ID, replaced with r__folder_Path during retrieve + * @property {string} r__folder_Path folder path in which this DE is saved + * @property {string} [queryDefinitionId] Object ID of query + * @typedef {Object.<string, QueryItem>} QueryMap + */ + +/** + * @typedef {object} ScriptItem + * @property {string} name name + * @property {string} key key + * @property {string} description - + * @property {string} createdDate e.g. "2020-09-14T01:42:03.017" + * @property {string} modifiedDate e.g. "2020-09-14T01:42:03.017" + * @property {string} [script] contains script with line breaks converted to '\n'. The content is extracted during retrieval and written into a separate *.ssjs file + * @property {string} [categoryId] holds folder ID, replaced with r__folder_Path during retrieve + * @property {string} r__folder_Path folder path in which this DE is saved + * @typedef {Object.<string, ScriptItem>} ScriptMap + */ + +/** + * @typedef {Object.<string, any>} AssetItem + * @typedef {Object.<string, AssetItem>} AssetMap + * @typedef {'archive'|'asset'|'audio'|'block'|'code'|'document'|'image'|'message'|'other'|'rawimage'|'template'|'textfile'|'video'} AssetSubType + */ + +/** + * @typedef {object} DataExtensionFieldItem + * @property {string} [ObjectID] id + * @property {string} [CustomerKey] key in format [DEkey].[FieldName] + * @property {object} [DataExtension] - + * @property {string} DataExtension.CustomerKey key of DE + * @property {string} Name name of field + * @property {string} [Name_new] custom attribute that is only used when trying to rename a field from Name to Name_new + * @property {string} DefaultValue empty string for not set + * @property {true|false} IsRequired - + * @property {true|false} [IsNullable] opposite of IsRequired + * @property {true|false} IsPrimaryKey - + * @property {number} Ordinal 1, 2, 3, ... + * @property {'Text'|'Number'|'Date'|'Boolean'|'Decimal'|'EmailAddress'|'Phone'|'Locale'} FieldType can only be set on create + * @property {number|string} MaxLength field length + * @property {string} Scale the number of places after the decimal that the field can hold; example: "0","1", ... + */ + +/** + * @typedef {Object.<string, DataExtensionFieldItem>} DataExtensionFieldMap key: name of field, value: DataExtensionFieldItem + */ + +/** + * @typedef {object} DataExtensionItem + * @property {string} CustomerKey key + * @property {string} Name name + * @property {string} Description - + * @property {string} [CreatedDate] iso format + * @property {string} [ModifiedDate] iso format + * @property {true|false} IsSendable - + * @property {true|false} IsTestable - + * @property {object} SendableDataExtensionField - + * @property {string} SendableDataExtensionField.Name - + * @property {object} SendableSubscriberField - + * @property {string} SendableSubscriberField.Name - + * @property {DataExtensionFieldItem[]} Fields list of DE fields + * @property {'dataextension'|'salesforcedataextension'|'synchronizeddataextension'|'shared_dataextension'|'shared_salesforcedataextension'} r__folder_ContentType retrieved from associated folder + * @property {string} r__folder_Path folder path in which this DE is saved + * @property {string} [CategoryID] holds folder ID, replaced with r__folder_Path during retrieve + * @property {string} [r__dataExtensionTemplate_name] name of optionally associated DE template + * @property {object} [Template] - + * @property {string} [Template.CustomerKey] key of optionally associated DE teplate + * @property {string} RetainUntil empty string or US date + 12:00:00 AM + * @property {string} c__retainUntil YYYY-MM-DD + * @property {'none'|'allRecordsAndDataextension'|'allRecords'|'individialRecords'} [c__retentionPolicy] readable name of retention policy + * @property {number} [DataRetentionPeriodLength] number of days/weeks/months/years before retention kicks in + * @property {number} [DataRetentionPeriodUnitOfMeasure] 3:Days, 4:Weeks, 5:Months, 6:Years + * @property {string} [c__dataRetentionPeriodUnitOfMeasure] 3:Days, 4:Weeks, 5:Months, 6:Years + * @property {boolean} [RowBasedRetention] true for retention policy individialRecords + * @property {boolean} ResetRetentionPeriodOnImport ? + * @property {boolean} [DeleteAtEndOfRetentionPeriod] true for retention policy allRecords + */ + +/** + * @typedef {Object.<string, DataExtensionItem>} DataExtensionMap + */ + +/** + * @typedef {object} UserDocument + * @property {'User'|'Installed Package'|'Inactivated User'} TYPE - + * @property {string} [ID] equal to UserID; optional in update/create calls + * @property {string} UserID equal to ID; required in update/create calls + * @property {number} [AccountUserID] user.AccountUserID + * @property {number} c__AccountUserID copy of AccountUserID + * @property {string} CustomerKey user.CustomerKey + * @property {string} Name user.Name + * @property {string} Email user.Email + * @property {string} NotificationEmailAddress user.NotificationEmailAddress + * @property {boolean} ActiveFlag user.ActiveFlag === true ? '✓' : '-' + * @property {boolean} IsAPIUser user.IsAPIUser === true ? '✓' : '-' + * @property {boolean} MustChangePassword user.MustChangePassword === true ? '✓' : '-' + * @property {number} DefaultBusinessUnit default MID; BUName after we resolved it + * @property {number[]} c__AssociatedBusinessUnits associatedBus + * @property {object} [Roles] (API only) + * @property {object[]} [Roles.Role] roles (API only) + * @property {string[]} c__RoleNamesGlobal roles + * @property {string[]} UserPermissions userPermissions + * @property {string} LastSuccessfulLogin this.timeSinceDate(user.LastSuccessfulLogin) + * @property {string} CreatedDate user.CreatedDate + * @property {string} ModifiedDate user.ModifiedDate + * @property {object} Client - + * @property {number} [Client.ID] EID e.g:7281698 + * @property {number} [Client.ModifiedBy] AccountUserID of user who last modified this user + * @property {'User'|'Installed Package'} c__type - + * @property {boolean} [IsLocked] (API only) + * @property {boolean} [Unlock] used to unlock a user that has IsLocked === true + * @property {boolean} c__IsLocked_readOnly copy of IsLocked + * @property {string} c__TimeZoneName name of timezone + * @property {object} [TimeZone] (API only) + * @property {string} [TimeZone.Name] (API only) + * @property {string} [TimeZone.ID] (API only) + * @property {string} [Password] only used to set the password. cannot be retrieved + * @property {'en-US'|'fr-CA'|'fr-FR'|'de-DE'|'it-IT'|'ja-JP'|'pt-BR'|'es-419'|'es-ES'} c__LocaleCode fr-CA, en-US, ... + * @property {object} [Locale] (API only) + * @property {'en-US'|'fr-CA'|'fr-FR'|'de-DE'|'it-IT'|'ja-JP'|'pt-BR'|'es-419'|'es-ES'} [Locale.LocaleCode] (API only) + * @property {object} [SsoIdentity] - + * @property {Array|object} [SsoIdentities] - + */ + +/** + * @typedef {{before:UserDocument,after:UserDocument}} UserDocumentDiff + * @typedef {Object.<string, UserDocument>} UserDocumentMap key=customer key + */ + +/** + * @typedef {object} UserDocumentDocumentHelper + * @property {string} ActiveFlagDocs docs: user.ActiveFlag === true ? '✓' : '-' + * @property {string} IsAPIUserDocs docs: user.IsAPIUser === true ? '✓' : '-' + * @property {string} MustChangePasswordDocs docs: user.MustChangePassword === true ? '✓' : '-' + * @property {string} DefaultBusinessUnitDocs docs: default MID; BUName after we resolved it + * @property {string} RolesDocs docs: list of roles as concatenated string + * @property {string} AssociatedBusDocs docs: list of associated BUs as concatenated string + * @property {string | number} ModifiedBy docs: user name who last modified this user + * @property {string} TimeZoneName docs: name of timezone + * @property {string} IsLockedDocs docs: if the user cannot login + * @typedef {UserDocument & UserDocumentDocumentHelper} UserDocumentDocument + */ + +/** + * @typedef {object} AccountUserConfiguration + * @property {object} Client wrapper + * @property {number} Client.ID EID e.g:7281698 + * @property {string} [PartnerKey] empty string + * @property {number | string} ID User ID e.g:717133502 + * @property {string} [ObjectID] empty string + * @property {number} [Delete] 0,1 + * @property {BusinessUnitAssignmentConfiguration} BusinessUnitAssignmentConfiguration - + * @typedef {object} BusinessUnitAssignmentConfiguration + * @property {object} BusinessUnitIds wrapper + * @property {number[]|number} BusinessUnitIds.BusinessUnitId e.g:[518003624] + * @property {boolean} IsDelete assign BU if false, remove assignment if true + */ + +/** + * @typedef {object} AutomationActivity + * @property {string} r__key key of associated activity + * @property {string} [name] name (not key) of associated activity + * @property {string} [timeZone] used by wait activity if a specific time of day was set + * @property {number} [objectTypeId] Id of assoicated activity type; see this.definition.activityTypeMapping + * @property {string} [activityObjectId] Object Id of assoicated metadata item + * @property {number} [displayOrder] order within step; starts with 1 or higher number + * @property {string} r__type see this.definition.activityTypeMapping + */ + +/** + * @typedef {object} AutomationStep + * @property {string} name description + * @property {string} [annotation] equals AutomationStep.name + * @property {number} [step] step iterator; starts with 1 + * @property {number} [stepNumber] step iterator, automatically set during deployment + * @property {AutomationActivity[]} activities - + */ + +/** + * @typedef {object} AutomationSchedule REST format + * @property {string} id legacy id of schedule + * @property {number} typeId equals schedule.scheduleTypeId; upsert endpoint requires scheduleTypeId. retrieve endpoint returns typeId + * @property {number} [scheduleTypeId] equals schedule.typeId; upsert endpoint requires scheduleTypeId. retrieve endpoint returns typeId + * @property {string} startDate example: '2021-05-07T09:00:00' + * @property {string} endDate example: '2021-05-07T09:00:00' + * @property {string} icalRecur example: 'FREQ=DAILY;UNTIL=20790606T160000;INTERVAL=1' + * @property {string} [iCalRecur] same as icalRecur but returned by legacy-API; example: 'FREQ=DAILY;UNTIL=20790606T160000;INTERVAL=1' + * @property {string} timezoneName example: 'W. Europe Standard Time'; see this.definition.timeZoneMapping + * @property {string} [timeZone] same as timezoneName but returned by legacy-API; example: 'W. Europe Standard Time'; see this.definition.timeZoneMapping + * @property {string} [description] kept in legacy API only, exact description of what this schedule does + * @property {number} [timezoneId] see this.definition.timeZoneMapping + * @property {number} [timeZoneId] same as timezoneId but returned by legacy-API; see this.definition.timeZoneMapping + * @property {number} [rangeTypeId] ? + * @property {any} [pattern] ? + * @property {any} [scheduledTime] ? + * @property {string} [scheduledStatus] ? + */ + +/** + * @typedef {object} AutomationScheduleSoap SOAP format + * @property {string} [RecurrenceType] 'Minutely'|'Hourly'|'Daily'|'Weekly'|'Monthly'|'Yearly' + * @property {object} Recurrence - + * @property {object} [Recurrence.$] {'xsi:type': keyStem + 'lyRecurrence'} + * @property {'ByYear'} [Recurrence.YearlyRecurrencePatternType] * currently not supported by tool * + * @property {'ByMonth'} [Recurrence.MonthlyRecurrencePatternType] * currently not supported by tool * + * @property {'ByWeek'} [Recurrence.WeeklyRecurrencePatternType] * currently not supported by tool * + * @property {'ByDay'} [Recurrence.DailyRecurrencePatternType] - + * @property {'Interval'} [Recurrence.MinutelyRecurrencePatternType] - + * @property {'Interval'} [Recurrence.HourlyRecurrencePatternType] - + * @property {number} [Recurrence.YearInterval] 1..n * currently not supported by tool * + * @property {number} [Recurrence.MonthInterval] 1..n * currently not supported by tool * + * @property {number} [Recurrence.WeekInterval] 1..n * currently not supported by tool * + * @property {number} [Recurrence.DayInterval] 1..n + * @property {number} [Recurrence.HourInterval] 1..n + * @property {number} [Recurrence.MinuteInterval] 1..n + * @property {number} [_interval] internal variable for CLI output only + * @property {object} TimeZone - + * @property {number} TimeZone.ID AutomationSchedule.timezoneId + * @property {true} [TimeZone.IDSpecified] always true + * @property {string} [_timezoneString] internal variable for CLI output only + * @property {string} StartDateTime AutomationSchedule.startDate + * @property {string} [_StartDateTime] AutomationSchedule.startDate; internal variable for CLI output only + * @property {string} [EndDateTime] AutomationSchedule.endDate + * @property {'EndOn'|'EndAfter'} RecurrenceRangeType set to 'EndOn' if AutomationSchedule.icalRecur contains 'UNTIL'; otherwise to 'EndAfter' + * @property {number} [Occurrences] only exists if RecurrenceRangeType=='EndAfter' + */ + +/** + * @typedef {object} AutomationItem + * @property {string} id Object Id + * @property {string} [legacyId] legacy Object Id - used for handling notifications + * @property {string} [ObjectID] Object Id as returned by SOAP API + * @property {string} [programId] legacy id + * @property {string} key key (Rest API) + * @property {string} [CustomerKey] key (SOAP API) + * @property {string} [name] name (Rest API) + * @property {string} [Name] name (SOAP API) + * @property {any} [notifications] notifications + * @property {string} [description] - + * @property {'scheduled'|'triggered'|'automationtriggered'} [type] Starting Source = Schedule / File Drop + * @property {'scheduled'|'triggered'|'automationtriggered'} [automationType] Starting Source = Schedule / File Drop; from legacy api + * @property {'Scheduled'|'Running'|'Ready'|'Building'|'PausedSchedule'|'InactiveTrigger'} [status] automation status + * @property {number} [statusId] automation status + * @property {AutomationSchedule} [schedule] only existing if type=scheduled + * @property {object} [fileTrigger] only existing if type=triggered + * @property {string} fileTrigger.fileNamingPattern file name with placeholders + * @property {number} fileTrigger.fileNamePatternTypeId - + * @property {string} fileTrigger.folderLocationText where to look for the fileNamingPattern + * @property {boolean} fileTrigger.isPublished ? + * @property {boolean} fileTrigger.queueFiles ? + * @property {boolean} fileTrigger.triggerActive - + * @property {object} [automationTrigger] only existing if type=automationtriggered + * @property {object} [startSource] - + * @property {AutomationSchedule} [startSource.schedule] rewritten to AutomationItem.schedule + * @property {object} [startSource.fileDrop] rewritten to AutomationItem.fileTrigger + * @property {string} startSource.fileDrop.fileNamePattern file name with placeholders + * @property {number} startSource.fileDrop.fileNamePatternTypeId - + * @property {string} startSource.fileDrop.folderLocation - + * @property {boolean} startSource.fileDrop.queueFiles - + * @property {number} startSource.typeId - + * @property {AutomationStep[]} [steps] - + * @property {string} [r__folder_Path] folder path + * @property {string} [categoryId] holds folder ID, replaced with r__folder_Path during retrieve + * @property {string} [createdName] user name of person who created this automation + * @property {string} [createdDate] iso format + * @property {string} [modifiedName] user name of person who last modified this automation + * @property {string} [modifiedDate] iso format + * @property {string} [pausedName] user name of person who paused this automation + * @property {string} [pausedDate] iso format + */ + +/** + * @typedef {object} VerificationItem + * @property {string} dataVerificationDefinitionId ID / Key + * @property {'IsEqualTo'|'IsLessThan'|'IsGreaterThan'|'IsOutsideRange'|'IsInsideRange'|'IsNotEqualTo'|'IsNotLessThan'|'IsNotGreaterThan'|'IsNotOutsideRange'|'IsNotInsideRange'} verificationType key + * @property {number} value1 used for all verificationTypes; lower value for IsOutsideRange, IsInsideRange, IsNotOutsideRange, IsNotInsideRange + * @property {number} value2 only used for IsOutsideRange, IsInsideRange, IsNotOutsideRange, IsNotInsideRange; otherwise set to 0 + * @property {boolean} shouldStopOnFailure flag to stop automation if verification fails + * @property {boolean} shouldEmailOnFailure flag to send email if verification fails + * @property {string} notificationEmailAddress email address to send notification to; empty string if shouldEmailOnFailure=false + * @property {string} notificationEmailMessage email message to send; empty string if shouldEmailOnFailure=false + * @property {number} createdBy user id of creator + * @property {string} [targetObjectId] ObjectID of target data extension + * @property {string} r__dataExtension_key key of target data extension + * @property {string} c__automation_step custom key for verifications based on automation, step and activity number + */ + +/** + * @typedef {Object.<string, AutomationItem>} AutomationMap + * @typedef {{metadata:AutomationMap,type:string}} AutomationMapObj + * @typedef {{metadata:object | AutomationItem,type:string}} AutomationItemObj + * @typedef {object} McdevDeltaPkgItem + * @property {string} file relative path to file + * @property {number} changes changed lines + * @property {number} insertions added lines + * @property {number} deletions deleted lines + * @property {boolean} binary is a binary file + * @property {boolean} moved git thinks this file was moved + * @property {string} [fromPath] git thinks this relative path is where the file was before + * @property {string} type metadata type + * @property {string} externalKey key + * @property {string} name name + * @property {'move'|'add/update'|'delete'} gitAction what git recognized as an action + * @property {string} _credential mcdev credential name + * @property {string} _businessUnit mcdev business unit name inside of _credential + * @typedef {import('simple-git').DiffResultTextFile & McdevDeltaPkgItem} DeltaPkgItem + */ + +/** + * @typedef {import('sfmc-sdk/util').RestError} RestError + * @typedef {import('sfmc-sdk/util').SOAPError} SOAPError + * @typedef {SOAPError & RestError} SDKError + */ + +/** + * @typedef {object} SkipInteraction signals what to insert automatically for things usually asked via wizard + * @property {string} [client_id] client id of installed package + * @property {string} [client_secret] client secret of installed package + * @property {string} [auth_url] tenant specific auth url of installed package + * @property {number} [account_id] MID of the Parent Business Unit + * @property {string} [credentialName] how you would like the credential to be named + * @property {string} [gitRemoteUrl] URL of Git remote server + * @property {boolean} [fixKeysReretrieve] will trigger re-downloading latest versions of dependent types after fixing keys + * @property {string} [gitPush] used by mcdev init to directly push to a remote + * @property {string} [developmentBu] used by mcdev init to directly push to a remote + * @property {string} [downloadBUs] used by mcdev init to directly push to a remote + */ + +/** + * @typedef {object} FilterItem + * @property {number} categoryId folder id + * @property {string} [createdDate] - + * @property {string} customerKey key + * @property {string} destinationObjectId DE/List ID + * @property {1|2|3|4} destinationTypeId 1:SubscriberList, 2:DataExtension, 3:GroupWizard, 4:BehavioralData + * @property {string} filterActivityId ? + * @property {string} filterDefinitionId ObjectID of filterDefinition + * @property {string} modifiedDate - + * @property {string} name name + * @property {string} [description] - + * @property {string} sourceObjectId DE/List ID + * @property {null} resultGroupFolderId required for upsert; unknown purpose; set to null + * @property {null} resultGroupName required for upsert; unknown purpose; set to null + * @property {null} sourceId required for upsert; unknown purpose; set to null + * @property {1|2|3|4} sourceTypeId 1:SubscriberList, 2:DataExtension, 3:GroupWizard, 4:BehavioralData + * @property {1|2|3|4} [filterDefinitionSourceTypeId] seems to be a duplicate of sourceTypeId? + * @property {string} [resultDEDescription] description of destination DE + * @property {string} [resultDEName] name of destination DE + * @property {string} [resultDEKey] key of destination DE + * @property {number} statusId ? + * @property {string} [r__dataFilter_key] relationship to filterDefinition + * @property {string} [r__source_dataExtension_key] relationship to dataExtension source + * @property {string} [r__destination_dataExtension_key] relationship to dataExtension destination + * @property {string} [r__folder_Path] relationship to folder + * @typedef {Object.<string, FilterItem>} FilterMap + */ + +/** + * /automation/v1/filterdefinitions/<id> (not used) + * + * @typedef {object} AutomationFilterDefinitionItem + * @property {string} id object id + * @property {string} key external key + * @property {string} createdDate - + * @property {number} createdBy user id + * @property {string} createdName - + * @property {string} [description] (omitted by API if empty) + * @property {string} modifiedDate - + * @property {number} modifiedBy user id + * @property {string} modifiedName - + * @property {string} name name + * @property {string} categoryId folder id + * @property {string} filterDefinitionXml from REST API defines the filter in XML form + * @property {1|2} derivedFromType 1:list/profile attributes/measures, 2: dataExtension + * @property {boolean} isSendable ? + */ +/** + * /email/v1/filters/filterdefinition/<id> + * + * @typedef {object} DataFilterItem + * @property {string} id object id + * @property {string} key external key + * @property {string} createdDate date + * @property {number} createdBy user id + * @property {string} createdName name + * @property {string} [description] (omitted by API if empty) + * @property {string} lastUpdated date + * @property {number} lastUpdatedBy user id + * @property {string} lastUpdatedName name + * @property {string} name name + * @property {string} categoryId folder id + * @property {string} filterDefinitionXml from REST API defines the filter in XML form + * @property {1|2} derivedFromType 1:list/profile attributes/measures, 2: dataExtension + * @property {string} derivedFromObjectId Id of DataExtension - present if derivedFromType=2 + * @property {'DataExtension'|'SubscriberAttributes'} derivedFromObjectTypeName - + * @property {string} [derivedFromObjectName] name of DataExtension + * @property {boolean} isSendable ? + * @property {object} [c__filterDefinition] copied from SOAP API, defines the filter in readable form + * @property {FilterConditionSet} c__filterDefinition.ConditionSet - + * @property {string} [r__source_list_PathName] relationship to list source (if derivedFromType=1) + * @property {string} [r__source_dataExtension_key] relationship to dataExtension source (if derivedFromType=2) + */ +/** + * @typedef {object} FilterConditionSet + * @property {FilterCondition | FilterCondition[]} Condition - + * @property {FilterConditionSet} ConditionSet - + */ +/** + * @typedef {object} FilterCondition + * @property {'IsEmpty'|'IsNotEmpty'|'Equals'} Operator comparison operator (actually \@_Operator) + * @property {string} [ID] object id of field (actually \@_ID) + * @property {string} [Value] filter value to compare against + * @property {string} [r__dataExtensionField_name] name of field + */ +/** + * @typedef {Object.<string, DataFilterItem>} DataFilterMap + */ + +/** + * @typedef {object} AuthObject + * @property {string} client_id client_id client_id for sfmc-sdk auth + * @property {string} client_secret client_secret for sfmc-sdk auth + * @property {number} account_id mid of business unit to auth against + * @property {string} auth_url authentication base url + */ + +/** + * @typedef {object} SoapRequestParams + * @property {string} [continueRequest] request id + * @property {object} [options] additional options (CallsInConversation, Client, ConversationID, Priority, RequestType, SaveOptions, ScheduledTime, SendResponseTo, SequenceCode) + * @property {*} [clientIDs] ? + * @property {SoapSDKFilter} [filter] simple or complex +complex + * @property {boolean} [QueryAllAccounts] all BUs or just one + */ + +/** + * @typedef {object} SoapFilterSimple + * @property {string} property field + * @property {'equals'|'notEquals'|'isNull'|'isNotNull'|'greaterThan'|'lessThan'|'greaterThanOrEqual'|'lessThanOrEqual'|'between'|'IN'|'in'|'like'} simpleOperator various options + * @property {string | number | boolean | string[] | number[]} [value] field value + */ + +/** + * @typedef {object} SoapFilterComplex + * @property {SoapSDKFilter} leftOperand string for simple or a new filter-object for complex + * @property {'AND'|'OR'} logicalOperator various options + * @property {SoapSDKFilter} rightOperand string for simple or a new filter-object for complex; omit for isNull and isNotNull + */ + +/** + * @typedef {object} SoapSDKFilterSimple + * @property {SoapFilterSimple["property"]} leftOperand string for simple or a new filter-object for complex + * @property {SoapFilterSimple["simpleOperator"]} operator various options + * @property {SoapFilterSimple["value"]} [rightOperand] string for simple or a new filter-object for complex; omit for isNull and isNotNull + */ + +/** + * @typedef {object} SoapSDKFilterComplex + * @property {SoapFilterComplex["leftOperand"]} leftOperand string for simple or a new filter-object for complex + * @property {SoapFilterComplex["logicalOperator"]} operator various options + * @property {SoapFilterComplex["rightOperand"]} rightOperand string for simple or a new filter-object for complex; omit for isNull and isNotNull + */ + +/** + * @typedef {SoapSDKFilterSimple | SoapSDKFilterComplex} SoapSDKFilter + */ + +/** + * @typedef {object} AssetRequestParams + * @property {string} [continueRequest] request id + * @property {object} [options] additional options (CallsInConversation, Client, ConversationID, Priority, RequestType, SaveOptions, ScheduledTime, SendResponseTo, SequenceCode) + * @property {*} [clientIDs] ? +complex + * @property {object} [page] pagination + * @property {string[]} [fields] list of fields we want returned + * @property {{property:string, direction: 'ASC'|'DESC'}[]} [sort] pagination + * @property {AssetFilter | AssetFilterSimple} [query] simple or complex filter + */ + +/** + * @typedef {object} AssetFilter + * @property {AssetFilter | AssetFilterSimple} leftOperand string for simple or a new filter-object for complex + * @property {'AND'|'OR'} logicalOperator various options + * @property {SoapSDKFilter | AssetFilterSimple} [rightOperand] string for simple or a new filter-object for complex; omit for isNull and isNotNull + */ + +/** + * @typedef {object} AssetFilterSimple + * @property {string} property field + * @property {'equal'|'notEquals'|'isNull'|'isNotNull'|'greaterThan'|'lessThan'|'greaterThanOrEqual'|'lessThanOrEqual'|'between'|'IN'|'in'|'like'} simpleOperator various options + * @property {string | number | boolean | Array} value field value + */ + +/** + * @typedef {object} Mcdevrc + * @property {object} credentials list of credentials + * @property {object} options configure options for mcdev + * @property {object} directories configure directories for mcdev to read/write to + * @property {string} directories.businessUnits "businessUnits/" + * @property {string} directories.deploy "deploy/" + * @property {string} directories.docs "docs/" + * @property {string} directories.retrieve "retrieve/" + * @property {string} directories.template "template/" + * @property {string} directories.templateBuilds ["retrieve/", "deploy/"] + * @property {Object.<string, object>} markets templating variables grouped by markets + * @property {object} marketList combination of markets and BUs for streamlined deployments + * @property {object} metaDataTypes templating variables grouped by markets + * @property {string[]} metaDataTypes.retrieve define what types shall be downloaded by default during retrieve + * @property {string[]} metaDataTypes.createDeltaPkg defines what types shall be passed to build() as part of running cdp + * @property {string[]} metaDataTypes.documentOnRetrieve which types should be parsed & documented after retrieve + * @property {string} version mcdev version that last updated the config file + */ + +/** + * @typedef {'error'|'verbose'|'info'|'debug'} LoggerLevel + * @typedef {object} McdevLogger + * @property {LoggerLevel} [level] (msg) print info message + * @property {(msg:string)=>void} error (msg) print error message; wrapper around winstonLogger.error that also sets error code to 1 + * @property {(ex:SDKError,message?:string)=>void} errorStack print error with trace message + * @typedef {import('winston').Logger & McdevLogger} Logger + */ + +/** + * @typedef {{id: number, key: string, name: string}} AssetItemSimple + * @typedef {Object.<string, AssetItemSimple>} AssetItemSimpleMap + * @typedef {Object.<number, AssetItemSimple>} AssetItemIdSimpleMap + * @typedef {'id'|'key'|'name'} ContentBlockConversionTypes + */ + +/** + * @typedef {object} ExplainType + * @property {string} name readable name of type + * @property {string} apiName api parameter name for type + * @property {string} description more info on what this type is about + * @property {boolean | string[]} retrieveByDefault is it retrieved by default OR list of subtypes that are retrieved by default + * @property {object} supports supported features + * @property {boolean} supports.retrieve can you download this type + * @property {boolean} supports.create can you create new records of this type + * @property {boolean} supports.update can you update records of this type + * @property {boolean} supports.delete can you delete records of this type + * @property {boolean} supports.changeKey can you change the key of existing records of this type + * @property {boolean} supports.buildTemplate can you apply templating on downloaded records of this type + * @property {boolean} supports.retrieveAsTemplate can you retrieve & template in one step + */ + +/** + * @typedef {object} ListItem + * @property {object} [Client] wrapper + * @property {number} Client.ID owning BU's MID + * @property {string} [PartnerKey] not used + * @property {string} [CreatedDate] "2021-06-21T11:54:57.103" + * @property {string} [ModifiedDate] "2021-06-21T11:54:57.103" + * @property {number} [ID] unique identifier per BU + * @property {string} [ObjectID] not used + * @property {string} [CustomerKey] unique identifer per BU + * @property {string} [Path] customn field that tracks the exact directory path of the current folder including its own name + * @property {object} [ParentFolder] wrapper + * @property {number} ParentFolder.ID folder id of parent folder; 0 if current folder is already on top level + * @property {string} [ParentFolder.ObjectID] not used + * @property {string} [ParentFolder.Path] customn field that tracks the exact directory path of the current folder including its own name + * @property {string} Name folder name + * @property {string} [Description] deprecated option to describe the folder content + * @property {string} ContentType e.g. "shared_data"; see folder-subtypes for complete list + * @property {boolean} IsActive ? + * @property {boolean} IsEditable option to disable renaming/moving this folder via GUI + * @property {boolean} AllowChildren option to prevent creating subfolders via GUI + * @property {boolean} [_generated] helper flag for Deployer class to signal if the folder was auto-generated or manually placed + * + * @typedef {Object.<number, ListItem>} ListIdMap key=id + * @typedef {Object.<string, ListItem>} ListMap key=customer key + */ + +/** + * @typedef {object} ReferenceObject returned by /data/v1/integration/member/salesforce/object/<OBJECT NAME>/referenceobjects + * @property {string} displayname label + * @property {string} referenceObjectName api name of salesforce object + * @property {string} relationshipName name of lookup/MD field on related object ending on __r (way to return fields from other object) + * @property {string} relationshipIdName name of lookup/MD field on related object ending on __c (returning id) + * @property {boolean} isPolymorphic if this lookup can point to multiple objects or not + * + * @typedef {object} SfObjectPicklist returned by /legacy/v1/beta/integration/member/salesforce/object/<OBJECT NAME> + * @property {boolean} active - + * @property {boolean} defaultValue - + * @property {string} label what you see in the GUI + * @property {string} value whats stored in the DB + */ + +/** + * @typedef {object} SfObjectField returned by /legacy/v1/beta/integration/member/salesforce/object/<OBJECT NAME> + * @property {string} label "Annual Revenue" + * @property {string} name "AnnualRevenue" + * @property {'currency'|'string'|'int'|'picklist'|'textarea'|'boolean'|'date'|'datetime'|'email'} datatype type + * @property {number} length 0-4000 + * @property {boolean} nillable == not required + * @property {boolean} custom is it a custom field + * @property {boolean} updateable always true? + * @property {boolean} createable always true? + * @property {boolean} defaultedoncreate - + * @property {boolean} externalid - + * @property {boolean} idlookup - + * @property {number} precision - + * @property {number} scale - + * @property {'Currency'|'Text'|'Number'|'Picklist'|'Text Area (long)'|'Checkbox'|'Date'|'Date/Time'|'Email'} displaydatatype "Currency" + * @property {string} objectname "Lead", + * @property {string} relationname "", + * @property {boolean} isnamefield - + * @property {SfObjectPicklist[]} [picklist] list of values + */ + +/** + * @typedef {object} configurationArguments + * @property {string} applicationExtensionKey SalesforceObjectTriggerV2 + * @property {string} version 3.0 + * @property {'Created'|'Updated'|'CreatedUpdated'} salesforceTriggerCriteria what record event in SF triggers this + * @property {object} eventDataConfig what objects are used by this event + * @property {eventDataConfigObject[]} eventDataConfig.objects list of sf objects with the fields that are used + * @property {Conditions} primaryObjectFilterCriteria TODO + * @property {Conditions} relatedObjectFilterCriteria TODO + * @property {object} [additionalObjectFilterCriteria] seems to only exist on journey but not on event and also not on every journey + * @property {object} contactKey defines how this event links to the all contacts list + * @property {string} contactKey.relationshipIdName Id / the __c field + * @property {string} contactKey.relationshipName Common / the __r field + * @property {boolean} contactKey.isPolymorphic false + * @property {string} contactKey.referenceObjectName Common + * @property {string} [contactKey.fieldName] if relationshipIdName points to a __c field then this tends to be set to "Id" + * @property {object} passThroughArgument TODO + * @property {object} passThroughArgument.fields TODO + * @property {string} passThroughArgument.fields.ContactKey CampaignMember:Common:Id + * @property {object} passThroughArgument.fields.Email CampaignMember:Common:Email; not affected by changing which field is to be used for email in the journey + * @property {string} [passThroughArgument.fields.HasOptedOutOfEmail] Contact:HasOptedOutOfEmail + * @property {string} primaryObjectFilterSummary primaryObjectFilterCriteria in simplified string-form + * @property {string} relatedObjectFilterSummary relatedObjectFilterCriteria in simplified string-form + * @property {string[]} eventDataSummary eventDataConfig in simplified string-form + * @property {'Created;'|'Updated;'|'Created;Updated;'} evaluationCriteriaSummary salesforceTriggerCriteria plus semi-colon + * @property {'CampaignMember'|'Contact'} contactPersonType if objectAPIName==CampaignMember then this is also CampaignMember; otherwise it's Contact + * @property {string} objectAPIName the SF object on which the salesforceTriggerCriteria is listening on + * @property {string} whoToInject "objectAPIName (Contact / Lead / Contacts and Leads)" + * @property {string} criteria empty string for SF events + * @property {number} schemaVersionId set to 0 for SF events + */ + +/** + * @typedef {object} eventDataConfigObject part of configurationArguments + * @property {string} dePrefix CampaignMember:Campaign: + * @property {boolean} isPolymorphic ? + * @property {string} referenceObject field on parent object containing the id; ends on __c for custom fields; same as referenceObject for standard fields; can be "Contacts and Leads" + * @property {string} relationshipName field on parent object acting as lookup; ends on __r for custom fields; same as referenceObject for standard fields; can be "Common" + * @property {string} [relationshipIdName] ? + * @property {string[]} fields list of field names that are used by this journey + */ +/** + * @typedef {object} Conditions part of configurationArguments + * @property {'AND'|'OR'} operand - + * @property {(Conditions | FieldCondition)[]} conditions list of conditions + */ +/** + * @typedef {object} FieldCondition part of configurationArguments + * @property {number} _length is 0 for booleans, otherwise field length + * @property {'currency'|'string'|'int'|'picklist'|'textarea'|'boolean'|'date'|'datetime'|'email'} datatype type + * @property {string} fieldName field API name; "TR1__Email__c" + * @property {string} folderId "CampaignMember-CampaignMember" + * @property {string} id "CampaignMember-CampaignMember-TR1__Email__c" + * @property {boolean} isPolymorphic ? + * @property {string} name likely the field label; "Email" + * @property {'equals'|'EQUALS'|'WASSET'} operator condition comparator + * @property {string} [value] value to compare the field with if operator is sth like "equals"; booleans are stored as upper-camel-case string! + * @property {number} precision ? + * @property {string} referenceObjectName "Contacts and Leads" + * @property {string} relationshipIdName "CommonId"; can be an empty string + * @property {string} relationshipName "Common"; can be an empty string + * @property {number} scale ? + * @property {string} text seems to be equal to name-attribute?; "Email" + */ +/** + * + * @callback validationRuleFix + * @returns {boolean|null} true = test passed; false = test failed & fixed; null = test failed & item removed to fix + * + * @callback validationRuleTest + * @returns {boolean} true = test passed; false = test failed + * + * @typedef {object} validationRule + * @property {string} failedMsg error message to display in case of a failed test + * @property {validationRuleTest} passed test to run + * @property {validationRuleFix} [fix] test to run + * + * @typedef {Object.<string, validationRule>} validationRuleList key=rule name + */ + +/** + * @typedef {object} DomainVerificationItem + * @property {number} [enterpriseId] EID + * @property {number} [memberId] MID + * @property {string} [domain] domain or email address used in retrieve and create + * @property {string} [emailAddress] email address used in update call for isSendable field + * @property {'Verified'|'Pending'} [status] returned by retrieve + * @property {'SAP'|'UserDomain'|'PrivateDomain'|'RegisteredDomain'} [domainType] returned by retrieve and required for update call + * @property {boolean} isSendable automatically true upon creation. can be changed to false via update + * @property {string} [emailSendTime] e.g. ""2023-06-19T11:11:17.32"" + * @property {string} [notificationEmail] for bulk-creation only: email address to send notifications to when done + * @property {string[]} [addresses] for bulk-creation only: list of email addresses to verify + * @property {string} [deTable] for bulk-creation only: instead of an array in addresses, specify the name of a DE + * @property {string} [deColumn] for bulk-creation only: instead of an array in addresses, specify the name of a DE column/field here + */ + +/** + * @typedef {object} BuildFilter + * @property {BuildFilterKeys} [include] include key filters + * @property {BuildFilterKeys} [exclude] exclude key filters + */ + +/** + * @typedef {object} BuildFilterKeys + * @property {Object.<"*"|SupportedMetadataTypes, string[]>} [key] object with keys representing metadata types ("*" for all types, or specific type names) and values being arrays of string patterns to match against + */ + +export default {};