-
Notifications
You must be signed in to change notification settings - Fork 0
/
index.js
executable file
·241 lines (204 loc) · 9.98 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
#!/usr/bin/env node
import { glob } from 'glob';
import fs from 'fs';
import path from 'path';
import ora from 'ora';
const MAGENTO_SUBDIRECTORIES = ['app/code', 'vendor'];
function readConfigFile(filePath) {
try {
const content = fs.readFileSync(filePath, 'utf8');
const moduleMatch = content.match(/'modules'\s*=>\s*\[([\s\S]*?)\]/);
if (moduleMatch && moduleMatch[1]) {
return moduleMatch[1]
.match(/'([^']+)'/g)
.map(m => m.replace(/'/g, ''));
}
return [];
} catch (error) {
console.error('Error reading config file:', error.message);
return [];
}
}
async function findModulePath(moduleName, magentoRoot) {
let modulePath = false;
const possibleSubDirectories = getPossibleDirectories(moduleName);
const possibleDirectories = MAGENTO_SUBDIRECTORIES.map(subDir => path.join(magentoRoot, subDir));
for (const subDir of possibleSubDirectories) {
for (const baseDir of possibleDirectories) {
let fullPath = `${baseDir}/${subDir}`.replace(/\/\//g, '/');
if (fs.existsSync(fullPath)) {
modulePath = fullPath;
break;
}
}
if (modulePath) break;
}
if (!modulePath) {
const registrationFiles = glob.sync(path.join(magentoRoot, '**', 'registration.php'));
for (const file of registrationFiles) {
const content = fs.readFileSync(file, 'utf8');
if (content.includes(moduleName)) {
modulePath = path.dirname(file);
break;
}
}
}
return modulePath ? modulePath : 'Not found';
}
function getPossibleDirectories(moduleName) {
const parts = moduleName.split('_');
const appCode = parts.join('/');
const vendor = `${parts[0]}/${parts[1]?.replace(/\/([A-Z])/g, '/$1').replace(/([A-Z])/g, '-$1').replace(/^-(?=.)/, '')}`.toLowerCase();
const vendorModule = `${parts[0]}/module-${parts[1]?.replace(/\/([A-Z])/g, '/$1').replace(/([A-Z])/g, '-$1').replace(/^-(?=.)/, '')}`.toLowerCase();
const vendorMagento2 = `${parts[0]}/magento2-${parts[1]?.replace(/\/([A-Z])/g, '/$1').replace(/([A-Z])/g, '-$1').replace(/^-(?=.)/, '')}`.toLowerCase();
return [appCode, vendor, vendorModule, vendorMagento2];
}
function getHyvaCompatibilityModuleName(moduleName) {
const parts = moduleName.split('_');
return `Hyva_${parts.join('')}`;
}
async function filterModules(modules, modulesInclHyva) {
const filteredModules = modules.filter(module => {
const hyvaCompatibilityModuleName = getHyvaCompatibilityModuleName(module.name);
module.layoutFiles = [];
module.layoutLineCount = 0;
module.layoutFilesSize = 0;
module.jsFiles = [];
module.jsLineCount = 0;
module.jsFilesSize = 0;
module.phtmlFiles = [];
module.phtmlLineCount = 0;
module.phtmlFilesSize = 0;
module.compatibilityModuleInstalled = modulesInclHyva.includes(hyvaCompatibilityModuleName) ? hyvaCompatibilityModuleName : 'Not Found';
const path = module.path;
const files = glob.sync(path + '/**/*', { nodir: true });
const frontendFiles = files.filter(file => file.includes('view/frontend'));
const hyvaFiles = files.filter(file => {
const fileName = file.split('/').pop(); // Get just the filename
const isHyvaFile = fileName.startsWith('hyva_') && fileName.endsWith('.xml');
const isTailwindFile = file.includes('tailwind');
if (fileName.endsWith('.phtml') && file.includes('view/frontend/')) {
module.phtmlFiles.push(file);
module.phtmlFilesSize += fs.statSync(file)?.size ?? 0;
module.phtmlLineCount += fs.readFileSync(file, 'utf8')?.split('\n')?.length ?? 0;
}
if (fileName.endsWith('.js') && file.includes('view/frontend/')) {
module.jsFiles.push(file);
module.jsFilesSize += fs.statSync(file)?.size ?? 0;
module.jsLineCount += fs.readFileSync(file, 'utf8')?.split('\n')?.length ?? 0;
}
if (fileName.endsWith('.xml') && file.includes('view/frontend/layout')) {
module.layoutFiles.push(file);
module.layoutFilesSize += fs.statSync(file)?.size ?? 0;
module.layoutLineCount += fs.readFileSync(file, 'utf8')?.split('\n')?.length ?? 0;
}
return isHyvaFile || isTailwindFile;
});
const requiresHyvaCompatibility = frontendFiles.length > 0 && hyvaFiles.length === 0;
return requiresHyvaCompatibility;
});
return filteredModules;
}
function addSummary(modulesPathMap) {
const summary = {
info: "Summary of the modules and files which require Hyva compatibility",
totalModules: modulesPathMap.length,
jsFiles: modulesPathMap.reduce((acc, module) => acc + module.jsFiles.length, 0),
jsLineCount: modulesPathMap.reduce((acc, module) => acc + module.jsLineCount, 0),
jsFilesSize: modulesPathMap.reduce((acc, module) => acc + module.jsFilesSize, 0),
phtmlFiles: modulesPathMap.reduce((acc, module) => acc + module.phtmlFiles.length, 0),
phtmlLineCount: modulesPathMap.reduce((acc, module) => acc + module.phtmlLineCount, 0),
phtmlFilesSize: modulesPathMap.reduce((acc, module) => acc + module.phtmlFilesSize, 0),
layoutFiles: modulesPathMap.reduce((acc, module) => acc + module.layoutFiles.length, 0),
layoutLineCount: modulesPathMap.reduce((acc, module) => acc + module.layoutLineCount, 0),
layoutFilesSize: modulesPathMap.reduce((acc, module) => acc + module.layoutFilesSize, 0)
};
modulesPathMap.unshift(summary);
return modulesPathMap;
}
async function main() {
console.log(
"Optionally pass magento root as an argument:\n" +
" npm start /path/to/magento\n"
);
let magentoRoot = process.argv[2] || path.join(process.cwd(), '..');
let configPath = path.join(magentoRoot, 'app', 'etc', 'config.php');
if (!fs.existsSync(configPath)) {
magentoRoot = process.cwd();
configPath = path.join(magentoRoot, 'app', 'etc', 'config.php');
if (!fs.existsSync(configPath)) {
console.log("\u274C Error: app/etc/config.php not found. Make sure you're in the Magento 2 root directory or pass the correct path.");
process.exit(1);
}
}
console.log("\u2705 Retrieved app/etc/config.php");
const modulesInclHyva = readConfigFile(configPath).filter(module => !module.includes('Magento_'));
let modules = modulesInclHyva.filter(module => !module.includes('Hyva_'));
console.log("\u2705 Parsed config.php and retrieved module list of third party and custom modules");
const modulePaths = [];
let completedModules = 0;
const totalModules = modules.length;
const spinner = ora(`Finding module paths... [0/${totalModules}]`).start();
for (const module of modules) {
modulePaths.push(await findModulePath(module, magentoRoot));
completedModules++;
spinner.text =`Finding module paths... [${completedModules}/${totalModules}]`;
spinner.render();
}
let modulesPathMap = modules.map((module, index) => {
return {
name: module,
path: modulePaths[index]
}
});
spinner.stopAndPersist({ symbol: '\u2705', text: `Found ${completedModules}/${totalModules} module paths` });
modulesPathMap = await filterModules(modulesPathMap, modulesInclHyva);
console.log(`\u2705 Filtered Modules. ${modulesPathMap.length} may require Hyva compatibility.`);
modulesPathMap = addSummary(modulesPathMap);
console.log("\u2705 Analyzed files");
const reportsPath = path.join(magentoRoot, 'hyva-compatibility-analysis');
let outputCSV = 'Module,Relative Path,Compatibility Module,JS Files,JS Line Count,PHTML Files,PHTML Line Count,Layout Files,Layout Line Count\n';
for (const module of modulesPathMap) {
if (module.name && module.path) {
outputCSV += `
${module.name},
${module.path?.replace(magentoRoot, '')?.replace(/^\//, '')},
${module.compatibilityModuleInstalled},
${module.jsFiles.length},
${module.jsLineCount},
${module.phtmlFiles.length},
${module.phtmlLineCount},
${module.layoutFiles.length},
${module.layoutLineCount}
`.replace(/\s+/g, '').trim() + '\n';
}
}
if (!fs.existsSync(reportsPath)) {
fs.mkdirSync(reportsPath);
}
fs.writeFileSync(`${reportsPath}/report.csv`, outputCSV);
fs.writeFileSync(`${reportsPath}/report.json`, JSON.stringify(modulesPathMap, null, 2));
console.log('\n');
console.log(`Results have been written to the directory:`);
console.log(` \x1b]8;;file://${reportsPath}\x07${reportsPath}\x1b]8;;\x07`);
console.log(`\n`);
console.log(`Next steps:
- Review the reports to identify the modules that require Hyva compatibility modules.
- Checkout the \x1b]8;;https://gitlab.hyva.io/hyva-public/module-tracker/\x07Hyva Compatibility Module Tracker\x1b]8;;\x07 to see if there is already a Hyva compatibility modules available which can be used.
- If there is no Hyva compatibility modules available, you can either:
- Create a new issue in the \x1b]8;;https://gitlab.hyva.io/hyva-public/module-tracker/\x07Hyva Compatibility Module Tracker\x1b]8;;\x07 to request a new Hyva compatibility modules.
- Try to create one yourself, see \x1b]8;;https://docs.hyva.io/hyva-themes/compatibility-modules/index.html\x07Hyvä documentation\x1b]8;;\x07 for more information.
`);
}
process.on('unhandledRejection', (reason, promise) => {
console.error('Unhandled Rejection at:', promise, 'reason:', reason);
process.exit(1);
});
(async () => {
try {
await main();
} catch (error) {
console.error("An error occurred:", error);
process.exit(1);
}
})();