@automattic/vip 3.5.1 → 3.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bin/vip-dev-env-create.js +1 -1
- package/dist/bin/vip-dev-env-destroy.js +1 -1
- package/dist/bin/vip-dev-env-exec.js +1 -1
- package/dist/bin/vip-dev-env-info.js +1 -1
- package/dist/bin/vip-dev-env-list.js +1 -1
- package/dist/bin/vip-dev-env-logs.js +1 -1
- package/dist/bin/vip-dev-env-purge.js +1 -1
- package/dist/bin/vip-dev-env-shell.js +1 -1
- package/dist/bin/vip-dev-env-start.js +1 -1
- package/dist/bin/vip-dev-env-stop.js +1 -1
- package/dist/bin/vip-dev-env-update.js +1 -1
- package/dist/bin/vip-import-validate-files.js +54 -74
- package/dist/commands/dev-env-import-sql.js +1 -1
- package/dist/lib/dev-environment/dev-environment-cli.js +1 -31
- package/dist/lib/dev-environment/dev-environment-lando.js +41 -2
- package/dist/lib/media-import/config.js +25 -0
- package/dist/lib/vip-import-validate-files.js +156 -36
- package/docs/CHANGELOG.md +15 -0
- package/npm-shrinkwrap.json +477 -782
- package/package.json +7 -7
|
@@ -1,13 +1,118 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
|
|
3
3
|
exports.__esModule = true;
|
|
4
|
-
exports.summaryLogs = exports.
|
|
4
|
+
exports.summaryLogs = exports.logErrors = exports.isFileSanitized = exports.folderStructureValidation = exports.findNestedDirectories = exports.doesImageHaveExistingSource = exports.ValidateFilesErrors = void 0;
|
|
5
|
+
exports.validateFiles = validateFiles;
|
|
5
6
|
var _chalk = _interopRequireDefault(require("chalk"));
|
|
6
7
|
var _fs = _interopRequireDefault(require("fs"));
|
|
7
8
|
var _path = _interopRequireDefault(require("path"));
|
|
8
9
|
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
9
|
-
|
|
10
|
-
|
|
10
|
+
/**
|
|
11
|
+
* External dependencies
|
|
12
|
+
*/
|
|
13
|
+
/**
|
|
14
|
+
* Internal dependencies
|
|
15
|
+
*/
|
|
16
|
+
let ValidateFilesErrors = exports.ValidateFilesErrors = /*#__PURE__*/function (ValidateFilesErrors) {
|
|
17
|
+
ValidateFilesErrors["INVALID_TYPES"] = "invalid_types";
|
|
18
|
+
ValidateFilesErrors["INTERMEDIATE_IMAGES"] = "intermediate_images";
|
|
19
|
+
ValidateFilesErrors["INVALID_SIZES"] = "invalid_sizes";
|
|
20
|
+
ValidateFilesErrors["INVALID_NAMES"] = "invalid_names";
|
|
21
|
+
ValidateFilesErrors["INVALID_NAME_CHARACTER_COUNTS"] = "invalid_name_character_counts";
|
|
22
|
+
return ValidateFilesErrors;
|
|
23
|
+
}({});
|
|
24
|
+
/**
|
|
25
|
+
* File info validation
|
|
26
|
+
*
|
|
27
|
+
* Validate the file info for media files
|
|
28
|
+
*/
|
|
29
|
+
async function validateFiles(files, mediaImportConfig) {
|
|
30
|
+
const validationResult = {
|
|
31
|
+
intermediateImagesTotal: 0,
|
|
32
|
+
errorFileTypes: [],
|
|
33
|
+
errorFileNames: [],
|
|
34
|
+
errorFileSizes: [],
|
|
35
|
+
errorFileNamesCharCount: [],
|
|
36
|
+
intermediateImages: {}
|
|
37
|
+
};
|
|
38
|
+
const fileValidationPromises = files.map(async file => {
|
|
39
|
+
const isFolder = await isDirectory(file);
|
|
40
|
+
const fileExtType = getFileExtType(file,
|
|
41
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
|
|
42
|
+
mediaImportConfig.allowedFileTypes);
|
|
43
|
+
if (isInvalidFile(fileExtType, isFolder)) {
|
|
44
|
+
validationResult.errorFileTypes.push(file);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
|
|
48
|
+
if (!isFileSizeValid(file, mediaImportConfig.fileSizeLimitInBytes)) {
|
|
49
|
+
validationResult.errorFileSizes.push(file);
|
|
50
|
+
}
|
|
51
|
+
if (isFileSanitized(file)) {
|
|
52
|
+
validationResult.errorFileNames.push(file);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
|
|
56
|
+
if (!isFileNameCharCountValid(file, mediaImportConfig?.fileNameCharCount)) {
|
|
57
|
+
validationResult.errorFileNamesCharCount.push(file);
|
|
58
|
+
}
|
|
59
|
+
const original = doesImageHaveExistingSource(file);
|
|
60
|
+
if (original) {
|
|
61
|
+
validationResult.intermediateImagesTotal++;
|
|
62
|
+
if (validationResult.intermediateImages[original]) {
|
|
63
|
+
validationResult.intermediateImages[original] += `, ${file}`;
|
|
64
|
+
} else {
|
|
65
|
+
validationResult.intermediateImages[original] = file;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
});
|
|
69
|
+
await Promise.all(fileValidationPromises);
|
|
70
|
+
return validationResult;
|
|
71
|
+
}
|
|
72
|
+
const isDirectory = async file => {
|
|
73
|
+
const stats = await _fs.default.promises.stat(file);
|
|
74
|
+
return stats.isDirectory();
|
|
75
|
+
};
|
|
76
|
+
const getFileExtType = (file, allowedFileTypes) => {
|
|
77
|
+
if (!allowedFileTypes) return {
|
|
78
|
+
ext: null,
|
|
79
|
+
type: null
|
|
80
|
+
};
|
|
81
|
+
return getExtAndType(file, allowedFileTypes);
|
|
82
|
+
};
|
|
83
|
+
const isInvalidFile = (fileExtType, isFolder) => {
|
|
84
|
+
return !fileExtType.type || !fileExtType.ext || isFolder;
|
|
85
|
+
};
|
|
86
|
+
const getExtAndType = (filePath, allowedFileTypes) => {
|
|
87
|
+
const extType = {
|
|
88
|
+
ext: null,
|
|
89
|
+
type: null
|
|
90
|
+
};
|
|
91
|
+
for (const [key, value] of Object.entries(allowedFileTypes)) {
|
|
92
|
+
// Create a regular expression to match the file extension
|
|
93
|
+
// eslint-disable-next-line security/detect-non-literal-regexp
|
|
94
|
+
const regex = new RegExp(`(?:\\.)(${key})$`, 'i');
|
|
95
|
+
const matches = regex.exec(filePath);
|
|
96
|
+
if (matches) {
|
|
97
|
+
extType.type = value;
|
|
98
|
+
extType.ext = matches[1];
|
|
99
|
+
break;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
return extType;
|
|
103
|
+
};
|
|
104
|
+
const isFileSizeValid = (filePathOnDisk, fileSizeLimitInBytes) => {
|
|
105
|
+
const fileStat = _fs.default.statSync(filePathOnDisk);
|
|
106
|
+
return fileSizeLimitInBytes >= fileStat.size;
|
|
107
|
+
};
|
|
108
|
+
const isFileNameCharCountValid = (file, fileNameCharCount) => {
|
|
109
|
+
const filename = _path.default.basename(file);
|
|
110
|
+
return filename.length <= fileNameCharCount;
|
|
111
|
+
};
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* End file info validation
|
|
115
|
+
*/
|
|
11
116
|
|
|
12
117
|
/**
|
|
13
118
|
* Character validation global variables
|
|
@@ -38,8 +143,8 @@ const recommendedFileStructure = () => {
|
|
|
38
143
|
};
|
|
39
144
|
|
|
40
145
|
// Recommend accepted file types
|
|
41
|
-
const recommendAcceptableFileTypes =
|
|
42
|
-
console.log('Accepted file types: \n\n' + _chalk.default.magenta(`${
|
|
146
|
+
const recommendAcceptableFileTypes = allowedFileTypesString => {
|
|
147
|
+
console.log('Accepted file types: \n\n' + _chalk.default.magenta(`${allowedFileTypesString}`));
|
|
43
148
|
console.log();
|
|
44
149
|
};
|
|
45
150
|
|
|
@@ -392,8 +497,8 @@ const isFileSanitized = file => {
|
|
|
392
497
|
sanitizedFile = sanitizedFile.replace(regexSpaces, ' ');
|
|
393
498
|
|
|
394
499
|
// Check if the filename has been sanitized
|
|
395
|
-
|
|
396
|
-
return
|
|
500
|
+
|
|
501
|
+
return sanitizedFile !== filename;
|
|
397
502
|
};
|
|
398
503
|
|
|
399
504
|
/**
|
|
@@ -449,45 +554,50 @@ const doesImageHaveExistingSource = file => {
|
|
|
449
554
|
*
|
|
450
555
|
* Log errors for invalid folders or files
|
|
451
556
|
*/
|
|
452
|
-
|
|
453
|
-
// Log errors for files with invalid file extensions and recommend accepted file types
|
|
454
557
|
exports.doesImageHaveExistingSource = doesImageHaveExistingSource;
|
|
455
|
-
const
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
};
|
|
464
|
-
|
|
465
|
-
// Log errors for files with invalid filenames and show a list of accepted/prohibited chars
|
|
466
|
-
exports.logErrorsForInvalidFileTypes = logErrorsForInvalidFileTypes;
|
|
467
|
-
const logErrorsForInvalidFilenames = invalidFiles => {
|
|
558
|
+
const logErrors = ({
|
|
559
|
+
errorType,
|
|
560
|
+
invalidFiles,
|
|
561
|
+
limit
|
|
562
|
+
}) => {
|
|
563
|
+
if (invalidFiles.length === 0) {
|
|
564
|
+
return;
|
|
565
|
+
}
|
|
468
566
|
invalidFiles.forEach(file => {
|
|
469
|
-
|
|
567
|
+
switch (errorType) {
|
|
568
|
+
case ValidateFilesErrors.INVALID_TYPES:
|
|
569
|
+
console.error(_chalk.default.red('✕'), 'File extensions: Invalid file type for file: ', _chalk.default.cyan(`${file}`));
|
|
570
|
+
console.log();
|
|
571
|
+
recommendAcceptableFileTypes(limit);
|
|
572
|
+
break;
|
|
573
|
+
case ValidateFilesErrors.INTERMEDIATE_IMAGES:
|
|
574
|
+
console.error(_chalk.default.red('✕'), 'Intermediate images: Duplicate files found:\n' + 'Original file: ' + _chalk.default.blue(`${file}\n`) + 'Intermediate images: ' + _chalk.default.cyan(`${limit[file]}\n`));
|
|
575
|
+
break;
|
|
576
|
+
case ValidateFilesErrors.INVALID_SIZES:
|
|
577
|
+
console.error(_chalk.default.red('✕'), `File size cannot be more than ${limit / 1024 / 1024 / 1024} GB`, _chalk.default.cyan(`${file}`));
|
|
578
|
+
console.log();
|
|
579
|
+
break;
|
|
580
|
+
case ValidateFilesErrors.INVALID_NAME_CHARACTER_COUNTS:
|
|
581
|
+
console.error(_chalk.default.red('✕'), `File name cannot have more than ${limit} characters`, _chalk.default.cyan(`${file}`));
|
|
582
|
+
break;
|
|
583
|
+
case ValidateFilesErrors.INVALID_NAMES:
|
|
584
|
+
console.error(_chalk.default.red('✕'), 'Character validation: Invalid filename for file: ', _chalk.default.cyan(`${file}`));
|
|
585
|
+
recommendAcceptableFileNames();
|
|
586
|
+
break;
|
|
587
|
+
default:
|
|
588
|
+
console.error(_chalk.default.red('✕'), 'Unknown error type:', errorType);
|
|
589
|
+
}
|
|
470
590
|
});
|
|
471
591
|
console.log();
|
|
472
|
-
recommendAcceptableFileNames();
|
|
473
|
-
console.log('------------------------------------------------------------');
|
|
474
|
-
console.log();
|
|
475
|
-
};
|
|
476
|
-
|
|
477
|
-
// Log errors for intermediate image file duplicates
|
|
478
|
-
exports.logErrorsForInvalidFilenames = logErrorsForInvalidFilenames;
|
|
479
|
-
const logErrorsForIntermediateImages = obj => {
|
|
480
|
-
for (const original in obj) {
|
|
481
|
-
console.error(_chalk.default.red('✕'), 'Intermediate images: Duplicate files found:\n' + 'Original file: ' + _chalk.default.blue(`${original}\n`) + 'Intermediate images: ' + _chalk.default.cyan(`${obj[original]}\n`));
|
|
482
|
-
}
|
|
483
|
-
console.log('------------------------------------------------------------');
|
|
484
592
|
};
|
|
485
|
-
exports.
|
|
593
|
+
exports.logErrors = logErrors;
|
|
486
594
|
const summaryLogs = ({
|
|
487
595
|
folderErrorsLength,
|
|
488
596
|
intImagesErrorsLength,
|
|
489
597
|
fileTypeErrorsLength,
|
|
598
|
+
fileErrorFileSizesLength,
|
|
490
599
|
filenameErrorsLength,
|
|
600
|
+
fileNameCharCountErrorsLength,
|
|
491
601
|
totalFiles,
|
|
492
602
|
totalFolders
|
|
493
603
|
}) => {
|
|
@@ -507,11 +617,21 @@ const summaryLogs = ({
|
|
|
507
617
|
} else {
|
|
508
618
|
messages.push(_chalk.default.white.bgGreen(' PASS ') + _chalk.default.green(` ${fileTypeErrorsLength} invalid file extensions`) + `, ${totalFiles} files total`);
|
|
509
619
|
}
|
|
620
|
+
if (fileErrorFileSizesLength > 0) {
|
|
621
|
+
messages.push(_chalk.default.white.bgRed(' ERROR ') + _chalk.default.red(` ${fileTypeErrorsLength} invalid file sizes`) + `, ${totalFiles} files total`);
|
|
622
|
+
} else {
|
|
623
|
+
messages.push(_chalk.default.white.bgGreen(' PASS ') + _chalk.default.green(` ${fileTypeErrorsLength} invalid file sizes`) + `, ${totalFiles} files total`);
|
|
624
|
+
}
|
|
510
625
|
if (filenameErrorsLength) {
|
|
511
626
|
messages.push(_chalk.default.white.bgRed(' ERROR ') + _chalk.default.red(` ${filenameErrorsLength} invalid filenames`) + `, ${totalFiles} files total`);
|
|
512
627
|
} else {
|
|
513
628
|
messages.push(_chalk.default.bgGreen(' PASS ') + _chalk.default.green(` ${filenameErrorsLength} invalid filenames`) + `, ${totalFiles} files total`);
|
|
514
629
|
}
|
|
630
|
+
if (fileNameCharCountErrorsLength) {
|
|
631
|
+
messages.push(_chalk.default.white.bgRed(' ERROR ') + _chalk.default.red(` ${filenameErrorsLength} file names reached the maximum character count limit `) + `, ${totalFiles} files total`);
|
|
632
|
+
} else {
|
|
633
|
+
messages.push(_chalk.default.bgGreen(' PASS ') + _chalk.default.green(` ${filenameErrorsLength} file names reached the maximum character count limit`) + `, ${totalFiles} files total`);
|
|
634
|
+
}
|
|
515
635
|
console.log(`\n${messages.join('\n')}\n`);
|
|
516
636
|
};
|
|
517
637
|
exports.summaryLogs = summaryLogs;
|
package/docs/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,20 @@
|
|
|
1
1
|
## Changelog
|
|
2
2
|
|
|
3
|
+
## 3.6.0
|
|
4
|
+
|
|
5
|
+
* build(deps-dev): bump rimraf from 5.0.7 to 5.0.8
|
|
6
|
+
* feat(dev-env): add DNS check to health check to ensure domains resolve correctly
|
|
7
|
+
|
|
8
|
+
**Full Changelog**: https://github.com/Automattic/vip-cli/compare/3.5.1...3.6.0
|
|
9
|
+
|
|
10
|
+
## 3.5.1
|
|
11
|
+
|
|
12
|
+
* fix(dev-env): display cron status in `vip dev-env info --extended`
|
|
13
|
+
* build(deps-dev): bump typescript from 5.5.2 to 5.5.3
|
|
14
|
+
* fix: case mismatch in environment identifier matcher
|
|
15
|
+
|
|
16
|
+
**Full Changelog**: https://github.com/Automattic/vip-cli/compare/3.5.0...3.5.1
|
|
17
|
+
|
|
3
18
|
### 3.5.0
|
|
4
19
|
|
|
5
20
|
* feat(dev-env): add support for cron
|