magector 2.7.1 → 2.7.2
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/package.json +5 -5
- package/src/mcp-server.js +51 -3
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "magector",
|
|
3
|
-
"version": "2.7.
|
|
3
|
+
"version": "2.7.2",
|
|
4
4
|
"description": "Semantic code search for Magento 2 — index, search, MCP server",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "src/mcp-server.js",
|
|
@@ -33,10 +33,10 @@
|
|
|
33
33
|
"ruvector": "^0.1.96"
|
|
34
34
|
},
|
|
35
35
|
"optionalDependencies": {
|
|
36
|
-
"@magector/cli-darwin-arm64": "2.7.
|
|
37
|
-
"@magector/cli-linux-x64": "2.7.
|
|
38
|
-
"@magector/cli-linux-arm64": "2.7.
|
|
39
|
-
"@magector/cli-win32-x64": "2.7.
|
|
36
|
+
"@magector/cli-darwin-arm64": "2.7.2",
|
|
37
|
+
"@magector/cli-linux-x64": "2.7.2",
|
|
38
|
+
"@magector/cli-linux-arm64": "2.7.2",
|
|
39
|
+
"@magector/cli-win32-x64": "2.7.2"
|
|
40
40
|
},
|
|
41
41
|
"keywords": [
|
|
42
42
|
"magento",
|
package/src/mcp-server.js
CHANGED
|
@@ -2303,6 +2303,33 @@ async function analyzeImpact(className) {
|
|
|
2303
2303
|
...diTrace.virtualTypes.map(v => ({ type: 'virtualType', file: v.file, detail: `${v.name} extends ${v.type}` })),
|
|
2304
2304
|
...diTrace.argumentOverrides.map(a => ({ type: 'argument', file: a.file, detail: `${a.target}.${a.argumentName}` }))
|
|
2305
2305
|
];
|
|
2306
|
+
// Also find where this class is used AS a plugin/preference/virtualType implementation
|
|
2307
|
+
if (references.diXmlReferences.length === 0 && root) {
|
|
2308
|
+
const diFiles = await getDiXmlFiles(root);
|
|
2309
|
+
for (const { content, relPath } of diFiles) {
|
|
2310
|
+
if (!content.toLowerCase().includes(shortName.toLowerCase())) continue;
|
|
2311
|
+
// Check if class appears as plugin type
|
|
2312
|
+
const pluginTypeRegex = /<plugin\s+[^>]*type="([^"]+)"[^>]*\/?>/g;
|
|
2313
|
+
let pm;
|
|
2314
|
+
while ((pm = pluginTypeRegex.exec(content)) !== null) {
|
|
2315
|
+
if (pm[1].toLowerCase().includes(shortName.toLowerCase())) {
|
|
2316
|
+
// Find parent <type> to know the target
|
|
2317
|
+
const beforePlugin = content.slice(0, pm.index);
|
|
2318
|
+
const typeMatch = beforePlugin.match(/<type\s+name="([^"]+)"[^>]*>\s*$/m);
|
|
2319
|
+
const target = typeMatch ? typeMatch[1] : 'unknown';
|
|
2320
|
+
references.diXmlReferences.push({ type: 'registered-as-plugin', file: relPath, detail: `plugin on ${target} → ${pm[1]}` });
|
|
2321
|
+
}
|
|
2322
|
+
}
|
|
2323
|
+
// Check if class appears as preference type
|
|
2324
|
+
const prefRegex = /<preference\s+for="([^"]+)"\s+type="([^"]+)"\s*\/?>/g;
|
|
2325
|
+
let prm;
|
|
2326
|
+
while ((prm = prefRegex.exec(content)) !== null) {
|
|
2327
|
+
if (prm[2].toLowerCase().includes(shortName.toLowerCase())) {
|
|
2328
|
+
references.diXmlReferences.push({ type: 'registered-as-preference', file: relPath, detail: `preference for ${prm[1]} → ${prm[2]}` });
|
|
2329
|
+
}
|
|
2330
|
+
}
|
|
2331
|
+
}
|
|
2332
|
+
}
|
|
2306
2333
|
|
|
2307
2334
|
// Check PHP files for direct references
|
|
2308
2335
|
const escapedShort = shortName.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
@@ -5789,13 +5816,34 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
5789
5816
|
case 'magento_module_structure': {
|
|
5790
5817
|
const raw = await rustSearchAsync(a.moduleName, 200);
|
|
5791
5818
|
const modulePath = a.moduleName.replace('_', '/') + '/';
|
|
5792
|
-
const
|
|
5793
|
-
|
|
5794
|
-
const
|
|
5819
|
+
const mParts = a.moduleName.split('_');
|
|
5820
|
+
// Hyphenate camelCase for vendor path: OrderSplit → order-split
|
|
5821
|
+
const vendorPath = mParts.length === 2
|
|
5822
|
+
? `module-${mParts[1].replace(/([a-z])([A-Z])/g, '$1-$2').toLowerCase()}/`
|
|
5823
|
+
: '';
|
|
5824
|
+
let res = raw.map(normalizeResult).filter(r => {
|
|
5795
5825
|
const p = r.path || '';
|
|
5796
5826
|
const mod = r.module || '';
|
|
5797
5827
|
return mod === a.moduleName || p.includes(modulePath) || (vendorPath && p.toLowerCase().includes(vendorPath));
|
|
5798
5828
|
});
|
|
5829
|
+
// Filesystem fallback
|
|
5830
|
+
if (res.length === 0 && config.magentoRoot && vendorPath) {
|
|
5831
|
+
try {
|
|
5832
|
+
const vendorGlob = `**/${vendorPath}**/*.{php,xml,phtml}`;
|
|
5833
|
+
const files = await glob(vendorGlob, { cwd: config.magentoRoot, absolute: false, nodir: true });
|
|
5834
|
+
for (const f of files.slice(0, 100)) {
|
|
5835
|
+
const entry = { path: f, score: 0.5 };
|
|
5836
|
+
if (f.includes('/Controller/')) entry.isController = true;
|
|
5837
|
+
if (f.includes('/Model/')) entry.isModel = true;
|
|
5838
|
+
if (f.includes('/Plugin/')) entry.isPlugin = true;
|
|
5839
|
+
if (f.includes('/Observer/')) entry.isObserver = true;
|
|
5840
|
+
if (f.endsWith('.xml')) entry.type = 'xml';
|
|
5841
|
+
const phpMatch = f.match(/\/([A-Z]\w+)\.php$/);
|
|
5842
|
+
if (phpMatch) entry.className = phpMatch[1];
|
|
5843
|
+
res.push(entry);
|
|
5844
|
+
}
|
|
5845
|
+
} catch {}
|
|
5846
|
+
}
|
|
5799
5847
|
text = `Module: ${a.moduleName} (${res.length} files)\n`;
|
|
5800
5848
|
const cats = { controllers: '/Controller/', models: '/Model/', plugins: '/Plugin/', observers: '/Observer/', api: '/Api/' };
|
|
5801
5849
|
for (const [cat, pattern] of Object.entries(cats)) {
|