mage-obsidian 1.1.2 → 2.0.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.
Files changed (111) hide show
  1. package/.github/workflows/ci.yml +38 -0
  2. package/.github/workflows/publish.yml +26 -25
  3. package/.oxlintrc.json +19 -0
  4. package/.prettierignore +7 -0
  5. package/.prettierrc.json +7 -0
  6. package/LICENSE +1 -1
  7. package/README.md +1 -0
  8. package/eslint.config.js +24 -0
  9. package/package.json +39 -13
  10. package/pnpm-workspace.yaml +4 -0
  11. package/src/cli/buildThemes.ts +263 -0
  12. package/src/config/default.ts +31 -0
  13. package/src/config/eslint.js +60 -0
  14. package/src/core/configResolver.ts +141 -0
  15. package/src/core/contractValidator.ts +56 -0
  16. package/src/core/cssResolver.ts +153 -0
  17. package/src/{service/generateInterceptors.js → core/generateInterceptors.ts} +79 -46
  18. package/src/core/generateJsconfig.ts +168 -0
  19. package/src/{service/moduleResolver.js → core/moduleResolver.ts} +79 -46
  20. package/src/core/preCompileFiles.ts +105 -0
  21. package/src/core/preCompileMagentoFiles.ts +34 -0
  22. package/src/core/themeResolverSync.ts +66 -0
  23. package/src/runtime/i18nCore.ts +113 -0
  24. package/src/runtime/interceptorManager.ts +186 -0
  25. package/src/runtime/islands.ts +84 -0
  26. package/src/runtime/sectionStoreCore.ts +259 -0
  27. package/src/utils/{findComponents.js → findComponents.ts} +29 -16
  28. package/src/utils/runWithConcurrency.ts +35 -0
  29. package/src/vite/defaultNodeResolver.ts +17 -0
  30. package/src/{service/inheritAssetsModuleResolver.js → vite/inheritAssetsModuleResolver.ts} +15 -11
  31. package/src/{service/inheritModuleResolver.js → vite/inheritModuleResolver.ts} +6 -10
  32. package/src/{service/interceptorsPlugin.js → vite/interceptorsPlugin.ts} +25 -19
  33. package/src/vite/magentoHrmRewrite.ts +44 -0
  34. package/src/vite/sharedPlugins.ts +54 -0
  35. package/src/vite/themeSourceWatcher.ts +96 -0
  36. package/src/vite/unresolvedModuleGuard.ts +87 -0
  37. package/tsconfig.json +34 -0
  38. package/vitest.config.js +18 -0
  39. package/jest.config.js +0 -5
  40. package/src/__tests__/__mocks__/configResolver.js +0 -35
  41. package/src/__tests__/fixtures/interceptors/emptyTarget.js +0 -2
  42. package/src/__tests__/fixtures/interceptors/pluginForNonFunction.js +0 -7
  43. package/src/__tests__/fixtures/interceptors/pluginModule.js +0 -13
  44. package/src/__tests__/fixtures/interceptors/targetModule.js +0 -12
  45. package/src/__tests__/fixtures/interceptors/targetNonFunction.js +0 -7
  46. package/src/__tests__/magento_scenarios/app/code/Vendor/ModuleNameA/view/frontend/web/components/ComponentA.vue +0 -0
  47. package/src/__tests__/magento_scenarios/app/code/Vendor/ModuleNameA/view/frontend/web/components/ComponentB.vue +0 -0
  48. package/src/__tests__/magento_scenarios/app/code/Vendor/ModuleNameA/view/frontend/web/css/module.extend.css +0 -0
  49. package/src/__tests__/magento_scenarios/app/code/Vendor/ModuleNameA/view/frontend/web/js/main.js +0 -0
  50. package/src/__tests__/magento_scenarios/app/code/Vendor/ModuleNameA/view/frontend/web/main.js +0 -0
  51. package/src/__tests__/magento_scenarios/app/code/Vendor/ModuleNameA/view/frontend/web/module.config.js +0 -9
  52. package/src/__tests__/magento_scenarios/app/code/Vendor/ModuleNameB/view/frontend/web/components/ComponentA.vue +0 -0
  53. package/src/__tests__/magento_scenarios/app/code/Vendor/ModuleNameB/view/frontend/web/components/ComponentB.vue +0 -0
  54. package/src/__tests__/magento_scenarios/app/code/Vendor/ModuleNameB/view/frontend/web/css/module.extend.css +0 -2
  55. package/src/__tests__/magento_scenarios/app/code/Vendor/ModuleNameB/view/frontend/web/js/main.js +0 -0
  56. package/src/__tests__/magento_scenarios/app/code/Vendor/ModuleNameB/view/frontend/web/module.config.js +0 -7
  57. package/src/__tests__/magento_scenarios/app/code/Vendor/ModuleNameC/view/frontend/web/components/ComponentA.vue +0 -0
  58. package/src/__tests__/magento_scenarios/app/code/Vendor/ModuleNameC/view/frontend/web/components/ComponentB.vue +0 -0
  59. package/src/__tests__/magento_scenarios/app/code/Vendor/ModuleNameC/view/frontend/web/css/module.extend.css +0 -2
  60. package/src/__tests__/magento_scenarios/app/code/Vendor/ModuleNameC/view/frontend/web/js/main.js +0 -0
  61. package/src/__tests__/magento_scenarios/app/code/Vendor/ModuleNameC/view/frontend/web/module.config.js +0 -7
  62. package/src/__tests__/magento_scenarios/app/design/frontend/Vendor/theme-a/Vendor_ModuleNameA/web/components/ComponentA.vue +0 -0
  63. package/src/__tests__/magento_scenarios/app/design/frontend/Vendor/theme-a/Vendor_ModuleNameA/web/components/ComponentB.vue +0 -0
  64. package/src/__tests__/magento_scenarios/app/design/frontend/Vendor/theme-a/Vendor_ModuleNameA/web/css/module.extend.css +0 -0
  65. package/src/__tests__/magento_scenarios/app/design/frontend/Vendor/theme-a/Vendor_ModuleNameA/web/js/main.js +0 -0
  66. package/src/__tests__/magento_scenarios/app/design/frontend/Vendor/theme-a/Vendor_ModuleNameA/web/module.config.js +0 -2
  67. package/src/__tests__/magento_scenarios/app/design/frontend/Vendor/theme-a/Vendor_ModuleNameB/web/components/ComponentA.vue +0 -0
  68. package/src/__tests__/magento_scenarios/app/design/frontend/Vendor/theme-a/Vendor_ModuleNameB/web/components/ComponentB.vue +0 -0
  69. package/src/__tests__/magento_scenarios/app/design/frontend/Vendor/theme-a/Vendor_ModuleNameB/web/css/module.extend.css +0 -0
  70. package/src/__tests__/magento_scenarios/app/design/frontend/Vendor/theme-a/Vendor_ModuleNameB/web/js/main.js +0 -0
  71. package/src/__tests__/magento_scenarios/app/design/frontend/Vendor/theme-a/Vendor_ModuleNameB/web/module.config.js +0 -2
  72. package/src/__tests__/magento_scenarios/app/design/frontend/Vendor/theme-a/Vendor_ModuleNameNoConfig/web/components/ComponentA.vue +0 -0
  73. package/src/__tests__/magento_scenarios/app/design/frontend/Vendor/theme-a/Vendor_ModuleNameNoConfig/web/components/ComponentB.vue +0 -0
  74. package/src/__tests__/magento_scenarios/app/design/frontend/Vendor/theme-a/Vendor_ModuleNameNoConfig/web/css/module.extend.css +0 -0
  75. package/src/__tests__/magento_scenarios/app/design/frontend/Vendor/theme-a/Vendor_ModuleNameNoConfig/web/js/main.js +0 -0
  76. package/src/__tests__/magento_scenarios/app/design/frontend/Vendor/theme-a/Vendor_ModuleNameNoConfig/web/module.config.js +0 -2
  77. package/src/__tests__/magento_scenarios/app/design/frontend/Vendor/theme-a/web/components/ComponentA.vue +0 -0
  78. package/src/__tests__/magento_scenarios/app/design/frontend/Vendor/theme-a/web/components/ComponentB.vue +0 -0
  79. package/src/__tests__/magento_scenarios/app/design/frontend/Vendor/theme-a/web/css/theme.source.css +0 -6
  80. package/src/__tests__/magento_scenarios/app/design/frontend/Vendor/theme-a/web/js/main.js +0 -0
  81. package/src/__tests__/magento_scenarios/app/design/frontend/Vendor/theme-a/web/theme.config.js +0 -5
  82. package/src/__tests__/magento_scenarios/app/design/frontend/Vendor/theme-b/web/css/theme.source.css +0 -6
  83. package/src/__tests__/magento_scenarios/app/design/frontend/Vendor/theme-b/web/theme.config.js +0 -5
  84. package/src/__tests__/magento_scenarios/app/design/frontend/Vendor/theme-c/Vendor_ModuleNameB/web/components/ComponentA.vue +0 -0
  85. package/src/__tests__/magento_scenarios/app/design/frontend/Vendor/theme-c/Vendor_ModuleNameB/web/components/ComponentB.vue +0 -0
  86. package/src/__tests__/magento_scenarios/app/design/frontend/Vendor/theme-c/Vendor_ModuleNameB/web/css/module.extend.css +0 -0
  87. package/src/__tests__/magento_scenarios/app/design/frontend/Vendor/theme-c/Vendor_ModuleNameB/web/js/main.js +0 -0
  88. package/src/__tests__/magento_scenarios/app/design/frontend/Vendor/theme-c/Vendor_ModuleNameB/web/module.config.js +0 -2
  89. package/src/__tests__/magento_scenarios/app/design/frontend/Vendor/theme-c/web/css/theme.source.css +0 -6
  90. package/src/__tests__/magento_scenarios/app/design/frontend/Vendor/theme-c/web/theme.config.js +0 -2
  91. package/src/__tests__/magento_scenarios/app/design/frontend/Vendor/theme-d/web/css/theme.source.css +0 -6
  92. package/src/__tests__/magento_scenarios/app/design/frontend/Vendor/theme-d/web/theme.config.js +0 -3
  93. package/src/__tests__/magento_scenarios/app/etc/mage_obsidian_frontend_modules_a.json +0 -53
  94. package/src/__tests__/magento_scenarios/app/etc/mage_obsidian_frontend_modules_b.json +0 -50
  95. package/src/__tests__/service/generateInterceptors.test.js +0 -196
  96. package/src/__tests__/service/inheritModuleResolver.test.js +0 -61
  97. package/src/__tests__/service/interceptorManager_magento_behavior.test.js +0 -137
  98. package/src/__tests__/service/moduleResolver.test.js +0 -194
  99. package/src/__tests__/service/themeResolverSync.test.js +0 -97
  100. package/src/__tests__/vite-plugins/interceptorsPlugin.test.js +0 -121
  101. package/src/config/default.js +0 -27
  102. package/src/scripts/buildThemes.js +0 -132
  103. package/src/service/configResolver.js +0 -63
  104. package/src/service/cssResolver.js +0 -73
  105. package/src/service/defaultNodeResolver.js +0 -16
  106. package/src/service/interceptorManager.js +0 -137
  107. package/src/service/magentoHrmRewrite.js +0 -43
  108. package/src/service/preCompileFiles.js +0 -37
  109. package/src/service/preCompileMagentoFiles.js +0 -16
  110. package/src/service/setupGlobals.js +0 -19
  111. package/src/service/themeResolverSync.js +0 -67
@@ -1,132 +0,0 @@
1
- #! /usr/bin/env node
2
- import { Command } from 'commander';
3
- import { execSync } from 'child_process';
4
- import readlineSync from 'readline-sync';
5
- import fs from 'fs';
6
- import path from 'path';
7
- import chalk from 'chalk';
8
- import configResolver from '../service/configResolver.js';
9
- import dotenv from 'dotenv';
10
- dotenv.config();
11
-
12
- const program = new Command();
13
-
14
- program
15
- .option('--theme <theme>', 'Specify the active theme')
16
- .option('--dev-server', 'Run the development server for a specific theme');
17
-
18
- program.parse(process.argv);
19
-
20
- const options = program.opts();
21
- const themesConfig = configResolver.getMagentoConfig().themes;
22
-
23
- if (options.devServer && !options.theme) {
24
- console.error(chalk.red('Error: The --theme option is required when using --dev-server.'));
25
- process.exit(1);
26
- }
27
-
28
- const theme = options.theme || 'all';
29
-
30
- const executeCommand = (command) => {
31
- try {
32
- execSync(command, { stdio: 'inherit' });
33
- } catch (error) {
34
- console.error(chalk.red(`Command failed: ${command}`), error);
35
- process.exit(1);
36
- }
37
- };
38
-
39
- function tryCreateEnvFile() {
40
- const defaultEnvVars = {
41
- VITE_SERVER_HOST: 'phpfpm',
42
- VITE_SERVER_PORT: '5173',
43
- VITE_SERVER_SECURE: 'true',
44
- VITE_HMR_PATH: '/__vite_ping',
45
- MAGENTO_HOST: 'magento.test',
46
- VITE_SERVER_ALLOWED_HOSTS: 'magento.test,localhost'
47
- };
48
-
49
- console.log(chalk.blue('Creating `.env` file with default or user-provided values...'));
50
-
51
- const envFilePath = path.resolve(process.cwd(), '.env');
52
- if (fs.existsSync(envFilePath)) {
53
- console.log(chalk.green('.env file already exists.'));
54
- return;
55
- }
56
-
57
- let envContent = '';
58
- for (const [key, defaultValue] of Object.entries(defaultEnvVars)) {
59
- const userInput = readlineSync.question(chalk.yellow(`Enter value for ${key} (default: ${defaultValue}): `), {
60
- defaultInput: defaultValue,
61
- });
62
- envContent += `${key}=${userInput || defaultValue}\n`;
63
- }
64
-
65
- fs.writeFileSync(envFilePath, envContent);
66
- console.log(chalk.green('.env file created successfully.'));
67
- }
68
-
69
- function validateEnv() {
70
- const requiredEnvVars = ['VITE_SERVER_HOST', 'VITE_SERVER_PORT', 'VITE_SERVER_SECURE', 'VITE_HMR_PATH', 'MAGENTO_HOST', 'VITE_SERVER_ALLOWED_HOSTS'];
71
- let missingEnvVars = [];
72
- for (const envVar of requiredEnvVars) {
73
- if (!process.env[envVar]) {
74
- missingEnvVars.push(envVar);
75
- }
76
- }
77
- if (missingEnvVars.length > 0) {
78
- console.error(chalk.red(`Missing required environment variables: ${missingEnvVars.join(', ')}`));
79
- tryCreateEnvFile();
80
- console.log(chalk.green('Please restart the script after setting up the .env file.'));
81
- process.exit(1);
82
- }
83
- }
84
-
85
- const buildTheme = (themeName) => {
86
- console.log(chalk.cyan(`Building theme: ${themeName}`));
87
- try {
88
- const theme = themesConfig[themeName];
89
- if (!theme) {
90
- console.error(chalk.red(`Theme "${themeName}" does not exist.`));
91
- process.exit(1);
92
- }
93
-
94
- process.env.CURRENT_THEME = themeName;
95
- executeCommand('vite build');
96
- } catch (error) {
97
- console.error(chalk.red(`Failed to build theme "${themeName}":`), error);
98
- }
99
- };
100
-
101
- const runDevServer = (themeName) => {
102
- console.log(chalk.cyan(`Starting development server for theme: ${themeName}`));
103
- try {
104
- const theme = themesConfig[themeName];
105
- if (!theme) {
106
- console.error(chalk.red(`Theme "${themeName}" does not exist.`));
107
- process.exit(1);
108
- }
109
-
110
- process.env.CURRENT_THEME = themeName;
111
- executeCommand('vite');
112
- } catch (error) {
113
- console.error(chalk.red(`Failed to start development server for theme "${themeName}":`), error);
114
- }
115
- };
116
-
117
- validateEnv();
118
-
119
- if (options.devServer) {
120
- runDevServer(theme);
121
- } else {
122
- if (theme === 'all') {
123
- for (const themeName of Object.keys(themesConfig)) {
124
- buildTheme(themeName);
125
- }
126
- } else if (themesConfig[theme]) {
127
- buildTheme(theme);
128
- } else {
129
- console.error(chalk.red(`Theme "${theme}" does not exist.`));
130
- process.exit(1);
131
- }
132
- }
@@ -1,63 +0,0 @@
1
- import fs from 'node:fs';
2
- import path from 'node:path';
3
- import { DEPENDENCY_CONFIG_FILE_PATH, OUTPUT_THEME_DIR } from '../config/default.js';
4
-
5
- let MAGENTO_CONFIG;
6
-
7
- try {
8
- const magentoConfigJson = fs.readFileSync(DEPENDENCY_CONFIG_FILE_PATH, 'utf-8');
9
- MAGENTO_CONFIG = JSON.parse(magentoConfigJson);
10
- } catch (error) {
11
- console.error(`Error reading or parsing configuration file at ${DEPENDENCY_CONFIG_FILE_PATH}:`, error.message);
12
- console.error('Try running `devcore:frontend:config --generate` to generate the configuration file.');
13
- process.exit(1);
14
- }
15
-
16
- export const getMagentoConfig = () => MAGENTO_CONFIG;
17
- export const getModulesConfigArray = () => Object.entries(MAGENTO_CONFIG.modules);
18
- export const getThemesConfigArray = () => Object.entries(MAGENTO_CONFIG.themes);
19
- export const getAllMagentoModulesEnabled = () => MAGENTO_CONFIG.allModules;
20
- export const isDev = () => MAGENTO_CONFIG.mode !== 'production';
21
-
22
- export const getOutputDirFromTheme = (themePath) =>
23
- path.resolve(themePath, OUTPUT_THEME_DIR);
24
-
25
- export const getModuleDefinition = (moduleName) =>
26
- MAGENTO_CONFIG.modules[moduleName];
27
-
28
- export const getThemeDefinition = (themeName) =>
29
- MAGENTO_CONFIG.themes[themeName];
30
-
31
- export const MODE = process.env.NODE_ENV;
32
-
33
- export function resolveLibPath(lib) {
34
- return path.join(MAGENTO_CONFIG.LIB_PATH, lib);
35
- }
36
-
37
- export function resolveNodePath(packageName) {
38
- try {
39
- const resolvedPath = import.meta.resolve(packageName);
40
- return resolvedPath.replace('file://', '');
41
- } catch (error) {
42
- console.error(`The package ${packageName} can't be resolved.`);
43
- throw error;
44
- }
45
- }
46
-
47
- export function resolveLibRealPath(lib) {
48
- return MODE === 'production' ? lib : resolveNodePath(lib);
49
- }
50
-
51
- export default {
52
- getMagentoConfig,
53
- getModulesConfigArray,
54
- getThemesConfigArray,
55
- getAllMagentoModulesEnabled,
56
- isDev,
57
- getOutputDirFromTheme,
58
- getModuleDefinition,
59
- getThemeDefinition,
60
- resolveLibPath,
61
- resolveNodePath,
62
- resolveLibRealPath
63
- };
@@ -1,73 +0,0 @@
1
- import themeResolver from './themeResolverSync.js';
2
- import path from 'node:path';
3
- import { MODULE_WEB_PATH, THEME_CSS_FOLDER, THEME_MODULE_WEB_PATH } from '../config/default.js';
4
- import { resolveFileByTheme, getAllJsVueFilesWithInheritanceCached } from './moduleResolver.js';
5
- import configResolver from './configResolver.js';
6
- import fs from 'node:fs/promises';
7
-
8
- const { getMagentoConfig, getModuleDefinition, getThemeDefinition, getModulesConfigArray } = configResolver;
9
-
10
- const MODULE_CSS_EXTEND_FILE = getMagentoConfig().MODULE_CSS_EXTEND_FILE;
11
- const THEME_CSS_SOURCE_FILE = getMagentoConfig().THEME_CSS_SOURCE_FILE;
12
-
13
- async function getThemeImports(themeName, themeConfig) {
14
- if (!themeConfig) {
15
- themeConfig = themeResolver.getThemeConfig(themeName);
16
- }
17
- const themeDefinition = getThemeDefinition(themeName);
18
- const themePath = themeDefinition.src;
19
-
20
- let imports = '';
21
- if (themeConfig.includeCssSourceFromParentThemes && themeDefinition.parent) {
22
- imports += await getThemeImports(themeDefinition.parent, themeConfig);
23
- }
24
-
25
- imports += `@import "${path.join(themePath, THEME_MODULE_WEB_PATH, THEME_CSS_FOLDER, THEME_CSS_SOURCE_FILE)}";\n`;
26
- return imports;
27
- }
28
-
29
- function resolveModuleCssSourcePath(moduleName, themeName) {
30
- let moduleConfigSourcePath = resolveFileByTheme(themeName, moduleName, 'css', MODULE_CSS_EXTEND_FILE);
31
- if (!moduleConfigSourcePath) {
32
- const moduleDefinition = getModuleDefinition(moduleName);
33
- moduleConfigSourcePath = path.join(moduleDefinition.src, MODULE_WEB_PATH, 'css', MODULE_CSS_EXTEND_FILE);
34
- }
35
- return moduleConfigSourcePath;
36
- }
37
-
38
- async function getVueComponentsSource(themeName) {
39
- const vueComponents = await getAllJsVueFilesWithInheritanceCached(themeName);
40
- // split with @source al inicio
41
- const vueComponentSources = Object.entries(vueComponents).map(([name, url]) => {
42
- return `@source "${url}";\n`;
43
- })
44
- return vueComponentSources.join('');
45
- }
46
-
47
- async function getCssImports(themeName) {
48
- const themeConfig = themeResolver.getThemeConfig(themeName);
49
- const excludedModules = new Set(themeConfig.ignoredCssFromModules || []);
50
- const modulesConfig = getModulesConfigArray();
51
-
52
- let cssSource = await getVueComponentsSource(themeName);
53
- let cssImports = '';
54
-
55
- if (themeConfig.ignoredCssFromModules !== 'all') {
56
- for (const [moduleName, moduleConfig] of modulesConfig) {
57
- if (excludedModules.has(moduleName)) continue;
58
-
59
- const filePath = resolveModuleCssSourcePath(moduleName, themeName);
60
- try {
61
- await fs.access(filePath);
62
- cssImports += `@import "${filePath}";\n`;
63
- } catch {
64
- // ignore if file doesn't exist
65
- }
66
- }
67
- }
68
-
69
- cssImports += await getThemeImports(themeName);
70
- return `${cssSource}\n${cssImports}`;
71
- }
72
-
73
- export default getCssImports;
@@ -1,16 +0,0 @@
1
- export default {
2
- name: 'default-node-resolver',
3
- resolveId: {
4
- order: 'post',
5
- handler(id) {
6
- try {
7
- const resolvedPath = import.meta.resolve(id);
8
- if (resolvedPath) {
9
- return resolvedPath.replace('file://', '');
10
- }
11
- } catch (err) {
12
- }
13
- return null;
14
- }
15
- }
16
- };
@@ -1,137 +0,0 @@
1
- class InterceptorManager {
2
- constructor() {
3
- this.interceptors = {};
4
- }
5
-
6
- /**
7
- * Register an interceptor
8
- * @param {string} target - The name of the target function/method to intercept
9
- * @param {string} name - Unique name for the interceptor
10
- * @param {string} type - 'before', 'around', 'after'
11
- * @param {Function} handler - The function to execute
12
- * @param {number} sortOrder - Order of execution
13
- */
14
- addInterceptor(target, name, type, handler, sortOrder = 10) {
15
- if (!this.interceptors[target]) {
16
- this.interceptors[target] = { before: [], around: [], after: [] };
17
- }
18
- if (!['before', 'around', 'after'].includes(type)) {
19
- throw new Error(`Invalid interceptor type: ${type}`);
20
- }
21
- this.interceptors[target][type].push({ name, handler, sortOrder });
22
- this.interceptors[target][type].sort((a, b) => a.sortOrder - b.sortOrder);
23
- }
24
-
25
- /**
26
- * Execute the intercepted method chain synchronously
27
- * @param {string} target - The target method name
28
- * @param {Function} originalMethod - The original function
29
- * @param {Object} context - The 'this' context
30
- * @param {Array} args - Arguments passed to the function
31
- */
32
- executeSync(target, originalMethod, context, ...args) {
33
- const interceptors = this.interceptors[target] || { before: [], around: [], after: [] };
34
-
35
- // Execute 'before' interceptors
36
- for (const interceptor of interceptors.before) {
37
- const result = interceptor.handler.apply(context, args);
38
- if (Array.isArray(result)) {
39
- args = result;
40
- }
41
- }
42
-
43
- // Execute 'around' interceptors
44
- let methodToExecute = (...currentArgs) => {
45
- return originalMethod.apply(context, currentArgs);
46
- };
47
-
48
- if (interceptors.around.length > 0) {
49
- const aroundInterceptors = [...interceptors.around].reverse();
50
- for (const interceptor of aroundInterceptors) {
51
- const next = methodToExecute;
52
- methodToExecute = (...currentArgs) => {
53
- return interceptor.handler.apply(context, [next, ...currentArgs]);
54
- };
55
- }
56
- }
57
-
58
- let result = methodToExecute(...args);
59
-
60
- // Execute 'after' interceptors
61
- for (const interceptor of interceptors.after) {
62
- result = interceptor.handler.apply(context, [result, ...args]);
63
- }
64
-
65
- return result;
66
- }
67
-
68
- /**
69
- * Execute the intercepted method chain
70
- * @param {string} target - The target method name
71
- * @param {Function} originalMethod - The original function
72
- * @param {Object} context - The 'this' context
73
- * @param {Array} args - Arguments passed to the function
74
- */
75
- async execute(target, originalMethod, context, ...args) {
76
- const interceptors = this.interceptors[target] || { before: [], around: [], after: [] };
77
-
78
- // Execute 'before' interceptors
79
- // Before interceptors can modify args by returning an array
80
- for (const interceptor of interceptors.before) {
81
- const result = await interceptor.handler.apply(context, args);
82
- if (Array.isArray(result)) {
83
- args = result;
84
- }
85
- }
86
-
87
- // Execute 'around' interceptors
88
- // Around interceptors receive (proceed, ...args)
89
- let methodToExecute = async (...currentArgs) => {
90
- return await originalMethod.apply(context, currentArgs);
91
- };
92
-
93
- // Wrap around interceptors: first registered is outer-most
94
- if (interceptors.around.length > 0) {
95
- const aroundInterceptors = [...interceptors.around].reverse();
96
- for (const interceptor of aroundInterceptors) {
97
- const next = methodToExecute;
98
- methodToExecute = async (...currentArgs) => {
99
- return await interceptor.handler.apply(context, [next, ...currentArgs]);
100
- };
101
- }
102
- }
103
-
104
- let result = await methodToExecute(...args);
105
-
106
- // Execute 'after' interceptors
107
- // After interceptors receive (result, ...args) and must return result
108
- for (const interceptor of interceptors.after) {
109
- result = await interceptor.handler.apply(context, [result, ...args]);
110
- }
111
-
112
- return result;
113
- }
114
-
115
- /**
116
- * Create a proxy to intercept method calls on an object
117
- * @param {Object} target - The target object (e.g. module exports)
118
- * @param {string} namespace - Namespace for interceptors
119
- * @param {boolean} useAsync - Whether to use async execution
120
- */
121
- intercept(target, namespace, useAsync = true) {
122
- return new Proxy(target, {
123
- get: (obj, prop) => {
124
- const value = obj[prop];
125
- if (typeof value === 'function') {
126
- return (...args) => {
127
- const method = useAsync ? this.execute : this.executeSync;
128
- return method.call(this, `${namespace}::${String(prop)}`, value, obj, ...args);
129
- };
130
- }
131
- return value;
132
- }
133
- });
134
- }
135
- }
136
-
137
- export default new InterceptorManager();
@@ -1,43 +0,0 @@
1
- import moduleResolver from "./moduleResolver.js";
2
-
3
- export default () => {
4
- const components = moduleResolver.getAllJsVueFilesWithInheritanceCached();
5
- return {
6
- name: 'handle-magento-routes-middleware',
7
- configureServer(server) {
8
- server.middlewares.use((req, res, next) => {
9
- const url = req.url;
10
-
11
- const matchedKey = Object.keys(components).find((key) => url.includes(key));
12
-
13
- if (matchedKey) {
14
- const filePath = components[matchedKey];
15
- let suffix = '/@fs';
16
- if (matchedKey === 'lib/vue') {
17
- suffix = '/';
18
- } else if (matchedKey.startsWith('lib/')) {
19
- suffix = '/@fs';
20
- const fileExtension = filePath.split('.').pop();
21
- let mimeType = 'application/node';
22
- if (
23
- fileExtension === 'cjs' ||
24
- fileExtension === 'mjs' ||
25
- fileExtension === 'js'
26
- ) mimeType = 'application/javascript';
27
- if (fileExtension === 'css') mimeType = 'text/css';
28
- if (fileExtension === 'json') mimeType = 'application/json';
29
- if (fileExtension === 'html') mimeType = 'text/html';
30
-
31
- res.setHeader('Content-Type', mimeType);
32
- } else {
33
- suffix = '/@fs';
34
- }
35
- req.url = `${suffix}${filePath}`;
36
- next();
37
- } else {
38
- next();
39
- }
40
- });
41
- },
42
- }
43
- }
@@ -1,37 +0,0 @@
1
- import path from "path";
2
- import fs from "fs/promises";
3
- import moduleResolver from "./moduleResolver.js";
4
- import {
5
- PRECOMPILED_FOLDER,
6
- ALL_JS_VUE_FILES_WITH_INHERITANCE_FILE_NAME
7
- } from "../config/default.js";
8
- import getCssImports from "./cssResolver.js";
9
- import { fileURLToPath } from 'url';
10
- const __filename = fileURLToPath(import.meta.url);
11
- const __dirname = path.dirname(__filename);
12
-
13
- async function writeToFile(outputPath, content) {
14
- await fs.mkdir(path.dirname(outputPath), { recursive: true });
15
- await fs.writeFile(outputPath, content, 'utf-8');
16
- }
17
-
18
- async function precompileCss(themeName) {
19
- const cssContent = await getCssImports(themeName);
20
- const outputPath = path.resolve(PRECOMPILED_FOLDER, themeName, 'precompiled.css');
21
- await writeToFile(outputPath, cssContent);
22
- }
23
-
24
- async function precompileJs(themeName) {
25
- const baseJsPath = path.resolve(__dirname, '../templates/base_main_js_file.js');
26
- const jsOutputPath = path.resolve(PRECOMPILED_FOLDER, themeName, 'precompiled.js');
27
- await fs.copyFile(baseJsPath, jsOutputPath);
28
-
29
- const vueFilesOutputPath = path.join(PRECOMPILED_FOLDER, themeName, ALL_JS_VUE_FILES_WITH_INHERITANCE_FILE_NAME);
30
- const vueFiles = await moduleResolver.getAllJsVueFilesWithInheritance(themeName);
31
- await writeToFile(vueFilesOutputPath, JSON.stringify(vueFiles));
32
- }
33
-
34
- export {
35
- precompileCss,
36
- precompileJs
37
- };
@@ -1,16 +0,0 @@
1
- import { precompileCss, precompileJs } from "./preCompileFiles.js";
2
- import {execSync} from "child_process";
3
-
4
- let isPrecompiled = false;
5
- export default async (themeName) => {
6
- if (isPrecompiled) {
7
- return;
8
- }
9
- console.log('Cleaning .precompiled folder');
10
- execSync('rm -rf .precompiled/*', { stdio: 'inherit' });
11
- execSync(`mkdir -p .precompiled/${themeName}`, { stdio: 'inherit' });
12
- console.log('Generating precompiled files');
13
- await precompileJs(themeName);
14
- await precompileCss(themeName);
15
- isPrecompiled = true;
16
- }
@@ -1,19 +0,0 @@
1
- import path from 'path';
2
- global.appRoot = path.resolve(path.resolve(), 'node_modules');
3
- global.importFromNode = async (moduleName) => {
4
- const suffixTries = [
5
- '.js',
6
- '/index.js',
7
- '/src/index.js',
8
- ];
9
- for (const suffix of suffixTries) {
10
- try {
11
- return await import(`${moduleName}${suffix}`);
12
- } catch (error) {
13
- }
14
- }
15
- throw new Error(`Module ${moduleName} not found`);
16
- }
17
- global.getPathFromNodeModules = (moduleName) => {
18
- return path.resolve(global.appRoot, moduleName);
19
- }
@@ -1,67 +0,0 @@
1
- import path from "path";
2
- import fs from "fs";
3
- import { fileURLToPath } from "url";
4
- import deepmerge from "deepmerge";
5
- import { THEME_MODULE_WEB_PATH } from "../config/default.js";
6
- import configResolver from "./configResolver.js";
7
-
8
- const themeConfigCache = new Map();
9
- const themeConfigPlainCache = new Map();
10
-
11
- function getThemeConfigPath(themeSrc) {
12
- return path.join(
13
- themeSrc,
14
- THEME_MODULE_WEB_PATH,
15
- configResolver.getMagentoConfig().THEME_CONFIG_FILE
16
- );
17
- }
18
-
19
- async function loadThemeConfig(themeDefinition, themeName) {
20
- if (!themeDefinition) return null;
21
- if (themeConfigPlainCache.has(themeName)) return themeConfigPlainCache.get(themeName);
22
-
23
- try {
24
- const configPath = getThemeConfigPath(themeDefinition.src);
25
- fs.accessSync(configPath, fs.constants.F_OK);
26
-
27
- let themeConfig = await import(pathToFileUrl(configPath));
28
- themeConfig = themeConfig.default ?? themeConfig;
29
-
30
- themeConfigPlainCache.set(themeName, themeConfig);
31
- return deepmerge({}, themeConfig);
32
- } catch (error) {
33
- console.error(`Failed to load configuration for theme "${themeName}":`, error.message);
34
- return null;
35
- }
36
- }
37
-
38
- function pathToFileUrl(filePath) {
39
- const resolvedPath = path.resolve(filePath);
40
- const fileUrl = new URL(`file://${resolvedPath}`);
41
- return fileUrl.href;
42
- }
43
-
44
- export async function getThemeConfig(themeName) {
45
- if (themeConfigCache.has(themeName)) return themeConfigCache.get(themeName);
46
-
47
- const themeDefinition = configResolver.getMagentoConfig().themes[themeName];
48
- if (!themeDefinition) return null;
49
-
50
- let themeConfig = await loadThemeConfig(themeDefinition, themeName);
51
- if (!themeConfig) return null;
52
-
53
- themeConfig.includeCssSourceFromParentThemes ??= true;
54
- themeConfig.ignoredCssFromModules ??= [];
55
- themeConfig.exposeNpmPackages ??= [];
56
- if (themeDefinition.parent) {
57
- const parentConfig = await getThemeConfig(themeDefinition.parent);
58
- themeConfig = deepmerge(parentConfig || {}, themeConfig);
59
- }
60
- themeConfigCache.set(themeName, themeConfig);
61
- return themeConfig;
62
- }
63
-
64
- // Export default con todo
65
- export default {
66
- getThemeConfig
67
- };