@withbuddi/buddi 0.1.0-pre.53 → 0.1.0-pre.54
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/extension/background.js +38 -7
- package/extension/manifest.json +2 -2
- package/extension/popup.html +2 -2
- package/node_modules/@buddi/cli/dist/.tsbuildinfo +1 -1
- package/node_modules/@buddi/cli/dist/dashboard-cmd.d.ts.map +1 -1
- package/node_modules/@buddi/cli/dist/dashboard-cmd.js +6 -3
- package/node_modules/@buddi/cli/dist/dashboard-cmd.js.map +1 -1
- package/node_modules/@buddi/cli/dist/main.js +2 -2
- package/node_modules/@buddi/cli/dist/main.js.map +1 -1
- package/node_modules/@buddi/cli/dist/status.d.ts +16 -2
- package/node_modules/@buddi/cli/dist/status.d.ts.map +1 -1
- package/node_modules/@buddi/cli/dist/status.js +42 -2
- package/node_modules/@buddi/cli/dist/status.js.map +1 -1
- package/node_modules/@buddi/core/dist/.tsbuildinfo +1 -1
- package/node_modules/@buddi/core/dist/agents/catalog.d.ts +6 -0
- package/node_modules/@buddi/core/dist/agents/catalog.d.ts.map +1 -1
- package/node_modules/@buddi/core/dist/agents/catalog.js +1 -1
- package/node_modules/@buddi/core/dist/agents/catalog.js.map +1 -1
- package/node_modules/@buddi/core/dist/backup/archive.d.ts +6 -0
- package/node_modules/@buddi/core/dist/backup/archive.d.ts.map +1 -1
- package/node_modules/@buddi/core/dist/backup/archive.js +19 -6
- package/node_modules/@buddi/core/dist/backup/archive.js.map +1 -1
- package/node_modules/@buddi/core/dist/postgres/binaries.d.ts +21 -1
- package/node_modules/@buddi/core/dist/postgres/binaries.d.ts.map +1 -1
- package/node_modules/@buddi/core/dist/postgres/binaries.js +72 -10
- package/node_modules/@buddi/core/dist/postgres/binaries.js.map +1 -1
- package/node_modules/@buddi/core/dist/postgres/cluster.d.ts +8 -0
- package/node_modules/@buddi/core/dist/postgres/cluster.d.ts.map +1 -1
- package/node_modules/@buddi/core/dist/postgres/cluster.js +119 -17
- package/node_modules/@buddi/core/dist/postgres/cluster.js.map +1 -1
- package/node_modules/@buddi/core/dist/postgres/windows-guard.d.ts +20 -0
- package/node_modules/@buddi/core/dist/postgres/windows-guard.d.ts.map +1 -0
- package/node_modules/@buddi/core/dist/postgres/windows-guard.js +140 -0
- package/node_modules/@buddi/core/dist/postgres/windows-guard.js.map +1 -0
- package/node_modules/@buddi/gateway/dist/.tsbuildinfo +1 -1
- package/node_modules/@buddi/gateway/dist/agents/catalog.d.ts.map +1 -1
- package/node_modules/@buddi/gateway/dist/agents/catalog.js +3 -2
- package/node_modules/@buddi/gateway/dist/agents/catalog.js.map +1 -1
- package/node_modules/@buddi/gateway/dist/agents/catalogue-package.d.ts +2 -2
- package/node_modules/@buddi/gateway/dist/agents/catalogue-package.d.ts.map +1 -1
- package/node_modules/@buddi/gateway/dist/agents/catalogue-package.js +1 -1
- package/node_modules/@buddi/gateway/dist/agents/catalogue-package.js.map +1 -1
- package/node_modules/@buddi/gateway/dist/agents/platform-catalogue.d.ts +6 -6
- package/node_modules/@buddi/gateway/dist/agents/platform-catalogue.d.ts.map +1 -1
- package/node_modules/@buddi/gateway/dist/agents/platform-catalogue.js +5 -5
- package/node_modules/@buddi/gateway/dist/agents/platform-catalogue.js.map +1 -1
- package/node_modules/@buddi/gateway/dist/browser-host.js +1 -1
- package/node_modules/@buddi/gateway/dist/browser-host.js.map +1 -1
- package/node_modules/@buddi/gateway/dist/missions/chrome-scope.d.ts +10 -10
- package/node_modules/@buddi/gateway/dist/missions/chrome-scope.d.ts.map +1 -1
- package/node_modules/@buddi/gateway/dist/missions/chrome-scope.js +20 -20
- package/node_modules/@buddi/gateway/dist/missions/chrome-scope.js.map +1 -1
- package/node_modules/@buddi/gateway/dist/missions/execute.d.ts +2 -2
- package/node_modules/@buddi/gateway/dist/missions/execute.d.ts.map +1 -1
- package/node_modules/@buddi/gateway/dist/missions/execute.js +11 -11
- package/node_modules/@buddi/gateway/dist/missions/execute.js.map +1 -1
- package/node_modules/@buddi/gateway/dist/missions/reminders.d.ts +2 -2
- package/node_modules/@buddi/gateway/dist/missions/reminders.d.ts.map +1 -1
- package/node_modules/@buddi/gateway/dist/missions/reminders.js +5 -5
- package/node_modules/@buddi/gateway/dist/missions/reminders.js.map +1 -1
- package/node_modules/@buddi/gateway/dist/owner-notify.js +1 -1
- package/node_modules/@buddi/gateway/dist/owner-notify.js.map +1 -1
- package/node_modules/@buddi/gateway/dist/plugins/npm.d.ts +9 -2
- package/node_modules/@buddi/gateway/dist/plugins/npm.d.ts.map +1 -1
- package/node_modules/@buddi/gateway/dist/plugins/npm.js +29 -6
- package/node_modules/@buddi/gateway/dist/plugins/npm.js.map +1 -1
- package/node_modules/@buddi/gateway/dist/plugins/stage.d.ts.map +1 -1
- package/node_modules/@buddi/gateway/dist/plugins/stage.js +2 -2
- package/node_modules/@buddi/gateway/dist/plugins/stage.js.map +1 -1
- package/node_modules/@buddi/gateway/dist/serve.js +1 -1
- package/node_modules/@buddi/gateway/dist/serve.js.map +1 -1
- package/node_modules/@buddi/gateway/dist/surfaces/browser-cards.d.ts +1 -1
- package/node_modules/@buddi/gateway/dist/surfaces/browser-cards.js +1 -1
- package/node_modules/@buddi/gateway/dist/system-context.d.ts +11 -0
- package/node_modules/@buddi/gateway/dist/system-context.d.ts.map +1 -1
- package/node_modules/@buddi/gateway/dist/system-context.js +42 -1
- package/node_modules/@buddi/gateway/dist/system-context.js.map +1 -1
- package/node_modules/@buddi/gateway/dist/telegram/approvals.js +1 -1
- package/node_modules/@buddi/gateway/dist/telegram/approvals.js.map +1 -1
- package/node_modules/@buddi/gateway/dist/telegram/browser-view.js +1 -1
- package/node_modules/@buddi/gateway/dist/telegram/browser-view.js.map +1 -1
- package/node_modules/@buddi/gateway/dist/web/api-routes.js +6 -6
- package/node_modules/@buddi/gateway/dist/web/api-routes.js.map +1 -1
- package/node_modules/@buddi/gateway/dist/web/approval-ask.js +1 -1
- package/node_modules/@buddi/gateway/dist/web/extension.d.ts +6 -0
- package/node_modules/@buddi/gateway/dist/web/extension.d.ts.map +1 -1
- package/node_modules/@buddi/gateway/dist/web/extension.js +22 -11
- package/node_modules/@buddi/gateway/dist/web/extension.js.map +1 -1
- package/node_modules/@buddi/gateway/dist/web/read.d.ts +1 -1
- package/node_modules/@buddi/gateway/dist/web/read.d.ts.map +1 -1
- package/node_modules/@buddi/gateway/dist/web/server.js +4 -4
- package/node_modules/@buddi/gateway/dist/web/server.js.map +1 -1
- package/node_modules/@buddi/gateway/dist/web/service.d.ts +6 -1
- package/node_modules/@buddi/gateway/dist/web/service.d.ts.map +1 -1
- package/node_modules/@buddi/gateway/dist/web/service.js +10 -1
- package/node_modules/@buddi/gateway/dist/web/service.js.map +1 -1
- package/node_modules/@buddi/gateway/dist/web/skills.d.ts.map +1 -1
- package/node_modules/@buddi/gateway/dist/web/skills.js +2 -1
- package/node_modules/@buddi/gateway/dist/web/skills.js.map +1 -1
- package/node_modules/@buddi/gateway/dist/web/write.d.ts +1 -1
- package/node_modules/@buddi/gateway/dist/web/write.js +1 -1
- package/node_modules/@buddi/install/dist/.tsbuildinfo +1 -1
- package/node_modules/@buddi/install/dist/app-layout.d.ts +30 -1
- package/node_modules/@buddi/install/dist/app-layout.d.ts.map +1 -1
- package/node_modules/@buddi/install/dist/app-layout.js +61 -10
- package/node_modules/@buddi/install/dist/app-layout.js.map +1 -1
- package/node_modules/@buddi/install/dist/cloudflared.js +2 -2
- package/node_modules/@buddi/install/dist/cloudflared.js.map +1 -1
- package/node_modules/@buddi/install/dist/environment.d.ts +40 -1
- package/node_modules/@buddi/install/dist/environment.d.ts.map +1 -1
- package/node_modules/@buddi/install/dist/environment.js +158 -12
- package/node_modules/@buddi/install/dist/environment.js.map +1 -1
- package/node_modules/@buddi/install/dist/launcher.d.ts.map +1 -1
- package/node_modules/@buddi/install/dist/launcher.js +257 -50
- package/node_modules/@buddi/install/dist/launcher.js.map +1 -1
- package/node_modules/@buddi/install/dist/postgres-check.js +1 -1
- package/node_modules/@buddi/install/dist/postgres-check.js.map +1 -1
- package/node_modules/@buddi/install/dist/product-uninstall.d.ts +14 -0
- package/node_modules/@buddi/install/dist/product-uninstall.d.ts.map +1 -1
- package/node_modules/@buddi/install/dist/product-uninstall.js +10 -0
- package/node_modules/@buddi/install/dist/product-uninstall.js.map +1 -1
- package/node_modules/@buddi/install/dist/runtime-info.d.ts.map +1 -1
- package/node_modules/@buddi/install/dist/runtime-info.js +4 -1
- package/node_modules/@buddi/install/dist/runtime-info.js.map +1 -1
- package/node_modules/@buddi/install/dist/supervisor.d.ts +60 -3
- package/node_modules/@buddi/install/dist/supervisor.d.ts.map +1 -1
- package/node_modules/@buddi/install/dist/supervisor.js +173 -17
- package/node_modules/@buddi/install/dist/supervisor.js.map +1 -1
- package/node_modules/@buddi/install/dist/uninstall.d.ts +29 -3
- package/node_modules/@buddi/install/dist/uninstall.d.ts.map +1 -1
- package/node_modules/@buddi/install/dist/uninstall.js +135 -27
- package/node_modules/@buddi/install/dist/uninstall.js.map +1 -1
- package/node_modules/@buddi/install/dist/upgrade.d.ts +16 -4
- package/node_modules/@buddi/install/dist/upgrade.d.ts.map +1 -1
- package/node_modules/@buddi/install/dist/upgrade.js +50 -13
- package/node_modules/@buddi/install/dist/upgrade.js.map +1 -1
- package/node_modules/@buddi/install/dist/windows-install.d.ts +102 -0
- package/node_modules/@buddi/install/dist/windows-install.d.ts.map +1 -0
- package/node_modules/@buddi/install/dist/windows-install.js +223 -0
- package/node_modules/@buddi/install/dist/windows-install.js.map +1 -0
- package/node_modules/@buddi/install/dist/windows-setup.d.ts +107 -0
- package/node_modules/@buddi/install/dist/windows-setup.d.ts.map +1 -0
- package/node_modules/@buddi/install/dist/windows-setup.js +700 -0
- package/node_modules/@buddi/install/dist/windows-setup.js.map +1 -0
- package/node_modules/@buddi/install/dist/windows-task.d.ts +49 -0
- package/node_modules/@buddi/install/dist/windows-task.d.ts.map +1 -0
- package/node_modules/@buddi/install/dist/windows-task.js +167 -0
- package/node_modules/@buddi/install/dist/windows-task.js.map +1 -0
- package/node_modules/@buddi/runtime/dist/.tsbuildinfo +1 -1
- package/node_modules/@buddi/runtime/dist/codex-direct.d.ts +1 -1
- package/node_modules/@buddi/runtime/dist/codex-direct.js +1 -1
- package/node_modules/@buddi/runtime/dist/openai.d.ts +11 -0
- package/node_modules/@buddi/runtime/dist/openai.d.ts.map +1 -1
- package/node_modules/@buddi/runtime/dist/openai.js +36 -3
- package/node_modules/@buddi/runtime/dist/openai.js.map +1 -1
- package/node_modules/@buddi/tool-artifacts/dist/.tsbuildinfo +1 -1
- package/node_modules/@buddi/tool-artifacts/dist/tools/write.js +3 -3
- package/node_modules/@buddi/tool-artifacts/dist/tools/write.js.map +1 -1
- package/node_modules/@buddi/tool-browser/dist/.tsbuildinfo +1 -1
- package/node_modules/@buddi/tool-browser/dist/availability.d.ts.map +1 -1
- package/node_modules/@buddi/tool-browser/dist/availability.js +1 -0
- package/node_modules/@buddi/tool-browser/dist/availability.js.map +1 -1
- package/node_modules/@buddi/tool-browser/dist/brand.d.ts +19 -0
- package/node_modules/@buddi/tool-browser/dist/brand.d.ts.map +1 -0
- package/node_modules/@buddi/tool-browser/dist/brand.js +31 -0
- package/node_modules/@buddi/tool-browser/dist/brand.js.map +1 -0
- package/node_modules/@buddi/tool-browser/dist/controller.d.ts +2 -2
- package/node_modules/@buddi/tool-browser/dist/controller.d.ts.map +1 -1
- package/node_modules/@buddi/tool-browser/dist/controller.js +16 -7
- package/node_modules/@buddi/tool-browser/dist/controller.js.map +1 -1
- package/node_modules/@buddi/tool-browser/dist/downloads.js +1 -1
- package/node_modules/@buddi/tool-browser/dist/downloads.js.map +1 -1
- package/node_modules/@buddi/tool-browser/dist/extension.d.ts +3 -1
- package/node_modules/@buddi/tool-browser/dist/extension.d.ts.map +1 -1
- package/node_modules/@buddi/tool-browser/dist/extension.js +4 -4
- package/node_modules/@buddi/tool-browser/dist/extension.js.map +1 -1
- package/node_modules/@buddi/tool-browser/dist/index.d.ts +3 -2
- package/node_modules/@buddi/tool-browser/dist/index.d.ts.map +1 -1
- package/node_modules/@buddi/tool-browser/dist/index.js +7 -6
- package/node_modules/@buddi/tool-browser/dist/index.js.map +1 -1
- package/node_modules/@buddi/tool-browser/dist/routes.d.ts +12 -1
- package/node_modules/@buddi/tool-browser/dist/routes.d.ts.map +1 -1
- package/node_modules/@buddi/tool-browser/dist/routes.js +31 -14
- package/node_modules/@buddi/tool-browser/dist/routes.js.map +1 -1
- package/node_modules/@buddi/tool-browser/dist/service.d.ts +2 -0
- package/node_modules/@buddi/tool-browser/dist/service.d.ts.map +1 -1
- package/node_modules/@buddi/tool-browser/dist/service.js +6 -6
- package/node_modules/@buddi/tool-browser/dist/service.js.map +1 -1
- package/node_modules/@buddi/tool-browser/dist/telemetry.d.ts +2 -2
- package/node_modules/@buddi/tool-browser/dist/telemetry.js +2 -2
- package/node_modules/@buddi/tool-browser/dist/telemetry.js.map +1 -1
- package/node_modules/@buddi/tool-browser/dist/types.js +1 -1
- package/node_modules/@buddi/tool-browser/dist/types.js.map +1 -1
- package/node_modules/@buddi/tool-host/dist/.tsbuildinfo +1 -1
- package/node_modules/@buddi/tool-host/dist/index.d.ts +2 -1
- package/node_modules/@buddi/tool-host/dist/index.d.ts.map +1 -1
- package/node_modules/@buddi/tool-host/dist/index.js +11 -2
- package/node_modules/@buddi/tool-host/dist/index.js.map +1 -1
- package/node_modules/@buddi/tool-host/dist/process.d.ts +58 -1
- package/node_modules/@buddi/tool-host/dist/process.d.ts.map +1 -1
- package/node_modules/@buddi/tool-host/dist/process.js +229 -15
- package/node_modules/@buddi/tool-host/dist/process.js.map +1 -1
- package/node_modules/@buddi/tool-host/dist/service.d.ts +2 -0
- package/node_modules/@buddi/tool-host/dist/service.d.ts.map +1 -1
- package/node_modules/@buddi/tool-host/dist/service.js +8 -6
- package/node_modules/@buddi/tool-host/dist/service.js.map +1 -1
- package/node_modules/@buddi/tool-host/dist/skill-run.d.ts +10 -0
- package/node_modules/@buddi/tool-host/dist/skill-run.d.ts.map +1 -1
- package/node_modules/@buddi/tool-host/dist/skill-run.js +14 -0
- package/node_modules/@buddi/tool-host/dist/skill-run.js.map +1 -1
- package/node_modules/ip-address/README.md +70 -70
- package/node_modules/ip-address/dist/ipv6.js +7 -4
- package/node_modules/ip-address/dist/ipv6.js.map +1 -1
- package/node_modules/ip-address/dist/v6/constants.d.ts +3 -0
- package/node_modules/ip-address/dist/v6/constants.js +3 -0
- package/node_modules/ip-address/dist/v6/constants.js.map +1 -1
- package/node_modules/ip-address/package.json +2 -1
- package/node_modules/marked/bin/main.js +1 -1
- package/node_modules/marked/lib/marked.d.ts +6 -3
- package/node_modules/marked/lib/marked.esm.js +48 -50
- package/node_modules/marked/lib/marked.esm.js.map +3 -3
- package/node_modules/marked/lib/marked.umd.js +45 -47
- package/node_modules/marked/lib/marked.umd.js.map +3 -3
- package/node_modules/marked/man/marked.1 +1 -1
- package/node_modules/marked/package.json +1 -1
- package/package.json +2 -2
- package/packages/cli/dist/.tsbuildinfo +1 -1
- package/packages/cli/dist/dashboard-cmd.d.ts.map +1 -1
- package/packages/cli/dist/dashboard-cmd.js +6 -3
- package/packages/cli/dist/dashboard-cmd.js.map +1 -1
- package/packages/cli/dist/main.js +2 -2
- package/packages/cli/dist/main.js.map +1 -1
- package/packages/cli/dist/status.d.ts +16 -2
- package/packages/cli/dist/status.d.ts.map +1 -1
- package/packages/cli/dist/status.js +42 -2
- package/packages/cli/dist/status.js.map +1 -1
- package/packages/core/dist/.tsbuildinfo +1 -1
- package/packages/core/dist/agents/catalog.d.ts +6 -0
- package/packages/core/dist/agents/catalog.d.ts.map +1 -1
- package/packages/core/dist/agents/catalog.js +1 -1
- package/packages/core/dist/agents/catalog.js.map +1 -1
- package/packages/core/dist/backup/archive.d.ts +6 -0
- package/packages/core/dist/backup/archive.d.ts.map +1 -1
- package/packages/core/dist/backup/archive.js +19 -6
- package/packages/core/dist/backup/archive.js.map +1 -1
- package/packages/core/dist/postgres/binaries.d.ts +21 -1
- package/packages/core/dist/postgres/binaries.d.ts.map +1 -1
- package/packages/core/dist/postgres/binaries.js +72 -10
- package/packages/core/dist/postgres/binaries.js.map +1 -1
- package/packages/core/dist/postgres/cluster.d.ts +8 -0
- package/packages/core/dist/postgres/cluster.d.ts.map +1 -1
- package/packages/core/dist/postgres/cluster.js +119 -17
- package/packages/core/dist/postgres/cluster.js.map +1 -1
- package/packages/core/dist/postgres/windows-guard.d.ts +20 -0
- package/packages/core/dist/postgres/windows-guard.d.ts.map +1 -0
- package/packages/core/dist/postgres/windows-guard.js +140 -0
- package/packages/core/dist/postgres/windows-guard.js.map +1 -0
- package/packages/gateway/dist/.tsbuildinfo +1 -1
- package/packages/gateway/dist/agents/catalog.d.ts.map +1 -1
- package/packages/gateway/dist/agents/catalog.js +3 -2
- package/packages/gateway/dist/agents/catalog.js.map +1 -1
- package/packages/gateway/dist/agents/catalogue-package.d.ts +2 -2
- package/packages/gateway/dist/agents/catalogue-package.d.ts.map +1 -1
- package/packages/gateway/dist/agents/catalogue-package.js +1 -1
- package/packages/gateway/dist/agents/catalogue-package.js.map +1 -1
- package/packages/gateway/dist/agents/platform-catalogue.d.ts +6 -6
- package/packages/gateway/dist/agents/platform-catalogue.d.ts.map +1 -1
- package/packages/gateway/dist/agents/platform-catalogue.js +5 -5
- package/packages/gateway/dist/agents/platform-catalogue.js.map +1 -1
- package/packages/gateway/dist/browser-host.js +1 -1
- package/packages/gateway/dist/browser-host.js.map +1 -1
- package/packages/gateway/dist/missions/chrome-scope.d.ts +10 -10
- package/packages/gateway/dist/missions/chrome-scope.d.ts.map +1 -1
- package/packages/gateway/dist/missions/chrome-scope.js +20 -20
- package/packages/gateway/dist/missions/chrome-scope.js.map +1 -1
- package/packages/gateway/dist/missions/execute.d.ts +2 -2
- package/packages/gateway/dist/missions/execute.d.ts.map +1 -1
- package/packages/gateway/dist/missions/execute.js +11 -11
- package/packages/gateway/dist/missions/execute.js.map +1 -1
- package/packages/gateway/dist/missions/reminders.d.ts +2 -2
- package/packages/gateway/dist/missions/reminders.d.ts.map +1 -1
- package/packages/gateway/dist/missions/reminders.js +5 -5
- package/packages/gateway/dist/missions/reminders.js.map +1 -1
- package/packages/gateway/dist/owner-notify.js +1 -1
- package/packages/gateway/dist/owner-notify.js.map +1 -1
- package/packages/gateway/dist/plugins/npm.d.ts +9 -2
- package/packages/gateway/dist/plugins/npm.d.ts.map +1 -1
- package/packages/gateway/dist/plugins/npm.js +29 -6
- package/packages/gateway/dist/plugins/npm.js.map +1 -1
- package/packages/gateway/dist/plugins/stage.d.ts.map +1 -1
- package/packages/gateway/dist/plugins/stage.js +2 -2
- package/packages/gateway/dist/plugins/stage.js.map +1 -1
- package/packages/gateway/dist/serve.js +1 -1
- package/packages/gateway/dist/serve.js.map +1 -1
- package/packages/gateway/dist/surfaces/browser-cards.d.ts +1 -1
- package/packages/gateway/dist/surfaces/browser-cards.js +1 -1
- package/packages/gateway/dist/system-context.d.ts +11 -0
- package/packages/gateway/dist/system-context.d.ts.map +1 -1
- package/packages/gateway/dist/system-context.js +42 -1
- package/packages/gateway/dist/system-context.js.map +1 -1
- package/packages/gateway/dist/telegram/approvals.js +1 -1
- package/packages/gateway/dist/telegram/approvals.js.map +1 -1
- package/packages/gateway/dist/telegram/browser-view.js +1 -1
- package/packages/gateway/dist/telegram/browser-view.js.map +1 -1
- package/packages/gateway/dist/web/api-routes.js +6 -6
- package/packages/gateway/dist/web/api-routes.js.map +1 -1
- package/packages/gateway/dist/web/approval-ask.js +1 -1
- package/packages/gateway/dist/web/extension.d.ts +6 -0
- package/packages/gateway/dist/web/extension.d.ts.map +1 -1
- package/packages/gateway/dist/web/extension.js +22 -11
- package/packages/gateway/dist/web/extension.js.map +1 -1
- package/packages/gateway/dist/web/read.d.ts +1 -1
- package/packages/gateway/dist/web/read.d.ts.map +1 -1
- package/packages/gateway/dist/web/server.js +4 -4
- package/packages/gateway/dist/web/server.js.map +1 -1
- package/packages/gateway/dist/web/service.d.ts +6 -1
- package/packages/gateway/dist/web/service.d.ts.map +1 -1
- package/packages/gateway/dist/web/service.js +10 -1
- package/packages/gateway/dist/web/service.js.map +1 -1
- package/packages/gateway/dist/web/skills.d.ts.map +1 -1
- package/packages/gateway/dist/web/skills.js +2 -1
- package/packages/gateway/dist/web/skills.js.map +1 -1
- package/packages/gateway/dist/web/write.d.ts +1 -1
- package/packages/gateway/dist/web/write.js +1 -1
- package/packages/install/dist/.tsbuildinfo +1 -1
- package/packages/install/dist/app-layout.d.ts +30 -1
- package/packages/install/dist/app-layout.d.ts.map +1 -1
- package/packages/install/dist/app-layout.js +61 -10
- package/packages/install/dist/app-layout.js.map +1 -1
- package/packages/install/dist/cloudflared.js +2 -2
- package/packages/install/dist/cloudflared.js.map +1 -1
- package/packages/install/dist/environment.d.ts +40 -1
- package/packages/install/dist/environment.d.ts.map +1 -1
- package/packages/install/dist/environment.js +158 -12
- package/packages/install/dist/environment.js.map +1 -1
- package/packages/install/dist/launcher.d.ts.map +1 -1
- package/packages/install/dist/launcher.js +257 -50
- package/packages/install/dist/launcher.js.map +1 -1
- package/packages/install/dist/postgres-check.js +1 -1
- package/packages/install/dist/postgres-check.js.map +1 -1
- package/packages/install/dist/product-uninstall.d.ts +14 -0
- package/packages/install/dist/product-uninstall.d.ts.map +1 -1
- package/packages/install/dist/product-uninstall.js +10 -0
- package/packages/install/dist/product-uninstall.js.map +1 -1
- package/packages/install/dist/runtime-info.d.ts.map +1 -1
- package/packages/install/dist/runtime-info.js +4 -1
- package/packages/install/dist/runtime-info.js.map +1 -1
- package/packages/install/dist/supervisor.d.ts +60 -3
- package/packages/install/dist/supervisor.d.ts.map +1 -1
- package/packages/install/dist/supervisor.js +173 -17
- package/packages/install/dist/supervisor.js.map +1 -1
- package/packages/install/dist/uninstall.d.ts +29 -3
- package/packages/install/dist/uninstall.d.ts.map +1 -1
- package/packages/install/dist/uninstall.js +135 -27
- package/packages/install/dist/uninstall.js.map +1 -1
- package/packages/install/dist/upgrade.d.ts +16 -4
- package/packages/install/dist/upgrade.d.ts.map +1 -1
- package/packages/install/dist/upgrade.js +50 -13
- package/packages/install/dist/upgrade.js.map +1 -1
- package/packages/install/dist/windows-install.d.ts +102 -0
- package/packages/install/dist/windows-install.d.ts.map +1 -0
- package/packages/install/dist/windows-install.js +223 -0
- package/packages/install/dist/windows-install.js.map +1 -0
- package/packages/install/dist/windows-setup.d.ts +107 -0
- package/packages/install/dist/windows-setup.d.ts.map +1 -0
- package/packages/install/dist/windows-setup.js +700 -0
- package/packages/install/dist/windows-setup.js.map +1 -0
- package/packages/install/dist/windows-task.d.ts +49 -0
- package/packages/install/dist/windows-task.d.ts.map +1 -0
- package/packages/install/dist/windows-task.js +167 -0
- package/packages/install/dist/windows-task.js.map +1 -0
- package/packages/runtime/dist/.tsbuildinfo +1 -1
- package/packages/runtime/dist/codex-direct.d.ts +1 -1
- package/packages/runtime/dist/codex-direct.js +1 -1
- package/packages/runtime/dist/openai.d.ts +11 -0
- package/packages/runtime/dist/openai.d.ts.map +1 -1
- package/packages/runtime/dist/openai.js +36 -3
- package/packages/runtime/dist/openai.js.map +1 -1
- package/packages/tools/artifacts/dist/.tsbuildinfo +1 -1
- package/packages/tools/artifacts/dist/tools/write.js +3 -3
- package/packages/tools/artifacts/dist/tools/write.js.map +1 -1
- package/packages/tools/browser/dist/.tsbuildinfo +1 -1
- package/packages/tools/browser/dist/availability.d.ts.map +1 -1
- package/packages/tools/browser/dist/availability.js +1 -0
- package/packages/tools/browser/dist/availability.js.map +1 -1
- package/packages/tools/browser/dist/brand.d.ts +19 -0
- package/packages/tools/browser/dist/brand.d.ts.map +1 -0
- package/packages/tools/browser/dist/brand.js +31 -0
- package/packages/tools/browser/dist/brand.js.map +1 -0
- package/packages/tools/browser/dist/controller.d.ts +2 -2
- package/packages/tools/browser/dist/controller.d.ts.map +1 -1
- package/packages/tools/browser/dist/controller.js +16 -7
- package/packages/tools/browser/dist/controller.js.map +1 -1
- package/packages/tools/browser/dist/downloads.js +1 -1
- package/packages/tools/browser/dist/downloads.js.map +1 -1
- package/packages/tools/browser/dist/extension.d.ts +3 -1
- package/packages/tools/browser/dist/extension.d.ts.map +1 -1
- package/packages/tools/browser/dist/extension.js +4 -4
- package/packages/tools/browser/dist/extension.js.map +1 -1
- package/packages/tools/browser/dist/index.d.ts +3 -2
- package/packages/tools/browser/dist/index.d.ts.map +1 -1
- package/packages/tools/browser/dist/index.js +7 -6
- package/packages/tools/browser/dist/index.js.map +1 -1
- package/packages/tools/browser/dist/routes.d.ts +12 -1
- package/packages/tools/browser/dist/routes.d.ts.map +1 -1
- package/packages/tools/browser/dist/routes.js +31 -14
- package/packages/tools/browser/dist/routes.js.map +1 -1
- package/packages/tools/browser/dist/service.d.ts +2 -0
- package/packages/tools/browser/dist/service.d.ts.map +1 -1
- package/packages/tools/browser/dist/service.js +6 -6
- package/packages/tools/browser/dist/service.js.map +1 -1
- package/packages/tools/browser/dist/telemetry.d.ts +2 -2
- package/packages/tools/browser/dist/telemetry.js +2 -2
- package/packages/tools/browser/dist/telemetry.js.map +1 -1
- package/packages/tools/browser/dist/types.js +1 -1
- package/packages/tools/browser/dist/types.js.map +1 -1
- package/packages/tools/host/dist/.tsbuildinfo +1 -1
- package/packages/tools/host/dist/index.d.ts +2 -1
- package/packages/tools/host/dist/index.d.ts.map +1 -1
- package/packages/tools/host/dist/index.js +11 -2
- package/packages/tools/host/dist/index.js.map +1 -1
- package/packages/tools/host/dist/process.d.ts +58 -1
- package/packages/tools/host/dist/process.d.ts.map +1 -1
- package/packages/tools/host/dist/process.js +229 -15
- package/packages/tools/host/dist/process.js.map +1 -1
- package/packages/tools/host/dist/service.d.ts +2 -0
- package/packages/tools/host/dist/service.d.ts.map +1 -1
- package/packages/tools/host/dist/service.js +8 -6
- package/packages/tools/host/dist/service.js.map +1 -1
- package/packages/tools/host/dist/skill-run.d.ts +10 -0
- package/packages/tools/host/dist/skill-run.d.ts.map +1 -1
- package/packages/tools/host/dist/skill-run.js +14 -0
- package/packages/tools/host/dist/skill-run.js.map +1 -1
- package/packages/web/dist/assets/index-DnZhfnM7.js +155 -0
- package/packages/web/dist/assets/{lottie_light-twPed1FM.js → lottie_light-CGUtDt_b.js} +1 -1
- package/packages/web/dist/build.json +1 -1
- package/packages/web/dist/index.html +1 -1
- package/packages/web/dist/precache.json +3 -3
- package/packages/web/dist/assets/index-DgpPl0TR.js +0 -155
|
@@ -0,0 +1,700 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* The Windows setup's own program (apps/windows/buddi.iss runs it with the
|
|
4
|
+
* bundle's node): the counterpart of scripts/install.sh, in TypeScript
|
|
5
|
+
* because Inno Setup's Pascal is no place for a backup, a lock and a
|
|
6
|
+
* rollback. Two commands:
|
|
7
|
+
*
|
|
8
|
+
* windows-setup.js install --bundle <dir> --data <dir> --bin <dir> [--uninstaller <exe>]
|
|
9
|
+
* [--no-start] [--skip-backup] [--log <file>] [--result <file>]
|
|
10
|
+
* windows-setup.js uninstall --data <dir> [--keep-data] [--log <file>] [--summary <file>] [--result <file>]
|
|
11
|
+
*
|
|
12
|
+
* `install` puts the unpacked bundle (scripts/release/windows-bundle.sh) where
|
|
13
|
+
* the Linux install puts its own, under the data directory (windows-install.ts):
|
|
14
|
+
* `node\` (the runtime, swapped only when it holds another Node),
|
|
15
|
+
* `releases\buddi-<v>\` with `current` and `previous` junctions, and
|
|
16
|
+
* `buddi.cmd` in the setup's bin folder. Whenever there is data already, the
|
|
17
|
+
* buddi that serves it takes a backup first, then stops (Windows will not
|
|
18
|
+
* replace files a running program holds), and the switch is recorded the way
|
|
19
|
+
* buddi's own upgrade records it, so a failed migration says how to get back.
|
|
20
|
+
* A new release that does not start puts the old one back. An npm install
|
|
21
|
+
* (`npm install -g @withbuddi/buddi`) serving the same data folder is moved
|
|
22
|
+
* over and then removed; one serving another folder is left alone.
|
|
23
|
+
*
|
|
24
|
+
* `uninstall` is `buddi uninstall --yes` run from the setup's uninstaller (with
|
|
25
|
+
* the node it copied out of the data folder), its words kept for the
|
|
26
|
+
* uninstaller to show.
|
|
27
|
+
*
|
|
28
|
+
* The setup cannot read a console it hides, so everything said goes to the
|
|
29
|
+
* log, and the exit status to the result file as well (conhost, which keeps
|
|
30
|
+
* the console hidden, does not pass it on).
|
|
31
|
+
*/
|
|
32
|
+
import { spawn } from 'node:child_process';
|
|
33
|
+
import { appendFileSync, existsSync, readFileSync, readdirSync, realpathSync, statSync, writeFileSync } from 'node:fs';
|
|
34
|
+
import { cp, mkdir, readFile, rename, rm, unlink, writeFile } from 'node:fs/promises';
|
|
35
|
+
import { request } from 'node:http';
|
|
36
|
+
import os from 'node:os';
|
|
37
|
+
import path from 'node:path';
|
|
38
|
+
import { fileURLToPath } from 'node:url';
|
|
39
|
+
import { currentLauncher, pointAt, pruneReleases, releaseDir, releaseRoot, takeReleasesLock } from './app-layout.js';
|
|
40
|
+
import { KEPT_FOR_REINSTALL_FILE, keptForReinstall, launchAgentLabel, lockHolder } from './environment.js';
|
|
41
|
+
import { answeredBySupervisor, supervisorSocket } from './supervisor.js';
|
|
42
|
+
import { SETUP_UNINSTALL_VAR, buildWindowsCommand, insideFolder, windowsBundledNode, windowsCommandOwnedBy, windowsInstallEnvironment, windowsInstallPath } from './windows-install.js';
|
|
43
|
+
const win = path.win32;
|
|
44
|
+
const VERSION_RE = /^[0-9]+\.[0-9]+\.[0-9]+(-[0-9A-Za-z.-]+)?$/;
|
|
45
|
+
/** The command line the setup passes. Anything else is refused. */
|
|
46
|
+
export function parseSetupArgs(argv) {
|
|
47
|
+
const [command, ...rest] = argv;
|
|
48
|
+
if (command !== 'install' && command !== 'uninstall')
|
|
49
|
+
throw new Error(`usage: windows-setup.js install|uninstall …, not ${JSON.stringify(command ?? '')}`);
|
|
50
|
+
const out = { command, noStart: false, skipBackup: false, keepData: false };
|
|
51
|
+
const valued = { '--bundle': 'bundle', '--data': 'data', '--bin': 'bin', '--uninstaller': 'uninstaller', '--log': 'log', '--result': 'result', '--summary': 'summary' };
|
|
52
|
+
for (let i = 0; i < rest.length; i++) {
|
|
53
|
+
const arg = rest[i];
|
|
54
|
+
if (arg === '--no-start')
|
|
55
|
+
out.noStart = true;
|
|
56
|
+
else if (arg === '--skip-backup')
|
|
57
|
+
out.skipBackup = true;
|
|
58
|
+
else if (arg === '--keep-data')
|
|
59
|
+
out.keepData = true;
|
|
60
|
+
else if (arg in valued) {
|
|
61
|
+
const value = rest[++i];
|
|
62
|
+
if (value === undefined || value === '')
|
|
63
|
+
throw new Error(`${arg} needs a value`);
|
|
64
|
+
out[valued[arg]] = value;
|
|
65
|
+
}
|
|
66
|
+
else
|
|
67
|
+
throw new Error(`unknown option ${arg}`);
|
|
68
|
+
}
|
|
69
|
+
if (out.data === undefined)
|
|
70
|
+
throw new Error('--data is required');
|
|
71
|
+
if (command === 'install' && (out.bundle === undefined || out.bin === undefined))
|
|
72
|
+
throw new Error('install needs --bundle and --bin');
|
|
73
|
+
return out;
|
|
74
|
+
}
|
|
75
|
+
export function setupPlan(f) {
|
|
76
|
+
const old = f.oldRoot !== undefined ? 'release' : f.npm?.serves === true ? 'npm' : 'none';
|
|
77
|
+
const from = f.oldVersion ?? (old === 'npm' ? f.npm?.version : undefined);
|
|
78
|
+
const kind = f.sameRelease ? 'reinstall' : f.oldRoot !== undefined ? 'upgrade' : f.existing ? 'move' : 'fresh';
|
|
79
|
+
let backup = 'none';
|
|
80
|
+
if (f.existing && !f.sameRelease)
|
|
81
|
+
backup = f.skipBackup ? 'skipped' : old !== 'none' ? 'take' : f.kept ? 'kept' : 'refuse';
|
|
82
|
+
return { kind, backup, old, ...(from === undefined ? {} : { from }) };
|
|
83
|
+
}
|
|
84
|
+
/** The newest backup archive in any of these folders (the uninstall keeps its last one in the data folder's backups, or in buddi-backups when the dashboard took it). */
|
|
85
|
+
export function lastKeptBackup(dirs, list = dir => {
|
|
86
|
+
try {
|
|
87
|
+
return readdirSync(dir).map(name => ({ name, mtimeMs: statSync(path.join(dir, name)).mtimeMs }));
|
|
88
|
+
}
|
|
89
|
+
catch {
|
|
90
|
+
return [];
|
|
91
|
+
}
|
|
92
|
+
}) {
|
|
93
|
+
let best;
|
|
94
|
+
for (const dir of dirs) {
|
|
95
|
+
const entries = list(dir);
|
|
96
|
+
const name = newestArchive(entries);
|
|
97
|
+
const entry = entries.find(e => e.name === name);
|
|
98
|
+
if (name !== undefined && entry !== undefined && (best === undefined || entry.mtimeMs > best.mtimeMs))
|
|
99
|
+
best = { file: path.join(dir, name), mtimeMs: entry.mtimeMs };
|
|
100
|
+
}
|
|
101
|
+
return best?.file;
|
|
102
|
+
}
|
|
103
|
+
/** The newest archive in `<data>\backups` (not an envelope or a passphrase file). */
|
|
104
|
+
export function newestArchive(names) {
|
|
105
|
+
const archives = names.filter(entry => entry.name.startsWith('buddi-backup-') && !/\.(json|txt)$/i.test(entry.name));
|
|
106
|
+
archives.sort((a, b) => b.mtimeMs - a.mtimeMs);
|
|
107
|
+
return archives[0]?.name;
|
|
108
|
+
}
|
|
109
|
+
/** Does npm's `buddi.cmd` shim run `@withbuddi/buddi` from beside it? */
|
|
110
|
+
export function npmShimRunsBuddi(text) {
|
|
111
|
+
return text !== undefined && /node_modules[\\/]@withbuddi[\\/]buddi[\\/]/i.test(text);
|
|
112
|
+
}
|
|
113
|
+
/** The lines of `buddi uninstall`'s output the owner must keep: where the backup is, and its passphrase. */
|
|
114
|
+
export function uninstallSummary(output) {
|
|
115
|
+
return output.split(/\r?\n/).map(line => line.trim())
|
|
116
|
+
.filter(line => /^(The backup is |A copy is |Your backup passphrase|It is also in |buddi is removed)/.test(line));
|
|
117
|
+
}
|
|
118
|
+
/* ------------------------------------------------------------------ *
|
|
119
|
+
* The effects
|
|
120
|
+
* ------------------------------------------------------------------ */
|
|
121
|
+
export class Said {
|
|
122
|
+
file;
|
|
123
|
+
lines = [];
|
|
124
|
+
constructor(file) {
|
|
125
|
+
this.file = file;
|
|
126
|
+
// A byte order mark, so the setup reads the log as UTF-8 (C:\Users\Zoë).
|
|
127
|
+
if (file !== undefined) {
|
|
128
|
+
try {
|
|
129
|
+
writeFileSync(file, '\ufeff');
|
|
130
|
+
}
|
|
131
|
+
catch { /* the log is a courtesy */ }
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
say(line) {
|
|
135
|
+
this.lines.push(line);
|
|
136
|
+
process.stdout.write(`${line}\n`);
|
|
137
|
+
this.record(line);
|
|
138
|
+
}
|
|
139
|
+
/** Into the log only: what helps a report, not the owner (a stack). */
|
|
140
|
+
record(line) {
|
|
141
|
+
if (this.file !== undefined) {
|
|
142
|
+
try {
|
|
143
|
+
appendFileSync(this.file, `${line}\r\n`);
|
|
144
|
+
}
|
|
145
|
+
catch { /* as above */ }
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
export class SetupError extends Error {
|
|
150
|
+
}
|
|
151
|
+
function runProgram(command, args, env, opts = {}) {
|
|
152
|
+
return new Promise(resolve => {
|
|
153
|
+
let output = '';
|
|
154
|
+
const child = spawn(command, args, { env, cwd: os.homedir(), windowsHide: true, stdio: ['ignore', 'pipe', 'pipe'], ...(opts.verbatim ? { windowsVerbatimArguments: true } : {}) });
|
|
155
|
+
const timer = setTimeout(() => { child.kill(); }, opts.timeoutMs ?? 10 * 60_000);
|
|
156
|
+
child.stdout.setEncoding('utf8').on('data', chunk => { output += chunk; });
|
|
157
|
+
child.stderr.setEncoding('utf8').on('data', chunk => { output += chunk; });
|
|
158
|
+
child.once('error', error => { clearTimeout(timer); resolve({ code: 127, output: output + error.message }); });
|
|
159
|
+
child.once('close', code => { clearTimeout(timer); resolve({ code: code ?? 1, output }); });
|
|
160
|
+
});
|
|
161
|
+
}
|
|
162
|
+
/** Ask this data folder's supervisor, as the launcher does (its pipe, its secret). */
|
|
163
|
+
function askSupervisor(data, method, route) {
|
|
164
|
+
return new Promise((resolve, reject) => {
|
|
165
|
+
const req = request({ socketPath: supervisorSocket(data), path: route, method, headers: { host: 'localhost' }, timeout: 25_000 }, res => {
|
|
166
|
+
if (!answeredBySupervisor(data, res.headers)) {
|
|
167
|
+
res.resume();
|
|
168
|
+
reject(new Error('not this installation\'s supervisor'));
|
|
169
|
+
return;
|
|
170
|
+
}
|
|
171
|
+
let text = '';
|
|
172
|
+
res.setEncoding('utf8');
|
|
173
|
+
res.on('data', chunk => { text += chunk; });
|
|
174
|
+
res.on('end', () => {
|
|
175
|
+
if (res.statusCode !== 200 && res.statusCode !== 202) {
|
|
176
|
+
const refusal = (() => { try {
|
|
177
|
+
return JSON.parse(text).error;
|
|
178
|
+
}
|
|
179
|
+
catch {
|
|
180
|
+
return undefined;
|
|
181
|
+
} })();
|
|
182
|
+
reject(new Error(refusal ?? `the supervisor answered ${res.statusCode}`));
|
|
183
|
+
return;
|
|
184
|
+
}
|
|
185
|
+
try {
|
|
186
|
+
resolve(JSON.parse(text));
|
|
187
|
+
}
|
|
188
|
+
catch {
|
|
189
|
+
reject(new Error('the supervisor answered with something that is not JSON'));
|
|
190
|
+
}
|
|
191
|
+
});
|
|
192
|
+
});
|
|
193
|
+
req.once('timeout', () => req.destroy(new Error('the supervisor did not answer')));
|
|
194
|
+
req.once('error', reject);
|
|
195
|
+
req.end();
|
|
196
|
+
});
|
|
197
|
+
}
|
|
198
|
+
/** Does the pid on the first line of this file (supervisor.lock, postmaster.pid) name a live process? */
|
|
199
|
+
function pidAlive(file) {
|
|
200
|
+
let pid;
|
|
201
|
+
try {
|
|
202
|
+
pid = Number(readFileSync(file, 'utf8').split('\n')[0].trim());
|
|
203
|
+
}
|
|
204
|
+
catch {
|
|
205
|
+
return false;
|
|
206
|
+
}
|
|
207
|
+
if (!Number.isInteger(pid) || pid <= 0)
|
|
208
|
+
return false;
|
|
209
|
+
try {
|
|
210
|
+
process.kill(pid, 0);
|
|
211
|
+
return true;
|
|
212
|
+
}
|
|
213
|
+
catch (error) {
|
|
214
|
+
return error.code === 'EPERM';
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
const sleep = (ms) => new Promise(resolve => setTimeout(resolve, ms));
|
|
218
|
+
/** Stop the supervisor on its pipe (never a kill: that skips the database's shutdown), and wait for it and its Postgres. */
|
|
219
|
+
async function stopSupervisor(data) {
|
|
220
|
+
if (lockHolder(data) === undefined)
|
|
221
|
+
return;
|
|
222
|
+
await askSupervisor(data, 'POST', '/exit');
|
|
223
|
+
for (let waited = 0; lockHolder(data) !== undefined || pidAlive(path.join(data, 'postgres', 'postmaster.pid')); waited += 250) {
|
|
224
|
+
if (waited >= 120_000)
|
|
225
|
+
throw new SetupError('buddi did not stop within two minutes, so nothing was changed.');
|
|
226
|
+
await sleep(250);
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
/**
|
|
230
|
+
* A rename, retried while Windows says the folder is busy (an antivirus
|
|
231
|
+
* scanning what was just unpacked holds files for a moment), else a copy:
|
|
232
|
+
* where the bundle sits on another drive, or the folder stays held.
|
|
233
|
+
*/
|
|
234
|
+
async function move(from, to, attempts = 8) {
|
|
235
|
+
for (let attempt = 1;; attempt++) {
|
|
236
|
+
try {
|
|
237
|
+
await rename(from, to);
|
|
238
|
+
return;
|
|
239
|
+
}
|
|
240
|
+
catch (error) {
|
|
241
|
+
const code = error.code;
|
|
242
|
+
if (code === 'EXDEV' || ((code === 'EPERM' || code === 'EBUSY' || code === 'EACCES') && attempt >= attempts))
|
|
243
|
+
break;
|
|
244
|
+
if (code !== 'EPERM' && code !== 'EBUSY' && code !== 'EACCES')
|
|
245
|
+
throw error;
|
|
246
|
+
await sleep(250 * attempt);
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
await rm(to, { recursive: true, force: true, maxRetries: 10, retryDelay: 250 });
|
|
250
|
+
await cp(from, to, { recursive: true, verbatimSymlinks: true });
|
|
251
|
+
await rm(from, { recursive: true, force: true, maxRetries: 10, retryDelay: 250 }).catch(() => { });
|
|
252
|
+
}
|
|
253
|
+
const real = (file) => { try {
|
|
254
|
+
return realpathSync(file);
|
|
255
|
+
}
|
|
256
|
+
catch {
|
|
257
|
+
return undefined;
|
|
258
|
+
} };
|
|
259
|
+
const versionOf = (root) => {
|
|
260
|
+
try {
|
|
261
|
+
return JSON.parse(readFileSync(path.join(root, 'package.json'), 'utf8')).version;
|
|
262
|
+
}
|
|
263
|
+
catch {
|
|
264
|
+
return undefined;
|
|
265
|
+
}
|
|
266
|
+
};
|
|
267
|
+
const realDeps = {
|
|
268
|
+
status: data => askSupervisor(data, 'GET', '/status').catch(() => undefined),
|
|
269
|
+
stop: stopSupervisor,
|
|
270
|
+
runRelease: (data, root, argv) => runProgram(windowsBundledNode(data), [path.join(root, 'packages', 'install', 'dist', 'launcher.js'), ...argv], { ...process.env, ...windowsInstallEnvironment(data), PATH: windowsInstallPath(data, process.env.PATH ?? process.env.Path), Path: undefined }, { timeoutMs: 5 * 60_000 }),
|
|
271
|
+
runNpm: (cmd, data, argv) => runProgram(process.env.ComSpec ?? 'cmd.exe', ['/d', '/s', '/c', `""${cmd}" ${argv.join(' ')}"`], { ...process.env, BUDDI_DATA_DIR: data }, { verbatim: true }),
|
|
272
|
+
pathDirs: () => (process.env.Path ?? process.env.PATH ?? '').split(';').filter(Boolean),
|
|
273
|
+
otherTaskScripts: async (data) => {
|
|
274
|
+
const own = launchAgentLabel(data).toLowerCase();
|
|
275
|
+
const listed = await runProgram('schtasks.exe', ['/Query', '/FO', 'CSV', '/NH'], process.env);
|
|
276
|
+
const names = [...new Set(listed.output.split(/\r?\n/).map(line => line.split(',')[0]?.replace(/"/g, '').trim() ?? '')
|
|
277
|
+
.filter(name => /\\com\.buddi\.install\.[0-9a-f]+$/i.test(name) && !name.toLowerCase().endsWith(own)))];
|
|
278
|
+
const scripts = [];
|
|
279
|
+
for (const name of names) {
|
|
280
|
+
const xml = await runProgram('schtasks.exe', ['/Query', '/TN', name, '/XML'], process.env);
|
|
281
|
+
const script = /call "(.+?)"|call "(.+?)"/.exec(xml.output);
|
|
282
|
+
const file = script?.[1] ?? script?.[2];
|
|
283
|
+
if (file !== undefined) {
|
|
284
|
+
try {
|
|
285
|
+
scripts.push(readFileSync(file, 'utf8'));
|
|
286
|
+
}
|
|
287
|
+
catch {
|
|
288
|
+
scripts.push('');
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
return scripts;
|
|
293
|
+
},
|
|
294
|
+
};
|
|
295
|
+
/** Does any of these task scripts run something from inside this package folder? */
|
|
296
|
+
export function scriptsUse(scripts, pkg) {
|
|
297
|
+
const needle = pkg.toLowerCase();
|
|
298
|
+
return scripts.some(text => text.toLowerCase().includes(needle));
|
|
299
|
+
}
|
|
300
|
+
export async function install(args, said, deps = realDeps) {
|
|
301
|
+
const say = (line) => said.say(line);
|
|
302
|
+
const bundle = path.resolve(args.bundle);
|
|
303
|
+
const bin = path.resolve(args.bin);
|
|
304
|
+
const runtime = path.join(bundle, 'runtime');
|
|
305
|
+
const release = path.join(bundle, 'release');
|
|
306
|
+
if (!existsSync(path.join(runtime, 'node.exe')) || !existsSync(path.join(releaseRoot(release), 'packages', 'install', 'dist', 'launcher.js'))) {
|
|
307
|
+
throw new SetupError(`${bundle} is not a buddi Windows bundle. Nothing was changed.`);
|
|
308
|
+
}
|
|
309
|
+
const newVersion = readFileSync(path.join(bundle, 'VERSION'), 'utf8').trim();
|
|
310
|
+
if (!VERSION_RE.test(newVersion))
|
|
311
|
+
throw new SetupError(`the bundle names no buddi version ("${newVersion}"). Nothing was changed.`);
|
|
312
|
+
say(`buddi ${newVersion}, Node ${readFileSync(path.join(runtime, 'VERSION'), 'utf8').trim()}`);
|
|
313
|
+
/* Where. One spelling of the data folder: the one installation.json was given, when it is the same folder. */
|
|
314
|
+
let data = path.resolve(args.data);
|
|
315
|
+
await mkdir(data, { recursive: true });
|
|
316
|
+
const named = (() => { try {
|
|
317
|
+
return JSON.parse(readFileSync(path.join(data, 'installation.json'), 'utf8')).dataDir;
|
|
318
|
+
}
|
|
319
|
+
catch {
|
|
320
|
+
return undefined;
|
|
321
|
+
} })();
|
|
322
|
+
if (typeof named === 'string' && named !== data && real(named)?.toLowerCase() === real(data)?.toLowerCase())
|
|
323
|
+
data = named;
|
|
324
|
+
const releases = path.join(data, 'releases');
|
|
325
|
+
const nodeDir = path.join(data, 'node');
|
|
326
|
+
const command = path.join(bin, 'buddi.cmd');
|
|
327
|
+
/* What is there now. */
|
|
328
|
+
const currentLink = path.join(releases, 'current');
|
|
329
|
+
const previousLink = path.join(releases, 'previous');
|
|
330
|
+
const oldRoot = existsSync(path.join(currentLink, 'packages', 'install', 'dist', 'launcher.js')) ? real(currentLink) : undefined;
|
|
331
|
+
const oldVersion = oldRoot === undefined ? undefined : versionOf(oldRoot);
|
|
332
|
+
const oldPrev = existsSync(previousLink) ? real(previousLink) : undefined;
|
|
333
|
+
const existing = existsSync(path.join(data, 'installation.json'));
|
|
334
|
+
const newDir = releaseDir(releases, newVersion);
|
|
335
|
+
const newRoot = releaseRoot(newDir);
|
|
336
|
+
const sameRelease = oldRoot !== undefined && real(newRoot)?.toLowerCase() === oldRoot.toLowerCase();
|
|
337
|
+
/* npm's buddi on PATH (`npm install -g @withbuddi/buddi`), and whether it serves this data folder. */
|
|
338
|
+
let npm;
|
|
339
|
+
for (const dir of deps.pathDirs()) {
|
|
340
|
+
const cmd = path.join(dir, 'buddi.cmd');
|
|
341
|
+
if (insideFolder(cmd, bin) || !existsSync(cmd))
|
|
342
|
+
continue;
|
|
343
|
+
const text = (() => { try {
|
|
344
|
+
return readFileSync(cmd, 'utf8');
|
|
345
|
+
}
|
|
346
|
+
catch {
|
|
347
|
+
return undefined;
|
|
348
|
+
} })();
|
|
349
|
+
if (windowsCommandOwnedBy(text, data) || !npmShimRunsBuddi(text))
|
|
350
|
+
continue;
|
|
351
|
+
const pkg = path.join(dir, 'node_modules', '@withbuddi', 'buddi');
|
|
352
|
+
if (!existsSync(path.join(pkg, 'package.json')))
|
|
353
|
+
continue;
|
|
354
|
+
let serves = false;
|
|
355
|
+
if (existing && oldRoot === undefined) {
|
|
356
|
+
const script = (() => { try {
|
|
357
|
+
return readFileSync(path.join(data, 'service', 'supervise.cmd'), 'utf8');
|
|
358
|
+
}
|
|
359
|
+
catch {
|
|
360
|
+
return '';
|
|
361
|
+
} })();
|
|
362
|
+
const status = await deps.status(data);
|
|
363
|
+
serves = scriptsUse([script], pkg) || (real(pkg) !== undefined && scriptsUse([script], real(pkg)))
|
|
364
|
+
|| (status?.installRoot !== undefined && insideFolder(status.installRoot, real(pkg) ?? pkg));
|
|
365
|
+
}
|
|
366
|
+
npm = { cmd, prefix: dir, pkg, ...(versionOf(pkg) === undefined ? {} : { version: versionOf(pkg) }), serves };
|
|
367
|
+
break;
|
|
368
|
+
}
|
|
369
|
+
const kept = existing && oldRoot === undefined && keptForReinstall(data);
|
|
370
|
+
const plan = setupPlan({ existing, kept, ...(oldRoot === undefined ? {} : { oldRoot }), ...(oldVersion === undefined ? {} : { oldVersion }), newVersion, sameRelease, ...(npm === undefined ? {} : { npm: { serves: npm.serves, ...(npm.version === undefined ? {} : { version: npm.version }) } }), skipBackup: args.skipBackup });
|
|
371
|
+
if (plan.kind === 'reinstall')
|
|
372
|
+
say(`buddi ${newVersion} is installed already; refreshing the runtime, the command and the service.`);
|
|
373
|
+
else if (plan.kind === 'upgrade')
|
|
374
|
+
say(`Upgrading buddi ${oldVersion ?? ''} to ${newVersion}.`.replace(' ', ' '));
|
|
375
|
+
else if (plan.kind === 'move' && plan.backup === 'kept')
|
|
376
|
+
say(`Reinstalling buddi on the data kept in ${data}.`);
|
|
377
|
+
else if (plan.kind === 'move')
|
|
378
|
+
say(`Moving the buddi in ${data} onto this install; its data stays.`);
|
|
379
|
+
/** The buddi serving this folder now, as a program: what takes the backup, and what a rollback starts again. */
|
|
380
|
+
const oldBuddi = (argv) => plan.old === 'release'
|
|
381
|
+
? deps.runRelease(data, oldRoot, argv)
|
|
382
|
+
: deps.runNpm(npm.cmd, data, argv);
|
|
383
|
+
/* The backup, before anything changes. */
|
|
384
|
+
let archive;
|
|
385
|
+
if (plan.backup === 'refuse') {
|
|
386
|
+
throw new SetupError(`${data} holds a buddi installation, but no buddi here can back it up first (no release under ${releases}, no npm copy serving it). Nothing was changed. To go on without a backup, run the setup with /SKIPBACKUP.`);
|
|
387
|
+
}
|
|
388
|
+
if (plan.backup === 'skipped')
|
|
389
|
+
say(`No backup of ${data} before the switch (asked for).`);
|
|
390
|
+
if (plan.backup === 'kept') {
|
|
391
|
+
const last = lastKeptBackup([path.join(data, 'backups'), path.join(os.homedir(), 'buddi-backups')]);
|
|
392
|
+
say(`No new backup first: the buddi that wrote this data was removed, and only it could back up its database as it is. ${last !== undefined ? `The last backup it took is ${last}.` : 'It left no backup in its backups folder or in buddi-backups.'} The install leaves the data folder as it is; buddi ${newVersion} starts on it.`);
|
|
393
|
+
}
|
|
394
|
+
if (plan.backup === 'take') {
|
|
395
|
+
if (await deps.status(data) === undefined) {
|
|
396
|
+
say('Starting the installed buddi briefly for the backup.');
|
|
397
|
+
const brief = await oldBuddi(['--no-service', '--no-open']);
|
|
398
|
+
if (brief.code !== 0) {
|
|
399
|
+
say(brief.output.trim());
|
|
400
|
+
throw new SetupError('the installed buddi would not start for the backup, so nothing was changed. To go on without one, run the setup with /SKIPBACKUP.');
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
say('Taking a backup first.');
|
|
404
|
+
const taken = await oldBuddi(['backup', 'create']);
|
|
405
|
+
if (taken.code !== 0) {
|
|
406
|
+
say(taken.output.trim().split(/\r?\n/).slice(-5).join('\n'));
|
|
407
|
+
throw new SetupError('the backup before the switch failed, so nothing was changed.');
|
|
408
|
+
}
|
|
409
|
+
const names = (() => { try {
|
|
410
|
+
return readdirSync(path.join(data, 'backups')).map(name => ({ name, mtimeMs: statSync(path.join(data, 'backups', name)).mtimeMs }));
|
|
411
|
+
}
|
|
412
|
+
catch {
|
|
413
|
+
return [];
|
|
414
|
+
} })();
|
|
415
|
+
const newest = newestArchive(names);
|
|
416
|
+
if (newest !== undefined) {
|
|
417
|
+
archive = path.join(data, 'backups', newest);
|
|
418
|
+
say(`Backup: ${archive}`);
|
|
419
|
+
}
|
|
420
|
+
}
|
|
421
|
+
/* Windows will not replace a runtime or a release that a running buddi holds: the old one stops first. */
|
|
422
|
+
const runtimeChanges = !existsSync(path.join(nodeDir, 'node.exe'))
|
|
423
|
+
|| (() => { try {
|
|
424
|
+
return readFileSync(path.join(nodeDir, 'VERSION'), 'utf8').trim() !== readFileSync(path.join(runtime, 'VERSION'), 'utf8').trim();
|
|
425
|
+
}
|
|
426
|
+
catch {
|
|
427
|
+
return true;
|
|
428
|
+
} })();
|
|
429
|
+
if (!sameRelease || runtimeChanges) {
|
|
430
|
+
try {
|
|
431
|
+
await deps.stop(data);
|
|
432
|
+
}
|
|
433
|
+
catch (error) {
|
|
434
|
+
throw new SetupError(`buddi could not be stopped for the switch (${error.message.replace(/\.$/, '')}). Nothing was changed; run the setup again when it has finished what it is doing.`);
|
|
435
|
+
}
|
|
436
|
+
}
|
|
437
|
+
/* Put it in place, under the releases lock buddi's own upgrade takes too. */
|
|
438
|
+
const unlock = await takeReleasesLock(releases);
|
|
439
|
+
const nodeOld = `${nodeDir}.old`;
|
|
440
|
+
let started = false;
|
|
441
|
+
try {
|
|
442
|
+
// What an earlier setup could not clean up (a scanner held a file): any unpacked bundle but this one. Under the lock, so never a running setup's.
|
|
443
|
+
for (const name of readdirSync(data)) {
|
|
444
|
+
if (name.startsWith('.install-') && !insideFolder(bundle, path.join(data, name)))
|
|
445
|
+
await rm(path.join(data, name), { recursive: true, force: true, maxRetries: 5, retryDelay: 200 }).catch(() => { });
|
|
446
|
+
}
|
|
447
|
+
/*
|
|
448
|
+
* Every change from here is undone, last first, if anything after it
|
|
449
|
+
* fails: the files, the links, the command, the state, and then the buddi
|
|
450
|
+
* that served this folder before is started again.
|
|
451
|
+
*/
|
|
452
|
+
const undo = [];
|
|
453
|
+
try {
|
|
454
|
+
if (!sameRelease) {
|
|
455
|
+
const there = real(newDir);
|
|
456
|
+
const used = there !== undefined && [oldRoot, oldPrev].some(root => root !== undefined && insideFolder(root, there));
|
|
457
|
+
if (!used) {
|
|
458
|
+
await rm(newDir, { recursive: true, force: true, maxRetries: 10, retryDelay: 250 });
|
|
459
|
+
await move(release, newDir);
|
|
460
|
+
undo.push({ what: `the new release ${newDir}`, run: () => rm(newDir, { recursive: true, force: true, maxRetries: 10, retryDelay: 250 }) });
|
|
461
|
+
}
|
|
462
|
+
}
|
|
463
|
+
if (runtimeChanges) {
|
|
464
|
+
/*
|
|
465
|
+
* Copied, never renamed: this program runs on the bundle's node.exe,
|
|
466
|
+
* and Windows will not rename a folder whose program is running. The
|
|
467
|
+
* copy goes beside the old runtime first, so the swap is two renames.
|
|
468
|
+
*/
|
|
469
|
+
const nodeNew = `${nodeDir}.new`;
|
|
470
|
+
await rm(nodeOld, { recursive: true, force: true, maxRetries: 10, retryDelay: 250 });
|
|
471
|
+
await rm(nodeNew, { recursive: true, force: true, maxRetries: 10, retryDelay: 250 });
|
|
472
|
+
await cp(runtime, nodeNew, { recursive: true });
|
|
473
|
+
const hadRuntime = existsSync(nodeDir);
|
|
474
|
+
if (hadRuntime)
|
|
475
|
+
await move(nodeDir, nodeOld);
|
|
476
|
+
undo.push({ what: `the runtime ${nodeDir}`, run: async () => {
|
|
477
|
+
await rm(nodeDir, { recursive: true, force: true, maxRetries: 10, retryDelay: 250 });
|
|
478
|
+
if (hadRuntime)
|
|
479
|
+
await move(nodeOld, nodeDir);
|
|
480
|
+
} });
|
|
481
|
+
await move(nodeNew, nodeDir);
|
|
482
|
+
}
|
|
483
|
+
/* The switch, recorded as buddi's own upgrade records it: the new release's first start finishes it. */
|
|
484
|
+
if (!sameRelease && existing && plan.from !== undefined) {
|
|
485
|
+
const file = path.join(data, 'installation.json');
|
|
486
|
+
const before = await readFile(file, 'utf8');
|
|
487
|
+
const state = JSON.parse(before);
|
|
488
|
+
state.phase = 'upgrading';
|
|
489
|
+
state.upgrade = { from: plan.from, to: newVersion, startedAt: new Date().toISOString(), ...(archive === undefined ? {} : { backup: path.basename(archive) }) };
|
|
490
|
+
undo.push({ what: `the state in ${file}`, run: async () => { await writeFile(`${file}.tmp`, before, { mode: 0o600 }); await rename(`${file}.tmp`, file); } });
|
|
491
|
+
await writeFile(`${file}.tmp`, JSON.stringify(state, null, 2) + '\n', { mode: 0o600 });
|
|
492
|
+
await rename(`${file}.tmp`, file);
|
|
493
|
+
}
|
|
494
|
+
if (!sameRelease) {
|
|
495
|
+
undo.push({ what: `the links in ${releases}`, run: async () => {
|
|
496
|
+
if (oldRoot !== undefined)
|
|
497
|
+
await pointAt(currentLink, oldRoot);
|
|
498
|
+
else
|
|
499
|
+
await unlink(currentLink).catch(() => { });
|
|
500
|
+
if (oldPrev !== undefined)
|
|
501
|
+
await pointAt(previousLink, oldPrev);
|
|
502
|
+
else
|
|
503
|
+
await unlink(previousLink).catch(() => { });
|
|
504
|
+
} });
|
|
505
|
+
if (oldRoot !== undefined)
|
|
506
|
+
await pointAt(previousLink, oldRoot);
|
|
507
|
+
await pointAt(currentLink, newRoot);
|
|
508
|
+
}
|
|
509
|
+
/* The command: the bundled node, `current`, this data folder. Never rewritten by an upgrade. */
|
|
510
|
+
const commandBefore = (() => { try {
|
|
511
|
+
return readFileSync(command, 'utf8');
|
|
512
|
+
}
|
|
513
|
+
catch {
|
|
514
|
+
return undefined;
|
|
515
|
+
} })();
|
|
516
|
+
undo.push({ what: `the command ${command}`, run: async () => {
|
|
517
|
+
if (commandBefore === undefined)
|
|
518
|
+
await rm(command, { force: true });
|
|
519
|
+
else
|
|
520
|
+
await writeFile(command, commandBefore);
|
|
521
|
+
} });
|
|
522
|
+
await mkdir(bin, { recursive: true });
|
|
523
|
+
await writeFile(`${command}.tmp`, buildWindowsCommand(data));
|
|
524
|
+
await rename(`${command}.tmp`, command);
|
|
525
|
+
/* Start it: the new release writes and starts the Task Scheduler task (and stops anything still running). */
|
|
526
|
+
if (args.noStart) {
|
|
527
|
+
say(`Installed. Start it with: ${command}`);
|
|
528
|
+
}
|
|
529
|
+
else {
|
|
530
|
+
say('Starting buddi.');
|
|
531
|
+
const start = await deps.runRelease(data, currentLinkRoot(releases), ['--no-open']);
|
|
532
|
+
for (const line of start.output.split(/\r?\n/))
|
|
533
|
+
if (line.trim() !== '' && !/^(Dashboard: |The link is good)/.test(line))
|
|
534
|
+
say(` ${line}`);
|
|
535
|
+
if (start.code !== 0)
|
|
536
|
+
throw new SetupError(`buddi ${newVersion} did not start (it exited with ${start.code})`);
|
|
537
|
+
started = true;
|
|
538
|
+
}
|
|
539
|
+
}
|
|
540
|
+
catch (error) {
|
|
541
|
+
const why = error instanceof SetupError ? error.message : `the install stopped: ${error.message.split('\n')[0]}`;
|
|
542
|
+
say(`${why}. Putting back what was there.`);
|
|
543
|
+
if (!(error instanceof SetupError))
|
|
544
|
+
said.record(String(error.stack ?? error));
|
|
545
|
+
// Whatever runs now is the failed one (or nothing): it stops before its files go.
|
|
546
|
+
await deps.stop(data).catch(err => say(`(it would not stop: ${err.message})`));
|
|
547
|
+
for (const step of undo.reverse())
|
|
548
|
+
await step.run().catch(err => say(`(could not put back ${step.what}: ${err.message})`));
|
|
549
|
+
if (plan.old !== 'none' && !sameRelease) {
|
|
550
|
+
// npm's buddi or the old release writes its own service again (its task script) and starts it.
|
|
551
|
+
const back = await oldBuddi(['--no-open']);
|
|
552
|
+
say(back.code === 0 ? `Back on ${plan.from ?? 'the version before'}, running.` : `${plan.from ?? 'The version before'} did not come back either. See ${path.join(data, 'logs', 'supervisor.log')}.`);
|
|
553
|
+
if (archive !== undefined)
|
|
554
|
+
say(`If ${newVersion} changed the database before it failed, ${plan.from ?? 'the old version'} may refuse it; restore the backup taken first: buddi backup restore ${archive}`);
|
|
555
|
+
}
|
|
556
|
+
else if (sameRelease && oldRoot !== undefined) {
|
|
557
|
+
const back = await deps.runRelease(data, oldRoot, ['--no-open']);
|
|
558
|
+
say(back.code === 0 ? `Back on ${newVersion} as it was, running.` : `buddi did not come back. See ${path.join(data, 'logs', 'supervisor.log')}.`);
|
|
559
|
+
}
|
|
560
|
+
throw new SetupError(`${why}. What was there before is back; see ${path.join(data, 'logs', 'supervisor.log')}.`);
|
|
561
|
+
}
|
|
562
|
+
}
|
|
563
|
+
finally {
|
|
564
|
+
await unlock();
|
|
565
|
+
}
|
|
566
|
+
/* Past this point the install stands: a failure is said, never undone. */
|
|
567
|
+
const record = { version: newVersion, arch: 'windows-x64', command, data, ...(args.uninstaller === undefined ? {} : { uninstaller: path.resolve(args.uninstaller) }), installedAt: new Date().toISOString() };
|
|
568
|
+
await writeFile(path.join(data, 'installer.json'), JSON.stringify(record, null, 2) + '\n', { mode: 0o600 }).catch(err => say(`(could not write installer.json: ${err.message})`));
|
|
569
|
+
// The data is an installation's again.
|
|
570
|
+
await rm(path.join(data, KEPT_FOR_REINSTALL_FILE), { force: true }).catch(() => { });
|
|
571
|
+
await pruneReleases(releases).catch(err => say(`(an old release could not be removed yet: ${err.message}; it goes at the next install)`));
|
|
572
|
+
await rm(nodeOld, { recursive: true, force: true, maxRetries: 10, retryDelay: 250 }).catch(() => { say(`(${nodeOld} is still in use; it goes at the next install.)`); });
|
|
573
|
+
/*
|
|
574
|
+
* npm's copy would answer `buddi` before this one on PATH. Removed only once
|
|
575
|
+
* this install serves the same data folder, runs, and no other buddi task on
|
|
576
|
+
* this machine runs that package; otherwise, the line that removes it.
|
|
577
|
+
*/
|
|
578
|
+
if (npm !== undefined) {
|
|
579
|
+
const others = started && npm.serves ? await deps.otherTaskScripts(data).catch(() => undefined) : undefined;
|
|
580
|
+
const elsewhere = others === undefined || scriptsUse(others, npm.pkg) || (real(npm.pkg) !== undefined && scriptsUse(others, real(npm.pkg)));
|
|
581
|
+
if (started && npm.serves && !elsewhere) {
|
|
582
|
+
const shims = ['buddi.cmd', 'buddi.ps1', 'buddi'].map(name => path.join(npm.prefix, name)).filter(file => npmShimRunsBuddi((() => { try {
|
|
583
|
+
return readFileSync(file, 'utf8');
|
|
584
|
+
}
|
|
585
|
+
catch {
|
|
586
|
+
return undefined;
|
|
587
|
+
} })()));
|
|
588
|
+
try {
|
|
589
|
+
await rm(npm.pkg, { recursive: true, force: true, maxRetries: 10, retryDelay: 250 });
|
|
590
|
+
for (const shim of shims)
|
|
591
|
+
await rm(shim, { force: true });
|
|
592
|
+
say(`Removed the npm copy of buddi (${npm.pkg}): this install serves its data now, and nothing else ran it.`);
|
|
593
|
+
}
|
|
594
|
+
catch (error) {
|
|
595
|
+
say(`The npm copy of buddi at ${npm.pkg} could not be removed (${error.message}); remove it with: npm uninstall -g @withbuddi/buddi`);
|
|
596
|
+
}
|
|
597
|
+
}
|
|
598
|
+
else {
|
|
599
|
+
say(`An npm copy of buddi is at ${npm.cmd}. It was left alone (${started && npm.serves ? 'another buddi installation on this computer runs it' : 'it may serve another installation'}); once you no longer need it: npm uninstall -g @withbuddi/buddi`);
|
|
600
|
+
}
|
|
601
|
+
}
|
|
602
|
+
say(`buddi ${newVersion} is installed in ${data}. ${command} runs it; buddi doctor checks it; Settings → Apps removes it (keeping one last backup).`);
|
|
603
|
+
return 0;
|
|
604
|
+
}
|
|
605
|
+
/** The release `current` names, as a path through the link (the launcher resolves it). */
|
|
606
|
+
function currentLinkRoot(releases) {
|
|
607
|
+
return path.join(releases, 'current');
|
|
608
|
+
}
|
|
609
|
+
/** What the setup alone puts in the data folder, before buddi first starts. */
|
|
610
|
+
export const NEVER_STARTED_PARTS = ['node', 'releases', 'installer.json', 'cache', 'logs'];
|
|
611
|
+
async function uninstall(args, said) {
|
|
612
|
+
const data = path.resolve(args.data);
|
|
613
|
+
const launcher = currentLauncher(path.join(data, 'releases'));
|
|
614
|
+
if (!existsSync(launcher)) {
|
|
615
|
+
said.say(`No buddi release in ${data}; nothing for buddi uninstall to do.`);
|
|
616
|
+
return 0;
|
|
617
|
+
}
|
|
618
|
+
/*
|
|
619
|
+
* Installed (/NOSTART) and never started: no installation, nothing to back
|
|
620
|
+
* up, and `buddi uninstall` rightly refuses a folder that is not one. Only
|
|
621
|
+
* the program the setup put there goes, and the folder if that leaves it empty.
|
|
622
|
+
*/
|
|
623
|
+
if (!existsSync(path.join(data, 'installation.json')) && !existsSync(path.join(data, 'postgres'))) {
|
|
624
|
+
for (const part of NEVER_STARTED_PARTS)
|
|
625
|
+
await rm(path.join(data, part), { recursive: true, force: true, maxRetries: 10, retryDelay: 250 });
|
|
626
|
+
// The setup's own unpack folders (.install-*): a scanner can hold one for a moment after the setup let it go.
|
|
627
|
+
for (const name of readdirSync(data))
|
|
628
|
+
if (name.startsWith('.install-'))
|
|
629
|
+
await rm(path.join(data, name), { recursive: true, force: true, maxRetries: 10, retryDelay: 250 }).catch(() => { });
|
|
630
|
+
if (readdirSync(data).length === 0)
|
|
631
|
+
await rm(data, { recursive: true, force: true, maxRetries: 10, retryDelay: 250 });
|
|
632
|
+
said.say(`buddi was never started here; removed the program from ${data}.`);
|
|
633
|
+
return 0;
|
|
634
|
+
}
|
|
635
|
+
const env = { ...process.env, ...windowsInstallEnvironment(data), PATH: windowsInstallPath(data, process.env.PATH ?? process.env.Path), Path: undefined, [SETUP_UNINSTALL_VAR]: '1' };
|
|
636
|
+
const run = await runProgram(process.execPath, [launcher, 'uninstall', '--yes', ...(args.keepData ? ['--keep-data'] : [])], env, { timeoutMs: 30 * 60_000 });
|
|
637
|
+
// The six words go to the summary the uninstaller shows, never into a log (Inno Setup's /LOG copies this one).
|
|
638
|
+
for (const line of run.output.split(/\r?\n/))
|
|
639
|
+
if (line.trim() !== '')
|
|
640
|
+
said.say(/^Your backup passphrase/.test(line.trim()) ? 'Your backup passphrase: shown on screen and kept beside the backup, not in this log.' : line);
|
|
641
|
+
if (args.summary !== undefined) {
|
|
642
|
+
const lines = uninstallSummary(run.output);
|
|
643
|
+
// A blank line between them: the uninstaller shows them as they are.
|
|
644
|
+
try {
|
|
645
|
+
writeFileSync(args.summary, `\ufeff${lines.join('\r\n\r\n')}\r\n`);
|
|
646
|
+
}
|
|
647
|
+
catch { /* the log has it all */ }
|
|
648
|
+
}
|
|
649
|
+
return run.code;
|
|
650
|
+
}
|
|
651
|
+
export async function main(argv) {
|
|
652
|
+
let args;
|
|
653
|
+
try {
|
|
654
|
+
args = parseSetupArgs(argv);
|
|
655
|
+
}
|
|
656
|
+
catch (error) {
|
|
657
|
+
console.error(`windows-setup: ${error.message}`);
|
|
658
|
+
return 2;
|
|
659
|
+
}
|
|
660
|
+
const said = new Said(args.log);
|
|
661
|
+
let code;
|
|
662
|
+
try {
|
|
663
|
+
code = args.command === 'install' ? await install(args, said) : await uninstall(args, said);
|
|
664
|
+
}
|
|
665
|
+
catch (error) {
|
|
666
|
+
// The owner reads one sentence with a next step; the stack goes to the log only.
|
|
667
|
+
const plain = error instanceof SetupError ? error.message
|
|
668
|
+
: `something unexpected went wrong (${error.message?.split('\n')[0] ?? String(error)}). Nothing you need is lost: run the setup again, and if it fails the same way, send the log below.`;
|
|
669
|
+
said.say(`buddi setup: ${plain}`);
|
|
670
|
+
if (!(error instanceof SetupError))
|
|
671
|
+
said.record(String(error.stack ?? error));
|
|
672
|
+
if (args.summary !== undefined) {
|
|
673
|
+
try {
|
|
674
|
+
writeFileSync(args.summary, `\ufeff${plain.charAt(0).toUpperCase()}${plain.slice(1)}\r\n`);
|
|
675
|
+
}
|
|
676
|
+
catch { /* the log says it */ }
|
|
677
|
+
}
|
|
678
|
+
code = 1;
|
|
679
|
+
}
|
|
680
|
+
if (args.result !== undefined) {
|
|
681
|
+
try {
|
|
682
|
+
writeFileSync(args.result, `${code}\r\n`);
|
|
683
|
+
}
|
|
684
|
+
catch { /* the log says it */ }
|
|
685
|
+
}
|
|
686
|
+
return code;
|
|
687
|
+
}
|
|
688
|
+
/** Is this module the program node was asked to run? Named through `current` (a junction) it is still this file; Windows paths ignore case. */
|
|
689
|
+
export function runAsProgram(argv1, self, resolve = file => { try {
|
|
690
|
+
return realpathSync(file);
|
|
691
|
+
}
|
|
692
|
+
catch {
|
|
693
|
+
return path.resolve(file);
|
|
694
|
+
} }) {
|
|
695
|
+
return argv1 !== undefined && resolve(argv1).toLowerCase() === resolve(self).toLowerCase();
|
|
696
|
+
}
|
|
697
|
+
if (runAsProgram(process.argv[1], fileURLToPath(import.meta.url))) {
|
|
698
|
+
main(process.argv.slice(2)).then(code => { process.exitCode = code; }, error => { console.error(error); process.exitCode = 1; });
|
|
699
|
+
}
|
|
700
|
+
//# sourceMappingURL=windows-setup.js.map
|