@automattic/vip 3.6.0 → 3.7.1
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/assets/dev-env.lando.template.yml.ejs +2 -0
- package/dist/bin/vip-import-validate-files.js +74 -79
- package/dist/commands/dev-env-import-sql.js +2 -4
- package/dist/commands/dev-env-sync-sql.js +36 -35
- package/dist/commands/export-sql.js +60 -56
- package/dist/lib/constants/dev-environment.js +1 -1
- package/dist/lib/media-import/config.js +25 -0
- package/dist/lib/vip-import-validate-files.js +157 -36
- package/docs/CHANGELOG.md +14 -0
- package/npm-shrinkwrap.json +494 -799
- package/package.json +7 -7
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
exports.__esModule = true;
|
|
4
|
+
exports.getMediaImportConfig = getMediaImportConfig;
|
|
5
|
+
var _graphqlTag = _interopRequireDefault(require("graphql-tag"));
|
|
6
|
+
var _api = _interopRequireDefault(require("../api"));
|
|
7
|
+
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
8
|
+
const IMPORT_MEDIA_CONFIG_QUERY = (0, _graphqlTag.default)`
|
|
9
|
+
{
|
|
10
|
+
mediaImportConfig {
|
|
11
|
+
fileNameCharCount
|
|
12
|
+
fileSizeLimitInBytes
|
|
13
|
+
allowedFileTypes
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
`;
|
|
17
|
+
async function getMediaImportConfig() {
|
|
18
|
+
const api = (0, _api.default)();
|
|
19
|
+
const response = await api.query({
|
|
20
|
+
query: IMPORT_MEDIA_CONFIG_QUERY,
|
|
21
|
+
variables: {},
|
|
22
|
+
fetchPolicy: 'network-only'
|
|
23
|
+
});
|
|
24
|
+
return response?.data?.mediaImportConfig;
|
|
25
|
+
}
|
|
@@ -1,13 +1,119 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
|
|
3
3
|
exports.__esModule = true;
|
|
4
|
-
exports.summaryLogs = exports.
|
|
4
|
+
exports.summaryLogs = exports.logErrors = exports.isFileSanitized = exports.isDirectory = 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
|
+
exports.isDirectory = isDirectory;
|
|
77
|
+
const getFileExtType = (file, allowedFileTypes) => {
|
|
78
|
+
if (!allowedFileTypes) return {
|
|
79
|
+
ext: null,
|
|
80
|
+
type: null
|
|
81
|
+
};
|
|
82
|
+
return getExtAndType(file, allowedFileTypes);
|
|
83
|
+
};
|
|
84
|
+
const isInvalidFile = (fileExtType, isFolder) => {
|
|
85
|
+
return !fileExtType.type || !fileExtType.ext || isFolder;
|
|
86
|
+
};
|
|
87
|
+
const getExtAndType = (filePath, allowedFileTypes) => {
|
|
88
|
+
const extType = {
|
|
89
|
+
ext: null,
|
|
90
|
+
type: null
|
|
91
|
+
};
|
|
92
|
+
for (const [key, value] of Object.entries(allowedFileTypes)) {
|
|
93
|
+
// Create a regular expression to match the file extension
|
|
94
|
+
// eslint-disable-next-line security/detect-non-literal-regexp
|
|
95
|
+
const regex = new RegExp(`(?:\\.)(${key})$`, 'i');
|
|
96
|
+
const matches = regex.exec(filePath);
|
|
97
|
+
if (matches) {
|
|
98
|
+
extType.type = value;
|
|
99
|
+
extType.ext = matches[1];
|
|
100
|
+
break;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
return extType;
|
|
104
|
+
};
|
|
105
|
+
const isFileSizeValid = (filePathOnDisk, fileSizeLimitInBytes) => {
|
|
106
|
+
const fileStat = _fs.default.statSync(filePathOnDisk);
|
|
107
|
+
return fileSizeLimitInBytes >= fileStat.size;
|
|
108
|
+
};
|
|
109
|
+
const isFileNameCharCountValid = (file, fileNameCharCount) => {
|
|
110
|
+
const filename = _path.default.basename(file);
|
|
111
|
+
return filename.length <= fileNameCharCount;
|
|
112
|
+
};
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* End file info validation
|
|
116
|
+
*/
|
|
11
117
|
|
|
12
118
|
/**
|
|
13
119
|
* Character validation global variables
|
|
@@ -38,8 +144,8 @@ const recommendedFileStructure = () => {
|
|
|
38
144
|
};
|
|
39
145
|
|
|
40
146
|
// Recommend accepted file types
|
|
41
|
-
const recommendAcceptableFileTypes =
|
|
42
|
-
console.log('Accepted file types: \n\n' + _chalk.default.magenta(`${
|
|
147
|
+
const recommendAcceptableFileTypes = allowedFileTypesString => {
|
|
148
|
+
console.log('Accepted file types: \n\n' + _chalk.default.magenta(`${allowedFileTypesString}`));
|
|
43
149
|
console.log();
|
|
44
150
|
};
|
|
45
151
|
|
|
@@ -392,8 +498,8 @@ const isFileSanitized = file => {
|
|
|
392
498
|
sanitizedFile = sanitizedFile.replace(regexSpaces, ' ');
|
|
393
499
|
|
|
394
500
|
// Check if the filename has been sanitized
|
|
395
|
-
|
|
396
|
-
return
|
|
501
|
+
|
|
502
|
+
return sanitizedFile !== filename;
|
|
397
503
|
};
|
|
398
504
|
|
|
399
505
|
/**
|
|
@@ -449,45 +555,50 @@ const doesImageHaveExistingSource = file => {
|
|
|
449
555
|
*
|
|
450
556
|
* Log errors for invalid folders or files
|
|
451
557
|
*/
|
|
452
|
-
|
|
453
|
-
// Log errors for files with invalid file extensions and recommend accepted file types
|
|
454
558
|
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 => {
|
|
559
|
+
const logErrors = ({
|
|
560
|
+
errorType,
|
|
561
|
+
invalidFiles,
|
|
562
|
+
limit
|
|
563
|
+
}) => {
|
|
564
|
+
if (invalidFiles.length === 0) {
|
|
565
|
+
return;
|
|
566
|
+
}
|
|
468
567
|
invalidFiles.forEach(file => {
|
|
469
|
-
|
|
568
|
+
switch (errorType) {
|
|
569
|
+
case ValidateFilesErrors.INVALID_TYPES:
|
|
570
|
+
console.error(_chalk.default.red('✕'), 'File extensions: Invalid file type for file: ', _chalk.default.cyan(`${file}`));
|
|
571
|
+
console.log();
|
|
572
|
+
recommendAcceptableFileTypes(limit);
|
|
573
|
+
break;
|
|
574
|
+
case ValidateFilesErrors.INTERMEDIATE_IMAGES:
|
|
575
|
+
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`));
|
|
576
|
+
break;
|
|
577
|
+
case ValidateFilesErrors.INVALID_SIZES:
|
|
578
|
+
console.error(_chalk.default.red('✕'), `File size cannot be more than ${limit / 1024 / 1024 / 1024} GB`, _chalk.default.cyan(`${file}`));
|
|
579
|
+
console.log();
|
|
580
|
+
break;
|
|
581
|
+
case ValidateFilesErrors.INVALID_NAME_CHARACTER_COUNTS:
|
|
582
|
+
console.error(_chalk.default.red('✕'), `File name cannot have more than ${limit} characters`, _chalk.default.cyan(`${file}`));
|
|
583
|
+
break;
|
|
584
|
+
case ValidateFilesErrors.INVALID_NAMES:
|
|
585
|
+
console.error(_chalk.default.red('✕'), 'Character validation: Invalid filename for file: ', _chalk.default.cyan(`${file}`));
|
|
586
|
+
recommendAcceptableFileNames();
|
|
587
|
+
break;
|
|
588
|
+
default:
|
|
589
|
+
console.error(_chalk.default.red('✕'), 'Unknown error type:', errorType);
|
|
590
|
+
}
|
|
470
591
|
});
|
|
471
592
|
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
593
|
};
|
|
485
|
-
exports.
|
|
594
|
+
exports.logErrors = logErrors;
|
|
486
595
|
const summaryLogs = ({
|
|
487
596
|
folderErrorsLength,
|
|
488
597
|
intImagesErrorsLength,
|
|
489
598
|
fileTypeErrorsLength,
|
|
599
|
+
fileErrorFileSizesLength,
|
|
490
600
|
filenameErrorsLength,
|
|
601
|
+
fileNameCharCountErrorsLength,
|
|
491
602
|
totalFiles,
|
|
492
603
|
totalFolders
|
|
493
604
|
}) => {
|
|
@@ -507,11 +618,21 @@ const summaryLogs = ({
|
|
|
507
618
|
} else {
|
|
508
619
|
messages.push(_chalk.default.white.bgGreen(' PASS ') + _chalk.default.green(` ${fileTypeErrorsLength} invalid file extensions`) + `, ${totalFiles} files total`);
|
|
509
620
|
}
|
|
621
|
+
if (fileErrorFileSizesLength > 0) {
|
|
622
|
+
messages.push(_chalk.default.white.bgRed(' ERROR ') + _chalk.default.red(` ${fileTypeErrorsLength} invalid file sizes`) + `, ${totalFiles} files total`);
|
|
623
|
+
} else {
|
|
624
|
+
messages.push(_chalk.default.white.bgGreen(' PASS ') + _chalk.default.green(` ${fileTypeErrorsLength} invalid file sizes`) + `, ${totalFiles} files total`);
|
|
625
|
+
}
|
|
510
626
|
if (filenameErrorsLength) {
|
|
511
627
|
messages.push(_chalk.default.white.bgRed(' ERROR ') + _chalk.default.red(` ${filenameErrorsLength} invalid filenames`) + `, ${totalFiles} files total`);
|
|
512
628
|
} else {
|
|
513
629
|
messages.push(_chalk.default.bgGreen(' PASS ') + _chalk.default.green(` ${filenameErrorsLength} invalid filenames`) + `, ${totalFiles} files total`);
|
|
514
630
|
}
|
|
631
|
+
if (fileNameCharCountErrorsLength) {
|
|
632
|
+
messages.push(_chalk.default.white.bgRed(' ERROR ') + _chalk.default.red(` ${filenameErrorsLength} file names reached the maximum character count limit `) + `, ${totalFiles} files total`);
|
|
633
|
+
} else {
|
|
634
|
+
messages.push(_chalk.default.bgGreen(' PASS ') + _chalk.default.green(` ${filenameErrorsLength} file names reached the maximum character count limit`) + `, ${totalFiles} files total`);
|
|
635
|
+
}
|
|
515
636
|
console.log(`\n${messages.join('\n')}\n`);
|
|
516
637
|
};
|
|
517
638
|
exports.summaryLogs = summaryLogs;
|
package/docs/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,19 @@
|
|
|
1
1
|
## Changelog
|
|
2
2
|
|
|
3
|
+
## 3.7.0
|
|
4
|
+
|
|
5
|
+
* New develop release: 3.6.1-dev.0 by @github-actions in #1931
|
|
6
|
+
* build(deps-dev): bump @automattic/eslint-plugin-wpvip from 0.12.0 to 0.13.0 by @dependabot in #1932
|
|
7
|
+
* build(deps-dev): bump the babel group with 3 updates by @dependabot in #1936
|
|
8
|
+
* build(deps): bump update-notifier from 7.0.0 to 7.1.0 by @dependabot in #1937
|
|
9
|
+
* build(deps): bump actions/dependency-review-action from 4.3.3 to 4.3.4 by @dependabot in #1938
|
|
10
|
+
* build(deps-dev): bump @babel/core from 7.24.8 to 7.24.9 in the babel group by @dependabot in #1939
|
|
11
|
+
* build(deps-dev): bump @types/dockerode from 3.3.29 to 3.3.30 by @dependabot in #1941
|
|
12
|
+
* update: media import validate-files by @ariskataoka in #1919
|
|
13
|
+
* New package release: v3.7.0 by @github-actions in #1943
|
|
14
|
+
|
|
15
|
+
**Full Changelog**: https://github.com/Automattic/vip-cli/compare/3.6.0...3.7.0
|
|
16
|
+
|
|
3
17
|
## 3.6.0
|
|
4
18
|
|
|
5
19
|
* build(deps-dev): bump rimraf from 5.0.7 to 5.0.8
|