eslint-plugin-sfmc 1.0.2 → 2.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -25,8 +25,41 @@ export default [
25
25
  ];
26
26
  ```
27
27
 
28
+ ## VS Code Setup
29
+
30
+ To see `eslint(sfmc/...)` diagnostics in VS Code for `.amp`, `.ssjs`, and `.html` files you need the [VS Code ESLint extension](https://marketplace.visualstudio.com/items?itemName=dbaeumer.vscode-eslint) to validate the custom SFMC language IDs.
31
+
32
+ **Option A — Install `vscode-sfmc-language`** (recommended)
33
+
34
+ The [SFMC Language Service extension](https://marketplace.visualstudio.com/items?itemName=joernberkefeld.sfmc-language) contributes the SFMC language IDs **and** automatically configures `eslint.validate` for you. No manual settings required.
35
+
36
+ **Option B — Manual configuration**
37
+
38
+ Add the following to your `.vscode/settings.json`:
39
+
40
+ ```json
41
+ {
42
+ "eslint.validate": [
43
+ "javascript",
44
+ "javascriptreact",
45
+ "typescript",
46
+ "typescriptreact",
47
+ "html",
48
+ "vue",
49
+ "markdown",
50
+ "ampscript",
51
+ "ssjs",
52
+ "sfmc"
53
+ ]
54
+ }
55
+ ```
56
+
57
+ > **Why `eslint.validate` and not `eslint.probe`?** `eslint.probe` silently skips files for language IDs that the ESLint extension does not natively recognise. `eslint.validate` forces the extension to process those files regardless of language ID.
58
+
28
59
  ## Configs
29
60
 
61
+ ### Marketing Cloud Engagement (default)
62
+
30
63
  | Config | Files | What it does |
31
64
  | -------------------------- | ---------------------------- | --------------------------------------------------------- |
32
65
  | `sfmc.configs.ampscript` | `**/*.ampscript`, `**/*.amp` | AMPscript rules only (recommended severity) |
@@ -37,6 +70,30 @@ export default [
37
70
 
38
71
  `recommended`, `embedded`, and `strict` are arrays — spread them with `...`.
39
72
 
73
+ ### Marketing Cloud Next
74
+
75
+ Use the `-next` config variants when targeting **Marketing Cloud Next (MCN)**. MCN supports only a subset of AMPscript functions and does **not** support SSJS at all.
76
+
77
+ | Config | Files | What it does |
78
+ | -------------------------------- | ---------------------------- | ----------------------------------------------------------------------------------------- |
79
+ | `sfmc.configs['ampscript-next']` | `**/*.ampscript`, `**/*.amp` | AMPscript rules + flags functions unsupported in MCN (single config object) |
80
+ | `sfmc.configs['ssjs-next']` | `**/*.ssjs` | Flags all SSJS API calls as MCN-unsupported; all other SSJS quality rules disabled |
81
+ | `sfmc.configs['recommended-next']` | Both of the above | AMPscript MCN-aware + SSJS flagged for standalone files |
82
+ | `sfmc.configs['embedded-next']` | `**/*.html` | AMPscript MCN-aware + SSJS flagged for HTML-embedded code |
83
+ | `sfmc.configs['strict-next']` | All of the above + HTML | All AMPscript rules at `error` severity + MCN flag; SSJS fully flagged |
84
+
85
+ `recommended-next`, `embedded-next`, and `strict-next` are arrays — spread them with `...`.
86
+
87
+ ```js
88
+ // eslint.config.js — targeting Marketing Cloud Next
89
+ import sfmc from 'eslint-plugin-sfmc';
90
+
91
+ export default [
92
+ ...sfmc.configs['recommended-next'],
93
+ ...sfmc.configs['embedded-next'],
94
+ ];
95
+ ```
96
+
40
97
  ## AMPscript Rules (`amp-*`)
41
98
 
42
99
  | Rule | Default | Description |
@@ -12,6 +12,8 @@
12
12
 
13
13
  AMPscript functions have fixed required and optional argument counts documented in the Salesforce catalog. Calling a function with too few arguments causes a runtime error. Calling it with too many can silently truncate or fail. This rule validates every call against the known min/max argument counts.
14
14
 
15
+ Several AMPscript functions are variadic: their trailing arguments repeat in fixed-size groups (for example `Concat` repeats a single value, while the DataExtension `UpdateData`/`UpsertData` family repeats column/value pairs). For these functions the catalog carries a `repeat` model describing where the repeating block starts, how many arguments form one group, and — for the Update/Upsert family — which earlier argument dictates how many search pairs precede the update pairs. This rule additionally reports `incompleteGroup` when the trailing arguments do not form complete groups.
16
+
15
17
  ## Settings
16
18
 
17
19
  | Setting | Values | Default |
@@ -32,6 +34,9 @@ This rule has no configuration options.
32
34
 
33
35
  /* Format accepts at most 3 arguments */
34
36
  set @val = Format(@num, "0.00", "en-US", "extra")
37
+
38
+ /* UpdateData: one search pair, then an incomplete update group (odd trailing args) */
39
+ UpdateData("MyDE", 1, "Key", @key, "Col", @v, "Orphan")
35
40
  ]%%
36
41
  ```
37
42
 
@@ -42,6 +47,9 @@ This rule has no configuration options.
42
47
  var @val
43
48
  set @val = Lookup("MyDE", "Value", "Key", @key)
44
49
  set @val = Format(@num, "0.00", "en-US")
50
+
51
+ /* UpdateData: one search pair + one update pair (complete groups) */
52
+ UpdateData("MyDE", 1, "Key", @key, "Col", @v)
45
53
  ]%%
46
54
  ```
47
55
 
@@ -5,22 +5,30 @@
5
5
  | | |
6
6
  |---|---|
7
7
  | **Type** | `problem` |
8
- | **Default severity** | `error` in `recommended` and `strict` |
8
+ | **Default severity** | `error` in `recommended`, `strict`, and all `-next` configs |
9
9
  | **Fixable** | — |
10
10
 
11
11
  ## Why This Rule Exists
12
12
 
13
13
  AMPscript does not support user-defined functions. Every function call must match a name in Salesforce's published catalog. Calling an unknown name causes a runtime error (or is silently ignored depending on the execution context), making the code unreliable. This rule catches typos and invented names before deployment.
14
14
 
15
+ When targeting **Marketing Cloud Next**, only a subset of AMPscript functions are supported. Use the `target: 'next'` option to flag functions that cannot run in MCN.
16
+
15
17
  ## Settings
16
18
 
17
19
  | Setting | Values | Default |
18
20
  |---------|--------|---------|
19
21
  | severity | `"error"` \| `"warn"` \| `"off"` | `"error"` |
20
22
 
21
- This rule has no configuration options.
23
+ ### Options
24
+
25
+ | Option | Type | Default | Description |
26
+ |--------|------|---------|-------------|
27
+ | `target` | `'engagement'` \| `'next'` | — | Target platform. Set to `'next'` to additionally flag AMPscript functions not available in Marketing Cloud Next (API v67.0+). |
28
+
29
+ ## Examples
22
30
 
23
- ### Examples
31
+ ### Standard usage (Marketing Cloud Engagement)
24
32
 
25
33
  **Not allowed:**
26
34
 
@@ -40,6 +48,37 @@ This rule has no configuration options.
40
48
  ]%%
41
49
  ```
42
50
 
51
+ ### MCN target
52
+
53
+ Configure the rule with `target: 'next'` to flag functions unsupported in Marketing Cloud Next:
54
+
55
+ ```js
56
+ // eslint.config.js
57
+ rules: {
58
+ 'sfmc/amp-no-unknown-function': ['error', { target: 'next' }]
59
+ }
60
+ ```
61
+
62
+ Or use the built-in `recommended-next` / `strict-next` / `embedded-next` configs which apply this automatically.
63
+
64
+ **Not allowed (with `target: 'next'`):**
65
+
66
+ ```ampscript
67
+ %%[
68
+ /* InsertDE is not supported in Marketing Cloud Next */
69
+ InsertDE("MyDE", "Col", "Value")
70
+ ]%%
71
+ ```
72
+
73
+ **Allowed (with `target: 'next'`):**
74
+
75
+ ```ampscript
76
+ %%[
77
+ /* UpsertDE is supported in Marketing Cloud Next */
78
+ UpsertDE("MyDE", 1, "Key", @key, "Col", "Value")
79
+ ]%%
80
+ ```
81
+
43
82
  ## When to Disable
44
83
 
45
84
  Only disable this rule if you are intentionally using a proprietary or undocumented SFMC extension that is not in the public catalog.
@@ -6,7 +6,7 @@
6
6
  |---|---|
7
7
  | **Type** | `suggestion` |
8
8
  | **Default severity** | `off` by default |
9
- | **Fixable** | |
9
+ | **Fixable** | **Auto-fix** (`eslint --fix`) |
10
10
 
11
11
  ## Why This Rule Exists
12
12
 
@@ -41,6 +41,16 @@ This rule has no configuration options.
41
41
  ]%%
42
42
  ```
43
43
 
44
+ ## Fix
45
+
46
+ This rule provides an **auto-fix**. Applied by:
47
+
48
+ - `eslint --fix` on the command line
49
+ - **Fix this issue** / **Fix all auto-fixable problems** in VS Code (requires the [ESLint extension](https://marketplace.visualstudio.com/items?itemName=dbaeumer.vscode-eslint))
50
+ - On save via `editor.codeActionsOnSave: { "source.fixAll.eslint": "explicit" }`
51
+
52
+ What the auto-fix does: inserts `var @variableName` on the line immediately before the first `set` that uses an undeclared `@variable`. Only the first occurrence of each variable receives a fix in a single `--fix` pass to avoid duplicate `var` lines.
53
+
44
54
  ## When to Disable
45
55
 
46
56
  This rule is off by default because undeclared `set` is valid AMPscript. Enable it for teams that want to enforce a strict declaration-first style.
@@ -6,7 +6,7 @@
6
6
  |---|---|
7
7
  | **Type** | `suggestion` |
8
8
  | **Default severity** | `warn` in `recommended`; `error` in `strict` |
9
- | **Fixable** | **Suggestion** (manual, via VS Code lightbulb) |
9
+ | **Fixable** | **Auto-fix** (`eslint --fix`) |
10
10
 
11
11
  ## Why This Rule Exists
12
12
 
@@ -44,12 +44,13 @@ for (var i = 0, _len = items.length; i < _len; i++) {
44
44
 
45
45
  ## Fix
46
46
 
47
- This rule provides a **suggestion** (not applied automatically). To apply it:
47
+ This rule provides an **auto-fix**. Applied by:
48
48
 
49
- - Click the **lightbulb** / press `Ctrl+.` on the flagged code in VS Code (requires the [ESLint extension](https://marketplace.visualstudio.com/items?itemName=dbaeumer.vscode-eslint))
50
- - `eslint --fix` does **not** apply suggestions (`--fix-type suggestion` filters fixable rules by rule category, it does **not** apply `hasSuggestions` suggestions)
49
+ - `eslint --fix` on the command line
50
+ - **Fix this issue** / **Fix all auto-fixable problems** in VS Code (requires the [ESLint extension](https://marketplace.visualstudio.com/items?itemName=dbaeumer.vscode-eslint))
51
+ - On save via `editor.codeActionsOnSave: { "source.fixAll.eslint": "explicit" }`
51
52
 
52
- What the suggestion does: appends `, _len = arr.length` to the last declarator in the `for` loop initialiser and replaces `arr.length` in the test condition with `_len`. The suggestion is only offered when the loop `init` is a `var` declaration (the typical case).
53
+ What the auto-fix does: appends `, _len = arr.length` to the last declarator in the `for` loop initialiser and replaces `arr.length` in the test condition with `_len`. The fix is only applied when the loop `init` is a `var` declaration (the typical case). Loops with other init forms (for example `for (i = 0; i < arr.length; i++)`) are still reported but not auto-fixed.
53
54
 
54
55
  ## When to Disable
55
56
 
@@ -1,4 +1,4 @@
1
- # ssjs-no-deprecated-function
1
+ # `sfmc/ssjs-no-deprecated-function`
2
2
 
3
3
  Flags calls to deprecated SFMC SSJS APIs. Currently focuses on the **Content Areas** feature,
4
4
  which has been retired and no longer allows creating or updating content.
@@ -1,4 +1,4 @@
1
- # ssjs-no-property-call
1
+ # `sfmc/ssjs-no-property-call`
2
2
 
3
3
  Flags `Platform.Request` and `Platform.Response` members that are **properties**, not functions.
4
4
  Calling them with parentheses `()` is a runtime error — they must be accessed without parentheses.
@@ -6,7 +6,7 @@ Calling them with parentheses `()` is a runtime error — they must be accessed
6
6
  The rule is fixable:
7
7
 
8
8
  - **No-arg calls** (`Property()`) → removes the `()` on both `Request` and `Response` properties.
9
- - **Single-arg calls on `Platform.Response.*`** (`ContentType("text/html")`) → rewrites to an assignment (`= value`), because those two properties are read/write.
9
+ - **Single-arg calls on `Platform.Response.*`** (`ContentType("text/html")`) → rewrites to an assignment (`= value`), including when the call appears in a comma (`SequenceExpression`) expression.
10
10
  - **Any-arg calls on `Platform.Request.*`** → reported as an error with no auto-fix, because `Request` properties are read-only.
11
11
 
12
12
  ## Properties affected
@@ -64,6 +64,12 @@ Platform.Response.ContentType = "application/json";
64
64
  Platform.Response.CharacterSet = "UTF-8";
65
65
  ```
66
66
 
67
+ Auto-fix also applies inside comma expressions:
68
+
69
+ ```js
70
+ Platform.Response.CharacterSet = "UTF-8", Platform.Response.Write("ok");
71
+ ```
72
+
67
73
  ### ❌ Incorrect — attempting to set a read-only `Platform.Request` property (no fix)
68
74
 
69
75
  ```js
@@ -1,4 +1,4 @@
1
- # ssjs-no-switch-default
1
+ # `sfmc/ssjs-no-switch-default`
2
2
 
3
3
  Disallow `default` case in `switch` statements.
4
4
 
@@ -1,4 +1,4 @@
1
- # ssjs-no-treatascontent-injection
1
+ # `sfmc/ssjs-no-treatascontent-injection`
2
2
 
3
3
  Disallow string concatenation inside `TreatAsContent()` calls.
4
4
 
@@ -1,7 +1,9 @@
1
- # ssjs-no-unknown-function
1
+ # `sfmc/ssjs-no-unknown-function`
2
2
 
3
3
  Flags calls to SFMC API methods that do not exist in the catalog. This single rule replaces the seven narrow `no-unknown-*` rules from earlier versions of the plugin.
4
4
 
5
+ When targeting **Marketing Cloud Next**, SSJS is not supported at all. Set `target: 'next'` to flag every SSJS API call as an error, signalling that the SSJS block must be removed or rewritten in AMPscript.
6
+
5
7
  ## Covered namespaces
6
8
 
7
9
  | Namespace | Example |
@@ -15,9 +17,17 @@ Flags calls to SFMC API methods that do not exist in the catalog. This single ru
15
17
  | Core Library instance methods | `de.Rows.Retrieve()` (tracked from `DataExtension.Init(…)`) |
16
18
  | WSProxy instance methods | `api.retrieve(…)` (tracked from `new Script.Util.WSProxy()`) |
17
19
 
20
+ ## Options
21
+
22
+ | Option | Type | Default | Description |
23
+ |--------|------|---------|-------------|
24
+ | `target` | `'engagement'` \| `'next'` | — | Target platform. Set to `'next'` to flag every SSJS API call (all of `Platform.*`, `HTTP.*`, Core Library, and WSProxy) as unsupported in Marketing Cloud Next. |
25
+
18
26
  ## Examples
19
27
 
20
- ### Incorrect
28
+ ### Standard usage (Marketing Cloud Engagement)
29
+
30
+ #### ❌ Incorrect
21
31
 
22
32
  ```js
23
33
  // Typo in Platform.Function method name
@@ -32,7 +42,7 @@ var de = DataExtension.Init('CustomerData');
32
42
  de.ExportRows();
33
43
  ```
34
44
 
35
- ### ✅ Correct
45
+ #### ✅ Correct
36
46
 
37
47
  ```js
38
48
  Platform.Function.LookupRows('MyDE', 'Status', 'Active');
@@ -44,14 +54,37 @@ var de = DataExtension.Init('CustomerData');
44
54
  de.Rows.Retrieve();
45
55
  ```
46
56
 
57
+ ### MCN target (`target: 'next'`)
58
+
59
+ SSJS is not supported in Marketing Cloud Next. Configuring `target: 'next'` flags every SFMC API call within SSJS files, indicating they must be rewritten or removed.
60
+
61
+ ```js
62
+ // eslint.config.js
63
+ rules: {
64
+ 'sfmc/ssjs-no-unknown-function': ['error', { target: 'next' }]
65
+ }
66
+ ```
67
+
68
+ Or use the built-in `recommended-next` / `strict-next` / `embedded-next` configs which apply this automatically (and disable all other SSJS quality rules, since the entire SSJS block must be migrated).
69
+
70
+ #### ❌ Flagged (with `target: 'next'`)
71
+
72
+ ```js
73
+ // All SFMC API calls are flagged — SSJS is not available in MCN
74
+ Platform.Function.LookupRows('MyDE', 'Status', 'Active');
75
+
76
+ var de = DataExtension.Init('CustomerData');
77
+ de.Rows.Retrieve();
78
+ ```
79
+
47
80
  ## When to use
48
81
 
49
- Enable this rule to catch typos, outdated method names, and unsupported API calls before
50
- they cause runtime failures.
82
+ Enable this rule to catch typos, outdated method names, and unsupported API calls before they cause runtime failures. Use `target: 'next'` when migrating content to Marketing Cloud Next.
51
83
 
52
84
  ## Rule details
53
85
 
54
86
  - **Type:** `problem`
55
87
  - **Fixable:** No
56
- - **Recommended:** Yes
57
- - **Strict:** Yes
88
+ - **Recommended:** Yes (`engagement` mode)
89
+ - **Strict:** Yes (`engagement` mode)
90
+ - **`recommended-next` / `strict-next` / `embedded-next`:** Yes (`next` mode — all other SSJS rules disabled)
@@ -6,7 +6,7 @@
6
6
  |---|---|
7
7
  | **Type** | `problem` |
8
8
  | **Default severity** | `error` in `recommended` and `strict` |
9
- | **Fixable** | **Auto-fix** for `let`/`const`; **Suggestion** for `??` |
9
+ | **Fixable** | **Auto-fix** for `let`/`const`, `??`, and direct object `return` |
10
10
 
11
11
  ## Why This Rule Exists
12
12
 
@@ -49,22 +49,19 @@ var value = (obj && obj.prop !== null && obj.prop !== undefined) ? obj.prop : "d
49
49
 
50
50
  ## Fix
51
51
 
52
- **Auto-fix** for `let` and `const` declarations. Applied by:
52
+ This rule provides **auto-fix** for selected features. Applied by:
53
53
 
54
54
  - `eslint --fix` on the command line
55
55
  - **Fix this issue** / **Fix all auto-fixable problems** in VS Code (requires the [ESLint extension](https://marketplace.visualstudio.com/items?itemName=dbaeumer.vscode-eslint))
56
56
  - On save via `editor.codeActionsOnSave: { "source.fixAll.eslint": "explicit" }`
57
57
 
58
- What the auto-fix does: replaces the `let` or `const` keyword with `var`, leaving the rest of the declaration unchanged.
58
+ What the auto-fix does:
59
59
 
60
- ---
60
+ - **`let` / `const` declarations** — replaces the keyword with `var`, leaving the rest of the declaration unchanged.
61
+ - **Nullish coalescing (`??`)** — replaces `??` with `||`. Note that `||` has different semantics — it also treats `0`, `""`, and `false` as falsy, unlike `??` which only replaces `null` and `undefined`.
62
+ - **Direct object literal `return`** — rewrites `return { … }` to assign the object to a temporary `var _result` and then `return _result`.
61
63
 
62
- **Suggestion** for nullish coalescing (`??`). Applied by:
63
-
64
- - Click the **lightbulb** / press `Ctrl+.` on the flagged code in VS Code (requires the ESLint extension)
65
- - `eslint --fix` does **not** apply suggestions (`--fix-type suggestion` filters fixable rules by rule category, it does **not** apply `hasSuggestions` suggestions)
66
-
67
- What the suggestion does: replaces `??` with `||`. Note that `||` has different semantics — it also treats `0`, `""`, and `false` as falsy, unlike `??` which only replaces `null` and `undefined`.
64
+ Other unsupported features (arrow functions, template literals, classes, etc.) have no auto-fix.
68
65
 
69
66
  ## Configuration Example
70
67
 
@@ -1,4 +1,4 @@
1
- # ssjs-prefer-parsejson-safe-arg
1
+ # `sfmc/ssjs-prefer-parsejson-safe-arg`
2
2
 
3
3
  Require concatenating an empty string to `Platform.Function.ParseJSON()` arguments.
4
4
 
@@ -6,7 +6,7 @@
6
6
  |---|---|
7
7
  | **Type** | `suggestion` |
8
8
  | **Default severity** | `warn` in `recommended`; `error` in `strict` |
9
- | **Fixable** | **Suggestion** (manual, via VS Code lightbulb) |
9
+ | **Fixable** | **Auto-fix** (`eslint --fix`) |
10
10
 
11
11
  ## Why This Rule Exists
12
12
 
@@ -42,12 +42,13 @@ for (var key in myObject) {
42
42
 
43
43
  ## Fix
44
44
 
45
- This rule provides a **suggestion** (not applied automatically). To apply it:
45
+ This rule provides an **auto-fix**. Applied by:
46
46
 
47
- - Click the **lightbulb** / press `Ctrl+.` on the flagged code in VS Code (requires the [ESLint extension](https://marketplace.visualstudio.com/items?itemName=dbaeumer.vscode-eslint))
48
- - `eslint --fix` does **not** apply suggestions (`--fix-type suggestion` filters fixable rules by rule category, it does **not** apply `hasSuggestions` suggestions)
47
+ - `eslint --fix` on the command line
48
+ - **Fix this issue** / **Fix all auto-fixable problems** in VS Code (requires the [ESLint extension](https://marketplace.visualstudio.com/items?itemName=dbaeumer.vscode-eslint))
49
+ - On save via `editor.codeActionsOnSave: { "source.fixAll.eslint": "explicit" }`
49
50
 
50
- What the suggestion does: wraps the entire loop body in an `if (obj.hasOwnProperty(key)) { … }` guard. When the body is already a block statement, the existing content is preserved inside the new `if`; when it is a single statement, a new block is created around it.
51
+ What the auto-fix does: wraps the entire loop body in an `if (obj.hasOwnProperty(key)) { … }` guard. When the body is already a block statement, the existing content is preserved inside the new `if`; when it is a single statement, a new block is created around it.
51
52
 
52
53
  ## When to Disable
53
54
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "eslint-plugin-sfmc",
3
- "version": "1.0.2",
3
+ "version": "2.1.0",
4
4
  "description": "ESLint plugin for Salesforce Marketing Cloud — AMPscript and Server-Side JavaScript (SSJS)",
5
5
  "type": "module",
6
6
  "main": "src/index.js",
@@ -32,7 +32,7 @@
32
32
  "sfmc"
33
33
  ],
34
34
  "dependencies": {
35
- "ampscript-data": "^0.2.0",
35
+ "ampscript-data": "^2.0.0",
36
36
  "ampscript-parser": "^0.1.3",
37
37
  "ssjs-data": "^0.4.0"
38
38
  },
@@ -40,7 +40,10 @@
40
40
  "eslint": ">=9.0.0"
41
41
  },
42
42
  "scripts": {
43
- "test": "node --test tests/rules.test.js",
43
+ "test": "node --test tests/rules.test.js && node --test tests/fixtures.test.mjs && node --test tests/autofix-manual.test.mjs",
44
+ "test:autofix-manual": "node --test tests/autofix-manual.test.mjs",
45
+ "test:fixtures": "node --test tests/fixtures.test.mjs",
46
+ "test:fixtures:update": "node --test tests/fixtures.test.mjs -- --update-snapshots",
44
47
  "lint": "eslint .",
45
48
  "lint:fix": "eslint --fix .",
46
49
  "prepare": "husky || true",
package/src/index.js CHANGED
@@ -121,6 +121,34 @@ const plugin = {
121
121
  configs: {},
122
122
  };
123
123
 
124
+ // ── MCN SSJS rule set (all SSJS rules off except ssjs-no-unknown-function) ────
125
+
126
+ /**
127
+ * SSJS rules for MCN targets.
128
+ * All quality rules are disabled — only the presence of SSJS is flagged,
129
+ * because SSJS as a whole must be deleted when targeting Marketing Cloud Next.
130
+ */
131
+ const ssjsMcnRules = {
132
+ 'sfmc/ssjs-no-unknown-function': ['error', { target: 'next' }],
133
+ 'sfmc/ssjs-require-platform-load': 'off',
134
+ 'sfmc/ssjs-no-unsupported-syntax': 'off',
135
+ 'sfmc/ssjs-no-deprecated-function': 'off',
136
+ 'sfmc/ssjs-no-property-call': 'off',
137
+ 'sfmc/ssjs-platform-function-arity': 'off',
138
+ 'sfmc/ssjs-cache-loop-length': 'off',
139
+ 'sfmc/ssjs-require-hasownproperty': 'off',
140
+ 'sfmc/ssjs-require-platform-load-order': 'off',
141
+ 'sfmc/ssjs-no-hardcoded-credentials': 'off',
142
+ 'sfmc/ssjs-prefer-platform-load-version': 'off',
143
+ 'sfmc/ssjs-no-unavailable-method': 'off',
144
+ 'sfmc/ssjs-prefer-parsejson-safe-arg': 'off',
145
+ 'sfmc/ssjs-no-switch-default': 'off',
146
+ 'sfmc/ssjs-no-treatascontent-injection': 'off',
147
+ 'sfmc/ssjs-arg-types': 'off',
148
+ 'sfmc/ssjs-core-method-arity': 'off',
149
+ 'no-cond-assign': 'off',
150
+ };
151
+
124
152
  // ── AMPscript rule sets ───────────────────────────────────────────────────────
125
153
 
126
154
  const ampRecommendedRules = {
@@ -340,6 +368,153 @@ Object.assign(plugin.configs, {
340
368
  rules: { ...ssjsStrictRules },
341
369
  },
342
370
  ],
371
+
372
+ // ── Marketing Cloud Next configs ──────────────────────────────────────────
373
+
374
+ /**
375
+ * AMPscript-only MCN config. Flags functions not supported in MCN.
376
+ * No SSJS portion (AMPscript-only config).
377
+ */
378
+ 'ampscript-next': {
379
+ name: 'sfmc/ampscript-next',
380
+ plugins: { sfmc: plugin },
381
+ languageOptions: { parser: ampscriptParser },
382
+ files: ['**/*.ampscript', '**/*.amp'],
383
+ rules: {
384
+ ...ampRecommendedRules,
385
+ 'sfmc/amp-no-unknown-function': ['error', { target: 'next' }],
386
+ },
387
+ },
388
+
389
+ /**
390
+ * SSJS-only MCN config. Flags all SSJS API calls; disables all other SSJS rules.
391
+ */
392
+ 'ssjs-next': {
393
+ name: 'sfmc/ssjs-next',
394
+ plugins: { sfmc: plugin },
395
+ files: ['**/*.ssjs'],
396
+ languageOptions: {
397
+ ecmaVersion: 5,
398
+ sourceType: 'script',
399
+ globals: SSJS_GLOBALS_MAP,
400
+ },
401
+ rules: { ...ssjsMcnRules },
402
+ },
403
+
404
+ /**
405
+ * Recommended MCN config: both AMPscript and SSJS for standalone files.
406
+ * AMPscript portion flags MCN-unsupported functions; SSJS portion flags all SSJS as unsupported.
407
+ */
408
+ 'recommended-next': [
409
+ {
410
+ name: 'sfmc/recommended-next-ampscript',
411
+ plugins: { sfmc: plugin },
412
+ languageOptions: { parser: ampscriptParser },
413
+ files: ['**/*.ampscript', '**/*.amp'],
414
+ rules: {
415
+ ...ampRecommendedRules,
416
+ 'sfmc/amp-no-unknown-function': ['error', { target: 'next' }],
417
+ },
418
+ },
419
+ {
420
+ name: 'sfmc/recommended-next-ssjs',
421
+ plugins: { sfmc: plugin },
422
+ files: ['**/*.ssjs'],
423
+ languageOptions: {
424
+ ecmaVersion: 5,
425
+ sourceType: 'script',
426
+ globals: SSJS_GLOBALS_MAP,
427
+ },
428
+ rules: { ...ssjsMcnRules },
429
+ },
430
+ ],
431
+
432
+ /**
433
+ * MCN config for AMPscript and SSJS embedded in HTML files.
434
+ */
435
+ 'embedded-next': [
436
+ {
437
+ name: 'sfmc/embedded-next-processor',
438
+ plugins: { sfmc: plugin },
439
+ files: ['**/*.html'],
440
+ processor: 'sfmc/sfmc',
441
+ },
442
+ {
443
+ name: 'sfmc/embedded-next-ampscript-rules',
444
+ plugins: { sfmc: plugin },
445
+ languageOptions: { parser: ampscriptParser },
446
+ files: ['**/*.html/*.amp'],
447
+ rules: {
448
+ ...ampRecommendedRules,
449
+ 'sfmc/amp-no-unknown-function': ['error', { target: 'next' }],
450
+ },
451
+ },
452
+ {
453
+ name: 'sfmc/embedded-next-ssjs-rules',
454
+ plugins: { sfmc: plugin },
455
+ files: ['**/*.html/*.js'],
456
+ languageOptions: {
457
+ ecmaVersion: 5,
458
+ sourceType: 'script',
459
+ globals: SSJS_GLOBALS_MAP,
460
+ },
461
+ rules: { ...ssjsMcnRules },
462
+ },
463
+ ],
464
+
465
+ /**
466
+ * Strict MCN config: all rules at error severity for standalone + embedded.
467
+ */
468
+ 'strict-next': [
469
+ {
470
+ name: 'sfmc/strict-next-ampscript',
471
+ plugins: { sfmc: plugin },
472
+ languageOptions: { parser: ampscriptParser },
473
+ files: ['**/*.ampscript', '**/*.amp'],
474
+ rules: {
475
+ ...ampStrictRules,
476
+ 'sfmc/amp-no-unknown-function': ['error', { target: 'next' }],
477
+ },
478
+ },
479
+ {
480
+ name: 'sfmc/strict-next-ssjs',
481
+ plugins: { sfmc: plugin },
482
+ files: ['**/*.ssjs'],
483
+ languageOptions: {
484
+ ecmaVersion: 5,
485
+ sourceType: 'script',
486
+ globals: SSJS_GLOBALS_MAP,
487
+ },
488
+ rules: { ...ssjsMcnRules },
489
+ },
490
+ {
491
+ name: 'sfmc/strict-next-embedded-processor',
492
+ plugins: { sfmc: plugin },
493
+ files: ['**/*.html'],
494
+ processor: 'sfmc/sfmc',
495
+ },
496
+ {
497
+ name: 'sfmc/strict-next-embedded-ampscript-rules',
498
+ plugins: { sfmc: plugin },
499
+ languageOptions: { parser: ampscriptParser },
500
+ files: ['**/*.html/*.amp'],
501
+ rules: {
502
+ ...ampStrictRules,
503
+ 'sfmc/amp-no-unknown-function': ['error', { target: 'next' }],
504
+ },
505
+ },
506
+ {
507
+ name: 'sfmc/strict-next-embedded-ssjs-rules',
508
+ plugins: { sfmc: plugin },
509
+ files: ['**/*.html/*.js'],
510
+ languageOptions: {
511
+ ecmaVersion: 5,
512
+ sourceType: 'script',
513
+ globals: SSJS_GLOBALS_MAP,
514
+ },
515
+ rules: { ...ssjsMcnRules },
516
+ },
517
+ ],
343
518
  });
344
519
 
345
520
  export default plugin;