@oroinc/oro-webpack-config-builder 5.1.0-alpha8 → 5.1.0-lts001

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 (36) hide show
  1. package/README.md +1 -1
  2. package/error-handler.js +95 -0
  3. package/loader/config-loader.js +1 -2
  4. package/loader/inject-loader/LICENSE.md +21 -0
  5. package/loader/inject-loader/README.md +54 -0
  6. package/loader/inject-loader/index.js +10 -0
  7. package/loader/inject-loader/injectify.js +66 -0
  8. package/loader/inject-loader/package.json +55 -0
  9. package/loader/inject-loader/wrapper_template.js +32 -0
  10. package/modules-config/layout-modules-config-loader.js +66 -2
  11. package/modules-config/modules-config-loader.js +52 -19
  12. package/oro-webpack-config.js +416 -301
  13. package/package.json +37 -37
  14. package/plugin/logs/after-webpack-logs-plugin.js +25 -0
  15. package/style/admin-style-loader.js +23 -0
  16. package/style/layout-style-loader.js +12 -109
  17. package/style/style-loader.js +156 -46
  18. package/theme-config-factory.js +45 -6
  19. package/utils.js +30 -0
  20. package/validation/assets-validator.js +104 -0
  21. package/validation/errors/assets-input-file-error.js +24 -0
  22. package/validation/errors/assets-schema-error.js +40 -0
  23. package/validation/errors/base-error.js +37 -0
  24. package/validation/errors/jsmodules-extra-modules-error.js +22 -0
  25. package/validation/errors/jsmodules-schema-error.js +40 -0
  26. package/validation/errors/styles-error.js +24 -0
  27. package/validation/index.js +36 -0
  28. package/validation/jsmodules-validator.js +53 -0
  29. package/validation/schema-validator.js +62 -0
  30. package/validation/schemas/assets-schema-full.js +22 -0
  31. package/validation/schemas/assets-schema.js +32 -0
  32. package/validation/schemas/jsmodules-schema-full.js +11 -0
  33. package/validation/schemas/jsmodules-schema.js +76 -0
  34. package/writer/configs-file-writer.js +1 -1
  35. package/writer/dynamic-imports-file-writer.js +3 -3
  36. package/writer/scss-entry-point-file-writer.js +1 -1
package/package.json CHANGED
@@ -1,48 +1,48 @@
1
1
  {
2
2
  "name": "@oroinc/oro-webpack-config-builder",
3
- "version": "5.1.0-alpha8",
3
+ "version": "5.1.0-lts001",
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.4",
10
- "@babel/plugin-transform-runtime": "^7.10.4",
11
- "@babel/preset-env": "^7.10.4",
12
- "autoprefixer": "^9.8.6",
13
- "babel-loader": "^8.1.0",
14
- "bindings": "^1.5.0",
15
- "css-loader": "^5.0.2",
16
- "css-minimizer-webpack-plugin": "^1.2.0",
17
- "deepmerge": "^4.2.2",
18
- "exports-loader": "^2.0.0",
19
- "expose-loader": "^2.0.0",
20
- "extract-loader": "^5.1.0",
21
- "file-loader": "^6.2.0",
22
- "happypack": "^5.0.1",
23
- "html-webpack-plugin": "^5.2.0",
24
- "imports-loader": "^2.0.0",
25
- "js-yaml": "^4.0.0",
26
- "mini-css-extract-plugin": "^1.3.8",
27
- "minimist": "^1.2.3",
28
- "nan": "^2.14.2",
9
+ "@babel/core": "~7.21.3",
10
+ "@babel/plugin-transform-runtime": "~7.21.0",
11
+ "@babel/preset-env": "~7.20.2",
12
+ "autoprefixer": "~10.4.13",
13
+ "babel-loader": "~9.1.0",
14
+ "bindings": "~1.5.0",
15
+ "css-loader": "^6.7.3",
16
+ "css-minimizer-webpack-plugin": "~4.2.2",
17
+ "deepmerge": "~4.3.1",
18
+ "exports-loader": "~4.0.0",
19
+ "expose-loader": "~4.1.0",
20
+ "file-loader": "~6.2.0",
21
+ "html-webpack-plugin": "~5.5.0",
22
+ "imports-loader": "~4.0.1",
23
+ "js-yaml": "~4.1.0",
24
+ "mini-css-extract-plugin": "~2.7.1",
25
+ "minimist": "~1.2.7",
26
+ "nan": "~2.17.0",
29
27
  "path": "0.12.7",
30
- "postcss": "^8.2.9",
31
- "postcss-loader": "^5.0.0",
32
- "printf": "^0.6.0",
33
- "rtlcss-webpack-plugin": "^4.0.6",
34
- "sass": "^1.32.8",
35
- "sass-loader": "^11.0.1",
36
- "style-loader": "^2.0.0",
37
- "terser": "^5.6.0",
28
+ "postcss": "~8.4.19",
29
+ "postcss-loader": "~7.1.0",
30
+ "printf": "~0.6.0",
31
+ "resolve-url-loader": "^5.0.0",
32
+ "rtlcss-webpack-plugin": "~4.0.6",
33
+ "sass": "~1.59.3",
34
+ "sass-loader": "~13.2.0",
35
+ "schema-utils": "^4.0.0",
36
+ "style-loader": "~3.3.1",
37
+ "terser": "~5.16.1",
38
38
  "text-loader": "0.0.1",
39
- "underscore": "^1.10.2",
40
- "url-loader": "^4.1.1",
41
- "webpack": "^5.23.0",
42
- "webpack-bundle-analyzer": "^4.4.0",
43
- "webpack-cli": "^4.5.0",
44
- "webpack-dev-server": "^3.11.0",
45
- "webpack-merge": "^5.7.3",
46
- "wildcard": "^2.0.0"
39
+ "underscore": "1.13.*",
40
+ "url-loader": "~4.1.1",
41
+ "webpack": "~5.76.3",
42
+ "webpack-bundle-analyzer": "~4.8.0",
43
+ "webpack-cli": "~5.0.0",
44
+ "webpack-dev-server": "^4.11.1",
45
+ "webpack-merge": "~5.8.0",
46
+ "wildcard": "~2.0.0"
47
47
  }
48
48
  }
@@ -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;
@@ -0,0 +1,23 @@
1
+ const merge = require('deepmerge');
2
+ const StyleLoader = require('./style-loader');
3
+
4
+ class AdminStyleLoader extends StyleLoader {
5
+ /**
6
+ * @inheritdoc
7
+ */
8
+ _fetchThemeConfig(themeName) {
9
+ const {rtl_support: rtlSupport = false, styles: extraThemeConfig} =
10
+ this._configLoader.loadConfig(themeName, 'Resources/public/themes/' + themeName + '/settings.yml');
11
+ const baseThemeConfig = this._configLoader.loadConfig(themeName, 'Resources/config/oro/assets.yml');
12
+ const appRootExtraConfig = this._configLoader.loadConfig(themeName, 'config/oro/assets.yml');
13
+ /** @type {Object.<string, ThemeGroupConfig>} */
14
+ const themeConfig = merge(baseThemeConfig, appRootExtraConfig, extraThemeConfig);
15
+
16
+ return {
17
+ themeConfig,
18
+ settings: {rtlSupport}
19
+ };
20
+ }
21
+ }
22
+
23
+ module.exports = AdminStyleLoader;
@@ -1,115 +1,18 @@
1
- const path = require('path');
2
- const wildcard = require('wildcard');
3
- const _ = require('underscore')
1
+ const StyleLoader = require('./style-loader');
4
2
 
5
- class LayoutStyleLoader {
3
+ class LayoutStyleLoader extends StyleLoader {
6
4
  /**
7
- * @param {YamlConfigLoader} configLoader
8
- * @param {SCSSEntryPointFileWriter} entryPointFileWriter
5
+ * @inheritdoc
9
6
  */
10
- constructor(configLoader, entryPointFileWriter) {
11
- this._configLoader = configLoader;
12
- this._entryPointFileWriter = entryPointFileWriter;
13
- }
14
-
15
- /**
16
- * @param {string} theme Theme name
17
- * @param {string} buildPath Build path
18
- * @return {Object} List of Webpack entry-points
19
- */
20
- getThemeEntryPoints(theme, buildPath) {
21
- const entryPoints = {};
22
- const {rtl_support: rtlSupport = false} = this._configLoader.themes[theme];
23
- const themeConfig = this._configLoader.loadConfig(theme, 'config/assets.yml');
24
- const writingOptions = {};
25
-
26
- for (const [key, config] of Object.entries(themeConfig)) {
27
- let {inputs, output, auto_rtl_inputs: rtlMasks = []} = config;
28
- if (config.output === undefined) {
29
- throw new Error('"output" for "' + key + '" group in theme "' + theme + '" is not defined');
30
- }
31
- inputs = this._overrideInputs(inputs);
32
- inputs = this._sortInputs(inputs);
33
- if (rtlSupport) {
34
- writingOptions.ignoreRTLInputs = _.difference(inputs, this._matchInputs(rtlMasks, inputs));
35
- }
36
-
37
- const entryPointName = output.replace(/\.[^/.]+$/, '');
38
- const filePath = path.join(buildPath, output);
39
- entryPoints[entryPointName] =
40
- this._entryPointFileWriter.write('./../../../', inputs, filePath, writingOptions);
41
- }
42
- return entryPoints;
43
- }
44
-
45
- /**
46
- * @param {Object} inputs
47
- * @returns {string[]} List of inputs
48
- * @private
49
- */
50
- _overrideInputs(inputs) {
51
- const newInputs = [];
52
-
53
- inputs.forEach((input, index) => {
54
- if (typeof input !== 'string') {
55
- const oldInput = Object.keys(input)[0];
56
- const newInput = input[oldInput];
57
- const oldInputIndex = newInputs.findIndex(element => element === oldInput);
58
-
59
- if (newInput) { // replace input
60
- newInputs[oldInputIndex] = newInput;
61
- } else { // delete input
62
- newInputs.splice(oldInputIndex, 1);
63
- }
64
- newInputs.splice(index);
65
- } else {
66
- newInputs[index] = input;
67
- }
68
- });
69
-
70
- return newInputs;
71
- }
72
-
73
- /**
74
- * Sort inputs, so first will be settings, then variables, then other files
75
- * @param {Object} inputs
76
- * @returns {string[]} List of ordered inputs
77
- * @private
78
- */
79
- _sortInputs(inputs) {
80
- const settingsInputs = [];
81
- const variablesInputs = [];
82
- const restInputs = [];
83
-
84
- inputs.forEach(input => {
85
- if (input.indexOf('/settings/') > 0) {
86
- settingsInputs.push(input);
87
- } else if (input.indexOf('/variables/') > 0) {
88
- variablesInputs.push(input);
89
- } else {
90
- restInputs.push(input);
91
- }
92
- });
93
- return [...settingsInputs, ...variablesInputs, ...restInputs];
94
- }
95
-
96
- /**
97
- * Filter inputs that matches any mask from the list
98
- *
99
- * @param {[string]} masks list of wildcard masks
100
- * @param {[string]} inputs
101
- * @return {[string]} matched inputs
102
- * @private
103
- */
104
- _matchInputs(masks, inputs) {
105
- masks = masks.map(mask => wildcard(mask));
106
-
107
- const whiteListedInputs = masks.reduce((include, mask) => {
108
- include.push(...mask.match(inputs));
109
- return include;
110
- }, []);
111
-
112
- return _.unique(whiteListedInputs);
7
+ _fetchThemeConfig(themeName) {
8
+ const {rtl_support: rtlSupport = false} = this._configLoader.themes[themeName];
9
+ /** @type {Object.<string, ThemeGroupConfig>} */
10
+ const themeConfig = this._configLoader.loadConfig(themeName, 'config/assets.yml');
11
+
12
+ return {
13
+ themeConfig,
14
+ settings: {rtlSupport}
15
+ };
113
16
  }
114
17
  }
115
18
 
@@ -1,78 +1,188 @@
1
- const merge = require('deepmerge');
1
+ const path = require('path');
2
+ const wildcard = require('wildcard');
3
+ const _ = require('underscore');
4
+ const {isProdMode} = require('../utils');
5
+ const {assetsValidation} = require('../validation');
6
+ const StylesError = require('../validation/errors/styles-error');
7
+
8
+ /**
9
+ * @typedef ThemeGroupConfig
10
+ * @type {Object}
11
+ * @property {Array.<string|Object>} inputs - list of input resources for import into root SCSS file
12
+ * @property {Array.<string>} entries - list of direct entry resources
13
+ * @property {string} output - name or out put resource
14
+ * @property {[boolean]} auto_rtl_inputs - whether theme support RTL
15
+ */
2
16
 
3
17
  class StyleLoader {
4
18
  /**
5
19
  * @param {YamlConfigLoader} configLoader
20
+ * @param {SCSSEntryPointFileWriter} entryPointFileWriter
6
21
  */
7
- constructor(configLoader) {
22
+ constructor(configLoader, entryPointFileWriter) {
8
23
  this._configLoader = configLoader;
24
+ this._entryPointFileWriter = entryPointFileWriter;
9
25
  }
10
26
 
11
27
  /**
12
28
  * @param {string} theme Theme name
29
+ * @param {string} buildPath Build path
13
30
  * @return {Object} List of Webpack entry-points
14
31
  */
15
- getThemeEntryPoints(theme) {
32
+ getThemeEntryPoints(theme, buildPath) {
33
+ const {themeConfig, settings = {}} = this._fetchThemeConfig(theme);
34
+
35
+ assetsValidation.checkFullSchema(themeConfig, this._configLoader.processedFiles, theme);
36
+
16
37
  const entryPoints = {};
17
- const commonConfig = this._configLoader.loadConfig(theme, 'Resources/config/oro/assets.yml');
18
- let themeConfig = this._configLoader.loadConfig(theme, 'Resources/public/themes/' + theme + '/settings.yml');
19
-
20
- themeConfig = themeConfig.styles;
21
- for (const key in themeConfig) {
22
- if (themeConfig.hasOwnProperty(key)) {
23
- const config = themeConfig[key];
24
- if (commonConfig[key]) {
25
- commonConfig[key] = merge(commonConfig[key], config);
26
- }
38
+ const writingOptions = {};
39
+ for (const [group, config] of Object.entries(themeConfig)) {
40
+ let {inputs, entries = [], output, auto_rtl_inputs: rtlMasks = []} = config;
41
+
42
+ if (isProdMode() && output === void 0) {
43
+ throw new StylesError('output', group, theme);
27
44
  }
28
- }
29
45
 
30
- for (const key in commonConfig) {
31
- if (commonConfig.hasOwnProperty(key)) {
32
- const config = commonConfig[key];
33
- const inputs = this._overrideInputs(config.inputs);
34
- if (config.output === undefined) {
35
- throw new Error('"output" for "' + key + '" group in theme "' + theme + '" is not defined');
36
- }
37
- entryPoints[config.output.replace(/\.[^/.]+$/, '')] = inputs;
46
+ if (isProdMode() && inputs === void 0) {
47
+ throw new StylesError('inputs', group, theme);
38
48
  }
49
+
50
+ inputs = this._overrideInputs(inputs);
51
+ inputs = this._sortInputs(inputs);
52
+ inputs = this._applyInputsBasePathPrefix(inputs);
53
+
54
+ if (settings.rtlSupport) {
55
+ writingOptions.ignoreRTLInputs = _.difference(inputs, this._matchInputs(rtlMasks, inputs));
56
+ }
57
+
58
+ const entryPointName = output.replace(/\.[^/.]+$/, '');
59
+ const filePath = path.join(buildPath, output);
60
+ entryPoints[entryPointName] = [
61
+ ...entries,
62
+ this._entryPointFileWriter.write('./../../', inputs, filePath, writingOptions)
63
+ ];
39
64
  }
40
65
  return entryPoints;
41
66
  }
42
67
 
43
68
  /**
44
- * @param {Object} inputs
69
+ * Extracts theme configuration with its settings
70
+ *
71
+ * @param {string} themeName
72
+ * @return {{themeConfig: Object.<string, ThemeGroupConfig>, settings: {rtlSupport: boolean}}}
73
+ * @abstract
74
+ * @protected
75
+ */
76
+ _fetchThemeConfig(themeName) {
77
+ throw new Error('Method `_fetchThemeConfig` has to be implemented in extends');
78
+ }
79
+
80
+ /**
81
+ * Override inputs
82
+ *
83
+ * @param {(string|Object)[]} inputs
45
84
  * @returns {string[]} List of inputs
46
- * @private
85
+ * @protected
47
86
  */
48
87
  _overrideInputs(inputs) {
49
- const newInputs = [];
50
-
51
- inputs.forEach((input, index) => {
52
- if (typeof input !== 'string') {
53
- const oldInput = Object.keys(input)[0];
54
- const newInput = input[oldInput];
55
- const oldInputIndex = newInputs.findIndex(element => element === oldInput);
56
-
57
- if (newInput) { // replace input
58
- newInputs[oldInputIndex] = newInput;
59
- } else { // delete input
60
- newInputs.splice(oldInputIndex, 1);
61
- }
62
- newInputs.splice(index);
88
+ const mappedInputs = [];
89
+ inputs.forEach(input => {
90
+ if (typeof input === 'string') {
91
+ mappedInputs.push(input);
63
92
  } else {
64
- // cut off ~ prefix from the path,
65
- // if someone acidentaly used it for the admin theme assets.yml or settings.yml file,
66
- // because the syntax is valid only in the @import statement, that is
67
- // not used for the admin theme yaml files configuration
68
- if (input.startsWith('~')) {
69
- input = input.substr(1);
93
+ const [oldInput, newInput] = Object.entries(input)[0];
94
+ const oldInputIndex = mappedInputs.findIndex(item => item === oldInput);
95
+
96
+ if (oldInputIndex === -1) {
97
+ // old input does not exist anymore
98
+ mappedInputs.push(newInput);
99
+ } else if (newInput) {
100
+ // replace input
101
+ mappedInputs[oldInputIndex] = newInput;
102
+ } else {
103
+ // delete input
104
+ mappedInputs.splice(oldInputIndex, 1);
70
105
  }
71
- newInputs.push(input);
72
106
  }
73
107
  });
108
+ return mappedInputs;
109
+ }
110
+
111
+ /**
112
+ * Sort inputs, so first will be settings, then variables, then other files
113
+ *
114
+ * @param {string[]} inputs
115
+ * @returns {string[]} List of ordered inputs
116
+ * @protected
117
+ */
118
+ _sortInputs(inputs) {
119
+ const primarySettingsInputs = [];
120
+ const settingsInputs = [];
121
+ const primaryVariablesInputs = [];
122
+ const variablesInputs = [];
123
+ const restInputs = [];
124
+
125
+ inputs.forEach(input => {
126
+ if (input.indexOf('/settings/primary-settings') > 0) {
127
+ primarySettingsInputs.push(input);
128
+ } else if (input.indexOf('/settings/') > 0) {
129
+ settingsInputs.push(input);
130
+ } else if (input.indexOf('/variables/primary-variables') > 0) {
131
+ primaryVariablesInputs.push(input);
132
+ } else if (input.indexOf('/variables/') > 0) {
133
+ variablesInputs.push(input);
134
+ } else {
135
+ restInputs.push(input);
136
+ }
137
+ });
138
+
139
+ return [
140
+ ...primarySettingsInputs,
141
+ ...settingsInputs,
142
+ ...primaryVariablesInputs,
143
+ ...variablesInputs,
144
+ ...restInputs
145
+ ];
146
+ }
147
+
148
+ /**
149
+ * Filter inputs that matches any mask from the list
150
+ *
151
+ * @param {string[]} masks list of wildcard masks
152
+ * @param {string[]} inputs
153
+ * @return {string[]} matched inputs
154
+ * @protected
155
+ */
156
+ _matchInputs(masks, inputs) {
157
+ masks = this._applyInputsBasePathPrefix(masks);
158
+ masks = masks.map(mask => wildcard(mask));
159
+
160
+ const whiteListedInputs = masks.reduce((include, mask) => {
161
+ include.push(...mask.match(inputs));
162
+ return include;
163
+ }, []);
164
+
165
+ return _.unique(whiteListedInputs);
166
+ }
167
+
168
+ /**
169
+ * Considering base path as application's root.
170
+ * Bundles based *.scss sources go with '../' prefix.
171
+ *
172
+ * @param {string[]} inputs
173
+ * @private
174
+ */
175
+ _applyInputsBasePathPrefix(inputs) {
176
+ const processedInputs = [];
177
+
178
+ inputs.forEach(input => {
179
+ if (input.indexOf('bundles') === 0) {
180
+ input = '../' + input;
181
+ }
182
+ processedInputs.push(input);
183
+ });
74
184
 
75
- return newInputs;
185
+ return processedInputs;
76
186
  }
77
187
  }
78
188
 
@@ -1,3 +1,5 @@
1
+ const JSModulesExtraModulesError = require('./validation/errors/jsmodules-extra-modules-error');
2
+
1
3
  class ThemeConfigFactory {
2
4
  /**
3
5
  * @param {ModulesConfigLoader} configLoader
@@ -11,22 +13,59 @@ class ThemeConfigFactory {
11
13
  this._appModulesFileWriter = appModulesFileWriter;
12
14
  this._configsFileWriter = configsFileWriter;
13
15
  }
14
-
15
16
  /**
16
17
  * @param {string} theme Theme name
17
- * @param {string} buildPath Path to theme build folder
18
18
  * @param {string|string[]} configFilepath Path (or paths with fallback) to yaml config file in a bundle
19
- * @return {Object} List of Webpack entry-points
19
+ * @return {Object} Merged Configs loaded from all the bundles Yaml files matched by filePath
20
+ */
21
+ loadConfig(theme, configFilepath) {
22
+ return this._configLoader.loadConfig(theme, configFilepath);
23
+ }
24
+
25
+ extendConfig(baseConfig, extraConfig) {
26
+ const {
27
+ aliases = {},
28
+ configs,
29
+ map = {},
30
+ shim = {}
31
+ } = baseConfig;
32
+
33
+ const {
34
+ ['app-modules']: appModules,
35
+ ['dynamic-imports']: dynamicImports,
36
+ entry,
37
+ ...rest
38
+ } = extraConfig;
39
+
40
+ const beyondKeys = Object.keys(rest);
41
+ if (beyondKeys.length) {
42
+ throw new JSModulesExtraModulesError(beyondKeys);
43
+ }
44
+
45
+ return {
46
+ aliases,
47
+ 'app-modules': appModules,
48
+ configs,
49
+ 'dynamic-imports': dynamicImports,
50
+ entry,
51
+ map,
52
+ shim
53
+ };
54
+ }
55
+
56
+ /**
57
+ * @param {string} buildPath Path to theme build folder
58
+ * @param {Object} jsModulesConfig configuration loaded from jsmodules files and merged together
59
+ * @return {Object} webpack configuration fragment
20
60
  */
21
- create(theme, buildPath, configFilepath) {
22
- const jsModulesConfig = this._configLoader.loadConfig(theme, configFilepath);
61
+ create(buildPath, jsModulesConfig) {
23
62
  const {
24
63
  entry,
25
64
  map = {},
26
65
  shim = {},
27
66
  configs,
28
67
  aliases = {},
29
- ['app-modules']: appModules,
68
+ ['app-modules']: appModules = [],
30
69
  ['dynamic-imports']: dynamicImports
31
70
  } = jsModulesConfig;
32
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
+ };