@salesforce/b2c-dx-mcp 0.4.4 → 0.4.6

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.
Files changed (84) hide show
  1. package/README.md +82 -370
  2. package/content/pwav3/components.md +400 -0
  3. package/content/pwav3/config.md +124 -0
  4. package/content/pwav3/data-fetching.md +213 -0
  5. package/content/pwav3/extensibility.md +167 -0
  6. package/content/pwav3/i18n.md +214 -0
  7. package/content/pwav3/quick-reference.md +169 -0
  8. package/content/pwav3/routing.md +107 -0
  9. package/content/pwav3/state-management.md +193 -0
  10. package/content/pwav3/styling.md +248 -0
  11. package/content/pwav3/testing.md +124 -0
  12. package/content/site-theming/theming-accessibility.md +126 -0
  13. package/content/site-theming/theming-questions.md +208 -0
  14. package/content/site-theming/theming-validation.md +174 -0
  15. package/dist/commands/mcp.d.ts +3 -3
  16. package/dist/commands/mcp.js +7 -7
  17. package/dist/registry.js +1 -1
  18. package/dist/services.d.ts +15 -15
  19. package/dist/services.js +21 -14
  20. package/dist/tools/adapter.d.ts +2 -2
  21. package/dist/tools/adapter.js +2 -2
  22. package/dist/tools/cartridges/index.js +1 -6
  23. package/dist/tools/index.d.ts +1 -4
  24. package/dist/tools/index.js +1 -4
  25. package/dist/tools/mrt/index.js +4 -9
  26. package/dist/tools/pwav3/index.d.ts +12 -3
  27. package/dist/tools/pwav3/index.js +5 -63
  28. package/dist/tools/pwav3/pwa-kit-development-guidelines.d.ts +9 -0
  29. package/dist/tools/pwav3/pwa-kit-development-guidelines.js +151 -0
  30. package/dist/tools/scapi/index.d.ts +1 -1
  31. package/dist/tools/scapi/index.js +6 -1
  32. package/dist/tools/scapi/scapi-custom-api-scaffold.d.ts +60 -0
  33. package/dist/tools/scapi/scapi-custom-api-scaffold.js +175 -0
  34. package/dist/tools/storefrontnext/figma/figma-to-component/figma-url-parser.d.ts +24 -0
  35. package/dist/tools/storefrontnext/figma/figma-to-component/figma-url-parser.js +53 -0
  36. package/dist/tools/storefrontnext/figma/figma-to-component/index.d.ts +42 -0
  37. package/dist/tools/storefrontnext/figma/figma-to-component/index.js +325 -0
  38. package/dist/tools/storefrontnext/figma/generate-component/decision.d.ts +40 -0
  39. package/dist/tools/storefrontnext/figma/generate-component/decision.js +312 -0
  40. package/dist/tools/storefrontnext/figma/generate-component/formatter.d.ts +9 -0
  41. package/dist/tools/storefrontnext/figma/generate-component/formatter.js +92 -0
  42. package/dist/tools/storefrontnext/figma/generate-component/index.d.ts +114 -0
  43. package/dist/tools/storefrontnext/figma/generate-component/index.js +98 -0
  44. package/dist/tools/storefrontnext/figma/map-tokens/css-parser.d.ts +71 -0
  45. package/dist/tools/storefrontnext/figma/map-tokens/css-parser.js +260 -0
  46. package/dist/tools/storefrontnext/figma/map-tokens/index.d.ts +61 -0
  47. package/dist/tools/storefrontnext/figma/map-tokens/index.js +234 -0
  48. package/dist/tools/storefrontnext/figma/map-tokens/token-matcher.d.ts +65 -0
  49. package/dist/tools/storefrontnext/figma/map-tokens/token-matcher.js +268 -0
  50. package/dist/tools/storefrontnext/index.d.ts +17 -0
  51. package/dist/tools/storefrontnext/index.js +10 -60
  52. package/dist/tools/storefrontnext/page-designer-decorator/analyzer.js +15 -0
  53. package/dist/tools/storefrontnext/page-designer-decorator/index.js +3 -3
  54. package/dist/tools/storefrontnext/{developer-guidelines.js → sfnext-development-guidelines.js} +3 -3
  55. package/dist/tools/storefrontnext/site-theming/color-contrast.d.ts +92 -0
  56. package/dist/tools/storefrontnext/site-theming/color-contrast.js +186 -0
  57. package/dist/tools/storefrontnext/site-theming/color-mapping.d.ts +16 -0
  58. package/dist/tools/storefrontnext/site-theming/color-mapping.js +131 -0
  59. package/dist/tools/storefrontnext/site-theming/guidance-merger.d.ts +11 -0
  60. package/dist/tools/storefrontnext/site-theming/guidance-merger.js +78 -0
  61. package/dist/tools/storefrontnext/site-theming/index.d.ts +14 -0
  62. package/dist/tools/storefrontnext/site-theming/index.js +122 -0
  63. package/dist/tools/storefrontnext/site-theming/response-builder.d.ts +16 -0
  64. package/dist/tools/storefrontnext/site-theming/response-builder.js +316 -0
  65. package/dist/tools/storefrontnext/site-theming/theming-store.d.ts +62 -0
  66. package/dist/tools/storefrontnext/site-theming/theming-store.js +410 -0
  67. package/dist/tools/storefrontnext/site-theming/types.d.ts +35 -0
  68. package/dist/tools/storefrontnext/site-theming/types.js +7 -0
  69. package/oclif.manifest.json +8 -5
  70. package/package.json +9 -6
  71. /package/content/{auth.md → sfnext/auth.md} +0 -0
  72. /package/content/{components.md → sfnext/components.md} +0 -0
  73. /package/content/{config.md → sfnext/config.md} +0 -0
  74. /package/content/{data-fetching.md → sfnext/data-fetching.md} +0 -0
  75. /package/content/{extensions.md → sfnext/extensions.md} +0 -0
  76. /package/content/{i18n.md → sfnext/i18n.md} +0 -0
  77. /package/content/{page-designer.md → sfnext/page-designer.md} +0 -0
  78. /package/content/{performance.md → sfnext/performance.md} +0 -0
  79. /package/content/{pitfalls.md → sfnext/pitfalls.md} +0 -0
  80. /package/content/{quick-reference.md → sfnext/quick-reference.md} +0 -0
  81. /package/content/{state-management.md → sfnext/state-management.md} +0 -0
  82. /package/content/{styling.md → sfnext/styling.md} +0 -0
  83. /package/content/{testing.md → sfnext/testing.md} +0 -0
  84. /package/dist/tools/storefrontnext/{developer-guidelines.d.ts → sfnext-development-guidelines.d.ts} +0 -0
@@ -0,0 +1,60 @@
1
+ import type { Services } from '../../services.js';
2
+ import type { McpTool } from '../../utils/index.js';
3
+ import type { Scaffold, ResolvedParameters, ResolveParametersOptions } from '@salesforce/b2c-tooling-sdk/scaffold';
4
+ /** Optional overrides for testing (scaffold not found, missing required). */
5
+ export interface ScaffoldCustomApiExecuteOverrides {
6
+ getScaffold?: (id: string, opts: {
7
+ projectRoot: string;
8
+ }) => Promise<null | Scaffold>;
9
+ resolveScaffoldParameters?: (scaffold: Scaffold, opts: ResolveParametersOptions) => Promise<ResolvedParameters>;
10
+ }
11
+ /**
12
+ * Input schema for scapi_custom_api_scaffold tool.
13
+ * Parameters match the custom-api scaffold: apiName, apiType, cartridgeName, etc.
14
+ */
15
+ interface ScaffoldCustomApiInput {
16
+ /** API name (kebab-case, e.g. my-products). Required. */
17
+ apiName: string;
18
+ /** Cartridge name that will contain the API. Optional; defaults to first cartridge found in project. */
19
+ cartridgeName?: string;
20
+ /** API type: admin (no siteId) or shopper (siteId, customer-facing). Default: shopper */
21
+ apiType?: 'admin' | 'shopper';
22
+ /** Short description of the API. Default: "A custom B2C Commerce API" */
23
+ apiDescription?: string;
24
+ /** Project root for cartridge discovery and output. Default: MCP project directory */
25
+ projectRoot?: string;
26
+ /** Output directory override. Default: scaffold default or project root */
27
+ outputDir?: string;
28
+ }
29
+ /**
30
+ * Output schema for scapi_custom_api_scaffold tool.
31
+ */
32
+ interface ScaffoldCustomApiOutput {
33
+ scaffold: string;
34
+ outputDir: string;
35
+ dryRun: boolean;
36
+ files: Array<{
37
+ path: string;
38
+ action: string;
39
+ skipReason?: string;
40
+ }>;
41
+ postInstructions?: string;
42
+ error?: string;
43
+ }
44
+ /**
45
+ * Core execute logic for the custom API scaffold tool.
46
+ * Exported for tests so we can inject getScaffold / resolveScaffoldParameters and cover error branches.
47
+ */
48
+ export declare function executeScaffoldCustomApi(args: ScaffoldCustomApiInput, services: Services, overrides?: ScaffoldCustomApiExecuteOverrides): Promise<ScaffoldCustomApiOutput>;
49
+ /**
50
+ * Creates the scapi_custom_api_scaffold tool.
51
+ *
52
+ * Uses @salesforce/b2c-tooling-sdk scaffold: registry, resolveScaffoldParameters,
53
+ * resolveOutputDirectory, generateFromScaffold. cartridgeName must be a cartridge
54
+ * discovered under projectRoot (e.g. from .project or cartridges/).
55
+ *
56
+ * @param loadServices - Function that returns Services (used by adapter on each call).
57
+ * @param executeOverrides - Optional overrides for testing (getScaffold, resolveScaffoldParameters).
58
+ */
59
+ export declare function createScaffoldCustomApiTool(loadServices: () => Services, executeOverrides?: ScaffoldCustomApiExecuteOverrides): McpTool;
60
+ export {};
@@ -0,0 +1,175 @@
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
+ * SCAPI Custom API Scaffold tool.
8
+ *
9
+ * Generates a new custom SCAPI endpoint using the SDK's custom-api scaffold
10
+ * (schema.yaml, api.json, script.js).
11
+ *
12
+ * @module tools/scapi/scapi-custom-api-scaffold
13
+ */
14
+ import { z } from 'zod';
15
+ import { createToolAdapter, jsonResult, errorResult } from '../adapter.js';
16
+ import { createScaffoldRegistry, generateFromScaffold, resolveScaffoldParameters, resolveOutputDirectory, } from '@salesforce/b2c-tooling-sdk/scaffold';
17
+ import { findCartridges } from '@salesforce/b2c-tooling-sdk/operations/code';
18
+ const CUSTOM_API_SCAFFOLD_ID = 'custom-api';
19
+ /**
20
+ * Core execute logic for the custom API scaffold tool.
21
+ * Exported for tests so we can inject getScaffold / resolveScaffoldParameters and cover error branches.
22
+ */
23
+ export async function executeScaffoldCustomApi(args, services, overrides) {
24
+ const projectRoot = services.resolveWithProjectDirectory(args.projectRoot);
25
+ const getScaffold = overrides?.getScaffold ??
26
+ (async (id, opts) => {
27
+ const registry = createScaffoldRegistry();
28
+ return registry.getScaffold(id, opts);
29
+ });
30
+ const scaffold = await getScaffold(CUSTOM_API_SCAFFOLD_ID, { projectRoot });
31
+ if (!scaffold) {
32
+ return {
33
+ scaffold: CUSTOM_API_SCAFFOLD_ID,
34
+ outputDir: projectRoot,
35
+ dryRun: false,
36
+ files: [],
37
+ error: `Scaffold not found: ${CUSTOM_API_SCAFFOLD_ID}. Ensure @salesforce/b2c-tooling-sdk is installed.`,
38
+ };
39
+ }
40
+ const cartridges = findCartridges(projectRoot);
41
+ if (cartridges.length === 0) {
42
+ return {
43
+ scaffold: CUSTOM_API_SCAFFOLD_ID,
44
+ outputDir: projectRoot,
45
+ dryRun: false,
46
+ files: [],
47
+ error: 'No cartridges found in project. Custom API scaffold requires an existing cartridge. Create a cartridge first: use `b2c scaffold cartridge --name app_custom`, or manually create a directory with a `.project` file (e.g., cartridges/app_custom/.project).',
48
+ };
49
+ }
50
+ let cartridgeName = args.cartridgeName;
51
+ if (!cartridgeName) {
52
+ cartridgeName = cartridges[0].name;
53
+ }
54
+ const providedVariables = {
55
+ apiName: args.apiName,
56
+ cartridgeName,
57
+ includeExampleEndpoints: true,
58
+ };
59
+ if (args.apiType !== undefined)
60
+ providedVariables.apiType = args.apiType;
61
+ if (args.apiDescription !== undefined)
62
+ providedVariables.apiDescription = args.apiDescription;
63
+ const resolveParams = overrides?.resolveScaffoldParameters ?? resolveScaffoldParameters;
64
+ const resolved = await resolveParams(scaffold, {
65
+ providedVariables,
66
+ projectRoot,
67
+ useDefaults: true,
68
+ });
69
+ if (resolved.errors.length > 0) {
70
+ const message = resolved.errors.map((e) => `${e.parameter}: ${e.message}`).join('; ');
71
+ return {
72
+ scaffold: CUSTOM_API_SCAFFOLD_ID,
73
+ outputDir: projectRoot,
74
+ dryRun: false,
75
+ files: [],
76
+ error: `Parameter validation failed: ${message}`,
77
+ };
78
+ }
79
+ const missingRequired = resolved.missingParameters.filter((p) => p.required);
80
+ if (missingRequired.length > 0) {
81
+ return {
82
+ scaffold: CUSTOM_API_SCAFFOLD_ID,
83
+ outputDir: projectRoot,
84
+ dryRun: false,
85
+ files: [],
86
+ error: `Missing required parameter: ${missingRequired[0].name}. For cartridgeName, ensure the cartridge exists in the project (under projectRoot).`,
87
+ };
88
+ }
89
+ const outputDir = resolveOutputDirectory({
90
+ outputDir: args.outputDir,
91
+ scaffold,
92
+ projectRoot,
93
+ });
94
+ try {
95
+ const result = await generateFromScaffold(scaffold, {
96
+ outputDir,
97
+ variables: resolved.variables,
98
+ dryRun: false,
99
+ force: false,
100
+ });
101
+ return {
102
+ scaffold: CUSTOM_API_SCAFFOLD_ID,
103
+ outputDir,
104
+ dryRun: result.dryRun,
105
+ files: result.files.map((f) => ({
106
+ path: f.path,
107
+ action: f.action,
108
+ skipReason: f.skipReason,
109
+ })),
110
+ postInstructions: result.postInstructions,
111
+ };
112
+ }
113
+ catch (error) {
114
+ const message = error instanceof Error ? error.message : String(error);
115
+ return {
116
+ scaffold: CUSTOM_API_SCAFFOLD_ID,
117
+ outputDir,
118
+ dryRun: false,
119
+ files: [],
120
+ error: `Scaffold generation failed: ${message}`,
121
+ };
122
+ }
123
+ }
124
+ /**
125
+ * Creates the scapi_custom_api_scaffold tool.
126
+ *
127
+ * Uses @salesforce/b2c-tooling-sdk scaffold: registry, resolveScaffoldParameters,
128
+ * resolveOutputDirectory, generateFromScaffold. cartridgeName must be a cartridge
129
+ * discovered under projectRoot (e.g. from .project or cartridges/).
130
+ *
131
+ * @param loadServices - Function that returns Services (used by adapter on each call).
132
+ * @param executeOverrides - Optional overrides for testing (getScaffold, resolveScaffoldParameters).
133
+ */
134
+ export function createScaffoldCustomApiTool(loadServices, executeOverrides) {
135
+ return createToolAdapter({
136
+ name: 'scapi_custom_api_scaffold',
137
+ description: `Generate a new custom SCAPI endpoint (OAS 3.0 schema, api.json, script.js) in an existing cartridge. \
138
+ Required: apiName (kebab-case). Optional: cartridgeName (defaults to first cartridge found in project), apiType (shopper|admin) default to shopper, \
139
+ apiDescription, projectRoot, outputDir.`,
140
+ toolsets: ['PWAV3', 'SCAPI', 'STOREFRONTNEXT'],
141
+ isGA: false,
142
+ requiresInstance: false,
143
+ inputSchema: {
144
+ apiName: z
145
+ .string()
146
+ .min(1)
147
+ .describe('API name in kebab-case (e.g. my-products). Must start with lowercase letter, only letters, numbers, hyphens.'),
148
+ cartridgeName: z
149
+ .string()
150
+ .min(1)
151
+ .nullish()
152
+ .describe('Cartridge name that will contain the API. Optional; omit to use the first cartridge found under project root).'),
153
+ apiType: z
154
+ .enum(['admin', 'shopper'])
155
+ .optional()
156
+ .describe('Admin (no siteId) or shopper (siteId, customer-facing). Default: shopper'),
157
+ apiDescription: z.string().optional().describe('Short description of the API.'),
158
+ projectRoot: z
159
+ .string()
160
+ .nullish()
161
+ .describe('Project root for cartridge discovery. Default: project directory. Set to override the project directory.'),
162
+ outputDir: z.string().optional().describe('Output directory override. Default: project root'),
163
+ },
164
+ async execute(args, { services }) {
165
+ return executeScaffoldCustomApi(args, services, executeOverrides);
166
+ },
167
+ formatOutput(output) {
168
+ if (output.error) {
169
+ return errorResult(output.error);
170
+ }
171
+ return jsonResult(output);
172
+ },
173
+ }, loadServices);
174
+ }
175
+ //# sourceMappingURL=scapi-custom-api-scaffold.js.map
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Extracted parameters from a Figma design URL.
3
+ *
4
+ * @property {string} fileKey - Figma file identifier from URL path
5
+ * @property {string} nodeId - Node identifier (colon format for Figma MCP)
6
+ */
7
+ export interface FigmaParams {
8
+ fileKey: string;
9
+ nodeId: string;
10
+ }
11
+ /**
12
+ * Parses a Figma URL to extract fileKey and nodeId.
13
+ *
14
+ * Supported URL formats:
15
+ * - https://figma.com/design/:fileKey/:fileName?node-id=1-2
16
+ * - https://www.figma.com/design/:fileKey/:fileName?node-id=1-2
17
+ * - https://figma.com/file/:fileKey/:fileName?node-id=1-2
18
+ *
19
+ * @param figmaUrl - The Figma URL to parse
20
+ * @returns Object with fileKey and nodeId
21
+ * @throws {Error} When URL is not from figma.com, fileKey cannot be extracted, or node-id is missing
22
+ * @throws {TypeError} When URL format is invalid
23
+ */
24
+ export declare function parseFigmaUrl(figmaUrl: string): FigmaParams;
@@ -0,0 +1,53 @@
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
+ * Parses a Figma URL to extract fileKey and nodeId.
8
+ *
9
+ * Supported URL formats:
10
+ * - https://figma.com/design/:fileKey/:fileName?node-id=1-2
11
+ * - https://www.figma.com/design/:fileKey/:fileName?node-id=1-2
12
+ * - https://figma.com/file/:fileKey/:fileName?node-id=1-2
13
+ *
14
+ * @param figmaUrl - The Figma URL to parse
15
+ * @returns Object with fileKey and nodeId
16
+ * @throws {Error} When URL is not from figma.com, fileKey cannot be extracted, or node-id is missing
17
+ * @throws {TypeError} When URL format is invalid
18
+ */
19
+ export function parseFigmaUrl(figmaUrl) {
20
+ try {
21
+ const url = new URL(figmaUrl);
22
+ // Validate it's a Figma URL
23
+ if (!url.hostname.includes('figma.com')) {
24
+ throw new Error('URL must be from figma.com');
25
+ }
26
+ // Extract fileKey from pathname
27
+ // Pattern: /design/:fileKey/:fileName or /file/:fileKey/:fileName
28
+ const pathMatch = url.pathname.match(/\/(design|file)\/([^/]+)/);
29
+ if (!pathMatch || !pathMatch[2]) {
30
+ throw new Error('Could not extract fileKey from URL. Expected format: https://figma.com/design/:fileKey/:fileName');
31
+ }
32
+ const fileKey = pathMatch[2];
33
+ // Extract nodeId from query params
34
+ // Pattern: ?node-id=1-2 or ?node-id=1:2
35
+ const nodeIdParam = url.searchParams.get('node-id');
36
+ if (!nodeIdParam) {
37
+ throw new Error('Could not extract node-id from URL. Expected query parameter: ?node-id=1-2');
38
+ }
39
+ // Convert node-id format from "1-2" to "1:2" (Figma MCP expects colon format)
40
+ const nodeId = nodeIdParam.replaceAll('-', ':');
41
+ return {
42
+ fileKey,
43
+ nodeId,
44
+ };
45
+ }
46
+ catch (error) {
47
+ if (error instanceof TypeError) {
48
+ throw new TypeError(`Invalid URL format: ${figmaUrl}`);
49
+ }
50
+ throw error;
51
+ }
52
+ }
53
+ //# sourceMappingURL=figma-url-parser.js.map
@@ -0,0 +1,42 @@
1
+ /**
2
+ * Figma-to-component workflow orchestrator tool.
3
+ *
4
+ * Parses Figma URLs, loads workflow instructions, and returns step-by-step guidance
5
+ * for converting Figma designs to Storefront Next components.
6
+ *
7
+ * @module tools/storefrontnext/figma/figma-to-component
8
+ */
9
+ import { z } from 'zod';
10
+ import type { McpTool } from '../../../../utils/index.js';
11
+ import type { Services } from '../../../../services.js';
12
+ export declare const figmaToComponentSchema: z.ZodObject<{
13
+ figmaUrl: z.ZodString;
14
+ workflowFilePath: z.ZodOptional<z.ZodString>;
15
+ }, "strict", z.ZodTypeAny, {
16
+ figmaUrl: string;
17
+ workflowFilePath?: string | undefined;
18
+ }, {
19
+ figmaUrl: string;
20
+ workflowFilePath?: string | undefined;
21
+ }>;
22
+ export type FigmaToComponentInput = z.infer<typeof figmaToComponentSchema>;
23
+ export interface WorkflowConfig {
24
+ /** YAML frontmatter key-value pairs. Parsed for future use (e.g., taskType-specific behavior). */
25
+ metadata: Record<string, string>;
26
+ content: string;
27
+ }
28
+ /**
29
+ * Generates the workflow guide for Figma-to-component conversion.
30
+ *
31
+ * @param figmaUrl - Figma design URL with node-id query parameter
32
+ * @param workflowFilePath - Optional absolute path to custom workflow .md file; uses built-in default if omitted
33
+ * @returns Formatted workflow guide string with Figma parameters and step-by-step instructions, or error message if URL or workflow file is invalid
34
+ */
35
+ export declare function generateWorkflowResponse(figmaUrl: string, workflowFilePath?: string): string;
36
+ /**
37
+ * Creates the storefront_next_figma_to_component_workflow MCP tool.
38
+ *
39
+ * @param loadServices - Function that loads configuration and returns Services instance
40
+ * @returns MCP tool for workflow orchestration
41
+ */
42
+ export declare function createFigmaToComponentTool(loadServices: () => Services): McpTool;