@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,30 +1,62 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
var
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
var
|
|
19
|
-
var
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
36
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
37
|
+
};
|
|
38
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
+
exports.ExportSQLCommand = exports.CREATE_EXPORT_JOB_MUTATION = exports.GENERATE_DOWNLOAD_LINK_MUTATION = void 0;
|
|
40
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
41
|
+
const fs_1 = __importDefault(require("fs"));
|
|
42
|
+
const graphql_tag_1 = __importDefault(require("graphql-tag"));
|
|
43
|
+
const path_1 = __importDefault(require("path"));
|
|
44
|
+
const backup_db_1 = require("./backup-db");
|
|
45
|
+
const api_1 = __importStar(require("../lib/api"));
|
|
46
|
+
const backup_storage_availability_1 = require("../lib/backup-storage-availability/backup-storage-availability");
|
|
47
|
+
const exit = __importStar(require("../lib/cli/exit"));
|
|
48
|
+
const format_1 = require("../lib/cli/format");
|
|
49
|
+
const progress_1 = require("../lib/cli/progress");
|
|
50
|
+
const download_file_1 = require("../lib/http/download-file");
|
|
51
|
+
const liveBackupCopy = __importStar(require("../lib/live-backup-copy"));
|
|
52
|
+
const live_backup_copy_1 = require("../lib/live-backup-copy");
|
|
53
|
+
const retry_1 = require("../lib/retry");
|
|
54
|
+
const user_error_1 = __importDefault(require("../lib/user-error"));
|
|
55
|
+
const utils_1 = require("../lib/utils");
|
|
23
56
|
const EXPORT_SQL_PROGRESS_POLL_INTERVAL = 1000;
|
|
24
|
-
|
|
25
57
|
// Maximum allowed size for a live backup copy configuration file (500 KB).
|
|
26
58
|
const MAX_LIVE_BACKUP_CONFIG_SIZE_BYTES = 500 * 1024;
|
|
27
|
-
const BACKUP_AND_JOB_STATUS_QUERY = (0,
|
|
59
|
+
const BACKUP_AND_JOB_STATUS_QUERY = (0, graphql_tag_1.default) `
|
|
28
60
|
query AppBackupAndJobStatus($appId: Int!, $envId: Int!) {
|
|
29
61
|
app(id: $appId) {
|
|
30
62
|
id
|
|
@@ -63,9 +95,8 @@ const BACKUP_AND_JOB_STATUS_QUERY = (0, _graphqlTag.default)`
|
|
|
63
95
|
}
|
|
64
96
|
}
|
|
65
97
|
`;
|
|
66
|
-
|
|
67
98
|
// Exporting for test purposes
|
|
68
|
-
|
|
99
|
+
exports.GENERATE_DOWNLOAD_LINK_MUTATION = (0, graphql_tag_1.default) `
|
|
69
100
|
mutation GenerateDBBackupCopyUrl($input: AppEnvironmentGenerateDBBackupCopyUrlInput) {
|
|
70
101
|
generateDBBackupCopyUrl(input: $input) {
|
|
71
102
|
url
|
|
@@ -73,9 +104,8 @@ const GENERATE_DOWNLOAD_LINK_MUTATION = exports.GENERATE_DOWNLOAD_LINK_MUTATION
|
|
|
73
104
|
}
|
|
74
105
|
}
|
|
75
106
|
`;
|
|
76
|
-
|
|
77
107
|
// Exporting for test purposes
|
|
78
|
-
|
|
108
|
+
exports.CREATE_EXPORT_JOB_MUTATION = (0, graphql_tag_1.default) `
|
|
79
109
|
mutation BackupDBCopy($input: AppEnvironmentStartDBBackupCopyInput) {
|
|
80
110
|
startDBBackupCopy(input: $input) {
|
|
81
111
|
message
|
|
@@ -83,7 +113,6 @@ const CREATE_EXPORT_JOB_MUTATION = exports.CREATE_EXPORT_JOB_MUTATION = (0, _gra
|
|
|
83
113
|
}
|
|
84
114
|
}
|
|
85
115
|
`;
|
|
86
|
-
|
|
87
116
|
/**
|
|
88
117
|
* Fetches the latest backup and job status for an environment
|
|
89
118
|
*
|
|
@@ -92,37 +121,30 @@ const CREATE_EXPORT_JOB_MUTATION = exports.CREATE_EXPORT_JOB_MUTATION = (0, _gra
|
|
|
92
121
|
* @return {Promise} A promise which resolves to the latest backup and job status
|
|
93
122
|
*/
|
|
94
123
|
async function fetchLatestBackupAndJobStatusBase(appId, envId) {
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
const latestBackup = firstEnvironment?.latestBackup ?? undefined;
|
|
108
|
-
const jobs = firstEnvironment?.jobs || [];
|
|
109
|
-
return {
|
|
110
|
-
latestBackup,
|
|
111
|
-
jobs,
|
|
112
|
-
envSqlDumpTool
|
|
113
|
-
};
|
|
124
|
+
const api = (0, api_1.default)();
|
|
125
|
+
const response = await api.query({
|
|
126
|
+
query: BACKUP_AND_JOB_STATUS_QUERY,
|
|
127
|
+
variables: { appId, envId },
|
|
128
|
+
fetchPolicy: 'network-only',
|
|
129
|
+
});
|
|
130
|
+
const environments = response.data?.app?.environments;
|
|
131
|
+
const firstEnvironment = environments?.[0];
|
|
132
|
+
const envSqlDumpTool = firstEnvironment?.backupsSqlDumpTool;
|
|
133
|
+
const latestBackup = firstEnvironment?.latestBackup ?? undefined;
|
|
134
|
+
const jobs = (firstEnvironment?.jobs || []);
|
|
135
|
+
return { latestBackup, jobs, envSqlDumpTool };
|
|
114
136
|
}
|
|
115
137
|
async function fetchLatestBackupAndJobStatus(appId, envId) {
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
}
|
|
119
|
-
return await (0, _retry.retry)({
|
|
120
|
-
retryOnlyIf: options => {
|
|
121
|
-
return (options.error.message || '').indexOf('Unexpected token < in JSON at position 0') !== -1;
|
|
138
|
+
if (!appId || !envId) {
|
|
139
|
+
throw new Error('App ID and Env ID missing');
|
|
122
140
|
}
|
|
123
|
-
|
|
141
|
+
return await (0, retry_1.retry)({
|
|
142
|
+
retryOnlyIf: options => {
|
|
143
|
+
return ((options.error.message || '').indexOf('Unexpected token < in JSON at position 0') !==
|
|
144
|
+
-1);
|
|
145
|
+
},
|
|
146
|
+
}, () => fetchLatestBackupAndJobStatusBase(appId, envId));
|
|
124
147
|
}
|
|
125
|
-
|
|
126
148
|
/**
|
|
127
149
|
* Generates a download link for a backup
|
|
128
150
|
*
|
|
@@ -132,23 +154,22 @@ async function fetchLatestBackupAndJobStatus(appId, envId) {
|
|
|
132
154
|
* @return {Promise} A promise which resolves to the download link
|
|
133
155
|
*/
|
|
134
156
|
async function generateDownloadLink(appId, envId, backupId) {
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
}
|
|
138
|
-
const api = (0, _api.default)();
|
|
139
|
-
const response = await api.mutate({
|
|
140
|
-
mutation: GENERATE_DOWNLOAD_LINK_MUTATION,
|
|
141
|
-
variables: {
|
|
142
|
-
input: {
|
|
143
|
-
id: appId,
|
|
144
|
-
environmentId: envId,
|
|
145
|
-
backupId
|
|
146
|
-
}
|
|
157
|
+
if (!appId || !envId || !backupId) {
|
|
158
|
+
throw new Error('generateDownloadLink: A parameter is missing');
|
|
147
159
|
}
|
|
148
|
-
|
|
149
|
-
|
|
160
|
+
const api = (0, api_1.default)();
|
|
161
|
+
const response = await api.mutate({
|
|
162
|
+
mutation: exports.GENERATE_DOWNLOAD_LINK_MUTATION,
|
|
163
|
+
variables: {
|
|
164
|
+
input: {
|
|
165
|
+
id: appId,
|
|
166
|
+
environmentId: envId,
|
|
167
|
+
backupId,
|
|
168
|
+
},
|
|
169
|
+
},
|
|
170
|
+
});
|
|
171
|
+
return response.data?.generateDBBackupCopyUrl?.url ?? '';
|
|
150
172
|
}
|
|
151
|
-
|
|
152
173
|
/**
|
|
153
174
|
* Creates an export job for a backup
|
|
154
175
|
*
|
|
@@ -159,381 +180,376 @@ async function generateDownloadLink(appId, envId, backupId) {
|
|
|
159
180
|
* @throws {Error} Throws an error if the job creation fails
|
|
160
181
|
*/
|
|
161
182
|
async function createExportJob(appId, envId, backupId) {
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
// Disable global error handling so that we can handle errors ourselves
|
|
167
|
-
(0, _api.disableGlobalGraphQLErrorHandling)();
|
|
168
|
-
const api = (0, _api.default)();
|
|
169
|
-
await api.mutate({
|
|
170
|
-
mutation: CREATE_EXPORT_JOB_MUTATION,
|
|
171
|
-
variables: {
|
|
172
|
-
input: {
|
|
173
|
-
id: appId,
|
|
174
|
-
environmentId: envId,
|
|
175
|
-
backupId
|
|
176
|
-
}
|
|
183
|
+
if (!appId || !envId || !backupId) {
|
|
184
|
+
throw new Error('createExportJob: Some fields are undefined');
|
|
177
185
|
}
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
186
|
+
// Disable global error handling so that we can handle errors ourselves
|
|
187
|
+
(0, api_1.disableGlobalGraphQLErrorHandling)();
|
|
188
|
+
const api = (0, api_1.default)();
|
|
189
|
+
await api.mutate({
|
|
190
|
+
mutation: exports.CREATE_EXPORT_JOB_MUTATION,
|
|
191
|
+
variables: {
|
|
192
|
+
input: {
|
|
193
|
+
id: appId,
|
|
194
|
+
environmentId: envId,
|
|
195
|
+
backupId,
|
|
196
|
+
},
|
|
197
|
+
},
|
|
198
|
+
});
|
|
199
|
+
// Re-enable global error handling
|
|
200
|
+
(0, api_1.enableGlobalGraphQLErrorHandling)();
|
|
182
201
|
}
|
|
183
202
|
/**
|
|
184
203
|
* Class representing an export command workflow
|
|
185
204
|
*/
|
|
186
205
|
class ExportSQLCommand {
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
name: 'Downloading file'
|
|
232
|
-
}]);
|
|
233
|
-
this.track = trackerFn;
|
|
234
|
-
this.liveBackupCopyCLIOptions = options.liveBackupCopyCLIOptions;
|
|
235
|
-
this.showMyDumperWarning = options.showMyDumperWarning === undefined ? true : options.showMyDumperWarning;
|
|
236
|
-
this.skipDownload = options.skipDownload || false;
|
|
237
|
-
}
|
|
238
|
-
|
|
239
|
-
/**
|
|
240
|
-
* Fetches the export job of the latest backup
|
|
241
|
-
*
|
|
242
|
-
* @return {Promise} A promise which resolves to the export job
|
|
243
|
-
*/
|
|
244
|
-
async getExportJob() {
|
|
245
|
-
const {
|
|
246
|
-
latestBackup,
|
|
247
|
-
jobs
|
|
248
|
-
} = await fetchLatestBackupAndJobStatus(this.app.id, this.env.id);
|
|
249
|
-
if (!latestBackup) {
|
|
250
|
-
return undefined;
|
|
251
|
-
}
|
|
252
|
-
|
|
253
|
-
// Find the job that generates the export for the latest backup
|
|
254
|
-
return jobs.find(job => {
|
|
255
|
-
const metadata = (job.metadata || []).find(md => md?.name === 'backupId');
|
|
256
|
-
return metadata && parseInt(metadata.value, 10) === latestBackup.id;
|
|
257
|
-
});
|
|
258
|
-
}
|
|
259
|
-
|
|
260
|
-
/**
|
|
261
|
-
* Fetches the S3 filename of the exported backup
|
|
262
|
-
*
|
|
263
|
-
* @return A promise which resolves to the filename
|
|
264
|
-
*/
|
|
265
|
-
async getExportedFileName() {
|
|
266
|
-
const job = await this.getExportJob();
|
|
267
|
-
if (!job) {
|
|
268
|
-
throw new Error('Job not found');
|
|
269
|
-
}
|
|
270
|
-
const metadata = job.metadata?.find(md => md?.name === 'uploadPath');
|
|
271
|
-
return metadata?.value?.split('/')[1];
|
|
272
|
-
}
|
|
273
|
-
|
|
274
|
-
/**
|
|
275
|
-
* Checks if the export job's preflight step is successful
|
|
276
|
-
*
|
|
277
|
-
* @param job The export job
|
|
278
|
-
* @return True if the preflight step is successful
|
|
279
|
-
*/
|
|
280
|
-
isPrepared(job) {
|
|
281
|
-
const step = job?.progress?.steps?.find(st => st?.id === 'preflight');
|
|
282
|
-
return step?.status === 'success';
|
|
283
|
-
}
|
|
284
|
-
|
|
285
|
-
/**
|
|
286
|
-
* Checks if the export job's S3 upload step is successful
|
|
287
|
-
*
|
|
288
|
-
* @param job The export job
|
|
289
|
-
* @return True if the upload step is successful
|
|
290
|
-
*/
|
|
291
|
-
isCreated(job) {
|
|
292
|
-
const step = job?.progress?.steps?.find(st => st?.id === 'upload_backup');
|
|
293
|
-
return step?.status === 'success';
|
|
294
|
-
}
|
|
295
|
-
|
|
296
|
-
/**
|
|
297
|
-
* Stops the progress tracker
|
|
298
|
-
*/
|
|
299
|
-
stopProgressTracker() {
|
|
300
|
-
this.progressTracker.print();
|
|
301
|
-
this.progressTracker.stopPrinting();
|
|
302
|
-
}
|
|
303
|
-
async runBackupJob() {
|
|
304
|
-
const cmd = new _backupDb.BackupDBCommand(this.app, this.env);
|
|
305
|
-
let noticeMessage = `\n${_chalk.default.yellow('NOTICE: ')}`;
|
|
306
|
-
noticeMessage += 'If a recent database backup does not exist, a new one will be generated for this environment. ';
|
|
307
|
-
noticeMessage += 'Learn more about this: https://docs.wpvip.com/databases/backups/download-a-full-database-backup/ \n';
|
|
308
|
-
console.log(noticeMessage);
|
|
309
|
-
await cmd.run(false);
|
|
310
|
-
}
|
|
311
|
-
async confirmEnoughStorage(archiveSize) {
|
|
312
|
-
if (this.confirmEnoughStorageHook) {
|
|
313
|
-
return await this.confirmEnoughStorageHook(archiveSize);
|
|
206
|
+
app;
|
|
207
|
+
env;
|
|
208
|
+
progressTracker;
|
|
209
|
+
outputFile;
|
|
210
|
+
generateBackup;
|
|
211
|
+
confirmEnoughStorageHook;
|
|
212
|
+
steps = {
|
|
213
|
+
PREPARE: 'prepare',
|
|
214
|
+
CREATE: 'create',
|
|
215
|
+
DOWNLOAD_LINK: 'downloadLink',
|
|
216
|
+
CONFIRM_ENOUGH_STORAGE: 'confirmEnoughStorage',
|
|
217
|
+
DOWNLOAD: 'download',
|
|
218
|
+
};
|
|
219
|
+
track;
|
|
220
|
+
liveBackupCopyCLIOptions;
|
|
221
|
+
showMyDumperWarning;
|
|
222
|
+
skipDownload;
|
|
223
|
+
/**
|
|
224
|
+
* Creates an instance of SQLExportCommand
|
|
225
|
+
*
|
|
226
|
+
* @param {any} app The application object
|
|
227
|
+
* @param {any} env The environment object
|
|
228
|
+
* @param {object} options The optional parameters
|
|
229
|
+
* @param {Function} trackerFn The progress tracker function
|
|
230
|
+
*/
|
|
231
|
+
constructor(app, env, options = {}, trackerFn = () => { }) {
|
|
232
|
+
this.app = app;
|
|
233
|
+
this.env = env;
|
|
234
|
+
this.outputFile =
|
|
235
|
+
typeof options.outputFile === 'string' ? (0, utils_1.getAbsolutePath)(options.outputFile) : null;
|
|
236
|
+
this.confirmEnoughStorageHook = options.confirmEnoughStorageHook;
|
|
237
|
+
this.generateBackup = options.generateBackup || false;
|
|
238
|
+
this.progressTracker = new progress_1.ProgressTracker([
|
|
239
|
+
{ id: this.steps.PREPARE, name: 'Preparing for backup download' },
|
|
240
|
+
{ id: this.steps.CREATE, name: 'Creating backup copy' },
|
|
241
|
+
{ id: this.steps.DOWNLOAD_LINK, name: 'Requesting download link' },
|
|
242
|
+
{ id: this.steps.CONFIRM_ENOUGH_STORAGE, name: "Checking if there's enough storage" },
|
|
243
|
+
{ id: this.steps.DOWNLOAD, name: 'Downloading file' },
|
|
244
|
+
]);
|
|
245
|
+
this.track = trackerFn;
|
|
246
|
+
this.liveBackupCopyCLIOptions = options.liveBackupCopyCLIOptions;
|
|
247
|
+
this.showMyDumperWarning =
|
|
248
|
+
options.showMyDumperWarning === undefined ? true : options.showMyDumperWarning;
|
|
249
|
+
this.skipDownload = options.skipDownload || false;
|
|
314
250
|
}
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
await this.track('error', {
|
|
330
|
-
error_type: 'cannot_write_to_path',
|
|
331
|
-
error_message: `Cannot write to the specified path: ${error?.message}`,
|
|
332
|
-
stack: error?.stack
|
|
251
|
+
/**
|
|
252
|
+
* Fetches the export job of the latest backup
|
|
253
|
+
*
|
|
254
|
+
* @return {Promise} A promise which resolves to the export job
|
|
255
|
+
*/
|
|
256
|
+
async getExportJob() {
|
|
257
|
+
const { latestBackup, jobs } = await fetchLatestBackupAndJobStatus(this.app.id, this.env.id);
|
|
258
|
+
if (!latestBackup) {
|
|
259
|
+
return undefined;
|
|
260
|
+
}
|
|
261
|
+
// Find the job that generates the export for the latest backup
|
|
262
|
+
return jobs.find(job => {
|
|
263
|
+
const metadata = (job.metadata || []).find(md => md?.name === 'backupId');
|
|
264
|
+
return metadata && parseInt(metadata.value, 10) === latestBackup.id;
|
|
333
265
|
});
|
|
334
|
-
exit.withError(`Cannot write to the specified path: ${error?.message}`);
|
|
335
|
-
}
|
|
336
266
|
}
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
} else {
|
|
347
|
-
url = await this.runBackup();
|
|
348
|
-
const exportJob = await this.getExportJob();
|
|
349
|
-
if (!exportJob) {
|
|
350
|
-
throw new Error('Export job not found');
|
|
351
|
-
}
|
|
352
|
-
const bytesWrittenMeta = exportJob.metadata?.find(meta => meta?.name === 'bytesWritten');
|
|
353
|
-
if (!bytesWrittenMeta?.value) {
|
|
354
|
-
throw new Error('Export job metadata does not contain bytesWritten');
|
|
355
|
-
}
|
|
356
|
-
size = Number(bytesWrittenMeta.value);
|
|
357
|
-
}
|
|
358
|
-
if (this.skipDownload) {
|
|
359
|
-
this.progressTracker.stepSkipped(this.steps.CONFIRM_ENOUGH_STORAGE);
|
|
360
|
-
this.progressTracker.stepSkipped(this.steps.DOWNLOAD);
|
|
361
|
-
this.progressTracker.print();
|
|
362
|
-
this.progressTracker.stopPrinting();
|
|
363
|
-
return;
|
|
364
|
-
}
|
|
365
|
-
const storageConfirmed = await this.progressTracker.handleContinuePrompt(async setPromptShown => {
|
|
366
|
-
const status = await this.confirmEnoughStorage(Number(size));
|
|
367
|
-
if (status.isPromptShown) {
|
|
368
|
-
setPromptShown();
|
|
369
|
-
}
|
|
370
|
-
return status.continue;
|
|
371
|
-
});
|
|
372
|
-
if (storageConfirmed) {
|
|
373
|
-
this.progressTracker.stepSuccess(this.steps.CONFIRM_ENOUGH_STORAGE);
|
|
374
|
-
} else {
|
|
375
|
-
this.progressTracker.stepFailed(this.steps.CONFIRM_ENOUGH_STORAGE);
|
|
376
|
-
this.stopProgressTracker();
|
|
377
|
-
exit.withError('Command canceled by user.');
|
|
378
|
-
}
|
|
379
|
-
|
|
380
|
-
// The export file is prepared. Let's download it
|
|
381
|
-
try {
|
|
382
|
-
const onProgressCallback = (current, total) => {
|
|
383
|
-
if (total) {
|
|
384
|
-
this.progressTracker.setProgress(`- ${(100 * current / total).toFixed(2)}% (${(0, _format.formatBytes)(current)}/${(0, _format.formatBytes)(total)})`);
|
|
267
|
+
/**
|
|
268
|
+
* Fetches the S3 filename of the exported backup
|
|
269
|
+
*
|
|
270
|
+
* @return A promise which resolves to the filename
|
|
271
|
+
*/
|
|
272
|
+
async getExportedFileName() {
|
|
273
|
+
const job = await this.getExportJob();
|
|
274
|
+
if (!job) {
|
|
275
|
+
throw new Error('Job not found');
|
|
385
276
|
}
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
this.progressTracker.stepSuccess(this.steps.DOWNLOAD);
|
|
389
|
-
this.stopProgressTracker();
|
|
390
|
-
console.log(`File saved to ${filename}`);
|
|
391
|
-
} catch (err) {
|
|
392
|
-
const error = err;
|
|
393
|
-
this.progressTracker.stepFailed(this.steps.DOWNLOAD);
|
|
394
|
-
this.stopProgressTracker();
|
|
395
|
-
await this.track('error', {
|
|
396
|
-
error_type: 'download_failed',
|
|
397
|
-
error_message: error.message,
|
|
398
|
-
stack: error.stack
|
|
399
|
-
});
|
|
400
|
-
exit.withError(`Error downloading exported file: ${error.message}`);
|
|
401
|
-
}
|
|
402
|
-
}
|
|
403
|
-
generateDownloadURLOutputString(url) {
|
|
404
|
-
return `${_chalk.default.green('Download URL')}: ${url}`;
|
|
405
|
-
}
|
|
406
|
-
async runBackup() {
|
|
407
|
-
if (this.generateBackup) {
|
|
408
|
-
await this.runBackupJob();
|
|
277
|
+
const metadata = job.metadata?.find(md => md?.name === 'uploadPath');
|
|
278
|
+
return metadata?.value?.split('/')[1];
|
|
409
279
|
}
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
exit.withError(`No backup found for site ${this.app.name}`);
|
|
280
|
+
/**
|
|
281
|
+
* Checks if the export job's preflight step is successful
|
|
282
|
+
*
|
|
283
|
+
* @param job The export job
|
|
284
|
+
* @return True if the preflight step is successful
|
|
285
|
+
*/
|
|
286
|
+
isPrepared(job) {
|
|
287
|
+
const step = job?.progress?.steps?.find(st => st?.id === 'preflight');
|
|
288
|
+
return step?.status === 'success';
|
|
420
289
|
}
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
290
|
+
/**
|
|
291
|
+
* Checks if the export job's S3 upload step is successful
|
|
292
|
+
*
|
|
293
|
+
* @param job The export job
|
|
294
|
+
* @return True if the upload step is successful
|
|
295
|
+
*/
|
|
296
|
+
isCreated(job) {
|
|
297
|
+
const step = job?.progress?.steps?.find(st => st?.id === 'upload_backup');
|
|
298
|
+
return step?.status === 'success';
|
|
425
299
|
}
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
} catch (err) {
|
|
433
|
-
const error = err;
|
|
434
|
-
// Todo: match error code instead of message substring
|
|
435
|
-
if (error.message.includes('Backup Copy already in progress')) {
|
|
436
|
-
await this.track('error', {
|
|
437
|
-
error_type: 'job_already_running',
|
|
438
|
-
error_message: error.message,
|
|
439
|
-
stack: error.stack
|
|
440
|
-
});
|
|
441
|
-
exit.withError('There is an export job already running for this environment: ' + `https://dashboard.wpvip.com/apps/${this.app.id}/${this.env.uniqueLabel}/database/backups\n` + 'Currently, we allow only one export job at a time, per site. Please try again later.');
|
|
442
|
-
} else {
|
|
443
|
-
await this.track('error', {
|
|
444
|
-
error_type: 'create_export_job',
|
|
445
|
-
error_message: error.message,
|
|
446
|
-
stack: error.stack
|
|
447
|
-
});
|
|
448
|
-
}
|
|
449
|
-
exit.withError(`Error creating export job: ${error.message}`);
|
|
450
|
-
}
|
|
300
|
+
/**
|
|
301
|
+
* Stops the progress tracker
|
|
302
|
+
*/
|
|
303
|
+
stopProgressTracker() {
|
|
304
|
+
this.progressTracker.print();
|
|
305
|
+
this.progressTracker.stopPrinting();
|
|
451
306
|
}
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
if (!this.liveBackupCopyCLIOptions) {
|
|
462
|
-
throw new _userError.default('Configuration file is required for live backup copy.');
|
|
307
|
+
async runBackupJob() {
|
|
308
|
+
const cmd = new backup_db_1.BackupDBCommand(this.app, this.env);
|
|
309
|
+
let noticeMessage = `\n${chalk_1.default.yellow('NOTICE: ')}`;
|
|
310
|
+
noticeMessage +=
|
|
311
|
+
'If a recent database backup does not exist, a new one will be generated for this environment. ';
|
|
312
|
+
noticeMessage +=
|
|
313
|
+
'Learn more about this: https://docs.wpvip.com/databases/backups/download-a-full-database-backup/ \n';
|
|
314
|
+
console.log(noticeMessage);
|
|
315
|
+
await cmd.run(false);
|
|
463
316
|
}
|
|
464
|
-
|
|
465
|
-
|
|
317
|
+
async confirmEnoughStorage(archiveSize) {
|
|
318
|
+
if (this.confirmEnoughStorageHook) {
|
|
319
|
+
return await this.confirmEnoughStorageHook(archiveSize);
|
|
320
|
+
}
|
|
321
|
+
const storageAvailability = new backup_storage_availability_1.BackupStorageAvailability();
|
|
322
|
+
return await storageAvailability.validateAndPromptDiskSpaceWarningForBackupImport(archiveSize);
|
|
466
323
|
}
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
324
|
+
/**
|
|
325
|
+
* Sequentially runs the steps of the export workflow
|
|
326
|
+
*
|
|
327
|
+
*/
|
|
328
|
+
async run() {
|
|
329
|
+
if (this.outputFile) {
|
|
330
|
+
try {
|
|
331
|
+
fs_1.default.accessSync(path_1.default.parse(this.outputFile).dir, fs_1.default.constants.W_OK);
|
|
332
|
+
}
|
|
333
|
+
catch (err) {
|
|
334
|
+
const error = err;
|
|
335
|
+
await this.track('error', {
|
|
336
|
+
error_type: 'cannot_write_to_path',
|
|
337
|
+
error_message: `Cannot write to the specified path: ${error?.message}`,
|
|
338
|
+
stack: error?.stack,
|
|
339
|
+
});
|
|
340
|
+
exit.withError(`Cannot write to the specified path: ${error?.message}`);
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
const filename = this.outputFile || 'exported.sql.gz';
|
|
344
|
+
this.progressTracker.stepRunning(this.steps.PREPARE);
|
|
345
|
+
this.progressTracker.startPrinting();
|
|
346
|
+
let url;
|
|
347
|
+
let size;
|
|
348
|
+
if (this.liveBackupCopyCLIOptions?.useLiveBackupCopy) {
|
|
349
|
+
const result = await this.generateLiveBackupCopy();
|
|
350
|
+
url = result.url;
|
|
351
|
+
size = Number(result.size);
|
|
352
|
+
}
|
|
353
|
+
else {
|
|
354
|
+
url = await this.runBackup();
|
|
355
|
+
const exportJob = await this.getExportJob();
|
|
356
|
+
if (!exportJob) {
|
|
357
|
+
throw new Error('Export job not found');
|
|
358
|
+
}
|
|
359
|
+
const bytesWrittenMeta = exportJob.metadata?.find(meta => meta?.name === 'bytesWritten');
|
|
360
|
+
if (!bytesWrittenMeta?.value) {
|
|
361
|
+
throw new Error('Export job metadata does not contain bytesWritten');
|
|
362
|
+
}
|
|
363
|
+
size = Number(bytesWrittenMeta.value);
|
|
364
|
+
}
|
|
365
|
+
if (this.skipDownload) {
|
|
366
|
+
this.progressTracker.stepSkipped(this.steps.CONFIRM_ENOUGH_STORAGE);
|
|
367
|
+
this.progressTracker.stepSkipped(this.steps.DOWNLOAD);
|
|
368
|
+
this.progressTracker.print();
|
|
369
|
+
this.progressTracker.stopPrinting();
|
|
370
|
+
return;
|
|
371
|
+
}
|
|
372
|
+
const storageConfirmed = await this.progressTracker.handleContinuePrompt(async (setPromptShown) => {
|
|
373
|
+
const status = await this.confirmEnoughStorage(Number(size));
|
|
374
|
+
if (status.isPromptShown) {
|
|
375
|
+
setPromptShown();
|
|
376
|
+
}
|
|
377
|
+
return status.continue;
|
|
378
|
+
});
|
|
379
|
+
if (storageConfirmed) {
|
|
380
|
+
this.progressTracker.stepSuccess(this.steps.CONFIRM_ENOUGH_STORAGE);
|
|
381
|
+
}
|
|
382
|
+
else {
|
|
383
|
+
this.progressTracker.stepFailed(this.steps.CONFIRM_ENOUGH_STORAGE);
|
|
384
|
+
this.stopProgressTracker();
|
|
385
|
+
exit.withError('Command canceled by user.');
|
|
386
|
+
}
|
|
387
|
+
// The export file is prepared. Let's download it
|
|
388
|
+
try {
|
|
389
|
+
const onProgressCallback = (current, total) => {
|
|
390
|
+
if (total) {
|
|
391
|
+
this.progressTracker.setProgress(`- ${((100 * current) / total).toFixed(2)}% (${(0, format_1.formatBytes)(current)}/${(0, format_1.formatBytes)(total)})`);
|
|
392
|
+
}
|
|
393
|
+
};
|
|
394
|
+
await (0, download_file_1.downloadFile)(url, filename, onProgressCallback);
|
|
395
|
+
this.progressTracker.stepSuccess(this.steps.DOWNLOAD);
|
|
396
|
+
this.stopProgressTracker();
|
|
397
|
+
console.log(`File saved to ${filename}`);
|
|
398
|
+
}
|
|
399
|
+
catch (err) {
|
|
400
|
+
const error = err;
|
|
401
|
+
this.progressTracker.stepFailed(this.steps.DOWNLOAD);
|
|
402
|
+
this.stopProgressTracker();
|
|
403
|
+
await this.track('error', {
|
|
404
|
+
error_type: 'download_failed',
|
|
405
|
+
error_message: error.message,
|
|
406
|
+
stack: error.stack,
|
|
407
|
+
});
|
|
408
|
+
exit.withError(`Error downloading exported file: ${error.message}`);
|
|
409
|
+
}
|
|
492
410
|
}
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
if (this.liveBackupCopyCLIOptions?.configFile) {
|
|
496
|
-
return this.loadLiveBackupCopyConfig(this.liveBackupCopyCLIOptions?.configFile);
|
|
411
|
+
generateDownloadURLOutputString(url) {
|
|
412
|
+
return `${chalk_1.default.green('Download URL')}: ${url}`;
|
|
497
413
|
}
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
414
|
+
async runBackup() {
|
|
415
|
+
if (this.generateBackup) {
|
|
416
|
+
await this.runBackupJob();
|
|
417
|
+
}
|
|
418
|
+
const { latestBackup, envSqlDumpTool } = await fetchLatestBackupAndJobStatus(this.app.id, this.env.id);
|
|
419
|
+
if (!latestBackup) {
|
|
420
|
+
await this.track('error', {
|
|
421
|
+
error_type: 'no_backup_found',
|
|
422
|
+
error_message: 'No backup found for the site',
|
|
423
|
+
});
|
|
424
|
+
exit.withError(`No backup found for site ${this.app.name}`);
|
|
425
|
+
}
|
|
426
|
+
const prepareAdditionalInfo = [];
|
|
427
|
+
const showMyDumperWarning = this.showMyDumperWarning && (latestBackup.sqlDumpTool ?? envSqlDumpTool) === 'mydumper';
|
|
428
|
+
if (showMyDumperWarning) {
|
|
429
|
+
prepareAdditionalInfo.push(`${chalk_1.default.yellow.bold('WARNING:')} This is a large or complex database. The backup file for this database is generated with MyDumper. The file can only be loaded with MyLoader. For more information: https://github.com/mydumper/mydumper`);
|
|
430
|
+
}
|
|
431
|
+
if (await this.getExportJob()) {
|
|
432
|
+
prepareAdditionalInfo.push(`Attaching to an existing export for the backup with timestamp ${latestBackup.createdAt}`);
|
|
433
|
+
}
|
|
434
|
+
else {
|
|
435
|
+
prepareAdditionalInfo.push(`Exporting database backup with timestamp ${latestBackup.createdAt}`);
|
|
436
|
+
try {
|
|
437
|
+
await createExportJob(this.app.id, this.env.id, latestBackup.id);
|
|
438
|
+
}
|
|
439
|
+
catch (err) {
|
|
440
|
+
const error = err;
|
|
441
|
+
// Todo: match error code instead of message substring
|
|
442
|
+
if (error.message.includes('Backup Copy already in progress')) {
|
|
443
|
+
await this.track('error', {
|
|
444
|
+
error_type: 'job_already_running',
|
|
445
|
+
error_message: error.message,
|
|
446
|
+
stack: error.stack,
|
|
447
|
+
});
|
|
448
|
+
exit.withError('There is an export job already running for this environment: ' +
|
|
449
|
+
`https://dashboard.wpvip.com/apps/${this.app.id}/${this.env.uniqueLabel}/database/backups\n` +
|
|
450
|
+
'Currently, we allow only one export job at a time, per site. Please try again later.');
|
|
451
|
+
}
|
|
452
|
+
else {
|
|
453
|
+
await this.track('error', {
|
|
454
|
+
error_type: 'create_export_job',
|
|
455
|
+
error_message: error.message,
|
|
456
|
+
stack: error.stack,
|
|
457
|
+
});
|
|
458
|
+
}
|
|
459
|
+
exit.withError(`Error creating export job: ${error.message}`);
|
|
460
|
+
}
|
|
461
|
+
}
|
|
462
|
+
await (0, utils_1.pollUntil)(this.getExportJob.bind(this), EXPORT_SQL_PROGRESS_POLL_INTERVAL, this.isPrepared.bind(this));
|
|
463
|
+
this.progressTracker.stepSuccess(this.steps.PREPARE, prepareAdditionalInfo);
|
|
464
|
+
await (0, utils_1.pollUntil)(this.getExportJob.bind(this), EXPORT_SQL_PROGRESS_POLL_INTERVAL, this.isCreated.bind(this));
|
|
465
|
+
this.progressTracker.stepSuccess(this.steps.CREATE);
|
|
466
|
+
const url = await generateDownloadLink(this.app.id, this.env.id, latestBackup.id);
|
|
467
|
+
this.progressTracker.stepSuccess(this.steps.DOWNLOAD_LINK, [
|
|
468
|
+
this.generateDownloadURLOutputString(url),
|
|
469
|
+
]);
|
|
470
|
+
return url;
|
|
503
471
|
}
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
472
|
+
async generateLiveBackupCopy() {
|
|
473
|
+
if (!this.liveBackupCopyCLIOptions) {
|
|
474
|
+
throw new user_error_1.default('Configuration file is required for live backup copy.');
|
|
475
|
+
}
|
|
476
|
+
if (!this.app.id || !this.env.id) {
|
|
477
|
+
throw new user_error_1.default('App ID and Environment ID are required to start live backup copy.');
|
|
478
|
+
}
|
|
479
|
+
const config = this.getLiveBackupConfigFromCLIOptions();
|
|
480
|
+
try {
|
|
481
|
+
const copyId = await liveBackupCopy.startLiveBackupCopy({
|
|
482
|
+
appId: this.app.id,
|
|
483
|
+
environmentId: this.env.id,
|
|
484
|
+
config,
|
|
485
|
+
});
|
|
486
|
+
this.progressTracker.stepSuccess(this.steps.PREPARE);
|
|
487
|
+
this.progressTracker.stepRunning(this.steps.CREATE);
|
|
488
|
+
const result = await liveBackupCopy.getDownloadURL({
|
|
489
|
+
appId: this.app.id,
|
|
490
|
+
environmentId: this.env.id,
|
|
491
|
+
copyId,
|
|
492
|
+
});
|
|
493
|
+
this.progressTracker.stepSuccess(this.steps.CREATE);
|
|
494
|
+
this.progressTracker.stepSuccess(this.steps.DOWNLOAD_LINK, [
|
|
495
|
+
this.generateDownloadURLOutputString(result.url),
|
|
496
|
+
]);
|
|
497
|
+
return result;
|
|
498
|
+
}
|
|
499
|
+
catch (err) {
|
|
500
|
+
const message = (0, utils_1.parseApiError)(err) ?? 'Unknown error';
|
|
501
|
+
await this.track('error', {
|
|
502
|
+
error_type: 'live_backup_copy',
|
|
503
|
+
error_message: message,
|
|
504
|
+
stack: err instanceof Error ? err.stack : undefined,
|
|
505
|
+
});
|
|
506
|
+
exit.withError(`Error creating live backup copy: ${message}`);
|
|
507
|
+
}
|
|
507
508
|
}
|
|
508
|
-
|
|
509
|
-
|
|
509
|
+
getLiveBackupConfigFromCLIOptions() {
|
|
510
|
+
if (this.liveBackupCopyCLIOptions?.configFile) {
|
|
511
|
+
return this.loadLiveBackupCopyConfig(this.liveBackupCopyCLIOptions?.configFile);
|
|
512
|
+
}
|
|
513
|
+
let type = live_backup_copy_1.BackupLiveCopyType.TABLES;
|
|
514
|
+
let tables;
|
|
515
|
+
let siteIds;
|
|
516
|
+
if (this.liveBackupCopyCLIOptions?.tables) {
|
|
517
|
+
tables = Object.fromEntries(this.liveBackupCopyCLIOptions?.tables.map(key => [key, {}]));
|
|
518
|
+
}
|
|
519
|
+
if (this.liveBackupCopyCLIOptions?.siteIds) {
|
|
520
|
+
type = live_backup_copy_1.BackupLiveCopyType.SITE_IDS;
|
|
521
|
+
siteIds = this.liveBackupCopyCLIOptions?.siteIds.map(id => Number(id));
|
|
522
|
+
}
|
|
523
|
+
if (this.liveBackupCopyCLIOptions?.wpcliCommand) {
|
|
524
|
+
type = live_backup_copy_1.BackupLiveCopyType.WP_CLI_COMMAND;
|
|
525
|
+
}
|
|
526
|
+
return {
|
|
527
|
+
type,
|
|
528
|
+
tables,
|
|
529
|
+
site_ids: siteIds,
|
|
530
|
+
wpcli_command: this.liveBackupCopyCLIOptions?.wpcliCommand,
|
|
531
|
+
};
|
|
510
532
|
}
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
const errMessage = err instanceof Error ? err.message : 'Unknown error';
|
|
532
|
-
if (err instanceof SyntaxError) {
|
|
533
|
-
throw new _userError.default(`Invalid JSON in configuration file: ${configFile} - ${errMessage}`);
|
|
534
|
-
}
|
|
535
|
-
throw new _userError.default(`Error reading configuration file: ${configFile} - ${errMessage}`);
|
|
533
|
+
loadLiveBackupCopyConfig(configFile) {
|
|
534
|
+
try {
|
|
535
|
+
// Read the file once to avoid a check-then-use race condition.
|
|
536
|
+
const fileContents = fs_1.default.readFileSync(configFile, 'utf-8');
|
|
537
|
+
const size = Buffer.byteLength(fileContents);
|
|
538
|
+
if (size > MAX_LIVE_BACKUP_CONFIG_SIZE_BYTES) {
|
|
539
|
+
throw new user_error_1.default(`Configuration file is too large (${(0, format_1.formatBytes)(size)}); the maximum allowed size is ${(0, format_1.formatBytes)(MAX_LIVE_BACKUP_CONFIG_SIZE_BYTES)}. For large or complex exports, use the \`--wpcli-command\` option instead.`);
|
|
540
|
+
}
|
|
541
|
+
return JSON.parse(fileContents);
|
|
542
|
+
}
|
|
543
|
+
catch (err) {
|
|
544
|
+
if (err instanceof user_error_1.default) {
|
|
545
|
+
throw err;
|
|
546
|
+
}
|
|
547
|
+
const errMessage = err instanceof Error ? err.message : 'Unknown error';
|
|
548
|
+
if (err instanceof SyntaxError) {
|
|
549
|
+
throw new user_error_1.default(`Invalid JSON in configuration file: ${configFile} - ${errMessage}`);
|
|
550
|
+
}
|
|
551
|
+
throw new user_error_1.default(`Error reading configuration file: ${configFile} - ${errMessage}`);
|
|
552
|
+
}
|
|
536
553
|
}
|
|
537
|
-
}
|
|
538
554
|
}
|
|
539
|
-
exports.ExportSQLCommand = ExportSQLCommand;
|
|
555
|
+
exports.ExportSQLCommand = ExportSQLCommand;
|