@salesforce/pwa-kit-mcp 0.1.1 → 0.2.1-dev

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.
@@ -1,313 +0,0 @@
1
- "use strict";
2
-
3
- Object.defineProperty(exports, "__esModule", {
4
- value: true
5
- });
6
- exports.default = void 0;
7
- var _promises = _interopRequireDefault(require("fs/promises"));
8
- var _path = _interopRequireDefault(require("path"));
9
- var _utils = require("../utils");
10
- var _zod = require("zod");
11
- function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
12
- function asyncGeneratorStep(n, t, e, r, o, a, c) { try { var i = n[a](c), u = i.value; } catch (n) { return void e(n); } i.done ? t(u) : Promise.resolve(u).then(r, o); }
13
- function _asyncToGenerator(n) { return function () { var t = this, e = arguments; return new Promise(function (r, o) { var a = n.apply(t, e); function _next(n) { asyncGeneratorStep(a, r, o, _next, _throw, "next", n); } function _throw(n) { asyncGeneratorStep(a, r, o, _next, _throw, "throw", n); } _next(void 0); }); }; } /*
14
- * Copyright (c) 2025, Salesforce, Inc.
15
- * All rights reserved.
16
- * SPDX-License-Identifier: BSD-3-Clause
17
- * For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/BSD-3-Clause
18
- */
19
- const systemPromptForCreatePage = `You are a smart assistant that can use tools when needed. \
20
- Please ask the user to provide following information **one at a time**, in a natural and conversational way. \
21
- Do **not** ask all the questions at once. \
22
- Do **not** assume the answers to the questions, especially the URL route. **Always** ask the user for the URL route. \
23
- - What is the name of the new page to create? \
24
- - List the components to include on the page, separated by commas. Component names should be in PascalCase (e.g., Image, ProductView) \
25
- - What is the URL route for this page? (e.g., /new-home, /my-products) \
26
- - What is the absolute path to your node_modules directory? \
27
- - What is the absolute path to your components directory? \
28
- - What is the absolute path to your pages directory? \
29
- - What is the absolute path to your routes.jsx file? \
30
- - Is ccExtensibility.overridesDir set in your package.json? (true/false) \
31
- Collect answers to these questions, then call the tool with the collected information as input parameters.`;
32
- const systemPromptForProductHook = `User have added the ProductView component to the new page. Please ask user: \
33
- "To make it work, would you like to add the hook useProduct to your page?" \
34
- If user answers yes, please make sure do do following: \
35
- 1. add the useProduct with ALL parameters following product-detail's useProduct as example, \
36
- 2. update ProductView tag to pass product and isProductLoading as props, \
37
- 3. in routes.jsx, update the path for the new page with '/:productId'. \
38
- 4. open the new page in the browser with URL: http://localhost:3000/{static-route-path}/25592300M \
39
- If user answers no, skip above steps.`;
40
- const systemPromptForImageComponent = `User has added the Image component to the new page. Please ask the user, after they have provided the URL route:
41
- "To make it work, would you like to provide the full path of the image source to your page? Note that CORS (Cross-Origin Resource Sharing) restrictions may apply."
42
-
43
- If the user answers yes, please do the following:
44
- 1. Ask the user to provide the full path of the image source.
45
- 2. If the image is from a URL from the internet, always check in the codebase if the domain of the image source is present in the CSP img-src allow list in ssr.js or related server files.
46
- 3. When checking the allow list, also check for wildcard entries (e.g., '*.domain.com') that would cover the provided domain. If either the exact domain or a matching wildcard is present, inform the user that the image source is already allowed by the CSP and proceed.
47
- 4. If neither the domain nor a matching wildcard is present in the allow list, inform the user and **do not** update the src of the Image component. Tell the user that the CSP img-src allow list needs to be updated manually, and do not proceed further until the domain is confirmed present in the codebase.
48
- 5. **Do not** update the CSP img-src allow list in ssr.js yourself; always ask the user to update the CSP img-src allow list manually, even if the user requests it.
49
- 6. Once the user confirms they have updated the CSP img-src allow list, check again in the codebase if the domain of the image source or a matching wildcard is part of the CSP img-src allow list. If yes, then proceed. If no, tell the user that the CSP img-src allow list needs to be updated manually, or ask the user to provide another image source.
50
- 7. Only if the image from the internet is part of the CSP img-src allow list (either by exact domain or wildcard), then proceed.
51
- 8. If the image source is an https URL, then use the image source directly in the Image component. If it's a local image, update the path inside getAssetUrl and use it in the Image component.
52
- 9. Ask the user to provide the alt text for the image.
53
- 10. Ask the user to provide the width and height of the image.
54
- 11. Update the src, alt text, width, and height of the Image component in the newly created page once the user has provided them.
55
- 12. Request the user to restart the front end server.
56
- 13. Open the new page in the browser with URL: http://localhost:3000/{static-route-path}
57
-
58
- If the user answers no, tell the user that the default image located at /static/img/hero.png is being displayed.
59
-
60
- Note:
61
- If the automation cannot detect the Image component but you know it exists and works as intended, proceed with the above steps as if the component is available. Do not block or alter the workflow due to the detection issue. Clearly communicate to the user that the Image component will be used, even if it was not detected by the automation.
62
- `;
63
- const systemPromptForUnfoundComponents = unfoundComponents => `The following components were not found: ${unfoundComponents.join(', ')}. \
64
- If the component is not found, **Please** suggest changes to the newly generated page file based on the components not found.`;
65
- class CreateNewPageTool {
66
- constructor() {
67
- var _this = this;
68
- this.name = 'create_sample_storefront_page';
69
- this.description = 'Create a sample PWA storefront page. Gather information from user for the MCP tool parameters **one at a time**, in a natural and conversational way. Do **not** ask all the questions at once.';
70
- this.inputSchema = {
71
- pageName: _zod.z.string().describe('The name of the new page to create?'),
72
- componentList: _zod.z.array(_zod.z.string()).describe('The existing components to include on the page, separated by commas. Component names should be in PascalCase (e.g., AddressDisplay, ProductView, Footer)'),
73
- route: _zod.z.string().describe('The URL route for this page? (e.g., /new-home, /my-product-view)'),
74
- nodeModulesPath: _zod.z.string().describe('The absolute path to the node_modules directory'),
75
- componentsPath: _zod.z.string().describe('The absolute path to the components directory'),
76
- pagesPath: _zod.z.string().describe('The absolute path to the pages directory'),
77
- routesPath: _zod.z.string().describe('The absolute path to the routes.jsx file'),
78
- hasOverridesDir: _zod.z.boolean().describe('Whether ccExtensibility.overridesDir is set in package.json')
79
- };
80
- this.unfoundComponents = [];
81
- this.handler = /*#__PURE__*/function () {
82
- var _ref = _asyncToGenerator(function* (args) {
83
- (0, _utils.logMCPMessage)(`------- Calling CreateNewPageTool handler`);
84
- if (!args || !args.pageName || !args.componentList || !args.route || !args.nodeModulesPath || !args.componentsPath || !args.pagesPath || !args.routesPath || args.hasOverridesDir === undefined) {
85
- return {
86
- role: 'system',
87
- content: [{
88
- type: 'text',
89
- text: systemPromptForCreatePage
90
- }]
91
- };
92
- }
93
- return _this.createPage(args.pageName, args.componentList, args.route, {
94
- nodeModulesPath: args.nodeModulesPath,
95
- componentsPath: args.componentsPath,
96
- pagesPath: args.pagesPath,
97
- routesPath: args.routesPath,
98
- hasOverridesDir: args.hasOverridesDir
99
- });
100
- });
101
- return function (_x) {
102
- return _ref.apply(this, arguments);
103
- };
104
- }();
105
- }
106
- createPage(pageName, componentList, route, absolutePaths) {
107
- var _this2 = this;
108
- return _asyncToGenerator(function* () {
109
- (0, _utils.logMCPMessage)(`========== Creating page ${pageName} with components ${componentList} and route ${route}`);
110
- _this2.unfoundComponents = [];
111
- yield (0, _utils.logMCPMessage)(`Creating page ${pageName} with components ${componentList} and route ${route}`);
112
- try {
113
- const messages = [];
114
- // Use the provided absolute path for pages directory
115
- const pagesDir = absolutePaths.pagesPath;
116
- pageName = (0, _utils.toPascalCase)(pageName);
117
- const pageDir = _path.default.join(pagesDir, (0, _utils.toKebabCase)(pageName));
118
- try {
119
- yield _promises.default.access(pageDir);
120
- throw new Error(`Page directory already exists: ${pageDir}`);
121
- } catch (err) {
122
- if (err.code !== 'ENOENT') throw err;
123
- }
124
- yield _promises.default.mkdir(pageDir, {
125
- recursive: true
126
- });
127
- if (componentList.length == 0) {
128
- componentList.push(pageName);
129
- }
130
- const pageContent = yield _this2.generatePageContent(pageName, componentList, absolutePaths);
131
- (0, _utils.logMCPMessage)(`!!!!!! \n pageContent: ${pageContent} \n !!!!!`);
132
- const indexPath = _path.default.join(pageDir, 'index.jsx');
133
- yield _promises.default.writeFile(indexPath, pageContent, 'utf8');
134
- yield _this2.updateRoutes(pageName, route, absolutePaths);
135
- messages.push(`Created page ${pageName} at ${pageDir}`);
136
- messages.push(`Added route ${route}`);
137
- (0, _utils.logMCPMessage)(`componentList: ${componentList}`);
138
- if (componentList.includes('ProductView')) {
139
- messages.push(systemPromptForProductHook);
140
- }
141
- if (componentList.includes('Image')) {
142
- messages.push(systemPromptForImageComponent);
143
- }
144
- (0, _utils.logMCPMessage)(`Unfound components: ${_this2.unfoundComponents}`);
145
- if (_this2.unfoundComponents.length != 0) {
146
- messages.push(systemPromptForUnfoundComponents(_this2.unfoundComponents));
147
- }
148
- (0, _utils.logMCPMessage)(messages.join('\n'));
149
- return {
150
- role: 'system',
151
- content: [{
152
- type: 'text',
153
- text: messages.join('\n')
154
- }]
155
- };
156
- } catch (error) {
157
- (0, _utils.logMCPMessage)(`Error creating page: ${error.message}`);
158
- return {
159
- role: 'developer',
160
- content: [{
161
- type: 'text',
162
- text: `Error creating page: ${error.message}`
163
- }]
164
- };
165
- }
166
- })();
167
- }
168
- generatePageContent(pageName, componentList, absolutePaths) {
169
- var _this3 = this;
170
- const imports = [`import React from 'react'`, `import Seo from '@salesforce/retail-react-app/app/components/seo'`];
171
- const sharedUIComponents = ['Box'];
172
- // Add component imports
173
- const accessPromises = componentList.map(/*#__PURE__*/function () {
174
- var _ref2 = _asyncToGenerator(function* (component) {
175
- component = (0, _utils.toPascalCase)(component);
176
- const componentName = component.charAt(0).toUpperCase() + component.slice(1);
177
- const componentDir = (0, _utils.toKebabCase)(componentName);
178
- // Use the provided absolute paths for component detection
179
- const isLocal = (0, _utils.isLocalComponent)(componentDir, absolutePaths.componentsPath);
180
- const isLocalSharedUI = (0, _utils.isLocalSharedUIComponent)(componentDir, absolutePaths.componentsPath);
181
- const isBase = (0, _utils.isBaseComponent)(componentDir, absolutePaths.nodeModulesPath);
182
- const isSharedUI = (0, _utils.isSharedUIBaseComponent)(componentDir, absolutePaths.nodeModulesPath);
183
- if (!isLocal && !isLocalSharedUI && !isBase && !isSharedUI) {
184
- _this3.unfoundComponents.push(component);
185
- }
186
- // Import getAssetUrl for displaying image source if Image component is used
187
- if (componentName === 'Image') {
188
- imports.push(`import {getAssetUrl} from '@salesforce/pwa-kit-react-sdk/ssr/universal/utils'`);
189
- }
190
- if (isLocalSharedUI || isSharedUI) {
191
- sharedUIComponents.push(componentName);
192
- return;
193
- }
194
- // If the component name is the same as the page name, add 'Component' to the component name to avoid conflict with the page name
195
- const importComponentName = componentName === pageName ? componentName + 'Component' : componentName;
196
- const importComponentPath = (0, _utils.generateComponentImportStatement)(importComponentName, componentDir, isLocal, isBase, absolutePaths, absolutePaths.hasOverridesDir);
197
- imports.push(importComponentPath);
198
- });
199
- return function (_x2) {
200
- return _ref2.apply(this, arguments);
201
- };
202
- }());
203
-
204
- // Import all shared UI components in a single import statement
205
- if (sharedUIComponents.length > 0) {
206
- const importSharedUIComponents = sharedUIComponents.join(', ');
207
- imports.push(`import {${importSharedUIComponents}} from '@salesforce/retail-react-app/app/components/shared/ui'`);
208
- }
209
- return Promise.all(accessPromises).then(() => {
210
- (0, _utils.logMCPMessage)(`?????? imports ${imports.join('\n')}`);
211
- const componentJsx = componentList.map(component => {
212
- component = (0, _utils.toPascalCase)(component);
213
- const componentName = component.charAt(0).toUpperCase() + component.slice(1);
214
- // If the component name is the same as the page name, add 'Component' to the component name
215
- const importComponentName = componentName === pageName ? componentName + 'Component' : componentName;
216
- if (componentName === 'Image') {
217
- return ` <Image src={getAssetUrl('static/img/hero.png')} alt="pwa-kit banner" style={{ width: '700px', height: 'auto' }} />`;
218
- }
219
- return ` <${importComponentName} />`;
220
- }).join('\n');
221
- return `/*
222
- * Copyright (c) ${new Date().getFullYear()}, Salesforce, Inc.
223
- * All rights reserved.
224
- * SPDX-License-Identifier: BSD-3-Clause
225
- * For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/BSD-3-Clause
226
- */
227
-
228
- ${imports.join('\n')}
229
-
230
- /**
231
- * ${pageName} component
232
- * @returns {React.JSX.Element}
233
- */
234
- const ${pageName} = () => {
235
-
236
- return (
237
- <Box data-testid="${pageName.toLowerCase()}-page" layerStyle="page">
238
- <Seo
239
- title="${pageName}"
240
- description="${pageName} Page"
241
- keywords="Commerce Cloud, Retail React App, React Storefront"
242
- />
243
-
244
- ${componentJsx}
245
- </Box>
246
- );
247
- }
248
-
249
- export default ${pageName};
250
- `;
251
- });
252
- }
253
- updateRoutes(pageName, route, absolutePaths) {
254
- return _asyncToGenerator(function* () {
255
- // Use the provided absolute path to the routes.jsx file
256
- const routesPath = absolutePaths.routesPath;
257
- try {
258
- const routesContent = yield _promises.default.readFile(routesPath, 'utf8');
259
- const importStatement = `const ${pageName} = loadable(() => import('./pages/${(0, _utils.toKebabCase)(pageName)}'), {fallback})`;
260
- (0, _utils.logMCPMessage)(`!!!!!!!!!! importStatement: ${importStatement}`);
261
-
262
- // Match all loadable import statements
263
- const loadableRegex = /const\s+\w+\s*=\s*loadable\(\(\)\s*=>\s*import\(['"`].*?['"`]\)(?:,\s*\{fallback\})?\);?/g;
264
- const matches = [...routesContent.matchAll(loadableRegex)];
265
- if (matches.length === 0) {
266
- throw new Error('No loadable import statements found.');
267
- }
268
- const lastMatch = matches[matches.length - 1];
269
- const insertPosition = lastMatch.index + lastMatch[0].length;
270
-
271
- // Insert the new import after the last one
272
- let updatedContent = routesContent.slice(0, insertPosition) + `\n${importStatement}` + routesContent.slice(insertPosition);
273
- const routeObject = ` {\n path: '${route}',\n component: ${pageName},\n exact: true\n },`;
274
-
275
- // Find the routes array, works for both export and non-export cases
276
- const routesArrayRegex = /(export\s+)?const\s+routes\s*=\s*\[([\s\S]*?)\]/m;
277
- const match = updatedContent.match(routesArrayRegex);
278
- if (!match) {
279
- throw new Error('No routes array declaration found.');
280
- }
281
-
282
- // Find the start and end of the routes array
283
- const arrayStart = match.index + match[0].indexOf('[') + 1;
284
- const arrayEnd = match.index + match[0].lastIndexOf(']');
285
- let arrayBody = updatedContent.slice(arrayStart, arrayEnd).trim();
286
-
287
- // Remove leading/trailing commas and whitespace
288
- arrayBody = arrayBody.replace(/^,|,$/g, '').trim();
289
-
290
- // Remove trailing '}' if present after a spread operator (e.g., ..._routes} in case of generated app)
291
- arrayBody = arrayBody.replace(/(\.\.\.[^,}\]]+)}\s*$/, '$1');
292
- if (arrayBody) {
293
- if (!arrayBody.match(/\.\.\.[^,}\]]+\s*$/)) {
294
- if (!arrayBody.endsWith(',')) {
295
- arrayBody += ',';
296
- }
297
- } else {
298
- arrayBody = arrayBody.replace(/,\s*$/, '');
299
- }
300
- }
301
- const newArrayBody = `\n${routeObject}\n${arrayBody ? ' ' + arrayBody : ''}\n`;
302
-
303
- // Reassemble the file
304
- updatedContent = updatedContent.slice(0, arrayStart) + newArrayBody + updatedContent.slice(arrayEnd);
305
- yield _promises.default.writeFile(routesPath, updatedContent, 'utf8');
306
- } catch (error) {
307
- throw new Error(`Failed to update routes: ${error.message}`);
308
- }
309
- })();
310
- }
311
- }
312
- const createNewPageTool = new CreateNewPageTool();
313
- var _default = exports.default = createNewPageTool;
@@ -1,131 +0,0 @@
1
- "use strict";
2
-
3
- Object.defineProperty(exports, "__esModule", {
4
- value: true
5
- });
6
- exports.default = void 0;
7
- var _utils = require("../utils/utils");
8
- function asyncGeneratorStep(n, t, e, r, o, a, c) { try { var i = n[a](c), u = i.value; } catch (n) { return void e(n); } i.done ? t(u) : Promise.resolve(u).then(r, o); }
9
- function _asyncToGenerator(n) { return function () { var t = this, e = arguments; return new Promise(function (r, o) { var a = n.apply(t, e); function _next(n) { asyncGeneratorStep(a, r, o, _next, _throw, "next", n); } function _throw(n) { asyncGeneratorStep(a, r, o, _next, _throw, "throw", n); } _next(void 0); }); }; } /*
10
- * Copyright (c) 2025, Salesforce, Inc.
11
- * All rights reserved.
12
- * SPDX-License-Identifier: BSD-3-Clause
13
- * For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/BSD-3-Clause
14
- */
15
- const guidelinesText = `# Salesforce Commerce Composable Storefront Development Guidelines
16
-
17
- ## Overview
18
- This document offers guidelines in the development of Salesforce Commerce Composable Storefront applications using PWA Kit. The AI should possess a comprehensive understanding of the PWA Kit architecture, sample Retail React App, Chakra UI, and standard React application practices.
19
-
20
- ## Core Principles
21
-
22
- ### Project Understanding
23
- - Thoroughly analyze requests and the existing project for successful implementation.
24
- - Promptly clarify ambiguous requirements.
25
-
26
- ### Development Workflow
27
- - **Analyze Requirements** - Clearly define the objectives and functionalities required.
28
- - **Review Existing Code** - Examine the current codebase to identify similar solutions and potentially reusable components.
29
- - **Understand Existing Hooks and Utilities** - Familiarize with hooks and utility functions available within the project, including those from commerce-sdk-react and template-retail-react-app modules.
30
- - **Plan Implementation** - Design component structure before coding.
31
- - **Implement Incrementally** - Develop and test the service in small, manageable steps.
32
- - **Test Thoroughly** - Ensure comprehensive testing, including the use of Jest.
33
-
34
- ## Technical Stack
35
-
36
- ### Core Technologies
37
- - **React** - UI components and SPA architecture
38
- - **Express** - Server-side rendering and backend
39
- - **@salesforce/commerce-sdk-react** - Commerce Cloud API integration (hooks)
40
- - **PWA Kit** - SSR, routing, config, Salesforce integration
41
- - **Chakra UI V2** - UI components and theming
42
- - **Emotion** - CSS-in-JS styling
43
- - **React Router** - Routing
44
- - **React Intl** - Localization
45
- - **React Query** - Data fetching/caching
46
- - **Webpack** - Bundling
47
- - **React Testing Library, Jest** - Testing libraries
48
- - **react-helmet, framer-motion, etc.** - Utilities, animation, head management
49
- - **ESLint/Prettier** - Code formatting and linting
50
-
51
- ## PWK Kit Architecture
52
-
53
- ### Configuration Files
54
- - PWA Kit apps are customized using configuration files for API access, URL formatting, and server-side rendering.
55
- - These files support JavaScript, YAML, and JSON formats, with default.js being the standard.
56
- - Configuration values are serialized for isomorphic rendering, so secrets must not be included.
57
- - Environment-specific configuration files can replace or complement default.js.
58
- - File precedence is .js > .yml > .yaml > .json if base names are the same.
59
-
60
- ### Proxy Requests
61
- - Managed Runtime's proxy feature routes API requests through the storefront domain to avoid CORS issues and improve performance.
62
- - Local proxy configurations are set in config/default.js, while Managed Runtime deployments use Runtime Admin or the Managed Runtime API.
63
- - Requests use the /mobify/proxy/<PROXY_PATH> pattern.
64
- - Proxied requests and responses are modified for transparent operation.
65
- - Proxied requests are uncached by default but can be cached using a caching path prefix.
66
-
67
- ### Rendering
68
- - PWA Kit uses server-side rendering (SSR) for fast initial page loads, leveraging CDN caching.
69
- - After the first load, client-side rendering (CSR) takes over for fluid user interactions.
70
- - Application code must be isomorphic, functioning in both server and client environments, often with conditional logic.
71
- - Props from API requests are serialized into the page source during SSR for client-side hydration.
72
- - A correlation ID is provided on each page for tracking requests across PWA Kit and other systems.
73
-
74
- ### Routing
75
- - PWA Kit uses Express.js and React Router for handling requests and rendering components.
76
- - Routes are defined in app/routes.jsx as an array of objects with 'path' and 'component' properties.
77
- - You can use both withReactQuery and withLegacyGetProps at the same time.
78
- - getProps and shouldGetProps were removed from the default template of pages of the Retail React App, but aren't deprecated. Long-term support for these methods remains.
79
-
80
- ### PWA Kit Special Components
81
- - Customize your storefront by overriding default special components that start with an underscore (_), such as app/components/_app-config/index.jsx.
82
- - app/components/_app-config: The top-level component for app-wide configurations like theme providers and state management.
83
- - app/components/_app: The child of _app-config. Use it for layout and UI that persist throughout your React app, such as the header, footer, and sidebar.
84
- - app/components/_error: Renders when a page or its data isn't found, or when an error occurs, returning a 404 status.
85
-
86
- ### State Management
87
- - PWA Kit applications support various state management approaches, including simple prop-passing or React's Context API.
88
- - The React Context API can be used with useReducer and useContext for shared global state.
89
- - The AppConfig special component is the primary place to initialize a state management system.
90
- - When integrating libraries like Redux, AppConfig methods such as restore, freeze, extraGetPropsArgs, and render are utilized.
91
-
92
- ### PWA Kit Extensibility
93
- - In PWA Kit v3, you can extend a base template (@salesforce/retail-react-app) by replacing specific files using a local "overrides directory."
94
- - Extensibility is configured in package.json with the base template (ccExtensibility.extends) and your overrides directory (ccExtensibility.overridesDir).
95
- - To override a file, recreate its exact path and filename in your overrides directory.
96
-
97
- ### PWA Kit Storefront Development
98
- - Start development with Retail React App sample codebase and tooling.
99
- - Use included npm scripts for automating development tasks like build, test, and lint.
100
- - Access Shopper data through the commerce-sdk-react hooks to fetch, cache, and mutate utilizing Salesforce Commerce API (SLAS) and OCAPI.
101
- - Use Chakra UI and existing components when available.
102
- - Create simple, functional, modular, reusable components.
103
- - Use the React Helmet library to modify the HTML tags in Document, such as <head>.
104
- - Use kebab-case for file names. Only start with an underscore (_) if they are special components.
105
- - Use React Hooks (e.g., useState, useEffect, useContext, useMemo, useCallback) for state management and side effects.
106
-
107
- ## Quality Standards
108
- - Maintain consistent code formatting using project standards.
109
- - Write comprehensive test coverage.
110
- - Ensure components are accessible and mobile-friendly.
111
- - Follow security best practices for all code.
112
- `;
113
- var _default = exports.default = {
114
- name: 'development_guidelines',
115
- description: `You must follow this development guidelines before attempting to analyze/ generate / refactor / modify / fix code.
116
- - e.g. "Create a customer service Chat component", "Find bugs in my_script.jsx", "Refactor my_script.jsx to use React Hooks"`,
117
- inputSchema: _utils.EmptyJsonSchema,
118
- fn: function () {
119
- var _ref = _asyncToGenerator(function* () {
120
- return {
121
- content: [{
122
- type: 'text',
123
- text: guidelinesText
124
- }]
125
- };
126
- });
127
- return function fn() {
128
- return _ref.apply(this, arguments);
129
- };
130
- }()
131
- };
@@ -1,62 +0,0 @@
1
- "use strict";
2
-
3
- Object.defineProperty(exports, "__esModule", {
4
- value: true
5
- });
6
- Object.defineProperty(exports, "CreateAppGuidelinesTool", {
7
- enumerable: true,
8
- get: function () {
9
- return _createAppGuideline.default;
10
- }
11
- });
12
- Object.defineProperty(exports, "CreateNewComponentTool", {
13
- enumerable: true,
14
- get: function () {
15
- return _createNewComponent.default;
16
- }
17
- });
18
- Object.defineProperty(exports, "CreateNewPageTool", {
19
- enumerable: true,
20
- get: function () {
21
- return _createNewPageTool.default;
22
- }
23
- });
24
- Object.defineProperty(exports, "DeveloperGuidelinesTool", {
25
- enumerable: true,
26
- get: function () {
27
- return _developerGuideline.default;
28
- }
29
- });
30
- Object.defineProperty(exports, "TestWithPlaywrightTool", {
31
- enumerable: true,
32
- get: function () {
33
- return _siteTest.TestWithPlaywrightTool;
34
- }
35
- });
36
- Object.defineProperty(exports, "VersionControlGitTool", {
37
- enumerable: true,
38
- get: function () {
39
- return _versionControlGit.default;
40
- }
41
- });
42
- Object.defineProperty(exports, "runAccessibilityTest", {
43
- enumerable: true,
44
- get: function () {
45
- return _siteTestAccessibility.runAccessibilityTest;
46
- }
47
- });
48
- Object.defineProperty(exports, "runPerformanceTest", {
49
- enumerable: true,
50
- get: function () {
51
- return _siteTestPerformance.runPerformanceTest;
52
- }
53
- });
54
- var _createAppGuideline = _interopRequireDefault(require("./create-app-guideline.js"));
55
- var _createNewComponent = _interopRequireDefault(require("./create-new-component.js"));
56
- var _developerGuideline = _interopRequireDefault(require("./developer-guideline.js"));
57
- var _siteTest = require("./site-test.js");
58
- var _createNewPageTool = _interopRequireDefault(require("./create-new-page-tool.js"));
59
- var _versionControlGit = _interopRequireDefault(require("./version-control-git.js"));
60
- var _siteTestAccessibility = require("./site-test-accessibility.js");
61
- var _siteTestPerformance = require("./site-test-performance.js");
62
- function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
@@ -1,38 +0,0 @@
1
- "use strict";
2
-
3
- Object.defineProperty(exports, "__esModule", {
4
- value: true
5
- });
6
- exports.runAccessibilityTest = runAccessibilityTest;
7
- var _playwright = require("playwright");
8
- var _playwright2 = _interopRequireDefault(require("@axe-core/playwright"));
9
- function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
10
- function asyncGeneratorStep(n, t, e, r, o, a, c) { try { var i = n[a](c), u = i.value; } catch (n) { return void e(n); } i.done ? t(u) : Promise.resolve(u).then(r, o); }
11
- function _asyncToGenerator(n) { return function () { var t = this, e = arguments; return new Promise(function (r, o) { var a = n.apply(t, e); function _next(n) { asyncGeneratorStep(a, r, o, _next, _throw, "next", n); } function _throw(n) { asyncGeneratorStep(a, r, o, _next, _throw, "throw", n); } _next(void 0); }); }; } /*
12
- * Copyright (c) 2025, Salesforce, Inc.
13
- * All rights reserved.
14
- * SPDX-License-Identifier: BSD-3-Clause
15
- * For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/BSD-3-Clause
16
- */
17
- function runAccessibilityTest(_x) {
18
- return _runAccessibilityTest.apply(this, arguments);
19
- }
20
- function _runAccessibilityTest() {
21
- _runAccessibilityTest = _asyncToGenerator(function* (siteUrl) {
22
- const browser = yield _playwright.chromium.launch();
23
- const context = yield browser.newContext();
24
- const page = yield context.newPage();
25
- yield page.goto(siteUrl);
26
- const results = yield new _playwright2.default({
27
- page
28
- }).analyze();
29
- yield browser.close();
30
- return {
31
- content: [{
32
- type: 'text',
33
- text: JSON.stringify(results)
34
- }]
35
- };
36
- });
37
- return _runAccessibilityTest.apply(this, arguments);
38
- }
@@ -1,87 +0,0 @@
1
- "use strict";
2
-
3
- Object.defineProperty(exports, "__esModule", {
4
- value: true
5
- });
6
- exports.runPerformanceTest = runPerformanceTest;
7
- var _playwright = require("playwright");
8
- function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
9
- function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
10
- function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }
11
- function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == typeof i ? i : i + ""; }
12
- function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != typeof i) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
13
- function asyncGeneratorStep(n, t, e, r, o, a, c) { try { var i = n[a](c), u = i.value; } catch (n) { return void e(n); } i.done ? t(u) : Promise.resolve(u).then(r, o); }
14
- function _asyncToGenerator(n) { return function () { var t = this, e = arguments; return new Promise(function (r, o) { var a = n.apply(t, e); function _next(n) { asyncGeneratorStep(a, r, o, _next, _throw, "next", n); } function _throw(n) { asyncGeneratorStep(a, r, o, _next, _throw, "throw", n); } _next(void 0); }); }; } /*
15
- * Copyright (c) 2025, Salesforce, Inc.
16
- * All rights reserved.
17
- * SPDX-License-Identifier: BSD-3-Clause
18
- * For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/BSD-3-Clause
19
- */
20
- function runPerformanceTest(_x) {
21
- return _runPerformanceTest.apply(this, arguments);
22
- }
23
- function _runPerformanceTest() {
24
- _runPerformanceTest = _asyncToGenerator(function* (siteUrl) {
25
- const browser = yield _playwright.chromium.launch();
26
- const page = yield browser.newPage();
27
- yield page.goto(siteUrl);
28
-
29
- // Wait for page to fully load
30
- yield page.waitForLoadState('load');
31
-
32
- // Extract detailed navigation timing data from the browser
33
- const navigationEntries = yield page.evaluate(() => {
34
- const nav = performance.getEntriesByType('navigation')[0];
35
- if (!nav) return null;
36
- return {
37
- type: nav.type,
38
- startTime: nav.startTime,
39
- unloadEventStart: nav.unloadEventStart,
40
- unloadEventEnd: nav.unloadEventEnd,
41
- redirectStart: nav.redirectStart,
42
- redirectEnd: nav.redirectEnd,
43
- fetchStart: nav.fetchStart,
44
- domainLookupStart: nav.domainLookupStart,
45
- domainLookupEnd: nav.domainLookupEnd,
46
- connectStart: nav.connectStart,
47
- connectEnd: nav.connectEnd,
48
- secureConnectionStart: nav.secureConnectionStart,
49
- requestStart: nav.requestStart,
50
- responseStart: nav.responseStart,
51
- responseEnd: nav.responseEnd,
52
- domLoading: nav.domLoading,
53
- domInteractive: nav.domInteractive,
54
- domContentLoadedEventStart: nav.domContentLoadedEventStart,
55
- domContentLoadedEventEnd: nav.domContentLoadedEventEnd,
56
- domComplete: nav.domComplete,
57
- loadEventStart: nav.loadEventStart,
58
- loadEventEnd: nav.loadEventEnd,
59
- duration: nav.duration
60
- };
61
- });
62
-
63
- // Fallback for browsers that don't support Navigation Timing Level 2
64
- const perfTiming = navigationEntries || (yield page.evaluate(() => JSON.parse(JSON.stringify(window.performance.timing))));
65
-
66
- // Calculate key metrics
67
- const metrics = _objectSpread({
68
- totalLoadTime: perfTiming.loadEventEnd - perfTiming.startTime,
69
- domContentLoadedTime: perfTiming.domContentLoadedEventEnd - perfTiming.startTime,
70
- timeToFirstByte: perfTiming.responseStart - perfTiming.startTime,
71
- domInteractive: perfTiming.domInteractive - perfTiming.startTime,
72
- firstPaint: perfTiming.responseEnd - perfTiming.startTime
73
- }, perfTiming);
74
- yield browser.close();
75
- return {
76
- content: [{
77
- type: 'text',
78
- text: `Total Load Time: ${metrics.totalLoadTime}ms, \
79
- DOM Content Loaded: ${metrics.domContentLoadedTime}ms, \
80
- Time to First Byte: ${metrics.timeToFirstByte}ms,
81
- DOM Interactive: ${metrics.domInteractive}ms, \
82
- First Paint: ${metrics.firstPaint}ms`
83
- }]
84
- };
85
- });
86
- return _runPerformanceTest.apply(this, arguments);
87
- }