@automattic/vip 4.1.6 → 4.1.8
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 +1 -1
- package/dist/bin/vip-app-deploy-token-generate.js +110 -78
- package/dist/bin/vip-app-deploy-token.js +24 -16
- package/dist/bin/vip-app-deploy-validate.js +45 -41
- package/dist/bin/vip-app-deploy.js +222 -215
- package/dist/bin/vip-app-list.js +59 -43
- package/dist/bin/vip-app.js +97 -66
- package/dist/bin/vip-backup-db.js +36 -29
- package/dist/bin/vip-backup.js +16 -9
- package/dist/bin/vip-cache-purge-url.js +93 -55
- package/dist/bin/vip-cache.js +23 -14
- package/dist/bin/vip-config-envvar-delete.js +74 -73
- package/dist/bin/vip-config-envvar-get-all.js +68 -68
- package/dist/bin/vip-config-envvar-get.js +46 -46
- package/dist/bin/vip-config-envvar-list.js +54 -57
- package/dist/bin/vip-config-envvar-set.js +102 -96
- package/dist/bin/vip-config-envvar.js +38 -24
- package/dist/bin/vip-config-software-get.js +88 -75
- package/dist/bin/vip-config-software-update.js +116 -120
- package/dist/bin/vip-config-software.js +31 -21
- package/dist/bin/vip-config.js +25 -17
- package/dist/bin/vip-db-phpmyadmin.js +40 -39
- package/dist/bin/vip-db.js +13 -12
- package/dist/bin/vip-defensive-mode-configure.js +197 -197
- package/dist/bin/vip-defensive-mode-disable.js +43 -35
- package/dist/bin/vip-defensive-mode-enable.js +47 -38
- package/dist/bin/vip-defensive-mode.js +28 -17
- package/dist/bin/vip-dev-env-create.js +147 -104
- package/dist/bin/vip-dev-env-destroy.js +48 -39
- package/dist/bin/vip-dev-env-envvar-delete.js +60 -49
- package/dist/bin/vip-dev-env-envvar-get-all.js +52 -45
- package/dist/bin/vip-dev-env-envvar-get.js +48 -37
- package/dist/bin/vip-dev-env-envvar-list.js +48 -41
- package/dist/bin/vip-dev-env-envvar-set.js +83 -70
- package/dist/bin/vip-dev-env-envvar.js +38 -23
- package/dist/bin/vip-dev-env-exec.js +81 -74
- package/dist/bin/vip-dev-env-import-media.js +34 -26
- package/dist/bin/vip-dev-env-import-sql.js +65 -51
- package/dist/bin/vip-dev-env-import.js +23 -14
- package/dist/bin/vip-dev-env-info.js +59 -50
- package/dist/bin/vip-dev-env-list.js +34 -31
- package/dist/bin/vip-dev-env-logs.js +59 -49
- package/dist/bin/vip-dev-env-purge.js +71 -63
- package/dist/bin/vip-dev-env-shell.js +82 -71
- package/dist/bin/vip-dev-env-start.js +77 -65
- package/dist/bin/vip-dev-env-stop.js +80 -74
- package/dist/bin/vip-dev-env-sync-sql.js +80 -72
- package/dist/bin/vip-dev-env-sync.js +18 -11
- package/dist/bin/vip-dev-env-update.js +93 -84
- package/dist/bin/vip-dev-env.js +25 -8
- package/dist/bin/vip-edge-workers-build.js +82 -54
- package/dist/bin/vip-edge-workers-delete.js +84 -52
- package/dist/bin/vip-edge-workers-deploy.js +186 -126
- package/dist/bin/vip-edge-workers-disable.js +75 -44
- package/dist/bin/vip-edge-workers-enable.js +86 -54
- package/dist/bin/vip-edge-workers-get.js +108 -88
- package/dist/bin/vip-edge-workers-init.js +83 -53
- package/dist/bin/vip-edge-workers-list.js +89 -54
- package/dist/bin/vip-edge-workers-new.js +98 -69
- package/dist/bin/vip-edge-workers-validate.js +123 -82
- package/dist/bin/vip-edge-workers.js +19 -6
- package/dist/bin/vip-export-sql.js +75 -69
- package/dist/bin/vip-export.js +12 -7
- package/dist/bin/vip-import-media-abort.js +99 -73
- package/dist/bin/vip-import-media-status.js +83 -51
- package/dist/bin/vip-import-media.js +165 -166
- package/dist/bin/vip-import-sql-status.js +75 -45
- package/dist/bin/vip-import-sql.js +536 -596
- package/dist/bin/vip-import-validate-files.js +122 -141
- package/dist/bin/vip-import-validate-sql.js +52 -16
- package/dist/bin/vip-import.js +16 -7
- package/dist/bin/vip-logout.js +17 -13
- package/dist/bin/vip-logs.js +209 -183
- package/dist/bin/vip-search-replace.js +85 -53
- package/dist/bin/vip-slowlogs.js +168 -147
- package/dist/bin/vip-sync.js +163 -133
- package/dist/bin/vip-whoami.js +71 -35
- package/dist/bin/vip-wp.js +506 -549
- package/dist/bin/vip.js +161 -116
- package/dist/commands/backup-db.js +183 -149
- package/dist/commands/dev-env-import-sql.js +162 -117
- package/dist/commands/dev-env-sync-sql.js +372 -330
- package/dist/commands/export-sql.js +441 -425
- package/dist/commands/phpmyadmin.js +232 -212
- package/dist/commands/wp-ssh.js +218 -187
- package/dist/lib/analytics/clients/tracks.js +84 -91
- package/dist/lib/analytics/index.js +27 -27
- package/dist/lib/api/app.js +37 -36
- package/dist/lib/api/cache-purge.js +17 -20
- package/dist/lib/api/constants.js +5 -6
- package/dist/lib/api/edge-workers.js +84 -135
- package/dist/lib/api/error-debug.js +10 -13
- package/dist/lib/api/feature-flags.js +16 -17
- package/dist/lib/api/http.js +47 -48
- package/dist/lib/api/user.js +17 -18
- package/dist/lib/api.js +107 -116
- package/dist/lib/app-logs/app-logs.js +24 -25
- package/dist/lib/app-slowlogs/app-slowlogs.js +23 -24
- package/dist/lib/app-slowlogs/types.js +2 -1
- package/dist/lib/app.js +6 -8
- package/dist/lib/backup-storage-availability/backup-storage-availability.js +119 -119
- package/dist/lib/backup-storage-availability/docker-machine-not-found-error.js +5 -6
- package/dist/lib/cli/apiConfig.js +71 -41
- package/dist/lib/cli/command.js +1120 -873
- package/dist/lib/cli/config.js +29 -29
- package/dist/lib/cli/envAlias.js +35 -50
- package/dist/lib/cli/exit.js +19 -19
- package/dist/lib/cli/format.js +172 -172
- package/dist/lib/cli/progress.js +193 -236
- package/dist/lib/cli/prompt.js +14 -15
- package/dist/lib/cli/runtime-mode.js +5 -6
- package/dist/lib/client-file-uploader.js +489 -641
- package/dist/lib/config/software.js +206 -212
- package/dist/lib/constants/dev-environment.js +40 -37
- package/dist/lib/constants/file-size.js +6 -7
- package/dist/lib/constants/vipgo.js +24 -12
- package/dist/lib/custom-deploy/custom-deploy.js +138 -120
- package/dist/lib/database.js +88 -85
- package/dist/lib/defensive-mode/api.js +41 -46
- package/dist/lib/defensive-mode/cli-helpers.js +40 -40
- package/dist/lib/dev-environment/dev-environment-cli.js +776 -735
- package/dist/lib/dev-environment/dev-environment-configuration-file.js +224 -191
- package/dist/lib/dev-environment/dev-environment-core.js +697 -732
- package/dist/lib/dev-environment/dev-environment-database.js +57 -41
- package/dist/lib/dev-environment/dev-environment-lando.js +734 -666
- package/dist/lib/dev-environment/docker-utils.js +96 -90
- package/dist/lib/dev-environment/env-vars.js +61 -59
- package/dist/lib/dev-environment/lando-loader.js +6 -7
- package/dist/lib/dev-environment/types.js +2 -1
- package/dist/lib/edge-workers/confirmation.js +42 -36
- package/dist/lib/edge-workers/deployment.js +150 -159
- package/dist/lib/edge-workers/index.js +68 -85
- package/dist/lib/edge-workers/location.js +26 -26
- package/dist/lib/edge-workers/output.js +14 -15
- package/dist/lib/edge-workers/project.js +123 -132
- package/dist/lib/edge-workers/toolchains/assemblyscript/constants.js +6 -8
- package/dist/lib/edge-workers/toolchains/assemblyscript/index.js +100 -101
- package/dist/lib/edge-workers/toolchains/assemblyscript/templates.js +31 -33
- package/dist/lib/edge-workers/toolchains/index.js +15 -15
- package/dist/lib/edge-workers/types.js +10 -38
- package/dist/lib/edge-workers/validation.js +161 -150
- package/dist/lib/env.js +16 -17
- package/dist/lib/envvar/api-delete.js +16 -18
- package/dist/lib/envvar/api-get-all.js +15 -19
- package/dist/lib/envvar/api-get.js +8 -9
- package/dist/lib/envvar/api-list.js +16 -21
- package/dist/lib/envvar/api-set.js +20 -19
- package/dist/lib/envvar/api.js +34 -29
- package/dist/lib/envvar/input.js +29 -34
- package/dist/lib/envvar/logging.js +9 -11
- package/dist/lib/envvar/read-file.js +6 -7
- package/dist/lib/http/download-file.js +76 -44
- package/dist/lib/http/proxy-agent.js +37 -40
- package/dist/lib/http/proxy-dispatcher.js +69 -71
- package/dist/lib/keychain/insecure.js +40 -36
- package/dist/lib/keychain/keychain.js +2 -1
- package/dist/lib/keychain/secure.js +16 -15
- package/dist/lib/keychain.js +22 -22
- package/dist/lib/live-backup-copy.js +117 -115
- package/dist/lib/logout.js +17 -19
- package/dist/lib/media-import/config.js +15 -14
- package/dist/lib/media-import/media-file-import.js +9 -13
- package/dist/lib/media-import/progress.js +53 -65
- package/dist/lib/media-import/status.js +241 -256
- package/dist/lib/media-import/utils.js +15 -15
- package/dist/lib/node-version-check.js +16 -16
- package/dist/lib/promise.js +16 -17
- package/dist/lib/read-file.js +48 -16
- package/dist/lib/rechallenge/client.js +37 -43
- package/dist/lib/rechallenge/errors.js +38 -37
- package/dist/lib/rechallenge/flow.js +148 -123
- package/dist/lib/rechallenge/index.js +23 -24
- package/dist/lib/rechallenge/link.js +153 -151
- package/dist/lib/rechallenge/open-browser.js +14 -17
- package/dist/lib/rechallenge/token-cache.js +83 -86
- package/dist/lib/rechallenge/types.js +5 -14
- package/dist/lib/retry.js +93 -129
- package/dist/lib/search-and-replace.js +164 -148
- package/dist/lib/site-import/db-file-import.js +12 -16
- package/dist/lib/site-import/status.js +291 -291
- package/dist/lib/token.js +86 -87
- package/dist/lib/tracker.js +51 -62
- package/dist/lib/types/graphql/rate-limit-exceeded-error.js +2 -1
- package/dist/lib/types.js +2 -1
- package/dist/lib/user-error.js +6 -8
- package/dist/lib/utils.js +81 -87
- package/dist/lib/validations/custom-deploy.js +218 -186
- package/dist/lib/validations/is-multi-site-sql-dump.js +6 -6
- package/dist/lib/validations/is-multi-site.js +83 -50
- package/dist/lib/validations/is-multisite-domain-mapped.js +92 -62
- package/dist/lib/validations/line-by-line.js +78 -46
- package/dist/lib/validations/site-type.js +59 -63
- package/dist/lib/validations/sql-insert-parser.js +415 -0
- package/dist/lib/validations/sql.js +551 -431
- package/dist/lib/validations/utils.js +27 -29
- package/dist/lib/vip-import-validate-files.js +481 -490
- package/dist/lib/wp/helpers.js +41 -45
- package/dist/lib/wp/readline.js +21 -57
- package/dist/lib/xdg-data.js +11 -12
- package/helpers/mark-cli-executable.js +9 -0
- package/node_modules/@apollo/client/CHANGELOG.md +10 -0
- package/node_modules/@apollo/client/__cjs/cache/inmemory/helpers.cjs +5 -0
- package/node_modules/@apollo/client/__cjs/cache/inmemory/helpers.cjs.map +1 -1
- package/node_modules/@apollo/client/__cjs/cache/inmemory/inMemoryCache.cjs +2 -1
- package/node_modules/@apollo/client/__cjs/cache/inmemory/inMemoryCache.cjs.map +1 -1
- package/node_modules/@apollo/client/__cjs/cache/inmemory/key-extractor.cjs +14 -2
- package/node_modules/@apollo/client/__cjs/cache/inmemory/key-extractor.cjs.map +1 -1
- package/node_modules/@apollo/client/__cjs/cache/inmemory/policies.cjs +16 -0
- package/node_modules/@apollo/client/__cjs/cache/inmemory/policies.cjs.map +1 -1
- package/node_modules/@apollo/client/__cjs/cache/inmemory/policies.d.cts +2 -0
- package/node_modules/@apollo/client/__cjs/cache/inmemory/writeToStore.cjs +3 -2
- package/node_modules/@apollo/client/__cjs/cache/inmemory/writeToStore.cjs.map +1 -1
- package/node_modules/@apollo/client/__cjs/core/QueryInfo.cjs +9 -1
- package/node_modules/@apollo/client/__cjs/core/QueryInfo.cjs.map +1 -1
- package/node_modules/@apollo/client/__cjs/core/QueryInfo.d.cts +1 -1
- package/node_modules/@apollo/client/__cjs/core/QueryManager.cjs +10 -3
- package/node_modules/@apollo/client/__cjs/core/QueryManager.cjs.map +1 -1
- package/node_modules/@apollo/client/__cjs/react/hooks/useFragment.cjs.map +1 -1
- package/node_modules/@apollo/client/__cjs/react/hooks/useFragment.d.cts +42 -43
- package/node_modules/@apollo/client/__cjs/version.cjs +1 -1
- package/node_modules/@apollo/client/cache/inmemory/helpers.js +5 -0
- package/node_modules/@apollo/client/cache/inmemory/helpers.js.map +1 -1
- package/node_modules/@apollo/client/cache/inmemory/inMemoryCache.js +2 -1
- package/node_modules/@apollo/client/cache/inmemory/inMemoryCache.js.map +1 -1
- package/node_modules/@apollo/client/cache/inmemory/key-extractor.js +14 -2
- package/node_modules/@apollo/client/cache/inmemory/key-extractor.js.map +1 -1
- package/node_modules/@apollo/client/cache/inmemory/policies.d.ts +2 -0
- package/node_modules/@apollo/client/cache/inmemory/policies.js +17 -1
- package/node_modules/@apollo/client/cache/inmemory/policies.js.map +1 -1
- package/node_modules/@apollo/client/cache/inmemory/writeToStore.js +3 -2
- package/node_modules/@apollo/client/cache/inmemory/writeToStore.js.map +1 -1
- package/node_modules/@apollo/client/core/QueryInfo.d.ts +1 -1
- package/node_modules/@apollo/client/core/QueryInfo.js +10 -2
- package/node_modules/@apollo/client/core/QueryInfo.js.map +1 -1
- package/node_modules/@apollo/client/core/QueryManager.js +10 -3
- package/node_modules/@apollo/client/core/QueryManager.js.map +1 -1
- package/node_modules/@apollo/client/package.json +1 -1
- package/node_modules/@apollo/client/react/hooks/useFragment.d.ts +42 -43
- package/node_modules/@apollo/client/react/hooks/useFragment.js.map +1 -1
- package/node_modules/@apollo/client/react/hooks-compiled/useFragment.d.ts +42 -43
- package/node_modules/@apollo/client/react/hooks-compiled/useFragment.js.map +1 -1
- package/node_modules/@apollo/client/version.js +1 -1
- package/node_modules/@automattic/vip-search-replace/README.md +6 -1
- package/node_modules/@automattic/vip-search-replace/lib/index.js +46 -14
- package/node_modules/@automattic/vip-search-replace/package.json +1 -1
- package/node_modules/@types/node/README.md +1 -1
- package/node_modules/@types/node/package.json +2 -2
- package/node_modules/@types/node/zlib.d.ts +752 -0
- package/node_modules/check-disk-space/README.md +92 -32
- package/node_modules/check-disk-space/dist/check-disk-space.d.mts +58 -0
- package/node_modules/check-disk-space/dist/check-disk-space.mjs +170 -190
- package/node_modules/check-disk-space/package.json +43 -71
- package/node_modules/cpu-features/build/Makefile +2 -2
- package/node_modules/cpu-features/build/Release/.deps/Release/obj.target/cpu_features/deps/cpu_features/src/filesystem.o.d +1 -1
- package/node_modules/cpu-features/build/Release/.deps/Release/obj.target/cpu_features/deps/cpu_features/src/impl_aarch64_linux_or_android.o.d +1 -1
- package/node_modules/cpu-features/build/Release/.deps/Release/obj.target/cpu_features/deps/cpu_features/src/impl_aarch64_macos_or_iphone.o.d +1 -1
- package/node_modules/cpu-features/build/Release/.deps/Release/obj.target/cpu_features/deps/cpu_features/src/impl_aarch64_windows.o.d +1 -1
- package/node_modules/cpu-features/build/Release/.deps/Release/obj.target/cpu_features/deps/cpu_features/src/impl_arm_linux_or_android.o.d +1 -1
- package/node_modules/cpu-features/build/Release/.deps/Release/obj.target/cpu_features/deps/cpu_features/src/impl_mips_linux_or_android.o.d +1 -1
- package/node_modules/cpu-features/build/Release/.deps/Release/obj.target/cpu_features/deps/cpu_features/src/impl_ppc_linux.o.d +1 -1
- package/node_modules/cpu-features/build/Release/.deps/Release/obj.target/cpu_features/deps/cpu_features/src/impl_x86_freebsd.o.d +1 -1
- package/node_modules/cpu-features/build/Release/.deps/Release/obj.target/cpu_features/deps/cpu_features/src/impl_x86_linux_or_android.o.d +1 -1
- package/node_modules/cpu-features/build/Release/.deps/Release/obj.target/cpu_features/deps/cpu_features/src/impl_x86_macos.o.d +1 -1
- package/node_modules/cpu-features/build/Release/.deps/Release/obj.target/cpu_features/deps/cpu_features/src/impl_x86_windows.o.d +1 -1
- package/node_modules/cpu-features/build/Release/.deps/Release/obj.target/cpu_features/deps/cpu_features/src/stack_line_reader.o.d +1 -1
- package/node_modules/cpu-features/build/Release/.deps/Release/obj.target/cpu_features/deps/cpu_features/src/string_view.o.d +1 -1
- package/node_modules/cpu-features/build/Release/.deps/Release/obj.target/cpufeatures/src/binding.o.d +157 -145
- package/node_modules/cpu-features/build/Release/cpufeatures.node +0 -0
- package/node_modules/cpu-features/build/Release/obj.target/cpufeatures/src/binding.o +0 -0
- package/node_modules/cpu-features/build/Release/obj.target/cpufeatures.node +0 -0
- package/node_modules/cpu-features/build/config.gypi +100 -31
- package/node_modules/cpu-features/build/cpufeatures.target.mk +14 -14
- package/node_modules/cpu-features/build/deps/cpu_features/cpu_features.target.mk +14 -14
- package/node_modules/ssh2/lib/protocol/crypto/build/Makefile +2 -2
- package/node_modules/ssh2/lib/protocol/crypto/build/Release/.deps/Release/obj.target/sshcrypto/src/binding.o.d.raw +136 -0
- package/node_modules/ssh2/lib/protocol/crypto/build/sshcrypto.target.mk +14 -14
- package/node_modules/undici/docs/docs/api/Interceptors.md +15 -2
- package/node_modules/undici/lib/dispatcher/client-h2.js +78 -3
- package/node_modules/undici/lib/dispatcher/pool-base.js +20 -3
- package/node_modules/undici/package.json +3 -3
- package/node_modules/undici/types/api.d.ts +1 -1
- package/node_modules/undici/types/utility.d.ts +4 -4
- package/package.json +44 -13
- package/dist/lib/analytics/clients/client.js +0 -1
- package/dist/lib/analytics/clients/pendo.js +0 -78
- package/helpers/check-version.js +0 -16
- package/node_modules/check-disk-space/dist/check-disk-space.cjs +0 -210
- package/node_modules/check-disk-space/dist/check-disk-space.d.ts +0 -53
- package/node_modules/fetch-retry/.eslintignore +0 -1
- package/node_modules/fetch-retry/.eslintrc.yml +0 -20
- package/node_modules/fetch-retry/.github/workflows/node.js.yml +0 -32
- package/node_modules/fetch-retry/.husky/pre-commit +0 -6
- package/node_modules/fetch-retry/.nycrc.json +0 -24
- package/node_modules/fetch-retry/.travis.yml +0 -3
- package/node_modules/fetch-retry/LICENSE +0 -21
- package/node_modules/fetch-retry/README.md +0 -128
- package/node_modules/fetch-retry/dist/fetch-retry.umd.js +0 -151
- package/node_modules/fetch-retry/index.d.ts +0 -29
- package/node_modules/fetch-retry/index.js +0 -143
- package/node_modules/fetch-retry/package.json +0 -41
- package/node_modules/fetch-retry/rollup.config.js +0 -12
- package/node_modules/fetch-retry/test/.eslintrc.yml +0 -7
- package/node_modules/fetch-retry/test/integration/index.js +0 -212
- package/node_modules/fetch-retry/test/integration/mock-api/index.js +0 -42
- package/node_modules/fetch-retry/test/unit/index.js +0 -1169
- package/node_modules/ssh2/lib/protocol/crypto/build/Release/.deps/Release/obj.target/sshcrypto/src/binding.o.d +0 -265
- package/node_modules/ssh2/lib/protocol/crypto/build/Release/.deps/Release/obj.target/sshcrypto.node.d +0 -1
- package/node_modules/ssh2/lib/protocol/crypto/build/Release/.deps/Release/sshcrypto.node.d +0 -1
- package/node_modules/ssh2/lib/protocol/crypto/build/Release/obj.target/sshcrypto/src/binding.o +0 -0
- package/node_modules/ssh2/lib/protocol/crypto/build/Release/obj.target/sshcrypto.node +0 -0
- package/node_modules/ssh2/lib/protocol/crypto/build/Release/sshcrypto.node +0 -0
|
@@ -1,155 +1,183 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.summaryLogs = exports.logErrors = exports.doesImageHaveExistingSource = exports.isFileSanitized = exports.folderStructureValidation = exports.findNestedDirectories = exports.isDirectory = exports.ValidateFilesErrors = void 0;
|
|
5
7
|
exports.validateFiles = validateFiles;
|
|
6
|
-
var _chalk = _interopRequireDefault(require("chalk"));
|
|
7
|
-
var _fs = _interopRequireDefault(require("fs"));
|
|
8
|
-
var _path = _interopRequireDefault(require("path"));
|
|
9
|
-
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
10
8
|
/**
|
|
11
9
|
* External dependencies
|
|
12
10
|
*/
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
}({});
|
|
11
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
12
|
+
const fs_1 = __importDefault(require("fs"));
|
|
13
|
+
const path_1 = __importDefault(require("path"));
|
|
14
|
+
var ValidateFilesErrors;
|
|
15
|
+
(function (ValidateFilesErrors) {
|
|
16
|
+
ValidateFilesErrors["INVALID_TYPES"] = "invalid_types";
|
|
17
|
+
ValidateFilesErrors["INTERMEDIATE_IMAGES"] = "intermediate_images";
|
|
18
|
+
ValidateFilesErrors["INVALID_SIZES"] = "invalid_sizes";
|
|
19
|
+
ValidateFilesErrors["INVALID_NAMES"] = "invalid_names";
|
|
20
|
+
ValidateFilesErrors["INVALID_NAME_CHARACTER_COUNTS"] = "invalid_name_character_counts";
|
|
21
|
+
})(ValidateFilesErrors || (exports.ValidateFilesErrors = ValidateFilesErrors = {}));
|
|
24
22
|
/**
|
|
25
23
|
* File info validation
|
|
26
24
|
*
|
|
27
25
|
* Validate the file info for media files
|
|
28
26
|
*/
|
|
29
27
|
async function validateFiles(files, mediaImportConfig) {
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
28
|
+
const validationResult = {
|
|
29
|
+
intermediateImagesTotal: 0,
|
|
30
|
+
errorFileTypes: [],
|
|
31
|
+
errorFileNames: [],
|
|
32
|
+
errorFileSizes: [],
|
|
33
|
+
errorFileNamesCharCount: [],
|
|
34
|
+
intermediateImages: {},
|
|
35
|
+
};
|
|
36
|
+
const fileValidationPromises = files.map(async (file) => {
|
|
37
|
+
const isFolder = await (0, exports.isDirectory)(file);
|
|
38
|
+
const fileExtType = getFileExtType(file, mediaImportConfig.allowedFileTypes);
|
|
39
|
+
if (isInvalidFile(fileExtType, isFolder)) {
|
|
40
|
+
validationResult.errorFileTypes.push(file);
|
|
41
|
+
}
|
|
42
|
+
if (!isFileSizeValid(file, mediaImportConfig.fileSizeLimitInBytes)) {
|
|
43
|
+
validationResult.errorFileSizes.push(file);
|
|
44
|
+
}
|
|
45
|
+
if ((0, exports.isFileSanitized)(file)) {
|
|
46
|
+
validationResult.errorFileNames.push(file);
|
|
47
|
+
}
|
|
48
|
+
if (!isFileNameCharCountValid(file, mediaImportConfig?.fileNameCharCount)) {
|
|
49
|
+
validationResult.errorFileNamesCharCount.push(file);
|
|
50
|
+
}
|
|
51
|
+
const original = (0, exports.doesImageHaveExistingSource)(file);
|
|
52
|
+
if (original) {
|
|
53
|
+
validationResult.intermediateImagesTotal++;
|
|
54
|
+
if (validationResult.intermediateImages[original]) {
|
|
55
|
+
validationResult.intermediateImages[original] += `, ${file}`;
|
|
56
|
+
}
|
|
57
|
+
else {
|
|
58
|
+
validationResult.intermediateImages[original] = file;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
});
|
|
62
|
+
await Promise.all(fileValidationPromises);
|
|
63
|
+
return validationResult;
|
|
65
64
|
}
|
|
66
|
-
const isDirectory = async file => {
|
|
67
|
-
|
|
68
|
-
|
|
65
|
+
const isDirectory = async (file) => {
|
|
66
|
+
const stats = await fs_1.default.promises.stat(file);
|
|
67
|
+
return stats.isDirectory();
|
|
69
68
|
};
|
|
70
69
|
exports.isDirectory = isDirectory;
|
|
71
70
|
const getFileExtType = (file, allowedFileTypes) => {
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
};
|
|
76
|
-
return getExtAndType(file, allowedFileTypes);
|
|
71
|
+
if (!allowedFileTypes)
|
|
72
|
+
return { ext: null, type: null };
|
|
73
|
+
return getExtAndType(file, allowedFileTypes);
|
|
77
74
|
};
|
|
78
75
|
const isInvalidFile = (fileExtType, isFolder) => {
|
|
79
|
-
|
|
76
|
+
return !fileExtType.type || !fileExtType.ext || isFolder;
|
|
80
77
|
};
|
|
81
78
|
const getExtAndType = (filePath, allowedFileTypes) => {
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
return extType;
|
|
79
|
+
const extType = { ext: null, type: null };
|
|
80
|
+
for (const [key, value] of Object.entries(allowedFileTypes)) {
|
|
81
|
+
// Create a regular expression to match the file extension
|
|
82
|
+
// eslint-disable-next-line security/detect-non-literal-regexp
|
|
83
|
+
const regex = new RegExp(`(?:\\.)(${key})$`, 'i');
|
|
84
|
+
const matches = regex.exec(filePath);
|
|
85
|
+
if (matches) {
|
|
86
|
+
extType.type = value;
|
|
87
|
+
extType.ext = matches[1];
|
|
88
|
+
break;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
return extType;
|
|
98
92
|
};
|
|
99
93
|
const isFileSizeValid = (filePathOnDisk, fileSizeLimitInBytes) => {
|
|
100
|
-
|
|
101
|
-
|
|
94
|
+
const fileStat = fs_1.default.statSync(filePathOnDisk);
|
|
95
|
+
return fileSizeLimitInBytes >= fileStat.size;
|
|
102
96
|
};
|
|
103
97
|
const isFileNameCharCountValid = (file, fileNameCharCount) => {
|
|
104
|
-
|
|
105
|
-
|
|
98
|
+
const filename = path_1.default.basename(file);
|
|
99
|
+
return filename.length <= fileNameCharCount;
|
|
106
100
|
};
|
|
107
|
-
|
|
108
101
|
/**
|
|
109
102
|
* End file info validation
|
|
110
103
|
*/
|
|
111
|
-
|
|
112
104
|
/**
|
|
113
105
|
* Character validation global variables
|
|
114
106
|
*
|
|
115
107
|
* Accepted and prohibited characters for filenames
|
|
116
108
|
*/
|
|
117
|
-
|
|
118
109
|
// Accepted characters in filenames
|
|
119
|
-
|
|
120
|
-
|
|
110
|
+
const acceptedCharacters = [
|
|
111
|
+
'Non-English characters',
|
|
112
|
+
'(',
|
|
113
|
+
')',
|
|
114
|
+
'[',
|
|
115
|
+
']',
|
|
116
|
+
'~',
|
|
117
|
+
'&',
|
|
118
|
+
'#',
|
|
119
|
+
'%',
|
|
120
|
+
'=',
|
|
121
|
+
'’',
|
|
122
|
+
`'`,
|
|
123
|
+
'×',
|
|
124
|
+
'@',
|
|
125
|
+
'`',
|
|
126
|
+
'?',
|
|
127
|
+
'*',
|
|
128
|
+
'!',
|
|
129
|
+
'"',
|
|
130
|
+
'\\',
|
|
131
|
+
'<',
|
|
132
|
+
'>',
|
|
133
|
+
':',
|
|
134
|
+
';',
|
|
135
|
+
',',
|
|
136
|
+
'/',
|
|
137
|
+
'$',
|
|
138
|
+
'|',
|
|
139
|
+
'`',
|
|
140
|
+
'{',
|
|
141
|
+
'}',
|
|
142
|
+
'spaces',
|
|
143
|
+
];
|
|
121
144
|
const acceptedCharactersSet = new Set(acceptedCharacters); // Prevent duplicates with a Set
|
|
122
|
-
|
|
123
145
|
// Prohibited characters in filenames
|
|
124
146
|
const prohibitedCharacters = ['+', '%20'];
|
|
125
147
|
const prohibitedCharactersSet = new Set(prohibitedCharacters);
|
|
126
|
-
|
|
127
148
|
/**
|
|
128
149
|
* Recommendations
|
|
129
150
|
*
|
|
130
151
|
* Recommend alternatives to invalid folders or files
|
|
131
152
|
*/
|
|
132
|
-
|
|
133
153
|
// Recommend the WordPress year/month file structure for media files
|
|
134
154
|
const recommendedFileStructure = () => {
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
155
|
+
console.log(chalk_1.default.underline('We recommend the WordPress default folder structure for your media files: \n\n') +
|
|
156
|
+
chalk_1.default.underline('Single sites:') +
|
|
157
|
+
chalk_1.default.yellow('`uploads/year/month/image.png`\n') +
|
|
158
|
+
' e.g.-' +
|
|
159
|
+
chalk_1.default.yellow('`uploads/2020/06/image.png`\n') +
|
|
160
|
+
chalk_1.default.underline('Multisites:') +
|
|
161
|
+
chalk_1.default.cyan('`uploads/sites/siteID/year/month/image.png`\n') +
|
|
162
|
+
' e.g.-' +
|
|
163
|
+
chalk_1.default.cyan('`uploads/sites/5/2020/06/images.png`\n'));
|
|
164
|
+
console.log('------------------------------------------------------------');
|
|
165
|
+
console.log();
|
|
138
166
|
};
|
|
139
|
-
|
|
140
167
|
// Recommend accepted file types
|
|
141
|
-
const recommendAcceptableFileTypes = allowedFileTypesString => {
|
|
142
|
-
|
|
143
|
-
|
|
168
|
+
const recommendAcceptableFileTypes = (allowedFileTypesString) => {
|
|
169
|
+
console.log('Accepted file types: \n\n' + chalk_1.default.magenta(`${allowedFileTypesString}`));
|
|
170
|
+
console.log();
|
|
144
171
|
};
|
|
145
|
-
|
|
146
172
|
// Accepted file name characters
|
|
147
173
|
const recommendAcceptableFileNames = () => {
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
174
|
+
const allowedCharacters = [...acceptedCharactersSet].join(' ');
|
|
175
|
+
const notAllowedCharacters = [...prohibitedCharactersSet].join(' ');
|
|
176
|
+
console.log('The following characters are allowed in file names:\n' +
|
|
177
|
+
chalk_1.default.green(`All special characters, including: ${allowedCharacters}\n\n`) +
|
|
178
|
+
'The following characters are prohibited in file names:\n' +
|
|
179
|
+
chalk_1.default.red(`Encoded or alternate whitespace, such as ${notAllowedCharacters}, are converted to proper spaces\n`));
|
|
151
180
|
};
|
|
152
|
-
|
|
153
181
|
/**
|
|
154
182
|
* Nested Directory Search
|
|
155
183
|
*
|
|
@@ -165,133 +193,107 @@ const recommendAcceptableFileNames = () => {
|
|
|
165
193
|
*/
|
|
166
194
|
const files = [];
|
|
167
195
|
const folderStructureObj = {};
|
|
168
|
-
const findNestedDirectories = directory => {
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
return {
|
|
198
|
-
files,
|
|
199
|
-
folderStructureObj
|
|
200
|
-
};
|
|
196
|
+
const findNestedDirectories = (directory) => {
|
|
197
|
+
let nestedDirectories;
|
|
198
|
+
try {
|
|
199
|
+
// Read nested directories within the given directory
|
|
200
|
+
nestedDirectories = fs_1.default.readdirSync(directory);
|
|
201
|
+
// Filter out hidden files such as .DS_Store
|
|
202
|
+
nestedDirectories = nestedDirectories.filter(file => !/(^|\/)\.[^/.]/g.test(file));
|
|
203
|
+
nestedDirectories.forEach(dir => {
|
|
204
|
+
// Concatenate the file path of the parent directory with the nested directory
|
|
205
|
+
const filePath = path_1.default.join(directory, dir);
|
|
206
|
+
const statSync = fs_1.default.statSync(filePath); // Get stats on the file/folder
|
|
207
|
+
// Keep looking for nested directories until we hit individual files
|
|
208
|
+
if (statSync.isDirectory()) {
|
|
209
|
+
(0, exports.findNestedDirectories)(filePath);
|
|
210
|
+
}
|
|
211
|
+
else {
|
|
212
|
+
// Once we hit media files, add the path of all existing folders
|
|
213
|
+
// as object keys to validate folder structure later on
|
|
214
|
+
folderStructureObj[directory] = true;
|
|
215
|
+
// Also, push individual files to an array to do individual file validations later on
|
|
216
|
+
return files.push(filePath);
|
|
217
|
+
}
|
|
218
|
+
});
|
|
219
|
+
}
|
|
220
|
+
catch (error) {
|
|
221
|
+
console.error(chalk_1.default.red('✕'), ` Error: Cannot read nested directory: ${directory}. Reason: ${error.message}`);
|
|
222
|
+
return;
|
|
223
|
+
}
|
|
224
|
+
return { files, folderStructureObj };
|
|
201
225
|
};
|
|
202
|
-
|
|
203
|
-
/**
|
|
204
|
-
* Folder structure validation
|
|
205
|
-
*
|
|
206
|
-
* Identify the index position of each directory to validate the folder structure
|
|
207
|
-
*
|
|
208
|
-
* @param {string} folderPath Path of the entire folder structure
|
|
209
|
-
* @param {boolean} sites Check if site is a multisite or single site
|
|
210
|
-
* @return {Object} indexes
|
|
211
|
-
*/
|
|
212
226
|
exports.findNestedDirectories = findNestedDirectories;
|
|
213
227
|
function getIndexPositionOfFolders(folderPath, sites = false) {
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
if (sites) {
|
|
228
|
+
let sitesIndex;
|
|
229
|
+
let siteIDIndex;
|
|
230
|
+
let yearIndex;
|
|
231
|
+
let monthIndex;
|
|
232
|
+
let pathMutate = folderPath; // Mutate `path` for multisites
|
|
233
|
+
// Turn the path into an array to determine index position
|
|
234
|
+
const directories = pathMutate.split('/');
|
|
235
|
+
/**
|
|
236
|
+
* Upload folder
|
|
237
|
+
*
|
|
238
|
+
* Find if an `uploads` folder exists and return its index position
|
|
239
|
+
*/
|
|
240
|
+
const uploadsIndex = directories.indexOf('uploads');
|
|
241
|
+
/**
|
|
242
|
+
* Multisite folder
|
|
243
|
+
*
|
|
244
|
+
* If a sites directory exists, find the directory and return its index position
|
|
245
|
+
* Find if a siteID folder exists via regex, then obtain that value
|
|
246
|
+
*/
|
|
247
|
+
if (sites) {
|
|
248
|
+
sitesIndex = directories.indexOf('sites');
|
|
249
|
+
const regexSiteID = /\/sites\/(\d+)/g;
|
|
250
|
+
const siteID = regexSiteID.exec(pathMutate); // Returns an array with the regex-matching value
|
|
251
|
+
if (siteID) {
|
|
252
|
+
siteIDIndex = directories.indexOf(siteID[1]);
|
|
253
|
+
// Remove the multisite-specific path to avoid confusing a 2 digit site ID with the month
|
|
254
|
+
// e.g.- `uploads/sites/11/2020/06` -> `uploads/2020/06`
|
|
255
|
+
pathMutate = pathMutate.replace(siteID[0], '');
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
/**
|
|
259
|
+
* Year folder
|
|
260
|
+
*
|
|
261
|
+
* Find if a year folder exists via a four digit regex matching pattern,
|
|
262
|
+
* then obtain that value
|
|
263
|
+
*/
|
|
264
|
+
const regexYear = /\b\d{4}\b/g;
|
|
265
|
+
const year = regexYear.exec(pathMutate); // Returns an array with the regex-matching value
|
|
266
|
+
if (year) {
|
|
267
|
+
yearIndex = directories.indexOf(year[0]);
|
|
268
|
+
}
|
|
269
|
+
/**
|
|
270
|
+
* Month folder
|
|
271
|
+
*
|
|
272
|
+
* Find if a month folder exists via a two digit regex matching pattern,
|
|
273
|
+
* then obtain that value
|
|
274
|
+
*/
|
|
275
|
+
const regexMonth = /\b\d{2}\b/g;
|
|
276
|
+
const month = regexMonth.exec(pathMutate); // Returns an array with the regex-matching value
|
|
277
|
+
if (month) {
|
|
278
|
+
monthIndex = directories.indexOf(month[0]);
|
|
279
|
+
}
|
|
280
|
+
// Multisite
|
|
281
|
+
if (sites) {
|
|
282
|
+
return {
|
|
283
|
+
uploadsIndex,
|
|
284
|
+
sitesIndex,
|
|
285
|
+
siteIDIndex,
|
|
286
|
+
yearIndex,
|
|
287
|
+
monthIndex,
|
|
288
|
+
};
|
|
289
|
+
}
|
|
290
|
+
// Single site
|
|
278
291
|
return {
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
yearIndex,
|
|
283
|
-
monthIndex
|
|
292
|
+
uploadsIndex,
|
|
293
|
+
yearIndex,
|
|
294
|
+
monthIndex,
|
|
284
295
|
};
|
|
285
|
-
}
|
|
286
|
-
|
|
287
|
-
// Single site
|
|
288
|
-
return {
|
|
289
|
-
uploadsIndex,
|
|
290
|
-
yearIndex,
|
|
291
|
-
monthIndex
|
|
292
|
-
};
|
|
293
296
|
}
|
|
294
|
-
|
|
295
297
|
/**
|
|
296
298
|
* Single site folder structure validation
|
|
297
299
|
*
|
|
@@ -304,57 +306,48 @@ function getIndexPositionOfFolders(folderPath, sites = false) {
|
|
|
304
306
|
* @param {string} folderPath Path of the entire folder structure
|
|
305
307
|
* @return {string|null} Returns null if the folder structure is good; else, returns the folder path
|
|
306
308
|
*/
|
|
307
|
-
const singleSiteValidation = folderPath => {
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
errors++;
|
|
349
|
-
}
|
|
350
|
-
|
|
351
|
-
// Push individual folder errors to the collective array of errors
|
|
352
|
-
if (errors > 0) {
|
|
353
|
-
return folderPath;
|
|
354
|
-
}
|
|
355
|
-
return null;
|
|
309
|
+
const singleSiteValidation = (folderPath) => {
|
|
310
|
+
let errors = 0; // Tally individual folder errors
|
|
311
|
+
console.log(chalk_1.default.bold('Folder:'), chalk_1.default.cyan(`${folderPath}`));
|
|
312
|
+
// Use destructuring to retrieve the index position of each folder
|
|
313
|
+
const { uploadsIndex, yearIndex, monthIndex } = getIndexPositionOfFolders(folderPath);
|
|
314
|
+
/**
|
|
315
|
+
* Logging
|
|
316
|
+
*/
|
|
317
|
+
// Uploads folder
|
|
318
|
+
if (uploadsIndex === 0) {
|
|
319
|
+
console.log();
|
|
320
|
+
console.log('✅ File structure: Uploads directory exists');
|
|
321
|
+
}
|
|
322
|
+
else {
|
|
323
|
+
console.log();
|
|
324
|
+
console.log(chalk_1.default.yellow('✕'), 'Recommended: Media files should reside in an', chalk_1.default.magenta('`uploads`'), 'directory');
|
|
325
|
+
errors++;
|
|
326
|
+
}
|
|
327
|
+
// Year folder
|
|
328
|
+
if (yearIndex && yearIndex === 1) {
|
|
329
|
+
console.log('✅ File structure: Year directory exists (format: YYYY)');
|
|
330
|
+
}
|
|
331
|
+
else {
|
|
332
|
+
console.log(chalk_1.default.yellow('✕'), 'Recommended: Structure your WordPress media files into', chalk_1.default.magenta('`uploads/YYYY`'), 'directories');
|
|
333
|
+
errors++;
|
|
334
|
+
}
|
|
335
|
+
// Month folder
|
|
336
|
+
if (monthIndex && monthIndex === 2) {
|
|
337
|
+
console.log('✅ File structure: Month directory exists (format: MM)');
|
|
338
|
+
console.log();
|
|
339
|
+
}
|
|
340
|
+
else {
|
|
341
|
+
console.log(chalk_1.default.yellow('✕'), 'Recommended: Structure your WordPress media files into', chalk_1.default.magenta('`uploads/YYYY/MM`'), 'directories');
|
|
342
|
+
console.log();
|
|
343
|
+
errors++;
|
|
344
|
+
}
|
|
345
|
+
// Push individual folder errors to the collective array of errors
|
|
346
|
+
if (errors > 0) {
|
|
347
|
+
return folderPath;
|
|
348
|
+
}
|
|
349
|
+
return null;
|
|
356
350
|
};
|
|
357
|
-
|
|
358
351
|
/**
|
|
359
352
|
* Multisite folder structure validation
|
|
360
353
|
*
|
|
@@ -368,76 +361,65 @@ const singleSiteValidation = folderPath => {
|
|
|
368
361
|
* @param {string} folderPath Path of the entire folder structure
|
|
369
362
|
* @return {string|null} Returns null if the folder structure is good; else, returns the folder path
|
|
370
363
|
*/
|
|
371
|
-
const multiSiteValidation = folderPath => {
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
console.log(_chalk.default.yellow('✕'), 'Recommended: Structure your WordPress media files into', _chalk.default.magenta('`uploads/sites/<siteID>/YYYY/MM`'), 'directories');
|
|
430
|
-
console.log();
|
|
431
|
-
errors++;
|
|
432
|
-
}
|
|
433
|
-
|
|
434
|
-
// Push individual folder errors to the collective array of errors
|
|
435
|
-
if (errors > 0) {
|
|
436
|
-
return folderPath;
|
|
437
|
-
}
|
|
438
|
-
return null;
|
|
364
|
+
const multiSiteValidation = (folderPath) => {
|
|
365
|
+
let errors = 0; // Tally individual folder errors
|
|
366
|
+
console.log(chalk_1.default.bold('Folder:'), chalk_1.default.cyan(`${folderPath}`));
|
|
367
|
+
// Use destructuring to retrieve the index position of each folder
|
|
368
|
+
const { uploadsIndex, sitesIndex, siteIDIndex, yearIndex, monthIndex } = getIndexPositionOfFolders(folderPath, true);
|
|
369
|
+
/**
|
|
370
|
+
* Logging
|
|
371
|
+
*/
|
|
372
|
+
// Uploads folder
|
|
373
|
+
if (uploadsIndex === 0) {
|
|
374
|
+
console.log();
|
|
375
|
+
console.log('✅ File structure: Uploads directory exists');
|
|
376
|
+
}
|
|
377
|
+
else {
|
|
378
|
+
console.log();
|
|
379
|
+
console.log(chalk_1.default.yellow('✕'), 'Recommended: Media files should reside in an', chalk_1.default.magenta('`uploads`'), 'directory');
|
|
380
|
+
errors++;
|
|
381
|
+
}
|
|
382
|
+
// Sites folder
|
|
383
|
+
if (sitesIndex === 1) {
|
|
384
|
+
console.log('✅ File structure: Sites directory exists');
|
|
385
|
+
}
|
|
386
|
+
else {
|
|
387
|
+
console.log();
|
|
388
|
+
console.log(chalk_1.default.yellow('✕'), 'Recommended: Media files should reside in an', chalk_1.default.magenta('`sites`'), 'directory');
|
|
389
|
+
errors++;
|
|
390
|
+
}
|
|
391
|
+
// Site ID folder
|
|
392
|
+
if (siteIDIndex && siteIDIndex === 2) {
|
|
393
|
+
console.log('✅ File structure: Site ID directory exists');
|
|
394
|
+
}
|
|
395
|
+
else {
|
|
396
|
+
console.log(chalk_1.default.yellow('✕'), 'Recommended: Structure your WordPress media files into', chalk_1.default.magenta('`uploads/sites/<siteID>`'), 'directories');
|
|
397
|
+
errors++;
|
|
398
|
+
}
|
|
399
|
+
// Year folder
|
|
400
|
+
if (yearIndex && yearIndex === 3) {
|
|
401
|
+
console.log('✅ File structure: Year directory exists (format: YYYY)');
|
|
402
|
+
}
|
|
403
|
+
else {
|
|
404
|
+
console.log(chalk_1.default.yellow('✕'), 'Recommended: Structure your WordPress media files into', chalk_1.default.magenta('`uploads/sites/<siteID>/YYYY`'), 'directories');
|
|
405
|
+
errors++;
|
|
406
|
+
}
|
|
407
|
+
// Month folder
|
|
408
|
+
if (monthIndex && monthIndex === 4) {
|
|
409
|
+
console.log('✅ File structure: Month directory exists (format: MM)');
|
|
410
|
+
console.log();
|
|
411
|
+
}
|
|
412
|
+
else {
|
|
413
|
+
console.log(chalk_1.default.yellow('✕'), 'Recommended: Structure your WordPress media files into', chalk_1.default.magenta('`uploads/sites/<siteID>/YYYY/MM`'), 'directories');
|
|
414
|
+
console.log();
|
|
415
|
+
errors++;
|
|
416
|
+
}
|
|
417
|
+
// Push individual folder errors to the collective array of errors
|
|
418
|
+
if (errors > 0) {
|
|
419
|
+
return folderPath;
|
|
420
|
+
}
|
|
421
|
+
return null;
|
|
439
422
|
};
|
|
440
|
-
|
|
441
423
|
/**
|
|
442
424
|
* Folder structure validation
|
|
443
425
|
*
|
|
@@ -446,32 +428,31 @@ const multiSiteValidation = folderPath => {
|
|
|
446
428
|
* @param {Array} folderStructureKeys Array of paths for each folder
|
|
447
429
|
* @return {Array} All the erroneous folder paths in an array
|
|
448
430
|
*/
|
|
449
|
-
const folderStructureValidation = folderStructureKeys => {
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
}
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
return allErrors;
|
|
431
|
+
const folderStructureValidation = (folderStructureKeys) => {
|
|
432
|
+
// Collect all the folder paths that aren't in the recommended structure
|
|
433
|
+
const allErrors = [];
|
|
434
|
+
// Loop through each path to validate the folder structure format
|
|
435
|
+
for (const folderPath of folderStructureKeys) {
|
|
436
|
+
let badFolders;
|
|
437
|
+
// Check for multisite folder structure
|
|
438
|
+
if (folderPath.search('sites') !== -1) {
|
|
439
|
+
// Returns null if the folder path is good, otherwise it returns the folder path itself
|
|
440
|
+
badFolders = multiSiteValidation(folderPath);
|
|
441
|
+
}
|
|
442
|
+
else {
|
|
443
|
+
// Returns null if the folder path is good, otherwise it returns the folder path itself
|
|
444
|
+
badFolders = singleSiteValidation(folderPath);
|
|
445
|
+
}
|
|
446
|
+
if (badFolders) {
|
|
447
|
+
allErrors.push(badFolders);
|
|
448
|
+
}
|
|
449
|
+
}
|
|
450
|
+
if (allErrors.length > 0) {
|
|
451
|
+
recommendedFileStructure();
|
|
452
|
+
}
|
|
453
|
+
return allErrors;
|
|
473
454
|
};
|
|
474
|
-
|
|
455
|
+
exports.folderStructureValidation = folderStructureValidation;
|
|
475
456
|
/**
|
|
476
457
|
* Character validation
|
|
477
458
|
*
|
|
@@ -481,21 +462,17 @@ const folderStructureValidation = folderStructureKeys => {
|
|
|
481
462
|
* @param {string} file - The current file being validated
|
|
482
463
|
* @return {boolean} - Checks if the filename has been sanitized
|
|
483
464
|
*/
|
|
484
|
-
|
|
485
|
-
const
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
// Check if the filename has been sanitized
|
|
495
|
-
|
|
496
|
-
return sanitizedFile !== filename;
|
|
465
|
+
const isFileSanitized = (file) => {
|
|
466
|
+
const filename = path_1.default.basename(file);
|
|
467
|
+
let sanitizedFile = filename;
|
|
468
|
+
// Convert encoded or alternate whitespace into a proper space
|
|
469
|
+
// Encoded spaces (%20), no-break spaces - keeps words together (\u00A0), and plus signs
|
|
470
|
+
const regexSpaces = /\u00A0|(%20)|\+/g;
|
|
471
|
+
sanitizedFile = sanitizedFile.replace(regexSpaces, ' ');
|
|
472
|
+
// Check if the filename has been sanitized
|
|
473
|
+
return sanitizedFile !== filename;
|
|
497
474
|
};
|
|
498
|
-
|
|
475
|
+
exports.isFileSanitized = isFileSanitized;
|
|
499
476
|
/**
|
|
500
477
|
* Intermediate image validation
|
|
501
478
|
*
|
|
@@ -510,123 +487,137 @@ const isFileSanitized = file => {
|
|
|
510
487
|
* @param {string} filename The current file being validated
|
|
511
488
|
* @return {Array} Returns an array of the matching regex characters
|
|
512
489
|
*/
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
return filename.match(regex); // NOSONAR
|
|
490
|
+
const identifyIntermediateImage = (filename) => {
|
|
491
|
+
// eslint-disable-next-line security/detect-unsafe-regex
|
|
492
|
+
const regex = /([_-])?(\d+x\d+)(@\d+\w)?(\.\w{3,4})$/;
|
|
493
|
+
return filename.match(regex); // NOSONAR
|
|
518
494
|
};
|
|
519
|
-
|
|
520
495
|
// Check if an intermediate image has an existing original (source) image
|
|
521
|
-
const doesImageHaveExistingSource = file => {
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
return originalImage;
|
|
542
|
-
}
|
|
543
|
-
}
|
|
544
|
-
return false;
|
|
496
|
+
const doesImageHaveExistingSource = (file) => {
|
|
497
|
+
const filename = path_1.default.basename(file);
|
|
498
|
+
// Intermediate image regex check
|
|
499
|
+
const intermediateImage = identifyIntermediateImage(filename);
|
|
500
|
+
if (null !== intermediateImage) {
|
|
501
|
+
const imageSizing = intermediateImage[0]; // First capture group of the regex validation
|
|
502
|
+
const extension = path_1.default.extname(filename).slice(1); // Extension of the path (e.g.- `.jpg`)
|
|
503
|
+
// Filename manipulation: if an image is an intermediate image, strip away the image sizing
|
|
504
|
+
// e.g.- `panda4000x6000.png` -> `panda.png`
|
|
505
|
+
const baseFileName = filename.replace(imageSizing, '') + '.' + extension;
|
|
506
|
+
const splitFolder = file.split('/');
|
|
507
|
+
// Remove the last element (intermediate image filename) and replace it with the original image filename
|
|
508
|
+
splitFolder.splice(splitFolder.length - 1, 1, baseFileName);
|
|
509
|
+
const originalImage = splitFolder.join('/');
|
|
510
|
+
// Check if an image with the same path + name (the original) already exists
|
|
511
|
+
if (fs_1.default.existsSync(originalImage)) {
|
|
512
|
+
return originalImage;
|
|
513
|
+
}
|
|
514
|
+
}
|
|
515
|
+
return false;
|
|
545
516
|
};
|
|
546
|
-
|
|
517
|
+
exports.doesImageHaveExistingSource = doesImageHaveExistingSource;
|
|
547
518
|
/**
|
|
548
519
|
* Error logging
|
|
549
520
|
*
|
|
550
521
|
* Log errors for invalid folders or files
|
|
551
522
|
*/
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
}
|
|
585
|
-
|
|
586
|
-
console.log();
|
|
523
|
+
const logErrors = ({ errorType, invalidFiles, limit }) => {
|
|
524
|
+
if (invalidFiles.length === 0) {
|
|
525
|
+
return;
|
|
526
|
+
}
|
|
527
|
+
invalidFiles.forEach(file => {
|
|
528
|
+
switch (errorType) {
|
|
529
|
+
case ValidateFilesErrors.INVALID_TYPES:
|
|
530
|
+
console.error(chalk_1.default.red('✕'), 'File extensions: Invalid file type for file: ', chalk_1.default.cyan(`${file}`));
|
|
531
|
+
console.log();
|
|
532
|
+
recommendAcceptableFileTypes(limit);
|
|
533
|
+
break;
|
|
534
|
+
case ValidateFilesErrors.INTERMEDIATE_IMAGES:
|
|
535
|
+
console.error(chalk_1.default.red('✕'), 'Intermediate images: Duplicate files found:\n' +
|
|
536
|
+
'Original file: ' +
|
|
537
|
+
chalk_1.default.blue(`${file}\n`) +
|
|
538
|
+
'Intermediate images: ' +
|
|
539
|
+
chalk_1.default.cyan(`${limit[file]}\n`));
|
|
540
|
+
break;
|
|
541
|
+
case ValidateFilesErrors.INVALID_SIZES:
|
|
542
|
+
console.error(chalk_1.default.red('✕'), `File size cannot be more than ${limit / 1024 / 1024 / 1024} GB`, chalk_1.default.cyan(`${file}`));
|
|
543
|
+
console.log();
|
|
544
|
+
break;
|
|
545
|
+
case ValidateFilesErrors.INVALID_NAME_CHARACTER_COUNTS:
|
|
546
|
+
console.error(chalk_1.default.red('✕'), `File name cannot have more than ${limit} characters`, chalk_1.default.cyan(`${file}`));
|
|
547
|
+
break;
|
|
548
|
+
case ValidateFilesErrors.INVALID_NAMES:
|
|
549
|
+
console.error(chalk_1.default.red('✕'), 'Character validation: Invalid filename for file: ', chalk_1.default.cyan(`${file}`));
|
|
550
|
+
recommendAcceptableFileNames();
|
|
551
|
+
break;
|
|
552
|
+
default:
|
|
553
|
+
console.error(chalk_1.default.red('✕'), 'Unknown error type:', errorType);
|
|
554
|
+
}
|
|
555
|
+
});
|
|
556
|
+
console.log();
|
|
587
557
|
};
|
|
588
558
|
exports.logErrors = logErrors;
|
|
589
|
-
const summaryLogs = ({
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
})
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
559
|
+
const summaryLogs = ({ folderErrorsLength, intImagesErrorsLength, fileTypeErrorsLength, fileErrorFileSizesLength, filenameErrorsLength, fileNameCharCountErrorsLength, totalFiles, totalFolders, }) => {
|
|
560
|
+
const messages = [];
|
|
561
|
+
if (folderErrorsLength > 0) {
|
|
562
|
+
messages.push(chalk_1.default.bgYellow(' RECOMMENDED ') +
|
|
563
|
+
chalk_1.default.bold.yellow(` ${folderErrorsLength} folders, `) +
|
|
564
|
+
`${totalFolders} folders total`);
|
|
565
|
+
}
|
|
566
|
+
else {
|
|
567
|
+
messages.push(chalk_1.default.bgGreen(' PASS ') +
|
|
568
|
+
chalk_1.default.bold.green(` ${totalFolders} folders, `) +
|
|
569
|
+
`${totalFolders} folders total`);
|
|
570
|
+
}
|
|
571
|
+
if (intImagesErrorsLength > 0) {
|
|
572
|
+
messages.push(chalk_1.default.white.bgRed(' ERROR ') +
|
|
573
|
+
chalk_1.default.red(` ${intImagesErrorsLength} intermediate images`) +
|
|
574
|
+
`, ${totalFiles} files total`);
|
|
575
|
+
}
|
|
576
|
+
else {
|
|
577
|
+
messages.push(chalk_1.default.white.bgGreen(' PASS ') +
|
|
578
|
+
chalk_1.default.green(` ${intImagesErrorsLength} intermediate images`) +
|
|
579
|
+
`, ${totalFiles} files total`);
|
|
580
|
+
}
|
|
581
|
+
if (fileTypeErrorsLength > 0) {
|
|
582
|
+
messages.push(chalk_1.default.white.bgRed(' ERROR ') +
|
|
583
|
+
chalk_1.default.red(` ${fileTypeErrorsLength} invalid file extensions`) +
|
|
584
|
+
`, ${totalFiles} files total`);
|
|
585
|
+
}
|
|
586
|
+
else {
|
|
587
|
+
messages.push(chalk_1.default.white.bgGreen(' PASS ') +
|
|
588
|
+
chalk_1.default.green(` ${fileTypeErrorsLength} invalid file extensions`) +
|
|
589
|
+
`, ${totalFiles} files total`);
|
|
590
|
+
}
|
|
591
|
+
if (fileErrorFileSizesLength > 0) {
|
|
592
|
+
messages.push(chalk_1.default.white.bgRed(' ERROR ') +
|
|
593
|
+
chalk_1.default.red(` ${fileTypeErrorsLength} invalid file sizes`) +
|
|
594
|
+
`, ${totalFiles} files total`);
|
|
595
|
+
}
|
|
596
|
+
else {
|
|
597
|
+
messages.push(chalk_1.default.white.bgGreen(' PASS ') +
|
|
598
|
+
chalk_1.default.green(` ${fileTypeErrorsLength} invalid file sizes`) +
|
|
599
|
+
`, ${totalFiles} files total`);
|
|
600
|
+
}
|
|
601
|
+
if (filenameErrorsLength) {
|
|
602
|
+
messages.push(chalk_1.default.white.bgRed(' ERROR ') +
|
|
603
|
+
chalk_1.default.red(` ${filenameErrorsLength} invalid filenames`) +
|
|
604
|
+
`, ${totalFiles} files total`);
|
|
605
|
+
}
|
|
606
|
+
else {
|
|
607
|
+
messages.push(chalk_1.default.bgGreen(' PASS ') +
|
|
608
|
+
chalk_1.default.green(` ${filenameErrorsLength} invalid filenames`) +
|
|
609
|
+
`, ${totalFiles} files total`);
|
|
610
|
+
}
|
|
611
|
+
if (fileNameCharCountErrorsLength) {
|
|
612
|
+
messages.push(chalk_1.default.white.bgRed(' ERROR ') +
|
|
613
|
+
chalk_1.default.red(` ${filenameErrorsLength} file names reached the maximum character count limit `) +
|
|
614
|
+
`, ${totalFiles} files total`);
|
|
615
|
+
}
|
|
616
|
+
else {
|
|
617
|
+
messages.push(chalk_1.default.bgGreen(' PASS ') +
|
|
618
|
+
chalk_1.default.green(` ${filenameErrorsLength} file names reached the maximum character count limit`) +
|
|
619
|
+
`, ${totalFiles} files total`);
|
|
620
|
+
}
|
|
621
|
+
console.log(`\n${messages.join('\n')}\n`);
|
|
631
622
|
};
|
|
632
|
-
exports.summaryLogs = summaryLogs;
|
|
623
|
+
exports.summaryLogs = summaryLogs;
|