eslint-plugin-sfmc 0.2.0 → 1.0.1
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 +4 -9
- package/docs/rules/ssjs/no-deprecated-function.md +56 -0
- package/docs/rules/ssjs/no-property-call.md +95 -0
- package/docs/rules/ssjs/no-unknown-function.md +57 -0
- package/package.json +9 -3
- package/src/index.js +15 -33
- package/src/rules/ssjs/no-deprecated-function.js +181 -0
- package/src/rules/ssjs/no-property-call.js +136 -0
- package/src/rules/ssjs/no-unknown-function.js +236 -0
- package/src/rules/ssjs/require-platform-load.js +28 -9
- package/docs/rules/ssjs/no-unknown-core-method.md +0 -46
- package/docs/rules/ssjs/no-unknown-http-method.md +0 -44
- package/docs/rules/ssjs/no-unknown-platform-client-browser.md +0 -44
- package/docs/rules/ssjs/no-unknown-platform-function.md +0 -44
- package/docs/rules/ssjs/no-unknown-platform-request.md +0 -43
- package/docs/rules/ssjs/no-unknown-platform-response.md +0 -43
- package/docs/rules/ssjs/no-unknown-platform-variable.md +0 -43
- package/docs/rules/ssjs/no-unknown-wsproxy-method.md +0 -46
- package/src/rules/ssjs/no-unknown-core-method.js +0 -121
- package/src/rules/ssjs/no-unknown-http-method.js +0 -47
- package/src/rules/ssjs/no-unknown-platform-client-browser.js +0 -53
- package/src/rules/ssjs/no-unknown-platform-function.js +0 -51
- package/src/rules/ssjs/no-unknown-platform-request.js +0 -52
- package/src/rules/ssjs/no-unknown-platform-response.js +0 -52
- package/src/rules/ssjs/no-unknown-platform-variable.js +0 -52
- package/src/rules/ssjs/no-unknown-wsproxy-method.js +0 -88
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Rule: ssjs-no-property-call
|
|
3
|
+
*
|
|
4
|
+
* Flags Platform.Request and Platform.Response members that are properties,
|
|
5
|
+
* not methods. Calling them with `()` is a runtime error.
|
|
6
|
+
*
|
|
7
|
+
* Three cases are handled:
|
|
8
|
+
*
|
|
9
|
+
* 1. Read with parens (both namespaces, no args):
|
|
10
|
+
* Platform.Request.Method() → Platform.Request.Method
|
|
11
|
+
*
|
|
12
|
+
* 2. Write via function call (Platform.Response.* only, single arg):
|
|
13
|
+
* Platform.Response.ContentType("text/html")
|
|
14
|
+
* → Platform.Response.ContentType = "text/html"
|
|
15
|
+
*
|
|
16
|
+
* 3. Attempt to set a read-only property (Platform.Request.*, with args):
|
|
17
|
+
* Platform.Request.Method("POST") → no auto-fix (read-only)
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
import { PLATFORM_RESPONSE_METHODS, PLATFORM_REQUEST_METHODS } from 'ssjs-data';
|
|
21
|
+
|
|
22
|
+
// Platform.Response properties — readable AND writable
|
|
23
|
+
const RESPONSE_PROPERTIES = new Set(
|
|
24
|
+
PLATFORM_RESPONSE_METHODS.filter((m) => m.isProperty).map((m) => m.name.toLowerCase()),
|
|
25
|
+
);
|
|
26
|
+
|
|
27
|
+
// Platform.Request properties — read-only
|
|
28
|
+
const REQUEST_PROPERTIES = new Set(
|
|
29
|
+
PLATFORM_REQUEST_METHODS.filter((m) => m.isProperty).map((m) => m.name.toLowerCase()),
|
|
30
|
+
);
|
|
31
|
+
|
|
32
|
+
export default {
|
|
33
|
+
meta: {
|
|
34
|
+
type: 'problem',
|
|
35
|
+
fixable: 'code',
|
|
36
|
+
docs: {
|
|
37
|
+
description: 'Disallow calling Platform.Request/Response properties as functions',
|
|
38
|
+
},
|
|
39
|
+
messages: {
|
|
40
|
+
propertyReadWithCall:
|
|
41
|
+
"'Platform.{{ns}}.{{name}}' is a property, not a function. " +
|
|
42
|
+
"Remove the '()' to read its value.",
|
|
43
|
+
readOnlyPropertySet:
|
|
44
|
+
"'Platform.Request.{{name}}' is a read-only property. It cannot be assigned a value.",
|
|
45
|
+
writablePropertySet:
|
|
46
|
+
"'Platform.Response.{{name}}' is a property. " +
|
|
47
|
+
'Use `Platform.Response.{{name}} = value` to assign instead of calling it as a function.',
|
|
48
|
+
},
|
|
49
|
+
schema: [],
|
|
50
|
+
},
|
|
51
|
+
|
|
52
|
+
create(context) {
|
|
53
|
+
const sourceCode = context.sourceCode;
|
|
54
|
+
|
|
55
|
+
return {
|
|
56
|
+
CallExpression(node) {
|
|
57
|
+
const callee = node.callee;
|
|
58
|
+
|
|
59
|
+
// Must be Platform.<NS>.<property>()
|
|
60
|
+
if (
|
|
61
|
+
callee.type !== 'MemberExpression' ||
|
|
62
|
+
callee.object.type !== 'MemberExpression' ||
|
|
63
|
+
callee.object.object.type !== 'Identifier' ||
|
|
64
|
+
callee.object.object.name !== 'Platform' ||
|
|
65
|
+
callee.object.property.type !== 'Identifier' ||
|
|
66
|
+
callee.property.type !== 'Identifier'
|
|
67
|
+
) {
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
const ns = callee.object.property.name.toLowerCase();
|
|
72
|
+
const propName = callee.property.name.toLowerCase();
|
|
73
|
+
const displayNs = callee.object.property.name;
|
|
74
|
+
const displayName = callee.property.name;
|
|
75
|
+
|
|
76
|
+
if (ns === 'response' && RESPONSE_PROPERTIES.has(propName)) {
|
|
77
|
+
if (node.arguments.length === 0) {
|
|
78
|
+
// Reading with parens — remove ()
|
|
79
|
+
context.report({
|
|
80
|
+
node,
|
|
81
|
+
messageId: 'propertyReadWithCall',
|
|
82
|
+
data: { ns: displayNs, name: displayName },
|
|
83
|
+
fix(fixer) {
|
|
84
|
+
return fixer.replaceText(node, sourceCode.getText(callee));
|
|
85
|
+
},
|
|
86
|
+
});
|
|
87
|
+
} else if (node.arguments.length === 1) {
|
|
88
|
+
// Setting via function call — convert to assignment
|
|
89
|
+
context.report({
|
|
90
|
+
node,
|
|
91
|
+
messageId: 'writablePropertySet',
|
|
92
|
+
data: { ns: displayNs, name: displayName },
|
|
93
|
+
fix(fixer) {
|
|
94
|
+
// Only safe when the call is a standalone expression statement
|
|
95
|
+
if (node.parent.type !== 'ExpressionStatement') {
|
|
96
|
+
return null;
|
|
97
|
+
}
|
|
98
|
+
const argText = sourceCode.getText(node.arguments[0]);
|
|
99
|
+
return fixer.replaceText(
|
|
100
|
+
node,
|
|
101
|
+
`${sourceCode.getText(callee)} = ${argText}`,
|
|
102
|
+
);
|
|
103
|
+
},
|
|
104
|
+
});
|
|
105
|
+
} else {
|
|
106
|
+
// >1 args — unusual, flag without a fix
|
|
107
|
+
context.report({
|
|
108
|
+
node,
|
|
109
|
+
messageId: 'writablePropertySet',
|
|
110
|
+
data: { ns: displayNs, name: displayName },
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
} else if (ns === 'request' && REQUEST_PROPERTIES.has(propName)) {
|
|
114
|
+
if (node.arguments.length === 0) {
|
|
115
|
+
// Reading with parens — remove ()
|
|
116
|
+
context.report({
|
|
117
|
+
node,
|
|
118
|
+
messageId: 'propertyReadWithCall',
|
|
119
|
+
data: { ns: displayNs, name: displayName },
|
|
120
|
+
fix(fixer) {
|
|
121
|
+
return fixer.replaceText(node, sourceCode.getText(callee));
|
|
122
|
+
},
|
|
123
|
+
});
|
|
124
|
+
} else {
|
|
125
|
+
// Attempting to set a read-only property — no fix
|
|
126
|
+
context.report({
|
|
127
|
+
node,
|
|
128
|
+
messageId: 'readOnlyPropertySet',
|
|
129
|
+
data: { name: displayName },
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
},
|
|
134
|
+
};
|
|
135
|
+
},
|
|
136
|
+
};
|
|
@@ -0,0 +1,236 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Rule: ssjs-no-unknown-function
|
|
3
|
+
*
|
|
4
|
+
* Unified rule that replaces the seven narrow no-unknown-* rules.
|
|
5
|
+
* Flags calls to API methods that do not exist in the SFMC catalog:
|
|
6
|
+
*
|
|
7
|
+
* - Platform.Function.<method>() — unknown Platform.Function method
|
|
8
|
+
* - Platform.Variable.<method>() — unknown Platform.Variable method
|
|
9
|
+
* - Platform.Request.<method>() — unknown Platform.Request method
|
|
10
|
+
* - Platform.Response.<method>() — unknown Platform.Response method
|
|
11
|
+
* - Platform.Recipient.<method>() — unknown Platform.Recipient method
|
|
12
|
+
* - HTTP.<method>() — unknown HTTP method
|
|
13
|
+
* - <wsproxyVar>.<method>() — unknown WSProxy method on a tracked variable
|
|
14
|
+
* - <coreVar>.<method>() — unknown method on a tracked Core Library object
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
import {
|
|
18
|
+
platformFunctionNames,
|
|
19
|
+
PLATFORM_VARIABLE_METHODS,
|
|
20
|
+
PLATFORM_REQUEST_METHODS,
|
|
21
|
+
PLATFORM_RESPONSE_METHODS,
|
|
22
|
+
platformRecipientMethodNames,
|
|
23
|
+
httpMethodNames,
|
|
24
|
+
coreObjectLookup,
|
|
25
|
+
coreObjectNames,
|
|
26
|
+
wsproxyMethodNames,
|
|
27
|
+
} from 'ssjs-data';
|
|
28
|
+
|
|
29
|
+
// Map of lowercase Platform namespace → Set of known lowercase method names
|
|
30
|
+
const PLATFORM_NS = new Map([
|
|
31
|
+
['function', platformFunctionNames],
|
|
32
|
+
['variable', new Set(PLATFORM_VARIABLE_METHODS.map((m) => m.name.toLowerCase()))],
|
|
33
|
+
['request', new Set(PLATFORM_REQUEST_METHODS.map((m) => m.name.toLowerCase()))],
|
|
34
|
+
['response', new Set(PLATFORM_RESPONSE_METHODS.map((m) => m.name.toLowerCase()))],
|
|
35
|
+
['recipient', platformRecipientMethodNames],
|
|
36
|
+
]);
|
|
37
|
+
|
|
38
|
+
export default {
|
|
39
|
+
meta: {
|
|
40
|
+
type: 'problem',
|
|
41
|
+
docs: {
|
|
42
|
+
description:
|
|
43
|
+
'Disallow calls to unknown SFMC API methods (Platform.*, HTTP.*, Core library, WSProxy)',
|
|
44
|
+
},
|
|
45
|
+
messages: {
|
|
46
|
+
unknownPlatformMethod:
|
|
47
|
+
"'Platform.{{ns}}.{{name}}' is not a recognized SFMC Platform.{{ns}} method.",
|
|
48
|
+
unknownHttpMethod: "'HTTP.{{name}}' is not a recognized SFMC HTTP method.",
|
|
49
|
+
unknownCoreMethod:
|
|
50
|
+
"'{{method}}' is not a known method of {{objectType}}. Available methods: {{available}}.",
|
|
51
|
+
unknownWsproxyMethod: "'{{name}}' is not a recognized WSProxy method.",
|
|
52
|
+
},
|
|
53
|
+
schema: [],
|
|
54
|
+
},
|
|
55
|
+
|
|
56
|
+
create(context) {
|
|
57
|
+
// Track variable name → Core Library type name (assigned via TypeName.Init())
|
|
58
|
+
const coreVariables = new Map();
|
|
59
|
+
// Track variable names assigned via new Script.Util.WSProxy()
|
|
60
|
+
const wsproxyVariables = new Set();
|
|
61
|
+
|
|
62
|
+
return {
|
|
63
|
+
VariableDeclaration(node) {
|
|
64
|
+
for (const decl of node.declarations) {
|
|
65
|
+
if (!decl.init || !decl.id || decl.id.type !== 'Identifier') {
|
|
66
|
+
continue;
|
|
67
|
+
}
|
|
68
|
+
const coreType = getCoreInitType(decl.init);
|
|
69
|
+
if (coreType) {
|
|
70
|
+
coreVariables.set(decl.id.name, coreType);
|
|
71
|
+
}
|
|
72
|
+
if (isWSProxyConstructor(decl.init)) {
|
|
73
|
+
wsproxyVariables.add(decl.id.name);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
},
|
|
77
|
+
|
|
78
|
+
AssignmentExpression(node) {
|
|
79
|
+
if (node.left.type !== 'Identifier') {
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
82
|
+
const coreType = getCoreInitType(node.right);
|
|
83
|
+
if (coreType) {
|
|
84
|
+
coreVariables.set(node.left.name, coreType);
|
|
85
|
+
}
|
|
86
|
+
if (isWSProxyConstructor(node.right)) {
|
|
87
|
+
wsproxyVariables.add(node.left.name);
|
|
88
|
+
}
|
|
89
|
+
},
|
|
90
|
+
|
|
91
|
+
CallExpression(node) {
|
|
92
|
+
const callee = node.callee;
|
|
93
|
+
if (callee.type !== 'MemberExpression') {
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
96
|
+
const property = callee.property;
|
|
97
|
+
if (property.type !== 'Identifier') {
|
|
98
|
+
return;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
const methodName = property.name;
|
|
102
|
+
|
|
103
|
+
// ── Platform.<NS>.<method>() ──────────────────────────────────
|
|
104
|
+
if (
|
|
105
|
+
callee.object.type === 'MemberExpression' &&
|
|
106
|
+
callee.object.object.type === 'Identifier' &&
|
|
107
|
+
callee.object.object.name === 'Platform' &&
|
|
108
|
+
callee.object.property.type === 'Identifier'
|
|
109
|
+
) {
|
|
110
|
+
const ns = callee.object.property.name.toLowerCase();
|
|
111
|
+
const knownNames = PLATFORM_NS.get(ns);
|
|
112
|
+
// Only report if we know this namespace; unknown namespaces are ignored.
|
|
113
|
+
if (knownNames && !knownNames.has(methodName.toLowerCase())) {
|
|
114
|
+
context.report({
|
|
115
|
+
node: property,
|
|
116
|
+
messageId: 'unknownPlatformMethod',
|
|
117
|
+
data: { ns: callee.object.property.name, name: methodName },
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
return;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
// ── HTTP.<method>() ───────────────────────────────────────────
|
|
124
|
+
if (
|
|
125
|
+
callee.object.type === 'Identifier' &&
|
|
126
|
+
callee.object.name === 'HTTP' &&
|
|
127
|
+
!httpMethodNames.has(methodName.toLowerCase())
|
|
128
|
+
) {
|
|
129
|
+
context.report({
|
|
130
|
+
node: property,
|
|
131
|
+
messageId: 'unknownHttpMethod',
|
|
132
|
+
data: { name: methodName },
|
|
133
|
+
});
|
|
134
|
+
return;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
// ── Instance method calls (Core Library / WSProxy) ────────────
|
|
138
|
+
if (callee.object.type === 'Identifier') {
|
|
139
|
+
const objectName = callee.object.name;
|
|
140
|
+
|
|
141
|
+
// Core library: var de = DataExtension.Init("key"); de.Foo();
|
|
142
|
+
const coreType = coreVariables.get(objectName);
|
|
143
|
+
if (coreType) {
|
|
144
|
+
const objectDef = coreObjectLookup.get(coreType);
|
|
145
|
+
if (objectDef) {
|
|
146
|
+
const knownMethods = new Set(
|
|
147
|
+
objectDef.methods.map((m) => m.toLowerCase()),
|
|
148
|
+
);
|
|
149
|
+
if (!knownMethods.has(methodName.toLowerCase())) {
|
|
150
|
+
context.report({
|
|
151
|
+
node: property,
|
|
152
|
+
messageId: 'unknownCoreMethod',
|
|
153
|
+
data: {
|
|
154
|
+
method: methodName,
|
|
155
|
+
objectType: coreType,
|
|
156
|
+
available: objectDef.methods.join(', '),
|
|
157
|
+
},
|
|
158
|
+
});
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
return;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
// WSProxy: var api = new Script.Util.WSProxy(); api.Foo();
|
|
165
|
+
if (
|
|
166
|
+
wsproxyVariables.has(objectName) &&
|
|
167
|
+
!wsproxyMethodNames.has(methodName.toLowerCase())
|
|
168
|
+
) {
|
|
169
|
+
context.report({
|
|
170
|
+
node: property,
|
|
171
|
+
messageId: 'unknownWsproxyMethod',
|
|
172
|
+
data: { name: methodName },
|
|
173
|
+
});
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
},
|
|
177
|
+
};
|
|
178
|
+
},
|
|
179
|
+
};
|
|
180
|
+
|
|
181
|
+
/**
|
|
182
|
+
* If `node` is a Core Library Init call (e.g. `DataExtension.Init("key")`),
|
|
183
|
+
* return the Core Library type name; otherwise return null.
|
|
184
|
+
*
|
|
185
|
+
* @param {import('eslint').Rule.Node} node - AST node to inspect
|
|
186
|
+
* @returns {string | null} Core Library type name, or null when not a Core Library Init call
|
|
187
|
+
*/
|
|
188
|
+
function getCoreInitType(node) {
|
|
189
|
+
if (!node || node.type !== 'CallExpression') {
|
|
190
|
+
return null;
|
|
191
|
+
}
|
|
192
|
+
const callee = node.callee;
|
|
193
|
+
if (callee.type !== 'MemberExpression') {
|
|
194
|
+
return null;
|
|
195
|
+
}
|
|
196
|
+
if (callee.property.type !== 'Identifier' || callee.property.name !== 'Init') {
|
|
197
|
+
return null;
|
|
198
|
+
}
|
|
199
|
+
if (callee.object.type === 'Identifier' && coreObjectNames.has(callee.object.name)) {
|
|
200
|
+
return callee.object.name;
|
|
201
|
+
}
|
|
202
|
+
if (
|
|
203
|
+
callee.object.type === 'MemberExpression' &&
|
|
204
|
+
callee.object.object.type === 'Identifier' &&
|
|
205
|
+
callee.object.property.type === 'Identifier'
|
|
206
|
+
) {
|
|
207
|
+
const fullName = `${callee.object.object.name}.${callee.object.property.name}`;
|
|
208
|
+
if (coreObjectNames.has(fullName)) {
|
|
209
|
+
return fullName;
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
return null;
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
/**
|
|
216
|
+
* Returns true if `node` is `new Script.Util.WSProxy()`.
|
|
217
|
+
*
|
|
218
|
+
* @param {import('eslint').Rule.Node} node - AST node to inspect
|
|
219
|
+
* @returns {boolean} true when the node is a WSProxy constructor call
|
|
220
|
+
*/
|
|
221
|
+
function isWSProxyConstructor(node) {
|
|
222
|
+
if (!node || node.type !== 'NewExpression') {
|
|
223
|
+
return false;
|
|
224
|
+
}
|
|
225
|
+
const c = node.callee;
|
|
226
|
+
return (
|
|
227
|
+
c.type === 'MemberExpression' &&
|
|
228
|
+
c.property.type === 'Identifier' &&
|
|
229
|
+
c.property.name === 'WSProxy' &&
|
|
230
|
+
c.object.type === 'MemberExpression' &&
|
|
231
|
+
c.object.property.type === 'Identifier' &&
|
|
232
|
+
c.object.property.name === 'Util' &&
|
|
233
|
+
c.object.object.type === 'Identifier' &&
|
|
234
|
+
c.object.object.name === 'Script'
|
|
235
|
+
);
|
|
236
|
+
}
|
|
@@ -10,10 +10,16 @@
|
|
|
10
10
|
* reported violation so ESLint does not duplicate the insertion.
|
|
11
11
|
*/
|
|
12
12
|
|
|
13
|
-
import { coreObjectNames } from 'ssjs-data';
|
|
13
|
+
import { coreObjectNames, SSJS_GLOBALS } from 'ssjs-data';
|
|
14
14
|
|
|
15
15
|
const TOP_LEVEL_CORE_NAMES = new Set([...coreObjectNames].map((n) => n.split('.')[0]));
|
|
16
16
|
|
|
17
|
+
// Globals that resolve at runtime only after Platform.Load("core", ...) has been called.
|
|
18
|
+
// E.g. Now(), Write(), GUID(), Base64Encode(), Attribute.GetValue(), DateTime.Parse(), …
|
|
19
|
+
const REQUIRES_CORE_LOAD_GLOBALS = new Set(
|
|
20
|
+
SSJS_GLOBALS.filter((g) => g.requiresCoreLoad).map((g) => g.name.toLowerCase()),
|
|
21
|
+
);
|
|
22
|
+
|
|
17
23
|
const PLATFORM_LOAD_STATEMENT = 'Platform.Load("core", "1.1.5");\n';
|
|
18
24
|
|
|
19
25
|
export default {
|
|
@@ -96,10 +102,20 @@ function isPlatformLoadCall(node) {
|
|
|
96
102
|
|
|
97
103
|
function getCoreObjectUsage(node) {
|
|
98
104
|
const callee = node.callee;
|
|
105
|
+
|
|
106
|
+
// Bare call: Now(), Write(), GUID(), Base64Encode(), Redirect(), …
|
|
107
|
+
if (callee.type === 'Identifier') {
|
|
108
|
+
if (REQUIRES_CORE_LOAD_GLOBALS.has(callee.name.toLowerCase())) {
|
|
109
|
+
return callee.name;
|
|
110
|
+
}
|
|
111
|
+
return null;
|
|
112
|
+
}
|
|
113
|
+
|
|
99
114
|
if (callee.type !== 'MemberExpression') {
|
|
100
115
|
return null;
|
|
101
116
|
}
|
|
102
117
|
|
|
118
|
+
// Nested Core Library call: DataExtension.Rows.Init(…)
|
|
103
119
|
if (
|
|
104
120
|
callee.object.type === 'MemberExpression' &&
|
|
105
121
|
callee.object.object.type === 'Identifier' &&
|
|
@@ -110,14 +126,17 @@ function getCoreObjectUsage(node) {
|
|
|
110
126
|
return `${callee.object.object.name}.${callee.object.property.name}`;
|
|
111
127
|
}
|
|
112
128
|
|
|
113
|
-
if (
|
|
114
|
-
callee.object.
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
129
|
+
if (callee.object.type === 'Identifier' && callee.property.type === 'Identifier') {
|
|
130
|
+
const objectName = callee.object.name;
|
|
131
|
+
|
|
132
|
+
// Core Library static Init: DataExtension.Init(…), Subscriber.Init(…), …
|
|
133
|
+
if (TOP_LEVEL_CORE_NAMES.has(objectName) && callee.property.name === 'Init') {
|
|
134
|
+
return objectName;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
// requiresCoreLoad globals used as object: Attribute.GetValue(…), DateTime.Parse(…), …
|
|
138
|
+
if (REQUIRES_CORE_LOAD_GLOBALS.has(objectName.toLowerCase())) {
|
|
139
|
+
return `${objectName}.${callee.property.name}`;
|
|
121
140
|
}
|
|
122
141
|
}
|
|
123
142
|
|
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
# `sfmc/ssjs-no-unknown-core-method`
|
|
2
|
-
|
|
3
|
-
> Disallow calls to methods that don't exist on a Core library object.
|
|
4
|
-
|
|
5
|
-
| | |
|
|
6
|
-
|---|---|
|
|
7
|
-
| **Type** | `problem` |
|
|
8
|
-
| **Default severity** | `warn` in `recommended`; `error` in `strict` |
|
|
9
|
-
| **Fixable** | — |
|
|
10
|
-
|
|
11
|
-
## Why This Rule Exists
|
|
12
|
-
|
|
13
|
-
When a variable is initialised with a known Core library constructor (e.g. `var de = DataExtension.Init("MyDE")`), only the methods documented for that Core object type should be called on it. Calling an undocumented or misspelled method causes a runtime error. This rule infers the object type from the `.Init()` call and validates subsequent method calls.
|
|
14
|
-
|
|
15
|
-
## Settings
|
|
16
|
-
|
|
17
|
-
| Setting | Values | Default |
|
|
18
|
-
|---------|--------|---------|
|
|
19
|
-
| severity | `"error"` \| `"warn"` \| `"off"` | `"warn"` |
|
|
20
|
-
|
|
21
|
-
This rule has no configuration options.
|
|
22
|
-
|
|
23
|
-
### Examples
|
|
24
|
-
|
|
25
|
-
**Not allowed:**
|
|
26
|
-
|
|
27
|
-
```js
|
|
28
|
-
Platform.Load("core", "1.1.5");
|
|
29
|
-
var de = DataExtension.Init("MyDE");
|
|
30
|
-
de.Execute(); /* 'Execute' is not a method of DataExtension */
|
|
31
|
-
```
|
|
32
|
-
|
|
33
|
-
**Allowed:**
|
|
34
|
-
|
|
35
|
-
```js
|
|
36
|
-
Platform.Load("core", "1.1.5");
|
|
37
|
-
var de = DataExtension.Init("MyDE");
|
|
38
|
-
var rows = de.Rows.Retrieve();
|
|
39
|
-
```
|
|
40
|
-
|
|
41
|
-
## When to Disable
|
|
42
|
-
|
|
43
|
-
```js
|
|
44
|
-
// eslint.config.js
|
|
45
|
-
rules: { 'sfmc/ssjs-no-unknown-core-method': 'off' }
|
|
46
|
-
```
|
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
# `sfmc/ssjs-no-unknown-http-method`
|
|
2
|
-
|
|
3
|
-
> Disallow unknown `HTTP.*` method calls.
|
|
4
|
-
|
|
5
|
-
| | |
|
|
6
|
-
|---|---|
|
|
7
|
-
| **Type** | `problem` |
|
|
8
|
-
| **Default severity** | `error` in `recommended` and `strict` |
|
|
9
|
-
| **Fixable** | — |
|
|
10
|
-
|
|
11
|
-
## Why This Rule Exists
|
|
12
|
-
|
|
13
|
-
SFMC's SSJS runtime exposes only four `HTTP` methods: `HTTP.Get`, `HTTP.Post`, `HTTP.GetRequest`, and `HTTP.PostRequest`. Calling any other `HTTP.*` method causes a runtime error. This rule validates every `HTTP.*` call against that fixed list.
|
|
14
|
-
|
|
15
|
-
## Settings
|
|
16
|
-
|
|
17
|
-
| Setting | Values | Default |
|
|
18
|
-
|---------|--------|---------|
|
|
19
|
-
| severity | `"error"` \| `"warn"` \| `"off"` | `"error"` |
|
|
20
|
-
|
|
21
|
-
This rule has no configuration options.
|
|
22
|
-
|
|
23
|
-
### Examples
|
|
24
|
-
|
|
25
|
-
**Not allowed:**
|
|
26
|
-
|
|
27
|
-
```js
|
|
28
|
-
var response = HTTP.Delete("https://api.example.com/resource/1");
|
|
29
|
-
var response = HTTP.Patch("https://api.example.com/resource/1", payload);
|
|
30
|
-
```
|
|
31
|
-
|
|
32
|
-
**Allowed:**
|
|
33
|
-
|
|
34
|
-
```js
|
|
35
|
-
var getResponse = HTTP.Get("https://api.example.com/resource/1");
|
|
36
|
-
var postResponse = HTTP.Post("https://api.example.com/resource", payload, contentType);
|
|
37
|
-
```
|
|
38
|
-
|
|
39
|
-
## When to Disable
|
|
40
|
-
|
|
41
|
-
```js
|
|
42
|
-
// eslint.config.js
|
|
43
|
-
rules: { 'sfmc/ssjs-no-unknown-http-method': 'off' }
|
|
44
|
-
```
|
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
# `sfmc/ssjs-no-unknown-platform-client-browser`
|
|
2
|
-
|
|
3
|
-
> Disallow unknown `Platform.ClientBrowser.*` method calls.
|
|
4
|
-
|
|
5
|
-
| | |
|
|
6
|
-
|---|---|
|
|
7
|
-
| **Type** | `problem` |
|
|
8
|
-
| **Default severity** | `error` in `recommended` and `strict` |
|
|
9
|
-
| **Fixable** | — |
|
|
10
|
-
|
|
11
|
-
## Why This Rule Exists
|
|
12
|
-
|
|
13
|
-
`Platform.ClientBrowser` exposes a small, fixed set of methods for writing to and redirecting the HTTP response on CloudPages and landing pages. Calling a method that does not exist in this catalog causes a runtime error. This rule validates every `Platform.ClientBrowser.*` call against the known list.
|
|
14
|
-
|
|
15
|
-
## Settings
|
|
16
|
-
|
|
17
|
-
| Setting | Values | Default |
|
|
18
|
-
|---------|--------|---------|
|
|
19
|
-
| severity | `"error"` \| `"warn"` \| `"off"` | `"error"` |
|
|
20
|
-
|
|
21
|
-
This rule has no configuration options.
|
|
22
|
-
|
|
23
|
-
### Examples
|
|
24
|
-
|
|
25
|
-
**Not allowed:**
|
|
26
|
-
|
|
27
|
-
```js
|
|
28
|
-
Platform.ClientBrowser.Send("data");
|
|
29
|
-
```
|
|
30
|
-
|
|
31
|
-
**Allowed:**
|
|
32
|
-
|
|
33
|
-
```js
|
|
34
|
-
Platform.ClientBrowser.Redirect("https://example.com");
|
|
35
|
-
Platform.ClientBrowser.Write("<p>Hello</p>");
|
|
36
|
-
Platform.ClientBrowser.SetCookie("session", "abc123");
|
|
37
|
-
```
|
|
38
|
-
|
|
39
|
-
## When to Disable
|
|
40
|
-
|
|
41
|
-
```js
|
|
42
|
-
// eslint.config.js
|
|
43
|
-
rules: { 'sfmc/ssjs-no-unknown-platform-client-browser': 'off' }
|
|
44
|
-
```
|
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
# `sfmc/ssjs-no-unknown-platform-function`
|
|
2
|
-
|
|
3
|
-
> Disallow calls to unknown `Platform.Function.*` methods.
|
|
4
|
-
|
|
5
|
-
| | |
|
|
6
|
-
|---|---|
|
|
7
|
-
| **Type** | `problem` |
|
|
8
|
-
| **Default severity** | `error` in `recommended` and `strict` |
|
|
9
|
-
| **Fixable** | — |
|
|
10
|
-
|
|
11
|
-
## Why This Rule Exists
|
|
12
|
-
|
|
13
|
-
`Platform.Function` exposes a fixed set of SFMC server-side utility functions (e.g. `Platform.Function.Lookup`, `Platform.Function.InsertData`). Calling a method that does not exist in the catalog causes a runtime error. This rule validates every `Platform.Function.*` call against the known list.
|
|
14
|
-
|
|
15
|
-
## Settings
|
|
16
|
-
|
|
17
|
-
| Setting | Values | Default |
|
|
18
|
-
|---------|--------|---------|
|
|
19
|
-
| severity | `"error"` \| `"warn"` \| `"off"` | `"error"` |
|
|
20
|
-
|
|
21
|
-
This rule has no configuration options.
|
|
22
|
-
|
|
23
|
-
### Examples
|
|
24
|
-
|
|
25
|
-
**Not allowed:**
|
|
26
|
-
|
|
27
|
-
```js
|
|
28
|
-
Platform.Load("core", "1.1.5");
|
|
29
|
-
var result = Platform.Function.CustomQuery("MyDE");
|
|
30
|
-
```
|
|
31
|
-
|
|
32
|
-
**Allowed:**
|
|
33
|
-
|
|
34
|
-
```js
|
|
35
|
-
Platform.Load("core", "1.1.5");
|
|
36
|
-
var result = Platform.Function.Lookup("MyDE", "Value", "Key", keyValue);
|
|
37
|
-
```
|
|
38
|
-
|
|
39
|
-
## When to Disable
|
|
40
|
-
|
|
41
|
-
```js
|
|
42
|
-
// eslint.config.js
|
|
43
|
-
rules: { 'sfmc/ssjs-no-unknown-platform-function': 'off' }
|
|
44
|
-
```
|
|
@@ -1,43 +0,0 @@
|
|
|
1
|
-
# `sfmc/ssjs-no-unknown-platform-request`
|
|
2
|
-
|
|
3
|
-
> Disallow unknown `Platform.Request.*` method calls.
|
|
4
|
-
|
|
5
|
-
| | |
|
|
6
|
-
|---|---|
|
|
7
|
-
| **Type** | `problem` |
|
|
8
|
-
| **Default severity** | `error` in `recommended` and `strict` |
|
|
9
|
-
| **Fixable** | — |
|
|
10
|
-
|
|
11
|
-
## Why This Rule Exists
|
|
12
|
-
|
|
13
|
-
`Platform.Request` exposes a fixed set of methods for reading incoming HTTP request data on CloudPages and landing pages (e.g. `Platform.Request.GetQueryStringParameter`, `Platform.Request.GetFormField`). Calling an unknown method causes a runtime error. This rule validates every `Platform.Request.*` call against the known list.
|
|
14
|
-
|
|
15
|
-
## Settings
|
|
16
|
-
|
|
17
|
-
| Setting | Values | Default |
|
|
18
|
-
|---------|--------|---------|
|
|
19
|
-
| severity | `"error"` \| `"warn"` \| `"off"` | `"error"` |
|
|
20
|
-
|
|
21
|
-
This rule has no configuration options.
|
|
22
|
-
|
|
23
|
-
### Examples
|
|
24
|
-
|
|
25
|
-
**Not allowed:**
|
|
26
|
-
|
|
27
|
-
```js
|
|
28
|
-
var val = Platform.Request.ReadParam("myParam");
|
|
29
|
-
```
|
|
30
|
-
|
|
31
|
-
**Allowed:**
|
|
32
|
-
|
|
33
|
-
```js
|
|
34
|
-
var val = Platform.Request.GetQueryStringParameter("myParam");
|
|
35
|
-
var field = Platform.Request.GetFormField("email");
|
|
36
|
-
```
|
|
37
|
-
|
|
38
|
-
## When to Disable
|
|
39
|
-
|
|
40
|
-
```js
|
|
41
|
-
// eslint.config.js
|
|
42
|
-
rules: { 'sfmc/ssjs-no-unknown-platform-request': 'off' }
|
|
43
|
-
```
|