@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,34 +1,66 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
"use strict";
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
3
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
4
|
+
if (k2 === undefined) k2 = k;
|
|
5
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
6
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
7
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
8
|
+
}
|
|
9
|
+
Object.defineProperty(o, k2, desc);
|
|
10
|
+
}) : (function(o, m, k, k2) {
|
|
11
|
+
if (k2 === undefined) k2 = k;
|
|
12
|
+
o[k2] = m[k];
|
|
13
|
+
}));
|
|
14
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
15
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
16
|
+
}) : function(o, v) {
|
|
17
|
+
o["default"] = v;
|
|
18
|
+
});
|
|
19
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
20
|
+
var ownKeys = function(o) {
|
|
21
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
22
|
+
var ar = [];
|
|
23
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
24
|
+
return ar;
|
|
25
|
+
};
|
|
26
|
+
return ownKeys(o);
|
|
27
|
+
};
|
|
28
|
+
return function (mod) {
|
|
29
|
+
if (mod && mod.__esModule) return mod;
|
|
30
|
+
var result = {};
|
|
31
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
32
|
+
__setModuleDefault(result, mod);
|
|
33
|
+
return result;
|
|
34
|
+
};
|
|
35
|
+
})();
|
|
36
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
37
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
38
|
+
};
|
|
39
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
40
|
+
exports.confirmSkipBackup = exports.promptToContinue = void 0;
|
|
7
41
|
exports.parseHeaders = parseHeaders;
|
|
8
|
-
exports.
|
|
42
|
+
exports.gates = gates;
|
|
9
43
|
exports.validateAndGetTableNames = validateAndGetTableNames;
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function (e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (const t in e) "default" !== t && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]); return f; })(e, t); }
|
|
31
|
-
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
44
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
45
|
+
const cli_columns_1 = __importDefault(require("cli-columns"));
|
|
46
|
+
const debug_1 = __importDefault(require("debug"));
|
|
47
|
+
const enquirer_1 = require("enquirer");
|
|
48
|
+
const graphql_tag_1 = __importDefault(require("graphql-tag"));
|
|
49
|
+
const api_1 = __importDefault(require("../lib/api"));
|
|
50
|
+
const command_1 = __importDefault(require("../lib/cli/command"));
|
|
51
|
+
const exit = __importStar(require("../lib/cli/exit"));
|
|
52
|
+
const format_1 = require("../lib/cli/format");
|
|
53
|
+
const progress_1 = require("../lib/cli/progress");
|
|
54
|
+
const prompt_1 = require("../lib/cli/prompt");
|
|
55
|
+
const client_file_uploader_1 = require("../lib/client-file-uploader");
|
|
56
|
+
const search_and_replace_1 = require("../lib/search-and-replace");
|
|
57
|
+
const db_file_import_1 = require("../lib/site-import/db-file-import");
|
|
58
|
+
const status_1 = require("../lib/site-import/status");
|
|
59
|
+
const tracker_1 = require("../lib/tracker");
|
|
60
|
+
const is_multi_site_1 = require("../lib/validations/is-multi-site");
|
|
61
|
+
const line_by_line_1 = require("../lib/validations/line-by-line");
|
|
62
|
+
const site_type_1 = require("../lib/validations/site-type");
|
|
63
|
+
const sql_1 = require("../lib/validations/sql");
|
|
32
64
|
const appQuery = `
|
|
33
65
|
id,
|
|
34
66
|
name,
|
|
@@ -50,7 +82,7 @@ const appQuery = `
|
|
|
50
82
|
}
|
|
51
83
|
}
|
|
52
84
|
`;
|
|
53
|
-
const START_IMPORT_MUTATION = (0,
|
|
85
|
+
const START_IMPORT_MUTATION = (0, graphql_tag_1.default) `
|
|
54
86
|
mutation StartImport($input: AppEnvironmentImportInput) {
|
|
55
87
|
startImport(input: $input) {
|
|
56
88
|
app {
|
|
@@ -63,70 +95,59 @@ const START_IMPORT_MUTATION = (0, _graphqlTag.default)`
|
|
|
63
95
|
}
|
|
64
96
|
`;
|
|
65
97
|
const usage = 'vip import sql';
|
|
66
|
-
const debug = (0,
|
|
67
|
-
const SQL_IMPORT_PREFLIGHT_PROGRESS_STEPS = [
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
},
|
|
71
|
-
|
|
72
|
-
name: 'Uploading file'
|
|
73
|
-
}, {
|
|
74
|
-
id: 'queue_import',
|
|
75
|
-
name: 'Queueing import'
|
|
76
|
-
}];
|
|
77
|
-
|
|
98
|
+
const debug = (0, debug_1.default)('@automattic/vip:bin:vip-import-sql');
|
|
99
|
+
const SQL_IMPORT_PREFLIGHT_PROGRESS_STEPS = [
|
|
100
|
+
{ id: 'replace', name: 'Performing search and replace' },
|
|
101
|
+
{ id: 'upload', name: 'Uploading file' },
|
|
102
|
+
{ id: 'queue_import', name: 'Queueing import' },
|
|
103
|
+
];
|
|
78
104
|
/**
|
|
79
105
|
* Check if a string is a valid URL
|
|
80
106
|
* @param {string} str - The string to check
|
|
81
107
|
* @returns {boolean} True if the string is a valid URL
|
|
82
108
|
*/
|
|
83
109
|
function isValidUrl(str) {
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
110
|
+
try {
|
|
111
|
+
const url = new URL(str);
|
|
112
|
+
return !/^[a-z]:$/iu.test(url.protocol);
|
|
113
|
+
}
|
|
114
|
+
catch {
|
|
115
|
+
return false;
|
|
116
|
+
}
|
|
90
117
|
}
|
|
91
|
-
|
|
92
118
|
/**
|
|
93
119
|
* Validate MD5 hash format
|
|
94
120
|
* @param {string} md5 - The MD5 hash to validate
|
|
95
121
|
* @returns {boolean} True if the hash is valid
|
|
96
122
|
*/
|
|
97
123
|
function isValidMd5(md5) {
|
|
98
|
-
|
|
124
|
+
return /^[a-f0-9]{32}$/i.test(md5);
|
|
99
125
|
}
|
|
100
|
-
|
|
101
126
|
/**
|
|
102
127
|
* Parse and validate headers from CLI input
|
|
103
128
|
* @param {string|string[]} headers - Header(s) in "Name: Value" format
|
|
104
129
|
* @returns {Array<{name: string, value: string}>} Parsed headers
|
|
105
130
|
*/
|
|
106
131
|
function parseHeaders(headers) {
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
});
|
|
126
|
-
}
|
|
127
|
-
return parsedHeaders;
|
|
132
|
+
if (!headers) {
|
|
133
|
+
return [];
|
|
134
|
+
}
|
|
135
|
+
const headerArray = Array.isArray(headers) ? headers : [headers];
|
|
136
|
+
const parsedHeaders = [];
|
|
137
|
+
for (const header of headerArray) {
|
|
138
|
+
const colonIndex = header.indexOf(':');
|
|
139
|
+
if (colonIndex === -1) {
|
|
140
|
+
exit.withError(`Invalid header format: "${header}". Expected format: "Name: Value"`);
|
|
141
|
+
}
|
|
142
|
+
const name = header.substring(0, colonIndex).trim();
|
|
143
|
+
const value = header.substring(colonIndex + 1).trim();
|
|
144
|
+
if (!name) {
|
|
145
|
+
exit.withError(`Invalid header format: "${header}". Header name cannot be empty.`);
|
|
146
|
+
}
|
|
147
|
+
parsedHeaders.push({ name, value });
|
|
148
|
+
}
|
|
149
|
+
return parsedHeaders;
|
|
128
150
|
}
|
|
129
|
-
|
|
130
151
|
/**
|
|
131
152
|
* @param {import('../lib/site-import/db-file-import').AppForImport} app
|
|
132
153
|
* @param {import('../lib/site-import/db-file-import').EnvForImport} env
|
|
@@ -136,556 +157,475 @@ function parseHeaders(headers) {
|
|
|
136
157
|
*/
|
|
137
158
|
// eslint-disable-next-line complexity
|
|
138
159
|
async function gates(app, env, fileNameOrURL, isUrl = false, md5 = null) {
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
if (md5 && !isValidMd5(md5)) {
|
|
145
|
-
await track('import_sql_command_error', {
|
|
146
|
-
error_type: 'invalid-md5'
|
|
147
|
-
});
|
|
148
|
-
exit.withError('The provided MD5 hash is invalid. It should be a 32-character hexadecimal string.');
|
|
149
|
-
}
|
|
150
|
-
if (!isUrl && md5) {
|
|
151
|
-
console.log(_chalk.default.yellowBright('The --md5 parameter is only valid for imports from a remote URL. This option will be ignored.'));
|
|
152
|
-
}
|
|
153
|
-
if (!isUrl) {
|
|
154
|
-
const fileName = fileNameOrURL;
|
|
155
|
-
const fileMeta = await (0, _clientFileUploader.getFileMeta)(fileName);
|
|
156
|
-
try {
|
|
157
|
-
// Extract base file name and exit if it contains unsafe character
|
|
158
|
-
(0, _sql.validateFilename)(fileMeta.basename);
|
|
159
|
-
} catch (error) {
|
|
160
|
-
await track('import_sql_command_error', {
|
|
161
|
-
error_type: 'invalid-filename'
|
|
162
|
-
});
|
|
163
|
-
exit.withError(error);
|
|
160
|
+
const { id: envId, appId } = env;
|
|
161
|
+
const track = tracker_1.trackEventWithEnv.bind(null, appId, envId);
|
|
162
|
+
if (md5 && !isValidMd5(md5)) {
|
|
163
|
+
await track('import_sql_command_error', { error_type: 'invalid-md5' });
|
|
164
|
+
exit.withError('The provided MD5 hash is invalid. It should be a 32-character hexadecimal string.');
|
|
164
165
|
}
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
166
|
+
if (!isUrl && md5) {
|
|
167
|
+
console.log(chalk_1.default.yellowBright('The --md5 parameter is only valid for imports from a remote URL. This option will be ignored.'));
|
|
168
|
+
}
|
|
169
|
+
if (!isUrl) {
|
|
170
|
+
const fileName = fileNameOrURL;
|
|
171
|
+
const fileMeta = await (0, client_file_uploader_1.getFileMeta)(fileName);
|
|
172
|
+
try {
|
|
173
|
+
// Extract base file name and exit if it contains unsafe character
|
|
174
|
+
(0, sql_1.validateFilename)(fileMeta.basename);
|
|
175
|
+
}
|
|
176
|
+
catch (error) {
|
|
177
|
+
await track('import_sql_command_error', { error_type: 'invalid-filename' });
|
|
178
|
+
exit.withError(error);
|
|
179
|
+
}
|
|
180
|
+
try {
|
|
181
|
+
(0, sql_1.validateImportFileExtension)(fileName);
|
|
182
|
+
}
|
|
183
|
+
catch (error) {
|
|
184
|
+
await track('import_sql_command_error', { error_type: 'invalid-extension' });
|
|
185
|
+
exit.withError(error);
|
|
186
|
+
}
|
|
187
|
+
try {
|
|
188
|
+
await (0, client_file_uploader_1.checkFileAccess)(fileName);
|
|
189
|
+
}
|
|
190
|
+
catch {
|
|
191
|
+
await track('import_sql_command_error', { error_type: 'sqlfile-unreadable' });
|
|
192
|
+
exit.withError(`File '${fileName}' does not exist or is not readable.`);
|
|
193
|
+
}
|
|
194
|
+
if (!(await (0, client_file_uploader_1.isFile)(fileName))) {
|
|
195
|
+
await track('import_sql_command_error', { error_type: 'sqlfile-notfile' });
|
|
196
|
+
exit.withError(`Path '${fileName}' is not a file.`);
|
|
197
|
+
}
|
|
198
|
+
const fileSize = await (0, client_file_uploader_1.getFileSize)(fileName);
|
|
199
|
+
if (!fileSize) {
|
|
200
|
+
await track('import_sql_command_error', { error_type: 'sqlfile-empty' });
|
|
201
|
+
exit.withError(`File '${fileName}' is empty.`);
|
|
202
|
+
}
|
|
203
|
+
const maxFileSize = env?.launched
|
|
204
|
+
? db_file_import_1.SQL_IMPORT_FILE_SIZE_LIMIT_LAUNCHED
|
|
205
|
+
: db_file_import_1.SQL_IMPORT_FILE_SIZE_LIMIT;
|
|
206
|
+
if (fileSize > maxFileSize) {
|
|
207
|
+
await track('import_sql_command_error', {
|
|
208
|
+
error_type: 'sqlfile-toobig',
|
|
209
|
+
file_size: fileSize,
|
|
210
|
+
launched: Boolean(env?.launched),
|
|
211
|
+
});
|
|
212
|
+
exit.withError(`The sql import file size (${fileSize} bytes) exceeds the limit (${maxFileSize} bytes).` +
|
|
213
|
+
(env.launched
|
|
214
|
+
? ' Note: This limit is lower for launched environments to maintain site stability.'
|
|
215
|
+
: '') +
|
|
216
|
+
'\n\nPlease split it into multiple files or contact support for assistance.');
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
if (!(0, db_file_import_1.currentUserCanImportForApp)(app)) {
|
|
220
|
+
await track('import_sql_command_error', { error_type: 'unauthorized' });
|
|
221
|
+
exit.withError('The currently authenticated account does not have permission to perform a SQL import.');
|
|
222
|
+
}
|
|
223
|
+
if (!(0, db_file_import_1.isSupportedApp)(app)) {
|
|
224
|
+
await track('import_sql_command_error', { error_type: 'unsupported-app' });
|
|
225
|
+
exit.withError('The type of application you specified does not currently support SQL imports.');
|
|
226
|
+
}
|
|
227
|
+
if (!env?.importStatus) {
|
|
228
|
+
await track('import_sql_command_error', { error_type: 'empty-import-status' });
|
|
229
|
+
exit.withError('Could not determine the import status for this environment. Check the app/environment and if the problem persists, contact support for assistance.');
|
|
230
|
+
}
|
|
231
|
+
const { importStatus: { dbOperationInProgress, importInProgress }, } = env;
|
|
232
|
+
if (importInProgress) {
|
|
233
|
+
await track('import_sql_command_error', { error_type: 'existing-import' });
|
|
234
|
+
exit.withError('There is already an import in progress.\n\nYou can view the status with command:\n vip import sql status');
|
|
235
|
+
}
|
|
236
|
+
if (dbOperationInProgress) {
|
|
237
|
+
await track('import_sql_command_error', { error_type: 'existing-dbop' });
|
|
238
|
+
exit.withError('There is already a database operation in progress. Please try again later.');
|
|
172
239
|
}
|
|
173
|
-
try {
|
|
174
|
-
await (0, _clientFileUploader.checkFileAccess)(fileName);
|
|
175
|
-
} catch {
|
|
176
|
-
await track('import_sql_command_error', {
|
|
177
|
-
error_type: 'sqlfile-unreadable'
|
|
178
|
-
});
|
|
179
|
-
exit.withError(`File '${fileName}' does not exist or is not readable.`);
|
|
180
|
-
}
|
|
181
|
-
if (!(await (0, _clientFileUploader.isFile)(fileName))) {
|
|
182
|
-
await track('import_sql_command_error', {
|
|
183
|
-
error_type: 'sqlfile-notfile'
|
|
184
|
-
});
|
|
185
|
-
exit.withError(`Path '${fileName}' is not a file.`);
|
|
186
|
-
}
|
|
187
|
-
const fileSize = await (0, _clientFileUploader.getFileSize)(fileName);
|
|
188
|
-
if (!fileSize) {
|
|
189
|
-
await track('import_sql_command_error', {
|
|
190
|
-
error_type: 'sqlfile-empty'
|
|
191
|
-
});
|
|
192
|
-
exit.withError(`File '${fileName}' is empty.`);
|
|
193
|
-
}
|
|
194
|
-
const maxFileSize = env?.launched ? _dbFileImport.SQL_IMPORT_FILE_SIZE_LIMIT_LAUNCHED : _dbFileImport.SQL_IMPORT_FILE_SIZE_LIMIT;
|
|
195
|
-
if (fileSize > maxFileSize) {
|
|
196
|
-
await track('import_sql_command_error', {
|
|
197
|
-
error_type: 'sqlfile-toobig',
|
|
198
|
-
file_size: fileSize,
|
|
199
|
-
launched: Boolean(env?.launched)
|
|
200
|
-
});
|
|
201
|
-
exit.withError(`The sql import file size (${fileSize} bytes) exceeds the limit (${maxFileSize} bytes).` + (env.launched ? ' Note: This limit is lower for launched environments to maintain site stability.' : '') + '\n\nPlease split it into multiple files or contact support for assistance.');
|
|
202
|
-
}
|
|
203
|
-
}
|
|
204
|
-
if (!(0, _dbFileImport.currentUserCanImportForApp)(app)) {
|
|
205
|
-
await track('import_sql_command_error', {
|
|
206
|
-
error_type: 'unauthorized'
|
|
207
|
-
});
|
|
208
|
-
exit.withError('The currently authenticated account does not have permission to perform a SQL import.');
|
|
209
|
-
}
|
|
210
|
-
if (!(0, _dbFileImport.isSupportedApp)(app)) {
|
|
211
|
-
await track('import_sql_command_error', {
|
|
212
|
-
error_type: 'unsupported-app'
|
|
213
|
-
});
|
|
214
|
-
exit.withError('The type of application you specified does not currently support SQL imports.');
|
|
215
|
-
}
|
|
216
|
-
if (!env?.importStatus) {
|
|
217
|
-
await track('import_sql_command_error', {
|
|
218
|
-
error_type: 'empty-import-status'
|
|
219
|
-
});
|
|
220
|
-
exit.withError('Could not determine the import status for this environment. Check the app/environment and if the problem persists, contact support for assistance.');
|
|
221
|
-
}
|
|
222
|
-
const {
|
|
223
|
-
importStatus: {
|
|
224
|
-
dbOperationInProgress,
|
|
225
|
-
importInProgress
|
|
226
|
-
}
|
|
227
|
-
} = env;
|
|
228
|
-
if (importInProgress) {
|
|
229
|
-
await track('import_sql_command_error', {
|
|
230
|
-
error_type: 'existing-import'
|
|
231
|
-
});
|
|
232
|
-
exit.withError('There is already an import in progress.\n\nYou can view the status with command:\n vip import sql status');
|
|
233
|
-
}
|
|
234
|
-
if (dbOperationInProgress) {
|
|
235
|
-
await track('import_sql_command_error', {
|
|
236
|
-
error_type: 'existing-dbop'
|
|
237
|
-
});
|
|
238
|
-
exit.withError('There is already a database operation in progress. Please try again later.');
|
|
239
|
-
}
|
|
240
240
|
}
|
|
241
|
-
|
|
242
241
|
// Command examples for the `vip import sql` help prompt
|
|
243
242
|
const examples = [
|
|
244
|
-
// `sql` subcommand
|
|
245
|
-
{
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
},
|
|
249
|
-
// `search-replace` option
|
|
250
|
-
{
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
},
|
|
254
|
-
// `in-place` option
|
|
255
|
-
{
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
},
|
|
259
|
-
// `output` option
|
|
260
|
-
{
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
},
|
|
264
|
-
// remote URL import
|
|
265
|
-
{
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
},
|
|
269
|
-
// remote URL import with HTTP basic auth
|
|
270
|
-
{
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
},
|
|
274
|
-
// remote URL import with headers
|
|
275
|
-
{
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
},
|
|
279
|
-
// `sql status` subcommand
|
|
280
|
-
{
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
});
|
|
300
|
-
if (promptResponse.confirmedDomain.toUpperCase() !== promptToMatch) {
|
|
301
|
-
await track('import_sql_unexpected_tables');
|
|
302
|
-
exit.withError('The input did not match the expected environment label. Import aborted.');
|
|
303
|
-
}
|
|
243
|
+
// `sql` subcommand
|
|
244
|
+
{
|
|
245
|
+
usage: 'vip @example-app.develop import sql file.sql',
|
|
246
|
+
description: 'Import a local SQL database file named "file.sql" to the develop environment of the "example-app" application.',
|
|
247
|
+
},
|
|
248
|
+
// `search-replace` option
|
|
249
|
+
{
|
|
250
|
+
usage: 'vip @example-app.develop import sql file.sql --search-replace="from.example.com,to.example.com" --search-replace="example.com/from,example.com/to"',
|
|
251
|
+
description: 'Perform multiple search and replace operations on a local SQL database file during the import process.',
|
|
252
|
+
},
|
|
253
|
+
// `in-place` option
|
|
254
|
+
{
|
|
255
|
+
usage: 'vip @example-app.develop import sql file.sql --search-replace="https://from.example.com,https://to.example.com" --in-place',
|
|
256
|
+
description: 'Perform a search and replace operation on a local file named "file.sql", save the changes to the file, then import the updated file.',
|
|
257
|
+
},
|
|
258
|
+
// `output` option
|
|
259
|
+
{
|
|
260
|
+
usage: 'vip @example-app.develop import sql file.sql --search-replace="https://from.example.com,https://to.example.com" --output="updated-file.sql"',
|
|
261
|
+
description: 'At the completion of the import of a local SQL database file that was modified by a search and replace operation, create a copy of the file in its updated state and save it locally to a new file named "updated-file.sql".',
|
|
262
|
+
},
|
|
263
|
+
// remote URL import
|
|
264
|
+
{
|
|
265
|
+
usage: 'vip @example-app.develop import sql https://example.com/file.sql --md5=5d41402abc4b2a76b9719d911017c592',
|
|
266
|
+
description: 'Import a SQL database file from a remote URL and verify the integrity of its contents with an MD5 hash.',
|
|
267
|
+
},
|
|
268
|
+
// remote URL import with HTTP basic auth
|
|
269
|
+
{
|
|
270
|
+
usage: 'vip @example-app.develop import sql https://username:password@example.com/file.sql',
|
|
271
|
+
description: 'Access and import a remote SQL database file by formatting the URL with valid HTTP basic authentication credentials.',
|
|
272
|
+
},
|
|
273
|
+
// remote URL import with headers
|
|
274
|
+
{
|
|
275
|
+
usage: 'vip @example-app.develop import sql https://example.com/file.sql --header="Authorization: bearer-token-value"',
|
|
276
|
+
description: 'Access and import a SQL database file located at a remote URL by passing a valid authorization header and bearer token.',
|
|
277
|
+
},
|
|
278
|
+
// `sql status` subcommand
|
|
279
|
+
{
|
|
280
|
+
usage: 'vip @example-app.develop import sql status',
|
|
281
|
+
description: 'Check the status of the most recent SQL database import to the develop environment of the "example-app" application.\n' +
|
|
282
|
+
' * This will continue to poll until the import is complete.',
|
|
283
|
+
},
|
|
284
|
+
];
|
|
285
|
+
const promptToContinue = async ({ launched, formattedEnvironment, track, domain, isMultiSite, tableNames, }) => {
|
|
286
|
+
console.log();
|
|
287
|
+
const promptToMatch = domain.toUpperCase();
|
|
288
|
+
const source = !isMultiSite && tableNames?.length ? 'the above tables' : 'the above file';
|
|
289
|
+
const promptResponse = await (0, enquirer_1.prompt)({
|
|
290
|
+
type: 'input',
|
|
291
|
+
name: 'confirmedDomain',
|
|
292
|
+
message: `You are about to import ${source} into the ${launched ? 'launched' : 'unlaunched'} ${formattedEnvironment} environment ${chalk_1.default.yellow(domain)}.\nType '${chalk_1.default.yellow(promptToMatch)}' (without the quotes) to continue:\n`,
|
|
293
|
+
});
|
|
294
|
+
if (promptResponse.confirmedDomain.toUpperCase() !== promptToMatch) {
|
|
295
|
+
await track('import_sql_unexpected_tables');
|
|
296
|
+
exit.withError('The input did not match the expected environment label. Import aborted.');
|
|
297
|
+
}
|
|
304
298
|
};
|
|
305
|
-
|
|
299
|
+
exports.promptToContinue = promptToContinue;
|
|
306
300
|
/**
|
|
307
301
|
* Show a huge warning and prompt the user to confirm twice when skipping backup
|
|
308
302
|
*
|
|
309
303
|
* @param {Function} track - Tracking function
|
|
310
304
|
* @returns {Promise<boolean>} True if user confirmed both times, false otherwise
|
|
311
305
|
*/
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
firstConfirm
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
await track('
|
|
357
|
-
console.log(
|
|
358
|
-
|
|
359
|
-
return false;
|
|
360
|
-
}
|
|
361
|
-
await track('import_sql_skip_backup_confirmed');
|
|
362
|
-
console.log(_chalk.default.red('⚠️ Backup will be skipped. Proceeding with import...'));
|
|
363
|
-
return true;
|
|
306
|
+
const confirmSkipBackup = async (track) => {
|
|
307
|
+
console.log(chalk_1.default.bold.red('⚠️ WARNING ⚠️'));
|
|
308
|
+
console.log(chalk_1.default.red(chalk_1.default.bold.red('YOU ARE ABOUT TO SKIP CREATING A BACKUP BEFORE IMPORTING SQL!\n')));
|
|
309
|
+
console.log(chalk_1.default.bold.yellow('This action is EXTREMELY DANGEROUS and can result in:'));
|
|
310
|
+
console.log(chalk_1.default.bold.yellow('• Permanent data loss'));
|
|
311
|
+
console.log(chalk_1.default.bold.yellow('• Inability to automatically restore your database'));
|
|
312
|
+
console.log(chalk_1.default.bold.yellow('• Complete site failure'));
|
|
313
|
+
console.log(chalk_1.default.bold.red('There is NO way to undo this action once the import begins!\n'));
|
|
314
|
+
const importAbortedMsg = chalk_1.default.red('✗ Import aborted.');
|
|
315
|
+
try {
|
|
316
|
+
// First confirmation: y/n prompt
|
|
317
|
+
const firstConfirm = await (0, enquirer_1.prompt)({
|
|
318
|
+
type: 'confirm',
|
|
319
|
+
name: 'firstConfirm',
|
|
320
|
+
message: 'Are you absolutely certain you want to skip the backup?',
|
|
321
|
+
}).catch(() => {
|
|
322
|
+
return { firstConfirm: false };
|
|
323
|
+
});
|
|
324
|
+
if (!firstConfirm.firstConfirm) {
|
|
325
|
+
await track('import_sql_skip_backup_cancelled');
|
|
326
|
+
console.log(importAbortedMsg);
|
|
327
|
+
return false;
|
|
328
|
+
}
|
|
329
|
+
// Second confirmation: requires typing "yes"
|
|
330
|
+
const secondConfirm = await (0, enquirer_1.prompt)({
|
|
331
|
+
type: 'input',
|
|
332
|
+
name: 'secondConfirm',
|
|
333
|
+
message: `Type '${chalk_1.default.yellow('yes')}' (without quotes) to proceed WITHOUT creating a backup (this cannot be undone):\n`,
|
|
334
|
+
}).catch(() => {
|
|
335
|
+
return { secondConfirm: '' };
|
|
336
|
+
});
|
|
337
|
+
if (secondConfirm.secondConfirm?.toLowerCase() !== 'yes') {
|
|
338
|
+
await track('import_sql_skip_backup_cancelled');
|
|
339
|
+
console.error('Failed to confirm!');
|
|
340
|
+
console.log(importAbortedMsg);
|
|
341
|
+
return false;
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
catch (error) {
|
|
345
|
+
await track('import_sql_skip_backup_cancelled');
|
|
346
|
+
console.log(importAbortedMsg);
|
|
347
|
+
console.error(error);
|
|
348
|
+
return false;
|
|
349
|
+
}
|
|
350
|
+
await track('import_sql_skip_backup_confirmed');
|
|
351
|
+
console.log(chalk_1.default.red('⚠️ Backup will be skipped. Proceeding with import...'));
|
|
352
|
+
return true;
|
|
364
353
|
};
|
|
365
|
-
|
|
354
|
+
exports.confirmSkipBackup = confirmSkipBackup;
|
|
366
355
|
/**
|
|
367
356
|
* @returns {Promise<string[]>}
|
|
368
357
|
*/
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
try {
|
|
383
|
-
await (0, _lineByLine.fileLineValidations)(appId, envId, fileNameToUpload, validations, searchReplace);
|
|
384
|
-
} catch (validateErr) {
|
|
385
|
-
console.log('');
|
|
386
|
-
exit.withError(`${validateErr.message}\n
|
|
387
|
-
If you are confident that the file does not contain unsupported statements, you can retry the command with the ${_chalk.default.yellow('--skip-validate')} option.
|
|
358
|
+
async function validateAndGetTableNames({ skipValidate, appId, envId, fileNameToUpload, searchReplace, }) {
|
|
359
|
+
const validations = [sql_1.staticSqlValidations, site_type_1.siteTypeValidations];
|
|
360
|
+
if (skipValidate) {
|
|
361
|
+
console.log('Skipping SQL file validation.');
|
|
362
|
+
return [];
|
|
363
|
+
}
|
|
364
|
+
try {
|
|
365
|
+
await (0, line_by_line_1.fileLineValidations)(appId, envId, fileNameToUpload, validations, searchReplace);
|
|
366
|
+
}
|
|
367
|
+
catch (validateErr) {
|
|
368
|
+
console.log('');
|
|
369
|
+
exit.withError(`${validateErr.message}\n
|
|
370
|
+
If you are confident that the file does not contain unsupported statements, you can retry the command with the ${chalk_1.default.yellow('--skip-validate')} option.
|
|
388
371
|
`);
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
372
|
+
}
|
|
373
|
+
// this can only be called after static validation of the SQL file
|
|
374
|
+
return (0, sql_1.getTableNames)();
|
|
392
375
|
}
|
|
393
|
-
const displayPlaybook = ({
|
|
394
|
-
launched,
|
|
395
|
-
tableNames,
|
|
396
|
-
searchReplace,
|
|
397
|
-
fileName,
|
|
398
|
-
domain,
|
|
399
|
-
formattedEnvironment,
|
|
400
|
-
isMultiSite,
|
|
401
|
-
app
|
|
402
|
-
}) => {
|
|
403
|
-
console.log();
|
|
404
|
-
console.log(` importing: ${_chalk.default.blueBright(fileName)}`);
|
|
405
|
-
console.log(` to: ${_chalk.default.cyan(domain)}`);
|
|
406
|
-
console.log(` site: ${app.name} (${formattedEnvironment})`);
|
|
407
|
-
if (searchReplace?.length) {
|
|
408
|
-
const output = (from, to) => {
|
|
409
|
-
const message = ` s-r: ${_chalk.default.blue(from)} -> ${_chalk.default.blue(to)}`;
|
|
410
|
-
console.log(message);
|
|
411
|
-
};
|
|
412
|
-
(0, _format.formatSearchReplaceValues)(searchReplace, output);
|
|
413
|
-
}
|
|
414
|
-
if (isMultiSite) {
|
|
415
|
-
console.log(` multisite: ${isMultiSite.toString()}`);
|
|
416
|
-
}
|
|
417
|
-
if (!tableNames.length) {
|
|
418
|
-
debug('Validation was skipped. No playbook information will be displayed.');
|
|
419
|
-
} else {
|
|
420
|
-
// output the table names
|
|
376
|
+
const displayPlaybook = ({ launched, tableNames, searchReplace, fileName, domain, formattedEnvironment, isMultiSite, app, }) => {
|
|
421
377
|
console.log();
|
|
422
|
-
|
|
423
|
-
|
|
378
|
+
console.log(` importing: ${chalk_1.default.blueBright(fileName)}`);
|
|
379
|
+
console.log(` to: ${chalk_1.default.cyan(domain)}`);
|
|
380
|
+
console.log(` site: ${app.name} (${formattedEnvironment})`);
|
|
381
|
+
if (searchReplace?.length) {
|
|
382
|
+
const output = (from, to) => {
|
|
383
|
+
const message = ` s-r: ${chalk_1.default.blue(from)} -> ${chalk_1.default.blue(to)}`;
|
|
384
|
+
console.log(message);
|
|
385
|
+
};
|
|
386
|
+
(0, format_1.formatSearchReplaceValues)(searchReplace, output);
|
|
387
|
+
}
|
|
388
|
+
if (isMultiSite) {
|
|
389
|
+
console.log(` multisite: ${isMultiSite.toString()}`);
|
|
390
|
+
}
|
|
391
|
+
if (!tableNames.length) {
|
|
392
|
+
debug('Validation was skipped. No playbook information will be displayed.');
|
|
393
|
+
}
|
|
394
|
+
else {
|
|
395
|
+
// output the table names
|
|
396
|
+
console.log();
|
|
397
|
+
if (isMultiSite && launched) {
|
|
398
|
+
console.log(chalk_1.default.yellowBright('You are updating tables in a launched multisite environment. The performance of sites on the network might be impacted by this operation.'));
|
|
399
|
+
}
|
|
400
|
+
console.log('Tables that will be imported by this process:');
|
|
401
|
+
console.log((0, cli_columns_1.default)(tableNames));
|
|
424
402
|
}
|
|
425
|
-
console.log('Tables that will be imported by this process:');
|
|
426
|
-
console.log((0, _cliColumns.default)(tableNames));
|
|
427
|
-
}
|
|
428
403
|
};
|
|
429
|
-
(0,
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
})
|
|
437
|
-
|
|
438
|
-
.
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
appId
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
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
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
404
|
+
(0, command_1.default)({
|
|
405
|
+
appContext: true,
|
|
406
|
+
appQuery,
|
|
407
|
+
envContext: true,
|
|
408
|
+
requiredArgs: 1,
|
|
409
|
+
module: 'import-sql',
|
|
410
|
+
usage,
|
|
411
|
+
})
|
|
412
|
+
.command('status', 'Check the status of a SQL database import currently in progress.')
|
|
413
|
+
.option('skip-validate', 'Do not perform file validation prior to import. If the file contains unsupported entries, the import is likely to fail.')
|
|
414
|
+
.option('search-replace', 'Search for a string in a local or remote SQL database file and replace it with a new string. Separate the values by a comma only; no spaces (e.g. --search-replace="from,to"). Can be passed more than once.')
|
|
415
|
+
.option('in-place', 'Overwrite a local SQL database file with the results of a search and replace operation prior to import.')
|
|
416
|
+
.option('output', 'Save the results of a --search-replace operation that is run against a local SQL database file to a copy of that file. Accepts a local file path. Ignored when used with the --in-place option.')
|
|
417
|
+
.option('skip-maintenance-mode', 'Prevent an unlaunched environment from going into maintenance mode during the import of a local or remote SQL database file. Skipping maintenance mode can cause site instability during import.')
|
|
418
|
+
.option('md5', 'Verify the integrity of a remote SQL database file. Accepts an MD5 hash value.')
|
|
419
|
+
.option('header', 'Pass a header name and value (Formatted as "Name: Value") in a request for a remote SQL database file. Can be passed more than once for multiple headers and values.')
|
|
420
|
+
.option(['B', 'skip-backup'], 'Skip creating a backup before importing the SQL file. WARNING: This is extremely dangerous and can result in permanent data loss.')
|
|
421
|
+
.examples(examples)
|
|
422
|
+
// eslint-disable-next-line complexity
|
|
423
|
+
.argv(process.argv, async (arg, opts) => {
|
|
424
|
+
const { app, env } = opts;
|
|
425
|
+
const { skipValidate, searchReplace, skipMaintenanceMode, md5, header, skipBackup } = opts;
|
|
426
|
+
const { id: envId, appId } = env;
|
|
427
|
+
const [fileNameOrURL] = arg;
|
|
428
|
+
const isMultiSite = await (0, is_multi_site_1.isMultiSiteInSiteMeta)(appId, envId);
|
|
429
|
+
const isUrl = isValidUrl(fileNameOrURL);
|
|
430
|
+
// Parse and validate headers
|
|
431
|
+
const headers = parseHeaders(header);
|
|
432
|
+
if (!isUrl && headers.length > 0) {
|
|
433
|
+
console.log(chalk_1.default.yellowBright('The --header option is only valid for imports from a remote URL. This option will be ignored.'));
|
|
434
|
+
}
|
|
435
|
+
if (isUrl && opts.inPlace) {
|
|
436
|
+
console.log(chalk_1.default.yellowBright('The --in-place option is only valid for imports from a remote URL. This option will be ignored.'));
|
|
437
|
+
opts.inPlace = false;
|
|
438
|
+
}
|
|
439
|
+
if (isUrl && opts.output) {
|
|
440
|
+
console.log(chalk_1.default.yellowBright('The --output option is only valid for imports of a local file. This option will be ignored.'));
|
|
441
|
+
opts.output = undefined;
|
|
442
|
+
}
|
|
443
|
+
debug('Options: ', opts);
|
|
444
|
+
debug('Args: ', arg);
|
|
445
|
+
const track = tracker_1.trackEventWithEnv.bind(null, appId, envId);
|
|
446
|
+
await track('import_sql_command_execute', { is_url: isUrl });
|
|
447
|
+
// halt operation of the import based on some rules
|
|
448
|
+
await gates(app, env, fileNameOrURL, isUrl, md5);
|
|
449
|
+
// Log summary of import details
|
|
450
|
+
const domain = env?.primaryDomain?.name ? env.primaryDomain.name : `#${env.id}`;
|
|
451
|
+
const formattedEnvironment = (0, format_1.formatEnvironment)(opts.env.type);
|
|
452
|
+
const launched = opts.env.launched;
|
|
453
|
+
const fileNameToUpload = fileNameOrURL;
|
|
454
|
+
// SQL file validations - only for local files
|
|
455
|
+
let tableNames = [];
|
|
456
|
+
if (!isUrl) {
|
|
457
|
+
tableNames = await validateAndGetTableNames({
|
|
458
|
+
skipValidate,
|
|
459
|
+
appId,
|
|
460
|
+
envId,
|
|
461
|
+
fileNameToUpload,
|
|
462
|
+
searchReplace,
|
|
463
|
+
});
|
|
464
|
+
}
|
|
465
|
+
// display playbook of what will happen during execution
|
|
466
|
+
displayPlaybook({
|
|
467
|
+
launched,
|
|
468
|
+
tableNames,
|
|
469
|
+
searchReplace,
|
|
470
|
+
fileName: fileNameOrURL,
|
|
471
|
+
domain,
|
|
472
|
+
formattedEnvironment,
|
|
473
|
+
isMultiSite,
|
|
474
|
+
app,
|
|
497
475
|
});
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
}
|
|
537
|
-
|
|
538
|
-
/**
|
|
539
|
-
* =========== WARNING =============
|
|
540
|
-
*
|
|
541
|
-
* NO `console.log` after this point!
|
|
542
|
-
* Yes, even inside called functions.
|
|
543
|
-
* It will break the progress printing.
|
|
544
|
-
*
|
|
545
|
-
* =========== WARNING =============
|
|
546
|
-
*/
|
|
547
|
-
const progressTracker = new _progress.ProgressTracker(SQL_IMPORT_PREFLIGHT_PROGRESS_STEPS);
|
|
548
|
-
let status = 'running';
|
|
549
|
-
const setProgressTrackerPrefixAndSuffix = () => {
|
|
550
|
-
progressTracker.prefix = `
|
|
476
|
+
// PROMPT TO PROCEED WITH THE IMPORT
|
|
477
|
+
await (0, exports.promptToContinue)({
|
|
478
|
+
launched,
|
|
479
|
+
formattedEnvironment,
|
|
480
|
+
track,
|
|
481
|
+
domain,
|
|
482
|
+
isMultiSite,
|
|
483
|
+
tableNames,
|
|
484
|
+
});
|
|
485
|
+
if (skipBackup) {
|
|
486
|
+
const confirmed = await (0, exports.confirmSkipBackup)(track);
|
|
487
|
+
if (!confirmed) {
|
|
488
|
+
process.exit(0);
|
|
489
|
+
}
|
|
490
|
+
}
|
|
491
|
+
if (!isUrl && opts.inPlace) {
|
|
492
|
+
const approved = await (0, prompt_1.confirm)([], 'Are you sure you want to run search and replace on your input file? This operation is not reversible.');
|
|
493
|
+
if (!approved) {
|
|
494
|
+
await (0, tracker_1.trackEventWithEnv)('search_replace_in_place_cancelled', {
|
|
495
|
+
is_import: true,
|
|
496
|
+
in_place: opts.inPlace,
|
|
497
|
+
});
|
|
498
|
+
process.exit();
|
|
499
|
+
}
|
|
500
|
+
}
|
|
501
|
+
/**
|
|
502
|
+
* =========== WARNING =============
|
|
503
|
+
*
|
|
504
|
+
* NO `console.log` after this point!
|
|
505
|
+
* Yes, even inside called functions.
|
|
506
|
+
* It will break the progress printing.
|
|
507
|
+
*
|
|
508
|
+
* =========== WARNING =============
|
|
509
|
+
*/
|
|
510
|
+
const progressTracker = new progress_1.ProgressTracker(SQL_IMPORT_PREFLIGHT_PROGRESS_STEPS);
|
|
511
|
+
let status = 'running';
|
|
512
|
+
const setProgressTrackerPrefixAndSuffix = () => {
|
|
513
|
+
progressTracker.prefix = `
|
|
551
514
|
=============================================================
|
|
552
515
|
Processing the SQL import for your environment...
|
|
553
516
|
`;
|
|
554
|
-
|
|
555
|
-
};
|
|
556
|
-
const failWithError = failureError => {
|
|
557
|
-
status = 'failed';
|
|
558
|
-
setProgressTrackerPrefixAndSuffix();
|
|
559
|
-
progressTracker.stopPrinting();
|
|
560
|
-
progressTracker.print({
|
|
561
|
-
clearAfter: true
|
|
562
|
-
});
|
|
563
|
-
exit.withError(failureError);
|
|
564
|
-
};
|
|
565
|
-
progressTracker.startPrinting(setProgressTrackerPrefixAndSuffix);
|
|
566
|
-
|
|
567
|
-
// Run Search and Replace if the --search-replace flag was provided (local files only)
|
|
568
|
-
if (!isUrl && searchReplace && searchReplace.length) {
|
|
569
|
-
progressTracker.stepRunning('replace');
|
|
570
|
-
const {
|
|
571
|
-
outputFileName
|
|
572
|
-
} = await (0, _searchAndReplace.searchAndReplace)(fileNameOrURL, searchReplace, {
|
|
573
|
-
isImport: true,
|
|
574
|
-
inPlace: opts.inPlace,
|
|
575
|
-
output: opts.output ?? true,
|
|
576
|
-
batchMode: true
|
|
577
|
-
});
|
|
578
|
-
if (typeof outputFileName !== 'string') {
|
|
579
|
-
progressTracker.stepFailed('replace');
|
|
580
|
-
return failWithError('Unable to determine location of the intermediate search and replace file.');
|
|
581
|
-
}
|
|
582
|
-
progressTracker.stepSuccess('replace');
|
|
583
|
-
} else {
|
|
584
|
-
progressTracker.stepSkipped('replace');
|
|
585
|
-
}
|
|
586
|
-
|
|
587
|
-
// Call the Public API
|
|
588
|
-
const api = (0, _api.default)();
|
|
589
|
-
const startImportVariables = {
|
|
590
|
-
input: {
|
|
591
|
-
id: app.id,
|
|
592
|
-
environmentId: env.id,
|
|
593
|
-
skipMaintenanceMode,
|
|
594
|
-
...(skipBackup && {
|
|
595
|
-
skipBackup: true
|
|
596
|
-
})
|
|
597
|
-
}
|
|
598
|
-
};
|
|
599
|
-
if (isUrl) {
|
|
600
|
-
progressTracker.stepSkipped('upload');
|
|
601
|
-
startImportVariables.input = {
|
|
602
|
-
...startImportVariables.input,
|
|
603
|
-
url: fileNameOrURL,
|
|
604
|
-
searchReplace: [],
|
|
605
|
-
md5,
|
|
606
|
-
urlHeaders: headers
|
|
517
|
+
progressTracker.suffix = `\n${(0, format_1.getGlyphForStatus)(status, progressTracker.runningSprite)} ${status === 'running' ? 'Loading remaining steps' : ''}`;
|
|
607
518
|
};
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
519
|
+
const failWithError = failureError => {
|
|
520
|
+
status = 'failed';
|
|
521
|
+
setProgressTrackerPrefixAndSuffix();
|
|
522
|
+
progressTracker.stopPrinting();
|
|
523
|
+
progressTracker.print({ clearAfter: true });
|
|
524
|
+
exit.withError(failureError);
|
|
613
525
|
};
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
526
|
+
progressTracker.startPrinting(setProgressTrackerPrefixAndSuffix);
|
|
527
|
+
// Run Search and Replace if the --search-replace flag was provided (local files only)
|
|
528
|
+
if (!isUrl && searchReplace && searchReplace.length) {
|
|
529
|
+
progressTracker.stepRunning('replace');
|
|
530
|
+
const { outputFileName } = await (0, search_and_replace_1.searchAndReplace)(fileNameOrURL, searchReplace, {
|
|
531
|
+
isImport: true,
|
|
532
|
+
inPlace: opts.inPlace,
|
|
533
|
+
output: opts.output ?? true,
|
|
534
|
+
batchMode: true,
|
|
535
|
+
});
|
|
536
|
+
if (typeof outputFileName !== 'string') {
|
|
537
|
+
progressTracker.stepFailed('replace');
|
|
538
|
+
return failWithError('Unable to determine location of the intermediate search and replace file.');
|
|
539
|
+
}
|
|
540
|
+
progressTracker.stepSuccess('replace');
|
|
541
|
+
}
|
|
542
|
+
else {
|
|
543
|
+
progressTracker.stepSkipped('replace');
|
|
544
|
+
}
|
|
545
|
+
// Call the Public API
|
|
546
|
+
const api = (0, api_1.default)();
|
|
547
|
+
const startImportVariables = {
|
|
548
|
+
input: {
|
|
549
|
+
id: app.id,
|
|
550
|
+
environmentId: env.id,
|
|
551
|
+
skipMaintenanceMode,
|
|
552
|
+
...(skipBackup && { skipBackup: true }),
|
|
619
553
|
},
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
});
|
|
554
|
+
};
|
|
555
|
+
if (isUrl) {
|
|
556
|
+
progressTracker.stepSkipped('upload');
|
|
557
|
+
startImportVariables.input = {
|
|
558
|
+
...startImportVariables.input,
|
|
559
|
+
url: fileNameOrURL,
|
|
560
|
+
searchReplace: [],
|
|
561
|
+
md5,
|
|
562
|
+
urlHeaders: headers,
|
|
563
|
+
};
|
|
564
|
+
}
|
|
565
|
+
else {
|
|
566
|
+
progressTracker.stepRunning('upload');
|
|
567
|
+
const fileMeta = await (0, client_file_uploader_1.getFileMeta)(fileNameOrURL);
|
|
568
|
+
const progressCallback = percentage => {
|
|
569
|
+
progressTracker.setUploadPercentage(percentage);
|
|
570
|
+
};
|
|
571
|
+
fileMeta.fileName = fileNameToUpload;
|
|
572
|
+
try {
|
|
573
|
+
const { fileMeta: { basename }, checksum: uploadedMD5, result, } = await (0, client_file_uploader_1.uploadImportFileToS3)({
|
|
574
|
+
app,
|
|
575
|
+
env,
|
|
576
|
+
fileMeta,
|
|
577
|
+
progressCallback,
|
|
578
|
+
});
|
|
579
|
+
startImportVariables.input = {
|
|
580
|
+
...startImportVariables.input,
|
|
581
|
+
basename,
|
|
582
|
+
md5: uploadedMD5,
|
|
583
|
+
searchReplace: [],
|
|
584
|
+
};
|
|
585
|
+
debug({ basename, uploadedMD5, result, startImportVariables });
|
|
586
|
+
debug('Upload complete. Initiating the import.');
|
|
587
|
+
progressTracker.stepSuccess('upload');
|
|
588
|
+
await track('import_sql_upload_complete');
|
|
589
|
+
}
|
|
590
|
+
catch (uploadError) {
|
|
591
|
+
await track('import_sql_command_error', {
|
|
592
|
+
error_type: 'upload_failed',
|
|
593
|
+
upload_error: uploadError.message,
|
|
594
|
+
});
|
|
595
|
+
progressTracker.stepFailed('upload');
|
|
596
|
+
return failWithError(uploadError);
|
|
597
|
+
}
|
|
598
|
+
}
|
|
599
|
+
if (searchReplace) {
|
|
600
|
+
let pairs = searchReplace;
|
|
601
|
+
if (!Array.isArray(pairs)) {
|
|
602
|
+
pairs = [searchReplace];
|
|
603
|
+
}
|
|
604
|
+
// determine all the replacements required
|
|
605
|
+
const replacementsArr = pairs.map(pair => pair.split(',').map(str => str.trim()));
|
|
606
|
+
startImportVariables.input.searchReplace = replacementsArr.map(arr => {
|
|
607
|
+
return {
|
|
608
|
+
from: arr[0],
|
|
609
|
+
to: arr[1],
|
|
610
|
+
};
|
|
611
|
+
});
|
|
612
|
+
}
|
|
613
|
+
// Start the import
|
|
614
|
+
try {
|
|
615
|
+
const startImportResults = await api.mutate({
|
|
616
|
+
mutation: START_IMPORT_MUTATION,
|
|
617
|
+
variables: startImportVariables,
|
|
618
|
+
});
|
|
619
|
+
debug({ startImportResults });
|
|
620
|
+
}
|
|
621
|
+
catch (gqlErr) {
|
|
622
|
+
await track('import_sql_command_error', {
|
|
623
|
+
error_type: 'StartImport-failed',
|
|
624
|
+
gql_err: gqlErr,
|
|
625
|
+
});
|
|
626
|
+
progressTracker.stepFailed('queue_import');
|
|
627
|
+
return failWithError(`StartImport call failed: ${gqlErr}`);
|
|
628
|
+
}
|
|
629
|
+
progressTracker.stepSuccess('queue_import');
|
|
630
|
+
await (0, status_1.importSqlCheckStatus)({ app, env, progressTracker });
|
|
631
|
+
});
|