@oroinc/oro-webpack-config-builder 5.1.0-alpha31 → 5.1.0-alpha34
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/error-handler.js +95 -0
- package/loader/inject-loader/index.js +1 -0
- package/loader/inject-loader/index.js.map +1 -0
- package/modules-config/layout-modules-config-loader.js +7 -3
- package/modules-config/modules-config-loader.js +18 -1
- package/oro-webpack-config.js +64 -17
- package/package.json +15 -14
- package/plugin/logs/after-webpack-logs-plugin.js +25 -0
- package/style/style-loader.js +13 -9
- package/theme-config-factory.js +5 -9
- package/utils.js +30 -0
- package/validation/assets-validator.js +103 -0
- package/validation/errors/assets-input-file-error.js +24 -0
- package/validation/errors/assets-schema-error.js +40 -0
- package/validation/errors/base-error.js +37 -0
- package/validation/errors/jsmodules-extra-modules-error.js +22 -0
- package/validation/errors/jsmodules-schema-error.js +40 -0
- package/validation/errors/styles-error.js +24 -0
- package/validation/index.js +36 -0
- package/validation/jsmodules-validator.js +53 -0
- package/validation/schema-validator.js +62 -0
- package/validation/schemas/assets-schema-full.js +22 -0
- package/validation/schemas/assets-schema.js +32 -0
- package/validation/schemas/jsmodules-schema-full.js +11 -0
- package/validation/schemas/jsmodules-schema.js +76 -0
- package/writer/dynamic-imports-file-writer.js +2 -2
- package/writer/scss-entry-point-file-writer.js +1 -1
- package/messages.js +0 -29
package/error-handler.js
ADDED
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
const BaseError = require('./validation/errors/base-error');
|
|
2
|
+
const {isVerboseMode} = require('./utils');
|
|
3
|
+
const {red, yellow, green, bgRed} = require('colorette');
|
|
4
|
+
|
|
5
|
+
const emptyLine = length => new Array(length).fill(' ').join('');
|
|
6
|
+
const multiline = (color, msg) => {
|
|
7
|
+
msg = ` ${msg}`;
|
|
8
|
+
msg = msg + emptyLine(120 - msg.length);
|
|
9
|
+
|
|
10
|
+
return `\n${color(emptyLine(msg.length))}\n${color(msg)}\n${color(emptyLine(msg.length))}`;
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
class ErrorHandler {
|
|
14
|
+
constructor() {
|
|
15
|
+
this.failedThemes = [];
|
|
16
|
+
|
|
17
|
+
process.on('beforeExit', code => {
|
|
18
|
+
this.onProcess();
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Show a message about failed themes
|
|
24
|
+
*/
|
|
25
|
+
onProcess() {
|
|
26
|
+
if (this.failedThemes.length) {
|
|
27
|
+
let msg = '[ERROR] Assets build';
|
|
28
|
+
|
|
29
|
+
if (this.failedThemes.length === 1) {
|
|
30
|
+
msg = `${msg} for "${this.failedThemes[0]}" theme failed.`;
|
|
31
|
+
} else {
|
|
32
|
+
msg = `${msg} for "${this.failedThemes.join(', ')}" themes failed.`;
|
|
33
|
+
}
|
|
34
|
+
console.error(multiline(bgRed, msg));
|
|
35
|
+
process.exit(1);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Executes when the Webpack Compiler will complete a compilation
|
|
41
|
+
* In case of empty Webpack Config this method will not run
|
|
42
|
+
*
|
|
43
|
+
* @param {Object} stats
|
|
44
|
+
*/
|
|
45
|
+
onBuildComplete(stats) {
|
|
46
|
+
const failed = stats?.compilation?.errors.length !== 0;
|
|
47
|
+
|
|
48
|
+
if (failed) {
|
|
49
|
+
console.error(multiline(bgRed, '[ERROR] Assets build failed.'));
|
|
50
|
+
process.exit(1);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* @param {Array|string} errors
|
|
56
|
+
* @param {string} [failedTheme]
|
|
57
|
+
*/
|
|
58
|
+
displayError(errors, failedTheme) {
|
|
59
|
+
if (typeof failedTheme === 'string') {
|
|
60
|
+
this.failedThemes.push(failedTheme);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
if (typeof errors === 'string') {
|
|
64
|
+
errors = [errors];
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
const errorMessage = errors.map(err => {
|
|
68
|
+
const highlightPrefix = str => {
|
|
69
|
+
const prefix = str.substring(0, str.search(':'));
|
|
70
|
+
return red(prefix) + str.substring(str.search(':'));
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
if (err instanceof BaseError) {
|
|
74
|
+
err.message = `${err.message}\n${green(err.extra)}`;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
let msg = err.message;
|
|
78
|
+
|
|
79
|
+
if (isVerboseMode()) {
|
|
80
|
+
msg = highlightPrefix(err.stack);
|
|
81
|
+
} else {
|
|
82
|
+
const command = yellow('php bin/console oro:assets:build --env=dev --verbose');
|
|
83
|
+
const info = `${green(`Run the command ${command} to see more information`)}`;
|
|
84
|
+
|
|
85
|
+
msg = highlightPrefix(`${err.name}: ${msg}\n${info}`);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
return `${msg}\n`;
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
console.error(errorMessage.join('\n'));
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
module.exports = ErrorHandler;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
module.exports=function(e){var n={};function t(i){if(n[i])return n[i].exports;var r=n[i]={i:i,l:!1,exports:{}};return e[i].call(r.exports,r,r.exports,t),r.l=!0,r.exports}return t.m=e,t.c=n,t.d=function(e,n,i){t.o(e,n)||Object.defineProperty(e,n,{configurable:!1,enumerable:!0,get:i})},t.r=function(e){Object.defineProperty(e,"__esModule",{value:!0})},t.n=function(e){var n=e&&e.__esModule?function(){return e.default}:function(){return e};return t.d(n,"a",n),n},t.o=function(e,n){return Object.prototype.hasOwnProperty.call(e,n)},t.p="",t.w={},t(t.s=3)}([function(e,n){e.exports=require("babel-core")},function(e,n,t){"use strict";Object.defineProperty(n,"__esModule",{value:!0});var i=t(0);n.default=(0,i.template)("\n module.exports = function __injector(__injections) {\n __injections = __injections || {};\n\n (function __validateInjection() {\n var validDependencies = DEPENDENCIES;\n var injectedDependencies = Object.keys(__injections);\n var invalidInjectedDependencies = injectedDependencies.filter(function (dependency) {\n return validDependencies.indexOf(dependency) === -1;\n });\n\n if (invalidInjectedDependencies.length > 0) {\n var validDependenciesString = ' - ' + validDependencies.join('\\n - ');\n var injectedDependenciesString = ' - ' + injectedDependencies.join('\\n - ');\n var invalidDependenciesString = ' - ' + invalidInjectedDependencies.join('\\n - ');\n\n throw new Error('Injection Error in ' + SOURCE_PATH + '\\n\\n' +\n 'The following injections are invalid:\\n' + invalidDependenciesString + '\\n\\n' +\n 'The following injections were passed in:\\n' + injectedDependenciesString + '\\n\\n' +\n 'Valid injection targets for this module are:\\n' + validDependenciesString + '\\n'\n );\n }\n })();\n\n __injector.sourcePath = SOURCE_PATH;\n __injector.validDependencies = DEPENDENCIES;\n\n var module = { exports: {} };\n var exports = module.exports;\n\n (function () {\n SOURCE\n })();\n\n return module.exports;\n }\n"),e.exports=n.default},function(e,n,t){"use strict";Object.defineProperty(n,"__esModule",{value:!0}),n.default=function(e,n,t){var i=(0,r.transform)(n,{babelrc:!1,code:!1,compact:!1,filename:e.resourcePath}).ast,o=[];(0,r.traverse)(i,{CallExpression:function(e){r.types.isIdentifier(e.node.callee,{name:"require"})&&(o.push(function(e){var n=e.node.arguments[0].value;return e.replaceWith(r.types.expressionStatement(r.types.conditionalExpression(r.types.callExpression(r.types.memberExpression(r.types.identifier("__injections"),r.types.identifier("hasOwnProperty"),!1),[r.types.stringLiteral(n)]),r.types.memberExpression(r.types.identifier("__injections"),r.types.stringLiteral(n),!0),e.node))),n}(e)),e.skip())}}),0===o.length&&e.emitWarning("The module you are trying to inject into doesn't have any dependencies. Are you sure you want to do this?");var a=r.types.file(r.types.program([(0,s.default)({SOURCE:i,SOURCE_PATH:r.types.stringLiteral(e.resourcePath),DEPENDENCIES:r.types.arrayExpression(o.map(function(e){return r.types.stringLiteral(e)}))})]));return(0,r.transformFromAst)(a,n,{sourceMaps:e.sourceMap,sourceFileName:e.resourcePath,inputSourceMap:t,babelrc:!1,compact:!1,filename:e.resourcePath})};var i,r=t(0),o=t(1),s=(i=o)&&i.__esModule?i:{default:i};e.exports=n.default},function(e,n,t){"use strict";Object.defineProperty(n,"__esModule",{value:!0}),n.default=function(e,n){this.cacheable&&this.cacheable();var t=(0,o.default)(this,e,n),i=t.code,r=t.map;this.callback(null,i,r)};var i,r=t(2),o=(i=r)&&i.__esModule?i:{default:i};e.exports=n.default}]);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sources":["webpack:///webpack/bootstrap 393a9525777b8b817cc3","webpack:///external \"babel-core\"","webpack:///src/index.js","webpack:///src/injectify.js","webpack:///src/wrapper_template.js"],"sourcesContent":[" \t// The module cache\n \tvar installedModules = {};\n\n \t// The require function\n \tfunction __webpack_require__(moduleId) {\n\n \t\t// Check if module is in cache\n \t\tif(installedModules[moduleId]) {\n \t\t\treturn installedModules[moduleId].exports;\n \t\t}\n \t\t// Create a new module (and put it into the cache)\n \t\tvar module = installedModules[moduleId] = {\n \t\t\ti: moduleId,\n \t\t\tl: false,\n \t\t\texports: {}\n \t\t};\n\n \t\t// Execute the module function\n \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n \t\t// Flag the module as loaded\n \t\tmodule.l = true;\n\n \t\t// Return the exports of the module\n \t\treturn module.exports;\n \t}\n\n\n \t// expose the modules object (__webpack_modules__)\n \t__webpack_require__.m = modules;\n\n \t// expose the module cache\n \t__webpack_require__.c = installedModules;\n\n \t// define getter function for harmony exports\n \t__webpack_require__.d = function(exports, name, getter) {\n \t\tif(!__webpack_require__.o(exports, name)) {\n \t\t\tObject.defineProperty(exports, name, {\n \t\t\t\tconfigurable: false,\n \t\t\t\tenumerable: true,\n \t\t\t\tget: getter\n \t\t\t});\n \t\t}\n \t};\n\n \t// getDefaultExport function for compatibility with non-harmony modules\n \t__webpack_require__.n = function(module) {\n \t\tvar getter = module && module.__esModule ?\n \t\t\tfunction getDefault() { return module['default']; } :\n \t\t\tfunction getModuleExports() { return module; };\n \t\t__webpack_require__.d(getter, 'a', getter);\n \t\treturn getter;\n \t};\n\n \t// Object.prototype.hasOwnProperty.call\n \t__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };\n\n \t// __webpack_public_path__\n \t__webpack_require__.p = \"\";\n\n \t// Load entry module and return exports\n \treturn __webpack_require__(__webpack_require__.s = 1);\n\n\n\n// WEBPACK FOOTER //\n// webpack/bootstrap 393a9525777b8b817cc3","module.exports = require(\"babel-core\");\n\n\n//////////////////\n// WEBPACK FOOTER\n// external \"babel-core\"\n// module id = 0\n// module chunks = 0","// @flow\n\nimport injectify from './injectify.js';\n\nexport default function injectifyLoader(source, inputSourceMap) {\n if (this.cacheable) {\n this.cacheable();\n }\n\n const { code, map } = injectify(this, source, inputSourceMap);\n this.callback(null, code, map);\n}\n\n\n\n// WEBPACK FOOTER //\n// src/index.js","// @flow\n\nimport { transform, traverse, types as t, transformFromAst } from 'babel-core';\nimport wrapperTemplate from './wrapper_template.js';\n\nfunction processRequireCall(path) {\n const dependencyString = path.node.arguments[0].value;\n path.replaceWith(\n t.expressionStatement(\n t.conditionalExpression(\n t.callExpression(\n t.memberExpression(\n t.identifier('__injections'),\n t.identifier('hasOwnProperty'),\n false,\n ),\n [\n t.stringLiteral(dependencyString),\n ],\n ),\n t.memberExpression(\n t.identifier('__injections'),\n t.stringLiteral(dependencyString),\n true,\n ),\n path.node,\n ),\n ),\n );\n\n return dependencyString;\n}\n\nexport default function injectify(context, source, inputSourceMap) {\n const { ast } = transform(source, {\n babelrc: false,\n code: false,\n compact: false,\n filename: context.resourcePath,\n });\n\n const dependencies = [];\n traverse(ast, {\n CallExpression(path) {\n if (t.isIdentifier(path.node.callee, { name: 'require' })) {\n dependencies.push(processRequireCall(path));\n path.skip();\n }\n },\n });\n\n if (dependencies.length === 0) {\n context.emitWarning('The module you are trying to inject into doesn\\'t have any dependencies. ' +\n 'Are you sure you want to do this?');\n }\n\n const dependenciesArrayAst = t.arrayExpression(\n dependencies.map(dependency => t.stringLiteral(dependency)),\n );\n const wrapperModuleAst = t.file(t.program([\n wrapperTemplate({ SOURCE: ast, DEPENDENCIES: dependenciesArrayAst }),\n ]));\n\n return transformFromAst(wrapperModuleAst, source, {\n sourceMaps: context.sourceMap,\n sourceFileName: context.resourcePath,\n inputSourceMap,\n babelrc: false,\n compact: false,\n filename: context.resourcePath,\n });\n}\n\n\n\n// WEBPACK FOOTER //\n// src/injectify.js","// @flow\n\nimport { template } from 'babel-core';\n\nexport default template(`\n module.exports = function __injector(__injections) {\n __injections = __injections || {};\n\n (function __validateInjection() {\n var validDependencies = DEPENDENCIES;\n var injectedDependencies = Object.keys(__injections);\n var invalidInjectedDependencies = injectedDependencies.filter(function (dependency) {\n return validDependencies.indexOf(dependency) === -1;\n });\n\n if (invalidInjectedDependencies.length > 0) {\n var validDependenciesString = '- ' + validDependencies.join('\\\\n- ');\n var injectedDependenciesString = '- ' + injectedDependencies.join('\\\\n- ');\n var invalidDependenciesString = '- ' + invalidInjectedDependencies.join('\\\\n- ');\n\n throw new Error('Some of the injections you passed in are invalid.\\\\n' +\n 'Valid injection targets for this module are:\\\\n' + validDependenciesString + '\\\\n' +\n 'The following injections were passed in:\\\\n' + injectedDependenciesString + '\\\\n' +\n 'The following injections are invalid:\\\\n' + invalidDependenciesString + '\\\\n'\n );\n }\n })();\n\n var module = { exports: {} };\n var exports = module.exports;\n\n (function () {\n SOURCE\n })();\n\n return module.exports;\n }\n`);\n\n\n\n// WEBPACK FOOTER //\n// src/wrapper_template.js"],"mappings":";;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;AC7DA;;;;;;;;;;;;;;;;;;;ACIA;AACA;AAHA;AACA;;;;;AACA;AACA;AACA;AACA;AACA;AAJA;AAAA;AAAA;AACA;AAKA;AACA;AACA;;;;;;;;;;;;;ACqBA;AACA;AAhCA;AACA;AAAA;AACA;;;;;AAJA;AACA;AAIA;AACA;AACA;AACA;AAsBA;AACA;AACA;AACA;AAAA;AAEA;AACA;AACA;AACA;AAJA;AADA;AACA;AAOA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AANA;AACA;AAQA;AACA;AAEA;AACA;AACA;AACA;AAAA;AAEA;AACA;AAGA;AACA;AACA;AACA;AACA;AACA;AACA;AANA;AAQA;;;;;;;;;;;;;;ACrEA;AACA;AACA;AACA;;;;A","sourceRoot":""}
|
|
@@ -8,13 +8,17 @@ class LayoutModulesConfigLoader extends ModulesConfigLoader {
|
|
|
8
8
|
*/
|
|
9
9
|
loadConfig(theme, filePath) {
|
|
10
10
|
let themeConfig = super.loadConfig(theme, path.join('Resources/views/layouts/', theme, filePath));
|
|
11
|
+
|
|
11
12
|
// recursive process parent theme
|
|
12
13
|
const {parent: parentTheme} = this.themes[theme];
|
|
13
14
|
if (typeof parentTheme === 'string') {
|
|
15
|
+
const processedFiles = this.processedFiles;
|
|
14
16
|
const parentThemeConfig = this.loadConfig(parentTheme, filePath);
|
|
17
|
+
|
|
15
18
|
themeConfig = merge(parentThemeConfig, themeConfig);
|
|
19
|
+
// processedFiles from parent theme is added to processedFiles of current theme
|
|
20
|
+
this._processedFiles = [...processedFiles, ...this.processedFiles];
|
|
16
21
|
}
|
|
17
|
-
|
|
18
22
|
return themeConfig;
|
|
19
23
|
}
|
|
20
24
|
|
|
@@ -40,7 +44,7 @@ class LayoutModulesConfigLoader extends ModulesConfigLoader {
|
|
|
40
44
|
* @return {string[]}
|
|
41
45
|
*/
|
|
42
46
|
extraJSBuildNames(theme) {
|
|
43
|
-
const {extra_js_builds:
|
|
47
|
+
const {extra_js_builds: extraJSBuilds = []} = this._themes[theme] || {};
|
|
44
48
|
return [...extraJSBuilds.map(suffix => `${theme}-${suffix}`)];
|
|
45
49
|
}
|
|
46
50
|
|
|
@@ -66,7 +70,7 @@ class LayoutModulesConfigLoader extends ModulesConfigLoader {
|
|
|
66
70
|
const result = [];
|
|
67
71
|
if (marches) {
|
|
68
72
|
const [, theme, suffix] = marches;
|
|
69
|
-
const {extra_js_builds:
|
|
73
|
+
const {extra_js_builds: extraJSBuilds = []} = this._themes[theme] || {};
|
|
70
74
|
if (extraJSBuilds.includes(suffix)) {
|
|
71
75
|
result.push(marches[1], marches[2]);
|
|
72
76
|
} else {
|
|
@@ -2,6 +2,7 @@ const path = require('path');
|
|
|
2
2
|
const fs = require('fs');
|
|
3
3
|
const merge = require('deepmerge');
|
|
4
4
|
const yaml = require('js-yaml');
|
|
5
|
+
const validation = require('../validation');
|
|
5
6
|
|
|
6
7
|
// merge only unique items
|
|
7
8
|
const arrayMerge = (target, source) => target.concat(source.filter(item => !target.includes(item)));
|
|
@@ -28,6 +29,13 @@ class ModulesConfigLoader {
|
|
|
28
29
|
return this.themeNames;
|
|
29
30
|
}
|
|
30
31
|
|
|
32
|
+
/**
|
|
33
|
+
* @returns {Array}
|
|
34
|
+
*/
|
|
35
|
+
get processedFiles() {
|
|
36
|
+
return [...this._processedFiles];
|
|
37
|
+
}
|
|
38
|
+
|
|
31
39
|
/**
|
|
32
40
|
* @param {Array} bundles Array of ordered symfony bundle paths
|
|
33
41
|
* @param {string} themesLocation Path inside the bundle, where to find the theme
|
|
@@ -36,6 +44,7 @@ class ModulesConfigLoader {
|
|
|
36
44
|
constructor(bundles, themesLocation, themeInfoFileName) {
|
|
37
45
|
this._bundles = bundles;
|
|
38
46
|
this._themes = this._getThemes(themesLocation, themeInfoFileName);
|
|
47
|
+
this._processedFiles = [];
|
|
39
48
|
}
|
|
40
49
|
|
|
41
50
|
/**
|
|
@@ -76,6 +85,8 @@ class ModulesConfigLoader {
|
|
|
76
85
|
loadConfig(theme, filePath) {
|
|
77
86
|
let configs = {};
|
|
78
87
|
const filePaths = [].concat(filePath);
|
|
88
|
+
|
|
89
|
+
this._processedFiles = [];
|
|
79
90
|
this._bundles.forEach(bundle => {
|
|
80
91
|
let absolutePath;
|
|
81
92
|
|
|
@@ -88,10 +99,16 @@ class ModulesConfigLoader {
|
|
|
88
99
|
}
|
|
89
100
|
|
|
90
101
|
if (absolutePath) {
|
|
91
|
-
const
|
|
102
|
+
const rawDoc = fs.readFileSync(absolutePath, 'utf8');
|
|
103
|
+
const doc = yaml.load(rawDoc);
|
|
104
|
+
|
|
105
|
+
this._processedFiles.push(absolutePath);
|
|
106
|
+
|
|
107
|
+
validation.checkSchema(absolutePath, doc, theme);
|
|
92
108
|
configs = merge(configs, doc);
|
|
93
109
|
}
|
|
94
110
|
});
|
|
111
|
+
|
|
95
112
|
return configs;
|
|
96
113
|
}
|
|
97
114
|
}
|
package/oro-webpack-config.js
CHANGED
|
@@ -3,6 +3,7 @@ const printf = require('printf');
|
|
|
3
3
|
const AppConfigLoader = require('./app-config-loader');
|
|
4
4
|
const AppModulesFileWriter = require('./writer/app-modules-file-writer');
|
|
5
5
|
const CleanupStatsPlugin = require('./plugin/stats/cleanup-stats-plugin');
|
|
6
|
+
const AfterWebpackLogsPlugin = require('./plugin/logs/after-webpack-logs-plugin');
|
|
6
7
|
const ConfigsFileWriter = require('./writer/configs-file-writer');
|
|
7
8
|
const EntryPointFileWriter = require('./writer/scss-entry-point-file-writer');
|
|
8
9
|
const LayoutModulesConfigLoader = require('./modules-config/layout-modules-config-loader');
|
|
@@ -23,33 +24,44 @@ const resolve = require('enhanced-resolve');
|
|
|
23
24
|
const {merge: webpackMerge} = require('webpack-merge');
|
|
24
25
|
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
|
|
25
26
|
const RtlCssWebpackPlugin = require('rtlcss-webpack-plugin');
|
|
26
|
-
const
|
|
27
|
+
const validation = require('./validation');
|
|
28
|
+
const EventEmitter = require('events');
|
|
29
|
+
const ErrorHandler = require('./error-handler');
|
|
30
|
+
|
|
27
31
|
require('resolve-url-loader');
|
|
28
32
|
|
|
29
33
|
class ConfigBuilder {
|
|
30
34
|
constructor() {
|
|
31
|
-
this._publicPath = 'public/';
|
|
32
|
-
this._adminTheme = 'admin.oro';
|
|
33
35
|
this._enableLayoutThemes = false;
|
|
34
36
|
this._defaultLayoutThemes = null;
|
|
35
|
-
this.
|
|
36
|
-
this.
|
|
37
|
+
this.emitter = new EventEmitter();
|
|
38
|
+
this.errorHandler = new ErrorHandler();
|
|
39
|
+
this.addListeners();
|
|
40
|
+
this.setPublicPath('public/');
|
|
41
|
+
this.setAdminTheme('admin.oro');
|
|
42
|
+
this.setVersionFormat('%s?v=%s');
|
|
43
|
+
this.setBabelConfig({
|
|
37
44
|
sourceType: 'unambiguous',
|
|
38
45
|
presets: [
|
|
39
46
|
[
|
|
40
47
|
'@babel/preset-env', {
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
48
|
+
useBuiltIns: 'usage',
|
|
49
|
+
corejs: {
|
|
50
|
+
version: 3,
|
|
51
|
+
proposals: true
|
|
52
|
+
}
|
|
45
53
|
}
|
|
46
|
-
}
|
|
47
54
|
]
|
|
48
55
|
],
|
|
49
56
|
plugins: [
|
|
50
57
|
'@babel/plugin-transform-runtime'
|
|
51
58
|
]
|
|
52
|
-
};
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
addListeners() {
|
|
63
|
+
this.emitter.on('publicPath:updated', path => validation.setPublicPath(path));
|
|
64
|
+
this.emitter.on('build:complete', stats => this.errorHandler.onBuildComplete(stats));
|
|
53
65
|
}
|
|
54
66
|
|
|
55
67
|
/**
|
|
@@ -59,6 +71,7 @@ class ConfigBuilder {
|
|
|
59
71
|
*/
|
|
60
72
|
setPublicPath(publicPath) {
|
|
61
73
|
this._publicPath = publicPath;
|
|
74
|
+
this.emitter.emit('publicPath:updated', publicPath);
|
|
62
75
|
return this;
|
|
63
76
|
}
|
|
64
77
|
|
|
@@ -80,6 +93,7 @@ class ConfigBuilder {
|
|
|
80
93
|
*/
|
|
81
94
|
setVersionFormat(versionFormat) {
|
|
82
95
|
this._versionFormat = versionFormat;
|
|
96
|
+
this.emitter.emit('versionFormat:updated', versionFormat);
|
|
83
97
|
return this;
|
|
84
98
|
}
|
|
85
99
|
|
|
@@ -96,6 +110,7 @@ class ConfigBuilder {
|
|
|
96
110
|
}
|
|
97
111
|
|
|
98
112
|
this._adminTheme = adminTheme;
|
|
113
|
+
this.emitter.emit('adminTheme:updated', adminTheme);
|
|
99
114
|
return this;
|
|
100
115
|
}
|
|
101
116
|
|
|
@@ -105,8 +120,10 @@ class ConfigBuilder {
|
|
|
105
120
|
enableLayoutThemes(themes) {
|
|
106
121
|
if (themes) {
|
|
107
122
|
this._defaultLayoutThemes = themes;
|
|
123
|
+
this.emitter.emit('defaultLayoutThemes:updated', themes);
|
|
108
124
|
}
|
|
109
125
|
this._enableLayoutThemes = true;
|
|
126
|
+
this.emitter.emit('enableLayoutThemes:updated', true);
|
|
110
127
|
return this;
|
|
111
128
|
}
|
|
112
129
|
|
|
@@ -117,6 +134,7 @@ class ConfigBuilder {
|
|
|
117
134
|
*/
|
|
118
135
|
setBabelConfig(babelConfig) {
|
|
119
136
|
this._babelConfig = babelConfig;
|
|
137
|
+
this.emitter.emit('babelConfig:updated', babelConfig);
|
|
120
138
|
return this;
|
|
121
139
|
}
|
|
122
140
|
|
|
@@ -132,19 +150,30 @@ class ConfigBuilder {
|
|
|
132
150
|
try {
|
|
133
151
|
commonConfig = this._getCommonWebpackConfig(args, env);
|
|
134
152
|
} catch (e) {
|
|
135
|
-
|
|
153
|
+
this.errorHandler.displayError(e);
|
|
136
154
|
process.exit(1);
|
|
137
155
|
}
|
|
138
156
|
|
|
139
157
|
const webpackConfigs = [];
|
|
140
158
|
const requestedBuildNames = env.theme ? env.theme.split(',') : [];
|
|
141
159
|
const buildNames = this._getBuildNames(requestedBuildNames);
|
|
160
|
+
|
|
161
|
+
const buildErrors = [];
|
|
162
|
+
validation.jsmodulesValidator.emitter.on('error', error => buildErrors.push(error));
|
|
163
|
+
validation.assetsValidation.emitter.on('error', error => buildErrors.push(error));
|
|
142
164
|
buildNames.forEach(buildName => {
|
|
143
165
|
let buildConfig;
|
|
166
|
+
// flush all collected errors from previews builds
|
|
167
|
+
buildErrors.splice(0, buildErrors.length);
|
|
168
|
+
|
|
144
169
|
try {
|
|
145
170
|
buildConfig = this._getThemeWebpackConfig(buildName, args, env);
|
|
146
|
-
} catch (
|
|
147
|
-
|
|
171
|
+
} catch (error) {
|
|
172
|
+
buildErrors.push(error);
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
if (buildErrors.length) {
|
|
176
|
+
this.errorHandler.displayError(buildErrors, buildName);
|
|
148
177
|
return;
|
|
149
178
|
}
|
|
150
179
|
|
|
@@ -331,7 +360,10 @@ class ConfigBuilder {
|
|
|
331
360
|
}),
|
|
332
361
|
new webpack.optimize.MinChunkSizePlugin({
|
|
333
362
|
minChunkSize: 30000 // Minimum number of characters
|
|
334
|
-
})
|
|
363
|
+
}),
|
|
364
|
+
new AfterWebpackLogsPlugin(
|
|
365
|
+
stats => this.emitter.emit('build:complete', stats)
|
|
366
|
+
)
|
|
335
367
|
]
|
|
336
368
|
};
|
|
337
369
|
|
|
@@ -403,6 +435,11 @@ class ConfigBuilder {
|
|
|
403
435
|
buildPublicPath = '/build/admin/';
|
|
404
436
|
const jsModulesConfig = this._themeConfigFactory.loadConfig(buildName,
|
|
405
437
|
['Resources/config/oro/jsmodules.yml', 'Resources/config/jsmodules.yml']);
|
|
438
|
+
validation.jsmodulesValidator.checkFullSchema(
|
|
439
|
+
jsModulesConfig,
|
|
440
|
+
this._themeConfigFactory?._configLoader.processedFiles,
|
|
441
|
+
buildName
|
|
442
|
+
);
|
|
406
443
|
jsBuildConfig = this._themeConfigFactory.create(buildPublicPath, jsModulesConfig);
|
|
407
444
|
} else if (this._layoutModulesConfigLoader.isExtraJSBuild(buildName)) {
|
|
408
445
|
const [theme, suffix] = this._layoutModulesConfigLoader.splitBuildName(buildName);
|
|
@@ -412,11 +449,21 @@ class ConfigBuilder {
|
|
|
412
449
|
const baseConfig = this._layoutThemeConfigFactory.loadConfig(theme, 'config/jsmodules.yml');
|
|
413
450
|
const extraConfig = this._layoutThemeConfigFactory.loadConfig(theme, `config/jsmodules-${suffix}.yml`);
|
|
414
451
|
const jsModulesConfig = this._layoutThemeConfigFactory.extendConfig(baseConfig, extraConfig);
|
|
452
|
+
validation.jsmodulesValidator.checkFullSchema(
|
|
453
|
+
jsModulesConfig,
|
|
454
|
+
this._layoutThemeConfigFactory?._configLoader.processedFiles,
|
|
455
|
+
buildName
|
|
456
|
+
);
|
|
415
457
|
jsBuildConfig = this._layoutThemeConfigFactory.create(buildPublicPath, jsModulesConfig);
|
|
416
458
|
} else {
|
|
417
459
|
themeDefinition = this._layoutModulesConfigLoader.themes[buildName];
|
|
418
460
|
buildPublicPath = `/build/${buildName}/`;
|
|
419
461
|
const jsModulesConfig = this._layoutThemeConfigFactory.loadConfig(buildName, 'config/jsmodules.yml');
|
|
462
|
+
validation.jsmodulesValidator.checkFullSchema(
|
|
463
|
+
jsModulesConfig,
|
|
464
|
+
this._layoutThemeConfigFactory?._configLoader.processedFiles,
|
|
465
|
+
buildName
|
|
466
|
+
);
|
|
420
467
|
jsBuildConfig = this._layoutThemeConfigFactory.create(buildPublicPath, jsModulesConfig);
|
|
421
468
|
}
|
|
422
469
|
const {rtl_support: rtlSupport = false} = themeDefinition;
|
|
@@ -481,7 +528,7 @@ class ConfigBuilder {
|
|
|
481
528
|
...prepareModulesShim(resolver, jsBuildConfig.shim)
|
|
482
529
|
]
|
|
483
530
|
}
|
|
484
|
-
}
|
|
531
|
+
};
|
|
485
532
|
}
|
|
486
533
|
|
|
487
534
|
_initialize(args, env) {
|
|
@@ -520,7 +567,7 @@ class ConfigBuilder {
|
|
|
520
567
|
}
|
|
521
568
|
|
|
522
569
|
_getVersionedPath(name, assetVersion) {
|
|
523
|
-
if(!assetVersion) {
|
|
570
|
+
if (!assetVersion) {
|
|
524
571
|
return name;
|
|
525
572
|
}
|
|
526
573
|
return printf(this._versionFormat, name, assetVersion);
|
package/package.json
CHANGED
|
@@ -1,19 +1,19 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@oroinc/oro-webpack-config-builder",
|
|
3
|
-
"version": "5.1.0-
|
|
3
|
+
"version": "5.1.0-alpha34",
|
|
4
4
|
"author": "Oro, Inc (https://www.oroinc.com)",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"description": "An integration of OroPlatform based applications with the Webpack.",
|
|
7
7
|
"main": "oro-webpack-config.js",
|
|
8
8
|
"dependencies": {
|
|
9
|
-
"@babel/core": "~7.
|
|
10
|
-
"@babel/plugin-transform-runtime": "~7.
|
|
11
|
-
"@babel/preset-env": "~7.16.
|
|
9
|
+
"@babel/core": "~7.17.9",
|
|
10
|
+
"@babel/plugin-transform-runtime": "~7.17.0",
|
|
11
|
+
"@babel/preset-env": "~7.16.11",
|
|
12
12
|
"autoprefixer": "~10.4.0",
|
|
13
13
|
"babel-loader": "~8.2.3",
|
|
14
14
|
"bindings": "~1.5.0",
|
|
15
|
-
"css-loader": "~6.
|
|
16
|
-
"css-minimizer-webpack-plugin": "~3.1
|
|
15
|
+
"css-loader": "~6.7.1",
|
|
16
|
+
"css-minimizer-webpack-plugin": "~3.4.1",
|
|
17
17
|
"deepmerge": "~4.2.2",
|
|
18
18
|
"exports-loader": "~3.1.0",
|
|
19
19
|
"expose-loader": "~3.1.0",
|
|
@@ -23,26 +23,27 @@
|
|
|
23
23
|
"html-webpack-plugin": "~5.5.0",
|
|
24
24
|
"imports-loader": "~3.1.1",
|
|
25
25
|
"js-yaml": "~4.1.0",
|
|
26
|
-
"mini-css-extract-plugin": "~2.
|
|
26
|
+
"mini-css-extract-plugin": "~2.6.0",
|
|
27
27
|
"minimist": "~1.2.3",
|
|
28
28
|
"nan": "~2.15.0",
|
|
29
29
|
"path": "0.12.7",
|
|
30
|
-
"postcss": "~8.
|
|
30
|
+
"postcss": "~8.4.5",
|
|
31
31
|
"postcss-loader": "~6.2.0",
|
|
32
32
|
"printf": "~0.6.0",
|
|
33
|
-
"resolve-url-loader": "
|
|
33
|
+
"resolve-url-loader": "^5.0.0",
|
|
34
34
|
"rtlcss-webpack-plugin": "~4.0.6",
|
|
35
|
-
"sass": "~1.
|
|
36
|
-
"sass-loader": "~12.
|
|
35
|
+
"sass": "~1.50.0",
|
|
36
|
+
"sass-loader": "~12.6.0",
|
|
37
|
+
"schema-utils": "^4.0.0",
|
|
37
38
|
"style-loader": "~3.3.1",
|
|
38
|
-
"terser": "~5.
|
|
39
|
+
"terser": "~5.12.1",
|
|
39
40
|
"text-loader": "0.0.1",
|
|
40
41
|
"underscore": "~1.13.1",
|
|
41
42
|
"url-loader": "~4.1.1",
|
|
42
|
-
"webpack": "~5.
|
|
43
|
+
"webpack": "~5.72.0",
|
|
43
44
|
"webpack-bundle-analyzer": "~4.5.0",
|
|
44
45
|
"webpack-cli": "~4.9.1",
|
|
45
|
-
"webpack-dev-server": "
|
|
46
|
+
"webpack-dev-server": "^4.7.3",
|
|
46
47
|
"webpack-merge": "~5.8.0",
|
|
47
48
|
"wildcard": "~2.0.0"
|
|
48
49
|
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
const {once} = require('underscore');
|
|
2
|
+
|
|
3
|
+
class AfterWebpackLogsPlugin {
|
|
4
|
+
/**
|
|
5
|
+
* @param {function} afterLogsCb
|
|
6
|
+
*/
|
|
7
|
+
constructor(afterLogsCb) {
|
|
8
|
+
if (typeof afterLogsCb !== 'function') {
|
|
9
|
+
throw new Error('The "afterLogsCb" arg should be a function');
|
|
10
|
+
}
|
|
11
|
+
this._afterLogsCb = once(afterLogsCb);
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
apply(compiler) {
|
|
15
|
+
compiler.hooks.done.tap('AfterWebpackLogsPlugin', stats => {
|
|
16
|
+
const compilerStats = stats;
|
|
17
|
+
stats.compilation.hooks.statsPrinter.tap('AfterWebpackLogsPlugin', stats => {
|
|
18
|
+
// Making logs to be after all webpack logs in the console
|
|
19
|
+
setImmediate(() => this._afterLogsCb(compilerStats));
|
|
20
|
+
});
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
module.exports = AfterWebpackLogsPlugin;
|
package/style/style-loader.js
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
const path = require('path');
|
|
2
2
|
const wildcard = require('wildcard');
|
|
3
3
|
const _ = require('underscore');
|
|
4
|
-
const
|
|
4
|
+
const {isProdMode} = require('../utils');
|
|
5
|
+
const {assetsValidation} = require('../validation');
|
|
6
|
+
const StylesError = require('../validation/errors/styles-error');
|
|
5
7
|
|
|
6
8
|
/**
|
|
7
9
|
* @typedef ThemeGroupConfig
|
|
@@ -30,17 +32,19 @@ class StyleLoader {
|
|
|
30
32
|
getThemeEntryPoints(theme, buildPath) {
|
|
31
33
|
const {themeConfig, settings = {}} = this._fetchThemeConfig(theme);
|
|
32
34
|
|
|
35
|
+
assetsValidation.checkFullSchema(themeConfig, this._configLoader.processedFiles, theme);
|
|
36
|
+
|
|
33
37
|
const entryPoints = {};
|
|
34
38
|
const writingOptions = {};
|
|
35
39
|
for (const [group, config] of Object.entries(themeConfig)) {
|
|
36
40
|
let {inputs, entries = [], output, auto_rtl_inputs: rtlMasks = []} = config;
|
|
37
41
|
|
|
38
|
-
if (output === void 0) {
|
|
39
|
-
throw new
|
|
42
|
+
if (isProdMode() && output === void 0) {
|
|
43
|
+
throw new StylesError('output', group, theme);
|
|
40
44
|
}
|
|
41
45
|
|
|
42
|
-
if (inputs === void 0) {
|
|
43
|
-
throw new
|
|
46
|
+
if (isProdMode() && inputs === void 0) {
|
|
47
|
+
throw new StylesError('inputs', group, theme);
|
|
44
48
|
}
|
|
45
49
|
|
|
46
50
|
inputs = this._overrideInputs(inputs);
|
|
@@ -89,7 +93,7 @@ class StyleLoader {
|
|
|
89
93
|
const oldInputIndex = mappedInputs.findIndex(item => item === oldInput);
|
|
90
94
|
|
|
91
95
|
if (oldInputIndex === -1) {
|
|
92
|
-
// old input does not
|
|
96
|
+
// old input does not exist anymore
|
|
93
97
|
mappedInputs.push(newInput);
|
|
94
98
|
} else if (newInput) {
|
|
95
99
|
// replace input
|
|
@@ -120,11 +124,11 @@ class StyleLoader {
|
|
|
120
124
|
inputs.forEach(input => {
|
|
121
125
|
if (input.indexOf('/settings/primary-settings') > 0) {
|
|
122
126
|
primarySettingsInputs.push(input);
|
|
123
|
-
} else if (input.indexOf('/settings/') > 0)
|
|
127
|
+
} else if (input.indexOf('/settings/') > 0) {
|
|
124
128
|
settingsInputs.push(input);
|
|
125
|
-
} else
|
|
129
|
+
} else if (input.indexOf('/variables/primary-variables') > 0) {
|
|
126
130
|
primaryVariablesInputs.push(input);
|
|
127
|
-
} else if (input.indexOf('/variables/') > 0)
|
|
131
|
+
} else if (input.indexOf('/variables/') > 0) {
|
|
128
132
|
variablesInputs.push(input);
|
|
129
133
|
} else {
|
|
130
134
|
restInputs.push(input);
|
package/theme-config-factory.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
const
|
|
1
|
+
const JSModulesExtraModulesError = require('./validation/errors/jsmodules-extra-modules-error');
|
|
2
2
|
|
|
3
3
|
class ThemeConfigFactory {
|
|
4
4
|
/**
|
|
@@ -19,11 +19,7 @@ class ThemeConfigFactory {
|
|
|
19
19
|
* @return {Object} Merged Configs loaded from all the bundles Yaml files matched by filePath
|
|
20
20
|
*/
|
|
21
21
|
loadConfig(theme, configFilepath) {
|
|
22
|
-
|
|
23
|
-
return this._configLoader.loadConfig(theme, configFilepath)
|
|
24
|
-
} catch (e) {
|
|
25
|
-
throw new Error(messages.jsModulesError(theme));
|
|
26
|
-
}
|
|
22
|
+
return this._configLoader.loadConfig(theme, configFilepath);
|
|
27
23
|
}
|
|
28
24
|
|
|
29
25
|
extendConfig(baseConfig, extraConfig) {
|
|
@@ -31,7 +27,7 @@ class ThemeConfigFactory {
|
|
|
31
27
|
aliases = {},
|
|
32
28
|
configs,
|
|
33
29
|
map = {},
|
|
34
|
-
shim = {}
|
|
30
|
+
shim = {}
|
|
35
31
|
} = baseConfig;
|
|
36
32
|
|
|
37
33
|
const {
|
|
@@ -43,7 +39,7 @@ class ThemeConfigFactory {
|
|
|
43
39
|
|
|
44
40
|
const beyondKeys = Object.keys(rest);
|
|
45
41
|
if (beyondKeys.length) {
|
|
46
|
-
throw new
|
|
42
|
+
throw new JSModulesExtraModulesError(beyondKeys);
|
|
47
43
|
}
|
|
48
44
|
|
|
49
45
|
return {
|
|
@@ -69,7 +65,7 @@ class ThemeConfigFactory {
|
|
|
69
65
|
shim = {},
|
|
70
66
|
configs,
|
|
71
67
|
aliases = {},
|
|
72
|
-
['app-modules']: appModules,
|
|
68
|
+
['app-modules']: appModules = [],
|
|
73
69
|
['dynamic-imports']: dynamicImports
|
|
74
70
|
} = jsModulesConfig;
|
|
75
71
|
|
package/utils.js
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
let prodMode;
|
|
2
|
+
let verboseMode;
|
|
3
|
+
|
|
4
|
+
module.exports = {
|
|
5
|
+
isVerboseMode() {
|
|
6
|
+
if (verboseMode === void 0) {
|
|
7
|
+
verboseMode = process.argv.filter(arg => {
|
|
8
|
+
// Depending on how the command was run (-v, -vv, -vvv, --verbose) -
|
|
9
|
+
// arguments can be present in different formats: stats=normal, stats=detailed, stats=verbose, verbose
|
|
10
|
+
return arg.search(/^verbose|(^stats=(normal|detailed|verbose))/) !== -1;
|
|
11
|
+
}).length > 0;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
return verboseMode;
|
|
15
|
+
},
|
|
16
|
+
isProdMode() {
|
|
17
|
+
if (prodMode !== void 0) {
|
|
18
|
+
return prodMode;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
process.argv.forEach(arg => {
|
|
22
|
+
if (prodMode) {
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
prodMode = ['--mode=production', '--env=prod'].some(item => item === arg);
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
return prodMode;
|
|
29
|
+
}
|
|
30
|
+
};
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
const {isProdMode} = require('../utils');
|
|
2
|
+
const fs = require('fs');
|
|
3
|
+
const path = require('path');
|
|
4
|
+
const schema = require('./schemas/assets-schema');
|
|
5
|
+
const fullSchema = require('./schemas/assets-schema-full');
|
|
6
|
+
const schemaValidator = require('./schema-validator');
|
|
7
|
+
const EventEmitter = require('events');
|
|
8
|
+
const emitter = new EventEmitter();
|
|
9
|
+
const AssetsSchemaError = require('./errors/assets-schema-error');
|
|
10
|
+
const AssetsInputFileError = require('./errors/assets-input-file-error');
|
|
11
|
+
|
|
12
|
+
module.exports = Object.assign({}, schemaValidator, {
|
|
13
|
+
emitter,
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* @param {string} filePath
|
|
17
|
+
* @param {Object} doc
|
|
18
|
+
* @param {string} theme
|
|
19
|
+
* @returns {boolean|undefined}
|
|
20
|
+
*/
|
|
21
|
+
checkSchema(filePath, doc, theme) {
|
|
22
|
+
if (isProdMode()) {
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
const result = this.validateSchema(schema, doc);
|
|
26
|
+
|
|
27
|
+
if (!result.valid) {
|
|
28
|
+
const error = new AssetsSchemaError(result.formattedError, [filePath], theme);
|
|
29
|
+
|
|
30
|
+
this.emitter.emit('error', error);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
return result.valid;
|
|
34
|
+
},
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* @param {Object} doc
|
|
38
|
+
* @param {Array} files
|
|
39
|
+
* @param {string} theme
|
|
40
|
+
* @returns {boolean|undefined}
|
|
41
|
+
*/
|
|
42
|
+
checkFullSchema(doc, files = [], theme) {
|
|
43
|
+
if (isProdMode()) {
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
const result = this.validateSchema(fullSchema, doc);
|
|
47
|
+
|
|
48
|
+
if (!result.valid) {
|
|
49
|
+
const error = new AssetsSchemaError(result.formattedError, files, theme);
|
|
50
|
+
|
|
51
|
+
this.emitter.emit('error', error);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
return result.valid;
|
|
55
|
+
},
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* @param {string} filePath
|
|
59
|
+
* @param {Object} doc
|
|
60
|
+
* @param {string} theme
|
|
61
|
+
* @returns {boolean|undefined}
|
|
62
|
+
*/
|
|
63
|
+
checkInputsExist(filePath, doc, theme) {
|
|
64
|
+
if (isProdMode()) {
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
let valid = true;
|
|
69
|
+
for (const [, props] of Object.entries(doc)) {
|
|
70
|
+
if (!Array.isArray(props.inputs)) {
|
|
71
|
+
continue;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
const files = [];
|
|
75
|
+
props.inputs.forEach(input => {
|
|
76
|
+
if (typeof input === 'object') {
|
|
77
|
+
const newPath = Object.values(input)[0];
|
|
78
|
+
|
|
79
|
+
if (newPath === '~') {
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
82
|
+
input = newPath;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
const fullPath = path.resolve(this._publicPath + input);
|
|
86
|
+
// skip the path to global node modules,
|
|
87
|
+
// e.g. '~bootstrap/scss/bootstrap'
|
|
88
|
+
if (!input.startsWith('~') && !fs.existsSync(fullPath)) {
|
|
89
|
+
files.push(input);
|
|
90
|
+
}
|
|
91
|
+
});
|
|
92
|
+
if (files.length) {
|
|
93
|
+
valid = false;
|
|
94
|
+
files.forEach(notExistFile => {
|
|
95
|
+
const error = new AssetsInputFileError(notExistFile, filePath);
|
|
96
|
+
|
|
97
|
+
this.emitter.emit('error', error);
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
return valid;
|
|
102
|
+
}
|
|
103
|
+
});
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
const BaseError = require('./base-error');
|
|
2
|
+
|
|
3
|
+
class AssetsInputFileError extends BaseError {
|
|
4
|
+
/**
|
|
5
|
+
* @example
|
|
6
|
+
* Invalid styles config: input file does not exist /scss/test.scss
|
|
7
|
+
* at /config/assets.yml
|
|
8
|
+
* Please, find more information in the documentation https://doc.oroinc.com/...
|
|
9
|
+
*
|
|
10
|
+
* @param {string} notExistFile
|
|
11
|
+
* @param {string} path
|
|
12
|
+
*/
|
|
13
|
+
constructor(notExistFile, path) {
|
|
14
|
+
const msg = `input file does not exist: ${notExistFile}\nat ${path}:1`;
|
|
15
|
+
|
|
16
|
+
super(msg);
|
|
17
|
+
|
|
18
|
+
this.name = 'Invalid styles config';
|
|
19
|
+
this.docLink =
|
|
20
|
+
'https://doc.oroinc.com/backend/bundles/platform/AssetBundle/#load-scss-or-css-files-from-the-bundle';
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
module.exports = AssetsInputFileError;
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
const BaseError = require('./base-error');
|
|
2
|
+
|
|
3
|
+
class AssetsSchemaError extends BaseError {
|
|
4
|
+
/**
|
|
5
|
+
* @example
|
|
6
|
+
* Invalid styles config: the "assets.yml" in the "default" theme file does not match the API schema.
|
|
7
|
+
* styles.inputs[0] should be: string | object
|
|
8
|
+
* at /config/assets.yml
|
|
9
|
+
* Please, find more information in the documentation https://doc.oroinc.com/...
|
|
10
|
+
*
|
|
11
|
+
* @example
|
|
12
|
+
* Invalid styles config: the "assets.yml" file the "default" theme does not match the API schema.
|
|
13
|
+
* styles misses the property 'output'.
|
|
14
|
+
* List of processed files for the "default" theme:
|
|
15
|
+
* /default/config/assets.yml
|
|
16
|
+
* /default/config/assets.yml
|
|
17
|
+
* Please, find more information in the documentation https://doc.oroinc.com/...
|
|
18
|
+
*
|
|
19
|
+
* @param {string} reason
|
|
20
|
+
* @param {Array} files
|
|
21
|
+
* @param {string} theme
|
|
22
|
+
*/
|
|
23
|
+
constructor(reason, files, theme) {
|
|
24
|
+
let msg = `the "assets.yml" file in the "${theme}" theme does not match the API schema.\n${reason}`;
|
|
25
|
+
|
|
26
|
+
const filesListMsg = BaseError.generateFilesListMsg(files, theme);
|
|
27
|
+
|
|
28
|
+
if (filesListMsg.length) {
|
|
29
|
+
msg = `${msg}\n${filesListMsg}`;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
super(msg);
|
|
33
|
+
|
|
34
|
+
this.name = 'Invalid styles config';
|
|
35
|
+
this.docLink =
|
|
36
|
+
'https://doc.oroinc.com/backend/bundles/platform/AssetBundle/#load-scss-or-css-files-from-the-bundle';
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
module.exports = AssetsSchemaError;
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
const {isVerboseMode} = require('../../utils');
|
|
2
|
+
|
|
3
|
+
class BaseError extends Error {
|
|
4
|
+
/**
|
|
5
|
+
* Prepares documentation phrase
|
|
6
|
+
* @returns {string}
|
|
7
|
+
*/
|
|
8
|
+
get extra() {
|
|
9
|
+
return this.docLink ? `Please, find more information in the documentation ${this.docLink}` : '';
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Creates an instance of BaseError
|
|
14
|
+
* @param {string} message error message
|
|
15
|
+
*/
|
|
16
|
+
constructor(message) {
|
|
17
|
+
super(message);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Creates a part of message about processed files
|
|
22
|
+
* @param {Array} files
|
|
23
|
+
* @param {string} theme
|
|
24
|
+
* @returns {string}
|
|
25
|
+
*/
|
|
26
|
+
static generateFilesListMsg(files, theme) {
|
|
27
|
+
if (files.length === 1) {
|
|
28
|
+
return `at ${files[0]}:1`;
|
|
29
|
+
} else if (isVerboseMode()) {
|
|
30
|
+
return `List of processed files for the "${theme}" theme:\n ${files.join('\n ')}`;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
return '';
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
module.exports = BaseError;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
const BaseError = require('./base-error');
|
|
2
|
+
|
|
3
|
+
class JsmodulesExtraModulesError extends BaseError {
|
|
4
|
+
/**
|
|
5
|
+
* @example
|
|
6
|
+
* Failed assembly JS: sections ["shim"] are not allowed in extra js build definition.
|
|
7
|
+
* Please, find more information in the documentation https://doc.oroinc.com/...
|
|
8
|
+
*
|
|
9
|
+
* @param {Array} parts
|
|
10
|
+
*/
|
|
11
|
+
constructor(parts) {
|
|
12
|
+
const msg = `sections ["${parts.join('", "')}"] are not allowed in extra js build definition.`;
|
|
13
|
+
|
|
14
|
+
super(msg);
|
|
15
|
+
|
|
16
|
+
this.name = 'Failed assembly JS';
|
|
17
|
+
this.docLink =
|
|
18
|
+
'https://doc.oroinc.com/master/frontend/storefront/how-to/how-to-create-extra-js-build-for-landing-page';
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
module.exports = JsmodulesExtraModulesError;
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
const BaseError = require('./base-error');
|
|
2
|
+
|
|
3
|
+
class JSModulesSchemaError extends BaseError {
|
|
4
|
+
/**
|
|
5
|
+
* @example
|
|
6
|
+
* Invalid JS config: the "jsmodules.yml" files in the "default" theme do not match the API schema.
|
|
7
|
+
* has an unknown property 'rest'.
|
|
8
|
+
* at default/config/jsmodules.yml
|
|
9
|
+
* Please, find more information in the documentation https://doc.oroinc.com/...
|
|
10
|
+
*
|
|
11
|
+
* @example
|
|
12
|
+
* Invalid JS config: the "jsmodules.yml" files in the "default" theme do not match the API schema.
|
|
13
|
+
* misses the property 'entry'.
|
|
14
|
+
* List of processed files for the "default" theme:
|
|
15
|
+
* /default/config/jsmodules.yml
|
|
16
|
+
* /default/config/jsmodules.yml
|
|
17
|
+
* Please, find more information in the documentation https://doc.oroinc.com/...
|
|
18
|
+
*
|
|
19
|
+
* @param {string} reason
|
|
20
|
+
* @param {Array} files
|
|
21
|
+
* @param {string} theme
|
|
22
|
+
*/
|
|
23
|
+
constructor(reason, files, theme) {
|
|
24
|
+
let msg = `the "jsmodules.yml" files in the "${theme}" theme do not match the API schema.\n${reason}`;
|
|
25
|
+
|
|
26
|
+
const filesListMsg = BaseError.generateFilesListMsg(files, theme);
|
|
27
|
+
|
|
28
|
+
if (filesListMsg.length) {
|
|
29
|
+
msg = `${msg}\n${filesListMsg}`;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
super(msg);
|
|
33
|
+
|
|
34
|
+
this.name = 'Invalid JS config';
|
|
35
|
+
this.docLink =
|
|
36
|
+
'https://doc.oroinc.com/backend/bundles/platform/AssetBundle/#create-jsmodules-yml-configuration';
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
module.exports = JSModulesSchemaError;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
const BaseError = require('./base-error');
|
|
2
|
+
|
|
3
|
+
class StylesError extends BaseError {
|
|
4
|
+
/**
|
|
5
|
+
* @example
|
|
6
|
+
* Failed assembly styles: the "output" for "styles" entry point in "default" theme is not defined.
|
|
7
|
+
* Please, find more information in the documentation https://doc.oroinc.com/...
|
|
8
|
+
*
|
|
9
|
+
* @param {string} key
|
|
10
|
+
* @param {string} group
|
|
11
|
+
* @param {string} theme
|
|
12
|
+
*/
|
|
13
|
+
constructor(key, group, theme) {
|
|
14
|
+
const msg = `the "${key}" for "${group}" entry point in "${theme}" theme is not defined.`;
|
|
15
|
+
|
|
16
|
+
super(msg);
|
|
17
|
+
|
|
18
|
+
this.name = 'Failed assembly styles';
|
|
19
|
+
this.docLink =
|
|
20
|
+
'https://doc.oroinc.com/backend/bundles/platform/AssetBundle/#load-scss-or-css-files-from-the-bundle';
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
module.exports = StylesError;
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
const assetsValidation = require('./assets-validator');
|
|
2
|
+
const jsmodulesValidator = require('./jsmodules-validator');
|
|
3
|
+
|
|
4
|
+
const isJSModulesPath = path => /jsmodules([-a-zA-Z\d]*)\.yml$/.test(path);
|
|
5
|
+
const isAssetsPath = path => /assets\.yml$/.test(path);
|
|
6
|
+
|
|
7
|
+
module.exports = {
|
|
8
|
+
assetsValidation,
|
|
9
|
+
jsmodulesValidator,
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* set public path for all validators
|
|
13
|
+
* {string} path
|
|
14
|
+
*/
|
|
15
|
+
setPublicPath(path) {
|
|
16
|
+
[assetsValidation, jsmodulesValidator].forEach(validator => validator.setPublicPath(path));
|
|
17
|
+
},
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Run appropriate validator
|
|
21
|
+
* {string} filePath
|
|
22
|
+
* {Object} doc
|
|
23
|
+
* {string} theme
|
|
24
|
+
*/
|
|
25
|
+
checkSchema(filePath, doc, theme) {
|
|
26
|
+
if (isJSModulesPath(filePath)) {
|
|
27
|
+
jsmodulesValidator.checkSchema(filePath, doc, theme);
|
|
28
|
+
} else if (isAssetsPath(filePath)) {
|
|
29
|
+
const validSchema = assetsValidation.checkSchema(filePath, doc, theme);
|
|
30
|
+
|
|
31
|
+
if (validSchema) {
|
|
32
|
+
assetsValidation.checkInputsExist(filePath, doc, theme);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
};
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
const schema = require('./schemas/jsmodules-schema');
|
|
2
|
+
const fullSchema = require('./schemas/jsmodules-schema-full');
|
|
3
|
+
const schemaValidator = require('./schema-validator');
|
|
4
|
+
const {isProdMode} = require('../utils');
|
|
5
|
+
const EventEmitter = require('events');
|
|
6
|
+
const emitter = new EventEmitter();
|
|
7
|
+
const JSModulesSchemaError = require('./errors/jsmodules-schema-error');
|
|
8
|
+
|
|
9
|
+
module.exports = Object.assign({}, schemaValidator, {
|
|
10
|
+
emitter,
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* @param {string} filePath
|
|
14
|
+
* @param {Object} doc
|
|
15
|
+
* @param {string} theme
|
|
16
|
+
* @returns {boolean|undefined}
|
|
17
|
+
*/
|
|
18
|
+
checkSchema(filePath, doc, theme) {
|
|
19
|
+
if (isProdMode()) {
|
|
20
|
+
return;
|
|
21
|
+
}
|
|
22
|
+
const result = this.validateSchema(schema, doc);
|
|
23
|
+
|
|
24
|
+
if (!result.valid) {
|
|
25
|
+
const error = new JSModulesSchemaError(result.formattedError, [filePath], theme);
|
|
26
|
+
|
|
27
|
+
this.emitter.emit('error', error);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
return result.valid;
|
|
31
|
+
},
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* @param {Object} doc
|
|
35
|
+
* @param {Array} files
|
|
36
|
+
* @param {string} theme
|
|
37
|
+
* @returns {boolean|undefined}
|
|
38
|
+
*/
|
|
39
|
+
checkFullSchema(doc, files = [], theme) {
|
|
40
|
+
if (isProdMode()) {
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
const result = this.validateSchema(fullSchema, doc);
|
|
44
|
+
|
|
45
|
+
if (!result.valid) {
|
|
46
|
+
const error = new JSModulesSchemaError(result.formattedError, files, theme);
|
|
47
|
+
|
|
48
|
+
this.emitter.emit('error', error);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
return result.valid;
|
|
52
|
+
}
|
|
53
|
+
});
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
const {validate} = require('schema-utils');
|
|
2
|
+
|
|
3
|
+
module.exports = {
|
|
4
|
+
/**
|
|
5
|
+
* Symfony public directory path related to application root folder
|
|
6
|
+
* {string}
|
|
7
|
+
*/
|
|
8
|
+
_publicPath: 'public/',
|
|
9
|
+
|
|
10
|
+
setPublicPath(path) {
|
|
11
|
+
this._publicPath = path;
|
|
12
|
+
},
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Validates data according to the schema
|
|
16
|
+
* @param {Object} scheme
|
|
17
|
+
* @param {Object} data
|
|
18
|
+
* @param {Object} [options]
|
|
19
|
+
* @returns {Object}
|
|
20
|
+
*/
|
|
21
|
+
validateSchema(scheme, data, options) {
|
|
22
|
+
const result = {
|
|
23
|
+
valid: true
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
try {
|
|
27
|
+
const baseDataPath = 'configuration';
|
|
28
|
+
const basePathReg = /^configuration\./;
|
|
29
|
+
validate(scheme, data, {
|
|
30
|
+
baseDataPath,
|
|
31
|
+
...options || {},
|
|
32
|
+
postFormatter(formattedError, error) {
|
|
33
|
+
if (result.formattedError === void 0) {
|
|
34
|
+
result.formattedError = [];
|
|
35
|
+
}
|
|
36
|
+
result.error = error;
|
|
37
|
+
|
|
38
|
+
if (
|
|
39
|
+
Array.isArray(error.params.type) ||
|
|
40
|
+
error.params.missingProperty
|
|
41
|
+
) {
|
|
42
|
+
// remove an excess line break
|
|
43
|
+
formattedError = formattedError.replace(/\n/g, ' ');
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
formattedError = formattedError.replace(basePathReg, '');
|
|
47
|
+
result.formattedError.push(formattedError.trim());
|
|
48
|
+
return formattedError;
|
|
49
|
+
}
|
|
50
|
+
});
|
|
51
|
+
} catch (e) {
|
|
52
|
+
result.valid = false;
|
|
53
|
+
result.errorMessage = e.message;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
if (result.formattedError) {
|
|
57
|
+
result.formattedError = result.formattedError.join('\n');
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
return result;
|
|
61
|
+
}
|
|
62
|
+
};
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Schema to validate assets.yml files
|
|
3
|
+
*
|
|
4
|
+
* @description
|
|
5
|
+
* Full scheme complements "assets-schema" one.
|
|
6
|
+
* It should have only rules which are not defined in "assets-schema" schema due to avoid duplicates in error messages
|
|
7
|
+
*/
|
|
8
|
+
module.exports = {
|
|
9
|
+
type: 'object',
|
|
10
|
+
patternProperties: {
|
|
11
|
+
'.*': {
|
|
12
|
+
type: 'object',
|
|
13
|
+
properties: {
|
|
14
|
+
inputs: {
|
|
15
|
+
description: 'The "inputs" property is an array of files to load.',
|
|
16
|
+
minItems: 1
|
|
17
|
+
}
|
|
18
|
+
},
|
|
19
|
+
required: ['inputs', 'output']
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
};
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Schema to validate assets.yml files
|
|
3
|
+
*/
|
|
4
|
+
module.exports = {
|
|
5
|
+
type: 'object',
|
|
6
|
+
patternProperties: {
|
|
7
|
+
'.*': {
|
|
8
|
+
type: 'object',
|
|
9
|
+
properties: {
|
|
10
|
+
inputs: {
|
|
11
|
+
description: 'The "inputs" property is an array of files to load.',
|
|
12
|
+
type: 'array',
|
|
13
|
+
items: {
|
|
14
|
+
type: ['string', 'object']
|
|
15
|
+
}
|
|
16
|
+
},
|
|
17
|
+
output: {
|
|
18
|
+
description: 'Output file path inside "public/" directory for the entry point',
|
|
19
|
+
type: 'string'
|
|
20
|
+
},
|
|
21
|
+
auto_rtl_inputs: {
|
|
22
|
+
description: 'List of wildcard file masks for inputs that has to be processed with RTL plugin.',
|
|
23
|
+
type: 'array',
|
|
24
|
+
items: {
|
|
25
|
+
type: 'string'
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
},
|
|
29
|
+
additionalProperties: false
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Schema to validate jsmodules.yml files
|
|
3
|
+
*
|
|
4
|
+
* @description
|
|
5
|
+
* Full scheme complements "jsmodules-schema" one.
|
|
6
|
+
* It should have only rules which are not defined in "jsmodules-schema" schema due to avoid duplicates in error messages
|
|
7
|
+
*/
|
|
8
|
+
module.exports = {
|
|
9
|
+
type: 'object',
|
|
10
|
+
required: ['entry']
|
|
11
|
+
};
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Schema to validate jsmodules.yml files
|
|
3
|
+
*/
|
|
4
|
+
module.exports = {
|
|
5
|
+
type: 'object',
|
|
6
|
+
properties: {
|
|
7
|
+
'entry': {
|
|
8
|
+
description: 'Webpack entry points configuration.',
|
|
9
|
+
type: 'object',
|
|
10
|
+
patternProperties: {
|
|
11
|
+
'.*': {
|
|
12
|
+
type: 'array',
|
|
13
|
+
items: {
|
|
14
|
+
type: 'string'
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
},
|
|
19
|
+
'shim': {
|
|
20
|
+
description: 'Configure a webpack shimming feature',
|
|
21
|
+
type: 'object',
|
|
22
|
+
patternProperties: {
|
|
23
|
+
'.*': {
|
|
24
|
+
type: 'object'
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
},
|
|
28
|
+
'map': {
|
|
29
|
+
description: 'The map option allows to substitute a module with the given ID with a different module.',
|
|
30
|
+
type: 'object',
|
|
31
|
+
patternProperties: {
|
|
32
|
+
'.*': {
|
|
33
|
+
type: 'object'
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
},
|
|
37
|
+
'app-modules': {
|
|
38
|
+
description: 'Introduces a list of modules that should be initialized before application is launched.',
|
|
39
|
+
type: 'array',
|
|
40
|
+
items: {
|
|
41
|
+
type: 'string'
|
|
42
|
+
}
|
|
43
|
+
},
|
|
44
|
+
'dynamic-imports': {
|
|
45
|
+
description: 'Gives possibility to import a module with the name that is determined at runtime.',
|
|
46
|
+
type: 'object',
|
|
47
|
+
patternProperties: {
|
|
48
|
+
'.*': {
|
|
49
|
+
type: 'array',
|
|
50
|
+
items: {
|
|
51
|
+
type: 'string'
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
},
|
|
56
|
+
'configs': {
|
|
57
|
+
description: 'Runtime configuration for a the module.',
|
|
58
|
+
type: 'object',
|
|
59
|
+
patternProperties: {
|
|
60
|
+
'.*': {
|
|
61
|
+
type: 'object'
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
},
|
|
65
|
+
'aliases': {
|
|
66
|
+
description: 'An alias is an alternative name.',
|
|
67
|
+
type: 'object',
|
|
68
|
+
patternProperties: {
|
|
69
|
+
'.*': {
|
|
70
|
+
type: 'string'
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
},
|
|
75
|
+
additionalProperties: false
|
|
76
|
+
};
|
|
@@ -19,8 +19,8 @@ class DynamicImportsFileWriter {
|
|
|
19
19
|
write(dynamicImports, output) {
|
|
20
20
|
const buildPath = path.join(output, 'dynamic-imports.js');
|
|
21
21
|
let content = Object.entries(dynamicImports).map(([chunkName, moduleNames]) => {
|
|
22
|
-
const notation = chunkName === 'commons'
|
|
23
|
-
'/* webpackMode: "eager" */' : `/* webpackChunkName: "${chunkName}" */`;
|
|
22
|
+
const notation = chunkName === 'commons'
|
|
23
|
+
? '/* webpackMode: "eager" */' : `/* webpackChunkName: "${chunkName}" */`;
|
|
24
24
|
return moduleNames.map(moduleName =>`'${moduleName}': () => import(${notation}'${moduleName}')`);
|
|
25
25
|
});
|
|
26
26
|
content = `module.exports = {\n ${content.flat().join(',\n ')}\n};\n`;
|
|
@@ -25,7 +25,7 @@ class SCSSEntryPointFileWriter {
|
|
|
25
25
|
input = input.replace(/\.[^/.]+$/, '');
|
|
26
26
|
// don't add the base path to global node modules,
|
|
27
27
|
// e.g. '~bootstrap/scss/bootstrap'
|
|
28
|
-
const basePath = input.startsWith('~') ? '': baseInputPath;
|
|
28
|
+
const basePath = input.startsWith('~') ? '' : baseInputPath;
|
|
29
29
|
let importModule = `@import "${basePath}${input}";\n`;
|
|
30
30
|
if (ignoreRTL) {
|
|
31
31
|
importModule = `/*rtl:begin:ignore*/\n${importModule}/*rtl:end:ignore*/\n`;
|
package/messages.js
DELETED
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
const doc = "Please, find more information in the documentation ";
|
|
2
|
-
const CSSError = "Failed assembly styles.\n";
|
|
3
|
-
const CSSDoc = "https://doc.oroinc.com/backend/bundles/platform/AssetBundle/#load-scss-or-css-files-from-the-bundle";
|
|
4
|
-
const JSError = `Failed assembly JS.\n`;
|
|
5
|
-
const JSDoc = "https://doc.oroinc.com/backend/bundles/platform/AssetBundle/#create-jsmodules-yml-configuration";
|
|
6
|
-
const JSExtraBuildDoc = "https://doc.oroinc.com/master/frontend/storefront/how-to/how-to-create-extra-js-build-for-landing-page";
|
|
7
|
-
|
|
8
|
-
module.exports = {
|
|
9
|
-
assetsMissedOutput(group, theme) {
|
|
10
|
-
const error = `The "output" for "${group}" entry point in "${theme}" theme is not defined.\n`;
|
|
11
|
-
|
|
12
|
-
return `${CSSError}${error}${doc}${CSSDoc}`;
|
|
13
|
-
},
|
|
14
|
-
assetsMissedInput(group, theme) {
|
|
15
|
-
const error = `The "output" for "${group}" entry point in "${theme}" theme is not defined.\n`;
|
|
16
|
-
|
|
17
|
-
return `${CSSError}${error}${doc}${CSSDoc}`
|
|
18
|
-
},
|
|
19
|
-
jsModulesError(theme) {
|
|
20
|
-
const error = `Failed assembly JS for the "${theme}" theme.\n`;
|
|
21
|
-
|
|
22
|
-
return `${error}${doc}${JSDoc}`
|
|
23
|
-
},
|
|
24
|
-
jsExtraModulesError(parts) {
|
|
25
|
-
const error = `Sections ["${parts.join('", "')}"] are not allowed in extra js build definition\n`;
|
|
26
|
-
|
|
27
|
-
return `${JSError}${error}${doc}${JSExtraBuildDoc}`;
|
|
28
|
-
}
|
|
29
|
-
};
|