spindb 0.37.2 → 0.38.0

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 (811) hide show
  1. package/dist/cli/bin.js +9 -0
  2. package/dist/cli/bin.js.map +1 -0
  3. package/dist/cli/commands/attach.js +102 -0
  4. package/dist/cli/commands/attach.js.map +1 -0
  5. package/dist/cli/commands/backup.js +197 -0
  6. package/dist/cli/commands/backup.js.map +1 -0
  7. package/dist/cli/commands/backups.js +190 -0
  8. package/dist/cli/commands/backups.js.map +1 -0
  9. package/dist/cli/commands/clone.js +119 -0
  10. package/dist/cli/commands/clone.js.map +1 -0
  11. package/dist/cli/commands/config.js +276 -0
  12. package/dist/cli/commands/config.js.map +1 -0
  13. package/dist/cli/commands/connect.js +559 -0
  14. package/dist/cli/commands/connect.js.map +1 -0
  15. package/dist/cli/commands/create.js +952 -0
  16. package/dist/cli/commands/create.js.map +1 -0
  17. package/dist/cli/commands/databases.js +485 -0
  18. package/dist/cli/commands/databases.js.map +1 -0
  19. package/dist/cli/commands/delete.js +106 -0
  20. package/dist/cli/commands/delete.js.map +1 -0
  21. package/dist/cli/commands/deps.js +238 -0
  22. package/dist/cli/commands/deps.js.map +1 -0
  23. package/dist/cli/commands/detach.js +81 -0
  24. package/dist/cli/commands/detach.js.map +1 -0
  25. package/dist/cli/commands/doctor.js +567 -0
  26. package/dist/cli/commands/doctor.js.map +1 -0
  27. package/dist/cli/commands/duckdb.js +207 -0
  28. package/dist/cli/commands/duckdb.js.map +1 -0
  29. package/dist/cli/commands/edit.js +524 -0
  30. package/dist/cli/commands/edit.js.map +1 -0
  31. package/dist/cli/commands/engines.js +1414 -0
  32. package/dist/cli/commands/engines.js.map +1 -0
  33. package/dist/cli/commands/export.js +383 -0
  34. package/dist/cli/commands/export.js.map +1 -0
  35. package/dist/cli/commands/info.js +270 -0
  36. package/dist/cli/commands/info.js.map +1 -0
  37. package/dist/cli/commands/list.js +215 -0
  38. package/dist/cli/commands/list.js.map +1 -0
  39. package/dist/cli/commands/logs.js +81 -0
  40. package/dist/cli/commands/logs.js.map +1 -0
  41. package/dist/cli/commands/menu/backup-handlers.js +1202 -0
  42. package/dist/cli/commands/menu/backup-handlers.js.map +1 -0
  43. package/dist/cli/commands/menu/container-handlers.js +1788 -0
  44. package/dist/cli/commands/menu/container-handlers.js.map +1 -0
  45. package/dist/cli/commands/menu/engine-handlers.js +235 -0
  46. package/dist/cli/commands/menu/engine-handlers.js.map +1 -0
  47. package/dist/cli/commands/menu/index.js +266 -0
  48. package/dist/cli/commands/menu/index.js.map +1 -0
  49. package/dist/cli/commands/menu/settings-handlers.js +320 -0
  50. package/dist/cli/commands/menu/settings-handlers.js.map +1 -0
  51. package/dist/cli/commands/menu/shared.js +13 -0
  52. package/dist/cli/commands/menu/shared.js.map +1 -0
  53. package/dist/cli/commands/menu/shell-handlers.js +1573 -0
  54. package/dist/cli/commands/menu/shell-handlers.js.map +1 -0
  55. package/dist/cli/commands/menu/sql-handlers.js +185 -0
  56. package/dist/cli/commands/menu/sql-handlers.js.map +1 -0
  57. package/dist/cli/commands/menu/update-handlers.js +322 -0
  58. package/dist/cli/commands/menu/update-handlers.js.map +1 -0
  59. package/dist/cli/commands/menu/validators.js +9 -0
  60. package/dist/cli/commands/menu/validators.js.map +1 -0
  61. package/dist/cli/commands/ports.js +166 -0
  62. package/dist/cli/commands/ports.js.map +1 -0
  63. package/dist/cli/commands/pull.js +166 -0
  64. package/dist/cli/commands/pull.js.map +1 -0
  65. package/dist/cli/commands/query.js +180 -0
  66. package/dist/cli/commands/query.js.map +1 -0
  67. package/dist/cli/commands/restore.js +428 -0
  68. package/dist/cli/commands/restore.js.map +1 -0
  69. package/dist/cli/commands/run.js +115 -0
  70. package/dist/cli/commands/run.js.map +1 -0
  71. package/dist/cli/commands/self-update.js +99 -0
  72. package/dist/cli/commands/self-update.js.map +1 -0
  73. package/dist/cli/commands/sqlite.js +207 -0
  74. package/dist/cli/commands/sqlite.js.map +1 -0
  75. package/dist/cli/commands/start.js +196 -0
  76. package/dist/cli/commands/start.js.map +1 -0
  77. package/dist/cli/commands/stop.js +182 -0
  78. package/dist/cli/commands/stop.js.map +1 -0
  79. package/dist/cli/commands/url.js +88 -0
  80. package/dist/cli/commands/url.js.map +1 -0
  81. package/dist/cli/commands/users.js +189 -0
  82. package/dist/cli/commands/users.js.map +1 -0
  83. package/dist/cli/commands/version.js +52 -0
  84. package/dist/cli/commands/version.js.map +1 -0
  85. package/dist/cli/commands/which.js +258 -0
  86. package/dist/cli/commands/which.js.map +1 -0
  87. package/dist/cli/constants.js +212 -0
  88. package/dist/cli/constants.js.map +1 -0
  89. package/dist/cli/helpers.js +1120 -0
  90. package/dist/cli/helpers.js.map +1 -0
  91. package/dist/cli/index.js +146 -0
  92. package/dist/cli/index.js.map +1 -0
  93. package/dist/cli/ui/prompts.js +1002 -0
  94. package/dist/cli/ui/prompts.js.map +1 -0
  95. package/dist/cli/ui/spinner.js +74 -0
  96. package/dist/cli/ui/spinner.js.map +1 -0
  97. package/dist/cli/ui/theme.js +99 -0
  98. package/dist/cli/ui/theme.js.map +1 -0
  99. package/dist/cli/utils/file-follower.js +79 -0
  100. package/dist/cli/utils/file-follower.js.map +1 -0
  101. package/dist/config/backup-formats.js +363 -0
  102. package/dist/config/backup-formats.js.map +1 -0
  103. package/dist/config/defaults.js +25 -0
  104. package/dist/config/defaults.js.map +1 -0
  105. package/dist/config/engine-defaults.js +303 -0
  106. package/dist/config/engine-defaults.js.map +1 -0
  107. package/dist/config/engines-registry.js +103 -0
  108. package/dist/config/engines-registry.js.map +1 -0
  109. package/dist/config/os-dependencies.js +767 -0
  110. package/dist/config/os-dependencies.js.map +1 -0
  111. package/dist/config/paths.js +156 -0
  112. package/dist/config/paths.js.map +1 -0
  113. package/dist/config/version.js +3 -0
  114. package/dist/config/version.js.map +1 -0
  115. package/dist/core/backup-restore.js +219 -0
  116. package/dist/core/backup-restore.js.map +1 -0
  117. package/dist/core/base-binary-manager.js +403 -0
  118. package/dist/core/base-binary-manager.js.map +1 -0
  119. package/dist/core/base-document-binary-manager.js +364 -0
  120. package/dist/core/base-document-binary-manager.js.map +1 -0
  121. package/dist/core/base-embedded-binary-manager.js +364 -0
  122. package/dist/core/base-embedded-binary-manager.js.map +1 -0
  123. package/dist/core/base-server-binary-manager.js +368 -0
  124. package/dist/core/base-server-binary-manager.js.map +1 -0
  125. package/dist/core/config-manager.js +495 -0
  126. package/dist/core/config-manager.js.map +1 -0
  127. package/dist/core/container-manager.js +609 -0
  128. package/dist/core/container-manager.js.map +1 -0
  129. package/dist/core/credential-generator.js +67 -0
  130. package/dist/core/credential-generator.js.map +1 -0
  131. package/dist/core/credential-manager.js +211 -0
  132. package/dist/core/credential-manager.js.map +1 -0
  133. package/dist/core/dblab-utils.js +105 -0
  134. package/dist/core/dblab-utils.js.map +1 -0
  135. package/dist/core/dependency-manager.js +359 -0
  136. package/dist/core/dependency-manager.js.map +1 -0
  137. package/dist/core/docker-exporter.js +1077 -0
  138. package/dist/core/docker-exporter.js.map +1 -0
  139. package/dist/core/error-handler.js +295 -0
  140. package/dist/core/error-handler.js.map +1 -0
  141. package/dist/core/fs-error-utils.js +74 -0
  142. package/dist/core/fs-error-utils.js.map +1 -0
  143. package/dist/core/homebrew-version-manager.js +280 -0
  144. package/dist/core/homebrew-version-manager.js.map +1 -0
  145. package/dist/core/hostdb-client.js +252 -0
  146. package/dist/core/hostdb-client.js.map +1 -0
  147. package/dist/core/hostdb-metadata.js +243 -0
  148. package/dist/core/hostdb-metadata.js.map +1 -0
  149. package/dist/core/hostdb-releases-factory.js +161 -0
  150. package/dist/core/hostdb-releases-factory.js.map +1 -0
  151. package/dist/core/library-env.js +88 -0
  152. package/dist/core/library-env.js.map +1 -0
  153. package/dist/core/pgweb-utils.js +53 -0
  154. package/dist/core/pgweb-utils.js.map +1 -0
  155. package/dist/core/platform-service.js +632 -0
  156. package/dist/core/platform-service.js.map +1 -0
  157. package/dist/core/port-manager.js +136 -0
  158. package/dist/core/port-manager.js.map +1 -0
  159. package/dist/core/process-manager.js +445 -0
  160. package/dist/core/process-manager.js.map +1 -0
  161. package/dist/core/pull-manager.js +418 -0
  162. package/dist/core/pull-manager.js.map +1 -0
  163. package/dist/core/query-parser.js +449 -0
  164. package/dist/core/query-parser.js.map +1 -0
  165. package/dist/core/spawn-utils.js +90 -0
  166. package/dist/core/spawn-utils.js.map +1 -0
  167. package/dist/core/start-with-retry.js +90 -0
  168. package/dist/core/start-with-retry.js.map +1 -0
  169. package/dist/core/test-cleanup.js +85 -0
  170. package/dist/core/test-cleanup.js.map +1 -0
  171. package/dist/core/tls-generator.js +84 -0
  172. package/dist/core/tls-generator.js.map +1 -0
  173. package/dist/core/transaction-manager.js +139 -0
  174. package/dist/core/transaction-manager.js.map +1 -0
  175. package/dist/core/update-manager.js +241 -0
  176. package/dist/core/update-manager.js.map +1 -0
  177. package/dist/core/version-migration.js +260 -0
  178. package/dist/core/version-migration.js.map +1 -0
  179. package/dist/core/version-utils.js +91 -0
  180. package/dist/core/version-utils.js.map +1 -0
  181. package/dist/engines/base-engine.js +179 -0
  182. package/dist/engines/base-engine.js.map +1 -0
  183. package/dist/engines/clickhouse/backup.js +289 -0
  184. package/dist/engines/clickhouse/backup.js.map +1 -0
  185. package/dist/engines/clickhouse/binary-manager.js +145 -0
  186. package/dist/engines/clickhouse/binary-manager.js.map +1 -0
  187. package/dist/engines/clickhouse/binary-urls.js +100 -0
  188. package/dist/engines/clickhouse/binary-urls.js.map +1 -0
  189. package/dist/engines/clickhouse/cli-utils.js +143 -0
  190. package/dist/engines/clickhouse/cli-utils.js.map +1 -0
  191. package/dist/engines/clickhouse/hostdb-releases.js +24 -0
  192. package/dist/engines/clickhouse/hostdb-releases.js.map +1 -0
  193. package/dist/engines/clickhouse/index.js +1077 -0
  194. package/dist/engines/clickhouse/index.js.map +1 -0
  195. package/dist/engines/clickhouse/restore.js +335 -0
  196. package/dist/engines/clickhouse/restore.js.map +1 -0
  197. package/dist/engines/clickhouse/version-maps.js +83 -0
  198. package/dist/engines/clickhouse/version-maps.js.map +1 -0
  199. package/dist/engines/clickhouse/version-validator.js +133 -0
  200. package/dist/engines/clickhouse/version-validator.js.map +1 -0
  201. package/dist/engines/cockroachdb/backup.js +261 -0
  202. package/dist/engines/cockroachdb/backup.js.map +1 -0
  203. package/dist/engines/cockroachdb/binary-manager.js +33 -0
  204. package/dist/engines/cockroachdb/binary-manager.js.map +1 -0
  205. package/dist/engines/cockroachdb/binary-urls.js +33 -0
  206. package/dist/engines/cockroachdb/binary-urls.js.map +1 -0
  207. package/dist/engines/cockroachdb/cli-utils.js +338 -0
  208. package/dist/engines/cockroachdb/cli-utils.js.map +1 -0
  209. package/dist/engines/cockroachdb/hostdb-releases.js +21 -0
  210. package/dist/engines/cockroachdb/hostdb-releases.js.map +1 -0
  211. package/dist/engines/cockroachdb/index.js +1016 -0
  212. package/dist/engines/cockroachdb/index.js.map +1 -0
  213. package/dist/engines/cockroachdb/restore.js +323 -0
  214. package/dist/engines/cockroachdb/restore.js.map +1 -0
  215. package/dist/engines/cockroachdb/version-maps.js +37 -0
  216. package/dist/engines/cockroachdb/version-maps.js.map +1 -0
  217. package/dist/engines/couchdb/api-client.js +64 -0
  218. package/dist/engines/couchdb/api-client.js.map +1 -0
  219. package/dist/engines/couchdb/backup.js +90 -0
  220. package/dist/engines/couchdb/backup.js.map +1 -0
  221. package/dist/engines/couchdb/binary-manager.js +62 -0
  222. package/dist/engines/couchdb/binary-manager.js.map +1 -0
  223. package/dist/engines/couchdb/binary-urls.js +92 -0
  224. package/dist/engines/couchdb/binary-urls.js.map +1 -0
  225. package/dist/engines/couchdb/hostdb-releases.js +21 -0
  226. package/dist/engines/couchdb/hostdb-releases.js.map +1 -0
  227. package/dist/engines/couchdb/index.js +1043 -0
  228. package/dist/engines/couchdb/index.js.map +1 -0
  229. package/dist/engines/couchdb/restore.js +198 -0
  230. package/dist/engines/couchdb/restore.js.map +1 -0
  231. package/dist/engines/couchdb/version-maps.js +67 -0
  232. package/dist/engines/couchdb/version-maps.js.map +1 -0
  233. package/dist/engines/couchdb/version-validator.js +88 -0
  234. package/dist/engines/couchdb/version-validator.js.map +1 -0
  235. package/dist/engines/duckdb/binary-manager.js +33 -0
  236. package/dist/engines/duckdb/binary-manager.js.map +1 -0
  237. package/{engines/duckdb/binary-urls.ts → dist/engines/duckdb/binary-urls.js} +11 -16
  238. package/dist/engines/duckdb/binary-urls.js.map +1 -0
  239. package/dist/engines/duckdb/hostdb-releases.js +21 -0
  240. package/dist/engines/duckdb/hostdb-releases.js.map +1 -0
  241. package/dist/engines/duckdb/index.js +594 -0
  242. package/dist/engines/duckdb/index.js.map +1 -0
  243. package/dist/engines/duckdb/registry.js +265 -0
  244. package/dist/engines/duckdb/registry.js.map +1 -0
  245. package/dist/engines/duckdb/scanner.js +12 -0
  246. package/dist/engines/duckdb/scanner.js.map +1 -0
  247. package/dist/engines/duckdb/version-maps.js +67 -0
  248. package/dist/engines/duckdb/version-maps.js.map +1 -0
  249. package/dist/engines/duckdb/version-validator.js +62 -0
  250. package/dist/engines/duckdb/version-validator.js.map +1 -0
  251. package/dist/engines/ferretdb/backup.js +170 -0
  252. package/dist/engines/ferretdb/backup.js.map +1 -0
  253. package/dist/engines/ferretdb/binary-manager.js +765 -0
  254. package/dist/engines/ferretdb/binary-manager.js.map +1 -0
  255. package/dist/engines/ferretdb/binary-urls.js +135 -0
  256. package/dist/engines/ferretdb/binary-urls.js.map +1 -0
  257. package/dist/engines/ferretdb/index.js +1517 -0
  258. package/dist/engines/ferretdb/index.js.map +1 -0
  259. package/dist/engines/ferretdb/restore.js +310 -0
  260. package/dist/engines/ferretdb/restore.js.map +1 -0
  261. package/{engines/ferretdb/version-maps.ts → dist/engines/ferretdb/version-maps.js} +62 -79
  262. package/dist/engines/ferretdb/version-maps.js.map +1 -0
  263. package/dist/engines/file-based-utils.js +184 -0
  264. package/dist/engines/file-based-utils.js.map +1 -0
  265. package/dist/engines/index.js +124 -0
  266. package/dist/engines/index.js.map +1 -0
  267. package/dist/engines/influxdb/api-client.js +54 -0
  268. package/dist/engines/influxdb/api-client.js.map +1 -0
  269. package/dist/engines/influxdb/backup.js +119 -0
  270. package/dist/engines/influxdb/backup.js.map +1 -0
  271. package/dist/engines/influxdb/binary-manager.js +87 -0
  272. package/dist/engines/influxdb/binary-manager.js.map +1 -0
  273. package/dist/engines/influxdb/binary-urls.js +56 -0
  274. package/dist/engines/influxdb/binary-urls.js.map +1 -0
  275. package/dist/engines/influxdb/hostdb-releases.js +21 -0
  276. package/dist/engines/influxdb/hostdb-releases.js.map +1 -0
  277. package/dist/engines/influxdb/index.js +962 -0
  278. package/dist/engines/influxdb/index.js.map +1 -0
  279. package/dist/engines/influxdb/restore.js +329 -0
  280. package/dist/engines/influxdb/restore.js.map +1 -0
  281. package/dist/engines/influxdb/version-maps.js +64 -0
  282. package/dist/engines/influxdb/version-maps.js.map +1 -0
  283. package/dist/engines/influxdb/version-validator.js +109 -0
  284. package/dist/engines/influxdb/version-validator.js.map +1 -0
  285. package/dist/engines/mariadb/backup.js +178 -0
  286. package/dist/engines/mariadb/backup.js.map +1 -0
  287. package/dist/engines/mariadb/binary-manager.js +33 -0
  288. package/dist/engines/mariadb/binary-manager.js.map +1 -0
  289. package/{engines/mariadb/binary-urls.ts → dist/engines/mariadb/binary-urls.js} +38 -55
  290. package/dist/engines/mariadb/binary-urls.js.map +1 -0
  291. package/dist/engines/mariadb/hostdb-releases.js +21 -0
  292. package/dist/engines/mariadb/hostdb-releases.js.map +1 -0
  293. package/dist/engines/mariadb/index.js +1011 -0
  294. package/dist/engines/mariadb/index.js.map +1 -0
  295. package/dist/engines/mariadb/restore.js +322 -0
  296. package/dist/engines/mariadb/restore.js.map +1 -0
  297. package/dist/engines/mariadb/version-maps.js +63 -0
  298. package/dist/engines/mariadb/version-maps.js.map +1 -0
  299. package/dist/engines/mariadb/version-validator.js +143 -0
  300. package/dist/engines/mariadb/version-validator.js.map +1 -0
  301. package/dist/engines/meilisearch/api-client.js +50 -0
  302. package/dist/engines/meilisearch/api-client.js.map +1 -0
  303. package/dist/engines/meilisearch/backup.js +167 -0
  304. package/dist/engines/meilisearch/backup.js.map +1 -0
  305. package/dist/engines/meilisearch/binary-manager.js +31 -0
  306. package/dist/engines/meilisearch/binary-manager.js.map +1 -0
  307. package/dist/engines/meilisearch/binary-urls.js +56 -0
  308. package/dist/engines/meilisearch/binary-urls.js.map +1 -0
  309. package/dist/engines/meilisearch/hostdb-releases.js +21 -0
  310. package/dist/engines/meilisearch/hostdb-releases.js.map +1 -0
  311. package/dist/engines/meilisearch/index.js +992 -0
  312. package/dist/engines/meilisearch/index.js.map +1 -0
  313. package/dist/engines/meilisearch/restore.js +167 -0
  314. package/dist/engines/meilisearch/restore.js.map +1 -0
  315. package/dist/engines/meilisearch/version-maps.js +67 -0
  316. package/dist/engines/meilisearch/version-maps.js.map +1 -0
  317. package/dist/engines/meilisearch/version-validator.js +109 -0
  318. package/dist/engines/meilisearch/version-validator.js.map +1 -0
  319. package/dist/engines/mongodb/backup.js +109 -0
  320. package/dist/engines/mongodb/backup.js.map +1 -0
  321. package/dist/engines/mongodb/binary-manager.js +36 -0
  322. package/dist/engines/mongodb/binary-manager.js.map +1 -0
  323. package/dist/engines/mongodb/binary-urls.js +46 -0
  324. package/dist/engines/mongodb/binary-urls.js.map +1 -0
  325. package/dist/engines/mongodb/cli-utils.js +131 -0
  326. package/dist/engines/mongodb/cli-utils.js.map +1 -0
  327. package/dist/engines/mongodb/hostdb-releases.js +77 -0
  328. package/dist/engines/mongodb/hostdb-releases.js.map +1 -0
  329. package/dist/engines/mongodb/index.js +873 -0
  330. package/dist/engines/mongodb/index.js.map +1 -0
  331. package/dist/engines/mongodb/restore.js +276 -0
  332. package/dist/engines/mongodb/restore.js.map +1 -0
  333. package/dist/engines/mongodb/version-maps.js +79 -0
  334. package/dist/engines/mongodb/version-maps.js.map +1 -0
  335. package/dist/engines/mongodb/version-validator.js +133 -0
  336. package/dist/engines/mongodb/version-validator.js.map +1 -0
  337. package/dist/engines/mysql/backup.js +210 -0
  338. package/dist/engines/mysql/backup.js.map +1 -0
  339. package/dist/engines/mysql/binary-detection.js +325 -0
  340. package/dist/engines/mysql/binary-detection.js.map +1 -0
  341. package/dist/engines/mysql/binary-manager.js +30 -0
  342. package/dist/engines/mysql/binary-manager.js.map +1 -0
  343. package/dist/engines/mysql/binary-urls.js +87 -0
  344. package/dist/engines/mysql/binary-urls.js.map +1 -0
  345. package/{engines/mysql/hostdb-releases.ts → dist/engines/mysql/hostdb-releases.js} +20 -23
  346. package/dist/engines/mysql/hostdb-releases.js.map +1 -0
  347. package/dist/engines/mysql/index.js +1066 -0
  348. package/dist/engines/mysql/index.js.map +1 -0
  349. package/dist/engines/mysql/restore.js +361 -0
  350. package/dist/engines/mysql/restore.js.map +1 -0
  351. package/dist/engines/mysql/version-maps.js +79 -0
  352. package/dist/engines/mysql/version-maps.js.map +1 -0
  353. package/dist/engines/mysql/version-validator.js +266 -0
  354. package/dist/engines/mysql/version-validator.js.map +1 -0
  355. package/dist/engines/postgresql/backup.js +118 -0
  356. package/dist/engines/postgresql/backup.js.map +1 -0
  357. package/dist/engines/postgresql/binary-manager.js +85 -0
  358. package/dist/engines/postgresql/binary-manager.js.map +1 -0
  359. package/dist/engines/postgresql/binary-urls.js +80 -0
  360. package/dist/engines/postgresql/binary-urls.js.map +1 -0
  361. package/dist/engines/postgresql/hostdb-releases.js +21 -0
  362. package/dist/engines/postgresql/hostdb-releases.js.map +1 -0
  363. package/dist/engines/postgresql/index.js +852 -0
  364. package/dist/engines/postgresql/index.js.map +1 -0
  365. package/dist/engines/postgresql/remote-version.js +109 -0
  366. package/dist/engines/postgresql/remote-version.js.map +1 -0
  367. package/dist/engines/postgresql/restore.js +254 -0
  368. package/dist/engines/postgresql/restore.js.map +1 -0
  369. package/dist/engines/postgresql/version-maps.js +73 -0
  370. package/dist/engines/postgresql/version-maps.js.map +1 -0
  371. package/dist/engines/postgresql/version-validator.js +286 -0
  372. package/dist/engines/postgresql/version-validator.js.map +1 -0
  373. package/dist/engines/qdrant/api-client.js +50 -0
  374. package/dist/engines/qdrant/api-client.js.map +1 -0
  375. package/dist/engines/qdrant/backup.js +115 -0
  376. package/dist/engines/qdrant/backup.js.map +1 -0
  377. package/dist/engines/qdrant/binary-manager.js +31 -0
  378. package/dist/engines/qdrant/binary-manager.js.map +1 -0
  379. package/dist/engines/qdrant/binary-urls.js +92 -0
  380. package/dist/engines/qdrant/binary-urls.js.map +1 -0
  381. package/dist/engines/qdrant/cli-utils.js +39 -0
  382. package/dist/engines/qdrant/cli-utils.js.map +1 -0
  383. package/dist/engines/qdrant/hostdb-releases.js +21 -0
  384. package/dist/engines/qdrant/hostdb-releases.js.map +1 -0
  385. package/dist/engines/qdrant/index.js +1002 -0
  386. package/dist/engines/qdrant/index.js.map +1 -0
  387. package/dist/engines/qdrant/restore.js +154 -0
  388. package/dist/engines/qdrant/restore.js.map +1 -0
  389. package/dist/engines/qdrant/version-maps.js +67 -0
  390. package/dist/engines/qdrant/version-maps.js.map +1 -0
  391. package/dist/engines/qdrant/version-validator.js +109 -0
  392. package/dist/engines/qdrant/version-validator.js.map +1 -0
  393. package/dist/engines/questdb/backup.js +191 -0
  394. package/dist/engines/questdb/backup.js.map +1 -0
  395. package/dist/engines/questdb/binary-manager.js +247 -0
  396. package/dist/engines/questdb/binary-manager.js.map +1 -0
  397. package/dist/engines/questdb/binary-urls.js +27 -0
  398. package/dist/engines/questdb/binary-urls.js.map +1 -0
  399. package/dist/engines/questdb/hostdb-releases.js +21 -0
  400. package/dist/engines/questdb/hostdb-releases.js.map +1 -0
  401. package/dist/engines/questdb/index.js +814 -0
  402. package/dist/engines/questdb/index.js.map +1 -0
  403. package/dist/engines/questdb/restore.js +202 -0
  404. package/dist/engines/questdb/restore.js.map +1 -0
  405. package/dist/engines/questdb/version-maps.js +33 -0
  406. package/dist/engines/questdb/version-maps.js.map +1 -0
  407. package/dist/engines/questdb/version-validator.js +99 -0
  408. package/dist/engines/questdb/version-validator.js.map +1 -0
  409. package/dist/engines/redis/backup.js +292 -0
  410. package/dist/engines/redis/backup.js.map +1 -0
  411. package/dist/engines/redis/binary-manager.js +32 -0
  412. package/dist/engines/redis/binary-manager.js.map +1 -0
  413. package/dist/engines/redis/binary-urls.js +96 -0
  414. package/dist/engines/redis/binary-urls.js.map +1 -0
  415. package/dist/engines/redis/cli-utils.js +38 -0
  416. package/dist/engines/redis/cli-utils.js.map +1 -0
  417. package/dist/engines/redis/hostdb-releases.js +21 -0
  418. package/dist/engines/redis/hostdb-releases.js.map +1 -0
  419. package/dist/engines/redis/index.js +1263 -0
  420. package/dist/engines/redis/index.js.map +1 -0
  421. package/dist/engines/redis/restore.js +338 -0
  422. package/dist/engines/redis/restore.js.map +1 -0
  423. package/dist/engines/redis/version-maps.js +70 -0
  424. package/dist/engines/redis/version-maps.js.map +1 -0
  425. package/dist/engines/redis/version-validator.js +109 -0
  426. package/dist/engines/redis/version-validator.js.map +1 -0
  427. package/dist/engines/sqlite/binary-manager.js +39 -0
  428. package/dist/engines/sqlite/binary-manager.js.map +1 -0
  429. package/{engines/sqlite/binary-urls.ts → dist/engines/sqlite/binary-urls.js} +11 -16
  430. package/dist/engines/sqlite/binary-urls.js.map +1 -0
  431. package/dist/engines/sqlite/hostdb-releases.js +21 -0
  432. package/dist/engines/sqlite/hostdb-releases.js.map +1 -0
  433. package/dist/engines/sqlite/index.js +493 -0
  434. package/dist/engines/sqlite/index.js.map +1 -0
  435. package/dist/engines/sqlite/registry.js +163 -0
  436. package/dist/engines/sqlite/registry.js.map +1 -0
  437. package/dist/engines/sqlite/scanner.js +12 -0
  438. package/dist/engines/sqlite/scanner.js.map +1 -0
  439. package/dist/engines/sqlite/version-maps.js +57 -0
  440. package/dist/engines/sqlite/version-maps.js.map +1 -0
  441. package/dist/engines/surrealdb/backup.js +97 -0
  442. package/dist/engines/surrealdb/backup.js.map +1 -0
  443. package/dist/engines/surrealdb/binary-manager.js +33 -0
  444. package/dist/engines/surrealdb/binary-manager.js.map +1 -0
  445. package/dist/engines/surrealdb/binary-urls.js +33 -0
  446. package/dist/engines/surrealdb/binary-urls.js.map +1 -0
  447. package/dist/engines/surrealdb/cli-utils.js +147 -0
  448. package/dist/engines/surrealdb/cli-utils.js.map +1 -0
  449. package/dist/engines/surrealdb/hostdb-releases.js +21 -0
  450. package/dist/engines/surrealdb/hostdb-releases.js.map +1 -0
  451. package/dist/engines/surrealdb/index.js +1022 -0
  452. package/dist/engines/surrealdb/index.js.map +1 -0
  453. package/dist/engines/surrealdb/restore.js +224 -0
  454. package/dist/engines/surrealdb/restore.js.map +1 -0
  455. package/dist/engines/surrealdb/version-maps.js +36 -0
  456. package/dist/engines/surrealdb/version-maps.js.map +1 -0
  457. package/dist/engines/tigerbeetle/backup.js +36 -0
  458. package/dist/engines/tigerbeetle/backup.js.map +1 -0
  459. package/dist/engines/tigerbeetle/binary-manager.js +72 -0
  460. package/dist/engines/tigerbeetle/binary-manager.js.map +1 -0
  461. package/dist/engines/tigerbeetle/binary-urls.js +49 -0
  462. package/dist/engines/tigerbeetle/binary-urls.js.map +1 -0
  463. package/dist/engines/tigerbeetle/hostdb-releases.js +21 -0
  464. package/dist/engines/tigerbeetle/hostdb-releases.js.map +1 -0
  465. package/dist/engines/tigerbeetle/index.js +559 -0
  466. package/dist/engines/tigerbeetle/index.js.map +1 -0
  467. package/dist/engines/tigerbeetle/restore.js +91 -0
  468. package/dist/engines/tigerbeetle/restore.js.map +1 -0
  469. package/{engines/tigerbeetle/version-maps.ts → dist/engines/tigerbeetle/version-maps.js} +22 -31
  470. package/dist/engines/tigerbeetle/version-maps.js.map +1 -0
  471. package/dist/engines/tigerbeetle/version-validator.js +108 -0
  472. package/dist/engines/tigerbeetle/version-validator.js.map +1 -0
  473. package/dist/engines/typedb/backup.js +129 -0
  474. package/dist/engines/typedb/backup.js.map +1 -0
  475. package/dist/engines/typedb/binary-manager.js +151 -0
  476. package/dist/engines/typedb/binary-manager.js.map +1 -0
  477. package/dist/engines/typedb/binary-urls.js +33 -0
  478. package/dist/engines/typedb/binary-urls.js.map +1 -0
  479. package/dist/engines/typedb/cli-utils.js +163 -0
  480. package/dist/engines/typedb/cli-utils.js.map +1 -0
  481. package/dist/engines/typedb/hostdb-releases.js +21 -0
  482. package/dist/engines/typedb/hostdb-releases.js.map +1 -0
  483. package/dist/engines/typedb/index.js +1003 -0
  484. package/dist/engines/typedb/index.js.map +1 -0
  485. package/dist/engines/typedb/restore.js +279 -0
  486. package/dist/engines/typedb/restore.js.map +1 -0
  487. package/dist/engines/typedb/version-maps.js +40 -0
  488. package/dist/engines/typedb/version-maps.js.map +1 -0
  489. package/dist/engines/typedb/version-validator.js +103 -0
  490. package/dist/engines/typedb/version-validator.js.map +1 -0
  491. package/dist/engines/valkey/backup.js +292 -0
  492. package/dist/engines/valkey/backup.js.map +1 -0
  493. package/dist/engines/valkey/binary-manager.js +33 -0
  494. package/dist/engines/valkey/binary-manager.js.map +1 -0
  495. package/dist/engines/valkey/binary-urls.js +98 -0
  496. package/dist/engines/valkey/binary-urls.js.map +1 -0
  497. package/dist/engines/valkey/cli-utils.js +38 -0
  498. package/dist/engines/valkey/cli-utils.js.map +1 -0
  499. package/dist/engines/valkey/hostdb-releases.js +21 -0
  500. package/dist/engines/valkey/hostdb-releases.js.map +1 -0
  501. package/dist/engines/valkey/index.js +1257 -0
  502. package/dist/engines/valkey/index.js.map +1 -0
  503. package/dist/engines/valkey/restore.js +340 -0
  504. package/dist/engines/valkey/restore.js.map +1 -0
  505. package/dist/engines/valkey/version-maps.js +70 -0
  506. package/dist/engines/valkey/version-maps.js.map +1 -0
  507. package/dist/engines/valkey/version-validator.js +112 -0
  508. package/dist/engines/valkey/version-validator.js.map +1 -0
  509. package/dist/engines/weaviate/api-client.js +50 -0
  510. package/dist/engines/weaviate/api-client.js.map +1 -0
  511. package/dist/engines/weaviate/backup.js +95 -0
  512. package/dist/engines/weaviate/backup.js.map +1 -0
  513. package/dist/engines/weaviate/binary-manager.js +58 -0
  514. package/dist/engines/weaviate/binary-manager.js.map +1 -0
  515. package/dist/engines/weaviate/binary-urls.js +92 -0
  516. package/dist/engines/weaviate/binary-urls.js.map +1 -0
  517. package/dist/engines/weaviate/cli-utils.js +39 -0
  518. package/dist/engines/weaviate/cli-utils.js.map +1 -0
  519. package/dist/engines/weaviate/hostdb-releases.js +21 -0
  520. package/dist/engines/weaviate/hostdb-releases.js.map +1 -0
  521. package/dist/engines/weaviate/index.js +871 -0
  522. package/dist/engines/weaviate/index.js.map +1 -0
  523. package/dist/engines/weaviate/restore.js +185 -0
  524. package/dist/engines/weaviate/restore.js.map +1 -0
  525. package/dist/engines/weaviate/version-maps.js +67 -0
  526. package/dist/engines/weaviate/version-maps.js.map +1 -0
  527. package/dist/engines/weaviate/version-validator.js +109 -0
  528. package/dist/engines/weaviate/version-validator.js.map +1 -0
  529. package/dist/types/index.js +102 -0
  530. package/dist/types/index.js.map +1 -0
  531. package/package.json +12 -9
  532. package/bin/cli.js +0 -68
  533. package/cli/bin.ts +0 -10
  534. package/cli/commands/attach.ts +0 -139
  535. package/cli/commands/backup.ts +0 -290
  536. package/cli/commands/backups.ts +0 -247
  537. package/cli/commands/clone.ts +0 -159
  538. package/cli/commands/config.ts +0 -367
  539. package/cli/commands/connect.ts +0 -684
  540. package/cli/commands/create.ts +0 -1201
  541. package/cli/commands/databases.ts +0 -630
  542. package/cli/commands/delete.ts +0 -133
  543. package/cli/commands/deps.ts +0 -342
  544. package/cli/commands/detach.ts +0 -107
  545. package/cli/commands/doctor.ts +0 -689
  546. package/cli/commands/duckdb.ts +0 -273
  547. package/cli/commands/edit.ts +0 -683
  548. package/cli/commands/engines.ts +0 -1914
  549. package/cli/commands/export.ts +0 -544
  550. package/cli/commands/info.ts +0 -340
  551. package/cli/commands/list.ts +0 -284
  552. package/cli/commands/logs.ts +0 -102
  553. package/cli/commands/menu/backup-handlers.ts +0 -1571
  554. package/cli/commands/menu/container-handlers.ts +0 -2288
  555. package/cli/commands/menu/engine-handlers.ts +0 -355
  556. package/cli/commands/menu/index.ts +0 -342
  557. package/cli/commands/menu/settings-handlers.ts +0 -365
  558. package/cli/commands/menu/shared.ts +0 -23
  559. package/cli/commands/menu/shell-handlers.ts +0 -1811
  560. package/cli/commands/menu/sql-handlers.ts +0 -231
  561. package/cli/commands/menu/update-handlers.ts +0 -378
  562. package/cli/commands/menu/validators.ts +0 -8
  563. package/cli/commands/ports.ts +0 -211
  564. package/cli/commands/pull.ts +0 -223
  565. package/cli/commands/query.ts +0 -241
  566. package/cli/commands/restore.ts +0 -587
  567. package/cli/commands/run.ts +0 -178
  568. package/cli/commands/self-update.ts +0 -121
  569. package/cli/commands/sqlite.ts +0 -273
  570. package/cli/commands/start.ts +0 -218
  571. package/cli/commands/stop.ts +0 -241
  572. package/cli/commands/url.ts +0 -104
  573. package/cli/commands/users.ts +0 -264
  574. package/cli/commands/version.ts +0 -55
  575. package/cli/commands/which.ts +0 -290
  576. package/cli/constants.ts +0 -233
  577. package/cli/helpers.ts +0 -1593
  578. package/cli/index.ts +0 -162
  579. package/cli/ui/prompts.ts +0 -1525
  580. package/cli/ui/spinner.ts +0 -88
  581. package/cli/ui/theme.ts +0 -128
  582. package/cli/utils/file-follower.ts +0 -93
  583. package/config/backup-formats.ts +0 -446
  584. package/config/defaults.ts +0 -56
  585. package/config/engine-defaults.ts +0 -336
  586. package/config/engines-registry.ts +0 -150
  587. package/config/engines.schema.json +0 -135
  588. package/config/os-dependencies.ts +0 -888
  589. package/config/paths.ts +0 -200
  590. package/core/backup-restore.ts +0 -330
  591. package/core/base-binary-manager.ts +0 -562
  592. package/core/base-document-binary-manager.ts +0 -523
  593. package/core/base-embedded-binary-manager.ts +0 -547
  594. package/core/base-server-binary-manager.ts +0 -523
  595. package/core/config-manager.ts +0 -652
  596. package/core/container-manager.ts +0 -787
  597. package/core/credential-generator.ts +0 -93
  598. package/core/credential-manager.ts +0 -259
  599. package/core/dblab-utils.ts +0 -113
  600. package/core/dependency-manager.ts +0 -512
  601. package/core/docker-exporter.ts +0 -1345
  602. package/core/error-handler.ts +0 -419
  603. package/core/fs-error-utils.ts +0 -82
  604. package/core/homebrew-version-manager.ts +0 -352
  605. package/core/hostdb-client.ts +0 -344
  606. package/core/hostdb-metadata.ts +0 -350
  607. package/core/hostdb-releases-factory.ts +0 -237
  608. package/core/library-env.ts +0 -118
  609. package/core/pgweb-utils.ts +0 -62
  610. package/core/platform-service.ts +0 -829
  611. package/core/port-manager.ts +0 -165
  612. package/core/process-manager.ts +0 -576
  613. package/core/pull-manager.ts +0 -511
  614. package/core/query-parser.ts +0 -514
  615. package/core/spawn-utils.ts +0 -122
  616. package/core/start-with-retry.ts +0 -130
  617. package/core/test-cleanup.ts +0 -108
  618. package/core/tls-generator.ts +0 -116
  619. package/core/transaction-manager.ts +0 -158
  620. package/core/update-manager.ts +0 -308
  621. package/core/version-migration.ts +0 -346
  622. package/core/version-utils.ts +0 -104
  623. package/engines/base-engine.ts +0 -340
  624. package/engines/clickhouse/README.md +0 -231
  625. package/engines/clickhouse/backup.ts +0 -398
  626. package/engines/clickhouse/binary-manager.ts +0 -201
  627. package/engines/clickhouse/binary-urls.ts +0 -125
  628. package/engines/clickhouse/cli-utils.ts +0 -176
  629. package/engines/clickhouse/hostdb-releases.ts +0 -30
  630. package/engines/clickhouse/index.ts +0 -1345
  631. package/engines/clickhouse/restore.ts +0 -466
  632. package/engines/clickhouse/version-maps.ts +0 -95
  633. package/engines/clickhouse/version-validator.ts +0 -154
  634. package/engines/cockroachdb/README.md +0 -170
  635. package/engines/cockroachdb/backup.ts +0 -376
  636. package/engines/cockroachdb/binary-manager.ts +0 -45
  637. package/engines/cockroachdb/binary-urls.ts +0 -40
  638. package/engines/cockroachdb/cli-utils.ts +0 -384
  639. package/engines/cockroachdb/hostdb-releases.ts +0 -26
  640. package/engines/cockroachdb/index.ts +0 -1276
  641. package/engines/cockroachdb/restore.ts +0 -455
  642. package/engines/cockroachdb/version-maps.ts +0 -42
  643. package/engines/couchdb/README.md +0 -257
  644. package/engines/couchdb/api-client.ts +0 -81
  645. package/engines/couchdb/backup.ts +0 -137
  646. package/engines/couchdb/binary-manager.ts +0 -86
  647. package/engines/couchdb/binary-urls.ts +0 -115
  648. package/engines/couchdb/hostdb-releases.ts +0 -23
  649. package/engines/couchdb/index.ts +0 -1429
  650. package/engines/couchdb/restore.ts +0 -290
  651. package/engines/couchdb/version-maps.ts +0 -78
  652. package/engines/couchdb/version-validator.ts +0 -111
  653. package/engines/duckdb/README.md +0 -154
  654. package/engines/duckdb/binary-manager.ts +0 -45
  655. package/engines/duckdb/hostdb-releases.ts +0 -23
  656. package/engines/duckdb/index.ts +0 -749
  657. package/engines/duckdb/registry.ts +0 -303
  658. package/engines/duckdb/scanner.ts +0 -22
  659. package/engines/duckdb/version-maps.ts +0 -78
  660. package/engines/duckdb/version-validator.ts +0 -78
  661. package/engines/ferretdb/README.md +0 -262
  662. package/engines/ferretdb/backup.ts +0 -173
  663. package/engines/ferretdb/binary-manager.ts +0 -1095
  664. package/engines/ferretdb/binary-urls.ts +0 -183
  665. package/engines/ferretdb/index.ts +0 -1907
  666. package/engines/ferretdb/restore.ts +0 -357
  667. package/engines/file-based-utils.ts +0 -262
  668. package/engines/index.ts +0 -131
  669. package/engines/influxdb/README.md +0 -180
  670. package/engines/influxdb/api-client.ts +0 -64
  671. package/engines/influxdb/backup.ts +0 -160
  672. package/engines/influxdb/binary-manager.ts +0 -110
  673. package/engines/influxdb/binary-urls.ts +0 -69
  674. package/engines/influxdb/hostdb-releases.ts +0 -23
  675. package/engines/influxdb/index.ts +0 -1272
  676. package/engines/influxdb/restore.ts +0 -417
  677. package/engines/influxdb/version-maps.ts +0 -75
  678. package/engines/influxdb/version-validator.ts +0 -128
  679. package/engines/mariadb/README.md +0 -141
  680. package/engines/mariadb/backup.ts +0 -233
  681. package/engines/mariadb/binary-manager.ts +0 -45
  682. package/engines/mariadb/hostdb-releases.ts +0 -23
  683. package/engines/mariadb/index.ts +0 -1300
  684. package/engines/mariadb/restore.ts +0 -447
  685. package/engines/mariadb/version-maps.ts +0 -72
  686. package/engines/mariadb/version-validator.ts +0 -181
  687. package/engines/meilisearch/README.md +0 -255
  688. package/engines/meilisearch/api-client.ts +0 -61
  689. package/engines/meilisearch/backup.ts +0 -233
  690. package/engines/meilisearch/binary-manager.ts +0 -43
  691. package/engines/meilisearch/binary-urls.ts +0 -69
  692. package/engines/meilisearch/hostdb-releases.ts +0 -26
  693. package/engines/meilisearch/index.ts +0 -1292
  694. package/engines/meilisearch/restore.ts +0 -219
  695. package/engines/meilisearch/version-maps.ts +0 -78
  696. package/engines/meilisearch/version-validator.ts +0 -128
  697. package/engines/mongodb/README.md +0 -162
  698. package/engines/mongodb/backup.ts +0 -127
  699. package/engines/mongodb/binary-manager.ts +0 -48
  700. package/engines/mongodb/binary-urls.ts +0 -63
  701. package/engines/mongodb/cli-utils.ts +0 -171
  702. package/engines/mongodb/hostdb-releases.ts +0 -91
  703. package/engines/mongodb/index.ts +0 -1118
  704. package/engines/mongodb/restore.ts +0 -361
  705. package/engines/mongodb/version-maps.ts +0 -91
  706. package/engines/mongodb/version-validator.ts +0 -160
  707. package/engines/mysql/README.md +0 -142
  708. package/engines/mysql/backup.ts +0 -270
  709. package/engines/mysql/binary-detection.ts +0 -408
  710. package/engines/mysql/binary-manager.ts +0 -42
  711. package/engines/mysql/binary-urls.ts +0 -104
  712. package/engines/mysql/index.ts +0 -1361
  713. package/engines/mysql/restore.ts +0 -500
  714. package/engines/mysql/version-maps.ts +0 -91
  715. package/engines/mysql/version-validator.ts +0 -369
  716. package/engines/postgresql/README.md +0 -158
  717. package/engines/postgresql/backup.ts +0 -151
  718. package/engines/postgresql/binary-manager.ts +0 -114
  719. package/engines/postgresql/binary-urls.ts +0 -99
  720. package/engines/postgresql/hostdb-releases.ts +0 -26
  721. package/engines/postgresql/index.ts +0 -1143
  722. package/engines/postgresql/remote-version.ts +0 -161
  723. package/engines/postgresql/restore.ts +0 -342
  724. package/engines/postgresql/version-maps.ts +0 -83
  725. package/engines/postgresql/version-validator.ts +0 -413
  726. package/engines/qdrant/README.md +0 -222
  727. package/engines/qdrant/api-client.ts +0 -61
  728. package/engines/qdrant/backup.ts +0 -165
  729. package/engines/qdrant/binary-manager.ts +0 -43
  730. package/engines/qdrant/binary-urls.ts +0 -115
  731. package/engines/qdrant/cli-utils.ts +0 -43
  732. package/engines/qdrant/hostdb-releases.ts +0 -23
  733. package/engines/qdrant/index.ts +0 -1312
  734. package/engines/qdrant/restore.ts +0 -203
  735. package/engines/qdrant/version-maps.ts +0 -78
  736. package/engines/qdrant/version-validator.ts +0 -128
  737. package/engines/questdb/README.md +0 -334
  738. package/engines/questdb/backup.ts +0 -220
  739. package/engines/questdb/binary-manager.ts +0 -310
  740. package/engines/questdb/binary-urls.ts +0 -34
  741. package/engines/questdb/hostdb-releases.ts +0 -23
  742. package/engines/questdb/index.ts +0 -1023
  743. package/engines/questdb/restore.ts +0 -260
  744. package/engines/questdb/version-maps.ts +0 -37
  745. package/engines/questdb/version-validator.ts +0 -121
  746. package/engines/redis/README.md +0 -173
  747. package/engines/redis/backup.ts +0 -389
  748. package/engines/redis/binary-manager.ts +0 -44
  749. package/engines/redis/binary-urls.ts +0 -117
  750. package/engines/redis/cli-utils.ts +0 -42
  751. package/engines/redis/hostdb-releases.ts +0 -23
  752. package/engines/redis/index.ts +0 -1583
  753. package/engines/redis/restore.ts +0 -443
  754. package/engines/redis/version-maps.ts +0 -81
  755. package/engines/redis/version-validator.ts +0 -131
  756. package/engines/sqlite/README.md +0 -162
  757. package/engines/sqlite/binary-manager.ts +0 -52
  758. package/engines/sqlite/hostdb-releases.ts +0 -23
  759. package/engines/sqlite/index.ts +0 -641
  760. package/engines/sqlite/registry.ts +0 -198
  761. package/engines/sqlite/scanner.ts +0 -22
  762. package/engines/sqlite/version-maps.ts +0 -64
  763. package/engines/surrealdb/README.md +0 -218
  764. package/engines/surrealdb/backup.ts +0 -131
  765. package/engines/surrealdb/binary-manager.ts +0 -45
  766. package/engines/surrealdb/binary-urls.ts +0 -40
  767. package/engines/surrealdb/cli-utils.ts +0 -173
  768. package/engines/surrealdb/hostdb-releases.ts +0 -23
  769. package/engines/surrealdb/index.ts +0 -1246
  770. package/engines/surrealdb/restore.ts +0 -302
  771. package/engines/surrealdb/version-maps.ts +0 -41
  772. package/engines/tigerbeetle/README.md +0 -61
  773. package/engines/tigerbeetle/backup.ts +0 -49
  774. package/engines/tigerbeetle/binary-manager.ts +0 -95
  775. package/engines/tigerbeetle/binary-urls.ts +0 -62
  776. package/engines/tigerbeetle/hostdb-releases.ts +0 -26
  777. package/engines/tigerbeetle/index.ts +0 -746
  778. package/engines/tigerbeetle/restore.ts +0 -130
  779. package/engines/tigerbeetle/version-validator.ts +0 -126
  780. package/engines/typedb/backup.ts +0 -167
  781. package/engines/typedb/binary-manager.ts +0 -200
  782. package/engines/typedb/binary-urls.ts +0 -40
  783. package/engines/typedb/cli-utils.ts +0 -210
  784. package/engines/typedb/hostdb-releases.ts +0 -23
  785. package/engines/typedb/index.ts +0 -1275
  786. package/engines/typedb/restore.ts +0 -377
  787. package/engines/typedb/version-maps.ts +0 -48
  788. package/engines/typedb/version-validator.ts +0 -127
  789. package/engines/valkey/README.md +0 -219
  790. package/engines/valkey/backup.ts +0 -389
  791. package/engines/valkey/binary-manager.ts +0 -45
  792. package/engines/valkey/binary-urls.ts +0 -122
  793. package/engines/valkey/cli-utils.ts +0 -42
  794. package/engines/valkey/hostdb-releases.ts +0 -23
  795. package/engines/valkey/index.ts +0 -1585
  796. package/engines/valkey/restore.ts +0 -446
  797. package/engines/valkey/version-maps.ts +0 -81
  798. package/engines/valkey/version-validator.ts +0 -131
  799. package/engines/weaviate/README.md +0 -302
  800. package/engines/weaviate/api-client.ts +0 -61
  801. package/engines/weaviate/backup.ts +0 -145
  802. package/engines/weaviate/binary-manager.ts +0 -80
  803. package/engines/weaviate/binary-urls.ts +0 -115
  804. package/engines/weaviate/cli-utils.ts +0 -43
  805. package/engines/weaviate/hostdb-releases.ts +0 -23
  806. package/engines/weaviate/index.ts +0 -1139
  807. package/engines/weaviate/restore.ts +0 -235
  808. package/engines/weaviate/version-maps.ts +0 -78
  809. package/engines/weaviate/version-validator.ts +0 -128
  810. package/types/index.ts +0 -624
  811. /package/{config → dist/config}/engines.json +0 -0
@@ -1,1571 +0,0 @@
1
- import chalk from 'chalk'
2
- import inquirer from 'inquirer'
3
- import { existsSync } from 'fs'
4
- import { rm, mkdir } from 'fs/promises'
5
- import { join } from 'path'
6
- import { tmpdir } from 'os'
7
- import { containerManager } from '../../../core/container-manager'
8
- import { getMissingDependencies } from '../../../core/dependency-manager'
9
- import { platformService } from '../../../core/platform-service'
10
- import { portManager } from '../../../core/port-manager'
11
- import { getEngine } from '../../../engines'
12
- import { defaults } from '../../../config/defaults'
13
- import {
14
- getBackupExtension,
15
- getBackupSpinnerLabel,
16
- getDefaultFormat,
17
- } from '../../../config/backup-formats'
18
- import {
19
- generateBackupTimestamp,
20
- estimateBackupSize,
21
- checkBackupSize,
22
- } from '../../../core/backup-restore'
23
- import {
24
- promptCreateOptions,
25
- promptContainerName,
26
- promptContainerSelect,
27
- promptDatabaseName,
28
- promptDatabaseSelect,
29
- promptBackupFormat,
30
- promptBackupFilename,
31
- promptBackupDirectory,
32
- promptInstallDependencies,
33
- promptConfirm,
34
- escapeablePrompt,
35
- filterableListPrompt,
36
- type FilterableChoice,
37
- BACK_VALUE,
38
- MAIN_MENU_VALUE,
39
- ESCAPE_VALUE,
40
- } from '../../ui/prompts'
41
- import { createSpinner } from '../../ui/spinner'
42
- import {
43
- header,
44
- uiSuccess,
45
- uiError,
46
- uiWarning,
47
- connectionBox,
48
- formatBytes,
49
- } from '../../ui/theme'
50
- import { getEngineIcon, getPageSize } from '../../constants'
51
- import { Engine, assertExhaustive } from '../../../types'
52
- import { pressEnterToContinue } from './shared'
53
- import { SpinDBError, ErrorCodes } from '../../../core/error-handler'
54
- import { validateTypedbConnectionString } from './validators'
55
-
56
- // Strip surrounding quotes from paths (handles drag-and-drop paths)
57
- function stripQuotes(path: string): string {
58
- return path.replace(/^['"]|['"]$/g, '').trim()
59
- }
60
-
61
- /**
62
- * Mask the password portion of a connection string for display.
63
- * Example: postgresql://user:secretpass@host:5432/db → postgresql://user:****@host:5432/db
64
- * Handles passwords containing '@' characters by using URL parsing.
65
- */
66
- function maskConnectionStringPassword(connectionString: string): string {
67
- if (!connectionString) return connectionString
68
- try {
69
- // Use URL constructor for robust parsing (handles @ in passwords)
70
- const url = new URL(connectionString)
71
- if (url.password) {
72
- url.password = '****'
73
- return url.toString()
74
- }
75
- return connectionString
76
- } catch {
77
- // Fallback for malformed URLs - use greedy regex that captures everything up to last @
78
- try {
79
- return connectionString.replace(
80
- /^([a-z+]+:\/\/[^:]*:)(.+)(@[^@]+)$/i,
81
- (_, prefix, _password, suffix) => `${prefix}****${suffix}`,
82
- )
83
- } catch {
84
- return connectionString
85
- }
86
- }
87
- }
88
-
89
- /**
90
- * Validate a connection string for the given engine.
91
- * Returns true if valid, or an error message string if invalid.
92
- *
93
- * Empty input is intentionally allowed (returns true) to support the
94
- * "press Enter to go back" UX pattern. Callers must check for empty
95
- * input after the prompt returns (e.g., `if (!connectionString.trim()) return`).
96
- */
97
- function validateConnectionString(
98
- input: string,
99
- engine: Engine,
100
- ): true | string {
101
- // Allow empty input for "press Enter to go back" UX - callers handle this case
102
- if (!input) return true
103
-
104
- switch (engine) {
105
- case Engine.PostgreSQL:
106
- if (
107
- !input.startsWith('postgresql://') &&
108
- !input.startsWith('postgres://')
109
- ) {
110
- return 'Connection string must start with postgresql:// or postgres://'
111
- }
112
- break
113
- case Engine.MySQL:
114
- if (!input.startsWith('mysql://')) {
115
- return 'Connection string must start with mysql://'
116
- }
117
- break
118
- case Engine.MariaDB:
119
- if (!input.startsWith('mysql://') && !input.startsWith('mariadb://')) {
120
- return 'Connection string must start with mysql:// or mariadb://'
121
- }
122
- break
123
- case Engine.MongoDB:
124
- case Engine.FerretDB:
125
- if (
126
- !input.startsWith('mongodb://') &&
127
- !input.startsWith('mongodb+srv://')
128
- ) {
129
- return 'Connection string must start with mongodb:// or mongodb+srv://'
130
- }
131
- break
132
- case Engine.Redis:
133
- if (!input.startsWith('redis://') && !input.startsWith('rediss://')) {
134
- return 'Connection string must start with redis:// or rediss://'
135
- }
136
- break
137
- case Engine.Valkey:
138
- if (
139
- !input.startsWith('redis://') &&
140
- !input.startsWith('rediss://') &&
141
- !input.startsWith('valkey://') &&
142
- !input.startsWith('valkeys://')
143
- ) {
144
- return 'Connection string must start with redis://, rediss://, valkey://, or valkeys://'
145
- }
146
- break
147
- case Engine.ClickHouse:
148
- if (
149
- !input.startsWith('clickhouse://') &&
150
- !input.startsWith('http://') &&
151
- !input.startsWith('https://')
152
- ) {
153
- return 'Connection string must start with clickhouse://, http://, or https://'
154
- }
155
- break
156
- case Engine.Qdrant:
157
- if (
158
- !input.startsWith('qdrant://') &&
159
- !input.startsWith('http://') &&
160
- !input.startsWith('https://')
161
- ) {
162
- return 'Connection string must start with qdrant://, http://, or https://'
163
- }
164
- break
165
- case Engine.Meilisearch:
166
- if (
167
- !input.startsWith('meilisearch://') &&
168
- !input.startsWith('http://') &&
169
- !input.startsWith('https://')
170
- ) {
171
- return 'Connection string must start with meilisearch://, http://, or https://'
172
- }
173
- break
174
- case Engine.CouchDB:
175
- if (
176
- !input.startsWith('couchdb://') &&
177
- !input.startsWith('http://') &&
178
- !input.startsWith('https://')
179
- ) {
180
- return 'Connection string must start with couchdb://, http://, or https://'
181
- }
182
- break
183
- case Engine.CockroachDB:
184
- if (
185
- !input.startsWith('postgresql://') &&
186
- !input.startsWith('postgres://')
187
- ) {
188
- return 'Connection string must start with postgresql:// or postgres://'
189
- }
190
- break
191
- case Engine.SurrealDB:
192
- if (
193
- !input.startsWith('surrealdb://') &&
194
- !input.startsWith('ws://') &&
195
- !input.startsWith('wss://') &&
196
- !input.startsWith('http://') &&
197
- !input.startsWith('https://')
198
- ) {
199
- return 'Connection string must start with surrealdb://, ws://, wss://, http://, or https://'
200
- }
201
- break
202
- case Engine.QuestDB:
203
- // QuestDB uses PostgreSQL wire protocol
204
- if (
205
- !input.startsWith('postgresql://') &&
206
- !input.startsWith('postgres://')
207
- ) {
208
- return 'Connection string must start with postgresql:// or postgres://'
209
- }
210
- break
211
- case Engine.TypeDB:
212
- {
213
- const typedbError = validateTypedbConnectionString(input)
214
- if (typedbError) return typedbError
215
- }
216
- break
217
- case Engine.InfluxDB:
218
- if (
219
- !input.startsWith('influxdb://') &&
220
- !input.startsWith('http://') &&
221
- !input.startsWith('https://')
222
- ) {
223
- return 'Connection string must start with influxdb://, http://, or https://'
224
- }
225
- break
226
- case Engine.Weaviate:
227
- if (!input.startsWith('http://') && !input.startsWith('https://')) {
228
- return 'Connection string must start with http:// or https://'
229
- }
230
- break
231
- case Engine.TigerBeetle:
232
- return 'TigerBeetle does not support remote dumps (custom binary protocol)'
233
- case Engine.SQLite:
234
- case Engine.DuckDB:
235
- return 'File-based engines do not support remote connection strings'
236
- default:
237
- assertExhaustive(engine)
238
- }
239
- return true
240
- }
241
-
242
- /**
243
- * Prompt for a connection string with validation and password masking.
244
- * Shows a hint about pressing Enter to go back and Escape for main menu.
245
- *
246
- * @param engine - The database engine for connection string validation
247
- * @returns The connection string, or null if empty/escaped
248
- */
249
- async function promptConnectionString(engine: Engine): Promise<string | null> {
250
- console.log(
251
- chalk.gray(
252
- ' Enter connection string, or press Enter to go back (esc - main menu)',
253
- ),
254
- )
255
- const { connectionString } = await escapeablePrompt<{
256
- connectionString: string
257
- }>([
258
- {
259
- type: 'input',
260
- name: 'connectionString',
261
- message: 'Connection string:',
262
- transformer: (input: string) =>
263
- maskConnectionStringPassword(input.trim()),
264
- validate: (input: string) =>
265
- validateConnectionString(input.trim(), engine),
266
- },
267
- ])
268
-
269
- const trimmed = connectionString.trim()
270
- return trimmed || null
271
- }
272
-
273
- export async function handleCreateForRestore(): Promise<{
274
- name: string
275
- config: NonNullable<Awaited<ReturnType<typeof containerManager.getConfig>>>
276
- } | null> {
277
- console.log()
278
- const answers = await promptCreateOptions()
279
- let { name: containerName } = answers
280
- const { engine, version, port, database } = answers
281
-
282
- console.log()
283
- console.log(header('Creating Database Container'))
284
- console.log()
285
-
286
- const dbEngine = getEngine(engine)
287
-
288
- const portAvailable = await portManager.isPortAvailable(port)
289
- if (!portAvailable) {
290
- console.log(
291
- uiError(`Port ${port} is in use. Please choose a different port.`),
292
- )
293
- return null
294
- }
295
-
296
- const binarySpinner = createSpinner(
297
- `Checking ${dbEngine.displayName} ${version} binaries...`,
298
- )
299
- binarySpinner.start()
300
-
301
- const isInstalled = await dbEngine.isBinaryInstalled(version)
302
- if (isInstalled) {
303
- binarySpinner.succeed(
304
- `${dbEngine.displayName} ${version} binaries ready (cached)`,
305
- )
306
- } else {
307
- binarySpinner.text = `Downloading ${dbEngine.displayName} ${version} binaries...`
308
- await dbEngine.ensureBinaries(version, ({ message }) => {
309
- binarySpinner.text = message
310
- })
311
- binarySpinner.succeed(
312
- `${dbEngine.displayName} ${version} binaries downloaded`,
313
- )
314
- }
315
-
316
- while (await containerManager.exists(containerName)) {
317
- console.log(chalk.yellow(` Container "${containerName}" already exists.`))
318
- containerName = await promptContainerName()
319
- }
320
-
321
- const createSpinnerInstance = createSpinner('Creating container...')
322
- createSpinnerInstance.start()
323
-
324
- await containerManager.create(containerName, {
325
- engine: dbEngine.name as Engine,
326
- version,
327
- port,
328
- database,
329
- })
330
-
331
- createSpinnerInstance.succeed('Container created')
332
-
333
- const initSpinner = createSpinner('Initializing database cluster...')
334
- initSpinner.start()
335
-
336
- await dbEngine.initDataDir(containerName, version, {
337
- superuser: defaults.superuser,
338
- })
339
-
340
- initSpinner.succeed('Database cluster initialized')
341
-
342
- const startSpinner = createSpinner(`Starting ${dbEngine.displayName}...`)
343
- startSpinner.start()
344
-
345
- const config = await containerManager.getConfig(containerName)
346
- if (!config) {
347
- startSpinner.fail('Failed to get container config')
348
- return null
349
- }
350
-
351
- await dbEngine.start(config)
352
- await containerManager.updateConfig(containerName, { status: 'running' })
353
-
354
- startSpinner.succeed(`${dbEngine.displayName} started`)
355
-
356
- if (database !== 'postgres') {
357
- const dbSpinner = createSpinner(`Creating database "${database}"...`)
358
- dbSpinner.start()
359
-
360
- await dbEngine.createDatabase(config, database)
361
-
362
- dbSpinner.succeed(`Database "${database}" created`)
363
- }
364
-
365
- console.log()
366
- console.log(uiSuccess('Container ready for restore'))
367
- console.log()
368
-
369
- return { name: containerName, config }
370
- }
371
-
372
- export async function handleRestore(): Promise<void> {
373
- // Use a loop instead of recursion for "back" navigation
374
- while (true) {
375
- const containers = await containerManager.list()
376
- const running = containers.filter((c) => c.status === 'running')
377
-
378
- // Build filterable container choices
379
- const containerChoices: FilterableChoice[] = running.map((c) => ({
380
- name: `${c.name} ${chalk.gray(`(${getEngineIcon(c.engine)}${c.engine} ${c.version}, port ${c.port})`)} ${chalk.green('● running')}`,
381
- value: c.name,
382
- short: c.name,
383
- }))
384
-
385
- // Build footer with action and navigation options
386
- const footerChoices: (FilterableChoice | inquirer.Separator)[] = [
387
- new inquirer.Separator(),
388
- {
389
- name: `${chalk.green('➕')} Create new container`,
390
- value: '__create_new__',
391
- short: 'Create new',
392
- },
393
- new inquirer.Separator(),
394
- { name: `${chalk.blue('←')} Back`, value: BACK_VALUE },
395
- {
396
- name: `${chalk.blue('⌂')} Back to main menu ${chalk.gray('(esc)')}`,
397
- value: MAIN_MENU_VALUE,
398
- },
399
- new inquirer.Separator(),
400
- ]
401
-
402
- const allChoices = [...containerChoices, ...footerChoices]
403
-
404
- const selectedContainer = await filterableListPrompt(
405
- allChoices,
406
- 'Select container to restore to:',
407
- {
408
- filterableCount: containerChoices.length,
409
- pageSize: getPageSize(),
410
- emptyText: 'No containers match filter',
411
- },
412
- )
413
-
414
- // Handle navigation (including escape)
415
- if (
416
- selectedContainer === ESCAPE_VALUE ||
417
- selectedContainer === BACK_VALUE ||
418
- selectedContainer === MAIN_MENU_VALUE
419
- ) {
420
- return
421
- }
422
-
423
- let containerName: string
424
- let config: Awaited<ReturnType<typeof containerManager.getConfig>>
425
-
426
- if (selectedContainer === '__create_new__') {
427
- const createResult = await handleCreateForRestore()
428
- if (!createResult) return
429
- containerName = createResult.name
430
- config = createResult.config
431
- } else {
432
- containerName = selectedContainer
433
- config = await containerManager.getConfig(containerName)
434
- if (!config) {
435
- console.error(uiError(`Container "${containerName}" not found`))
436
- return
437
- }
438
- }
439
-
440
- const depsSpinner = createSpinner('Checking required tools...')
441
- depsSpinner.start()
442
-
443
- let missingDeps = await getMissingDependencies(config.engine)
444
- if (missingDeps.length > 0) {
445
- depsSpinner.warn(
446
- `Missing tools: ${missingDeps.map((d) => d.name).join(', ')}`,
447
- )
448
-
449
- const installed = await promptInstallDependencies(
450
- missingDeps[0].binary,
451
- config.engine,
452
- )
453
-
454
- if (!installed) {
455
- return
456
- }
457
-
458
- missingDeps = await getMissingDependencies(config.engine)
459
- if (missingDeps.length > 0) {
460
- console.log(
461
- uiError(
462
- `Still missing tools: ${missingDeps.map((d) => d.name).join(', ')}`,
463
- ),
464
- )
465
- return
466
- }
467
-
468
- console.log(chalk.green(' ✓ All required tools are now available'))
469
- console.log()
470
- } else {
471
- depsSpinner.succeed('Required tools available')
472
- }
473
-
474
- // All engines now support dumpFromConnectionString
475
- const restoreChoices: Array<
476
- { name: string; value: string } | inquirer.Separator
477
- > = [
478
- {
479
- name: `${chalk.magenta('☰')} Dump file (drag and drop or enter path)`,
480
- value: 'file',
481
- },
482
- ]
483
-
484
- restoreChoices.push({
485
- name: `${chalk.cyan('↗')} Connection string ${chalk.gray('(pull from remote database)')}`,
486
- value: 'connection',
487
- })
488
-
489
- restoreChoices.push(new inquirer.Separator(), {
490
- name: `${chalk.blue('←')} Back`,
491
- value: '__back__',
492
- })
493
-
494
- const { restoreSource } = await escapeablePrompt<{
495
- restoreSource: 'file' | 'connection' | '__back__'
496
- }>([
497
- {
498
- type: 'list',
499
- name: 'restoreSource',
500
- message: 'Restore from:',
501
- choices: restoreChoices,
502
- },
503
- ])
504
-
505
- if (restoreSource === '__back__') {
506
- continue // Go back to container selection
507
- }
508
-
509
- let backupPath = ''
510
- let isTempFile = false
511
-
512
- if (restoreSource === 'connection') {
513
- const connectionString = await promptConnectionString(config.engine)
514
- if (!connectionString) {
515
- continue // Return to container selection
516
- }
517
-
518
- const engine = getEngine(config.engine)
519
-
520
- const timestamp = Date.now()
521
- const defaultFormat = getDefaultFormat(config.engine as Engine)
522
- const dumpExtension = getBackupExtension(
523
- config.engine as Engine,
524
- defaultFormat,
525
- )
526
- const tempDumpPath = join(
527
- tmpdir(),
528
- `spindb-dump-${timestamp}${dumpExtension}`,
529
- )
530
-
531
- let dumpSuccess = false
532
- let attempts = 0
533
- const maxAttempts = 2
534
-
535
- while (!dumpSuccess && attempts < maxAttempts) {
536
- attempts++
537
- const dumpSpinner = createSpinner(
538
- 'Creating dump from remote database...',
539
- )
540
- dumpSpinner.start()
541
-
542
- try {
543
- const dumpResult = await engine.dumpFromConnectionString(
544
- connectionString,
545
- tempDumpPath,
546
- )
547
- dumpSpinner.succeed('Dump created from remote database')
548
- if (dumpResult.warnings?.length) {
549
- for (const warning of dumpResult.warnings) {
550
- console.log(chalk.yellow(` ${warning}`))
551
- }
552
- }
553
- backupPath = tempDumpPath
554
- isTempFile = true
555
- dumpSuccess = true
556
- } catch (error) {
557
- const e = error as Error
558
- dumpSpinner.fail('Failed to create dump')
559
-
560
- // Handle version mismatch errors with helpful message
561
- if (
562
- e instanceof SpinDBError &&
563
- e.code === ErrorCodes.VERSION_MISMATCH
564
- ) {
565
- console.log()
566
- console.log(uiError('PostgreSQL version mismatch:'))
567
- console.log(chalk.gray(` ${e.message}`))
568
- if (e.suggestion) {
569
- console.log()
570
- console.log(uiWarning('To fix this:'))
571
- console.log(chalk.yellow(` ${e.suggestion}`))
572
- }
573
- console.log()
574
-
575
- try {
576
- await rm(tempDumpPath, { force: true })
577
- } catch {
578
- // Ignore cleanup errors
579
- }
580
-
581
- await pressEnterToContinue()
582
- return
583
- }
584
-
585
- // Handle connection errors
586
- if (
587
- e instanceof SpinDBError &&
588
- e.code === ErrorCodes.CONNECTION_FAILED
589
- ) {
590
- console.log()
591
- console.log(uiError('Connection failed:'))
592
- console.log(chalk.gray(` ${e.message}`))
593
- if (e.suggestion) {
594
- console.log(chalk.yellow(` ${e.suggestion}`))
595
- }
596
- console.log()
597
-
598
- await pressEnterToContinue()
599
- return
600
- }
601
-
602
- // Handle missing tool errors
603
- if (
604
- e.message.includes('pg_dump not found') ||
605
- e.message.includes('mysqldump not found') ||
606
- e.message.includes('ENOENT')
607
- ) {
608
- const missingTool = e.message.includes('mysqldump')
609
- ? 'mysqldump'
610
- : 'pg_dump'
611
- const toolEngine =
612
- missingTool === 'mysqldump' ? 'mysql' : 'postgresql'
613
- const installed = await promptInstallDependencies(
614
- missingTool,
615
- toolEngine as Engine,
616
- )
617
- if (installed) {
618
- // Installation counts toward maxAttempts - retry with newly installed tools
619
- continue
620
- }
621
- } else {
622
- const dumpTool = config.engine === 'mysql' ? 'mysqldump' : 'pg_dump'
623
- console.log()
624
- console.log(uiError(`${dumpTool} error:`))
625
- console.log(chalk.gray(` ${e.message}`))
626
- console.log()
627
- }
628
-
629
- try {
630
- await rm(tempDumpPath, { force: true })
631
- } catch {
632
- // Ignore cleanup errors
633
- }
634
-
635
- await pressEnterToContinue()
636
- return
637
- }
638
- }
639
-
640
- if (!dumpSuccess) {
641
- console.log(uiError('Failed to create dump after retries'))
642
- return
643
- }
644
- } else {
645
- console.log(
646
- chalk.gray(
647
- ' Drag & drop, enter path (abs or rel), or press Enter to go back (esc - main menu)',
648
- ),
649
- )
650
- const { backupPath: rawBackupPath } = await escapeablePrompt<{
651
- backupPath: string
652
- }>([
653
- {
654
- type: 'input',
655
- name: 'backupPath',
656
- message: 'Backup file path:',
657
- validate: (input: string) => {
658
- if (!input) return true
659
- const cleanPath = stripQuotes(input)
660
- if (!existsSync(cleanPath)) return 'File not found'
661
- return true
662
- },
663
- },
664
- ])
665
-
666
- if (!rawBackupPath.trim()) {
667
- continue // Return to container selection
668
- }
669
-
670
- backupPath = stripQuotes(rawBackupPath)
671
- }
672
-
673
- const engine = getEngine(config.engine)
674
-
675
- // Get existing databases in this container
676
- const existingDatabases = config.databases || [config.database]
677
-
678
- // Redis uses numbered databases 0-15, so "create new" doesn't apply
679
- const isRedis = config.engine === 'redis'
680
-
681
- // Restore mode selection
682
- type RestoreMode = 'new' | 'replace' | '__back__'
683
- let restoreMode: RestoreMode
684
-
685
- if (isRedis) {
686
- // Redis: Always restore to existing database (0-15)
687
- restoreMode = 'replace'
688
- } else {
689
- const result = await escapeablePrompt<{ restoreMode: RestoreMode }>([
690
- {
691
- type: 'list',
692
- name: 'restoreMode',
693
- message: 'How would you like to restore?',
694
- choices: [
695
- {
696
- name: `${chalk.green('➕')} Create new database ${chalk.gray('(keeps existing databases intact)')}`,
697
- value: 'new',
698
- },
699
- {
700
- name: `${chalk.yellow('↻')} Replace existing database ${chalk.gray('(overwrites data)')}`,
701
- value: 'replace',
702
- disabled:
703
- existingDatabases.length === 0
704
- ? 'No existing databases'
705
- : false,
706
- },
707
- new inquirer.Separator(),
708
- {
709
- name: `${chalk.blue('←')} Back`,
710
- value: '__back__',
711
- },
712
- ],
713
- },
714
- ])
715
- restoreMode = result.restoreMode
716
- }
717
-
718
- if (restoreMode === '__back__') {
719
- continue // Return to container selection
720
- }
721
-
722
- let databaseName: string
723
-
724
- if (restoreMode === 'new') {
725
- // Show existing databases for context
726
- if (existingDatabases.length > 0) {
727
- console.log()
728
- console.log(chalk.gray(' Existing databases in this container:'))
729
- for (const db of existingDatabases) {
730
- console.log(chalk.gray(` • ${db}`))
731
- }
732
- console.log()
733
- }
734
-
735
- // Prompt for new database name (must not already exist)
736
- const result = await promptDatabaseName(containerName, config.engine, {
737
- allowBack: true,
738
- existingDatabases,
739
- disallowExisting: true,
740
- })
741
-
742
- if (result === null) {
743
- continue // Return to container selection
744
- }
745
- databaseName = result
746
- } else {
747
- // Replace existing database - show selection
748
- if (existingDatabases.length === 1) {
749
- databaseName = existingDatabases[0]
750
- } else {
751
- const result = await promptDatabaseSelect(
752
- existingDatabases,
753
- 'Select database to replace:',
754
- { includeBack: true },
755
- )
756
- if (result === null) {
757
- continue // Return to container selection
758
- }
759
- databaseName = result
760
- }
761
-
762
- // Confirm overwrite
763
- const confirmed = await promptConfirm(
764
- `This will overwrite all data in "${databaseName}". Continue?`,
765
- false,
766
- )
767
-
768
- if (!confirmed) {
769
- continue // Return to container selection
770
- }
771
-
772
- // Redis doesn't need drop/create - databases 0-15 always exist
773
- if (!isRedis) {
774
- // Drop the existing database before restore
775
- console.log()
776
- const dropSpinner = createSpinner(
777
- `Dropping existing database "${databaseName}"...`,
778
- )
779
- dropSpinner.start()
780
-
781
- try {
782
- await engine.dropDatabase(config, databaseName)
783
- dropSpinner.succeed(`Dropped database "${databaseName}"`)
784
- } catch (error) {
785
- dropSpinner.fail(`Failed to drop database "${databaseName}"`)
786
- console.log(uiError((error as Error).message))
787
- await pressEnterToContinue()
788
- return
789
- }
790
- }
791
- }
792
-
793
- const detectSpinner = createSpinner('Detecting backup format...')
794
- detectSpinner.start()
795
-
796
- const format = await engine.detectBackupFormat(backupPath)
797
- detectSpinner.succeed(`Detected: ${format.description}`)
798
-
799
- // For Redis .redis text files, ask about merge vs replace behavior
800
- let flushBeforeRestore = false
801
- if (isRedis && format.format === 'redis') {
802
- const { restoreBehavior } = await escapeablePrompt<{
803
- restoreBehavior: 'replace' | 'merge'
804
- }>([
805
- {
806
- type: 'list',
807
- name: 'restoreBehavior',
808
- message: 'How should existing data be handled?',
809
- choices: [
810
- {
811
- name: `${chalk.yellow('↻')} Replace all ${chalk.gray('(FLUSHDB - clear database first)')}`,
812
- value: 'replace',
813
- },
814
- {
815
- name: `${chalk.green('➕')} Merge ${chalk.gray('(add/update keys, keep others)')}`,
816
- value: 'merge',
817
- },
818
- ],
819
- },
820
- ])
821
- flushBeforeRestore = restoreBehavior === 'replace'
822
- }
823
-
824
- // Redis doesn't need createDatabase - databases 0-15 always exist
825
- if (!isRedis) {
826
- const dbSpinner = createSpinner(`Creating database "${databaseName}"...`)
827
- dbSpinner.start()
828
-
829
- await engine.createDatabase(config, databaseName)
830
- dbSpinner.succeed(`Database "${databaseName}" ready`)
831
- }
832
-
833
- const restoreSpinner = createSpinner('Restoring backup...')
834
- restoreSpinner.start()
835
-
836
- const result = await engine.restore(config, backupPath, {
837
- database: databaseName,
838
- createDatabase: false,
839
- flush: flushBeforeRestore,
840
- })
841
-
842
- if (result.code === 0) {
843
- restoreSpinner.succeed('Backup restored successfully')
844
- } else {
845
- const stderr = result.stderr || ''
846
-
847
- if (
848
- stderr.includes('unsupported version') ||
849
- stderr.includes('Archive version') ||
850
- stderr.includes('too old')
851
- ) {
852
- restoreSpinner.fail('Version compatibility detected')
853
- console.log()
854
- console.log(uiError('PostgreSQL version incompatibility detected:'))
855
- console.log(
856
- uiWarning('Your pg_restore version is too old for this backup file.'),
857
- )
858
-
859
- console.log(chalk.yellow('Cleaning up failed database...'))
860
- try {
861
- await engine.dropDatabase(config, databaseName)
862
- console.log(chalk.gray(`✓ Removed database "${databaseName}"`))
863
- } catch {
864
- console.log(
865
- chalk.yellow(
866
- `Warning: Could not remove database "${databaseName}"`,
867
- ),
868
- )
869
- }
870
-
871
- console.log()
872
-
873
- const versionMatch = stderr.match(/PostgreSQL (\d+)/)
874
- const requiredVersion = versionMatch ? versionMatch[1] : '17'
875
-
876
- console.log(
877
- chalk.gray(
878
- `This backup was created with PostgreSQL ${requiredVersion}`,
879
- ),
880
- )
881
- console.log()
882
-
883
- console.log()
884
- console.log(
885
- uiWarning(
886
- `To restore this backup, download PostgreSQL ${requiredVersion} binaries:`,
887
- ),
888
- )
889
- console.log(
890
- chalk.cyan(` spindb engines download postgresql ${requiredVersion}`),
891
- )
892
- console.log()
893
- console.log(
894
- chalk.gray(
895
- 'Then create a new container with that version and try the restore again.',
896
- ),
897
- )
898
- await pressEnterToContinue()
899
- return
900
- } else {
901
- // Other restore errors - show warnings
902
- restoreSpinner.warn('Restore completed with warnings')
903
- if (result.stderr) {
904
- console.log()
905
- console.log(chalk.yellow(' Warnings/Errors:'))
906
- const lines = result.stderr.split('\n').filter((l) => l.trim())
907
- const displayLines = lines.slice(0, 20)
908
- for (const line of displayLines) {
909
- console.log(chalk.gray(` ${line}`))
910
- }
911
- if (lines.length > 20) {
912
- console.log(chalk.gray(` ... and ${lines.length - 20} more lines`))
913
- }
914
- }
915
- }
916
- }
917
-
918
- if (result.code === 0) {
919
- const connectionString = engine.getConnectionString(config, databaseName)
920
- console.log()
921
- console.log(uiSuccess(`Database "${databaseName}" restored`))
922
- console.log(chalk.gray(' Connection string:'))
923
- console.log(chalk.cyan(` ${connectionString}`))
924
-
925
- const copied = await platformService.copyToClipboard(connectionString)
926
- if (copied) {
927
- console.log(chalk.gray(' ✓ Connection string copied to clipboard'))
928
- } else {
929
- console.log(chalk.gray(' (Could not copy to clipboard)'))
930
- }
931
-
932
- console.log()
933
- }
934
-
935
- if (isTempFile) {
936
- try {
937
- await rm(backupPath, { force: true })
938
- } catch {
939
- // Ignore cleanup errors
940
- }
941
- }
942
-
943
- await pressEnterToContinue()
944
-
945
- return // Exit the wizard loop after successful restore
946
- }
947
- }
948
-
949
- /**
950
- * Shared backup flow for both main menu and container submenu
951
- * Reduces code duplication between handleBackup and handleBackupForContainer
952
- *
953
- * @param containerName - The container to backup
954
- * @param database - Optional database name (skips database selection if provided)
955
- */
956
- async function performBackupFlow(
957
- containerName: string,
958
- database?: string,
959
- ): Promise<void> {
960
- const config = await containerManager.getConfig(containerName)
961
- if (!config) {
962
- console.log(uiError(`Container "${containerName}" not found`))
963
- return
964
- }
965
-
966
- const engine = getEngine(config.engine)
967
-
968
- // Check dependencies
969
- const depsSpinner = createSpinner('Checking required tools...')
970
- depsSpinner.start()
971
-
972
- let missingDeps = await getMissingDependencies(config.engine)
973
- if (missingDeps.length > 0) {
974
- depsSpinner.warn(
975
- `Missing tools: ${missingDeps.map((d) => d.name).join(', ')}`,
976
- )
977
-
978
- const installed = await promptInstallDependencies(
979
- missingDeps[0].binary,
980
- config.engine,
981
- )
982
-
983
- if (!installed) {
984
- return
985
- }
986
-
987
- missingDeps = await getMissingDependencies(config.engine)
988
- if (missingDeps.length > 0) {
989
- console.log(
990
- uiError(
991
- `Still missing tools: ${missingDeps.map((d) => d.name).join(', ')}`,
992
- ),
993
- )
994
- return
995
- }
996
-
997
- console.log(chalk.green(' ✓ All required tools are now available'))
998
- console.log()
999
- } else {
1000
- depsSpinner.succeed('Required tools available')
1001
- }
1002
-
1003
- // Use provided database or select from available databases
1004
- const databases = config.databases || [config.database]
1005
- let databaseName: string
1006
-
1007
- if (database) {
1008
- // Use the pre-selected database from the container submenu
1009
- databaseName = database
1010
- } else if (databases.length > 1) {
1011
- databaseName = await promptDatabaseSelect(
1012
- databases,
1013
- 'Select database to backup:',
1014
- )
1015
- } else {
1016
- databaseName = databases[0]
1017
- }
1018
-
1019
- // Show estimated size
1020
- const estimatedSize = await estimateBackupSize(config)
1021
- if (estimatedSize !== null) {
1022
- console.log(
1023
- chalk.gray(` Estimated database size: ${formatBytes(estimatedSize)}`),
1024
- )
1025
- console.log()
1026
- }
1027
-
1028
- // Select format
1029
- const format = await promptBackupFormat(config.engine)
1030
-
1031
- // Select output directory
1032
- const outputDir = await promptBackupDirectory()
1033
- if (!outputDir) return
1034
-
1035
- // Ensure directory exists
1036
- if (!existsSync(outputDir)) {
1037
- await mkdir(outputDir, { recursive: true })
1038
- }
1039
-
1040
- // Get filename
1041
- const defaultFilename = `${containerName}-${databaseName}-backup-${generateBackupTimestamp()}`
1042
- const filename = await promptBackupFilename(defaultFilename)
1043
-
1044
- const extension = getBackupExtension(config.engine, format)
1045
- const outputPath = join(outputDir, `${filename}${extension}`)
1046
-
1047
- const spinnerLabel = getBackupSpinnerLabel(config.engine, format)
1048
- const backupSpinner = createSpinner(
1049
- `Creating ${spinnerLabel} backup of "${databaseName}"...`,
1050
- )
1051
- backupSpinner.start()
1052
-
1053
- try {
1054
- const result = await engine.backup(config, outputPath, {
1055
- database: databaseName,
1056
- format,
1057
- })
1058
-
1059
- backupSpinner.succeed('Backup created successfully')
1060
-
1061
- console.log()
1062
- console.log(uiSuccess('Backup complete'))
1063
- console.log()
1064
- console.log(chalk.gray(' Saved to:'), chalk.cyan(result.path))
1065
- console.log(chalk.gray(' Size:'), chalk.white(formatBytes(result.size)))
1066
- console.log(chalk.gray(' Format:'), chalk.white(result.format))
1067
- console.log()
1068
- } catch (error) {
1069
- const e = error as Error
1070
- backupSpinner.fail('Backup failed')
1071
- console.log()
1072
- console.log(uiError(e.message))
1073
- console.log()
1074
- }
1075
- }
1076
-
1077
- export async function handleBackup(): Promise<void> {
1078
- const containers = await containerManager.list()
1079
- const running = containers.filter((c) => c.status === 'running')
1080
-
1081
- if (running.length === 0) {
1082
- console.log(uiWarning('No running containers. Start a container first.'))
1083
- await pressEnterToContinue()
1084
- return
1085
- }
1086
-
1087
- const containerName = await promptContainerSelect(
1088
- running,
1089
- 'Select container to backup:',
1090
- { includeBack: true },
1091
- )
1092
- if (!containerName) return
1093
-
1094
- await performBackupFlow(containerName)
1095
- await pressEnterToContinue()
1096
- }
1097
-
1098
- /**
1099
- * Handle backup for a specific container (used from container submenu)
1100
- * Skips container selection since we already know which container
1101
- */
1102
- export async function handleBackupForContainer(
1103
- containerName: string,
1104
- database?: string,
1105
- ): Promise<void> {
1106
- await performBackupFlow(containerName, database)
1107
- await pressEnterToContinue()
1108
- }
1109
-
1110
- /**
1111
- * Handle restore for a specific container (used from container submenu)
1112
- * Skips container selection since we already know which container
1113
- *
1114
- * @param containerName - The container to restore to
1115
- * @param database - Optional database name (pre-selects target database if provided)
1116
- */
1117
- export async function handleRestoreForContainer(
1118
- containerName: string,
1119
- database?: string,
1120
- ): Promise<void> {
1121
- const config = await containerManager.getConfig(containerName)
1122
- if (!config) {
1123
- console.log(uiError(`Container "${containerName}" not found`))
1124
- await pressEnterToContinue()
1125
- return
1126
- }
1127
-
1128
- const engine = getEngine(config.engine)
1129
-
1130
- // Check dependencies
1131
- const depsSpinner = createSpinner('Checking required tools...')
1132
- depsSpinner.start()
1133
-
1134
- let missingDeps = await getMissingDependencies(config.engine)
1135
- if (missingDeps.length > 0) {
1136
- depsSpinner.warn(
1137
- `Missing tools: ${missingDeps.map((d) => d.name).join(', ')}`,
1138
- )
1139
-
1140
- const installed = await promptInstallDependencies(
1141
- missingDeps[0].binary,
1142
- config.engine,
1143
- )
1144
-
1145
- if (!installed) {
1146
- return
1147
- }
1148
-
1149
- missingDeps = await getMissingDependencies(config.engine)
1150
- if (missingDeps.length > 0) {
1151
- console.log(
1152
- uiError(
1153
- `Still missing tools: ${missingDeps.map((d) => d.name).join(', ')}`,
1154
- ),
1155
- )
1156
- return
1157
- }
1158
-
1159
- console.log(chalk.green(' ✓ All required tools are now available'))
1160
- console.log()
1161
- } else {
1162
- depsSpinner.succeed('Required tools available')
1163
- }
1164
-
1165
- // Restore source selection (file or connection string)
1166
- // All engines now support dumpFromConnectionString
1167
- const restoreChoices: Array<
1168
- { name: string; value: string } | inquirer.Separator
1169
- > = [
1170
- {
1171
- name: `${chalk.magenta('☰')} Dump file (drag and drop or enter path)`,
1172
- value: 'file',
1173
- },
1174
- {
1175
- name: `${chalk.cyan('↗')} Connection string ${chalk.gray('(pull from remote database)')}`,
1176
- value: 'connection',
1177
- },
1178
- ]
1179
-
1180
- restoreChoices.push(new inquirer.Separator(), {
1181
- name: `${chalk.blue('←')} Back`,
1182
- value: '__back__',
1183
- })
1184
-
1185
- const { restoreSource } = await escapeablePrompt<{
1186
- restoreSource: 'file' | 'connection' | '__back__'
1187
- }>([
1188
- {
1189
- type: 'list',
1190
- name: 'restoreSource',
1191
- message: 'Restore from:',
1192
- choices: restoreChoices,
1193
- },
1194
- ])
1195
-
1196
- if (restoreSource === '__back__') {
1197
- return
1198
- }
1199
-
1200
- let backupPath = ''
1201
- let isTempFile = false
1202
-
1203
- if (restoreSource === 'connection') {
1204
- const connectionString = await promptConnectionString(config.engine)
1205
- if (!connectionString) {
1206
- return
1207
- }
1208
-
1209
- const timestamp = Date.now()
1210
- const defaultFormat = getDefaultFormat(config.engine as Engine)
1211
- const dumpExtension = getBackupExtension(
1212
- config.engine as Engine,
1213
- defaultFormat,
1214
- )
1215
- const tempDumpPath = join(
1216
- tmpdir(),
1217
- `spindb-dump-${timestamp}${dumpExtension}`,
1218
- )
1219
-
1220
- const dumpSpinner = createSpinner('Creating dump from remote database...')
1221
- dumpSpinner.start()
1222
-
1223
- try {
1224
- const dumpResult = await engine.dumpFromConnectionString(
1225
- connectionString,
1226
- tempDumpPath,
1227
- )
1228
- dumpSpinner.succeed('Dump created from remote database')
1229
- if (dumpResult.warnings?.length) {
1230
- for (const warning of dumpResult.warnings) {
1231
- console.log(chalk.yellow(` ${warning}`))
1232
- }
1233
- }
1234
- backupPath = tempDumpPath
1235
- isTempFile = true
1236
- } catch (error) {
1237
- const e = error as Error
1238
- dumpSpinner.fail('Failed to create dump')
1239
- console.log(uiError(e.message))
1240
- await pressEnterToContinue()
1241
- return
1242
- }
1243
- } else {
1244
- // Handle file restore
1245
- console.log(
1246
- chalk.gray(
1247
- ' Drag & drop, enter path (abs or rel), or press Enter to go back (esc - main menu)',
1248
- ),
1249
- )
1250
- const { backupPath: rawBackupPath } = await escapeablePrompt<{
1251
- backupPath: string
1252
- }>([
1253
- {
1254
- type: 'input',
1255
- name: 'backupPath',
1256
- message: 'Backup file path:',
1257
- validate: (input: string) => {
1258
- if (!input) return true
1259
- const cleanPath = stripQuotes(input)
1260
- if (!existsSync(cleanPath)) return 'File not found'
1261
- return true
1262
- },
1263
- },
1264
- ])
1265
-
1266
- if (!rawBackupPath.trim()) {
1267
- return
1268
- }
1269
-
1270
- backupPath = stripQuotes(rawBackupPath)
1271
- }
1272
-
1273
- // Check backup file size and warn if large
1274
- const sizeCheck = checkBackupSize(backupPath)
1275
- if (sizeCheck.level === 'very_large') {
1276
- console.log()
1277
- console.log(
1278
- chalk.yellow(` ⚠ Large backup file: ${formatBytes(sizeCheck.size)}`),
1279
- )
1280
- console.log(chalk.gray(' This restore may take a while.'))
1281
- console.log()
1282
- const confirmed = await promptConfirm('Continue with restore?', true)
1283
- if (!confirmed) {
1284
- if (isTempFile) {
1285
- await rm(backupPath, { force: true }).catch(() => {})
1286
- }
1287
- return
1288
- }
1289
- } else if (sizeCheck.level === 'large') {
1290
- console.log(
1291
- chalk.gray(` Backup file size: ${formatBytes(sizeCheck.size)}`),
1292
- )
1293
- }
1294
-
1295
- // Detect backup format
1296
- const format = await engine.detectBackupFormat(backupPath)
1297
- console.log(chalk.gray(` Detected format: ${format.description}`))
1298
- console.log()
1299
-
1300
- // Get existing databases in this container
1301
- const existingDatabases = config.databases || [config.database]
1302
-
1303
- // Redis uses numbered databases 0-15, so "create new" doesn't apply
1304
- const isRedis = config.engine === 'redis'
1305
-
1306
- // Restore mode selection
1307
- type RestoreMode = 'new' | 'replace' | '__back__'
1308
- let restoreMode: RestoreMode
1309
-
1310
- if (isRedis) {
1311
- // Redis: Always restore to existing database (0-15)
1312
- restoreMode = 'replace'
1313
- } else {
1314
- const result = await escapeablePrompt<{ restoreMode: RestoreMode }>([
1315
- {
1316
- type: 'list',
1317
- name: 'restoreMode',
1318
- message: 'How would you like to restore?',
1319
- choices: [
1320
- {
1321
- name: `${chalk.green('➕')} Create new database ${chalk.gray('(keeps existing databases intact)')}`,
1322
- value: 'new',
1323
- },
1324
- {
1325
- name: `${chalk.yellow('↻')} Replace existing database ${chalk.gray('(overwrites data)')}`,
1326
- value: 'replace',
1327
- disabled:
1328
- existingDatabases.length === 0 ? 'No existing databases' : false,
1329
- },
1330
- new inquirer.Separator(),
1331
- {
1332
- name: `${chalk.blue('←')} Back`,
1333
- value: '__back__',
1334
- },
1335
- ],
1336
- },
1337
- ])
1338
- restoreMode = result.restoreMode
1339
- }
1340
-
1341
- if (restoreMode === '__back__') {
1342
- if (isTempFile) {
1343
- await rm(backupPath, { force: true }).catch(() => {})
1344
- }
1345
- return
1346
- }
1347
-
1348
- let databaseName: string
1349
-
1350
- if (restoreMode === 'new') {
1351
- // Show existing databases for context
1352
- if (existingDatabases.length > 0) {
1353
- console.log()
1354
- console.log(chalk.gray(' Existing databases in this container:'))
1355
- for (const db of existingDatabases) {
1356
- console.log(chalk.gray(` • ${db}`))
1357
- }
1358
- console.log()
1359
- }
1360
-
1361
- // Prompt for new database name
1362
- const result = await promptDatabaseName(containerName, config.engine, {
1363
- existingDatabases,
1364
- })
1365
- if (!result) {
1366
- if (isTempFile) {
1367
- await rm(backupPath, { force: true }).catch(() => {})
1368
- }
1369
- return
1370
- }
1371
- databaseName = result
1372
-
1373
- // Create the new database
1374
- const createDbSpinner = createSpinner(
1375
- `Creating database "${databaseName}"...`,
1376
- )
1377
- createDbSpinner.start()
1378
- try {
1379
- await engine.createDatabase(config, databaseName)
1380
- createDbSpinner.succeed(`Database "${databaseName}" created`)
1381
-
1382
- // Update container config with new database
1383
- const updatedDbs = [...existingDatabases, databaseName]
1384
- await containerManager.updateConfig(containerName, {
1385
- databases: updatedDbs,
1386
- })
1387
- } catch (error) {
1388
- const e = error as Error
1389
- createDbSpinner.fail('Failed to create database')
1390
- console.log(uiError(e.message))
1391
- if (isTempFile) {
1392
- await rm(backupPath, { force: true }).catch(() => {})
1393
- }
1394
- await pressEnterToContinue()
1395
- return
1396
- }
1397
- } else {
1398
- // Replace existing database - use pre-selected or auto-select if only one
1399
- if (database) {
1400
- // Use the pre-selected database from the container submenu
1401
- databaseName = database
1402
- console.log(chalk.gray(` Target database: ${databaseName}`))
1403
- } else if (existingDatabases.length === 1) {
1404
- databaseName = existingDatabases[0]
1405
- console.log(chalk.gray(` Using database: ${databaseName}`))
1406
- } else {
1407
- const { database: selectedDb } = await escapeablePrompt<{
1408
- database: string
1409
- }>([
1410
- {
1411
- type: 'list',
1412
- name: 'database',
1413
- message: 'Select database to replace:',
1414
- choices: existingDatabases.map((db) => ({ name: db, value: db })),
1415
- },
1416
- ])
1417
- databaseName = selectedDb
1418
- }
1419
- }
1420
-
1421
- // For Redis .redis text files, ask about merge vs replace behavior
1422
- let flushBeforeRestore = false
1423
- if (isRedis && format.format === 'redis') {
1424
- const { restoreBehavior } = await escapeablePrompt<{
1425
- restoreBehavior: 'replace' | 'merge'
1426
- }>([
1427
- {
1428
- type: 'list',
1429
- name: 'restoreBehavior',
1430
- message: 'How should existing data be handled?',
1431
- choices: [
1432
- {
1433
- name: `${chalk.yellow('↻')} Replace all ${chalk.gray('(FLUSHDB - clear database first)')}`,
1434
- value: 'replace',
1435
- },
1436
- {
1437
- name: `${chalk.green('➕')} Merge ${chalk.gray('(add/update keys, keep others)')}`,
1438
- value: 'merge',
1439
- },
1440
- ],
1441
- },
1442
- ])
1443
- flushBeforeRestore = restoreBehavior === 'replace'
1444
- }
1445
-
1446
- // Perform restore
1447
- const restoreSpinner = createSpinner(
1448
- `Restoring to "${databaseName}" in ${containerName}...`,
1449
- )
1450
- restoreSpinner.start()
1451
-
1452
- try {
1453
- const result = await engine.restore(config, backupPath, {
1454
- database: databaseName,
1455
- flush: flushBeforeRestore,
1456
- })
1457
-
1458
- if (result.code === 0) {
1459
- restoreSpinner.succeed('Restore completed successfully')
1460
-
1461
- const connectionString = engine.getConnectionString(config, databaseName)
1462
- console.log()
1463
- console.log(uiSuccess(`Database "${databaseName}" restored`))
1464
- console.log(chalk.gray(' Connection string:'))
1465
- console.log(chalk.cyan(` ${connectionString}`))
1466
-
1467
- const copied = await platformService.copyToClipboard(connectionString)
1468
- if (copied) {
1469
- console.log(chalk.gray(' ✓ Connection string copied to clipboard'))
1470
- }
1471
- console.log()
1472
- } else {
1473
- restoreSpinner.warn('Restore completed with warnings')
1474
- if (result.stderr) {
1475
- console.log()
1476
- console.log(chalk.yellow(' Warnings/Errors:'))
1477
- const lines = result.stderr.split('\n').filter((l) => l.trim())
1478
- const displayLines = lines.slice(0, 10)
1479
- for (const line of displayLines) {
1480
- console.log(chalk.gray(` ${line}`))
1481
- }
1482
- if (lines.length > 10) {
1483
- console.log(chalk.gray(` ... and ${lines.length - 10} more lines`))
1484
- }
1485
- }
1486
- }
1487
- } catch (error) {
1488
- const e = error as Error
1489
- restoreSpinner.fail('Restore failed')
1490
- console.log()
1491
- console.log(uiError(e.message))
1492
- console.log()
1493
- }
1494
-
1495
- await pressEnterToContinue()
1496
- }
1497
-
1498
- export async function handleClone(): Promise<void> {
1499
- const containers = await containerManager.list()
1500
- const stopped = containers.filter((c) => c.status !== 'running')
1501
-
1502
- if (containers.length === 0) {
1503
- console.log(uiWarning('No containers found'))
1504
- return
1505
- }
1506
-
1507
- if (stopped.length === 0) {
1508
- console.log(
1509
- uiWarning(
1510
- 'All containers are running. Stop a container first to clone it.',
1511
- ),
1512
- )
1513
- return
1514
- }
1515
-
1516
- const sourceName = await promptContainerSelect(
1517
- stopped,
1518
- 'Select container to clone:',
1519
- { includeBack: true },
1520
- )
1521
- if (!sourceName) return
1522
-
1523
- const sourceConfig = await containerManager.getConfig(sourceName)
1524
- if (!sourceConfig) {
1525
- console.log(uiError(`Container "${sourceName}" not found`))
1526
- return
1527
- }
1528
-
1529
- const { targetName } = await escapeablePrompt<{ targetName: string }>([
1530
- {
1531
- type: 'input',
1532
- name: 'targetName',
1533
- message: 'Name for the cloned container:',
1534
- default: `${sourceName}-copy`,
1535
- validate: (input: string) => {
1536
- if (!input) return 'Name is required'
1537
- if (!/^[a-zA-Z][a-zA-Z0-9_-]*$/.test(input)) {
1538
- return 'Name must start with a letter and contain only letters, numbers, hyphens, and underscores'
1539
- }
1540
- return true
1541
- },
1542
- },
1543
- ])
1544
-
1545
- // Check if target container already exists
1546
- if (
1547
- await containerManager.exists(targetName, { engine: sourceConfig.engine })
1548
- ) {
1549
- console.log(uiError(`Container "${targetName}" already exists`))
1550
- return
1551
- }
1552
-
1553
- const spinner = createSpinner(`Cloning ${sourceName} to ${targetName}...`)
1554
- spinner.start()
1555
-
1556
- try {
1557
- const newConfig = await containerManager.clone(sourceName, targetName)
1558
-
1559
- spinner.succeed(`Cloned "${sourceName}" to "${targetName}"`)
1560
-
1561
- const engine = getEngine(newConfig.engine)
1562
- const connectionString = engine.getConnectionString(newConfig)
1563
-
1564
- console.log()
1565
- console.log(connectionBox(targetName, connectionString, newConfig.port))
1566
- } catch (error) {
1567
- const e = error as Error
1568
- spinner.fail(`Failed to clone "${sourceName}"`)
1569
- console.log(uiError(e.message))
1570
- }
1571
- }