mcp-server-sfmc 1.9.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 +58 -8
- package/dist/cli/reviewDiff.d.ts +1 -17
- package/dist/cli/reviewDiff.d.ts.map +1 -1
- package/dist/cli/reviewDiff.js +25 -53
- package/dist/cli/reviewDiff.js.map +1 -1
- package/dist/cli/reviewSeverity.d.ts +23 -0
- package/dist/cli/reviewSeverity.d.ts.map +1 -0
- package/dist/cli/reviewSeverity.js +36 -0
- package/dist/cli/reviewSeverity.js.map +1 -0
- package/dist/conversion-rules.d.ts +72 -0
- package/dist/conversion-rules.d.ts.map +1 -1
- package/dist/conversion-rules.js +544 -165
- package/dist/conversion-rules.js.map +1 -1
- package/dist/index.js +729 -129
- package/dist/index.js.map +1 -1
- package/dist/mce-help-search.js +5 -5
- package/dist/mce-help-search.js.map +1 -1
- package/dist/mcn-help-search.js +5 -5
- package/dist/mcn-help-search.js.map +1 -1
- package/package.json +23 -10
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# mcp-server-sfmc
|
|
2
2
|
|
|
3
|
-
MCP server providing Salesforce Marketing Cloud language intelligence — AMPscript, SSJS, and
|
|
3
|
+
MCP server providing Salesforce Marketing Cloud language intelligence — AMPscript, SSJS, GTL, and **Marketing Cloud Next (MCN) Handlebars** — as Model Context Protocol tools, resources, and prompts for AI-assisted development and code review. Ships two searchable doc indexes: **MCE help** (Salesforce Help for Marketing Cloud Engagement administration and setup) and **MCN developer docs** (Marketing Cloud Next REST API and developer reference). Includes full **Marketing Cloud Next (MCN) platform awareness**: auto-detects whether a project targets MCE or MCN, restricts completions and validation to MCN-supported functions, flags SSJS as unsupported in MCN, surfaces MCN behavioral differences in hover and diagnostics, validates MCN Handlebars templates, and provides a **migration toolkit** to analyze and rewrite code for MCN — including AMPscript ↔ Handlebars and SSJS → Handlebars conversion.
|
|
4
4
|
|
|
5
5
|
Built on [sfmc-language-lsp](https://github.com/JoernBerkefeld/sfmc-language-lsp), the same engine that powers the [SFMC Language Service VS Code extension](https://marketplace.visualstudio.com/items?itemName=joernberkefeld.sfmc-language).
|
|
6
6
|
|
|
@@ -41,7 +41,7 @@ Ready-to-copy workflows (GitHub Actions, GitLab CI, Jenkins, Azure Pipelines, Bi
|
|
|
41
41
|
|
|
42
42
|
| Feature | Details |
|
|
43
43
|
| ------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
44
|
-
| **Validation** | Syntax errors, unknown functions, arity mismatches, unsupported SSJS syntax; `target: 'next'` flags MCN-incompatible functions and all SSJS
|
|
44
|
+
| **Validation** | Syntax errors, unknown functions, arity mismatches, unsupported SSJS syntax; `target: 'next'` flags MCN-incompatible functions and all SSJS; `validate_handlebars` checks MCN Handlebars helper names, arity, block balance, and unsupported constructs |
|
|
45
45
|
| **Lookup** | Full function signatures, parameters, return types, MCN compatibility badge (API version), behavioral notes, and examples |
|
|
46
46
|
| **PR review** | Diff-aware review tool that surfaces issues in the exact lines that changed |
|
|
47
47
|
| **Fix suggestions** | Concrete, compilable replacement code; `target: 'next'` includes MCN platform issues |
|
|
@@ -50,8 +50,10 @@ Ready-to-copy workflows (GitHub Actions, GitLab CI, Jenkins, Azure Pipelines, Bi
|
|
|
50
50
|
| **MCN compatibility analysis** | `check_mcn_compatibility` analyzes files for MCN readiness — per-function classification (supported / needs review / not supported), SSJS block migration difficulty, and an executive summary |
|
|
51
51
|
| **MCN migration** | `rewrite_for_mcn` (tool + prompt) deterministically rewrites AMPscript and converts convertible SSJS to AMPscript for MCN, then applies AI reasoning to remaining manual-rewrite sections |
|
|
52
52
|
| **Code conversion** | `convertSsjsToAmpscript` and `convertAmpscriptToSsjs` (tool + prompt hybrid) — rule-based conversion with AI-enhanced handling of flagged sections |
|
|
53
|
-
| **
|
|
54
|
-
| **
|
|
53
|
+
| **MCN Handlebars** | `lookup_handlebars_helper`, `list_handlebars_helpers`, `get_handlebars_completions`, and `write_handlebars` (authoring) backed by the `handlebars-data` catalog |
|
|
54
|
+
| **Handlebars conversion** | `convertAmpscriptToHandlebars`, `convertHandlebarsToAmpscript`, and `convertSsjsToHandlebars` (tool + prompt hybrid) — data-driven from `ampscript-data` `handlebarsEquivalent` / `mcnHandlebarsGap` |
|
|
55
|
+
| **Prompts** | Guided prompts for writing AMPscript/SSJS/Handlebars (with MCN constraints), reviewing code, converting between languages, and rewriting for MCN |
|
|
56
|
+
| **Resources** | Full function catalogs, keyword list, unsupported ES6+ syntax list, MCN Handlebars helper and binding catalogs |
|
|
55
57
|
| **Help search** | `search_help` (unified, auto-detects MCE vs MCN from project root); `search_mce_help` (MCE help, 7 product scopes); `search_mcn_help` (MCN developer API reference) |
|
|
56
58
|
|
|
57
59
|
## Connecting AI clients
|
|
@@ -156,6 +158,14 @@ Then replace `"command": "npx", "args": ["-y", "mcp-server-sfmc@latest"]` with:
|
|
|
156
158
|
| `rewrite_for_mcn` | Deterministic MCN rewrite engine: fixes `.NET → Java` format strings, removes `StringToDate` wrappers, converts convertible SSJS to AMPscript, marks unsupported functions, annotates the rest as `MANUAL_REWRITE_REQUIRED`. **Prefer the `rewrite_for_mcn` prompt** for interactive use — it calls this tool first, then applies AI reasoning to the flagged sections. Use the tool directly only for structured JSON output in pipelines. |
|
|
157
159
|
| `convertSsjsToAmpscript` | Rule-based SSJS → AMPscript conversion engine: `Platform.Function.*` → AMPscript equivalents, variable/request access, control flow. Flags JS-native constructs as `MANUAL_REWRITE_REQUIRED`. **Prefer the `convertSsjsToAmpscript` prompt** for interactive use. |
|
|
158
160
|
| `convertAmpscriptToSsjs` | Rule-based AMPscript → SSJS conversion engine: variables, control flow, function calls. Flags AMPscript-only constructs as `MANUAL_REWRITE_REQUIRED`. **Prefer the `convertAmpscriptToSsjs` prompt** for interactive use. |
|
|
161
|
+
| `validate_handlebars` | Validate MCN Handlebars template code — helper names, arity, block balance, and unsupported constructs (partials, decorators, built-in helpers absent from the locked-down MCN engine). |
|
|
162
|
+
| `lookup_handlebars_helper` | Signature, parameters, description, origin, and MCN API version for a single MCN Handlebars helper (case-insensitive). |
|
|
163
|
+
| `list_handlebars_helpers` | List all MCN Handlebars helpers, optionally filtered by `category` and/or `origin` (`handlebars-builtin`, `mcn-helper`, `mcn-platform`). |
|
|
164
|
+
| `get_handlebars_completions` | List MCN Handlebars helper completions, optionally filtered by prefix. |
|
|
165
|
+
| `convertAmpscriptToHandlebars` | Rule-based AMPscript → MCN Handlebars conversion. Maps functions to helpers where an equivalent exists; flags unsupported functions and runtime gaps as `MANUAL_REWRITE_REQUIRED`. **Prefer the `convertAmpscriptToHandlebars` prompt** for interactive use. |
|
|
166
|
+
| `convertHandlebarsToAmpscript` | Rule-based MCN Handlebars → AMPscript conversion. Maps helpers and bindings back to AMPscript; flags block helpers as `MANUAL_REWRITE_REQUIRED`. **Prefer the `convertHandlebarsToAmpscript` prompt** for interactive use. |
|
|
167
|
+
| `convertSsjsToHandlebars` | Transitive SSJS → AMPscript → MCN Handlebars conversion. Conservatively flags imperative SSJS for manual rewrite. **Prefer the `convertSsjsToHandlebars` prompt** for interactive use. |
|
|
168
|
+
| `write_handlebars` | Validate an MCN Handlebars-in-HTML draft against the helper catalog. **Prefer the `writeHandlebars` prompt** for authoring. |
|
|
159
169
|
| `search_help` | **Unified help search** — auto-detects the platform from `projectRoot` and routes to the right doc index. MCN projects search both the developer API reference and MCN admin docs. Pass `target` to override detection. |
|
|
160
170
|
| `search_mce_help` | Search bundled Marketing Cloud Engagement setup/ops help; use `product_focus` to target Engagement vs Next |
|
|
161
171
|
| `search_mcn_help` | Search bundled Marketing Cloud Next developer API documentation (objects, flows, segments, REST/SOAP APIs, AMPscript behavior in MCN) |
|
|
@@ -168,6 +178,8 @@ Then replace `"command": "npx", "args": ["-y", "mcp-server-sfmc@latest"]` with:
|
|
|
168
178
|
| `sfmc://ssjs/functions` | Full SSJS function catalog |
|
|
169
179
|
| `sfmc://ampscript/keywords` | All AMPscript keywords |
|
|
170
180
|
| `sfmc://ssjs/unsupported-syntax` | ES6+ features not supported in SFMC SSJS |
|
|
181
|
+
| `sfmc://handlebars/helpers` | Full MCN Handlebars helper catalog with signatures, origin, and MCN API version |
|
|
182
|
+
| `sfmc://handlebars/bindings` | MCN Handlebars data bindings (context variables available in templates) |
|
|
171
183
|
| `sfmc://mce/product-context` | How **Marketing Cloud Engagement** differs from **Marketing Cloud Next** (when to use which) |
|
|
172
184
|
| `sfmc://mce/help-index` | List of bundled MCE help files and section counts per product scope |
|
|
173
185
|
| `sfmc://mcn/help-index` | List of bundled MCN developer API doc files and chunk counts |
|
|
@@ -184,11 +196,15 @@ Access via `/mcp.sfmc.writeAmpscript` etc. in VS Code, or via the prompts API:
|
|
|
184
196
|
| `rewrite_for_mcn` | **Primary interface for MCN migration.** Internally calls the `rewrite_for_mcn` tool for all deterministic rewrites, then applies AI reasoning to every `MANUAL_REWRITE_REQUIRED` section — producing a single fully migrated code block with a prose changelog. You always get both the rule-based pass and the AI pass in one step. |
|
|
185
197
|
| `convertSsjsToAmpscript` | **Primary interface for SSJS → AMPscript conversion.** Internally calls the `convertSsjsToAmpscript` tool for rule-based conversion, then AI-reasons over any sections the rules could not handle. |
|
|
186
198
|
| `convertAmpscriptToSsjs` | **Primary interface for AMPscript → SSJS conversion.** Internally calls the `convertAmpscriptToSsjs` tool for rule-based conversion, then applies AI reasoning to flagged AMPscript-only constructs. |
|
|
199
|
+
| `writeHandlebars` | Generate MCN Handlebars-in-HTML for a described task, constrained to the locked-down MCN helper catalog. Validates the draft against `handlebars-data` and reports unsupported constructs. |
|
|
200
|
+
| `convertAmpscriptToHandlebars` | **Primary interface for AMPscript → MCN Handlebars conversion.** Internally calls the `convertAmpscriptToHandlebars` tool for rule-based conversion, then AI-reasons over functions with no Handlebars equivalent (runtime gaps and unsupported functions). |
|
|
201
|
+
| `convertHandlebarsToAmpscript` | **Primary interface for MCN Handlebars → AMPscript conversion.** Internally calls the `convertHandlebarsToAmpscript` tool for rule-based conversion, then AI-reasons over block helpers and constructs the rules could not handle. |
|
|
202
|
+
| `convertSsjsToHandlebars` | **Primary interface for SSJS → MCN Handlebars conversion.** Transitive (SSJS → AMPscript → Handlebars); calls the `convertSsjsToHandlebars` tool, then applies AI reasoning to imperative SSJS flagged for manual rewrite. |
|
|
187
203
|
| `answerMceHowTo` | Guided prompt for admin/setup questions — searches bundled help and keeps Engagement vs Next explicit |
|
|
188
204
|
|
|
189
205
|
## Migrating code to Marketing Cloud Next
|
|
190
206
|
|
|
191
|
-
Marketing Cloud Next (MCN) supports **41 of the
|
|
207
|
+
Marketing Cloud Next (MCN) supports **41 of the 155 AMPscript functions** and **does not support SSJS**. Three supported functions have behavioral differences (see below). The migration toolkit guides you from analysis through to a fully rewritten result.
|
|
192
208
|
|
|
193
209
|
### Recommended workflow
|
|
194
210
|
|
|
@@ -243,6 +259,34 @@ The same hybrid pattern applies to `convertSsjsToAmpscript` and `convertAmpscrip
|
|
|
243
259
|
|
|
244
260
|
Functions that depend on CloudPages context (`CloudPagesURL`, `RequestParameter`, `QueryParameter`, `Redirect`, `MicrositeURL`) have no equivalent in Marketing Cloud Next. `check_mcn_compatibility` and `rewrite_for_mcn` flag these as **Not migratable** immediately.
|
|
245
261
|
|
|
262
|
+
## MCN Handlebars
|
|
263
|
+
|
|
264
|
+
Marketing Cloud Next embeds a **locked-down Handlebars** templating layer (Handlebars.Net) alongside AMPscript. The server exposes the full helper catalog and conversion tooling, all data-driven from [`handlebars-data`](https://www.npmjs.com/package/handlebars-data) and the `handlebarsEquivalent` / `mcnHandlebarsGap` fields in [`ampscript-data`](https://www.npmjs.com/package/ampscript-data) — nothing is hand-maintained.
|
|
265
|
+
|
|
266
|
+
### Authoring & lookup
|
|
267
|
+
|
|
268
|
+
```
|
|
269
|
+
1. list_handlebars_helpers → browse the catalog (filter by category / origin)
|
|
270
|
+
2. lookup_handlebars_helper → signature, parameters, origin, MCN API version
|
|
271
|
+
3. get_handlebars_completions → prefix-filtered completions
|
|
272
|
+
4. writeHandlebars prompt → generate Handlebars-in-HTML, validated against the catalog
|
|
273
|
+
5. validate_handlebars → helper names, arity, block balance, unsupported constructs
|
|
274
|
+
```
|
|
275
|
+
|
|
276
|
+
`validate_handlebars` rejects constructs the MCN engine does not implement — partials (`{{> name}}`), decorators (`{{#* ...}}`), and built-in helpers absent from the locked-down runtime.
|
|
277
|
+
|
|
278
|
+
### Conversion categories
|
|
279
|
+
|
|
280
|
+
AMPscript → Handlebars conversion classifies every function from `ampscript-data`:
|
|
281
|
+
|
|
282
|
+
| Category | Condition (in `ampscript-data`) | Output |
|
|
283
|
+
| -------- | ----------------------------------------------------- | ----------------------------------------------------------------- |
|
|
284
|
+
| **A** | `handlebarsEquivalent` is a helper name | Mapped to the canonical MCN Handlebars helper |
|
|
285
|
+
| **B** | No Handlebars counterpart | `{{!-- MANUAL_REWRITE_REQUIRED: … no Handlebars equivalent --}}` |
|
|
286
|
+
| **C** | `mcnHandlebarsGap: true` (MCN-supported, no helper yet) | `{{!-- MANUAL_REWRITE_REQUIRED: … (runtime gap) --}}` (distinct note) |
|
|
287
|
+
|
|
288
|
+
The Category C note is intentionally distinct from Category B so consumers can tell a *runtime gap* (function works in MCN AMPscript but has no Handlebars helper) apart from a function with no MCN counterpart at all. `convertSsjsToHandlebars` is transitive (SSJS → AMPscript → Handlebars) and conservatively flags imperative SSJS for manual rewrite.
|
|
289
|
+
|
|
246
290
|
## Writing effective prompts
|
|
247
291
|
|
|
248
292
|
### Automatic tool use
|
|
@@ -262,6 +306,8 @@ Clients that honour the MCP `instructions` field (Cursor, Claude Desktop, GitHub
|
|
|
262
306
|
| Check if code is MCN-ready | Use `check_mcn_compatibility` with your file contents. |
|
|
263
307
|
| Migrate code to Marketing Cloud Next | Use the `rewrite_for_mcn` **prompt** — it calls the tool internally for deterministic rewrites, then applies AI reasoning to any remaining manual sections. Use the tool directly only when you need structured JSON output in a pipeline. |
|
|
264
308
|
| Convert SSJS ↔ AMPscript | Use the `convertSsjsToAmpscript` or `convertAmpscriptToSsjs` **prompt** — same hybrid pattern: tool runs first, AI handles what the rules couldn't. |
|
|
309
|
+
| Write or validate MCN Handlebars | Use the `writeHandlebars` prompt to author, or `validate_handlebars` to check existing template code. Look helpers up with `lookup_handlebars_helper` / `list_handlebars_helpers`. |
|
|
310
|
+
| Convert AMPscript ↔ Handlebars (or SSJS → Handlebars) | Use the `convertAmpscriptToHandlebars`, `convertHandlebarsToAmpscript`, or `convertSsjsToHandlebars` **prompt** — same hybrid pattern: tool runs first, AI handles what the rules couldn't. |
|
|
265
311
|
| Review a code diff | Use the `reviewSfmcCode` prompt or mention "review the following diff". |
|
|
266
312
|
|
|
267
313
|
### Copy-paste prompt templates
|
|
@@ -496,9 +542,13 @@ The `@eslint/mcp` server exposes an `eslint_lint` tool that your AI can call to
|
|
|
496
542
|
|
|
497
543
|
```
|
|
498
544
|
mcp-server-sfmc
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
545
|
+
├── sfmc-language-lsp (language intelligence core)
|
|
546
|
+
│ ├── ampscript-data (AMPscript function catalog)
|
|
547
|
+
│ ├── ssjs-data (SSJS function catalog)
|
|
548
|
+
│ └── handlebars-data (MCN Handlebars helper catalog)
|
|
549
|
+
├── ampscript-data (direct — conversion maps, mcnSince, handlebarsEquivalent)
|
|
550
|
+
├── ssjs-data (direct — Platform.Function ↔ AMPscript mapping)
|
|
551
|
+
└── handlebars-data (direct — AMPscript ↔ Handlebars conversion)
|
|
502
552
|
|
|
503
553
|
vscode-sfmc-language (VS Code extension)
|
|
504
554
|
└── sfmc-language-lsp (same core, bundled via esbuild)
|
package/dist/cli/reviewDiff.d.ts
CHANGED
|
@@ -2,21 +2,5 @@
|
|
|
2
2
|
/**
|
|
3
3
|
* sfmc-review-diff — CI helper: spawn mcp-server-sfmc and call review_change on a unified diff.
|
|
4
4
|
*/
|
|
5
|
-
export
|
|
6
|
-
export interface SeverityCounts {
|
|
7
|
-
errors: number;
|
|
8
|
-
warnings: number;
|
|
9
|
-
infos: number;
|
|
10
|
-
}
|
|
11
|
-
/**
|
|
12
|
-
* Counts diagnostic lines emitted by the review_change tool (see src/index.ts).
|
|
13
|
-
* @param output
|
|
14
|
-
*/
|
|
15
|
-
export declare function countReviewSeverities(output: string): SeverityCounts;
|
|
16
|
-
/**
|
|
17
|
-
* Whether the CLI should exit with code 1 given counts and --fail-on policy.
|
|
18
|
-
* @param counts
|
|
19
|
-
* @param failOn
|
|
20
|
-
*/
|
|
21
|
-
export declare function shouldFail(counts: SeverityCounts, failOn: FailOnLevel): boolean;
|
|
5
|
+
export {};
|
|
22
6
|
//# sourceMappingURL=reviewDiff.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"reviewDiff.d.ts","sourceRoot":"","sources":["../../src/cli/reviewDiff.ts"],"names":[],"mappings":";AACA;;GAEG
|
|
1
|
+
{"version":3,"file":"reviewDiff.d.ts","sourceRoot":"","sources":["../../src/cli/reviewDiff.ts"],"names":[],"mappings":";AACA;;GAEG"}
|
package/dist/cli/reviewDiff.js
CHANGED
|
@@ -8,41 +8,11 @@ import { fileURLToPath } from 'node:url';
|
|
|
8
8
|
import path from 'node:path';
|
|
9
9
|
import { Client } from '@modelcontextprotocol/sdk/client/index.js';
|
|
10
10
|
import { StdioClientTransport } from '@modelcontextprotocol/sdk/client/stdio.js';
|
|
11
|
-
|
|
12
|
-
* Counts diagnostic lines emitted by the review_change tool (see src/index.ts).
|
|
13
|
-
* @param output
|
|
14
|
-
*/
|
|
15
|
-
export function countReviewSeverities(output) {
|
|
16
|
-
let errors = 0;
|
|
17
|
-
let warnings = 0;
|
|
18
|
-
let infos = 0;
|
|
19
|
-
for (const line of output.split('\n')) {
|
|
20
|
-
if (line.startsWith('🔴 ERROR'))
|
|
21
|
-
errors += 1;
|
|
22
|
-
else if (line.startsWith('🟡 WARNING'))
|
|
23
|
-
warnings += 1;
|
|
24
|
-
else if (line.startsWith('🔵 INFO'))
|
|
25
|
-
infos += 1;
|
|
26
|
-
}
|
|
27
|
-
return { errors, warnings, infos };
|
|
28
|
-
}
|
|
29
|
-
/**
|
|
30
|
-
* Whether the CLI should exit with code 1 given counts and --fail-on policy.
|
|
31
|
-
* @param counts
|
|
32
|
-
* @param failOn
|
|
33
|
-
*/
|
|
34
|
-
export function shouldFail(counts, failOn) {
|
|
35
|
-
if (counts.errors > 0)
|
|
36
|
-
return true;
|
|
37
|
-
if ((failOn === 'warning' || failOn === 'info') && counts.warnings > 0)
|
|
38
|
-
return true;
|
|
39
|
-
if (failOn === 'info' && counts.infos > 0)
|
|
40
|
-
return true;
|
|
41
|
-
return false;
|
|
42
|
-
}
|
|
11
|
+
import { countReviewSeverities, shouldFail } from './reviewSeverity.js';
|
|
43
12
|
function toolResultToText(result) {
|
|
44
13
|
const parts = [];
|
|
45
|
-
|
|
14
|
+
const contentBlocks = result.content ?? [];
|
|
15
|
+
for (const block of contentBlocks) {
|
|
46
16
|
if (block.type === 'text' && 'text' in block && typeof block.text === 'string') {
|
|
47
17
|
parts.push(block.text);
|
|
48
18
|
}
|
|
@@ -52,7 +22,9 @@ function toolResultToText(result) {
|
|
|
52
22
|
function readStdin() {
|
|
53
23
|
return new Promise((resolve, reject) => {
|
|
54
24
|
const chunks = [];
|
|
55
|
-
stdin.on('data', (c) =>
|
|
25
|
+
stdin.on('data', (c) => {
|
|
26
|
+
chunks.push(c);
|
|
27
|
+
});
|
|
56
28
|
stdin.on('end', () => resolve(Buffer.concat(chunks).toString('utf8')));
|
|
57
29
|
stdin.on('error', reject);
|
|
58
30
|
});
|
|
@@ -66,11 +38,11 @@ function serverEntryPath() {
|
|
|
66
38
|
const here = path.dirname(fileURLToPath(import.meta.url));
|
|
67
39
|
return path.join(here, '..', 'index.js');
|
|
68
40
|
}
|
|
69
|
-
function
|
|
41
|
+
function packageVersion() {
|
|
70
42
|
try {
|
|
71
43
|
const p = path.join(projectRoot(), 'package.json');
|
|
72
|
-
const
|
|
73
|
-
return
|
|
44
|
+
const index = JSON.parse(readFileSync(p, 'utf8'));
|
|
45
|
+
return index.version ?? '0.0.0';
|
|
74
46
|
}
|
|
75
47
|
catch {
|
|
76
48
|
return '0.0.0';
|
|
@@ -95,20 +67,20 @@ Exit codes:
|
|
|
95
67
|
1 Review findings matched the failure policy, MCP error, or I/O error
|
|
96
68
|
`);
|
|
97
69
|
}
|
|
98
|
-
function
|
|
70
|
+
function parseArguments(argv) {
|
|
99
71
|
let failOn = 'error';
|
|
100
72
|
let language;
|
|
101
73
|
let maxProblems;
|
|
102
|
-
let
|
|
74
|
+
let isHelp = false;
|
|
103
75
|
const positional = [];
|
|
104
|
-
for (let
|
|
105
|
-
const a = argv[
|
|
76
|
+
for (let index = 0; index < argv.length; index++) {
|
|
77
|
+
const a = argv[index];
|
|
106
78
|
if (a === '-h' || a === '--help') {
|
|
107
|
-
|
|
79
|
+
isHelp = true;
|
|
108
80
|
continue;
|
|
109
81
|
}
|
|
110
82
|
if (a === '--fail-on') {
|
|
111
|
-
const v = argv[++
|
|
83
|
+
const v = argv[++index];
|
|
112
84
|
if (v !== 'error' && v !== 'warning' && v !== 'info') {
|
|
113
85
|
throw new Error(`--fail-on must be error, warning, or info, got: ${v ?? '(missing)'}`);
|
|
114
86
|
}
|
|
@@ -116,7 +88,7 @@ function parseArgs(argv) {
|
|
|
116
88
|
continue;
|
|
117
89
|
}
|
|
118
90
|
if (a === '--language') {
|
|
119
|
-
const v = argv[++
|
|
91
|
+
const v = argv[++index];
|
|
120
92
|
if (v !== 'ampscript' && v !== 'ssjs' && v !== 'html' && v !== 'auto') {
|
|
121
93
|
throw new Error(`--language must be ampscript, ssjs, html, or auto`);
|
|
122
94
|
}
|
|
@@ -124,8 +96,8 @@ function parseArgs(argv) {
|
|
|
124
96
|
continue;
|
|
125
97
|
}
|
|
126
98
|
if (a === '--max-problems') {
|
|
127
|
-
const v = argv[++
|
|
128
|
-
const n = v ? Number
|
|
99
|
+
const v = argv[++index];
|
|
100
|
+
const n = v ? Number(v) : NaN;
|
|
129
101
|
if (!Number.isFinite(n) || n < 1) {
|
|
130
102
|
throw new Error(`--max-problems must be a positive integer`);
|
|
131
103
|
}
|
|
@@ -145,7 +117,7 @@ function parseArgs(argv) {
|
|
|
145
117
|
failOn,
|
|
146
118
|
language,
|
|
147
119
|
maxProblems,
|
|
148
|
-
help,
|
|
120
|
+
help: isHelp,
|
|
149
121
|
};
|
|
150
122
|
}
|
|
151
123
|
function isExecutedDirectly() {
|
|
@@ -162,7 +134,7 @@ function isExecutedDirectly() {
|
|
|
162
134
|
async function main() {
|
|
163
135
|
let parsed;
|
|
164
136
|
try {
|
|
165
|
-
parsed =
|
|
137
|
+
parsed = parseArguments(process.argv.slice(2));
|
|
166
138
|
}
|
|
167
139
|
catch (ex) {
|
|
168
140
|
// eslint-disable-next-line no-console -- intentional CLI error output
|
|
@@ -183,18 +155,18 @@ async function main() {
|
|
|
183
155
|
});
|
|
184
156
|
const client = new Client({
|
|
185
157
|
name: 'sfmc-review-diff',
|
|
186
|
-
version:
|
|
158
|
+
version: packageVersion(),
|
|
187
159
|
});
|
|
188
160
|
try {
|
|
189
161
|
await client.connect(transport);
|
|
190
|
-
const
|
|
162
|
+
const arguments_ = { diff: diffText };
|
|
191
163
|
if (parsed.language !== undefined)
|
|
192
|
-
|
|
164
|
+
arguments_.language = parsed.language;
|
|
193
165
|
if (parsed.maxProblems !== undefined)
|
|
194
|
-
|
|
166
|
+
arguments_.maxProblems = parsed.maxProblems;
|
|
195
167
|
const result = await client.callTool({
|
|
196
168
|
name: 'review_change',
|
|
197
|
-
arguments:
|
|
169
|
+
arguments: arguments_,
|
|
198
170
|
});
|
|
199
171
|
const text = toolResultToText(result);
|
|
200
172
|
process.stdout.write(text);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"reviewDiff.js","sourceRoot":"","sources":["../../src/cli/reviewDiff.ts"],"names":[],"mappings":";AACA;;GAEG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,KAAK,EAAE,MAAM,cAAc,CAAC;AACrC,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,MAAM,EAAE,MAAM,2CAA2C,CAAC;AACnE,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;
|
|
1
|
+
{"version":3,"file":"reviewDiff.js","sourceRoot":"","sources":["../../src/cli/reviewDiff.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Severity parsing helpers for the sfmc-review-diff CLI. Kept in a dedicated
|
|
3
|
+
* module (no shebang) so the pure, unit-tested logic is importable without the
|
|
4
|
+
* executable CLI entry point.
|
|
5
|
+
*/
|
|
6
|
+
export type FailOnLevel = 'error' | 'warning' | 'info';
|
|
7
|
+
export interface SeverityCounts {
|
|
8
|
+
errors: number;
|
|
9
|
+
warnings: number;
|
|
10
|
+
infos: number;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Counts diagnostic lines emitted by the review_change tool (see src/index.ts).
|
|
14
|
+
* @param output
|
|
15
|
+
*/
|
|
16
|
+
export declare function countReviewSeverities(output: string): SeverityCounts;
|
|
17
|
+
/**
|
|
18
|
+
* Whether the CLI should exit with code 1 given counts and --fail-on policy.
|
|
19
|
+
* @param counts
|
|
20
|
+
* @param failOn
|
|
21
|
+
*/
|
|
22
|
+
export declare function shouldFail(counts: SeverityCounts, failOn: FailOnLevel): boolean;
|
|
23
|
+
//# sourceMappingURL=reviewSeverity.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"reviewSeverity.d.ts","sourceRoot":"","sources":["../../src/cli/reviewSeverity.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,MAAM,MAAM,WAAW,GAAG,OAAO,GAAG,SAAS,GAAG,MAAM,CAAC;AAEvD,MAAM,WAAW,cAAc;IAC3B,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;CACjB;AAED;;;GAGG;AACH,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,MAAM,GAAG,cAAc,CAUpE;AAED;;;;GAIG;AACH,wBAAgB,UAAU,CAAC,MAAM,EAAE,cAAc,EAAE,MAAM,EAAE,WAAW,GAAG,OAAO,CAI/E"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Severity parsing helpers for the sfmc-review-diff CLI. Kept in a dedicated
|
|
3
|
+
* module (no shebang) so the pure, unit-tested logic is importable without the
|
|
4
|
+
* executable CLI entry point.
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* Counts diagnostic lines emitted by the review_change tool (see src/index.ts).
|
|
8
|
+
* @param output
|
|
9
|
+
*/
|
|
10
|
+
export function countReviewSeverities(output) {
|
|
11
|
+
let errors = 0;
|
|
12
|
+
let warnings = 0;
|
|
13
|
+
let infos = 0;
|
|
14
|
+
for (const line of output.split('\n')) {
|
|
15
|
+
if (line.startsWith('🔴 ERROR'))
|
|
16
|
+
errors += 1;
|
|
17
|
+
else if (line.startsWith('🟡 WARNING'))
|
|
18
|
+
warnings += 1;
|
|
19
|
+
else if (line.startsWith('🔵 INFO'))
|
|
20
|
+
infos += 1;
|
|
21
|
+
}
|
|
22
|
+
return { errors, warnings, infos };
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Whether the CLI should exit with code 1 given counts and --fail-on policy.
|
|
26
|
+
* @param counts
|
|
27
|
+
* @param failOn
|
|
28
|
+
*/
|
|
29
|
+
export function shouldFail(counts, failOn) {
|
|
30
|
+
if (counts.errors > 0)
|
|
31
|
+
return true;
|
|
32
|
+
if ((failOn === 'warning' || failOn === 'info') && counts.warnings > 0)
|
|
33
|
+
return true;
|
|
34
|
+
return failOn === 'info' && counts.infos > 0;
|
|
35
|
+
}
|
|
36
|
+
//# sourceMappingURL=reviewSeverity.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"reviewSeverity.js","sourceRoot":"","sources":["../../src/cli/reviewSeverity.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAUH;;;GAGG;AACH,MAAM,UAAU,qBAAqB,CAAC,MAAc;IAChD,IAAI,MAAM,GAAG,CAAC,CAAC;IACf,IAAI,QAAQ,GAAG,CAAC,CAAC;IACjB,IAAI,KAAK,GAAG,CAAC,CAAC;IACd,KAAK,MAAM,IAAI,IAAI,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;QACpC,IAAI,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC;YAAE,MAAM,IAAI,CAAC,CAAC;aACxC,IAAI,IAAI,CAAC,UAAU,CAAC,YAAY,CAAC;YAAE,QAAQ,IAAI,CAAC,CAAC;aACjD,IAAI,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC;YAAE,KAAK,IAAI,CAAC,CAAC;IACpD,CAAC;IACD,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC;AACvC,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,UAAU,CAAC,MAAsB,EAAE,MAAmB;IAClE,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC;QAAE,OAAO,IAAI,CAAC;IACnC,IAAI,CAAC,MAAM,KAAK,SAAS,IAAI,MAAM,KAAK,MAAM,CAAC,IAAI,MAAM,CAAC,QAAQ,GAAG,CAAC;QAAE,OAAO,IAAI,CAAC;IACpF,OAAO,MAAM,KAAK,MAAM,IAAI,MAAM,CAAC,KAAK,GAAG,CAAC,CAAC;AACjD,CAAC"}
|
|
@@ -34,6 +34,31 @@ export declare const PLATFORM_FUNCTION_TO_AMP: Readonly<Record<string, string>>;
|
|
|
34
34
|
* PLATFORM_FUNCTION_TO_AMP at module load time.
|
|
35
35
|
*/
|
|
36
36
|
export declare const AMP_TO_PLATFORM_FUNCTION: Readonly<Record<string, string>>;
|
|
37
|
+
/**
|
|
38
|
+
* Maps an AMPscript function name (lowercase) to the canonical MCN Handlebars
|
|
39
|
+
* helper name it converts to. Built at module load time from ampscript-data's
|
|
40
|
+
* `handlebarsEquivalent` field — always in sync with the installed
|
|
41
|
+
* ampscript-data version, never hand-edited (`mcp-conversion-rules-sync.mdc`).
|
|
42
|
+
*
|
|
43
|
+
* Only Category A functions (non-null string `handlebarsEquivalent`) are
|
|
44
|
+
* included. The stored value is the bare helper name; the canonical casing is
|
|
45
|
+
* resolved through `handlebars-data` so emitted `{{helper}}` calls match the
|
|
46
|
+
* catalog exactly.
|
|
47
|
+
*/
|
|
48
|
+
export declare const AMP_TO_HANDLEBARS: Readonly<Record<string, string>>;
|
|
49
|
+
/**
|
|
50
|
+
* Maps a canonical MCN Handlebars helper name (lowercase) to its AMPscript
|
|
51
|
+
* function name. Inverted from AMP_TO_HANDLEBARS at module load time. Used by
|
|
52
|
+
* convertHandlebarsToAmpscript.
|
|
53
|
+
*/
|
|
54
|
+
export declare const HANDLEBARS_TO_AMP: Readonly<Record<string, string>>;
|
|
55
|
+
/**
|
|
56
|
+
* Set of AMPscript function names (lowercase) flagged `mcnHandlebarsGap: true`
|
|
57
|
+
* in ampscript-data (Category C). These are documented as MCN-supported but
|
|
58
|
+
* currently fail at runtime and have no Handlebars helper — converting them
|
|
59
|
+
* must emit a MANUAL_REWRITE marker distinct from Category B (no counterpart).
|
|
60
|
+
*/
|
|
61
|
+
export declare const AMP_MCN_HANDLEBARS_GAP: ReadonlySet<string>;
|
|
37
62
|
/**
|
|
38
63
|
* Maps an AMPscript function name (lowercase) to a native JavaScript rewrite
|
|
39
64
|
* hint comment. Checked BEFORE the TreatAsContent polyfill fallback in
|
|
@@ -109,6 +134,53 @@ export declare function ampscriptToSsjs(code: string): ConversionResult;
|
|
|
109
134
|
* @returns {string} Expression with `@` prefixes removed.
|
|
110
135
|
*/
|
|
111
136
|
export declare function stripAmpVars(expr: string): string;
|
|
137
|
+
/**
|
|
138
|
+
* Distinct MANUAL_REWRITE note for Category C functions (`mcnHandlebarsGap`).
|
|
139
|
+
* Must be visibly different from the Category B note so consumers can tell a
|
|
140
|
+
* documented-but-broken function apart from one with no counterpart at all.
|
|
141
|
+
*/
|
|
142
|
+
export declare const HBS_GAP_NOTE = "documented as supported in Marketing Cloud Next but currently fails at runtime \u2014 no Handlebars helper exists yet";
|
|
143
|
+
/**
|
|
144
|
+
* Convert AMPscript to MCN Handlebars using deterministic, data-driven rules.
|
|
145
|
+
*
|
|
146
|
+
* Inline expressions (`%%=Fn(args)=%%`, `%%=v(@x)=%%`, `%%var%%`) are mapped via
|
|
147
|
+
* the three conversion categories built from ampscript-data's
|
|
148
|
+
* `handlebarsEquivalent` / `mcnHandlebarsGap` fields:
|
|
149
|
+
* - **A** — mapped helper → `{{helper …}}`
|
|
150
|
+
* - **B** — no counterpart → `{{!-- MANUAL_REWRITE_REQUIRED … --}}`
|
|
151
|
+
* - **C** — `mcnHandlebarsGap` → `{{!-- MANUAL_REWRITE_REQUIRED … (distinct note) --}}`
|
|
152
|
+
*
|
|
153
|
+
* Procedural AMPscript blocks (`%%[ … ]%%`, `SET`/`VAR`/`IF`/`FOR`) have no
|
|
154
|
+
* Handlebars counterpart (Handlebars cannot assign variables or run imperative
|
|
155
|
+
* control flow) and are flagged MANUAL_REWRITE_REQUIRED.
|
|
156
|
+
* @param code - AMPscript source code (may include HTML context).
|
|
157
|
+
* @returns {ConversionResult} Converted Handlebars, change log, and flagged sections.
|
|
158
|
+
*/
|
|
159
|
+
export declare function ampscriptToHandlebars(code: string): ConversionResult;
|
|
160
|
+
/**
|
|
161
|
+
* Convert MCN Handlebars to AMPscript using deterministic, data-driven rules.
|
|
162
|
+
*
|
|
163
|
+
* Inline helper calls (`{{helper args}}`) whose helper maps back to an AMPscript
|
|
164
|
+
* function (via HANDLEBARS_TO_AMP) become `%%=Fn(args)=%%`; bare variables
|
|
165
|
+
* (`{{name}}`) become `%%=v(@name)=%%`. Block helpers (`{{#each}}`…), partials
|
|
166
|
+
* (`{{> …}}`), dotted binding paths, and unknown helpers are flagged
|
|
167
|
+
* MANUAL_REWRITE_REQUIRED.
|
|
168
|
+
* @param code - Handlebars source code (may include HTML context).
|
|
169
|
+
* @returns {ConversionResult} Converted AMPscript, change log, and flagged sections.
|
|
170
|
+
*/
|
|
171
|
+
export declare function handlebarsToAmpscript(code: string): ConversionResult;
|
|
172
|
+
/**
|
|
173
|
+
* Convert SSJS to MCN Handlebars deterministically via a two-step chain:
|
|
174
|
+
* SSJS → AMPscript (`ssjsToAmpscript`) → Handlebars (`ampscriptToHandlebars`).
|
|
175
|
+
*
|
|
176
|
+
* Because Handlebars is declarative, most imperative SSJS has no Handlebars
|
|
177
|
+
* counterpart and is conservatively flagged MANUAL_REWRITE_REQUIRED; inline
|
|
178
|
+
* `Platform.Function.X(…)` calls that map through AMPscript to a Handlebars
|
|
179
|
+
* helper are converted.
|
|
180
|
+
* @param code - SSJS source code (may include `<script runat="server">` tags).
|
|
181
|
+
* @returns {ConversionResult} Converted Handlebars, combined change log, and flagged sections.
|
|
182
|
+
*/
|
|
183
|
+
export declare function ssjsToHandlebars(code: string): ConversionResult;
|
|
112
184
|
export interface McnRewriteOptions {
|
|
113
185
|
/** Function to check if an AMPscript function is MCN-supported */
|
|
114
186
|
isMcnSupportedFn: (name: string) => boolean;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"conversion-rules.d.ts","sourceRoot":"","sources":["../src/conversion-rules.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAMH,MAAM,WAAW,WAAW;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,cAAc;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,gBAAgB;IAC7B,aAAa,EAAE,MAAM,CAAC;IACtB,OAAO,EAAE,WAAW,EAAE,CAAC;IACvB,eAAe,EAAE,cAAc,EAAE,CAAC;CACrC;AAQD;;;;;GAKG;AACH,eAAO,MAAM,wBAAwB,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAMrE,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,wBAAwB,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAKrE,CAAC;
|
|
1
|
+
{"version":3,"file":"conversion-rules.d.ts","sourceRoot":"","sources":["../src/conversion-rules.ts"],"names":[],"mappings":"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"}
|