@salesforce/b2c-dx-mcp 2.0.0 → 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 +15 -62
- package/dist/commands/mcp.d.ts +1 -0
- package/dist/commands/mcp.js +47 -9
- package/dist/registry.d.ts +3 -4
- package/dist/registry.js +7 -14
- package/dist/services.d.ts +21 -1
- package/dist/services.js +38 -1
- package/dist/tools/adapter.d.ts +19 -2
- package/dist/tools/adapter.js +49 -10
- package/dist/tools/cartridges/index.js +11 -3
- package/dist/tools/diagnostics/config-inspect.js +2 -2
- package/dist/tools/diagnostics/debug-list-sessions.js +1 -0
- package/dist/tools/diagnostics/debug-start-session.js +13 -2
- package/dist/tools/diagnostics/log-watch-registry.d.ts +3 -0
- package/dist/tools/diagnostics/log-watch-registry.js +1 -0
- package/dist/tools/diagnostics/logs-watch-list.js +1 -0
- package/dist/tools/diagnostics/logs-watch-start.js +6 -1
- package/dist/tools/diagnostics/mrt-log-watch-registry.d.ts +3 -0
- package/dist/tools/diagnostics/mrt-log-watch-registry.js +0 -0
- package/dist/tools/diagnostics/mrt-logs-watch-list.js +1 -0
- package/dist/tools/diagnostics/mrt-logs-watch-start.js +7 -1
- package/dist/tools/diagnostics/session-registry.d.ts +3 -0
- package/dist/tools/diagnostics/session-registry.js +2 -1
- package/dist/tools/index.d.ts +0 -1
- package/dist/tools/index.js +0 -1
- package/dist/tools/mrt/index.js +4 -0
- package/dist/tools/project-context.d.ts +42 -11
- package/dist/tools/project-context.js +48 -15
- package/dist/tools/scapi/metrics-get.js +1 -1
- package/dist/tools/scapi/scapi-custom-api-generate-scaffold.d.ts +4 -0
- package/dist/tools/scapi/scapi-custom-api-generate-scaffold.js +27 -7
- package/dist/tools/scapi/scapi-custom-apis-get-status.js +1 -1
- package/dist/tools/scapi/scapi-schemas-list.js +1 -0
- package/dist/utils/constants.d.ts +2 -13
- package/dist/utils/constants.js +1 -20
- package/oclif.manifest.json +2 -2
- package/package.json +3 -3
- package/content/sfnext/auth.md +0 -62
- package/content/sfnext/components.md +0 -123
- package/content/sfnext/config.md +0 -180
- package/content/sfnext/data-fetching.md +0 -323
- package/content/sfnext/extensions.md +0 -80
- package/content/sfnext/i18n.md +0 -121
- package/content/sfnext/page-designer.md +0 -78
- package/content/sfnext/performance.md +0 -80
- package/content/sfnext/pitfalls.md +0 -141
- package/content/sfnext/quick-reference.md +0 -226
- package/content/sfnext/state-management.md +0 -75
- package/content/sfnext/styling.md +0 -51
- package/content/sfnext/testing.md +0 -232
- package/dist/tools/storefrontnext/figma/figma-to-component/figma-url-parser.d.ts +0 -24
- package/dist/tools/storefrontnext/figma/figma-to-component/figma-url-parser.js +0 -53
- package/dist/tools/storefrontnext/figma/figma-to-component/index.d.ts +0 -45
- package/dist/tools/storefrontnext/figma/figma-to-component/index.js +0 -332
- package/dist/tools/storefrontnext/figma/generate-component/decision.d.ts +0 -40
- package/dist/tools/storefrontnext/figma/generate-component/decision.js +0 -312
- package/dist/tools/storefrontnext/figma/generate-component/formatter.d.ts +0 -9
- package/dist/tools/storefrontnext/figma/generate-component/formatter.js +0 -92
- package/dist/tools/storefrontnext/figma/generate-component/index.d.ts +0 -117
- package/dist/tools/storefrontnext/figma/generate-component/index.js +0 -102
- package/dist/tools/storefrontnext/figma/map-tokens/css-parser.d.ts +0 -71
- package/dist/tools/storefrontnext/figma/map-tokens/css-parser.js +0 -260
- package/dist/tools/storefrontnext/figma/map-tokens/index.d.ts +0 -64
- package/dist/tools/storefrontnext/figma/map-tokens/index.js +0 -242
- package/dist/tools/storefrontnext/figma/map-tokens/token-matcher.d.ts +0 -65
- package/dist/tools/storefrontnext/figma/map-tokens/token-matcher.js +0 -268
- package/dist/tools/storefrontnext/index.d.ts +0 -30
- package/dist/tools/storefrontnext/index.js +0 -28
- package/dist/tools/storefrontnext/page-designer-decorator/analyzer.d.ts +0 -169
- package/dist/tools/storefrontnext/page-designer-decorator/analyzer.js +0 -567
- package/dist/tools/storefrontnext/page-designer-decorator/index.d.ts +0 -259
- package/dist/tools/storefrontnext/page-designer-decorator/index.js +0 -622
- package/dist/tools/storefrontnext/page-designer-decorator/rules/1-mode-selection.d.ts +0 -8
- package/dist/tools/storefrontnext/page-designer-decorator/rules/1-mode-selection.js +0 -65
- package/dist/tools/storefrontnext/page-designer-decorator/rules/2a-auto-mode.d.ts +0 -13
- package/dist/tools/storefrontnext/page-designer-decorator/rules/2a-auto-mode.js +0 -87
- package/dist/tools/storefrontnext/page-designer-decorator/rules/2b-0-interactive-overview.d.ts +0 -4
- package/dist/tools/storefrontnext/page-designer-decorator/rules/2b-0-interactive-overview.js +0 -55
- package/dist/tools/storefrontnext/page-designer-decorator/rules/2b-1-interactive-analyze.d.ts +0 -22
- package/dist/tools/storefrontnext/page-designer-decorator/rules/2b-1-interactive-analyze.js +0 -109
- package/dist/tools/storefrontnext/page-designer-decorator/rules/2b-2-interactive-select-props.d.ts +0 -21
- package/dist/tools/storefrontnext/page-designer-decorator/rules/2b-2-interactive-select-props.js +0 -60
- package/dist/tools/storefrontnext/page-designer-decorator/rules/2b-3-interactive-configure-attrs.d.ts +0 -27
- package/dist/tools/storefrontnext/page-designer-decorator/rules/2b-3-interactive-configure-attrs.js +0 -68
- package/dist/tools/storefrontnext/page-designer-decorator/rules/2b-4-interactive-configure-regions.d.ts +0 -4
- package/dist/tools/storefrontnext/page-designer-decorator/rules/2b-4-interactive-configure-regions.js +0 -65
- package/dist/tools/storefrontnext/page-designer-decorator/rules/2b-5-interactive-confirm-generation.d.ts +0 -11
- package/dist/tools/storefrontnext/page-designer-decorator/rules/2b-5-interactive-confirm-generation.js +0 -92
- package/dist/tools/storefrontnext/page-designer-decorator/rules.d.ts +0 -51
- package/dist/tools/storefrontnext/page-designer-decorator/rules.js +0 -70
- package/dist/tools/storefrontnext/page-designer-decorator/templates/decorator-generator.d.ts +0 -116
- package/dist/tools/storefrontnext/page-designer-decorator/templates/decorator-generator.js +0 -350
- package/dist/tools/storefrontnext/sfnext-development-guidelines.d.ts +0 -9
- package/dist/tools/storefrontnext/sfnext-development-guidelines.js +0 -141
- package/dist/tools/storefrontnext/site-theming/color-contrast.d.ts +0 -92
- package/dist/tools/storefrontnext/site-theming/color-contrast.js +0 -186
- package/dist/tools/storefrontnext/site-theming/color-mapping.d.ts +0 -16
- package/dist/tools/storefrontnext/site-theming/color-mapping.js +0 -131
- package/dist/tools/storefrontnext/site-theming/guidance-merger.d.ts +0 -11
- package/dist/tools/storefrontnext/site-theming/guidance-merger.js +0 -78
- package/dist/tools/storefrontnext/site-theming/index.d.ts +0 -14
- package/dist/tools/storefrontnext/site-theming/index.js +0 -128
- package/dist/tools/storefrontnext/site-theming/response-builder.d.ts +0 -16
- package/dist/tools/storefrontnext/site-theming/response-builder.js +0 -316
- package/dist/tools/storefrontnext/site-theming/theming-store.d.ts +0 -64
- package/dist/tools/storefrontnext/site-theming/theming-store.js +0 -417
- package/dist/tools/storefrontnext/site-theming/types.d.ts +0 -36
- package/dist/tools/storefrontnext/site-theming/types.js +0 -7
|
@@ -1,65 +0,0 @@
|
|
|
1
|
-
import type { ThemeToken, ParsedTheme } from './css-parser.js';
|
|
2
|
-
/**
|
|
3
|
-
* Design token extracted from Figma.
|
|
4
|
-
*
|
|
5
|
-
* @property {string} name - Token name from Figma (e.g., "Primary/Blue", "Spacing/Large")
|
|
6
|
-
* @property {string} value - Token value (e.g., "#2563eb", "16px", "0.5rem")
|
|
7
|
-
* @property {'color'|'fontFamily'|'fontSize'|'opacity'|'other'|'radius'|'spacing'} type - Token type for matching logic
|
|
8
|
-
* @property {string} [description] - Optional description from Figma
|
|
9
|
-
*/
|
|
10
|
-
export interface FigmaToken {
|
|
11
|
-
name: string;
|
|
12
|
-
value: string;
|
|
13
|
-
type: 'color' | 'fontFamily' | 'fontSize' | 'opacity' | 'other' | 'radius' | 'spacing';
|
|
14
|
-
description?: string;
|
|
15
|
-
}
|
|
16
|
-
/**
|
|
17
|
-
* Result of matching a Figma token to theme tokens.
|
|
18
|
-
*
|
|
19
|
-
* @property {FigmaToken} figmaToken - The Figma token that was matched
|
|
20
|
-
* @property {ThemeToken} [matchedToken] - Best-matching theme token (if found)
|
|
21
|
-
* @property {number} confidence - Match confidence (0-100)
|
|
22
|
-
* @property {'exact'|'fuzzy'|'none'} matchType - 'exact', 'fuzzy', or 'none'
|
|
23
|
-
* @property {string} reason - Human-readable explanation of the match
|
|
24
|
-
* @property {TokenSuggestion[]} [suggestions] - Suggested new tokens or alternatives (when no match or fuzzy match)
|
|
25
|
-
*/
|
|
26
|
-
export interface TokenMatch {
|
|
27
|
-
figmaToken: FigmaToken;
|
|
28
|
-
matchedToken?: ThemeToken;
|
|
29
|
-
confidence: number;
|
|
30
|
-
matchType: 'exact' | 'fuzzy' | 'none';
|
|
31
|
-
reason: string;
|
|
32
|
-
suggestions?: TokenSuggestion[];
|
|
33
|
-
}
|
|
34
|
-
/**
|
|
35
|
-
* Suggestion for a new or alternative theme token.
|
|
36
|
-
*
|
|
37
|
-
* @property {string} tokenName - Suggested CSS custom property name
|
|
38
|
-
* @property {string} value - Token value
|
|
39
|
-
* @property {'both'|'dark'|'light'} theme - Which theme(s) to add to: 'both', 'dark', or 'light'
|
|
40
|
-
* @property {string} reason - Explanation for the suggestion
|
|
41
|
-
* @property {string} [insertAfter] - Optional token name to insert after in the theme file
|
|
42
|
-
*/
|
|
43
|
-
export interface TokenSuggestion {
|
|
44
|
-
tokenName: string;
|
|
45
|
-
value: string;
|
|
46
|
-
theme: 'both' | 'dark' | 'light';
|
|
47
|
-
reason: string;
|
|
48
|
-
insertAfter?: string;
|
|
49
|
-
}
|
|
50
|
-
/**
|
|
51
|
-
* Matches a single Figma token to existing theme tokens.
|
|
52
|
-
*
|
|
53
|
-
* @param figmaToken - Figma design token to match
|
|
54
|
-
* @param parsedTheme - Parsed theme from app.css
|
|
55
|
-
* @returns TokenMatch with exact, fuzzy, or no match and optional suggestions
|
|
56
|
-
*/
|
|
57
|
-
export declare function matchToken(figmaToken: FigmaToken, parsedTheme: ParsedTheme): TokenMatch;
|
|
58
|
-
/**
|
|
59
|
-
* Matches multiple Figma tokens to existing theme tokens.
|
|
60
|
-
*
|
|
61
|
-
* @param figmaTokens - Array of Figma design tokens to match
|
|
62
|
-
* @param parsedTheme - Parsed theme from app.css
|
|
63
|
-
* @returns Array of TokenMatch results, one per input token
|
|
64
|
-
*/
|
|
65
|
-
export declare function matchTokens(figmaTokens: FigmaToken[], parsedTheme: ParsedTheme): TokenMatch[];
|
|
@@ -1,268 +0,0 @@
|
|
|
1
|
-
/*
|
|
2
|
-
* Copyright (c) 2025, Salesforce, Inc.
|
|
3
|
-
* SPDX-License-Identifier: Apache-2
|
|
4
|
-
* For full license text, see the license.txt file in the repo root or http://www.apache.org/licenses/LICENSE-2.0
|
|
5
|
-
*/
|
|
6
|
-
/**
|
|
7
|
-
* Normalizes hex colors to lowercase 6-digit format
|
|
8
|
-
*/
|
|
9
|
-
function normalizeHexColor(hex) {
|
|
10
|
-
let normalized = hex.toLowerCase().trim();
|
|
11
|
-
// Remove # if present
|
|
12
|
-
if (normalized.startsWith('#')) {
|
|
13
|
-
normalized = normalized.slice(1);
|
|
14
|
-
}
|
|
15
|
-
// Expand 3-digit hex to 6-digit
|
|
16
|
-
if (normalized.length === 3) {
|
|
17
|
-
normalized = [...normalized].map((c) => c + c).join('');
|
|
18
|
-
}
|
|
19
|
-
return normalized;
|
|
20
|
-
}
|
|
21
|
-
/**
|
|
22
|
-
* Calculates color distance between two hex colors (0-100, lower is closer)
|
|
23
|
-
*/
|
|
24
|
-
function calculateColorDistance(hex1, hex2) {
|
|
25
|
-
const r1 = Number.parseInt(hex1.slice(0, 2), 16);
|
|
26
|
-
const g1 = Number.parseInt(hex1.slice(2, 4), 16);
|
|
27
|
-
const b1 = Number.parseInt(hex1.slice(4, 6), 16);
|
|
28
|
-
const r2 = Number.parseInt(hex2.slice(0, 2), 16);
|
|
29
|
-
const g2 = Number.parseInt(hex2.slice(2, 4), 16);
|
|
30
|
-
const b2 = Number.parseInt(hex2.slice(4, 6), 16);
|
|
31
|
-
// Euclidean distance normalized to 0-100 scale
|
|
32
|
-
const distance = Math.hypot(r1 - r2, g1 - g2, b1 - b2);
|
|
33
|
-
// Max distance is sqrt(255^2 * 3) ≈ 441
|
|
34
|
-
return (distance / 441) * 100;
|
|
35
|
-
}
|
|
36
|
-
/**
|
|
37
|
-
* Calculates string similarity between two strings (0-100, higher is more similar)
|
|
38
|
-
* Uses Levenshtein distance algorithm
|
|
39
|
-
*/
|
|
40
|
-
function calculateStringSimilarity(str1, str2) {
|
|
41
|
-
const s1 = str1.toLowerCase();
|
|
42
|
-
const s2 = str2.toLowerCase();
|
|
43
|
-
// Exact match
|
|
44
|
-
if (s1 === s2)
|
|
45
|
-
return 100;
|
|
46
|
-
// Contains match bonus
|
|
47
|
-
if (s1.includes(s2) || s2.includes(s1)) {
|
|
48
|
-
return 80 + (Math.min(s1.length, s2.length) / Math.max(s1.length, s2.length)) * 20;
|
|
49
|
-
}
|
|
50
|
-
// Levenshtein distance
|
|
51
|
-
const matrix = [];
|
|
52
|
-
const len1 = s1.length;
|
|
53
|
-
const len2 = s2.length;
|
|
54
|
-
for (let i = 0; i <= len1; i++) {
|
|
55
|
-
matrix[i] = [i];
|
|
56
|
-
}
|
|
57
|
-
for (let j = 0; j <= len2; j++) {
|
|
58
|
-
matrix[0][j] = j;
|
|
59
|
-
}
|
|
60
|
-
for (let i = 1; i <= len1; i++) {
|
|
61
|
-
for (let j = 1; j <= len2; j++) {
|
|
62
|
-
const cost = s1[i - 1] === s2[j - 1] ? 0 : 1;
|
|
63
|
-
matrix[i][j] = Math.min(matrix[i - 1][j] + 1, matrix[i][j - 1] + 1, matrix[i - 1][j - 1] + cost);
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
const distance = matrix[len1][len2];
|
|
67
|
-
const maxLen = Math.max(len1, len2);
|
|
68
|
-
return ((maxLen - distance) / maxLen) * 100;
|
|
69
|
-
}
|
|
70
|
-
/**
|
|
71
|
-
* Extracts semantic meaning from token name
|
|
72
|
-
*/
|
|
73
|
-
function extractSemantics(name) {
|
|
74
|
-
const parts = name.toLowerCase().replace(/^--/, '').split(/[-_]/);
|
|
75
|
-
const semantics = [];
|
|
76
|
-
// Color semantics
|
|
77
|
-
const colorKeywords = new Set([
|
|
78
|
-
'accent',
|
|
79
|
-
'background',
|
|
80
|
-
'border',
|
|
81
|
-
'destructive',
|
|
82
|
-
'error',
|
|
83
|
-
'foreground',
|
|
84
|
-
'info',
|
|
85
|
-
'muted',
|
|
86
|
-
'primary',
|
|
87
|
-
'secondary',
|
|
88
|
-
'success',
|
|
89
|
-
'text',
|
|
90
|
-
'warning',
|
|
91
|
-
]);
|
|
92
|
-
const lightDark = new Set(['dark', 'light']);
|
|
93
|
-
const colorNames = new Set(['black', 'blue', 'gray', 'green', 'orange', 'purple', 'red', 'white', 'yellow']);
|
|
94
|
-
for (const part of parts) {
|
|
95
|
-
if (colorKeywords.has(part)) {
|
|
96
|
-
semantics.push(`semantic:${part}`);
|
|
97
|
-
}
|
|
98
|
-
if (lightDark.has(part)) {
|
|
99
|
-
semantics.push(`theme:${part}`);
|
|
100
|
-
}
|
|
101
|
-
if (colorNames.has(part)) {
|
|
102
|
-
semantics.push(`color:${part}`);
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
return semantics;
|
|
106
|
-
}
|
|
107
|
-
/**
|
|
108
|
-
* Finds exact color match
|
|
109
|
-
*/
|
|
110
|
-
function findExactColorMatch(figmaValue, parsedTheme) {
|
|
111
|
-
const normalizedFigma = normalizeHexColor(figmaValue);
|
|
112
|
-
for (const token of parsedTheme.tokens) {
|
|
113
|
-
if (token.type === 'color' && token.resolvedValue) {
|
|
114
|
-
const normalizedToken = normalizeHexColor(token.resolvedValue);
|
|
115
|
-
if (normalizedFigma === normalizedToken) {
|
|
116
|
-
return token;
|
|
117
|
-
}
|
|
118
|
-
}
|
|
119
|
-
}
|
|
120
|
-
return null;
|
|
121
|
-
}
|
|
122
|
-
/**
|
|
123
|
-
* Finds fuzzy matches based on color similarity and name similarity
|
|
124
|
-
*/
|
|
125
|
-
function findFuzzyMatches(figmaToken, parsedTheme) {
|
|
126
|
-
const matches = [];
|
|
127
|
-
// Filter tokens by type
|
|
128
|
-
const relevantTokens = parsedTheme.tokens.filter((token) => token.type === figmaToken.type);
|
|
129
|
-
const figmaSemantics = extractSemantics(figmaToken.name);
|
|
130
|
-
const normalizedFigmaValue = figmaToken.type === 'color' && figmaToken.value.startsWith('#')
|
|
131
|
-
? normalizeHexColor(figmaToken.value)
|
|
132
|
-
: figmaToken.value;
|
|
133
|
-
for (const token of relevantTokens) {
|
|
134
|
-
let score = 0;
|
|
135
|
-
// Name similarity (40% weight)
|
|
136
|
-
const nameSimilarity = calculateStringSimilarity(figmaToken.name, token.name);
|
|
137
|
-
score += nameSimilarity * 0.4;
|
|
138
|
-
// Semantic similarity (30% weight)
|
|
139
|
-
const tokenSemantics = extractSemantics(token.name);
|
|
140
|
-
const semanticMatches = figmaSemantics.filter((s) => tokenSemantics.includes(s)).length;
|
|
141
|
-
const semanticScore = figmaSemantics.length > 0 ? (semanticMatches / figmaSemantics.length) * 100 : 0;
|
|
142
|
-
score += semanticScore * 0.3;
|
|
143
|
-
// Value similarity (30% weight)
|
|
144
|
-
if (figmaToken.type === 'color' && token.resolvedValue) {
|
|
145
|
-
const normalizedTokenValue = normalizeHexColor(token.resolvedValue);
|
|
146
|
-
const colorDistance = calculateColorDistance(normalizedFigmaValue, normalizedTokenValue);
|
|
147
|
-
const colorSimilarity = Math.max(0, 100 - colorDistance);
|
|
148
|
-
score += colorSimilarity * 0.3;
|
|
149
|
-
}
|
|
150
|
-
if (score > 20) {
|
|
151
|
-
// Only include matches with score > 20
|
|
152
|
-
matches.push({ token, score });
|
|
153
|
-
}
|
|
154
|
-
}
|
|
155
|
-
// Sort by score descending
|
|
156
|
-
return matches.sort((a, b) => b.score - a.score);
|
|
157
|
-
}
|
|
158
|
-
/**
|
|
159
|
-
* Generates suggestions for new tokens if no good match found
|
|
160
|
-
*/
|
|
161
|
-
function generateTokenSuggestions(figmaToken, parsedTheme) {
|
|
162
|
-
const suggestions = [];
|
|
163
|
-
// Analyze existing token naming patterns
|
|
164
|
-
const existingNames = parsedTheme.tokens.filter((t) => t.type === figmaToken.type).map((t) => t.name);
|
|
165
|
-
// Extract common prefixes
|
|
166
|
-
const hasColorPrefix = existingNames.some((n) => n.startsWith('--color-'));
|
|
167
|
-
const hasRadiusPrefix = existingNames.some((n) => n.startsWith('--radius-'));
|
|
168
|
-
// Generate token name based on Figma token name
|
|
169
|
-
let suggestedName = figmaToken.name.toLowerCase().replaceAll(/[^a-z0-9-]/g, '-');
|
|
170
|
-
// Add appropriate prefix if not present
|
|
171
|
-
if (figmaToken.type === 'color' && !suggestedName.startsWith('--color-') && hasColorPrefix) {
|
|
172
|
-
suggestedName = `--color-${suggestedName.replace(/^--/, '')}`;
|
|
173
|
-
}
|
|
174
|
-
else if (figmaToken.type === 'radius' && !suggestedName.startsWith('--radius-') && hasRadiusPrefix) {
|
|
175
|
-
suggestedName = `--radius-${suggestedName.replace(/^--/, '')}`;
|
|
176
|
-
}
|
|
177
|
-
else if (!suggestedName.startsWith('--')) {
|
|
178
|
-
suggestedName = `--${suggestedName}`;
|
|
179
|
-
}
|
|
180
|
-
// Find a good place to insert
|
|
181
|
-
const similarTokens = existingNames.filter((name) => {
|
|
182
|
-
const similarity = calculateStringSimilarity(name, suggestedName);
|
|
183
|
-
return similarity > 30;
|
|
184
|
-
});
|
|
185
|
-
const insertAfter = similarTokens.length > 0 ? similarTokens[0] : undefined;
|
|
186
|
-
// For colors, suggest both light and dark values
|
|
187
|
-
if (figmaToken.type === 'color') {
|
|
188
|
-
suggestions.push({
|
|
189
|
-
tokenName: suggestedName,
|
|
190
|
-
value: figmaToken.value,
|
|
191
|
-
theme: 'both',
|
|
192
|
-
reason: `New token suggestion based on Figma token "${figmaToken.name}"`,
|
|
193
|
-
insertAfter,
|
|
194
|
-
});
|
|
195
|
-
}
|
|
196
|
-
else {
|
|
197
|
-
suggestions.push({
|
|
198
|
-
tokenName: suggestedName,
|
|
199
|
-
value: figmaToken.value,
|
|
200
|
-
theme: 'light',
|
|
201
|
-
reason: `New token suggestion based on Figma token "${figmaToken.name}"`,
|
|
202
|
-
insertAfter,
|
|
203
|
-
});
|
|
204
|
-
}
|
|
205
|
-
return suggestions;
|
|
206
|
-
}
|
|
207
|
-
/**
|
|
208
|
-
* Matches a single Figma token to existing theme tokens.
|
|
209
|
-
*
|
|
210
|
-
* @param figmaToken - Figma design token to match
|
|
211
|
-
* @param parsedTheme - Parsed theme from app.css
|
|
212
|
-
* @returns TokenMatch with exact, fuzzy, or no match and optional suggestions
|
|
213
|
-
*/
|
|
214
|
-
export function matchToken(figmaToken, parsedTheme) {
|
|
215
|
-
// Try exact match first (only for colors with hex values)
|
|
216
|
-
if (figmaToken.type === 'color' && figmaToken.value.startsWith('#')) {
|
|
217
|
-
const exactMatch = findExactColorMatch(figmaToken.value, parsedTheme);
|
|
218
|
-
if (exactMatch) {
|
|
219
|
-
return {
|
|
220
|
-
figmaToken,
|
|
221
|
-
matchedToken: exactMatch,
|
|
222
|
-
confidence: 100,
|
|
223
|
-
matchType: 'exact',
|
|
224
|
-
reason: `Exact color match: ${figmaToken.value} matches ${exactMatch.name}`,
|
|
225
|
-
};
|
|
226
|
-
}
|
|
227
|
-
}
|
|
228
|
-
// Try fuzzy matching
|
|
229
|
-
const fuzzyMatches = findFuzzyMatches(figmaToken, parsedTheme);
|
|
230
|
-
if (fuzzyMatches.length > 0 && fuzzyMatches[0].score >= 50) {
|
|
231
|
-
const bestMatch = fuzzyMatches[0];
|
|
232
|
-
return {
|
|
233
|
-
figmaToken,
|
|
234
|
-
matchedToken: bestMatch.token,
|
|
235
|
-
confidence: Math.round(bestMatch.score),
|
|
236
|
-
matchType: 'fuzzy',
|
|
237
|
-
reason: `Fuzzy match based on name similarity and semantic meaning`,
|
|
238
|
-
suggestions: fuzzyMatches.length > 1
|
|
239
|
-
? fuzzyMatches.slice(1, 4).map((m) => ({
|
|
240
|
-
tokenName: m.token.name,
|
|
241
|
-
value: m.token.value,
|
|
242
|
-
theme: m.token.theme === 'shared' ? 'both' : m.token.theme,
|
|
243
|
-
reason: `Alternative match (confidence: ${Math.round(m.score)}%)`,
|
|
244
|
-
}))
|
|
245
|
-
: undefined,
|
|
246
|
-
};
|
|
247
|
-
}
|
|
248
|
-
// No good match found, generate suggestions
|
|
249
|
-
const suggestions = generateTokenSuggestions(figmaToken, parsedTheme);
|
|
250
|
-
return {
|
|
251
|
-
figmaToken,
|
|
252
|
-
confidence: 0,
|
|
253
|
-
matchType: 'none',
|
|
254
|
-
reason: 'No matching token found. Consider creating a new token.',
|
|
255
|
-
suggestions,
|
|
256
|
-
};
|
|
257
|
-
}
|
|
258
|
-
/**
|
|
259
|
-
* Matches multiple Figma tokens to existing theme tokens.
|
|
260
|
-
*
|
|
261
|
-
* @param figmaTokens - Array of Figma design tokens to match
|
|
262
|
-
* @param parsedTheme - Parsed theme from app.css
|
|
263
|
-
* @returns Array of TokenMatch results, one per input token
|
|
264
|
-
*/
|
|
265
|
-
export function matchTokens(figmaTokens, parsedTheme) {
|
|
266
|
-
return figmaTokens.map((token) => matchToken(token, parsedTheme));
|
|
267
|
-
}
|
|
268
|
-
//# sourceMappingURL=token-matcher.js.map
|
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Storefront Next (deprecated) toolset for B2C Commerce.
|
|
3
|
-
*
|
|
4
|
-
* **DEPRECATED:** These `sfnext_*` tools are superseded by the `storefront-next`
|
|
5
|
-
* and `storefront-next-figma` agent-skills plugins and are NOT compatible with
|
|
6
|
-
* the Storefront Next 1.0 GA release. They now live in the
|
|
7
|
-
* `STOREFRONTNEXT_DEPRECATED` toolset, which is never auto-activated by project
|
|
8
|
-
* detection and is excluded from `--toolsets ALL`. To use them you must request
|
|
9
|
-
* the toolset explicitly (`--toolsets STOREFRONTNEXT_DEPRECATED`). They will be
|
|
10
|
-
* removed in a future release.
|
|
11
|
-
*
|
|
12
|
-
* **Implemented Tools:**
|
|
13
|
-
* - `sfnext_get_guidelines` - Get development guidelines and best practices
|
|
14
|
-
* - `sfnext_add_page_designer_decorator` - Add Page Designer decorators to React components
|
|
15
|
-
* - `sfnext_configure_theme` - Get theming guidelines, questions, and validation
|
|
16
|
-
* - `sfnext_start_figma_workflow` - Convert Figma to components
|
|
17
|
-
* - `sfnext_analyze_component` - Analyze design and recommend REUSE/EXTEND/CREATE
|
|
18
|
-
* - `sfnext_match_tokens_to_theme` - Match design tokens to theme
|
|
19
|
-
*
|
|
20
|
-
* @module tools/storefrontnext
|
|
21
|
-
*/
|
|
22
|
-
import type { McpTool } from '../../utils/index.js';
|
|
23
|
-
import type { Services } from '../../services.js';
|
|
24
|
-
/**
|
|
25
|
-
* Creates all tools for the deprecated STOREFRONTNEXT_DEPRECATED toolset.
|
|
26
|
-
*
|
|
27
|
-
* @param loadServices - Function that loads configuration and returns Services instance
|
|
28
|
-
* @returns Array of MCP tools
|
|
29
|
-
*/
|
|
30
|
-
export declare function createStorefrontNextTools(loadServices: () => Promise<Services> | Services): McpTool[];
|
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
/*
|
|
2
|
-
* Copyright (c) 2025, Salesforce, Inc.
|
|
3
|
-
* SPDX-License-Identifier: Apache-2
|
|
4
|
-
* For full license text, see the license.txt file in the repo root or http://www.apache.org/licenses/LICENSE-2.0
|
|
5
|
-
*/
|
|
6
|
-
import { createDeveloperGuidelinesTool } from './sfnext-development-guidelines.js';
|
|
7
|
-
import { createPageDesignerDecoratorTool } from './page-designer-decorator/index.js';
|
|
8
|
-
import { createSiteThemingTool } from './site-theming/index.js';
|
|
9
|
-
import { createFigmaToComponentTool } from './figma/figma-to-component/index.js';
|
|
10
|
-
import { createGenerateComponentTool } from './figma/generate-component/index.js';
|
|
11
|
-
import { createMapTokensToThemeTool } from './figma/map-tokens/index.js';
|
|
12
|
-
/**
|
|
13
|
-
* Creates all tools for the deprecated STOREFRONTNEXT_DEPRECATED toolset.
|
|
14
|
-
*
|
|
15
|
-
* @param loadServices - Function that loads configuration and returns Services instance
|
|
16
|
-
* @returns Array of MCP tools
|
|
17
|
-
*/
|
|
18
|
-
export function createStorefrontNextTools(loadServices) {
|
|
19
|
-
return [
|
|
20
|
-
createDeveloperGuidelinesTool(loadServices),
|
|
21
|
-
createPageDesignerDecoratorTool(loadServices),
|
|
22
|
-
createSiteThemingTool(loadServices),
|
|
23
|
-
createFigmaToComponentTool(loadServices),
|
|
24
|
-
createGenerateComponentTool(loadServices),
|
|
25
|
-
createMapTokensToThemeTool(loadServices),
|
|
26
|
-
];
|
|
27
|
-
}
|
|
28
|
-
//# sourceMappingURL=index.js.map
|
|
@@ -1,169 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Component analysis result
|
|
3
|
-
*/
|
|
4
|
-
export interface ComponentInfo {
|
|
5
|
-
componentName: string;
|
|
6
|
-
interfaceName: null | string;
|
|
7
|
-
hasDecorators: boolean;
|
|
8
|
-
props: PropInfo[];
|
|
9
|
-
exportType: 'default' | 'named';
|
|
10
|
-
filePath: string;
|
|
11
|
-
}
|
|
12
|
-
/**
|
|
13
|
-
* Property information extracted from component interface
|
|
14
|
-
*/
|
|
15
|
-
export interface PropInfo {
|
|
16
|
-
name: string;
|
|
17
|
-
type: string;
|
|
18
|
-
optional: boolean;
|
|
19
|
-
isComplex: boolean;
|
|
20
|
-
isUIOnly: boolean;
|
|
21
|
-
}
|
|
22
|
-
/**
|
|
23
|
-
* Type suggestion for attribute configuration
|
|
24
|
-
*/
|
|
25
|
-
export interface TypeSuggestion {
|
|
26
|
-
type: string;
|
|
27
|
-
reason: string;
|
|
28
|
-
priority: 'high' | 'low' | 'medium';
|
|
29
|
-
}
|
|
30
|
-
/**
|
|
31
|
-
* Valid SFCC Page Designer attribute types
|
|
32
|
-
*/
|
|
33
|
-
export declare const VALID_ATTRIBUTE_TYPES: readonly ["string", "text", "markup", "integer", "boolean", "product", "category", "file", "page", "image", "url", "enum", "custom", "cms_record"];
|
|
34
|
-
/**
|
|
35
|
-
* Infer Page Designer attribute type from TypeScript type
|
|
36
|
-
*/
|
|
37
|
-
export declare function inferPageDesignerType(tsType: string): string;
|
|
38
|
-
/**
|
|
39
|
-
* Check if TypeScript type can be auto-inferred
|
|
40
|
-
*/
|
|
41
|
-
export declare function isAutoInferredType(tsType: string): boolean;
|
|
42
|
-
/**
|
|
43
|
-
* Check if type is too complex for Page Designer
|
|
44
|
-
*/
|
|
45
|
-
export declare function isComplexType(tsType: string): boolean;
|
|
46
|
-
/**
|
|
47
|
-
* Check if property is UI-only
|
|
48
|
-
*/
|
|
49
|
-
export declare function isUIOnlyProp(propName: string): boolean;
|
|
50
|
-
/**
|
|
51
|
-
* Generate Page Designer attribute type suggestions for a component prop
|
|
52
|
-
*
|
|
53
|
-
* **Inference Strategy:**
|
|
54
|
-
* Uses naming patterns and TypeScript types to suggest appropriate Page Designer types.
|
|
55
|
-
* This reduces manual configuration by auto-detecting common patterns.
|
|
56
|
-
*
|
|
57
|
-
* **Page Designer Types:**
|
|
58
|
-
* - `string`: Default text input
|
|
59
|
-
* - `url`: URL/link inputs (validates URL format)
|
|
60
|
-
* - `image`: Image asset picker
|
|
61
|
-
* - `html`: Rich text editor
|
|
62
|
-
* - `markup`: HTML/markdown editor
|
|
63
|
-
* - `enum`: Dropdown with predefined values
|
|
64
|
-
* - `boolean`: Checkbox
|
|
65
|
-
* - `number`: Numeric input
|
|
66
|
-
* - `product`: Product picker (SFCC-specific)
|
|
67
|
-
* - `category`: Category picker (SFCC-specific)
|
|
68
|
-
*
|
|
69
|
-
* **Heuristics (by priority):**
|
|
70
|
-
* 1. **High Priority**: Strong patterns (url, image, product)
|
|
71
|
-
* 2. **Medium Priority**: Contextual patterns (html, markup)
|
|
72
|
-
* 3. **Low Priority**: Weak signals (description → markup)
|
|
73
|
-
*
|
|
74
|
-
* Multiple suggestions allow developers to choose the best fit.
|
|
75
|
-
*
|
|
76
|
-
* @param propName - Property name from component interface
|
|
77
|
-
* @param tsType - TypeScript type string
|
|
78
|
-
* @returns Array of type suggestions with reasoning and priority
|
|
79
|
-
*
|
|
80
|
-
* @example
|
|
81
|
-
* // URL detection:
|
|
82
|
-
* generateTypeSuggestions('imageUrl', 'string')
|
|
83
|
-
* // => [{ type: 'url', reason: '...', priority: 'high' }]
|
|
84
|
-
*
|
|
85
|
-
* @example
|
|
86
|
-
* // Image detection:
|
|
87
|
-
* generateTypeSuggestions('heroImage', 'string')
|
|
88
|
-
* // => [{ type: 'image', reason: '...', priority: 'high' }]
|
|
89
|
-
*
|
|
90
|
-
* @example
|
|
91
|
-
* // Multiple suggestions:
|
|
92
|
-
* generateTypeSuggestions('description', 'string')
|
|
93
|
-
* // => [
|
|
94
|
-
* // { type: 'markup', reason: '...', priority: 'low' },
|
|
95
|
-
* // { type: 'html', reason: '...', priority: 'medium' }
|
|
96
|
-
* // ]
|
|
97
|
-
*
|
|
98
|
-
* @example
|
|
99
|
-
* // Product reference:
|
|
100
|
-
* generateTypeSuggestions('product', 'string')
|
|
101
|
-
* // => [{ type: 'product', reason: '...', priority: 'high' }]
|
|
102
|
-
*
|
|
103
|
-
* @public
|
|
104
|
-
*/
|
|
105
|
-
export declare function generateTypeSuggestions(propName: string, tsType: string): TypeSuggestion[];
|
|
106
|
-
/**
|
|
107
|
-
* Component analyzer for Page Designer decorator generation
|
|
108
|
-
*/
|
|
109
|
-
declare class ComponentAnalyzer {
|
|
110
|
-
private cache;
|
|
111
|
-
analyzeComponent(filePath: string): ComponentInfo;
|
|
112
|
-
clearCache(): void;
|
|
113
|
-
}
|
|
114
|
-
export declare const componentAnalyzer: ComponentAnalyzer;
|
|
115
|
-
/**
|
|
116
|
-
* Resolve component input (name or path) to absolute file path
|
|
117
|
-
*
|
|
118
|
-
* **This is the main entry point for component discovery.**
|
|
119
|
-
*
|
|
120
|
-
* Supports two input modes:
|
|
121
|
-
* 1. **Name-based** (recommended): Just provide the component name
|
|
122
|
-
* 2. **Path-based** (backward compatible): Provide relative path from workspace
|
|
123
|
-
*
|
|
124
|
-
* **Name-based detection:**
|
|
125
|
-
* Input is treated as a name if it:
|
|
126
|
-
* - Does NOT contain path separators (/ or \)
|
|
127
|
-
* - Does NOT have a file extension (.tsx, .ts, etc.)
|
|
128
|
-
*
|
|
129
|
-
* **Path-based detection:**
|
|
130
|
-
* Input is treated as a path if it:
|
|
131
|
-
* - Contains / or \
|
|
132
|
-
* - Has a file extension
|
|
133
|
-
*
|
|
134
|
-
* @param input - Component name or relative path
|
|
135
|
-
* @param workspaceRoot - Absolute path to workspace root
|
|
136
|
-
* @param searchPaths - Additional directories to search (only used for name-based)
|
|
137
|
-
* @returns Absolute file path to component
|
|
138
|
-
* @throws {Error} If component cannot be found, with detailed search information
|
|
139
|
-
*
|
|
140
|
-
* @example
|
|
141
|
-
* // Name-based (finds automatically):
|
|
142
|
-
* resolveComponent('ProductCard', '/workspace')
|
|
143
|
-
* // => '/workspace/src/components/product-tile/ProductCard.tsx'
|
|
144
|
-
*
|
|
145
|
-
* @example
|
|
146
|
-
* // Path-based (backward compatible):
|
|
147
|
-
* resolveComponent('src/components/ProductCard.tsx', '/workspace')
|
|
148
|
-
* // => '/workspace/src/components/ProductCard.tsx'
|
|
149
|
-
*
|
|
150
|
-
* @example
|
|
151
|
-
* // With custom search paths (for monorepos):
|
|
152
|
-
* resolveComponent('Hero', '/workspace', ['packages/retail/src', 'packages/shared'])
|
|
153
|
-
* // => '/workspace/packages/retail/src/components/Hero.tsx'
|
|
154
|
-
*
|
|
155
|
-
* @example
|
|
156
|
-
* // Error handling:
|
|
157
|
-
* try {
|
|
158
|
-
* resolveComponent('NonExistent', '/workspace')
|
|
159
|
-
* } catch (err) {
|
|
160
|
-
* // Error includes:
|
|
161
|
-
* // - List of searched locations
|
|
162
|
-
* // - Tried name variations
|
|
163
|
-
* // - Helpful tips for resolution
|
|
164
|
-
* }
|
|
165
|
-
*
|
|
166
|
-
* @public
|
|
167
|
-
*/
|
|
168
|
-
export declare function resolveComponent(input: string, workspaceRoot: string, searchPaths?: string[]): string;
|
|
169
|
-
export {};
|