eslint-plugin-sfmc 4.4.0 → 4.5.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "eslint-plugin-sfmc",
3
- "version": "4.4.0",
3
+ "version": "4.5.0",
4
4
  "description": "ESLint plugin for Salesforce Marketing Cloud Engagement+Next - AMPscript, Server-Side JavaScript (SSJS) and Handlebars",
5
5
  "type": "module",
6
6
  "main": "src/index.js",
@@ -42,7 +42,7 @@
42
42
  "eslint-plugin-mso-email": "^2.0.0",
43
43
  "handlebars-data": "^0.3.0",
44
44
  "mso-conditional-parser": "^2.0.1",
45
- "ssjs-data": "^0.19.0"
45
+ "ssjs-data": "^0.21.0"
46
46
  },
47
47
  "peerDependencies": {
48
48
  "eslint": ">=9.0.0"
@@ -2,13 +2,17 @@
2
2
  * Rule: ssjs-no-nonexistent-global
3
3
  *
4
4
  * Flags bare-name SSJS globals that are officially documented but proven NOT to
5
- * exist at runtime — calling them throws a ReferenceError. Currently covers:
5
+ * exist at runtime as callable identifiers — calling them throws a ReferenceError.
6
6
  *
7
- * - Redirect(url, movedPermanently) undefined under every Core version;
8
- * use Platform.Response.Redirect(url, movedPermanently) instead.
7
+ * The offending names come from ssjs-data's `notDefinedAtRuntime` flag, so phantom
8
+ * globals are picked up automatically without editing this rule. Only bare-name
9
+ * callable phantoms (Identifier callees) are flagged here; object-namespace
10
+ * phantoms accessed via member calls (e.g. `Recipient.GetAttributeValue(...)`) are
11
+ * out of scope for this rule.
9
12
  *
10
- * The offending names come from ssjs-data's `notDefinedAtRuntime` flag, so new
11
- * phantom globals are picked up automatically without editing this rule.
13
+ * Note: many bare-name Core globals (Write, Stringify, Base64Encode, Format,
14
+ * Redirect, …) are NOT phantom they exist after `Platform.Load("core")` when
15
+ * called in the same scope as the load, so they are intentionally not flagged.
12
16
  */
13
17
 
14
18
  import { notDefinedAtRuntimeGlobalLookup } from 'ssjs-data';
@@ -7,6 +7,20 @@
7
7
 
8
8
  import { platformFunctionLookup } from 'ssjs-data';
9
9
 
10
+ /**
11
+ * Render a set of permitted argument counts as human-readable text,
12
+ * e.g. `[1, 6]` → "1 or 6" and `[1, 3, 6]` → "1, 3 or 6".
13
+ *
14
+ * @param {number[]} arities - The permitted argument counts.
15
+ * @returns {string} The rendered list.
16
+ */
17
+ function formatArities(arities) {
18
+ if (arities.length === 1) {
19
+ return String(arities[0]);
20
+ }
21
+ return `${arities.slice(0, -1).join(', ')} or ${arities.at(-1)}`;
22
+ }
23
+
10
24
  export default {
11
25
  meta: {
12
26
  type: 'problem',
@@ -18,6 +32,8 @@ export default {
18
32
  "'Platform.Function.{{name}}' requires at least {{min}} argument(s) but was called with {{actual}}.",
19
33
  tooManyArgs:
20
34
  "'Platform.Function.{{name}}' accepts at most {{max}} argument(s) but was called with {{actual}}.",
35
+ invalidArity:
36
+ "'Platform.Function.{{name}}' must be called with exactly {{arities}} arguments (got {{actual}}); intermediate argument counts throw at runtime.",
21
37
  },
22
38
  schema: [],
23
39
  },
@@ -66,6 +82,22 @@ export default {
66
82
  actual: String(actual),
67
83
  },
68
84
  });
85
+ } else if (
86
+ Array.isArray(entry.validArities) &&
87
+ !entry.validArities.includes(actual)
88
+ ) {
89
+ // Discontinuous overload: actual is within [minArgs, maxArgs]
90
+ // but not one of the exact permitted arities (e.g. HTTPGet
91
+ // accepts only 1 or 6 arguments; 2-5 throw at runtime).
92
+ context.report({
93
+ node: callee.property,
94
+ messageId: 'invalidArity',
95
+ data: {
96
+ name: entry.name,
97
+ arities: formatArities(entry.validArities),
98
+ actual: String(actual),
99
+ },
100
+ });
69
101
  }
70
102
  }
71
103
  },