@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.
Files changed (311) hide show
  1. package/assets/dev-env.lando.template.yml.ejs +1 -1
  2. package/dist/bin/vip-app-deploy-token-generate.js +110 -78
  3. package/dist/bin/vip-app-deploy-token.js +24 -16
  4. package/dist/bin/vip-app-deploy-validate.js +45 -41
  5. package/dist/bin/vip-app-deploy.js +222 -215
  6. package/dist/bin/vip-app-list.js +59 -43
  7. package/dist/bin/vip-app.js +97 -66
  8. package/dist/bin/vip-backup-db.js +36 -29
  9. package/dist/bin/vip-backup.js +16 -9
  10. package/dist/bin/vip-cache-purge-url.js +93 -55
  11. package/dist/bin/vip-cache.js +23 -14
  12. package/dist/bin/vip-config-envvar-delete.js +74 -73
  13. package/dist/bin/vip-config-envvar-get-all.js +68 -68
  14. package/dist/bin/vip-config-envvar-get.js +46 -46
  15. package/dist/bin/vip-config-envvar-list.js +54 -57
  16. package/dist/bin/vip-config-envvar-set.js +102 -96
  17. package/dist/bin/vip-config-envvar.js +38 -24
  18. package/dist/bin/vip-config-software-get.js +88 -75
  19. package/dist/bin/vip-config-software-update.js +116 -120
  20. package/dist/bin/vip-config-software.js +31 -21
  21. package/dist/bin/vip-config.js +25 -17
  22. package/dist/bin/vip-db-phpmyadmin.js +40 -39
  23. package/dist/bin/vip-db.js +13 -12
  24. package/dist/bin/vip-defensive-mode-configure.js +197 -197
  25. package/dist/bin/vip-defensive-mode-disable.js +43 -35
  26. package/dist/bin/vip-defensive-mode-enable.js +47 -38
  27. package/dist/bin/vip-defensive-mode.js +28 -17
  28. package/dist/bin/vip-dev-env-create.js +147 -104
  29. package/dist/bin/vip-dev-env-destroy.js +48 -39
  30. package/dist/bin/vip-dev-env-envvar-delete.js +60 -49
  31. package/dist/bin/vip-dev-env-envvar-get-all.js +52 -45
  32. package/dist/bin/vip-dev-env-envvar-get.js +48 -37
  33. package/dist/bin/vip-dev-env-envvar-list.js +48 -41
  34. package/dist/bin/vip-dev-env-envvar-set.js +83 -70
  35. package/dist/bin/vip-dev-env-envvar.js +38 -23
  36. package/dist/bin/vip-dev-env-exec.js +81 -74
  37. package/dist/bin/vip-dev-env-import-media.js +34 -26
  38. package/dist/bin/vip-dev-env-import-sql.js +65 -51
  39. package/dist/bin/vip-dev-env-import.js +23 -14
  40. package/dist/bin/vip-dev-env-info.js +59 -50
  41. package/dist/bin/vip-dev-env-list.js +34 -31
  42. package/dist/bin/vip-dev-env-logs.js +59 -49
  43. package/dist/bin/vip-dev-env-purge.js +71 -63
  44. package/dist/bin/vip-dev-env-shell.js +82 -71
  45. package/dist/bin/vip-dev-env-start.js +77 -65
  46. package/dist/bin/vip-dev-env-stop.js +80 -74
  47. package/dist/bin/vip-dev-env-sync-sql.js +80 -72
  48. package/dist/bin/vip-dev-env-sync.js +18 -11
  49. package/dist/bin/vip-dev-env-update.js +93 -84
  50. package/dist/bin/vip-dev-env.js +25 -8
  51. package/dist/bin/vip-edge-workers-build.js +82 -54
  52. package/dist/bin/vip-edge-workers-delete.js +84 -52
  53. package/dist/bin/vip-edge-workers-deploy.js +186 -126
  54. package/dist/bin/vip-edge-workers-disable.js +75 -44
  55. package/dist/bin/vip-edge-workers-enable.js +86 -54
  56. package/dist/bin/vip-edge-workers-get.js +108 -88
  57. package/dist/bin/vip-edge-workers-init.js +83 -53
  58. package/dist/bin/vip-edge-workers-list.js +89 -54
  59. package/dist/bin/vip-edge-workers-new.js +98 -69
  60. package/dist/bin/vip-edge-workers-validate.js +123 -82
  61. package/dist/bin/vip-edge-workers.js +19 -6
  62. package/dist/bin/vip-export-sql.js +75 -69
  63. package/dist/bin/vip-export.js +12 -7
  64. package/dist/bin/vip-import-media-abort.js +99 -73
  65. package/dist/bin/vip-import-media-status.js +83 -51
  66. package/dist/bin/vip-import-media.js +165 -166
  67. package/dist/bin/vip-import-sql-status.js +75 -45
  68. package/dist/bin/vip-import-sql.js +536 -596
  69. package/dist/bin/vip-import-validate-files.js +122 -141
  70. package/dist/bin/vip-import-validate-sql.js +52 -16
  71. package/dist/bin/vip-import.js +16 -7
  72. package/dist/bin/vip-logout.js +17 -13
  73. package/dist/bin/vip-logs.js +209 -183
  74. package/dist/bin/vip-search-replace.js +85 -53
  75. package/dist/bin/vip-slowlogs.js +168 -147
  76. package/dist/bin/vip-sync.js +163 -133
  77. package/dist/bin/vip-whoami.js +71 -35
  78. package/dist/bin/vip-wp.js +506 -549
  79. package/dist/bin/vip.js +161 -116
  80. package/dist/commands/backup-db.js +183 -149
  81. package/dist/commands/dev-env-import-sql.js +162 -117
  82. package/dist/commands/dev-env-sync-sql.js +372 -330
  83. package/dist/commands/export-sql.js +441 -425
  84. package/dist/commands/phpmyadmin.js +232 -212
  85. package/dist/commands/wp-ssh.js +218 -187
  86. package/dist/lib/analytics/clients/tracks.js +84 -91
  87. package/dist/lib/analytics/index.js +27 -27
  88. package/dist/lib/api/app.js +37 -36
  89. package/dist/lib/api/cache-purge.js +17 -20
  90. package/dist/lib/api/constants.js +5 -6
  91. package/dist/lib/api/edge-workers.js +84 -135
  92. package/dist/lib/api/error-debug.js +10 -13
  93. package/dist/lib/api/feature-flags.js +16 -17
  94. package/dist/lib/api/http.js +47 -48
  95. package/dist/lib/api/user.js +17 -18
  96. package/dist/lib/api.js +107 -116
  97. package/dist/lib/app-logs/app-logs.js +24 -25
  98. package/dist/lib/app-slowlogs/app-slowlogs.js +23 -24
  99. package/dist/lib/app-slowlogs/types.js +2 -1
  100. package/dist/lib/app.js +6 -8
  101. package/dist/lib/backup-storage-availability/backup-storage-availability.js +119 -119
  102. package/dist/lib/backup-storage-availability/docker-machine-not-found-error.js +5 -6
  103. package/dist/lib/cli/apiConfig.js +71 -41
  104. package/dist/lib/cli/command.js +1120 -873
  105. package/dist/lib/cli/config.js +29 -29
  106. package/dist/lib/cli/envAlias.js +35 -50
  107. package/dist/lib/cli/exit.js +19 -19
  108. package/dist/lib/cli/format.js +172 -172
  109. package/dist/lib/cli/progress.js +193 -236
  110. package/dist/lib/cli/prompt.js +14 -15
  111. package/dist/lib/cli/runtime-mode.js +5 -6
  112. package/dist/lib/client-file-uploader.js +489 -641
  113. package/dist/lib/config/software.js +206 -212
  114. package/dist/lib/constants/dev-environment.js +40 -37
  115. package/dist/lib/constants/file-size.js +6 -7
  116. package/dist/lib/constants/vipgo.js +24 -12
  117. package/dist/lib/custom-deploy/custom-deploy.js +138 -120
  118. package/dist/lib/database.js +88 -85
  119. package/dist/lib/defensive-mode/api.js +41 -46
  120. package/dist/lib/defensive-mode/cli-helpers.js +40 -40
  121. package/dist/lib/dev-environment/dev-environment-cli.js +776 -735
  122. package/dist/lib/dev-environment/dev-environment-configuration-file.js +224 -191
  123. package/dist/lib/dev-environment/dev-environment-core.js +697 -732
  124. package/dist/lib/dev-environment/dev-environment-database.js +57 -41
  125. package/dist/lib/dev-environment/dev-environment-lando.js +734 -666
  126. package/dist/lib/dev-environment/docker-utils.js +96 -90
  127. package/dist/lib/dev-environment/env-vars.js +61 -59
  128. package/dist/lib/dev-environment/lando-loader.js +6 -7
  129. package/dist/lib/dev-environment/types.js +2 -1
  130. package/dist/lib/edge-workers/confirmation.js +42 -36
  131. package/dist/lib/edge-workers/deployment.js +150 -159
  132. package/dist/lib/edge-workers/index.js +68 -85
  133. package/dist/lib/edge-workers/location.js +26 -26
  134. package/dist/lib/edge-workers/output.js +14 -15
  135. package/dist/lib/edge-workers/project.js +123 -132
  136. package/dist/lib/edge-workers/toolchains/assemblyscript/constants.js +6 -8
  137. package/dist/lib/edge-workers/toolchains/assemblyscript/index.js +100 -101
  138. package/dist/lib/edge-workers/toolchains/assemblyscript/templates.js +31 -33
  139. package/dist/lib/edge-workers/toolchains/index.js +15 -15
  140. package/dist/lib/edge-workers/types.js +10 -38
  141. package/dist/lib/edge-workers/validation.js +161 -150
  142. package/dist/lib/env.js +16 -17
  143. package/dist/lib/envvar/api-delete.js +16 -18
  144. package/dist/lib/envvar/api-get-all.js +15 -19
  145. package/dist/lib/envvar/api-get.js +8 -9
  146. package/dist/lib/envvar/api-list.js +16 -21
  147. package/dist/lib/envvar/api-set.js +20 -19
  148. package/dist/lib/envvar/api.js +34 -29
  149. package/dist/lib/envvar/input.js +29 -34
  150. package/dist/lib/envvar/logging.js +9 -11
  151. package/dist/lib/envvar/read-file.js +6 -7
  152. package/dist/lib/http/download-file.js +76 -44
  153. package/dist/lib/http/proxy-agent.js +37 -40
  154. package/dist/lib/http/proxy-dispatcher.js +69 -71
  155. package/dist/lib/keychain/insecure.js +40 -36
  156. package/dist/lib/keychain/keychain.js +2 -1
  157. package/dist/lib/keychain/secure.js +16 -15
  158. package/dist/lib/keychain.js +22 -22
  159. package/dist/lib/live-backup-copy.js +117 -115
  160. package/dist/lib/logout.js +17 -19
  161. package/dist/lib/media-import/config.js +15 -14
  162. package/dist/lib/media-import/media-file-import.js +9 -13
  163. package/dist/lib/media-import/progress.js +53 -65
  164. package/dist/lib/media-import/status.js +241 -256
  165. package/dist/lib/media-import/utils.js +15 -15
  166. package/dist/lib/node-version-check.js +16 -16
  167. package/dist/lib/promise.js +16 -17
  168. package/dist/lib/read-file.js +48 -16
  169. package/dist/lib/rechallenge/client.js +37 -43
  170. package/dist/lib/rechallenge/errors.js +38 -37
  171. package/dist/lib/rechallenge/flow.js +148 -123
  172. package/dist/lib/rechallenge/index.js +23 -24
  173. package/dist/lib/rechallenge/link.js +153 -151
  174. package/dist/lib/rechallenge/open-browser.js +14 -17
  175. package/dist/lib/rechallenge/token-cache.js +83 -86
  176. package/dist/lib/rechallenge/types.js +5 -14
  177. package/dist/lib/retry.js +93 -129
  178. package/dist/lib/search-and-replace.js +164 -148
  179. package/dist/lib/site-import/db-file-import.js +12 -16
  180. package/dist/lib/site-import/status.js +291 -291
  181. package/dist/lib/token.js +86 -87
  182. package/dist/lib/tracker.js +51 -62
  183. package/dist/lib/types/graphql/rate-limit-exceeded-error.js +2 -1
  184. package/dist/lib/types.js +2 -1
  185. package/dist/lib/user-error.js +6 -8
  186. package/dist/lib/utils.js +81 -87
  187. package/dist/lib/validations/custom-deploy.js +218 -186
  188. package/dist/lib/validations/is-multi-site-sql-dump.js +6 -6
  189. package/dist/lib/validations/is-multi-site.js +83 -50
  190. package/dist/lib/validations/is-multisite-domain-mapped.js +92 -62
  191. package/dist/lib/validations/line-by-line.js +78 -46
  192. package/dist/lib/validations/site-type.js +59 -63
  193. package/dist/lib/validations/sql-insert-parser.js +415 -0
  194. package/dist/lib/validations/sql.js +551 -431
  195. package/dist/lib/validations/utils.js +27 -29
  196. package/dist/lib/vip-import-validate-files.js +481 -490
  197. package/dist/lib/wp/helpers.js +41 -45
  198. package/dist/lib/wp/readline.js +21 -57
  199. package/dist/lib/xdg-data.js +11 -12
  200. package/helpers/mark-cli-executable.js +9 -0
  201. package/node_modules/@apollo/client/CHANGELOG.md +10 -0
  202. package/node_modules/@apollo/client/__cjs/cache/inmemory/helpers.cjs +5 -0
  203. package/node_modules/@apollo/client/__cjs/cache/inmemory/helpers.cjs.map +1 -1
  204. package/node_modules/@apollo/client/__cjs/cache/inmemory/inMemoryCache.cjs +2 -1
  205. package/node_modules/@apollo/client/__cjs/cache/inmemory/inMemoryCache.cjs.map +1 -1
  206. package/node_modules/@apollo/client/__cjs/cache/inmemory/key-extractor.cjs +14 -2
  207. package/node_modules/@apollo/client/__cjs/cache/inmemory/key-extractor.cjs.map +1 -1
  208. package/node_modules/@apollo/client/__cjs/cache/inmemory/policies.cjs +16 -0
  209. package/node_modules/@apollo/client/__cjs/cache/inmemory/policies.cjs.map +1 -1
  210. package/node_modules/@apollo/client/__cjs/cache/inmemory/policies.d.cts +2 -0
  211. package/node_modules/@apollo/client/__cjs/cache/inmemory/writeToStore.cjs +3 -2
  212. package/node_modules/@apollo/client/__cjs/cache/inmemory/writeToStore.cjs.map +1 -1
  213. package/node_modules/@apollo/client/__cjs/core/QueryInfo.cjs +9 -1
  214. package/node_modules/@apollo/client/__cjs/core/QueryInfo.cjs.map +1 -1
  215. package/node_modules/@apollo/client/__cjs/core/QueryInfo.d.cts +1 -1
  216. package/node_modules/@apollo/client/__cjs/core/QueryManager.cjs +10 -3
  217. package/node_modules/@apollo/client/__cjs/core/QueryManager.cjs.map +1 -1
  218. package/node_modules/@apollo/client/__cjs/react/hooks/useFragment.cjs.map +1 -1
  219. package/node_modules/@apollo/client/__cjs/react/hooks/useFragment.d.cts +42 -43
  220. package/node_modules/@apollo/client/__cjs/version.cjs +1 -1
  221. package/node_modules/@apollo/client/cache/inmemory/helpers.js +5 -0
  222. package/node_modules/@apollo/client/cache/inmemory/helpers.js.map +1 -1
  223. package/node_modules/@apollo/client/cache/inmemory/inMemoryCache.js +2 -1
  224. package/node_modules/@apollo/client/cache/inmemory/inMemoryCache.js.map +1 -1
  225. package/node_modules/@apollo/client/cache/inmemory/key-extractor.js +14 -2
  226. package/node_modules/@apollo/client/cache/inmemory/key-extractor.js.map +1 -1
  227. package/node_modules/@apollo/client/cache/inmemory/policies.d.ts +2 -0
  228. package/node_modules/@apollo/client/cache/inmemory/policies.js +17 -1
  229. package/node_modules/@apollo/client/cache/inmemory/policies.js.map +1 -1
  230. package/node_modules/@apollo/client/cache/inmemory/writeToStore.js +3 -2
  231. package/node_modules/@apollo/client/cache/inmemory/writeToStore.js.map +1 -1
  232. package/node_modules/@apollo/client/core/QueryInfo.d.ts +1 -1
  233. package/node_modules/@apollo/client/core/QueryInfo.js +10 -2
  234. package/node_modules/@apollo/client/core/QueryInfo.js.map +1 -1
  235. package/node_modules/@apollo/client/core/QueryManager.js +10 -3
  236. package/node_modules/@apollo/client/core/QueryManager.js.map +1 -1
  237. package/node_modules/@apollo/client/package.json +1 -1
  238. package/node_modules/@apollo/client/react/hooks/useFragment.d.ts +42 -43
  239. package/node_modules/@apollo/client/react/hooks/useFragment.js.map +1 -1
  240. package/node_modules/@apollo/client/react/hooks-compiled/useFragment.d.ts +42 -43
  241. package/node_modules/@apollo/client/react/hooks-compiled/useFragment.js.map +1 -1
  242. package/node_modules/@apollo/client/version.js +1 -1
  243. package/node_modules/@automattic/vip-search-replace/README.md +6 -1
  244. package/node_modules/@automattic/vip-search-replace/lib/index.js +46 -14
  245. package/node_modules/@automattic/vip-search-replace/package.json +1 -1
  246. package/node_modules/@types/node/README.md +1 -1
  247. package/node_modules/@types/node/package.json +2 -2
  248. package/node_modules/@types/node/zlib.d.ts +752 -0
  249. package/node_modules/check-disk-space/README.md +92 -32
  250. package/node_modules/check-disk-space/dist/check-disk-space.d.mts +58 -0
  251. package/node_modules/check-disk-space/dist/check-disk-space.mjs +170 -190
  252. package/node_modules/check-disk-space/package.json +43 -71
  253. package/node_modules/cpu-features/build/Makefile +2 -2
  254. package/node_modules/cpu-features/build/Release/.deps/Release/obj.target/cpu_features/deps/cpu_features/src/filesystem.o.d +1 -1
  255. 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
  256. 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
  257. package/node_modules/cpu-features/build/Release/.deps/Release/obj.target/cpu_features/deps/cpu_features/src/impl_aarch64_windows.o.d +1 -1
  258. 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
  259. 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
  260. package/node_modules/cpu-features/build/Release/.deps/Release/obj.target/cpu_features/deps/cpu_features/src/impl_ppc_linux.o.d +1 -1
  261. package/node_modules/cpu-features/build/Release/.deps/Release/obj.target/cpu_features/deps/cpu_features/src/impl_x86_freebsd.o.d +1 -1
  262. 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
  263. package/node_modules/cpu-features/build/Release/.deps/Release/obj.target/cpu_features/deps/cpu_features/src/impl_x86_macos.o.d +1 -1
  264. package/node_modules/cpu-features/build/Release/.deps/Release/obj.target/cpu_features/deps/cpu_features/src/impl_x86_windows.o.d +1 -1
  265. package/node_modules/cpu-features/build/Release/.deps/Release/obj.target/cpu_features/deps/cpu_features/src/stack_line_reader.o.d +1 -1
  266. package/node_modules/cpu-features/build/Release/.deps/Release/obj.target/cpu_features/deps/cpu_features/src/string_view.o.d +1 -1
  267. package/node_modules/cpu-features/build/Release/.deps/Release/obj.target/cpufeatures/src/binding.o.d +157 -145
  268. package/node_modules/cpu-features/build/Release/cpufeatures.node +0 -0
  269. package/node_modules/cpu-features/build/Release/obj.target/cpufeatures/src/binding.o +0 -0
  270. package/node_modules/cpu-features/build/Release/obj.target/cpufeatures.node +0 -0
  271. package/node_modules/cpu-features/build/config.gypi +100 -31
  272. package/node_modules/cpu-features/build/cpufeatures.target.mk +14 -14
  273. package/node_modules/cpu-features/build/deps/cpu_features/cpu_features.target.mk +14 -14
  274. package/node_modules/ssh2/lib/protocol/crypto/build/Makefile +2 -2
  275. package/node_modules/ssh2/lib/protocol/crypto/build/Release/.deps/Release/obj.target/sshcrypto/src/binding.o.d.raw +136 -0
  276. package/node_modules/ssh2/lib/protocol/crypto/build/sshcrypto.target.mk +14 -14
  277. package/node_modules/undici/docs/docs/api/Interceptors.md +15 -2
  278. package/node_modules/undici/lib/dispatcher/client-h2.js +78 -3
  279. package/node_modules/undici/lib/dispatcher/pool-base.js +20 -3
  280. package/node_modules/undici/package.json +3 -3
  281. package/node_modules/undici/types/api.d.ts +1 -1
  282. package/node_modules/undici/types/utility.d.ts +4 -4
  283. package/package.json +44 -13
  284. package/dist/lib/analytics/clients/client.js +0 -1
  285. package/dist/lib/analytics/clients/pendo.js +0 -78
  286. package/helpers/check-version.js +0 -16
  287. package/node_modules/check-disk-space/dist/check-disk-space.cjs +0 -210
  288. package/node_modules/check-disk-space/dist/check-disk-space.d.ts +0 -53
  289. package/node_modules/fetch-retry/.eslintignore +0 -1
  290. package/node_modules/fetch-retry/.eslintrc.yml +0 -20
  291. package/node_modules/fetch-retry/.github/workflows/node.js.yml +0 -32
  292. package/node_modules/fetch-retry/.husky/pre-commit +0 -6
  293. package/node_modules/fetch-retry/.nycrc.json +0 -24
  294. package/node_modules/fetch-retry/.travis.yml +0 -3
  295. package/node_modules/fetch-retry/LICENSE +0 -21
  296. package/node_modules/fetch-retry/README.md +0 -128
  297. package/node_modules/fetch-retry/dist/fetch-retry.umd.js +0 -151
  298. package/node_modules/fetch-retry/index.d.ts +0 -29
  299. package/node_modules/fetch-retry/index.js +0 -143
  300. package/node_modules/fetch-retry/package.json +0 -41
  301. package/node_modules/fetch-retry/rollup.config.js +0 -12
  302. package/node_modules/fetch-retry/test/.eslintrc.yml +0 -7
  303. package/node_modules/fetch-retry/test/integration/index.js +0 -212
  304. package/node_modules/fetch-retry/test/integration/mock-api/index.js +0 -42
  305. package/node_modules/fetch-retry/test/unit/index.js +0 -1169
  306. package/node_modules/ssh2/lib/protocol/crypto/build/Release/.deps/Release/obj.target/sshcrypto/src/binding.o.d +0 -265
  307. package/node_modules/ssh2/lib/protocol/crypto/build/Release/.deps/Release/obj.target/sshcrypto.node.d +0 -1
  308. package/node_modules/ssh2/lib/protocol/crypto/build/Release/.deps/Release/sshcrypto.node.d +0 -1
  309. package/node_modules/ssh2/lib/protocol/crypto/build/Release/obj.target/sshcrypto/src/binding.o +0 -0
  310. package/node_modules/ssh2/lib/protocol/crypto/build/Release/obj.target/sshcrypto.node +0 -0
  311. package/node_modules/ssh2/lib/protocol/crypto/build/Release/sshcrypto.node +0 -0
@@ -1,198 +1,189 @@
1
1
  "use strict";
2
-
3
- exports.__esModule = true;
4
- exports.DEFAULT_SLUG = exports.CONFIGURATION_FOLDER = void 0;
5
- exports.addDevEnvConfigurationOptions = addDevEnvConfigurationOptions;
6
- exports.ensureValidPathsInOptions = ensureValidPathsInOptions;
7
- exports.formatDevEnvLogSlug = formatDevEnvLogSlug;
8
- exports.formatDevEnvLogTimestamp = formatDevEnvLogTimestamp;
9
- exports.getDevEnvLogFile = getDevEnvLogFile;
10
- exports.getEnvTrackingInfo = getEnvTrackingInfo;
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.validateDependencies = exports.CONFIGURATION_FOLDER = exports.DEFAULT_SLUG = void 0;
7
+ exports.setIsTTY = setIsTTY;
8
+ exports.handleCLIException = handleCLIException;
11
9
  exports.getEnvironmentName = getEnvironmentName;
12
10
  exports.getEnvironmentStartCommand = getEnvironmentStartCommand;
13
- exports.getOptionsFromAppInfo = getOptionsFromAppInfo;
14
- exports.getTagChoices = getTagChoices;
15
- exports.handleCLIException = handleCLIException;
16
- exports.postStart = postStart;
17
11
  exports.printTable = printTable;
18
- exports.processBooleanOption = processBooleanOption;
19
12
  exports.processComponentOptionInput = processComponentOptionInput;
20
- exports.processMediaRedirectDomainOption = processMediaRedirectDomainOption;
21
- exports.processSlug = processSlug;
22
- exports.processStringOrBooleanOption = processStringOrBooleanOption;
23
- exports.processVersionOption = processVersionOption;
13
+ exports.getOptionsFromAppInfo = getOptionsFromAppInfo;
24
14
  exports.promptForArguments = promptForArguments;
25
- exports.promptForBoolean = promptForBoolean;
26
- exports.promptForComponent = promptForComponent;
27
- exports.promptForMultisite = promptForMultisite;
28
- exports.promptForPhpVersion = promptForPhpVersion;
15
+ exports.ensureValidPathsInOptions = ensureValidPathsInOptions;
16
+ exports.resolvePath = resolvePath;
29
17
  exports.promptForText = promptForText;
30
18
  exports.promptForURL = promptForURL;
31
- exports.promptForWordPress = promptForWordPress;
19
+ exports.promptForMultisite = promptForMultisite;
20
+ exports.promptForBoolean = promptForBoolean;
32
21
  exports.resolveMultisite = resolveMultisite;
33
- exports.resolvePath = resolvePath;
34
22
  exports.resolvePhpVersion = resolvePhpVersion;
35
- exports.setIsTTY = setIsTTY;
36
- exports.validateDependencies = void 0;
37
- var _chalk = _interopRequireDefault(require("chalk"));
38
- var _child_process = require("child_process");
39
- var _debug = _interopRequireDefault(require("debug"));
40
- var _enquirer = require("enquirer");
41
- var _nodeFs = require("node:fs");
42
- var _nodeOs = require("node:os");
43
- var _path = _interopRequireDefault(require("path"));
44
- var _shelljs = require("shelljs");
45
- var _devEnvironmentConfigurationFile = require("./dev-environment-configuration-file");
46
- var _devEnvironmentCore = require("./dev-environment-core");
47
- var _devEnvironmentLando = require("./dev-environment-lando");
48
- var _landoLoader = require("./lando-loader");
49
- var _user = require("../api/user");
50
- var _devEnvironment = require("../constants/dev-environment");
51
- var _tracker = require("../tracker");
52
- var _userError = _interopRequireDefault(require("../user-error"));
53
- function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
54
- const debug = (0, _debug.default)('@automattic/vip:bin:dev-environment');
55
- const DEFAULT_SLUG = exports.DEFAULT_SLUG = 'vip-local';
56
- const CONFIGURATION_FOLDER = exports.CONFIGURATION_FOLDER = '.wpvip';
23
+ exports.promptForPhpVersion = promptForPhpVersion;
24
+ exports.promptForWordPress = promptForWordPress;
25
+ exports.promptForComponent = promptForComponent;
26
+ exports.processBooleanOption = processBooleanOption;
27
+ exports.processMediaRedirectDomainOption = processMediaRedirectDomainOption;
28
+ exports.processStringOrBooleanOption = processStringOrBooleanOption;
29
+ exports.processSlug = processSlug;
30
+ exports.formatDevEnvLogTimestamp = formatDevEnvLogTimestamp;
31
+ exports.formatDevEnvLogSlug = formatDevEnvLogSlug;
32
+ exports.getDevEnvLogFile = getDevEnvLogFile;
33
+ exports.processVersionOption = processVersionOption;
34
+ exports.addDevEnvConfigurationOptions = addDevEnvConfigurationOptions;
35
+ exports.getTagChoices = getTagChoices;
36
+ exports.getEnvTrackingInfo = getEnvTrackingInfo;
37
+ exports.postStart = postStart;
38
+ const chalk_1 = __importDefault(require("chalk"));
39
+ const child_process_1 = require("child_process");
40
+ const debug_1 = __importDefault(require("debug"));
41
+ const enquirer_1 = require("enquirer");
42
+ const node_fs_1 = require("node:fs");
43
+ const node_os_1 = require("node:os");
44
+ const path_1 = __importDefault(require("path"));
45
+ const shelljs_1 = require("shelljs");
46
+ const dev_environment_configuration_file_1 = require("./dev-environment-configuration-file");
47
+ const dev_environment_core_1 = require("./dev-environment-core");
48
+ const dev_environment_lando_1 = require("./dev-environment-lando");
49
+ const lando_loader_1 = require("./lando-loader");
50
+ const user_1 = require("../api/user");
51
+ const dev_environment_1 = require("../constants/dev-environment");
52
+ const tracker_1 = require("../tracker");
53
+ const user_error_1 = __importDefault(require("../user-error"));
54
+ const debug = (0, debug_1.default)('@automattic/vip:bin:dev-environment');
55
+ exports.DEFAULT_SLUG = 'vip-local';
56
+ exports.CONFIGURATION_FOLDER = '.wpvip';
57
57
  let isStdinTTY = Boolean(process.stdin.isTTY);
58
58
  let landoFormatters = null;
59
59
  const getLandoFormatters = () => {
60
- if (!landoFormatters) {
61
- landoFormatters = (0, _landoLoader.loadLandoModule)('lando/lib/formatters');
62
- }
63
- return landoFormatters;
60
+ if (!landoFormatters) {
61
+ landoFormatters = (0, lando_loader_1.loadLandoModule)('lando/lib/formatters');
62
+ }
63
+ return landoFormatters;
64
64
  };
65
-
66
65
  /**
67
66
  * Used internally for tests
68
67
  *
69
68
  * @param {boolean} val Value to set
70
69
  */
71
70
  function setIsTTY(val) {
72
- isStdinTTY = val;
71
+ isStdinTTY = val;
73
72
  }
74
73
  const componentDisplayNames = {
75
- wordpress: 'WordPress',
76
- muPlugins: 'VIP MU Plugins',
77
- appCode: 'application code'
74
+ wordpress: 'WordPress',
75
+ muPlugins: 'VIP MU Plugins',
76
+ appCode: 'application code',
78
77
  };
79
78
  const componentDemoNames = {
80
- muPlugins: 'vip-go-mu-plugins',
81
- appCode: 'vip-go-skeleton'
79
+ muPlugins: 'vip-go-mu-plugins',
80
+ appCode: 'vip-go-skeleton',
82
81
  };
83
82
  async function handleCLIException(exception, trackKey, trackBaseInfo = {}) {
84
- const errorPrefix = _chalk.default.red('Error:');
85
- if (_devEnvironment.DEV_ENVIRONMENT_NOT_FOUND === exception.message) {
86
- const createCommand = _chalk.default.bold(_devEnvironment.DEV_ENVIRONMENT_FULL_COMMAND + ' create');
87
- const message = `Environment doesn't exist.\n\n\nTo create a new environment run:\n\n${createCommand}\n`;
88
- console.error(errorPrefix, message);
89
- } else if (exception instanceof _userError.default) {
90
- // User errors are handled in global error handler
91
- throw exception;
92
- } else {
93
- let message = exception.message;
94
- // if the message has already ERROR prefix we should drop it as we are adding our own cool red Error-prefix
95
- message = message.replace('ERROR: ', '');
96
- console.error(errorPrefix, message);
97
- if (trackKey) {
98
- const errorTrackingInfo = {
99
- ...trackBaseInfo,
100
- failure: message,
101
- stack: exception.stack
102
- };
103
- // trackEvent does not throw
104
- await (0, _tracker.trackEvent)(trackKey, errorTrackingInfo);
105
- }
106
- if (!process.env.DEBUG) {
107
- console.error(`\nPlease re-run the command with "--debug ${_chalk.default.bold('@automattic/vip:bin:dev-environment')}" appended to it and provide the stack trace on the support ticket.`);
108
- console.error(_chalk.default.bold('\nExample:\n'));
109
- console.error('vip dev-env <command> <arguments> --debug @automattic/vip:bin:dev-environment \n');
110
- }
111
- debug(exception);
112
- }
113
- }
114
- const validateDependencies = lando => {
115
- const now = new Date();
116
- (0, _devEnvironmentLando.validateDockerInstalled)(lando);
117
- const duration = new Date().getTime() - now.getTime();
118
- debug('Validation checks completed in %d ms', duration);
83
+ const errorPrefix = chalk_1.default.red('Error:');
84
+ if (dev_environment_1.DEV_ENVIRONMENT_NOT_FOUND === exception.message) {
85
+ const createCommand = chalk_1.default.bold(dev_environment_1.DEV_ENVIRONMENT_FULL_COMMAND + ' create');
86
+ const message = `Environment doesn't exist.\n\n\nTo create a new environment run:\n\n${createCommand}\n`;
87
+ console.error(errorPrefix, message);
88
+ }
89
+ else if (exception instanceof user_error_1.default) {
90
+ // User errors are handled in global error handler
91
+ throw exception;
92
+ }
93
+ else {
94
+ let message = exception.message;
95
+ // if the message has already ERROR prefix we should drop it as we are adding our own cool red Error-prefix
96
+ message = message.replace('ERROR: ', '');
97
+ console.error(errorPrefix, message);
98
+ if (trackKey) {
99
+ const errorTrackingInfo = { ...trackBaseInfo, failure: message, stack: exception.stack };
100
+ // trackEvent does not throw
101
+ await (0, tracker_1.trackEvent)(trackKey, errorTrackingInfo);
102
+ }
103
+ if (!process.env.DEBUG) {
104
+ console.error(`\nPlease re-run the command with "--debug ${chalk_1.default.bold('@automattic/vip:bin:dev-environment')}" appended to it and provide the stack trace on the support ticket.`);
105
+ console.error(chalk_1.default.bold('\nExample:\n'));
106
+ console.error('vip dev-env <command> <arguments> --debug @automattic/vip:bin:dev-environment \n');
107
+ }
108
+ debug(exception);
109
+ }
110
+ }
111
+ const validateDependencies = (lando) => {
112
+ const now = new Date();
113
+ (0, dev_environment_lando_1.validateDockerInstalled)(lando);
114
+ const duration = new Date().getTime() - now.getTime();
115
+ debug('Validation checks completed in %d ms', duration);
119
116
  };
120
117
  exports.validateDependencies = validateDependencies;
121
118
  async function getEnvironmentName(options, quiet = false) {
122
- if (options.slug) {
123
- return options.slug;
124
- }
125
- if (options.app) {
126
- const envSuffix = options.env ? `-${options.env}` : '';
127
- const appName = options.app + envSuffix;
128
- if (options.allowAppEnv) {
129
- return appName;
130
- }
131
- const message = `This command does not support @app.env notation. Use '--slug=${appName}' to target the local environment.`;
132
- throw new _userError.default(message);
133
- }
134
- const configurationFileOptions = await (0, _devEnvironmentConfigurationFile.getConfigurationFileOptions)();
135
- if (configurationFileOptions.slug && configurationFileOptions.meta) {
136
- const slug = configurationFileOptions.slug;
137
- if (!quiet) {
138
- console.log(`Using environment ${_chalk.default.blue.bold(slug)} from ${_chalk.default.gray(configurationFileOptions.meta['configuration-path'])}\n`);
139
- }
140
- return slug;
141
- }
142
- const envs = (0, _devEnvironmentCore.getAllEnvironmentNames)();
143
- if (envs.length === 1) {
144
- return envs[0];
145
- }
146
- if (envs.length > 1 && typeof options.slug !== 'string') {
147
- const msg = `More than one environment found: ${_chalk.default.blue.bold(envs.join(', '))}. Please re-run command with the --slug parameter for the targeted environment.`;
148
- throw new _userError.default(msg);
149
- }
150
- return DEFAULT_SLUG; // Fall back to the default slug if we don't have any, e.g. during the env creation purpose
119
+ if (options.slug) {
120
+ return options.slug;
121
+ }
122
+ if (options.app) {
123
+ const envSuffix = options.env ? `-${options.env}` : '';
124
+ const appName = options.app + envSuffix;
125
+ if (options.allowAppEnv) {
126
+ return appName;
127
+ }
128
+ const message = `This command does not support @app.env notation. Use '--slug=${appName}' to target the local environment.`;
129
+ throw new user_error_1.default(message);
130
+ }
131
+ const configurationFileOptions = await (0, dev_environment_configuration_file_1.getConfigurationFileOptions)();
132
+ if (configurationFileOptions.slug && configurationFileOptions.meta) {
133
+ const slug = configurationFileOptions.slug;
134
+ if (!quiet) {
135
+ console.log(`Using environment ${chalk_1.default.blue.bold(slug)} from ${chalk_1.default.gray(configurationFileOptions.meta['configuration-path'])}\n`);
136
+ }
137
+ return slug;
138
+ }
139
+ const envs = (0, dev_environment_core_1.getAllEnvironmentNames)();
140
+ if (envs.length === 1) {
141
+ return envs[0];
142
+ }
143
+ if (envs.length > 1 && typeof options.slug !== 'string') {
144
+ const msg = `More than one environment found: ${chalk_1.default.blue.bold(envs.join(', '))}. Please re-run command with the --slug parameter for the targeted environment.`;
145
+ throw new user_error_1.default(msg);
146
+ }
147
+ return exports.DEFAULT_SLUG; // Fall back to the default slug if we don't have any, e.g. during the env creation purpose
151
148
  }
152
149
  function getEnvironmentStartCommand(slug, configurationFileOptions) {
153
- const isUsingConfigurationFileSlug = Object.keys(configurationFileOptions).length > 0 && configurationFileOptions.slug === slug;
154
- if (!slug || isUsingConfigurationFileSlug) {
155
- return `${_devEnvironment.DEV_ENVIRONMENT_FULL_COMMAND} start`;
156
- }
157
- return `${_devEnvironment.DEV_ENVIRONMENT_FULL_COMMAND} start --slug ${slug}`;
150
+ const isUsingConfigurationFileSlug = Object.keys(configurationFileOptions).length > 0 && configurationFileOptions.slug === slug;
151
+ if (!slug || isUsingConfigurationFileSlug) {
152
+ return `${dev_environment_1.DEV_ENVIRONMENT_FULL_COMMAND} start`;
153
+ }
154
+ return `${dev_environment_1.DEV_ENVIRONMENT_FULL_COMMAND} start --slug ${slug}`;
158
155
  }
159
156
  function printTable(data) {
160
- const formattedData = getLandoFormatters().formatData(data, {
161
- format: 'table'
162
- }, {
163
- border: false
164
- });
165
- console.log(formattedData);
157
+ const formattedData = getLandoFormatters().formatData(data, { format: 'table' }, { border: false });
158
+ console.log(formattedData);
166
159
  }
167
160
  function processComponentOptionInput(passedParam, allowLocal) {
168
- // cast to string
169
- const param = String(passedParam);
170
- // This is a bit of a naive check
171
- if (allowLocal && /[\\/]/.test(param)) {
161
+ // cast to string
162
+ const param = String(passedParam);
163
+ // This is a bit of a naive check
164
+ if (allowLocal && /[\\/]/.test(param)) {
165
+ return {
166
+ mode: 'local',
167
+ dir: param,
168
+ };
169
+ }
172
170
  return {
173
- mode: 'local',
174
- dir: param
171
+ mode: 'image',
172
+ tag: param === 'demo' || param === 'image' ? undefined : param,
175
173
  };
176
- }
177
- return {
178
- mode: 'image',
179
- tag: param === 'demo' || param === 'image' ? undefined : param
180
- };
181
174
  }
182
175
  function getOptionsFromAppInfo(appInfo) {
183
- const integrationsConfig = appInfo.environment?.integrations ?? {};
184
- const hasES = integrationsConfig['enterprise-search']?.env?.status === 'enabled';
185
- return {
186
- title: appInfo.environment?.name || appInfo.name || '',
187
- // NOSONAR
188
- multisite: Boolean(appInfo.environment?.isMultisite),
189
- mediaRedirectDomain: appInfo.environment?.primaryDomain,
190
- php: appInfo.environment?.php ?? '',
191
- wordpress: appInfo.environment?.wordpress ?? '',
192
- elasticsearch: hasES
193
- };
194
- }
195
-
176
+ const integrationsConfig = appInfo.environment?.integrations ?? {};
177
+ const hasES = integrationsConfig['enterprise-search']?.env?.status === 'enabled';
178
+ return {
179
+ title: appInfo.environment?.name || appInfo.name || '', // NOSONAR
180
+ multisite: Boolean(appInfo.environment?.isMultisite),
181
+ mediaRedirectDomain: appInfo.environment?.primaryDomain,
182
+ php: appInfo.environment?.php ?? '',
183
+ wordpress: appInfo.environment?.wordpress ?? '',
184
+ elasticsearch: hasES,
185
+ };
186
+ }
196
187
  /**
197
188
  * Prompt for arguments
198
189
  *
@@ -203,671 +194,721 @@ function getOptionsFromAppInfo(appInfo) {
203
194
  */
204
195
  // eslint-disable-next-line complexity
205
196
  async function promptForArguments(preselectedOptions, defaultOptions, suppressPrompts, create) {
206
- debug('Provided preselected', preselectedOptions, 'and default', defaultOptions);
207
- let isVIPUser;
208
- try {
209
- const currentUser = await (0, _user.getCurrentUserInfo)(true);
210
- isVIPUser = currentUser?.isVIP ?? false;
211
- } catch {
212
- isVIPUser = false;
213
- }
214
- if (suppressPrompts) {
215
- preselectedOptions = {
216
- ...defaultOptions,
217
- ...preselectedOptions
197
+ debug('Provided preselected', preselectedOptions, 'and default', defaultOptions);
198
+ let isVIPUser;
199
+ try {
200
+ const currentUser = await (0, user_1.getCurrentUserInfo)(true);
201
+ isVIPUser = currentUser?.isVIP ?? false;
202
+ }
203
+ catch {
204
+ isVIPUser = false;
205
+ }
206
+ if (suppressPrompts) {
207
+ preselectedOptions = { ...defaultOptions, ...preselectedOptions };
208
+ }
209
+ else {
210
+ console.log(dev_environment_1.DEV_ENVIRONMENT_PROMPT_INTRO);
211
+ }
212
+ let multisiteText = 'Multisite';
213
+ if (defaultOptions.title) {
214
+ multisiteText += ` (${defaultOptions.title} ${defaultOptions.multisite ? 'IS' : 'is NOT'} multisite)`;
215
+ }
216
+ const instanceData = {
217
+ wpTitle: preselectedOptions.title ??
218
+ (await promptForText('WordPress site title', defaultOptions.title ?? dev_environment_1.DEV_ENVIRONMENT_DEFAULTS.title)),
219
+ multisite: resolveMultisite(preselectedOptions.multisite ??
220
+ (await promptForMultisite(multisiteText, defaultOptions.multisite ?? dev_environment_1.DEV_ENVIRONMENT_DEFAULTS.multisite))),
221
+ elasticsearch: false,
222
+ php: preselectedOptions.php
223
+ ? resolvePhpVersion(preselectedOptions.php)
224
+ : await promptForPhpVersion(resolvePhpVersion(defaultOptions.php ?? dev_environment_1.DEV_ENVIRONMENT_DEFAULTS.phpVersion)),
225
+ mariadb: preselectedOptions.mariadb ?? defaultOptions.mariadb,
226
+ mediaRedirectDomain: preselectedOptions.mediaRedirectDomain ?? defaultOptions.mediaRedirectDomain ?? '',
227
+ wordpress: {
228
+ mode: 'image',
229
+ tag: '',
230
+ },
231
+ muPlugins: {
232
+ mode: 'image',
233
+ },
234
+ appCode: {
235
+ mode: 'image',
236
+ },
237
+ phpmyadmin: false,
238
+ xdebug: false,
239
+ xdebugConfig: preselectedOptions.xdebugConfig,
240
+ siteSlug: '',
241
+ mailpit: false,
242
+ photon: false,
243
+ cron: false,
244
+ overrides: preselectedOptions.overrides,
245
+ adminPassword: preselectedOptions.adminPassword,
218
246
  };
219
- } else {
220
- console.log(_devEnvironment.DEV_ENVIRONMENT_PROMPT_INTRO);
221
- }
222
- let multisiteText = 'Multisite';
223
- if (defaultOptions.title) {
224
- multisiteText += ` (${defaultOptions.title} ${defaultOptions.multisite ? 'IS' : 'is NOT'} multisite)`;
225
- }
226
- const instanceData = {
227
- wpTitle: preselectedOptions.title ?? (await promptForText('WordPress site title', defaultOptions.title ?? _devEnvironment.DEV_ENVIRONMENT_DEFAULTS.title)),
228
- multisite: resolveMultisite(preselectedOptions.multisite ?? (await promptForMultisite(multisiteText, defaultOptions.multisite ?? _devEnvironment.DEV_ENVIRONMENT_DEFAULTS.multisite))),
229
- elasticsearch: false,
230
- php: preselectedOptions.php ? resolvePhpVersion(preselectedOptions.php) : await promptForPhpVersion(resolvePhpVersion(defaultOptions.php ?? _devEnvironment.DEV_ENVIRONMENT_DEFAULTS.phpVersion)),
231
- mariadb: preselectedOptions.mariadb ?? defaultOptions.mariadb,
232
- mediaRedirectDomain: preselectedOptions.mediaRedirectDomain ?? defaultOptions.mediaRedirectDomain ?? '',
233
- wordpress: {
234
- mode: 'image',
235
- tag: ''
236
- },
237
- muPlugins: {
238
- mode: 'image'
239
- },
240
- appCode: {
241
- mode: 'image'
242
- },
243
- phpmyadmin: false,
244
- xdebug: false,
245
- xdebugConfig: preselectedOptions.xdebugConfig,
246
- siteSlug: '',
247
- mailpit: false,
248
- photon: false,
249
- cron: false,
250
- overrides: preselectedOptions.overrides,
251
- adminPassword: preselectedOptions.adminPassword
252
- };
253
- const promptLabels = {
254
- xdebug: 'XDebug',
255
- phpmyadmin: 'phpMyAdmin',
256
- mailpit: 'Mailpit',
257
- photon: 'Photon',
258
- cron: 'Cron'
259
- };
260
- if (create && !instanceData.mediaRedirectDomain && defaultOptions.mediaRedirectDomain) {
261
- const mediaRedirectPromptText = `Would you like to redirect to ${defaultOptions.mediaRedirectDomain} for missing media files?`;
262
- const setMediaRedirectDomain = await promptForBoolean(mediaRedirectPromptText, true);
263
- if (setMediaRedirectDomain) {
264
- instanceData.mediaRedirectDomain = defaultOptions.mediaRedirectDomain;
265
- }
266
- } else if (!create && defaultOptions.mediaRedirectDomain && !preselectedOptions.mediaRedirectDomain) {
267
- const mediaRedirectPromptText = 'URL to redirect for missing media files ("n" to disable)?';
268
- const mediaRedirectDomain = await promptForURL(mediaRedirectPromptText, defaultOptions.mediaRedirectDomain);
269
- instanceData.mediaRedirectDomain = mediaRedirectDomain;
270
- }
271
- instanceData.wordpress = await processWordPress(preselectedOptions.wordpress ?? '', defaultOptions.wordpress ?? '');
272
- instanceData.appCode = await processComponent('appCode', preselectedOptions.appCode ?? '', defaultOptions.appCode ?? '', suppressPrompts, validateAppCodeLocalPath);
273
- let preselectedMU = preselectedOptions.muPlugins;
274
- const defaultMU = defaultOptions.muPlugins;
275
- if (!preselectedMU && !isVIPUser && (!defaultMU || ['demo', 'image'].includes(defaultMU))) {
276
- preselectedMU = 'image';
277
- }
278
- instanceData.muPlugins = await processComponent('muPlugins', preselectedMU ?? '', defaultMU ?? '', suppressPrompts, validateMuPluginsLocalPath);
279
- debug(`Processing elasticsearch with preselected "%s"`, preselectedOptions.elasticsearch);
280
- if ('elasticsearch' in preselectedOptions) {
281
- instanceData.elasticsearch = Boolean(preselectedOptions.elasticsearch);
282
- } else {
283
- instanceData.elasticsearch = await promptForBoolean('Enable Elasticsearch (needed by Enterprise Search)?', Boolean(defaultOptions.elasticsearch));
284
- }
285
- const services = ['phpmyadmin', 'xdebug', 'mailpit', 'photon', 'cron'];
286
- for (const service of services) {
287
- if (service in instanceData) {
288
- const preselected = preselectedOptions[service];
289
- if (preselected !== undefined) {
290
- instanceData[service] = preselected;
291
- } else {
292
- // eslint-disable-next-line no-await-in-loop
293
- instanceData[service] = await promptForBoolean(`Enable ${promptLabels[service] || service}`, Boolean(defaultOptions[service]));
294
- }
295
- }
296
- }
297
- debug('Instance data after prompts', instanceData);
298
- return instanceData;
247
+ const promptLabels = {
248
+ xdebug: 'XDebug',
249
+ phpmyadmin: 'phpMyAdmin',
250
+ mailpit: 'Mailpit',
251
+ photon: 'Photon',
252
+ cron: 'Cron',
253
+ };
254
+ if (create && !instanceData.mediaRedirectDomain && defaultOptions.mediaRedirectDomain) {
255
+ const mediaRedirectPromptText = `Would you like to redirect to ${defaultOptions.mediaRedirectDomain} for missing media files?`;
256
+ const setMediaRedirectDomain = await promptForBoolean(mediaRedirectPromptText, true);
257
+ if (setMediaRedirectDomain) {
258
+ instanceData.mediaRedirectDomain = defaultOptions.mediaRedirectDomain;
259
+ }
260
+ }
261
+ else if (!create &&
262
+ defaultOptions.mediaRedirectDomain &&
263
+ !preselectedOptions.mediaRedirectDomain) {
264
+ const mediaRedirectPromptText = 'URL to redirect for missing media files ("n" to disable)?';
265
+ const mediaRedirectDomain = await promptForURL(mediaRedirectPromptText, defaultOptions.mediaRedirectDomain);
266
+ instanceData.mediaRedirectDomain = mediaRedirectDomain;
267
+ }
268
+ instanceData.wordpress = await processWordPress(preselectedOptions.wordpress ?? '', defaultOptions.wordpress ?? '');
269
+ instanceData.appCode = await processComponent('appCode', preselectedOptions.appCode ?? '', defaultOptions.appCode ?? '', suppressPrompts, validateAppCodeLocalPath);
270
+ let preselectedMU = preselectedOptions.muPlugins;
271
+ const defaultMU = defaultOptions.muPlugins;
272
+ if (!preselectedMU &&
273
+ !isVIPUser &&
274
+ (!defaultMU || ['demo', 'image'].includes(defaultMU))) {
275
+ preselectedMU = 'image';
276
+ }
277
+ instanceData.muPlugins = await processComponent('muPlugins', preselectedMU ?? '', defaultMU ?? '', suppressPrompts, validateMuPluginsLocalPath);
278
+ debug(`Processing elasticsearch with preselected "%s"`, preselectedOptions.elasticsearch);
279
+ if ('elasticsearch' in preselectedOptions) {
280
+ instanceData.elasticsearch = Boolean(preselectedOptions.elasticsearch);
281
+ }
282
+ else {
283
+ instanceData.elasticsearch = await promptForBoolean('Enable Elasticsearch (needed by Enterprise Search)?', Boolean(defaultOptions.elasticsearch));
284
+ }
285
+ const services = ['phpmyadmin', 'xdebug', 'mailpit', 'photon', 'cron'];
286
+ for (const service of services) {
287
+ if (service in instanceData) {
288
+ const preselected = preselectedOptions[service];
289
+ if (preselected !== undefined) {
290
+ instanceData[service] = preselected;
291
+ }
292
+ else {
293
+ // eslint-disable-next-line no-await-in-loop
294
+ instanceData[service] = await promptForBoolean(`Enable ${promptLabels[service] || service}`, Boolean(defaultOptions[service]));
295
+ }
296
+ }
297
+ }
298
+ debug('Instance data after prompts', instanceData);
299
+ return instanceData;
299
300
  }
300
301
  async function processWordPress(preselectedValue, defaultValue) {
301
- debug(`processing 'WordPress', with preselected/default - ${preselectedValue}/${defaultValue}`);
302
- let result;
303
- const allowLocal = false;
304
- const defaultObject = defaultValue ? processComponentOptionInput(defaultValue, allowLocal) : null;
305
- if (preselectedValue) {
306
- result = processComponentOptionInput(preselectedValue, allowLocal);
307
- } else {
308
- result = await promptForWordPress(defaultObject);
309
- }
310
- const versions = await (0, _devEnvironmentCore.getVersionList)();
311
- if (versions.length) {
312
- versions.sort((before, after) => before.tag < after.tag ? 1 : -1);
313
- const match = versions.find(({
314
- prerelease,
315
- tag
316
- }) => result.tag === 'latest' ? !prerelease : tag === result.tag);
317
- if (match === undefined) {
318
- throw new _userError.default(`Unknown or unsupported WordPress version: ${result.tag}.`);
319
- }
320
- result.tag = match.tag;
321
- }
322
- debug(result);
323
- return result;
302
+ debug(`processing 'WordPress', with preselected/default - ${preselectedValue}/${defaultValue}`);
303
+ let result;
304
+ const allowLocal = false;
305
+ const defaultObject = defaultValue
306
+ ? processComponentOptionInput(defaultValue, allowLocal)
307
+ : null;
308
+ if (preselectedValue) {
309
+ result = processComponentOptionInput(preselectedValue, allowLocal);
310
+ }
311
+ else {
312
+ result = await promptForWordPress(defaultObject);
313
+ }
314
+ const versions = await (0, dev_environment_core_1.getVersionList)();
315
+ if (versions.length) {
316
+ versions.sort((before, after) => (before.tag < after.tag ? 1 : -1));
317
+ const match = versions.find(({ prerelease, tag }) => result.tag === 'latest' ? !prerelease : tag === result.tag);
318
+ if (match === undefined) {
319
+ throw new user_error_1.default(`Unknown or unsupported WordPress version: ${result.tag}.`);
320
+ }
321
+ result.tag = match.tag;
322
+ }
323
+ debug(result);
324
+ return result;
324
325
  }
325
326
  async function processComponent(componentType, preselectedValue, defaultValue, suppressPrompts, localPathValidator) {
326
- debug(`Processing the '${componentType}' component, with preselected = %s, default = %s`, preselectedValue, defaultValue);
327
- const defaultObject = defaultValue ? processComponentOptionInput(defaultValue, true) : null;
328
- if (preselectedValue && !suppressPrompts) {
329
- console.log('%s Path to your local %s: %s', _chalk.default.green('✓'), componentDisplayNames[componentType], preselectedValue);
330
- }
331
- let result = preselectedValue ? processComponentOptionInput(preselectedValue, true) : await promptForComponent(componentType, true, defaultObject);
332
- debug(result);
333
- if (result.mode === 'local') {
334
- result = await validateLocalPath(result, localPathValidator, componentType, defaultObject);
335
- }
336
- debug(result);
337
- return result;
327
+ debug(`Processing the '${componentType}' component, with preselected = %s, default = %s`, preselectedValue, defaultValue);
328
+ const defaultObject = defaultValue ? processComponentOptionInput(defaultValue, true) : null;
329
+ if (preselectedValue && !suppressPrompts) {
330
+ console.log('%s Path to your local %s: %s', chalk_1.default.green('✓'), componentDisplayNames[componentType], preselectedValue);
331
+ }
332
+ let result = preselectedValue
333
+ ? processComponentOptionInput(preselectedValue, true)
334
+ : await promptForComponent(componentType, true, defaultObject);
335
+ debug(result);
336
+ if (result.mode === 'local') {
337
+ result = await validateLocalPath(result, localPathValidator, componentType, defaultObject);
338
+ }
339
+ debug(result);
340
+ return result;
338
341
  }
339
342
  function ensureValidPathsInOptions(opt) {
340
- if (opt.appCode) {
341
- const result = validateAppCodeLocalPath(`${opt.appCode}`);
342
- if (!result.result) {
343
- console.warn(_chalk.default.yellow('Warning:'), result.message);
344
- delete opt.appCode;
345
- delete opt.a;
346
- }
347
- }
348
- if (opt.muPlugins) {
349
- const result = validateMuPluginsLocalPath(`${opt.muPlugins}`);
350
- if (!result.result) {
351
- console.warn(_chalk.default.yellow('Warning:'), result.message);
352
- delete opt.muPlugins;
353
- delete opt.m;
354
- }
355
- }
343
+ if (opt.appCode) {
344
+ const result = validateAppCodeLocalPath(`${opt.appCode}`);
345
+ if (!result.result) {
346
+ console.warn(chalk_1.default.yellow('Warning:'), result.message);
347
+ delete opt.appCode;
348
+ delete opt.a;
349
+ }
350
+ }
351
+ if (opt.muPlugins) {
352
+ const result = validateMuPluginsLocalPath(`${opt.muPlugins}`);
353
+ if (!result.result) {
354
+ console.warn(chalk_1.default.yellow('Warning:'), result.message);
355
+ delete opt.muPlugins;
356
+ delete opt.m;
357
+ }
358
+ }
356
359
  }
357
360
  async function validateLocalPath(config, validator, componentName, defaultObject) {
358
- while (config.mode === 'local') {
359
- const resolvedPath = resolvePath(config.dir ?? '');
360
- config.dir = resolvedPath;
361
- const {
362
- result: isPathValid,
363
- message
364
- } = validator(resolvedPath);
365
- if (isPathValid) {
366
- break;
367
- } else if (isStdinTTY) {
368
- console.log(_chalk.default.yellow('Warning:'), message);
369
- // eslint-disable-next-line no-await-in-loop
370
- config = await promptForComponent(componentName, true, defaultObject);
371
- } else {
372
- throw new Error(message);
373
- }
374
- }
375
- return config;
361
+ while (config.mode === 'local') {
362
+ const resolvedPath = resolvePath(config.dir ?? '');
363
+ config.dir = resolvedPath;
364
+ const { result: isPathValid, message } = validator(resolvedPath);
365
+ if (isPathValid) {
366
+ break;
367
+ }
368
+ else if (isStdinTTY) {
369
+ console.log(chalk_1.default.yellow('Warning:'), message);
370
+ // eslint-disable-next-line no-await-in-loop
371
+ config = await promptForComponent(componentName, true, defaultObject);
372
+ }
373
+ else {
374
+ throw new Error(message);
375
+ }
376
+ }
377
+ return config;
376
378
  }
377
379
  function validateMuPluginsLocalPath(providedPath) {
378
- if (!isNonEmptyDirectory(providedPath)) {
379
- const message = `Provided path "${providedPath}" does not point to a valid or existing directory.`;
380
+ if (!isNonEmptyDirectory(providedPath)) {
381
+ const message = `Provided path "${providedPath}" does not point to a valid or existing directory.`;
382
+ return {
383
+ result: false,
384
+ message,
385
+ };
386
+ }
380
387
  return {
381
- result: false,
382
- message
388
+ result: true,
389
+ message: '',
383
390
  };
384
- }
385
- return {
386
- result: true,
387
- message: ''
388
- };
389
391
  }
390
392
  function validateAppCodeLocalPath(providedPath) {
391
- if (!isNonEmptyDirectory(providedPath)) {
392
- const message = `Provided path "${providedPath}" does not point to a valid or existing directory.`;
393
- return {
394
- result: false,
395
- message
396
- };
397
- }
398
- const files = ['languages', 'plugins', 'themes', 'private', 'images', 'client-mu-plugins', 'vip-config'];
399
- const missingFiles = [];
400
- for (const file of files) {
401
- const filePath = _path.default.resolve(providedPath, file);
402
- if (!(0, _nodeFs.existsSync)(filePath)) {
403
- missingFiles.push(file);
404
- }
405
- }
406
- if (missingFiles.length > 0) {
407
- const message = `Provided path "${providedPath}" is missing following files/folders: ${missingFiles.join(', ')}. Learn more: https://docs.wpvip.com/wordpress-skeleton/`;
393
+ if (!isNonEmptyDirectory(providedPath)) {
394
+ const message = `Provided path "${providedPath}" does not point to a valid or existing directory.`;
395
+ return {
396
+ result: false,
397
+ message,
398
+ };
399
+ }
400
+ const files = [
401
+ 'languages',
402
+ 'plugins',
403
+ 'themes',
404
+ 'private',
405
+ 'images',
406
+ 'client-mu-plugins',
407
+ 'vip-config',
408
+ ];
409
+ const missingFiles = [];
410
+ for (const file of files) {
411
+ const filePath = path_1.default.resolve(providedPath, file);
412
+ if (!(0, node_fs_1.existsSync)(filePath)) {
413
+ missingFiles.push(file);
414
+ }
415
+ }
416
+ if (missingFiles.length > 0) {
417
+ const message = `Provided path "${providedPath}" is missing following files/folders: ${missingFiles.join(', ')}. Learn more: https://docs.wpvip.com/wordpress-skeleton/`;
418
+ return {
419
+ result: false,
420
+ message,
421
+ };
422
+ }
408
423
  return {
409
- result: false,
410
- message
424
+ result: true,
425
+ message: '',
411
426
  };
412
- }
413
- return {
414
- result: true,
415
- message: ''
416
- };
417
427
  }
418
428
  function isNonEmptyDirectory(directoryPath) {
419
- const isDirectory = directoryPath && (0, _nodeFs.existsSync)(directoryPath) && (0, _nodeFs.lstatSync)(directoryPath).isDirectory();
420
- const isEmpty = isDirectory ? (0, _nodeFs.readdirSync)(directoryPath).length === 0 : true;
421
- return !isEmpty && isDirectory;
429
+ const isDirectory = directoryPath && (0, node_fs_1.existsSync)(directoryPath) && (0, node_fs_1.lstatSync)(directoryPath).isDirectory();
430
+ const isEmpty = isDirectory ? (0, node_fs_1.readdirSync)(directoryPath).length === 0 : true;
431
+ return !isEmpty && isDirectory;
422
432
  }
423
433
  function resolvePath(input) {
424
- // Resolve does not do ~ reliably
425
- const resolvedPath = input.replace(/^~/, (0, _nodeOs.homedir)());
426
- // And resolve to handle relative paths
427
- return _path.default.resolve(resolvedPath);
434
+ // Resolve does not do ~ reliably
435
+ const resolvedPath = input.replace(/^~/, (0, node_os_1.homedir)());
436
+ // And resolve to handle relative paths
437
+ return path_1.default.resolve(resolvedPath);
428
438
  }
429
439
  async function promptForText(message, initial) {
430
- let result = {
431
- input: initial
432
- };
433
- if (isStdinTTY) {
434
- const nonEmptyValidator = value => {
435
- if ((value || '').trim()) {
436
- return true;
437
- }
438
- return 'value needs to be provided';
439
- };
440
- result = await (0, _enquirer.prompt)({
441
- type: 'input',
442
- name: 'input',
443
- message,
444
- initial,
445
- validate: nonEmptyValidator
446
- });
447
- }
448
- return (result.input || '').trim();
440
+ let result = { input: initial };
441
+ if (isStdinTTY) {
442
+ const nonEmptyValidator = (value) => {
443
+ if ((value || '').trim()) {
444
+ return true;
445
+ }
446
+ return 'value needs to be provided';
447
+ };
448
+ result = await (0, enquirer_1.prompt)({
449
+ type: 'input',
450
+ name: 'input',
451
+ message,
452
+ initial,
453
+ validate: nonEmptyValidator,
454
+ });
455
+ }
456
+ return (result.input || '').trim();
449
457
  }
450
458
  async function promptForURL(message, initial) {
451
- let result = {
452
- input: initial
453
- };
454
- if (isStdinTTY) {
455
- const URLValidator = value => {
456
- if (!value.trim() || value === 'n') {
457
- return true;
458
- }
459
- try {
460
- const url = new URL(value);
461
- if (url.protocol !== 'http:' && url.protocol !== 'https:') {
462
- return 'value must be a http:// or https:// URL';
463
- }
464
- return true;
465
- } catch {
466
- return 'value needs to be a valid URL or an empty string';
467
- }
468
- };
469
- result = await (0, _enquirer.prompt)({
470
- type: 'input',
471
- name: 'input',
472
- message,
473
- initial,
474
- validate: URLValidator
475
- });
476
- }
477
- const retval = result.input.trim();
478
- return retval === 'n' ? '' : retval;
459
+ let result = { input: initial };
460
+ if (isStdinTTY) {
461
+ const URLValidator = (value) => {
462
+ if (!value.trim() || value === 'n') {
463
+ return true;
464
+ }
465
+ try {
466
+ const url = new URL(value);
467
+ if (url.protocol !== 'http:' && url.protocol !== 'https:') {
468
+ return 'value must be a http:// or https:// URL';
469
+ }
470
+ return true;
471
+ }
472
+ catch {
473
+ return 'value needs to be a valid URL or an empty string';
474
+ }
475
+ };
476
+ result = await (0, enquirer_1.prompt)({
477
+ type: 'input',
478
+ name: 'input',
479
+ message,
480
+ initial,
481
+ validate: URLValidator,
482
+ });
483
+ }
484
+ const retval = result.input.trim();
485
+ return retval === 'n' ? '' : retval;
479
486
  }
480
487
  const multisiteOptions = ['subdomain', 'subdirectory'];
481
488
  async function promptForMultisite(message, initial) {
482
- // `undefined` is used here only because our tests need overhauling
483
- let result = {
484
- input: initial
485
- };
486
- if (isStdinTTY) {
487
- result = await (0, _enquirer.prompt)({
488
- type: 'input',
489
- name: 'input',
490
- message,
491
- initial
492
- });
493
- }
494
- let input = (result?.input ?? initial).toString().trim();
495
- const allowedOptions = [...FALSE_OPTIONS, ...TRUE_OPTIONS, ...multisiteOptions, 'none'];
496
- if (!allowedOptions.includes(input) && isStdinTTY) {
497
- const select = new _enquirer.Select({
498
- message: `Please choose a valid option for multisite:`,
499
- choices: [...multisiteOptions, 'false']
500
- });
501
- input = await select.run();
502
- }
503
- return processStringOrBooleanOption(input);
489
+ // `undefined` is used here only because our tests need overhauling
490
+ let result = { input: initial };
491
+ if (isStdinTTY) {
492
+ result = await (0, enquirer_1.prompt)({
493
+ type: 'input',
494
+ name: 'input',
495
+ message,
496
+ initial,
497
+ });
498
+ }
499
+ let input = (result?.input ?? initial).toString().trim();
500
+ const allowedOptions = [
501
+ ...FALSE_OPTIONS,
502
+ ...TRUE_OPTIONS,
503
+ ...multisiteOptions,
504
+ 'none',
505
+ ];
506
+ if (!allowedOptions.includes(input) && isStdinTTY) {
507
+ const select = new enquirer_1.Select({
508
+ message: `Please choose a valid option for multisite:`,
509
+ choices: [...multisiteOptions, 'false'],
510
+ });
511
+ input = await select.run();
512
+ }
513
+ return processStringOrBooleanOption(input);
504
514
  }
505
515
  function promptForBoolean(message, initial) {
506
- if (isStdinTTY) {
507
- const confirm = new _enquirer.Confirm({
508
- message,
509
- // eslint-disable-next-line @typescript-eslint/no-explicit-any,@typescript-eslint/no-unsafe-assignment
510
- initial: initial // TS definition is wrong, so we need to bypass it to show the correct hint.
511
- });
512
- return confirm.run();
513
- }
514
- return Promise.resolve(initial);
516
+ if (isStdinTTY) {
517
+ const confirm = new enquirer_1.Confirm({
518
+ message,
519
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any,@typescript-eslint/no-unsafe-assignment
520
+ initial: initial, // TS definition is wrong, so we need to bypass it to show the correct hint.
521
+ });
522
+ return confirm.run();
523
+ }
524
+ return Promise.resolve(initial);
515
525
  }
516
526
  function resolveMultisite(value) {
517
- const isMultisiteOption = val => typeof val === 'string' && multisiteOptions.includes(val) || typeof val === 'boolean';
518
- return isMultisiteOption(value) ? value : _devEnvironment.DEV_ENVIRONMENT_DEFAULTS.multisite;
527
+ const isMultisiteOption = (val) => (typeof val === 'string' && multisiteOptions.includes(val)) ||
528
+ typeof val === 'boolean';
529
+ return isMultisiteOption(value) ? value : dev_environment_1.DEV_ENVIRONMENT_DEFAULTS.multisite;
519
530
  }
520
531
  function resolvePhpVersion(version) {
521
- // It is painful to rewrite tests :-(
522
- if (version === '') {
523
- return '';
524
- }
525
- debug(`Resolving PHP version %j`, version);
526
- let result;
527
- if (!Object.hasOwn(_devEnvironment.DEV_ENVIRONMENT_PHP_VERSIONS, version)) {
528
- const images = Object.values(_devEnvironment.DEV_ENVIRONMENT_PHP_VERSIONS);
529
- const image = images.find(value => value.image === version);
530
- if (image) {
531
- result = image.image;
532
- } else {
533
- throw new _userError.default(`Unknown or unsupported PHP version: ${version}.`);
534
- }
535
- } else {
536
- result = _devEnvironment.DEV_ENVIRONMENT_PHP_VERSIONS[version].image;
537
- }
538
- debug('Resolved PHP image: %j', result);
539
- return result;
532
+ // It is painful to rewrite tests :-(
533
+ if (version === '') {
534
+ return '';
535
+ }
536
+ debug(`Resolving PHP version %j`, version);
537
+ let result;
538
+ if (!Object.hasOwn(dev_environment_1.DEV_ENVIRONMENT_PHP_VERSIONS, version)) {
539
+ const images = Object.values(dev_environment_1.DEV_ENVIRONMENT_PHP_VERSIONS);
540
+ const image = images.find(value => value.image === version);
541
+ if (image) {
542
+ result = image.image;
543
+ }
544
+ else {
545
+ throw new user_error_1.default(`Unknown or unsupported PHP version: ${version}.`);
546
+ }
547
+ }
548
+ else {
549
+ result =
550
+ dev_environment_1.DEV_ENVIRONMENT_PHP_VERSIONS[version].image;
551
+ }
552
+ debug('Resolved PHP image: %j', result);
553
+ return result;
540
554
  }
541
555
  async function promptForPhpVersion(initialValue) {
542
- debug(`Prompting for PHP version, preselected option is ${initialValue}`);
543
- let answer = initialValue;
544
- if (isStdinTTY) {
545
- const choices = [];
546
- Object.keys(_devEnvironment.DEV_ENVIRONMENT_PHP_VERSIONS).forEach(version => {
547
- const phpImage = _devEnvironment.DEV_ENVIRONMENT_PHP_VERSIONS[version];
548
- const label = version === _devEnvironment.DEV_ENVIRONMENT_DEFAULT_PHP_VERSION ? `${phpImage.label} (recommended)` : phpImage.label;
549
- choices.push({
550
- message: label,
551
- value: version
552
- });
553
- });
554
- const images = Object.values(_devEnvironment.DEV_ENVIRONMENT_PHP_VERSIONS);
555
- let initial = images.findIndex(version => version.image === initialValue);
556
- if (initial === -1) {
557
- choices.push({
558
- message: initialValue,
559
- value: initialValue
560
- });
561
- initial = choices.length - 1;
562
- }
563
- const select = new _enquirer.Select({
564
- message: 'PHP version to use',
565
- choices,
566
- initial
567
- });
568
- answer = await select.run();
569
- }
570
- return resolvePhpVersion(answer);
556
+ debug(`Prompting for PHP version, preselected option is ${initialValue}`);
557
+ let answer = initialValue;
558
+ if (isStdinTTY) {
559
+ const choices = [];
560
+ Object.keys(dev_environment_1.DEV_ENVIRONMENT_PHP_VERSIONS).forEach(version => {
561
+ const phpImage = dev_environment_1.DEV_ENVIRONMENT_PHP_VERSIONS[version];
562
+ const label = version === dev_environment_1.DEV_ENVIRONMENT_DEFAULT_PHP_VERSION
563
+ ? `${phpImage.label} (recommended)`
564
+ : phpImage.label;
565
+ choices.push({ message: label, value: version });
566
+ });
567
+ const images = Object.values(dev_environment_1.DEV_ENVIRONMENT_PHP_VERSIONS);
568
+ let initial = images.findIndex(version => version.image === initialValue);
569
+ if (initial === -1) {
570
+ choices.push({ message: initialValue, value: initialValue });
571
+ initial = choices.length - 1;
572
+ }
573
+ const select = new enquirer_1.Select({
574
+ message: 'PHP version to use',
575
+ choices,
576
+ initial,
577
+ });
578
+ answer = await select.run();
579
+ }
580
+ return resolvePhpVersion(answer);
571
581
  }
572
582
  async function promptForWordPress(defaultObject) {
573
- debug(`Prompting for wordpress with default:`, defaultObject);
574
- const componentDisplayName = componentDisplayNames.wordpress;
575
- const messagePrefix = `${componentDisplayName} - `;
576
-
577
- // image with selection
578
- const tagChoices = await getTagChoices();
579
- if (typeof defaultObject === 'string' && !tagChoices.find(choice => choice.value === defaultObject)) {
580
- throw new Error(`Unknown or unsupported WordPress version: ${defaultObject}.`);
581
- }
582
- let option = typeof defaultObject === 'string' ? defaultObject : defaultObject?.tag ?? tagChoices[0].value;
583
- if (isStdinTTY) {
584
- const message = `${messagePrefix}Which version would you like`;
585
- const selectTag = new _enquirer.Select({
586
- message,
587
- choices: tagChoices,
588
- initial: option
589
- });
590
- option = await selectTag.run();
591
- }
592
- return {
593
- mode: 'image',
594
- tag: option
595
- };
583
+ debug(`Prompting for wordpress with default:`, defaultObject);
584
+ const componentDisplayName = componentDisplayNames.wordpress;
585
+ const messagePrefix = `${componentDisplayName} - `;
586
+ // image with selection
587
+ const tagChoices = await getTagChoices();
588
+ if (typeof defaultObject === 'string' &&
589
+ !tagChoices.find(choice => choice.value === defaultObject)) {
590
+ throw new Error(`Unknown or unsupported WordPress version: ${defaultObject}.`);
591
+ }
592
+ let option = typeof defaultObject === 'string' ? defaultObject : defaultObject?.tag ?? tagChoices[0].value;
593
+ if (isStdinTTY) {
594
+ const message = `${messagePrefix}Which version would you like`;
595
+ const selectTag = new enquirer_1.Select({
596
+ message,
597
+ choices: tagChoices,
598
+ initial: option,
599
+ });
600
+ option = await selectTag.run();
601
+ }
602
+ return {
603
+ mode: 'image',
604
+ tag: option,
605
+ };
596
606
  }
597
607
  async function promptForComponent(component, allowLocal, defaultObject) {
598
- debug(`Prompting for ${component} with default:`, defaultObject);
599
- const componentDisplayName = componentDisplayNames[component] || component;
600
- const componentDemoName = componentDemoNames[component];
601
- const modChoices = [];
602
- if (allowLocal) {
608
+ debug(`Prompting for ${component} with default:`, defaultObject);
609
+ const componentDisplayName = componentDisplayNames[component] || component;
610
+ const componentDemoName = componentDemoNames[component];
611
+ const modChoices = [];
612
+ if (allowLocal) {
613
+ modChoices.push({
614
+ message: `Custom - Path to a locally cloned ${componentDisplayName} directory`,
615
+ value: 'local',
616
+ });
617
+ }
603
618
  modChoices.push({
604
- message: `Custom - Path to a locally cloned ${componentDisplayName} directory`,
605
- value: 'local'
619
+ message: `Demo - Automatically fetched ${componentDemoName}`,
620
+ value: 'image',
606
621
  });
607
- }
608
- modChoices.push({
609
- message: `Demo - Automatically fetched ${componentDemoName}`,
610
- value: 'image'
611
- });
612
- let initialMode = 'image';
613
- if ('appCode' === component && isStdinTTY) {
614
- initialMode = 'local';
615
- }
616
- if (defaultObject?.mode) {
617
- initialMode = defaultObject.mode;
618
- }
619
- let modeResult = initialMode;
620
- const selectMode = modChoices.length > 1;
621
- if (selectMode && isStdinTTY) {
622
- const initialModeIndex = modChoices.findIndex(choice => choice.value === initialMode);
623
- const select = new _enquirer.Select({
624
- message: `How would you like to source ${componentDisplayName}`,
625
- choices: modChoices,
626
- initial: initialModeIndex
627
- });
628
- modeResult = await select.run();
629
- }
630
- debug(modeResult);
631
- const messagePrefix = selectMode ? '\t' : `${componentDisplayName} - `;
632
- if ('local' === modeResult) {
633
- const directoryPath = await promptForText(`${messagePrefix}What is a path to your local ${componentDisplayName}?`, defaultObject?.dir ?? '');
622
+ let initialMode = 'image';
623
+ if ('appCode' === component && isStdinTTY) {
624
+ initialMode = 'local';
625
+ }
626
+ if (defaultObject?.mode) {
627
+ initialMode = defaultObject.mode;
628
+ }
629
+ let modeResult = initialMode;
630
+ const selectMode = modChoices.length > 1;
631
+ if (selectMode && isStdinTTY) {
632
+ const initialModeIndex = modChoices.findIndex(choice => choice.value === initialMode);
633
+ const select = new enquirer_1.Select({
634
+ message: `How would you like to source ${componentDisplayName}`,
635
+ choices: modChoices,
636
+ initial: initialModeIndex,
637
+ });
638
+ modeResult = (await select.run());
639
+ }
640
+ debug(modeResult);
641
+ const messagePrefix = selectMode ? '\t' : `${componentDisplayName} - `;
642
+ if ('local' === modeResult) {
643
+ const directoryPath = await promptForText(`${messagePrefix}What is a path to your local ${componentDisplayName}?`, defaultObject?.dir ?? '');
644
+ return {
645
+ mode: modeResult,
646
+ dir: directoryPath,
647
+ };
648
+ }
649
+ // image
634
650
  return {
635
- mode: modeResult,
636
- dir: directoryPath
651
+ mode: modeResult,
637
652
  };
638
- }
639
-
640
- // image
641
- return {
642
- mode: modeResult
643
- };
644
653
  }
645
654
  const FALSE_OPTIONS = ['false', 'no', 'n', '0'];
646
655
  const TRUE_OPTIONS = ['true', 'yes', 'y', '1'];
647
656
  function processBooleanOption(value) {
648
- if (!value) {
649
- return false;
650
- }
651
-
652
- // eslint-disable-next-line @typescript-eslint/no-base-to-string
653
- return !FALSE_OPTIONS.includes(value.toString().toLowerCase()); // NOSONAR
657
+ if (!value) {
658
+ return false;
659
+ }
660
+ // eslint-disable-next-line @typescript-eslint/no-base-to-string
661
+ return !FALSE_OPTIONS.includes(value.toString().toLowerCase()); // NOSONAR
654
662
  }
655
663
  function processMediaRedirectDomainOption(value) {
656
- // eslint-disable-next-line @typescript-eslint/no-base-to-string
657
- const val = (value ?? '').toString();
658
- if (FALSE_OPTIONS.includes(val.toLowerCase())) {
659
- return '';
660
- }
661
- if (TRUE_OPTIONS.includes(val.toLowerCase())) {
662
- throw new _userError.default('Media redirect domain must be a domain name or an URL');
663
- }
664
- return val;
664
+ // eslint-disable-next-line @typescript-eslint/no-base-to-string
665
+ const val = (value ?? '').toString();
666
+ if (FALSE_OPTIONS.includes(val.toLowerCase())) {
667
+ return '';
668
+ }
669
+ if (TRUE_OPTIONS.includes(val.toLowerCase())) {
670
+ throw new user_error_1.default('Media redirect domain must be a domain name or an URL');
671
+ }
672
+ return val;
665
673
  }
666
674
  function processStringOrBooleanOption(value) {
667
- if (typeof value === 'boolean') {
675
+ if (typeof value === 'boolean') {
676
+ return value;
677
+ }
678
+ if (!value || FALSE_OPTIONS.includes(value.toLowerCase())) {
679
+ return false;
680
+ }
681
+ if (TRUE_OPTIONS.includes(value.toLowerCase())) {
682
+ return true;
683
+ }
668
684
  return value;
669
- }
670
- if (!value || FALSE_OPTIONS.includes(value.toLowerCase())) {
671
- return false;
672
- }
673
- if (TRUE_OPTIONS.includes(value.toLowerCase())) {
674
- return true;
675
- }
676
- return value;
677
685
  }
678
686
  function processSlug(value) {
679
- // eslint-disable-next-line @typescript-eslint/no-base-to-string
680
- return (value ?? '').toString().toLowerCase();
687
+ // eslint-disable-next-line @typescript-eslint/no-base-to-string
688
+ return (value ?? '').toString().toLowerCase();
681
689
  }
682
690
  function formatDevEnvLogTimestamp(date) {
683
- return date.toISOString().replace(/\..*$/, '').replace(/[-:]/g, '').replace('T', '-');
691
+ return date.toISOString().replace(/\..*$/, '').replace(/[-:]/g, '').replace('T', '-');
684
692
  }
685
693
  function formatDevEnvLogSlug(slug) {
686
- return slug.replace(/[^a-z0-9_-]+/gi, '-').toLowerCase();
694
+ return slug.replace(/[^a-z0-9_-]+/gi, '-').toLowerCase();
687
695
  }
688
696
  function getDevEnvLogFile(slug) {
689
- const slugPart = slug ? formatDevEnvLogSlug(slug) : 'all';
690
- return `vip-dev-env-${slugPart}-${formatDevEnvLogTimestamp(new Date())}.log`;
697
+ const slugPart = slug ? formatDevEnvLogSlug(slug) : 'all';
698
+ return `vip-dev-env-${slugPart}-${formatDevEnvLogTimestamp(new Date())}.log`;
691
699
  }
692
700
  function processVersionOption(value) {
693
- if (typeof value === 'string' || typeof value === 'number') {
694
- if (!isNaN(value) && Number(value) % 1 === 0) {
695
- return parseFloat(value).toFixed(1);
701
+ if (typeof value === 'string' || typeof value === 'number') {
702
+ if (!isNaN(value) && Number(value) % 1 === 0) {
703
+ return parseFloat(value).toFixed(1);
704
+ }
696
705
  }
697
- }
698
- return value?.toString() ?? '';
706
+ return value?.toString() ?? '';
699
707
  }
700
- const phpVersionsSupported = Object.keys(_devEnvironment.DEV_ENVIRONMENT_PHP_VERSIONS).join(', ');
708
+ const phpVersionsSupported = Object.keys(dev_environment_1.DEV_ENVIRONMENT_PHP_VERSIONS).join(', ');
701
709
  function addDevEnvConfigurationOptions(command) {
702
- // We leave the third parameter to undefined on some because the defaults are handled in preProcessInstanceData()
703
- return command.option('wordpress', 'Manage the version of WordPress. Accepts a string value for major versions (6.x) or "latest". Defaults to the recommended version of WordPress for development.', undefined, processVersionOption).option(['u', 'mu-plugins'], 'Manage the source for VIP MU plugins. Accepts "demo" (default) for a read-only image of the staging branch, or a path to a built copy of VIP MU plugins on the local machine.').option('app-code', 'Manage the source for application code. Accepts "demo" (default) for a read-only image of WordPress VIP skeleton application code, or a path to a VIP formatted application repo on the local machine.').option('phpmyadmin', 'Enable or disable phpMyAdmin, disabled by default. Accepts "y" (default value) to enable or "n" to disable. When enabled, refer to the value of "PHPMYADMIN URLS" in the information output for a local environment for the URL to access phpMyAdmin.', undefined, processBooleanOption).option('xdebug', 'Enable or disable XDebug, disabled by default. Accepts "y" (default value) to enable or "n" to disable.', undefined, processBooleanOption).option('xdebug_config', 'Override some default configuration settings for Xdebug. Accepts a string value that is assigned to the XDEBUG_CONFIG environment variable.').option('elasticsearch', 'Enable or disable Elasticsearch (required by Enterprise Search), disabled by default. Accepts "y" (default value) to enable or "n" to disable.', undefined, processBooleanOption).option(['r', 'media-redirect-domain'], 'Configure media files to be proxied from a VIP Platform environment. Accepts a string value for the primary domain of the VIP Platform environment or "n" to disable the media proxy.', undefined, processMediaRedirectDomainOption).option('php', `Manage the version of PHP. Accepts a string value for minor versions: ${phpVersionsSupported}`, undefined, processVersionOption).option('cron', 'Enable or disable cron, disabled by default. Accepts "y" (default value) to enable or "n" to disable.', undefined, processBooleanOption).option(['A', 'mailpit'], 'Enable or disable Mailpit, disabled by default. Accepts "y" (default value) to enable or "n" to disable.', undefined, processBooleanOption).option(['H', 'photon'], 'Enable or disable Photon, disabled by default. Accepts "y" (default value) to enable or "n" to disable.', undefined, processBooleanOption);
710
+ // We leave the third parameter to undefined on some because the defaults are handled in preProcessInstanceData()
711
+ return command
712
+ .option('wordpress', 'Manage the version of WordPress. Accepts a string value for major versions (6.x) or "latest". Defaults to the recommended version of WordPress for development.', undefined, processVersionOption)
713
+ .option(['u', 'mu-plugins'], 'Manage the source for VIP MU plugins. Accepts "demo" (default) for a read-only image of the staging branch, or a path to a built copy of VIP MU plugins on the local machine.')
714
+ .option('app-code', 'Manage the source for application code. Accepts "demo" (default) for a read-only image of WordPress VIP skeleton application code, or a path to a VIP formatted application repo on the local machine.')
715
+ .option('phpmyadmin', 'Enable or disable phpMyAdmin, disabled by default. Accepts "y" (default value) to enable or "n" to disable. When enabled, refer to the value of "PHPMYADMIN URLS" in the information output for a local environment for the URL to access phpMyAdmin.', undefined, processBooleanOption)
716
+ .option('xdebug', 'Enable or disable XDebug, disabled by default. Accepts "y" (default value) to enable or "n" to disable.', undefined, processBooleanOption)
717
+ .option('xdebug_config', 'Override some default configuration settings for Xdebug. Accepts a string value that is assigned to the XDEBUG_CONFIG environment variable.')
718
+ .option('elasticsearch', 'Enable or disable Elasticsearch (required by Enterprise Search), disabled by default. Accepts "y" (default value) to enable or "n" to disable.', undefined, processBooleanOption)
719
+ .option(['r', 'media-redirect-domain'], 'Configure media files to be proxied from a VIP Platform environment. Accepts a string value for the primary domain of the VIP Platform environment or "n" to disable the media proxy.', undefined, processMediaRedirectDomainOption)
720
+ .option('php', `Manage the version of PHP. Accepts a string value for minor versions: ${phpVersionsSupported}`, undefined, processVersionOption)
721
+ .option('cron', 'Enable or disable cron, disabled by default. Accepts "y" (default value) to enable or "n" to disable.', undefined, processBooleanOption)
722
+ .option(['A', 'mailpit'], 'Enable or disable Mailpit, disabled by default. Accepts "y" (default value) to enable or "n" to disable.', undefined, processBooleanOption)
723
+ .option(['H', 'photon'], 'Enable or disable Photon, disabled by default. Accepts "y" (default value) to enable or "n" to disable.', undefined, processBooleanOption);
704
724
  }
705
-
706
725
  /**
707
726
  * Provides the list of tag choices for selection
708
727
  */
709
728
  async function getTagChoices() {
710
- let versions = await (0, _devEnvironmentCore.getVersionList)();
711
- if (versions.length < 1) {
712
- versions = [{
713
- ref: '6.1.1',
714
- tag: '6.1',
715
- cacheable: true,
716
- locked: true,
717
- prerelease: false
718
- }, {
719
- ref: '6.0.3',
720
- tag: '6.0',
721
- cacheable: true,
722
- locked: true,
723
- prerelease: false
724
- }, {
725
- ref: '5.9.5',
726
- tag: '5.9',
727
- cacheable: true,
728
- locked: true,
729
- prerelease: false
730
- }];
731
- }
732
- return versions.map(version => {
733
- let mapping;
734
- const tagFormatted = version.tag.padEnd(8 - version.tag.length);
735
- const prerelease = version.prerelease ? '(Pre-Release)' : '';
736
- if (version.tag !== version.ref) {
737
- mapping = `→ ${prerelease} ${version.ref}`;
738
- } else {
739
- mapping = '';
729
+ let versions = await (0, dev_environment_core_1.getVersionList)();
730
+ if (versions.length < 1) {
731
+ versions = [
732
+ {
733
+ ref: '6.1.1',
734
+ tag: '6.1',
735
+ cacheable: true,
736
+ locked: true,
737
+ prerelease: false,
738
+ },
739
+ {
740
+ ref: '6.0.3',
741
+ tag: '6.0',
742
+ cacheable: true,
743
+ locked: true,
744
+ prerelease: false,
745
+ },
746
+ {
747
+ ref: '5.9.5',
748
+ tag: '5.9',
749
+ cacheable: true,
750
+ locked: true,
751
+ prerelease: false,
752
+ },
753
+ ];
740
754
  }
741
- return {
742
- name: version.tag,
743
- message: `${tagFormatted} ${mapping}`,
744
- value: version.tag
745
- };
746
- });
755
+ return versions.map(version => {
756
+ let mapping;
757
+ const tagFormatted = version.tag.padEnd(8 - version.tag.length);
758
+ const prerelease = version.prerelease ? '(Pre-Release)' : '';
759
+ if (version.tag !== version.ref) {
760
+ mapping = `→ ${prerelease} ${version.ref}`;
761
+ }
762
+ else {
763
+ mapping = '';
764
+ }
765
+ return {
766
+ name: version.tag,
767
+ message: `${tagFormatted} ${mapping}`,
768
+ value: version.tag,
769
+ };
770
+ });
747
771
  }
748
-
749
772
  // Keep this list in sync with vip-next's devEnvTrackingInfo. Instance data may
750
773
  // contain credentials and user-defined fields that must stay local (PLTFRM-2820).
751
- const TRACKING_ALLOWED_KEYS = ['siteSlug', 'wpTitle', 'multisite', 'wordpress', 'muPlugins', 'appCode', 'mediaRedirectDomain', 'phpmyadmin', 'xdebug', 'xdebugConfig', 'mariadb', 'php', 'elasticsearch', 'mailpit', 'photon', 'cron', 'pullAfter', 'version'];
774
+ const TRACKING_ALLOWED_KEYS = [
775
+ 'siteSlug',
776
+ 'wpTitle',
777
+ 'multisite',
778
+ 'wordpress',
779
+ 'muPlugins',
780
+ 'appCode',
781
+ 'mediaRedirectDomain',
782
+ 'phpmyadmin',
783
+ 'xdebug',
784
+ 'xdebugConfig',
785
+ 'mariadb',
786
+ 'php',
787
+ 'elasticsearch',
788
+ 'mailpit',
789
+ 'photon',
790
+ 'cron',
791
+ 'pullAfter',
792
+ 'version',
793
+ ];
752
794
  function getEnvTrackingInfo(slug) {
753
- try {
754
- const envData = (0, _devEnvironmentCore.readEnvironmentData)(slug);
755
- const result = {
756
- slug
757
- };
758
- for (const key of TRACKING_ALLOWED_KEYS) {
759
- if (!Object.hasOwn(envData, key)) {
760
- continue;
761
- }
762
-
763
- // track doesn't like camelCase
764
- const snakeCasedKey = key.replace(/[A-Z]/g, letter => `_${letter.toLowerCase()}`);
765
- const value = _devEnvironment.DEV_ENVIRONMENT_COMPONENTS_WITH_WP.includes(key) ? JSON.stringify(envData[key]) : envData[key];
766
- result[snakeCasedKey] = value;
767
- }
768
- if (typeof result.php === 'string') {
769
- result.php = result.php.replace(/^[^:]+:/, '');
795
+ try {
796
+ const envData = (0, dev_environment_core_1.readEnvironmentData)(slug);
797
+ const result = { slug };
798
+ for (const key of TRACKING_ALLOWED_KEYS) {
799
+ if (!Object.hasOwn(envData, key)) {
800
+ continue;
801
+ }
802
+ // track doesn't like camelCase
803
+ const snakeCasedKey = key.replace(/[A-Z]/g, letter => `_${letter.toLowerCase()}`);
804
+ const value = dev_environment_1.DEV_ENVIRONMENT_COMPONENTS_WITH_WP.includes(key)
805
+ ? JSON.stringify(envData[key])
806
+ : envData[key];
807
+ result[snakeCasedKey] = value;
808
+ }
809
+ if (typeof result.php === 'string') {
810
+ result.php = result.php.replace(/^[^:]+:/, '');
811
+ }
812
+ return result;
813
+ }
814
+ catch {
815
+ return {
816
+ slug,
817
+ };
770
818
  }
771
- return result;
772
- } catch {
773
- return {
774
- slug
775
- };
776
- }
777
819
  }
778
820
  // Map of supported editors and their configurations
779
821
  const SUPPORTED_EDITORS = {
780
- vscode: {
781
- displayName: 'VS Code',
782
- candidates: ['code', 'code-insiders', 'codium'],
783
- workspace: {
784
- extension: 'code-workspace',
785
- generator: _devEnvironmentCore.generateVSCodeWorkspace
786
- }
787
- },
788
- cursor: {
789
- displayName: 'Cursor',
790
- candidates: ['cursor'],
791
- workspace: {
792
- extension: 'code-workspace',
793
- generator: _devEnvironmentCore.generateVSCodeWorkspace
794
- }
795
- },
796
- phpstorm: {
797
- displayName: 'PHPStorm',
798
- candidates: ['phpstorm', 'phpstorm64.exe'],
799
- errors: {
800
- notFound: `PHPStorm launcher was not detected in the expected path.\nPlease follow the setup instructions: https://www.jetbrains.com/help/phpstorm/working-with-the-ide-features-from-command-line.html#standalone`
822
+ vscode: {
823
+ displayName: 'VS Code',
824
+ candidates: ['code', 'code-insiders', 'codium'],
825
+ workspace: {
826
+ extension: 'code-workspace',
827
+ generator: dev_environment_core_1.generateVSCodeWorkspace,
828
+ },
829
+ },
830
+ cursor: {
831
+ displayName: 'Cursor',
832
+ candidates: ['cursor'],
833
+ workspace: {
834
+ extension: 'code-workspace',
835
+ generator: dev_environment_core_1.generateVSCodeWorkspace,
836
+ },
837
+ },
838
+ phpstorm: {
839
+ displayName: 'PHPStorm',
840
+ candidates: ['phpstorm', 'phpstorm64.exe'],
841
+ errors: {
842
+ notFound: `PHPStorm launcher was not detected in the expected path.\nPlease follow the setup instructions: https://www.jetbrains.com/help/phpstorm/working-with-the-ide-features-from-command-line.html#standalone`,
843
+ },
844
+ workspace: {
845
+ extension: 'iml',
846
+ generator: dev_environment_core_1.generatePHPStormWorkspace,
847
+ },
848
+ },
849
+ windsurf: {
850
+ displayName: 'Windsurf',
851
+ candidates: ['windsurf'],
852
+ workspace: {
853
+ extension: 'code-workspace',
854
+ generator: dev_environment_core_1.generateVSCodeWorkspace,
855
+ },
801
856
  },
802
- workspace: {
803
- extension: 'iml',
804
- generator: _devEnvironmentCore.generatePHPStormWorkspace
805
- }
806
- },
807
- windsurf: {
808
- displayName: 'Windsurf',
809
- candidates: ['windsurf'],
810
- workspace: {
811
- extension: 'code-workspace',
812
- generator: _devEnvironmentCore.generateVSCodeWorkspace
813
- }
814
- }
815
857
  };
816
-
817
858
  // Helper to get workspace path for any editor
818
859
  function getWorkspacePath(slug, editor) {
819
- const {
820
- workspace
821
- } = SUPPORTED_EDITORS[editor];
822
- if (editor === 'phpstorm') {
823
- return _path.default.join((0, _devEnvironmentCore.getEnvironmentPath)(slug), '.idea', `${slug}.${workspace.extension}`);
824
- }
825
- return _path.default.join((0, _devEnvironmentCore.getEnvironmentPath)(slug), `${slug}.${workspace.extension}`);
860
+ const { workspace } = SUPPORTED_EDITORS[editor];
861
+ if (editor === 'phpstorm') {
862
+ return path_1.default.join((0, dev_environment_core_1.getEnvironmentPath)(slug), '.idea', `${slug}.${workspace.extension}`);
863
+ }
864
+ return path_1.default.join((0, dev_environment_core_1.getEnvironmentPath)(slug), `${slug}.${workspace.extension}`);
826
865
  }
827
866
  function postStart(slug, options) {
828
- let editorType;
829
- if (options.editor) {
830
- const editor = options.editor.toLowerCase();
831
- if (!Object.keys(SUPPORTED_EDITORS).includes(editor)) {
832
- throw new Error(`Invalid editor specified. Supported editors are: ${Object.keys(SUPPORTED_EDITORS).join(', ')}`);
833
- }
834
- editorType = editor;
835
- } else if (options.vscode) {
836
- editorType = 'vscode';
837
- }
838
- if (editorType) {
839
- launchEditor(slug, editorType);
840
- }
867
+ let editorType;
868
+ if (options.editor) {
869
+ const editor = options.editor.toLowerCase();
870
+ if (!Object.keys(SUPPORTED_EDITORS).includes(editor)) {
871
+ throw new Error(`Invalid editor specified. Supported editors are: ${Object.keys(SUPPORTED_EDITORS).join(', ')}`);
872
+ }
873
+ editorType = editor;
874
+ }
875
+ else if (options.vscode) {
876
+ editorType = 'vscode';
877
+ }
878
+ if (editorType) {
879
+ launchEditor(slug, editorType);
880
+ }
841
881
  }
842
882
  const launchEditor = (slug, type) => {
843
- const editorConfig = SUPPORTED_EDITORS[type];
844
- const workspacePath = getWorkspacePath(slug, type);
845
- if ((0, _nodeFs.existsSync)(workspacePath)) {
846
- console.log('Project already exists, skipping creation.');
847
- } else {
848
- editorConfig.workspace.generator(slug);
849
- console.log(`${editorConfig.displayName} project generated`);
850
- }
851
- console.log(`Project file location:\n${workspacePath}\n`);
852
- const executable = findExecutable(editorConfig.candidates);
853
- if (executable) {
854
- // For PHPStorm, pass the environment home folder instead of the workspace path
855
- const launchPath = type === 'phpstorm' ? (0, _devEnvironmentCore.getEnvironmentPath)(slug) : workspacePath;
856
- (0, _child_process.spawn)(executable, [launchPath], {
857
- shell: process.platform === 'win32'
858
- });
859
- } else {
860
- console.log(editorConfig.errors?.notFound || `${editorConfig.displayName} was not detected in the expected path.`);
861
- }
883
+ const editorConfig = SUPPORTED_EDITORS[type];
884
+ const workspacePath = getWorkspacePath(slug, type);
885
+ if ((0, node_fs_1.existsSync)(workspacePath)) {
886
+ console.log('Project already exists, skipping creation.');
887
+ }
888
+ else {
889
+ editorConfig.workspace.generator(slug);
890
+ console.log(`${editorConfig.displayName} project generated`);
891
+ }
892
+ console.log(`Project file location:\n${workspacePath}\n`);
893
+ const executable = findExecutable(editorConfig.candidates);
894
+ if (executable) {
895
+ // For PHPStorm, pass the environment home folder instead of the workspace path
896
+ const launchPath = type === 'phpstorm' ? (0, dev_environment_core_1.getEnvironmentPath)(slug) : workspacePath;
897
+ (0, child_process_1.spawn)(executable, [launchPath], { shell: process.platform === 'win32' });
898
+ }
899
+ else {
900
+ console.log(editorConfig.errors?.notFound ||
901
+ `${editorConfig.displayName} was not detected in the expected path.`);
902
+ }
903
+ };
904
+ const findExecutable = (candidates) => {
905
+ for (const candidate of candidates) {
906
+ const result = (0, shelljs_1.which)(candidate);
907
+ if (result) {
908
+ debug(`Found ${candidate} in path`);
909
+ return candidate;
910
+ }
911
+ debug(`Could not find ${candidate} in path`);
912
+ }
913
+ return null;
862
914
  };
863
- const findExecutable = candidates => {
864
- for (const candidate of candidates) {
865
- const result = (0, _shelljs.which)(candidate);
866
- if (result) {
867
- debug(`Found ${candidate} in path`);
868
- return candidate;
869
- }
870
- debug(`Could not find ${candidate} in path`);
871
- }
872
- return null;
873
- };