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}
+
+
+
+ | Type |
+ {#if has_base_data}
+ Base |
+ {/if}
+ This PR |
+
+
+ {#each summary_list as { type, percent }}
+
+ | {type} |
+ {#if has_base_data}
+
+ {#if Number.isFinite(percent.base)}
+ {percent.base}%
+ {:else}
+ -
+ {/if}
+ |
+ {/if}
+
+ {#if Number.isFinite(percent.total)}
+ {percent.total}%
+ {#if has_base_data}
+ ({formatPercentDiff(percent.diff)})
+ {/if}
+ {:else}
+ -
+ {/if}
+ |
+
+ {/each}
+
+
+
+
+ Details (changed files):
+
+
+ | File |
+ Statements |
+ Branches |
+ Functions |
+ Lines |
+
+
+ {#each changed_files_coverage_data as [file, data]}
+ {@const percents = [
+ data.statements.pct,
+ data.branches.pct,
+ data.functions.pct,
+ data.lines.pct,
+ ]}
+
+ |
+ {file}
+ |
+ {#each percents as percent}
+
+ {#if Number.isFinite(percent)}
+ {percent}%
+ {:else}
+ -
+ {/if}
+ |
+ {/each}
+
+ {/each}
+
+
+
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] '
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.} -
+ */
+ static buildTemplate(businessUnit: string, selectedType: string, keyArr: string[], marketArr: string[]): Promise;
+ /**
+ * 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.} -
+ */
+ static buildDefinition(businessUnit: string, selectedType: string, nameArr: string[], marketArr: string[]): Promise;
+ /**
+ * 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.