@zohodesk/react-cli 1.1.9 → 1.1.11
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/.vscode/settings.json +25 -0
- package/README.md +121 -43
- package/bin/cli.js +5 -48
- package/lib/common/runPreProcess.js +71 -0
- package/lib/configs/webpack.css.umd.config.js +3 -2
- package/lib/configs/webpack.dev.config.js +3 -0
- package/lib/configs/webpack.docs.config.js +2 -0
- package/lib/configs/webpack.impact.config.js +2 -0
- package/lib/configs/webpack.prod.config.js +3 -0
- package/lib/deprecationLogger.js +0 -1
- package/lib/loaderUtils/getCSSLoaders.js +4 -3
- package/lib/logger.js +7 -0
- package/lib/plugins/utils/fileHandling.js +13 -13
- package/lib/schemas/index.js +2 -1
- package/lib/utils/cssClassNameGenerate.js +38 -5
- package/lib/utils/deprecationSupport.js +7 -1
- package/lib/utils/getOptions.js +16 -1
- package/npm-shrinkwrap.json +94 -2
- package/package.json +2 -2
- package/templates/docs/css/style.css +136 -169
- package/templates/docs/index.html +795 -632
@@ -53,23 +53,23 @@ function isFileNameMatchingPattern({
|
|
53
53
|
plugins.forEach(p => {
|
54
54
|
pluginObj[p.postcssPlugin] = p;
|
55
55
|
});
|
56
|
-
const finalPlugins =
|
57
|
-
order.forEach(key => {
|
58
|
-
const p = pluginObj[aliasNames[key]];
|
56
|
+
const finalPlugins = order.filter(key => {
|
59
57
|
const pluginSpecificFilter = filterObject[key];
|
60
58
|
|
61
59
|
if (!pluginSpecificFilter || pluginSpecificFilter.length === 0) {
|
62
|
-
|
63
|
-
}
|
64
|
-
// eslint-disable-next-line no-use-before-define
|
65
|
-
const isMatching = isFilePathMatchingPattern(filename, pluginSpecificFilter);
|
60
|
+
return true;
|
61
|
+
} // eslint-disable-next-line no-use-before-define
|
66
62
|
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
63
|
+
|
64
|
+
const isMatching = isFilePathMatchingPattern(filename, pluginSpecificFilter);
|
65
|
+
return isMatching;
|
66
|
+
}).map(key => {
|
67
|
+
const p = pluginObj[aliasNames[key]];
|
68
|
+
return p;
|
69
|
+
}); // if unknown key given in plugins and pattern loop will run but post-css plugin won't be available and will be undefined in array
|
70
|
+
// So we do filter as safety measure.
|
71
|
+
|
72
|
+
return finalPlugins.filter(Boolean);
|
73
73
|
}
|
74
74
|
|
75
75
|
function isFilePathMatchingPattern(filePath, patterns) {
|
package/lib/schemas/index.js
CHANGED
@@ -15,7 +15,6 @@ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { de
|
|
15
15
|
|
16
16
|
// TODO move deprecated options to separate file and manage seperately
|
17
17
|
var _default = {
|
18
|
-
cliRootPath: null,
|
19
18
|
unstableDepsInverse: {
|
20
19
|
value: false,
|
21
20
|
cli: 'unstable_deps_inverse'
|
@@ -130,6 +129,7 @@ var _default = {
|
|
130
129
|
value: '@zohodesk/client_packages_group',
|
131
130
|
cli: 'module_resolve_path'
|
132
131
|
},
|
132
|
+
customClassNamePrefix: [],
|
133
133
|
// this option only for impact testing
|
134
134
|
devCssFileBountry: {
|
135
135
|
value: '',
|
@@ -357,6 +357,7 @@ var _default = {
|
|
357
357
|
hover: 'all and (min--moz-device-pixel-ratio:0) and (hover: hover), (hover: hover)',
|
358
358
|
none: '(hover: none)'
|
359
359
|
},
|
360
|
+
customClassNamePrefix: [],
|
360
361
|
componentFolder: 'src',
|
361
362
|
cssUniqueness: {
|
362
363
|
value: true,
|
@@ -38,14 +38,35 @@ const isSelectorPackage = (resourcePath, packages) => {
|
|
38
38
|
return isValid;
|
39
39
|
};
|
40
40
|
|
41
|
+
function patternBasedClass({
|
42
|
+
customClassNamePrefix,
|
43
|
+
context,
|
44
|
+
relativePath,
|
45
|
+
localName
|
46
|
+
}) {
|
47
|
+
let newName = null;
|
48
|
+
customClassNamePrefix.forEach(obj => {
|
49
|
+
if (obj.enable) {
|
50
|
+
if (obj.patterns && obj.prefix && (0, _fileHandling.isFileNameMatchingPluginPattern)({
|
51
|
+
filename: context.resourcePath,
|
52
|
+
filterArr: obj.patterns
|
53
|
+
})) {
|
54
|
+
const h = (0, _getHash.default)(`${relativePath}-${localName}`, 10);
|
55
|
+
newName = `${obj.prefix}${h}`;
|
56
|
+
}
|
57
|
+
}
|
58
|
+
});
|
59
|
+
return newName;
|
60
|
+
}
|
61
|
+
|
41
62
|
var _default = (unique = true, {
|
42
63
|
filenames,
|
43
64
|
packages
|
44
|
-
}, classNamePrefix, patterns) => (context, localIdentName, localName) => {
|
65
|
+
}, classNamePrefix, customClassNamePrefix, patterns) => (context, localIdentName, localName) => {
|
45
66
|
// console.log(patterns, context.resourcePath);
|
46
|
-
// NOTE: in build
|
67
|
+
// NOTE: in build machine we use date as folder path.
|
47
68
|
// So every time we create new build there is path will alway different
|
48
|
-
// in order to
|
69
|
+
// in order to minimize that problem we try in relative path;
|
49
70
|
// console.log('context.resourcePath', context.resourcePath, context);
|
50
71
|
// let contextResourcePath = context.resourcePath;
|
51
72
|
const filePaths = context.resourcePath.split(_path.default.sep);
|
@@ -53,7 +74,8 @@ var _default = (unique = true, {
|
|
53
74
|
const [fileNameWithoutExt] = fileName.split('.');
|
54
75
|
const cleanFileName = fileNameWithoutExt.replace(/-/g, '_').toLowerCase();
|
55
76
|
|
56
|
-
const relativePath = _path.default.relative(context.rootContext, context.resourcePath);
|
77
|
+
const relativePath = _path.default.relative(context.rootContext, context.resourcePath); // console.log('customClassNamePrefix', customClassNamePrefix);
|
78
|
+
|
57
79
|
/*
|
58
80
|
input :
|
59
81
|
context.resourcePath : 'D:/MyWork/..../desk_client_app/supportapp/src/components/Avatar/Avatar.module.css,
|
@@ -86,7 +108,18 @@ var _default = (unique = true, {
|
|
86
108
|
if (unique) {
|
87
109
|
const h = (0, _getHash.default)(`${relativePath}-${localName}`, 10);
|
88
110
|
return `${classNamePrefix}${h}`;
|
89
|
-
}
|
111
|
+
}
|
112
|
+
|
113
|
+
const patternClass = patternBasedClass({
|
114
|
+
customClassNamePrefix,
|
115
|
+
context,
|
116
|
+
relativePath,
|
117
|
+
localName
|
118
|
+
});
|
119
|
+
|
120
|
+
if (patternClass) {
|
121
|
+
return patternClass;
|
122
|
+
} //css file has case sensitive selector issue so can't toLowerCase
|
90
123
|
//let local = localName.toLowerCase()
|
91
124
|
|
92
125
|
|
@@ -109,13 +109,19 @@ function deprecationSupport(options, disableDeprecationWarning) {
|
|
109
109
|
|
110
110
|
function addExcludesToPattern(patterns, exclude, type) {
|
111
111
|
Object.keys(defaultPostCssPluginOptions).forEach(key => {
|
112
|
-
if (exclude[key]
|
112
|
+
if (!exclude[key] || exclude[key].length === 0) {
|
113
|
+
return;
|
114
|
+
}
|
115
|
+
|
116
|
+
if (patterns[key].length === 0) {
|
113
117
|
deprecateOption(`${type}.exclude.${key}`, `${type}.patterns.${key}`);
|
114
118
|
let tempArr = exclude[key];
|
115
119
|
tempArr = tempArr.map(x => _path.default.join('!**', x, '**')); // Since patterns[key] is empty we need to wildcard for allow all others.
|
116
120
|
|
117
121
|
tempArr.unshift('*');
|
118
122
|
patterns[key] = tempArr;
|
123
|
+
} else if (exclude[key].length > 0 && patterns[key].length > 0) {
|
124
|
+
deprecateOption(`${type}.exclude.${key}`, `${type}.patterns.${key}`, ` And Since you have used ${type}.patterns.${key} we won't use ${type}.exclude.${key}. So please make appropriate changes`);
|
119
125
|
}
|
120
126
|
});
|
121
127
|
}
|
package/lib/utils/getOptions.js
CHANGED
@@ -15,6 +15,10 @@ var _schemas = _interopRequireDefault(require("../schemas"));
|
|
15
15
|
|
16
16
|
var _deprecationSupport = require("./deprecationSupport");
|
17
17
|
|
18
|
+
var _deprecationLogger = require("../deprecationLogger");
|
19
|
+
|
20
|
+
var _logger = require("../logger");
|
21
|
+
|
18
22
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
19
23
|
|
20
24
|
function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
|
@@ -131,7 +135,11 @@ const defaulter = (target, source) => {
|
|
131
135
|
global.reactCLIOptions = null;
|
132
136
|
|
133
137
|
const getOptionsFromConfigFile = (appPath, configFileName) => {
|
134
|
-
const fileName = configFileName || '
|
138
|
+
const fileName = configFileName || 'react-cli.config.js';
|
139
|
+
|
140
|
+
if (!configFileName) {
|
141
|
+
(0, _logger.verboseLogger)('we have used default react-cli.config.js');
|
142
|
+
}
|
135
143
|
|
136
144
|
const packagePath = _path.default.join(appPath, fileName);
|
137
145
|
|
@@ -139,6 +147,13 @@ const getOptionsFromConfigFile = (appPath, configFileName) => {
|
|
139
147
|
return require(packagePath).config;
|
140
148
|
}
|
141
149
|
|
150
|
+
const oldDeprecatedConfigFilePath = _path.default.join(appPath, 'build.config.js');
|
151
|
+
|
152
|
+
if ((0, _fs.existsSync)(oldDeprecatedConfigFilePath)) {
|
153
|
+
(0, _deprecationLogger.deprecateMessage)('"build.config.js" file was deprecated. So Kindly rename it as "react-cli.config.js"');
|
154
|
+
return require(oldDeprecatedConfigFilePath).config;
|
155
|
+
}
|
156
|
+
|
142
157
|
return null;
|
143
158
|
};
|
144
159
|
|
package/npm-shrinkwrap.json
CHANGED
@@ -1,12 +1,12 @@
|
|
1
1
|
{
|
2
2
|
"name": "@zohodesk/react-cli",
|
3
|
-
"version": "1.1.
|
3
|
+
"version": "1.1.11",
|
4
4
|
"lockfileVersion": 2,
|
5
5
|
"requires": true,
|
6
6
|
"packages": {
|
7
7
|
"": {
|
8
8
|
"name": "@zohodesk/react-cli",
|
9
|
-
"version": "1.1.
|
9
|
+
"version": "1.1.11",
|
10
10
|
"license": "ISC",
|
11
11
|
"dependencies": {
|
12
12
|
"@babel/cli": "7.10.5",
|
@@ -57,6 +57,7 @@
|
|
57
57
|
"jsdom": "16.4.0",
|
58
58
|
"loader-utils": "2.0.0",
|
59
59
|
"lodash-webpack-plugin": "0.11.5",
|
60
|
+
"markdown-it": "13.0.1",
|
60
61
|
"mini-css-extract-plugin": "0.10.0",
|
61
62
|
"nock": "13.2.9",
|
62
63
|
"nodemailer": "6.4.11",
|
@@ -12144,6 +12145,14 @@
|
|
12144
12145
|
"resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz",
|
12145
12146
|
"integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg=="
|
12146
12147
|
},
|
12148
|
+
"node_modules/linkify-it": {
|
12149
|
+
"version": "4.0.1",
|
12150
|
+
"resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-4.0.1.tgz",
|
12151
|
+
"integrity": "sha512-C7bfi1UZmoj8+PQx22XyeXCuBlokoyWQL5pWSP+EI6nzRylyThouddufc2c1NDIcP9k5agmN9fLpA7VNJfIiqw==",
|
12152
|
+
"dependencies": {
|
12153
|
+
"uc.micro": "^1.0.1"
|
12154
|
+
}
|
12155
|
+
},
|
12147
12156
|
"node_modules/load-json-file": {
|
12148
12157
|
"version": "1.1.0",
|
12149
12158
|
"resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz",
|
@@ -12342,6 +12351,37 @@
|
|
12342
12351
|
"node": ">=0.10.0"
|
12343
12352
|
}
|
12344
12353
|
},
|
12354
|
+
"node_modules/markdown-it": {
|
12355
|
+
"version": "13.0.1",
|
12356
|
+
"resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-13.0.1.tgz",
|
12357
|
+
"integrity": "sha512-lTlxriVoy2criHP0JKRhO2VDG9c2ypWCsT237eDiLqi09rmbKoUetyGHq2uOIRoRS//kfoJckS0eUzzkDR+k2Q==",
|
12358
|
+
"dependencies": {
|
12359
|
+
"argparse": "^2.0.1",
|
12360
|
+
"entities": "~3.0.1",
|
12361
|
+
"linkify-it": "^4.0.1",
|
12362
|
+
"mdurl": "^1.0.1",
|
12363
|
+
"uc.micro": "^1.0.5"
|
12364
|
+
},
|
12365
|
+
"bin": {
|
12366
|
+
"markdown-it": "bin/markdown-it.js"
|
12367
|
+
}
|
12368
|
+
},
|
12369
|
+
"node_modules/markdown-it/node_modules/argparse": {
|
12370
|
+
"version": "2.0.1",
|
12371
|
+
"resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
|
12372
|
+
"integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q=="
|
12373
|
+
},
|
12374
|
+
"node_modules/markdown-it/node_modules/entities": {
|
12375
|
+
"version": "3.0.1",
|
12376
|
+
"resolved": "https://registry.npmjs.org/entities/-/entities-3.0.1.tgz",
|
12377
|
+
"integrity": "sha512-WiyBqoomrwMdFG1e0kqvASYfnlb0lp8M5o5Fw2OFq1hNZxxcNk8Ik0Xm7LxzBhuidnZB/UtBqVCgUz3kBOP51Q==",
|
12378
|
+
"engines": {
|
12379
|
+
"node": ">=0.12"
|
12380
|
+
},
|
12381
|
+
"funding": {
|
12382
|
+
"url": "https://github.com/fb55/entities?sponsor=1"
|
12383
|
+
}
|
12384
|
+
},
|
12345
12385
|
"node_modules/md5.js": {
|
12346
12386
|
"version": "1.3.5",
|
12347
12387
|
"resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz",
|
@@ -12352,6 +12392,11 @@
|
|
12352
12392
|
"safe-buffer": "^5.1.2"
|
12353
12393
|
}
|
12354
12394
|
},
|
12395
|
+
"node_modules/mdurl": {
|
12396
|
+
"version": "1.0.1",
|
12397
|
+
"resolved": "https://registry.npmjs.org/mdurl/-/mdurl-1.0.1.tgz",
|
12398
|
+
"integrity": "sha512-/sKlQJCBYVY9Ers9hqzKou4H6V5UWc/M59TH2dvkt+84itfnq7uFOMLpOiOS4ujvHP4etln18fmIxA5R5fll0g=="
|
12399
|
+
},
|
12355
12400
|
"node_modules/media-typer": {
|
12356
12401
|
"version": "0.3.0",
|
12357
12402
|
"resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
|
@@ -17169,6 +17214,11 @@
|
|
17169
17214
|
"is-typedarray": "^1.0.0"
|
17170
17215
|
}
|
17171
17216
|
},
|
17217
|
+
"node_modules/uc.micro": {
|
17218
|
+
"version": "1.0.6",
|
17219
|
+
"resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-1.0.6.tgz",
|
17220
|
+
"integrity": "sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA=="
|
17221
|
+
},
|
17172
17222
|
"node_modules/uglify-js": {
|
17173
17223
|
"version": "3.17.3",
|
17174
17224
|
"resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.17.3.tgz",
|
@@ -28076,6 +28126,14 @@
|
|
28076
28126
|
"resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz",
|
28077
28127
|
"integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg=="
|
28078
28128
|
},
|
28129
|
+
"linkify-it": {
|
28130
|
+
"version": "4.0.1",
|
28131
|
+
"resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-4.0.1.tgz",
|
28132
|
+
"integrity": "sha512-C7bfi1UZmoj8+PQx22XyeXCuBlokoyWQL5pWSP+EI6nzRylyThouddufc2c1NDIcP9k5agmN9fLpA7VNJfIiqw==",
|
28133
|
+
"requires": {
|
28134
|
+
"uc.micro": "^1.0.1"
|
28135
|
+
}
|
28136
|
+
},
|
28079
28137
|
"load-json-file": {
|
28080
28138
|
"version": "1.1.0",
|
28081
28139
|
"resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz",
|
@@ -28234,6 +28292,30 @@
|
|
28234
28292
|
"object-visit": "^1.0.0"
|
28235
28293
|
}
|
28236
28294
|
},
|
28295
|
+
"markdown-it": {
|
28296
|
+
"version": "13.0.1",
|
28297
|
+
"resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-13.0.1.tgz",
|
28298
|
+
"integrity": "sha512-lTlxriVoy2criHP0JKRhO2VDG9c2ypWCsT237eDiLqi09rmbKoUetyGHq2uOIRoRS//kfoJckS0eUzzkDR+k2Q==",
|
28299
|
+
"requires": {
|
28300
|
+
"argparse": "^2.0.1",
|
28301
|
+
"entities": "~3.0.1",
|
28302
|
+
"linkify-it": "^4.0.1",
|
28303
|
+
"mdurl": "^1.0.1",
|
28304
|
+
"uc.micro": "^1.0.5"
|
28305
|
+
},
|
28306
|
+
"dependencies": {
|
28307
|
+
"argparse": {
|
28308
|
+
"version": "2.0.1",
|
28309
|
+
"resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
|
28310
|
+
"integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q=="
|
28311
|
+
},
|
28312
|
+
"entities": {
|
28313
|
+
"version": "3.0.1",
|
28314
|
+
"resolved": "https://registry.npmjs.org/entities/-/entities-3.0.1.tgz",
|
28315
|
+
"integrity": "sha512-WiyBqoomrwMdFG1e0kqvASYfnlb0lp8M5o5Fw2OFq1hNZxxcNk8Ik0Xm7LxzBhuidnZB/UtBqVCgUz3kBOP51Q=="
|
28316
|
+
}
|
28317
|
+
}
|
28318
|
+
},
|
28237
28319
|
"md5.js": {
|
28238
28320
|
"version": "1.3.5",
|
28239
28321
|
"resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz",
|
@@ -28244,6 +28326,11 @@
|
|
28244
28326
|
"safe-buffer": "^5.1.2"
|
28245
28327
|
}
|
28246
28328
|
},
|
28329
|
+
"mdurl": {
|
28330
|
+
"version": "1.0.1",
|
28331
|
+
"resolved": "https://registry.npmjs.org/mdurl/-/mdurl-1.0.1.tgz",
|
28332
|
+
"integrity": "sha512-/sKlQJCBYVY9Ers9hqzKou4H6V5UWc/M59TH2dvkt+84itfnq7uFOMLpOiOS4ujvHP4etln18fmIxA5R5fll0g=="
|
28333
|
+
},
|
28247
28334
|
"media-typer": {
|
28248
28335
|
"version": "0.3.0",
|
28249
28336
|
"resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
|
@@ -32025,6 +32112,11 @@
|
|
32025
32112
|
"is-typedarray": "^1.0.0"
|
32026
32113
|
}
|
32027
32114
|
},
|
32115
|
+
"uc.micro": {
|
32116
|
+
"version": "1.0.6",
|
32117
|
+
"resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-1.0.6.tgz",
|
32118
|
+
"integrity": "sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA=="
|
32119
|
+
},
|
32028
32120
|
"uglify-js": {
|
32029
32121
|
"version": "3.17.3",
|
32030
32122
|
"resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.17.3.tgz",
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "@zohodesk/react-cli",
|
3
|
-
"version": "1.1.
|
3
|
+
"version": "1.1.11",
|
4
4
|
"description": "A CLI tool for build modern web application and libraries",
|
5
5
|
"scripts": {
|
6
6
|
"init": "node ./lib/utils/init.js",
|
@@ -80,7 +80,7 @@
|
|
80
80
|
"jsdom": "16.4.0",
|
81
81
|
"loader-utils": "2.0.0",
|
82
82
|
"lodash-webpack-plugin": "0.11.5",
|
83
|
-
"markdown-it": "
|
83
|
+
"markdown-it": "13.0.1",
|
84
84
|
"mini-css-extract-plugin": "0.10.0",
|
85
85
|
"nock": "13.2.9",
|
86
86
|
"nodemailer": "6.4.11",
|