@better-openclaw/core 1.0.26 → 1.0.31
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/README.md +67 -7
- package/dist/addon-stack.cjs +41 -28
- package/dist/addon-stack.cjs.map +1 -1
- package/dist/addon-stack.d.cts +1 -1
- package/dist/addon-stack.d.cts.map +1 -1
- package/dist/addon-stack.d.mts +1 -1
- package/dist/addon-stack.d.mts.map +1 -1
- package/dist/addon-stack.mjs +40 -27
- package/dist/addon-stack.mjs.map +1 -1
- package/dist/addon-stack.test.cjs +14 -14
- package/dist/addon-stack.test.cjs.map +1 -1
- package/dist/addon-stack.test.mjs +13 -13
- package/dist/addon-stack.test.mjs.map +1 -1
- package/dist/bare-metal-partition.d.cts +1 -1
- package/dist/bare-metal-partition.d.mts +1 -1
- package/dist/bare-metal-partition.test.cjs +1 -1
- package/dist/bare-metal-partition.test.mjs +1 -1
- package/dist/callback-sink-CdMKYayY.d.mts +15 -0
- package/dist/callback-sink-CdMKYayY.d.mts.map +1 -0
- package/dist/callback-sink-iNThWRnQ.d.cts +15 -0
- package/dist/callback-sink-iNThWRnQ.d.cts.map +1 -0
- package/dist/claude-code-fw-CrbAlzTM.d.mts +7 -0
- package/dist/claude-code-fw-CrbAlzTM.d.mts.map +1 -0
- package/dist/claude-code-fw-dKYH2prH.d.cts +7 -0
- package/dist/claude-code-fw-dKYH2prH.d.cts.map +1 -0
- package/dist/codex-fw-Ct8q4pzo.d.mts +7 -0
- package/dist/codex-fw-Ct8q4pzo.d.mts.map +1 -0
- package/dist/codex-fw-l7Ku8ZI8.d.cts +7 -0
- package/dist/codex-fw-l7Ku8ZI8.d.cts.map +1 -0
- package/dist/compose-validation.test.cjs +1 -1
- package/dist/composer.cjs +89 -129
- package/dist/composer.cjs.map +1 -1
- package/dist/composer.d.cts +3 -3
- package/dist/composer.d.cts.map +1 -1
- package/dist/composer.d.mts +3 -3
- package/dist/composer.d.mts.map +1 -1
- package/dist/composer.mjs +88 -128
- package/dist/composer.mjs.map +1 -1
- package/dist/composer.snapshot.test.cjs +1 -1
- package/dist/composer.snapshot.test.mjs +1 -1
- package/dist/composer.test.cjs +53 -2
- package/dist/composer.test.cjs.map +1 -1
- package/dist/composer.test.mjs +52 -1
- package/dist/composer.test.mjs.map +1 -1
- package/dist/console-sink-BHQpRyCt.d.cts +13 -0
- package/dist/console-sink-BHQpRyCt.d.cts.map +1 -0
- package/dist/console-sink-bouG_M1K.d.mts +13 -0
- package/dist/console-sink-bouG_M1K.d.mts.map +1 -0
- package/dist/{coolify-BVGGcMrT.d.mts → coolify-D5E0z01M.d.mts} +2 -2
- package/dist/{coolify-BVGGcMrT.d.mts.map → coolify-D5E0z01M.d.mts.map} +1 -1
- package/dist/{coolify-vlb1G9V2.d.cts → coolify-DjHecHCr.d.cts} +2 -2
- package/dist/{coolify-vlb1G9V2.d.cts.map → coolify-DjHecHCr.d.cts.map} +1 -1
- package/dist/copaw-BQyjioz7.d.cts +7 -0
- package/dist/copaw-BQyjioz7.d.cts.map +1 -0
- package/dist/copaw-C_3N7eQu.d.mts +7 -0
- package/dist/copaw-C_3N7eQu.d.mts.map +1 -0
- package/dist/deployers/coolify.cjs +25 -0
- package/dist/deployers/coolify.cjs.map +1 -1
- package/dist/deployers/coolify.d.cts +1 -1
- package/dist/deployers/coolify.d.mts +1 -1
- package/dist/deployers/coolify.mjs +25 -0
- package/dist/deployers/coolify.mjs.map +1 -1
- package/dist/deployers/coolify.test.cjs +156 -0
- package/dist/deployers/coolify.test.cjs.map +1 -0
- package/dist/deployers/coolify.test.d.cts +1 -0
- package/dist/deployers/coolify.test.d.mts +1 -0
- package/dist/deployers/coolify.test.mjs +157 -0
- package/dist/deployers/coolify.test.mjs.map +1 -0
- package/dist/deployers/dokploy.cjs +25 -0
- package/dist/deployers/dokploy.cjs.map +1 -1
- package/dist/deployers/dokploy.d.cts +1 -1
- package/dist/deployers/dokploy.d.mts +1 -1
- package/dist/deployers/dokploy.mjs +25 -0
- package/dist/deployers/dokploy.mjs.map +1 -1
- package/dist/deployers/dokploy.test.cjs +108 -0
- package/dist/deployers/dokploy.test.cjs.map +1 -0
- package/dist/deployers/dokploy.test.d.cts +1 -0
- package/dist/deployers/dokploy.test.d.mts +1 -0
- package/dist/deployers/dokploy.test.mjs +109 -0
- package/dist/deployers/dokploy.test.mjs.map +1 -0
- package/dist/deployers/index.d.cts +3 -3
- package/dist/deployers/index.d.mts +3 -3
- package/dist/deployers/strip-host-ports.cjs +1 -1
- package/dist/deployers/strip-host-ports.test.cjs +1 -1
- package/dist/deployers/strip-host-ports.test.mjs +1 -1
- package/dist/deployers/types.d.cts +1 -1
- package/dist/deployers/types.d.mts +1 -1
- package/dist/{dokploy-8cbrxUun.d.cts → dokploy-BnVDjWCV.d.cts} +2 -2
- package/dist/{dokploy-8cbrxUun.d.cts.map → dokploy-BnVDjWCV.d.cts.map} +1 -1
- package/dist/{dokploy-BTflLhTM.d.mts → dokploy-BqLdCfyR.d.mts} +2 -2
- package/dist/{dokploy-BTflLhTM.d.mts.map → dokploy-BqLdCfyR.d.mts.map} +1 -1
- package/dist/frameworks/claude-code-fw.cjs +79 -0
- package/dist/frameworks/claude-code-fw.cjs.map +1 -0
- package/dist/frameworks/claude-code-fw.d.cts +2 -0
- package/dist/frameworks/claude-code-fw.d.mts +2 -0
- package/dist/frameworks/claude-code-fw.mjs +78 -0
- package/dist/frameworks/claude-code-fw.mjs.map +1 -0
- package/dist/frameworks/codex-fw.cjs +67 -0
- package/dist/frameworks/codex-fw.cjs.map +1 -0
- package/dist/frameworks/codex-fw.d.cts +2 -0
- package/dist/frameworks/codex-fw.d.mts +2 -0
- package/dist/frameworks/codex-fw.mjs +66 -0
- package/dist/frameworks/codex-fw.mjs.map +1 -0
- package/dist/frameworks/copaw.cjs +118 -0
- package/dist/frameworks/copaw.cjs.map +1 -0
- package/dist/frameworks/copaw.d.cts +2 -0
- package/dist/frameworks/copaw.d.mts +2 -0
- package/dist/frameworks/copaw.mjs +117 -0
- package/dist/frameworks/copaw.mjs.map +1 -0
- package/dist/frameworks/frameworks.test.cjs +94 -0
- package/dist/frameworks/frameworks.test.cjs.map +1 -0
- package/dist/frameworks/frameworks.test.d.cts +1 -0
- package/dist/frameworks/frameworks.test.d.mts +1 -0
- package/dist/frameworks/frameworks.test.mjs +94 -0
- package/dist/frameworks/frameworks.test.mjs.map +1 -0
- package/dist/frameworks/index.cjs +35 -0
- package/dist/frameworks/index.cjs.map +1 -0
- package/dist/frameworks/index.d.cts +11 -0
- package/dist/frameworks/index.d.mts +11 -0
- package/dist/frameworks/index.mjs +22 -0
- package/dist/frameworks/index.mjs.map +1 -0
- package/dist/frameworks/memu.cjs +118 -0
- package/dist/frameworks/memu.cjs.map +1 -0
- package/dist/frameworks/memu.d.cts +2 -0
- package/dist/frameworks/memu.d.mts +2 -0
- package/dist/frameworks/memu.mjs +117 -0
- package/dist/frameworks/memu.mjs.map +1 -0
- package/dist/frameworks/nanobot.cjs +126 -0
- package/dist/frameworks/nanobot.cjs.map +1 -0
- package/dist/frameworks/nanobot.d.cts +2 -0
- package/dist/frameworks/nanobot.d.mts +2 -0
- package/dist/frameworks/nanobot.mjs +125 -0
- package/dist/frameworks/nanobot.mjs.map +1 -0
- package/dist/frameworks/nanoclaw.cjs +99 -0
- package/dist/frameworks/nanoclaw.cjs.map +1 -0
- package/dist/frameworks/nanoclaw.d.cts +2 -0
- package/dist/frameworks/nanoclaw.d.mts +2 -0
- package/dist/frameworks/nanoclaw.mjs +98 -0
- package/dist/frameworks/nanoclaw.mjs.map +1 -0
- package/dist/frameworks/openclaw.cjs +253 -0
- package/dist/frameworks/openclaw.cjs.map +1 -0
- package/dist/frameworks/openclaw.d.cts +2 -0
- package/dist/frameworks/openclaw.d.mts +2 -0
- package/dist/frameworks/openclaw.mjs +251 -0
- package/dist/frameworks/openclaw.mjs.map +1 -0
- package/dist/frameworks/registry.cjs +31 -0
- package/dist/frameworks/registry.cjs.map +1 -0
- package/dist/frameworks/registry.d.cts +2 -0
- package/dist/frameworks/registry.d.mts +2 -0
- package/dist/frameworks/registry.mjs +26 -0
- package/dist/frameworks/registry.mjs.map +1 -0
- package/dist/frameworks/registry.test.cjs +110 -0
- package/dist/frameworks/registry.test.cjs.map +1 -0
- package/dist/frameworks/registry.test.d.cts +1 -0
- package/dist/frameworks/registry.test.d.mts +1 -0
- package/dist/frameworks/registry.test.mjs +111 -0
- package/dist/frameworks/registry.test.mjs.map +1 -0
- package/dist/frameworks/types.cjs +0 -0
- package/dist/frameworks/types.d.cts +2 -0
- package/dist/frameworks/types.d.mts +2 -0
- package/dist/frameworks/types.mjs +1 -0
- package/dist/frameworks/zeroclaw.cjs +123 -0
- package/dist/frameworks/zeroclaw.cjs.map +1 -0
- package/dist/frameworks/zeroclaw.d.cts +2 -0
- package/dist/frameworks/zeroclaw.d.mts +2 -0
- package/dist/frameworks/zeroclaw.mjs +122 -0
- package/dist/frameworks/zeroclaw.mjs.map +1 -0
- package/dist/generate.cjs +64 -13
- package/dist/generate.cjs.map +1 -1
- package/dist/generate.d.cts +5 -2
- package/dist/generate.d.cts.map +1 -1
- package/dist/generate.d.mts +5 -2
- package/dist/generate.d.mts.map +1 -1
- package/dist/generate.mjs +63 -12
- package/dist/generate.mjs.map +1 -1
- package/dist/generate.test.cjs +42 -6
- package/dist/generate.test.cjs.map +1 -1
- package/dist/generate.test.mjs +41 -5
- package/dist/generate.test.mjs.map +1 -1
- package/dist/generators/bare-metal-install.d.cts +1 -1
- package/dist/generators/bare-metal-install.d.mts +1 -1
- package/dist/generators/bare-metal-install.test.cjs +1 -1
- package/dist/generators/bare-metal-install.test.mjs +1 -1
- package/dist/generators/caddy.cjs +9 -3
- package/dist/generators/caddy.cjs.map +1 -1
- package/dist/generators/caddy.d.cts +1 -1
- package/dist/generators/caddy.d.mts +1 -1
- package/dist/generators/caddy.mjs +9 -3
- package/dist/generators/caddy.mjs.map +1 -1
- package/dist/generators/caddy.test.cjs +30 -2
- package/dist/generators/caddy.test.cjs.map +1 -1
- package/dist/generators/caddy.test.mjs +30 -2
- package/dist/generators/caddy.test.mjs.map +1 -1
- package/dist/generators/clone-repos.cjs.map +1 -1
- package/dist/generators/clone-repos.d.cts +1 -1
- package/dist/generators/clone-repos.d.mts +1 -1
- package/dist/generators/clone-repos.mjs.map +1 -1
- package/dist/generators/clone-repos.test.cjs +1 -1
- package/dist/generators/clone-repos.test.cjs.map +1 -1
- package/dist/generators/clone-repos.test.mjs +1 -1
- package/dist/generators/clone-repos.test.mjs.map +1 -1
- package/dist/generators/cloud-init.test.cjs +58 -0
- package/dist/generators/cloud-init.test.cjs.map +1 -0
- package/dist/generators/cloud-init.test.d.cts +1 -0
- package/dist/generators/cloud-init.test.d.mts +1 -0
- package/dist/generators/cloud-init.test.mjs +59 -0
- package/dist/generators/cloud-init.test.mjs.map +1 -0
- package/dist/generators/env.cjs +28 -103
- package/dist/generators/env.cjs.map +1 -1
- package/dist/generators/env.d.cts +4 -1
- package/dist/generators/env.d.cts.map +1 -1
- package/dist/generators/env.d.mts +4 -1
- package/dist/generators/env.d.mts.map +1 -1
- package/dist/generators/env.mjs +27 -102
- package/dist/generators/env.mjs.map +1 -1
- package/dist/generators/env.test.cjs +3 -3
- package/dist/generators/env.test.cjs.map +1 -1
- package/dist/generators/env.test.mjs +3 -3
- package/dist/generators/env.test.mjs.map +1 -1
- package/dist/generators/get-shit-done.d.cts +1 -1
- package/dist/generators/get-shit-done.d.mts +1 -1
- package/dist/generators/get-shit-done.test.cjs +48 -0
- package/dist/generators/get-shit-done.test.cjs.map +1 -0
- package/dist/generators/get-shit-done.test.d.cts +1 -0
- package/dist/generators/get-shit-done.test.d.mts +1 -0
- package/dist/generators/get-shit-done.test.mjs +49 -0
- package/dist/generators/get-shit-done.test.mjs.map +1 -0
- package/dist/generators/grafana.test.cjs +74 -0
- package/dist/generators/grafana.test.cjs.map +1 -0
- package/dist/generators/grafana.test.d.cts +1 -0
- package/dist/generators/grafana.test.d.mts +1 -0
- package/dist/generators/grafana.test.mjs +74 -0
- package/dist/generators/grafana.test.mjs.map +1 -0
- package/dist/generators/health-check.cjs +6 -6
- package/dist/generators/health-check.cjs.map +1 -1
- package/dist/generators/health-check.d.cts +1 -1
- package/dist/generators/health-check.d.mts +1 -1
- package/dist/generators/health-check.mjs +6 -6
- package/dist/generators/health-check.mjs.map +1 -1
- package/dist/generators/health-check.test.cjs +1 -1
- package/dist/generators/health-check.test.mjs +1 -1
- package/dist/generators/n8n-workflows.d.cts +1 -1
- package/dist/generators/n8n-workflows.d.mts +1 -1
- package/dist/generators/n8n-workflows.test.cjs +75 -0
- package/dist/generators/n8n-workflows.test.cjs.map +1 -0
- package/dist/generators/n8n-workflows.test.d.cts +1 -0
- package/dist/generators/n8n-workflows.test.d.mts +1 -0
- package/dist/generators/n8n-workflows.test.mjs +76 -0
- package/dist/generators/n8n-workflows.test.mjs.map +1 -0
- package/dist/generators/native-services.d.cts +1 -1
- package/dist/generators/native-services.d.mts +1 -1
- package/dist/generators/openclaw-install-script.test.cjs +35 -0
- package/dist/generators/openclaw-install-script.test.cjs.map +1 -0
- package/dist/generators/openclaw-install-script.test.d.cts +1 -0
- package/dist/generators/openclaw-install-script.test.d.mts +1 -0
- package/dist/generators/openclaw-install-script.test.mjs +36 -0
- package/dist/generators/openclaw-install-script.test.mjs.map +1 -0
- package/dist/generators/openclaw-json.cjs +60 -4
- package/dist/generators/openclaw-json.cjs.map +1 -1
- package/dist/generators/openclaw-json.d.cts +1 -5
- package/dist/generators/openclaw-json.d.cts.map +1 -1
- package/dist/generators/openclaw-json.d.mts +1 -5
- package/dist/generators/openclaw-json.d.mts.map +1 -1
- package/dist/generators/openclaw-json.mjs +60 -4
- package/dist/generators/openclaw-json.mjs.map +1 -1
- package/dist/generators/postgres-init.cjs +20 -0
- package/dist/generators/postgres-init.cjs.map +1 -1
- package/dist/generators/postgres-init.d.cts +1 -1
- package/dist/generators/postgres-init.d.cts.map +1 -1
- package/dist/generators/postgres-init.d.mts +1 -1
- package/dist/generators/postgres-init.d.mts.map +1 -1
- package/dist/generators/postgres-init.mjs +20 -0
- package/dist/generators/postgres-init.mjs.map +1 -1
- package/dist/generators/postgres-init.test.cjs +111 -0
- package/dist/generators/postgres-init.test.cjs.map +1 -0
- package/dist/generators/postgres-init.test.d.cts +1 -0
- package/dist/generators/postgres-init.test.d.mts +1 -0
- package/dist/generators/postgres-init.test.mjs +112 -0
- package/dist/generators/postgres-init.test.mjs.map +1 -0
- package/dist/generators/prometheus.d.cts +1 -1
- package/dist/generators/prometheus.d.mts +1 -1
- package/dist/generators/prometheus.test.cjs +99 -0
- package/dist/generators/prometheus.test.cjs.map +1 -0
- package/dist/generators/prometheus.test.d.cts +1 -0
- package/dist/generators/prometheus.test.d.mts +1 -0
- package/dist/generators/prometheus.test.mjs +99 -0
- package/dist/generators/prometheus.test.mjs.map +1 -0
- package/dist/generators/readme.cjs +50 -7
- package/dist/generators/readme.cjs.map +1 -1
- package/dist/generators/readme.d.cts +3 -1
- package/dist/generators/readme.d.cts.map +1 -1
- package/dist/generators/readme.d.mts +3 -1
- package/dist/generators/readme.d.mts.map +1 -1
- package/dist/generators/readme.mjs +50 -7
- package/dist/generators/readme.mjs.map +1 -1
- package/dist/generators/scripts.test.cjs +2 -2
- package/dist/generators/scripts.test.cjs.map +1 -1
- package/dist/generators/scripts.test.mjs +2 -2
- package/dist/generators/scripts.test.mjs.map +1 -1
- package/dist/generators/skills.cjs +1 -1
- package/dist/generators/skills.d.cts +1 -1
- package/dist/generators/skills.d.cts.map +1 -1
- package/dist/generators/skills.d.mts +1 -1
- package/dist/generators/skills.d.mts.map +1 -1
- package/dist/generators/skills.mjs +310 -0
- package/dist/generators/skills.mjs.map +1 -1
- package/dist/generators/stack-manifest.d.cts +1 -1
- package/dist/generators/stack-manifest.d.mts +1 -1
- package/dist/generators/stack-manifest.test.cjs +97 -0
- package/dist/generators/stack-manifest.test.cjs.map +1 -0
- package/dist/generators/stack-manifest.test.d.cts +1 -0
- package/dist/generators/stack-manifest.test.d.mts +1 -0
- package/dist/generators/stack-manifest.test.mjs +98 -0
- package/dist/generators/stack-manifest.test.mjs.map +1 -0
- package/dist/generators/traefik.d.cts +1 -1
- package/dist/generators/traefik.d.mts +1 -1
- package/dist/generators/traefik.test.cjs +12 -12
- package/dist/generators/traefik.test.cjs.map +1 -1
- package/dist/generators/traefik.test.mjs +12 -12
- package/dist/generators/traefik.test.mjs.map +1 -1
- package/dist/index.cjs +18 -2
- package/dist/index.d.cts +13 -7
- package/dist/index.d.mts +13 -7
- package/dist/index.mjs +9 -3
- package/dist/logger/__tests__/logger.test.cjs +308 -0
- package/dist/logger/__tests__/logger.test.cjs.map +1 -0
- package/dist/logger/__tests__/logger.test.d.cts +1 -0
- package/dist/logger/__tests__/logger.test.d.mts +1 -0
- package/dist/logger/__tests__/logger.test.mjs +308 -0
- package/dist/logger/__tests__/logger.test.mjs.map +1 -0
- package/dist/logger/index.cjs +8 -0
- package/dist/logger/index.d.cts +5 -0
- package/dist/logger/index.d.mts +5 -0
- package/dist/logger/index.mjs +4 -0
- package/dist/logger/logger.cjs +270 -0
- package/dist/logger/logger.cjs.map +1 -0
- package/dist/logger/logger.d.cts +2 -0
- package/dist/logger/logger.d.mts +2 -0
- package/dist/logger/logger.mjs +267 -0
- package/dist/logger/logger.mjs.map +1 -0
- package/dist/logger/sinks/callback-sink.cjs +18 -0
- package/dist/logger/sinks/callback-sink.cjs.map +1 -0
- package/dist/logger/sinks/callback-sink.d.cts +2 -0
- package/dist/logger/sinks/callback-sink.d.mts +2 -0
- package/dist/logger/sinks/callback-sink.mjs +17 -0
- package/dist/logger/sinks/callback-sink.mjs.map +1 -0
- package/dist/logger/sinks/console-sink.cjs +39 -0
- package/dist/logger/sinks/console-sink.cjs.map +1 -0
- package/dist/logger/sinks/console-sink.d.cts +2 -0
- package/dist/logger/sinks/console-sink.d.mts +2 -0
- package/dist/logger/sinks/console-sink.mjs +38 -0
- package/dist/logger/sinks/console-sink.mjs.map +1 -0
- package/dist/logger/sinks/file-sink.cjs +72 -0
- package/dist/logger/sinks/file-sink.cjs.map +1 -0
- package/dist/logger/sinks/file-sink.d.cts +36 -0
- package/dist/logger/sinks/file-sink.d.cts.map +1 -0
- package/dist/logger/sinks/file-sink.d.mts +36 -0
- package/dist/logger/sinks/file-sink.d.mts.map +1 -0
- package/dist/logger/sinks/file-sink.mjs +70 -0
- package/dist/logger/sinks/file-sink.mjs.map +1 -0
- package/dist/logger/types.cjs +0 -0
- package/dist/logger/types.d.cts +2 -0
- package/dist/logger/types.d.mts +2 -0
- package/dist/logger/types.mjs +1 -0
- package/dist/logger-CZ0Qnyiu.d.mts +66 -0
- package/dist/logger-CZ0Qnyiu.d.mts.map +1 -0
- package/dist/logger-DDfwai-A.d.cts +66 -0
- package/dist/logger-DDfwai-A.d.cts.map +1 -0
- package/dist/memu-BfRXtwmL.d.cts +7 -0
- package/dist/memu-BfRXtwmL.d.cts.map +1 -0
- package/dist/memu-C-fXbWr-.d.mts +7 -0
- package/dist/memu-C-fXbWr-.d.mts.map +1 -0
- package/dist/migrations.cjs +17 -9
- package/dist/migrations.cjs.map +1 -1
- package/dist/migrations.d.cts +1 -1
- package/dist/migrations.d.cts.map +1 -1
- package/dist/migrations.d.mts +1 -1
- package/dist/migrations.d.mts.map +1 -1
- package/dist/migrations.mjs +17 -9
- package/dist/migrations.mjs.map +1 -1
- package/dist/migrations.test.cjs +4 -4
- package/dist/migrations.test.mjs +4 -4
- package/dist/nanobot-2c0bS4lu.d.cts +7 -0
- package/dist/nanobot-2c0bS4lu.d.cts.map +1 -0
- package/dist/nanobot-BUO6pVQc.d.mts +7 -0
- package/dist/nanobot-BUO6pVQc.d.mts.map +1 -0
- package/dist/nanoclaw-CgHubEig.d.mts +7 -0
- package/dist/nanoclaw-CgHubEig.d.mts.map +1 -0
- package/dist/nanoclaw-Dvz0ef6J.d.cts +7 -0
- package/dist/nanoclaw-Dvz0ef6J.d.cts.map +1 -0
- package/dist/openclaw-D8lVecjC.d.mts +7 -0
- package/dist/openclaw-D8lVecjC.d.mts.map +1 -0
- package/dist/openclaw-DThj8i3N.d.cts +7 -0
- package/dist/openclaw-DThj8i3N.d.cts.map +1 -0
- package/dist/port-scanner.d.cts +1 -1
- package/dist/port-scanner.d.mts +1 -1
- package/dist/port-scanner.test.cjs +155 -0
- package/dist/port-scanner.test.cjs.map +1 -0
- package/dist/port-scanner.test.d.cts +1 -0
- package/dist/port-scanner.test.d.mts +1 -0
- package/dist/port-scanner.test.mjs +156 -0
- package/dist/port-scanner.test.mjs.map +1 -0
- package/dist/presets/presets.test.cjs +5 -5
- package/dist/presets/presets.test.cjs.map +1 -1
- package/dist/presets/presets.test.mjs +4 -4
- package/dist/presets/presets.test.mjs.map +1 -1
- package/dist/presets/registry.d.cts +1 -1
- package/dist/presets/registry.d.mts +1 -1
- package/dist/presets/registry.test.cjs +7 -7
- package/dist/presets/registry.test.cjs.map +1 -1
- package/dist/presets/registry.test.mjs +7 -7
- package/dist/presets/registry.test.mjs.map +1 -1
- package/dist/registry-DHX7vnVo.d.cts +16 -0
- package/dist/registry-DHX7vnVo.d.cts.map +1 -0
- package/dist/registry-DTAILnga.d.mts +16 -0
- package/dist/registry-DTAILnga.d.mts.map +1 -0
- package/dist/resolver.cjs +13 -3
- package/dist/resolver.cjs.map +1 -1
- package/dist/resolver.d.cts +1 -1
- package/dist/resolver.d.cts.map +1 -1
- package/dist/resolver.d.mts +1 -1
- package/dist/resolver.d.mts.map +1 -1
- package/dist/resolver.mjs +13 -3
- package/dist/resolver.mjs.map +1 -1
- package/dist/resolver.test.cjs +35 -3
- package/dist/resolver.test.cjs.map +1 -1
- package/dist/resolver.test.mjs +35 -3
- package/dist/resolver.test.mjs.map +1 -1
- package/dist/{schema-BQnZrcw8.d.cts → schema-BSl9wiFe.d.mts} +134 -2
- package/dist/schema-BSl9wiFe.d.mts.map +1 -0
- package/dist/{schema-SBpL0bdI.d.mts → schema-Bd9l2r7p.d.cts} +134 -2
- package/dist/schema-Bd9l2r7p.d.cts.map +1 -0
- package/dist/schema.cjs +28 -4
- package/dist/schema.cjs.map +1 -1
- package/dist/schema.d.cts +2 -2
- package/dist/schema.d.mts +2 -2
- package/dist/schema.mjs +27 -4
- package/dist/schema.mjs.map +1 -1
- package/dist/schema.test.cjs +3 -3
- package/dist/schema.test.cjs.map +1 -1
- package/dist/schema.test.mjs +3 -3
- package/dist/schema.test.mjs.map +1 -1
- package/dist/services/definitions/adguard-home.d.cts +1 -1
- package/dist/services/definitions/adguard-home.d.mts +1 -1
- package/dist/services/definitions/agent-browser.cjs +161 -0
- package/dist/services/definitions/agent-browser.cjs.map +1 -0
- package/dist/services/definitions/agent-browser.d.cts +7 -0
- package/dist/services/definitions/agent-browser.d.cts.map +1 -0
- package/dist/services/definitions/agent-browser.d.mts +7 -0
- package/dist/services/definitions/agent-browser.d.mts.map +1 -0
- package/dist/services/definitions/agent-browser.mjs +160 -0
- package/dist/services/definitions/agent-browser.mjs.map +1 -0
- package/dist/services/definitions/airbyte.d.cts +1 -1
- package/dist/services/definitions/airbyte.d.mts +1 -1
- package/dist/services/definitions/airflow.d.cts +1 -1
- package/dist/services/definitions/airflow.d.mts +1 -1
- package/dist/services/definitions/anything-llm.d.cts +1 -1
- package/dist/services/definitions/anything-llm.d.mts +1 -1
- package/dist/services/definitions/appflowy.d.cts +1 -1
- package/dist/services/definitions/appflowy.d.mts +1 -1
- package/dist/services/definitions/apptension-saas.cjs.map +1 -1
- package/dist/services/definitions/apptension-saas.d.cts +1 -1
- package/dist/services/definitions/apptension-saas.d.mts +1 -1
- package/dist/services/definitions/apptension-saas.mjs.map +1 -1
- package/dist/services/definitions/appwrite.d.cts +1 -1
- package/dist/services/definitions/appwrite.d.mts +1 -1
- package/dist/services/definitions/audiobookshelf.d.cts +1 -1
- package/dist/services/definitions/audiobookshelf.d.mts +1 -1
- package/dist/services/definitions/authelia.d.cts +1 -1
- package/dist/services/definitions/authelia.d.mts +1 -1
- package/dist/services/definitions/authentik.d.cts +1 -1
- package/dist/services/definitions/authentik.d.mts +1 -1
- package/dist/services/definitions/axolotl.d.cts +1 -1
- package/dist/services/definitions/axolotl.d.mts +1 -1
- package/dist/services/definitions/baserow.d.cts +1 -1
- package/dist/services/definitions/baserow.d.mts +1 -1
- package/dist/services/definitions/beszel.d.cts +1 -1
- package/dist/services/definitions/beszel.d.mts +1 -1
- package/dist/services/definitions/boxyhq-saas.d.cts +1 -1
- package/dist/services/definitions/boxyhq-saas.d.mts +1 -1
- package/dist/services/definitions/browserless.d.cts +1 -1
- package/dist/services/definitions/browserless.d.mts +1 -1
- package/dist/services/definitions/burnlink.d.cts +1 -1
- package/dist/services/definitions/burnlink.d.mts +1 -1
- package/dist/services/definitions/caddy.d.cts +1 -1
- package/dist/services/definitions/caddy.d.mts +1 -1
- package/dist/services/definitions/cal-com.d.cts +1 -1
- package/dist/services/definitions/cal-com.d.mts +1 -1
- package/dist/services/definitions/calibre-web.d.cts +1 -1
- package/dist/services/definitions/calibre-web.d.mts +1 -1
- package/dist/services/definitions/chatwoot-worker.d.cts +1 -1
- package/dist/services/definitions/chatwoot-worker.d.mts +1 -1
- package/dist/services/definitions/chatwoot.d.cts +1 -1
- package/dist/services/definitions/chatwoot.d.mts +1 -1
- package/dist/services/definitions/chromadb.cjs +4 -1
- package/dist/services/definitions/chromadb.cjs.map +1 -1
- package/dist/services/definitions/chromadb.d.cts +1 -1
- package/dist/services/definitions/chromadb.d.mts +1 -1
- package/dist/services/definitions/chromadb.mjs +4 -1
- package/dist/services/definitions/chromadb.mjs.map +1 -1
- package/dist/services/definitions/claude-code.cjs +1 -1
- package/dist/services/definitions/claude-code.cjs.map +1 -1
- package/dist/services/definitions/claude-code.d.cts +1 -1
- package/dist/services/definitions/claude-code.d.mts +1 -1
- package/dist/services/definitions/claude-code.mjs +1 -1
- package/dist/services/definitions/claude-code.mjs.map +1 -1
- package/dist/services/definitions/clawrouter.cjs +138 -0
- package/dist/services/definitions/clawrouter.cjs.map +1 -0
- package/dist/services/definitions/clawrouter.d.cts +7 -0
- package/dist/services/definitions/clawrouter.d.cts.map +1 -0
- package/dist/services/definitions/clawrouter.d.mts +7 -0
- package/dist/services/definitions/clawrouter.d.mts.map +1 -0
- package/dist/services/definitions/clawrouter.mjs +137 -0
- package/dist/services/definitions/clawrouter.mjs.map +1 -0
- package/dist/services/definitions/clickhouse.d.cts +1 -1
- package/dist/services/definitions/clickhouse.d.mts +1 -1
- package/dist/services/definitions/cloudflared.d.cts +1 -1
- package/dist/services/definitions/cloudflared.d.mts +1 -1
- package/dist/services/definitions/cmsaas-starter.d.cts +1 -1
- package/dist/services/definitions/cmsaas-starter.d.mts +1 -1
- package/dist/services/definitions/cockroachdb.d.cts +1 -1
- package/dist/services/definitions/cockroachdb.d.mts +1 -1
- package/dist/services/definitions/code-server.d.cts +1 -1
- package/dist/services/definitions/code-server.d.mts +1 -1
- package/dist/services/definitions/coder.d.cts +1 -1
- package/dist/services/definitions/coder.d.mts +1 -1
- package/dist/services/definitions/codex.cjs +1 -1
- package/dist/services/definitions/codex.cjs.map +1 -1
- package/dist/services/definitions/codex.d.cts +1 -1
- package/dist/services/definitions/codex.d.mts +1 -1
- package/dist/services/definitions/codex.mjs +1 -1
- package/dist/services/definitions/codex.mjs.map +1 -1
- package/dist/services/definitions/comfyui.d.cts +1 -1
- package/dist/services/definitions/comfyui.d.mts +1 -1
- package/dist/services/definitions/convex-dashboard.d.cts +1 -1
- package/dist/services/definitions/convex-dashboard.d.mts +1 -1
- package/dist/services/definitions/convex.cjs.map +1 -1
- package/dist/services/definitions/convex.d.cts +1 -1
- package/dist/services/definitions/convex.d.mts +1 -1
- package/dist/services/definitions/convex.mjs.map +1 -1
- package/dist/services/definitions/coolify.d.cts +1 -1
- package/dist/services/definitions/coolify.d.mts +1 -1
- package/dist/services/definitions/copaw.cjs +97 -0
- package/dist/services/definitions/copaw.cjs.map +1 -0
- package/dist/services/definitions/copaw.d.cts +7 -0
- package/dist/services/definitions/copaw.d.cts.map +1 -0
- package/dist/services/definitions/copaw.d.mts +7 -0
- package/dist/services/definitions/copaw.d.mts.map +1 -0
- package/dist/services/definitions/copaw.mjs +96 -0
- package/dist/services/definitions/copaw.mjs.map +1 -0
- package/dist/services/definitions/crowdsec.d.cts +1 -1
- package/dist/services/definitions/crowdsec.d.mts +1 -1
- package/dist/services/definitions/dagster.d.cts +1 -1
- package/dist/services/definitions/dagster.d.mts +1 -1
- package/dist/services/definitions/desktop-environment.cjs +2 -1
- package/dist/services/definitions/desktop-environment.cjs.map +1 -1
- package/dist/services/definitions/desktop-environment.d.cts +1 -1
- package/dist/services/definitions/desktop-environment.d.mts +1 -1
- package/dist/services/definitions/desktop-environment.mjs +2 -1
- package/dist/services/definitions/desktop-environment.mjs.map +1 -1
- package/dist/services/definitions/dify.d.cts +1 -1
- package/dist/services/definitions/dify.d.mts +1 -1
- package/dist/services/definitions/directus.d.cts +1 -1
- package/dist/services/definitions/directus.d.mts +1 -1
- package/dist/services/definitions/docsgpt.d.cts +1 -1
- package/dist/services/definitions/docsgpt.d.mts +1 -1
- package/dist/services/definitions/dokploy.d.cts +1 -1
- package/dist/services/definitions/dokploy.d.mts +1 -1
- package/dist/services/definitions/dozzle.d.cts +1 -1
- package/dist/services/definitions/dozzle.d.mts +1 -1
- package/dist/services/definitions/dragonfly.d.cts +1 -1
- package/dist/services/definitions/dragonfly.d.mts +1 -1
- package/dist/services/definitions/drone-ci.d.cts +1 -1
- package/dist/services/definitions/drone-ci.d.mts +1 -1
- package/dist/services/definitions/duplicati.d.cts +1 -1
- package/dist/services/definitions/duplicati.d.mts +1 -1
- package/dist/services/definitions/element-web.d.cts +1 -1
- package/dist/services/definitions/element-web.d.mts +1 -1
- package/dist/services/definitions/excalidraw.d.cts +1 -1
- package/dist/services/definitions/excalidraw.d.mts +1 -1
- package/dist/services/definitions/ffmpeg.d.cts +1 -1
- package/dist/services/definitions/ffmpeg.d.mts +1 -1
- package/dist/services/definitions/firecrawl-playwright.d.cts +1 -1
- package/dist/services/definitions/firecrawl-playwright.d.mts +1 -1
- package/dist/services/definitions/firecrawl.d.cts +1 -1
- package/dist/services/definitions/firecrawl.d.mts +1 -1
- package/dist/services/definitions/flagsmith.d.cts +1 -1
- package/dist/services/definitions/flagsmith.d.mts +1 -1
- package/dist/services/definitions/flowise.d.cts +1 -1
- package/dist/services/definitions/flowise.d.mts +1 -1
- package/dist/services/definitions/focalboard.d.cts +1 -1
- package/dist/services/definitions/focalboard.d.mts +1 -1
- package/dist/services/definitions/fonoster.d.cts +1 -1
- package/dist/services/definitions/fonoster.d.mts +1 -1
- package/dist/services/definitions/forgejo.d.cts +1 -1
- package/dist/services/definitions/forgejo.d.mts +1 -1
- package/dist/services/definitions/formbricks.d.cts +1 -1
- package/dist/services/definitions/formbricks.d.mts +1 -1
- package/dist/services/definitions/gemini-cli.d.cts +1 -1
- package/dist/services/definitions/gemini-cli.d.mts +1 -1
- package/dist/services/definitions/ghost.d.cts +1 -1
- package/dist/services/definitions/ghost.d.mts +1 -1
- package/dist/services/definitions/gitea.d.cts +1 -1
- package/dist/services/definitions/gitea.d.mts +1 -1
- package/dist/services/definitions/gotify.d.cts +1 -1
- package/dist/services/definitions/gotify.d.mts +1 -1
- package/dist/services/definitions/grafana.d.cts +1 -1
- package/dist/services/definitions/grafana.d.mts +1 -1
- package/dist/services/definitions/graylog.d.cts +1 -1
- package/dist/services/definitions/graylog.d.mts +1 -1
- package/dist/services/definitions/headscale.d.cts +1 -1
- package/dist/services/definitions/headscale.d.mts +1 -1
- package/dist/services/definitions/hedgedoc.d.cts +1 -1
- package/dist/services/definitions/hedgedoc.d.mts +1 -1
- package/dist/services/definitions/hexstrike.d.cts +1 -1
- package/dist/services/definitions/hexstrike.d.mts +1 -1
- package/dist/services/definitions/heyform.d.cts +1 -1
- package/dist/services/definitions/heyform.d.mts +1 -1
- package/dist/services/definitions/hindsight.cjs +4 -1
- package/dist/services/definitions/hindsight.cjs.map +1 -1
- package/dist/services/definitions/hindsight.d.cts +1 -1
- package/dist/services/definitions/hindsight.d.mts +1 -1
- package/dist/services/definitions/hindsight.mjs +4 -1
- package/dist/services/definitions/hindsight.mjs.map +1 -1
- package/dist/services/definitions/homeassistant.d.cts +1 -1
- package/dist/services/definitions/homeassistant.d.mts +1 -1
- package/dist/services/definitions/hoppscotch.d.cts +1 -1
- package/dist/services/definitions/hoppscotch.d.mts +1 -1
- package/dist/services/definitions/immich.d.cts +1 -1
- package/dist/services/definitions/immich.d.mts +1 -1
- package/dist/services/definitions/index.cjs +42 -6
- package/dist/services/definitions/index.cjs.map +1 -1
- package/dist/services/definitions/index.d.cts +16 -4
- package/dist/services/definitions/index.d.cts.map +1 -1
- package/dist/services/definitions/index.d.mts +16 -4
- package/dist/services/definitions/index.d.mts.map +1 -1
- package/dist/services/definitions/index.mjs +31 -7
- package/dist/services/definitions/index.mjs.map +1 -1
- package/dist/services/definitions/infisical.d.cts +1 -1
- package/dist/services/definitions/infisical.d.mts +1 -1
- package/dist/services/definitions/influxdb.d.cts +1 -1
- package/dist/services/definitions/influxdb.d.mts +1 -1
- package/dist/services/definitions/invoke-ai.d.cts +1 -1
- package/dist/services/definitions/invoke-ai.d.mts +1 -1
- package/dist/services/definitions/ixartz-saas.d.cts +1 -1
- package/dist/services/definitions/ixartz-saas.d.mts +1 -1
- package/dist/services/definitions/jaeger.d.cts +1 -1
- package/dist/services/definitions/jaeger.d.mts +1 -1
- package/dist/services/definitions/jan.d.cts +1 -1
- package/dist/services/definitions/jan.d.mts +1 -1
- package/dist/services/definitions/jellyfin.d.cts +1 -1
- package/dist/services/definitions/jellyfin.d.mts +1 -1
- package/dist/services/definitions/jenkins.d.cts +1 -1
- package/dist/services/definitions/jenkins.d.mts +1 -1
- package/dist/services/definitions/jitsi-meet.d.cts +1 -1
- package/dist/services/definitions/jitsi-meet.d.mts +1 -1
- package/dist/services/definitions/keycloak.d.cts +1 -1
- package/dist/services/definitions/keycloak.d.mts +1 -1
- package/dist/services/definitions/kimi.d.cts +1 -1
- package/dist/services/definitions/kimi.d.mts +1 -1
- package/dist/services/definitions/kong.d.cts +1 -1
- package/dist/services/definitions/kong.d.mts +1 -1
- package/dist/services/definitions/lago.d.cts +1 -1
- package/dist/services/definitions/lago.d.mts +1 -1
- package/dist/services/definitions/langflow.d.cts +1 -1
- package/dist/services/definitions/langflow.d.mts +1 -1
- package/dist/services/definitions/langfuse.d.cts +1 -1
- package/dist/services/definitions/langfuse.d.mts +1 -1
- package/dist/services/definitions/lasuite-meet-agents.d.cts +1 -1
- package/dist/services/definitions/lasuite-meet-agents.d.mts +1 -1
- package/dist/services/definitions/lasuite-meet-backend.d.cts +1 -1
- package/dist/services/definitions/lasuite-meet-backend.d.mts +1 -1
- package/dist/services/definitions/lasuite-meet-frontend.d.cts +1 -1
- package/dist/services/definitions/lasuite-meet-frontend.d.mts +1 -1
- package/dist/services/definitions/librechat.d.cts +1 -1
- package/dist/services/definitions/librechat.d.mts +1 -1
- package/dist/services/definitions/lightpanda.d.cts +1 -1
- package/dist/services/definitions/lightpanda.d.mts +1 -1
- package/dist/services/definitions/listmonk.d.cts +1 -1
- package/dist/services/definitions/listmonk.d.mts +1 -1
- package/dist/services/definitions/litellm.d.cts +1 -1
- package/dist/services/definitions/litellm.d.mts +1 -1
- package/dist/services/definitions/livekit.d.cts +1 -1
- package/dist/services/definitions/livekit.d.mts +1 -1
- package/dist/services/definitions/local-ai.d.cts +1 -1
- package/dist/services/definitions/local-ai.d.mts +1 -1
- package/dist/services/definitions/loki.d.cts +1 -1
- package/dist/services/definitions/loki.d.mts +1 -1
- package/dist/services/definitions/mariadb.d.cts +1 -1
- package/dist/services/definitions/mariadb.d.mts +1 -1
- package/dist/services/definitions/matomo.d.cts +1 -1
- package/dist/services/definitions/matomo.d.mts +1 -1
- package/dist/services/definitions/matrix-synapse.d.cts +1 -1
- package/dist/services/definitions/matrix-synapse.d.mts +1 -1
- package/dist/services/definitions/mattermost.d.cts +1 -1
- package/dist/services/definitions/mattermost.d.mts +1 -1
- package/dist/services/definitions/mautic.d.cts +1 -1
- package/dist/services/definitions/mautic.d.mts +1 -1
- package/dist/services/definitions/medusa.d.cts +1 -1
- package/dist/services/definitions/medusa.d.mts +1 -1
- package/dist/services/definitions/meilisearch.d.cts +1 -1
- package/dist/services/definitions/meilisearch.d.mts +1 -1
- package/dist/services/definitions/mem0.cjs +133 -0
- package/dist/services/definitions/mem0.cjs.map +1 -0
- package/dist/services/definitions/mem0.d.cts +7 -0
- package/dist/services/definitions/mem0.d.cts.map +1 -0
- package/dist/services/definitions/mem0.d.mts +7 -0
- package/dist/services/definitions/mem0.d.mts.map +1 -0
- package/dist/services/definitions/mem0.mjs +132 -0
- package/dist/services/definitions/mem0.mjs.map +1 -0
- package/dist/services/definitions/memu.cjs +96 -0
- package/dist/services/definitions/memu.cjs.map +1 -0
- package/dist/services/definitions/memu.d.cts +7 -0
- package/dist/services/definitions/memu.d.cts.map +1 -0
- package/dist/services/definitions/memu.d.mts +7 -0
- package/dist/services/definitions/memu.d.mts.map +1 -0
- package/dist/services/definitions/memu.mjs +95 -0
- package/dist/services/definitions/memu.mjs.map +1 -0
- package/dist/services/definitions/metabase.d.cts +1 -1
- package/dist/services/definitions/metabase.d.mts +1 -1
- package/dist/services/definitions/milvus.cjs +4 -1
- package/dist/services/definitions/milvus.cjs.map +1 -1
- package/dist/services/definitions/milvus.d.cts +1 -1
- package/dist/services/definitions/milvus.d.mts +1 -1
- package/dist/services/definitions/milvus.mjs +4 -1
- package/dist/services/definitions/milvus.mjs.map +1 -1
- package/dist/services/definitions/minio.d.cts +1 -1
- package/dist/services/definitions/minio.d.mts +1 -1
- package/dist/services/definitions/mission-control.d.cts +1 -1
- package/dist/services/definitions/mission-control.d.mts +1 -1
- package/dist/services/definitions/mixpost.d.cts +1 -1
- package/dist/services/definitions/mixpost.d.mts +1 -1
- package/dist/services/definitions/mosquitto.d.cts +1 -1
- package/dist/services/definitions/mosquitto.d.mts +1 -1
- package/dist/services/definitions/motion-canvas.d.cts +1 -1
- package/dist/services/definitions/motion-canvas.d.mts +1 -1
- package/dist/services/definitions/mysql.d.cts +1 -1
- package/dist/services/definitions/mysql.d.mts +1 -1
- package/dist/services/definitions/n8n.d.cts +1 -1
- package/dist/services/definitions/n8n.d.mts +1 -1
- package/dist/services/definitions/nanobot.cjs +86 -0
- package/dist/services/definitions/nanobot.cjs.map +1 -0
- package/dist/services/definitions/nanobot.d.cts +7 -0
- package/dist/services/definitions/nanobot.d.cts.map +1 -0
- package/dist/services/definitions/nanobot.d.mts +7 -0
- package/dist/services/definitions/nanobot.d.mts.map +1 -0
- package/dist/services/definitions/nanobot.mjs +85 -0
- package/dist/services/definitions/nanobot.mjs.map +1 -0
- package/dist/services/definitions/nanoclaw.cjs +79 -0
- package/dist/services/definitions/nanoclaw.cjs.map +1 -0
- package/dist/services/definitions/nanoclaw.d.cts +7 -0
- package/dist/services/definitions/nanoclaw.d.cts.map +1 -0
- package/dist/services/definitions/nanoclaw.d.mts +7 -0
- package/dist/services/definitions/nanoclaw.d.mts.map +1 -0
- package/dist/services/definitions/nanoclaw.mjs +78 -0
- package/dist/services/definitions/nanoclaw.mjs.map +1 -0
- package/dist/services/definitions/navidrome.d.cts +1 -1
- package/dist/services/definitions/navidrome.d.mts +1 -1
- package/dist/services/definitions/neo4j.d.cts +1 -1
- package/dist/services/definitions/neo4j.d.mts +1 -1
- package/dist/services/definitions/nextcloud.d.cts +1 -1
- package/dist/services/definitions/nextcloud.d.mts +1 -1
- package/dist/services/definitions/nginx-proxy-manager.d.cts +1 -1
- package/dist/services/definitions/nginx-proxy-manager.d.mts +1 -1
- package/dist/services/definitions/nocodb.d.cts +1 -1
- package/dist/services/definitions/nocodb.d.mts +1 -1
- package/dist/services/definitions/node-red.d.cts +1 -1
- package/dist/services/definitions/node-red.d.mts +1 -1
- package/dist/services/definitions/ntfy.d.cts +1 -1
- package/dist/services/definitions/ntfy.d.mts +1 -1
- package/dist/services/definitions/ollama.d.cts +1 -1
- package/dist/services/definitions/ollama.d.mts +1 -1
- package/dist/services/definitions/open-saas.d.cts +1 -1
- package/dist/services/definitions/open-saas.d.mts +1 -1
- package/dist/services/definitions/open-webui.d.cts +1 -1
- package/dist/services/definitions/open-webui.d.mts +1 -1
- package/dist/services/definitions/opencode.d.cts +1 -1
- package/dist/services/definitions/opencode.d.mts +1 -1
- package/dist/services/definitions/openhands.d.cts +1 -1
- package/dist/services/definitions/openhands.d.mts +1 -1
- package/dist/services/definitions/openpanel.d.cts +1 -1
- package/dist/services/definitions/openpanel.d.mts +1 -1
- package/dist/services/definitions/opensandbox.cjs +2 -1
- package/dist/services/definitions/opensandbox.cjs.map +1 -1
- package/dist/services/definitions/opensandbox.d.cts +1 -1
- package/dist/services/definitions/opensandbox.d.mts +1 -1
- package/dist/services/definitions/opensandbox.mjs +2 -1
- package/dist/services/definitions/opensandbox.mjs.map +1 -1
- package/dist/services/definitions/opensearch.d.cts +1 -1
- package/dist/services/definitions/opensearch.d.mts +1 -1
- package/dist/services/definitions/outline.d.cts +1 -1
- package/dist/services/definitions/outline.d.mts +1 -1
- package/dist/services/definitions/paperless-ngx.d.cts +1 -1
- package/dist/services/definitions/paperless-ngx.d.mts +1 -1
- package/dist/services/definitions/pentagi.d.cts +1 -1
- package/dist/services/definitions/pentagi.d.mts +1 -1
- package/dist/services/definitions/pentestagent.d.cts +1 -1
- package/dist/services/definitions/pentestagent.d.mts +1 -1
- package/dist/services/definitions/photoprism.d.cts +1 -1
- package/dist/services/definitions/photoprism.d.mts +1 -1
- package/dist/services/definitions/pihole.d.cts +1 -1
- package/dist/services/definitions/pihole.d.mts +1 -1
- package/dist/services/definitions/piper-tts.d.cts +1 -1
- package/dist/services/definitions/piper-tts.d.mts +1 -1
- package/dist/services/definitions/plane.d.cts +1 -1
- package/dist/services/definitions/plane.d.mts +1 -1
- package/dist/services/definitions/plausible.d.cts +1 -1
- package/dist/services/definitions/plausible.d.mts +1 -1
- package/dist/services/definitions/playwright-server.d.cts +1 -1
- package/dist/services/definitions/playwright-server.d.mts +1 -1
- package/dist/services/definitions/pocket-id.d.cts +1 -1
- package/dist/services/definitions/pocket-id.d.mts +1 -1
- package/dist/services/definitions/pocketbase.d.cts +1 -1
- package/dist/services/definitions/pocketbase.d.mts +1 -1
- package/dist/services/definitions/portainer.d.cts +1 -1
- package/dist/services/definitions/portainer.d.mts +1 -1
- package/dist/services/definitions/postgresql.d.cts +1 -1
- package/dist/services/definitions/postgresql.d.mts +1 -1
- package/dist/services/definitions/posthog.d.cts +1 -1
- package/dist/services/definitions/posthog.d.mts +1 -1
- package/dist/services/definitions/postiz.d.cts +1 -1
- package/dist/services/definitions/postiz.d.mts +1 -1
- package/dist/services/definitions/prometheus.d.cts +1 -1
- package/dist/services/definitions/prometheus.d.mts +1 -1
- package/dist/services/definitions/qdrant.d.cts +1 -1
- package/dist/services/definitions/qdrant.d.mts +1 -1
- package/dist/services/definitions/rabbitmq.d.cts +1 -1
- package/dist/services/definitions/rabbitmq.d.mts +1 -1
- package/dist/services/definitions/ragflow.d.cts +1 -1
- package/dist/services/definitions/ragflow.d.mts +1 -1
- package/dist/services/definitions/redis.d.cts +1 -1
- package/dist/services/definitions/redis.d.mts +1 -1
- package/dist/services/definitions/relaticle-horizon.cjs +48 -0
- package/dist/services/definitions/relaticle-horizon.cjs.map +1 -0
- package/dist/services/definitions/relaticle-horizon.d.cts +7 -0
- package/dist/services/definitions/relaticle-horizon.d.cts.map +1 -0
- package/dist/services/definitions/relaticle-horizon.d.mts +7 -0
- package/dist/services/definitions/relaticle-horizon.d.mts.map +1 -0
- package/dist/services/definitions/relaticle-horizon.mjs +48 -0
- package/dist/services/definitions/relaticle-horizon.mjs.map +1 -0
- package/dist/services/definitions/relaticle-scheduler.cjs +44 -0
- package/dist/services/definitions/relaticle-scheduler.cjs.map +1 -0
- package/dist/services/definitions/relaticle-scheduler.d.cts +7 -0
- package/dist/services/definitions/relaticle-scheduler.d.cts.map +1 -0
- package/dist/services/definitions/relaticle-scheduler.d.mts +7 -0
- package/dist/services/definitions/relaticle-scheduler.d.mts.map +1 -0
- package/dist/services/definitions/relaticle-scheduler.mjs +44 -0
- package/dist/services/definitions/relaticle-scheduler.mjs.map +1 -0
- package/dist/services/definitions/relaticle.cjs +151 -0
- package/dist/services/definitions/relaticle.cjs.map +1 -0
- package/dist/services/definitions/relaticle.d.cts +80 -0
- package/dist/services/definitions/relaticle.d.cts.map +1 -0
- package/dist/services/definitions/relaticle.d.mts +80 -0
- package/dist/services/definitions/relaticle.d.mts.map +1 -0
- package/dist/services/definitions/relaticle.mjs +149 -0
- package/dist/services/definitions/relaticle.mjs.map +1 -0
- package/dist/services/definitions/remotion.d.cts +1 -1
- package/dist/services/definitions/remotion.d.mts +1 -1
- package/dist/services/definitions/restic.d.cts +1 -1
- package/dist/services/definitions/restic.d.mts +1 -1
- package/dist/services/definitions/revolt.d.cts +1 -1
- package/dist/services/definitions/revolt.d.mts +1 -1
- package/dist/services/definitions/rocketchat.d.cts +1 -1
- package/dist/services/definitions/rocketchat.d.mts +1 -1
- package/dist/services/definitions/saleor.d.cts +1 -1
- package/dist/services/definitions/saleor.d.mts +1 -1
- package/dist/services/definitions/scrapling.d.cts +1 -1
- package/dist/services/definitions/scrapling.d.mts +1 -1
- package/dist/services/definitions/searxng.d.cts +1 -1
- package/dist/services/definitions/searxng.d.mts +1 -1
- package/dist/services/definitions/sentry.d.cts +1 -1
- package/dist/services/definitions/sentry.d.mts +1 -1
- package/dist/services/definitions/signoz.d.cts +1 -1
- package/dist/services/definitions/signoz.d.mts +1 -1
- package/dist/services/definitions/solidityguard.d.cts +1 -1
- package/dist/services/definitions/solidityguard.d.mts +1 -1
- package/dist/services/definitions/sonarqube.d.cts +1 -1
- package/dist/services/definitions/sonarqube.d.mts +1 -1
- package/dist/services/definitions/stable-diffusion.d.cts +1 -1
- package/dist/services/definitions/stable-diffusion.d.mts +1 -1
- package/dist/services/definitions/steel-browser.d.cts +1 -1
- package/dist/services/definitions/steel-browser.d.mts +1 -1
- package/dist/services/definitions/stirling-pdf.d.cts +1 -1
- package/dist/services/definitions/stirling-pdf.d.mts +1 -1
- package/dist/services/definitions/strapi.d.cts +1 -1
- package/dist/services/definitions/strapi.d.mts +1 -1
- package/dist/services/definitions/stream-gateway.d.cts +1 -1
- package/dist/services/definitions/stream-gateway.d.mts +1 -1
- package/dist/services/definitions/supabase.d.cts +1 -1
- package/dist/services/definitions/supabase.d.mts +1 -1
- package/dist/services/definitions/superset.d.cts +1 -1
- package/dist/services/definitions/superset.d.mts +1 -1
- package/dist/services/definitions/surrealdb.d.cts +1 -1
- package/dist/services/definitions/surrealdb.d.mts +1 -1
- package/dist/services/definitions/tabby-ml.d.cts +1 -1
- package/dist/services/definitions/tabby-ml.d.mts +1 -1
- package/dist/services/definitions/tailscale.d.cts +1 -1
- package/dist/services/definitions/tailscale.d.mts +1 -1
- package/dist/services/definitions/tempo.d.cts +1 -1
- package/dist/services/definitions/tempo.d.mts +1 -1
- package/dist/services/definitions/temporal.d.cts +1 -1
- package/dist/services/definitions/temporal.d.mts +1 -1
- package/dist/services/definitions/text-gen-webui.d.cts +1 -1
- package/dist/services/definitions/text-gen-webui.d.mts +1 -1
- package/dist/services/definitions/timescaledb.d.cts +1 -1
- package/dist/services/definitions/timescaledb.d.mts +1 -1
- package/dist/services/definitions/traefik.d.cts +1 -1
- package/dist/services/definitions/traefik.d.mts +1 -1
- package/dist/services/definitions/twenty-worker.cjs +73 -0
- package/dist/services/definitions/twenty-worker.cjs.map +1 -0
- package/dist/services/definitions/twenty-worker.d.cts +7 -0
- package/dist/services/definitions/twenty-worker.d.cts.map +1 -0
- package/dist/services/definitions/twenty-worker.d.mts +7 -0
- package/dist/services/definitions/twenty-worker.d.mts.map +1 -0
- package/dist/services/definitions/twenty-worker.mjs +72 -0
- package/dist/services/definitions/twenty-worker.mjs.map +1 -0
- package/dist/services/definitions/twenty.cjs +24 -2
- package/dist/services/definitions/twenty.cjs.map +1 -1
- package/dist/services/definitions/twenty.d.cts +1 -1
- package/dist/services/definitions/twenty.d.mts +1 -1
- package/dist/services/definitions/twenty.mjs +24 -2
- package/dist/services/definitions/twenty.mjs.map +1 -1
- package/dist/services/definitions/umami.d.cts +1 -1
- package/dist/services/definitions/umami.d.mts +1 -1
- package/dist/services/definitions/uptime-kuma.d.cts +1 -1
- package/dist/services/definitions/uptime-kuma.d.mts +1 -1
- package/dist/services/definitions/usesend.d.cts +1 -1
- package/dist/services/definitions/usesend.d.mts +1 -1
- package/dist/services/definitions/valkey.d.cts +1 -1
- package/dist/services/definitions/valkey.d.mts +1 -1
- package/dist/services/definitions/vault.d.cts +1 -1
- package/dist/services/definitions/vault.d.mts +1 -1
- package/dist/services/definitions/vaultwarden.d.cts +1 -1
- package/dist/services/definitions/vaultwarden.d.mts +1 -1
- package/dist/services/definitions/vector-log.d.cts +1 -1
- package/dist/services/definitions/vector-log.d.mts +1 -1
- package/dist/services/definitions/vikunja.d.cts +1 -1
- package/dist/services/definitions/vikunja.d.mts +1 -1
- package/dist/services/definitions/watchtower.d.cts +1 -1
- package/dist/services/definitions/watchtower.d.mts +1 -1
- package/dist/services/definitions/weaviate.cjs +4 -1
- package/dist/services/definitions/weaviate.cjs.map +1 -1
- package/dist/services/definitions/weaviate.d.cts +1 -1
- package/dist/services/definitions/weaviate.d.mts +1 -1
- package/dist/services/definitions/weaviate.mjs +4 -1
- package/dist/services/definitions/weaviate.mjs.map +1 -1
- package/dist/services/definitions/whisper.d.cts +1 -1
- package/dist/services/definitions/whisper.d.mts +1 -1
- package/dist/services/definitions/wireguard.d.cts +1 -1
- package/dist/services/definitions/wireguard.d.mts +1 -1
- package/dist/services/definitions/woodpecker-ci.d.cts +1 -1
- package/dist/services/definitions/woodpecker-ci.d.mts +1 -1
- package/dist/services/definitions/xyops.d.cts +1 -1
- package/dist/services/definitions/xyops.d.mts +1 -1
- package/dist/services/definitions/zeroclaw.cjs +103 -0
- package/dist/services/definitions/zeroclaw.cjs.map +1 -0
- package/dist/services/definitions/zeroclaw.d.cts +7 -0
- package/dist/services/definitions/zeroclaw.d.cts.map +1 -0
- package/dist/services/definitions/zeroclaw.d.mts +7 -0
- package/dist/services/definitions/zeroclaw.d.mts.map +1 -0
- package/dist/services/definitions/zeroclaw.mjs +102 -0
- package/dist/services/definitions/zeroclaw.mjs.map +1 -0
- package/dist/services/definitions/zulip.d.cts +1 -1
- package/dist/services/definitions/zulip.d.mts +1 -1
- package/dist/services/registry.d.cts +1 -1
- package/dist/services/registry.d.mts +1 -1
- package/dist/services/registry.test.cjs +8 -8
- package/dist/services/registry.test.cjs.map +1 -1
- package/dist/services/registry.test.mjs +8 -8
- package/dist/services/registry.test.mjs.map +1 -1
- package/dist/skills/registry.cjs +19 -0
- package/dist/skills/registry.cjs.map +1 -1
- package/dist/skills/registry.d.cts +1 -1
- package/dist/skills/registry.d.cts.map +1 -1
- package/dist/skills/registry.d.mts +1 -1
- package/dist/skills/registry.d.mts.map +1 -1
- package/dist/skills/registry.mjs +19 -0
- package/dist/skills/registry.mjs.map +1 -1
- package/dist/{skills-BSF7iNa4.cjs → skills-uPxJVmKk.cjs} +311 -1
- package/dist/skills-uPxJVmKk.cjs.map +1 -0
- package/dist/{test.CTcmp4Su-ClCHJ3FA.mjs → test.CTcmp4Su-BRa7-bTj.mjs} +2 -2
- package/dist/{test.CTcmp4Su-ClCHJ3FA.mjs.map → test.CTcmp4Su-BRa7-bTj.mjs.map} +1 -1
- package/dist/{test.CTcmp4Su-DlzTarwH.cjs → test.CTcmp4Su-BWSPM8ZQ.cjs} +19 -1
- package/dist/{test.CTcmp4Su-DlzTarwH.cjs.map → test.CTcmp4Su-BWSPM8ZQ.cjs.map} +1 -1
- package/dist/track-analytics.d.cts +1 -1
- package/dist/track-analytics.d.mts +1 -1
- package/dist/track-analytics.test.cjs +1 -1
- package/dist/track-analytics.test.mjs +1 -1
- package/dist/types-BREUfzzq.d.mts +77 -0
- package/dist/types-BREUfzzq.d.mts.map +1 -0
- package/dist/types-Bsn0XzSP.d.cts +95 -0
- package/dist/types-Bsn0XzSP.d.cts.map +1 -0
- package/dist/types-CyZ5mn6w.d.cts +77 -0
- package/dist/types-CyZ5mn6w.d.cts.map +1 -0
- package/dist/types-DIsPc-hb.d.cts +100 -0
- package/dist/types-DIsPc-hb.d.cts.map +1 -0
- package/dist/types-DbXajvYq.d.mts +100 -0
- package/dist/types-DbXajvYq.d.mts.map +1 -0
- package/dist/types-DwTKyCZ9.d.mts +95 -0
- package/dist/types-DwTKyCZ9.d.mts.map +1 -0
- package/dist/{types-CR83OJiq.d.cts → types-dyBnrHm9.d.cts} +5 -1
- package/dist/types-dyBnrHm9.d.cts.map +1 -0
- package/dist/{types-zYjGTuyn.d.mts → types-fRSnaZTX.d.mts} +5 -1
- package/dist/types-fRSnaZTX.d.mts.map +1 -0
- package/dist/types.cjs +7 -0
- package/dist/types.cjs.map +1 -1
- package/dist/types.d.cts +2 -93
- package/dist/types.d.mts +2 -93
- package/dist/types.mjs +7 -0
- package/dist/types.mjs.map +1 -1
- package/dist/validator.cjs +1 -1
- package/dist/validator.d.cts +1 -1
- package/dist/validator.d.mts +1 -1
- package/dist/validator.test.cjs +1 -1
- package/dist/validator.test.mjs +1 -1
- package/dist/version-manager.d.cts +1 -1
- package/dist/version-manager.d.mts +1 -1
- package/dist/version-manager.test.cjs +3 -3
- package/dist/version-manager.test.cjs.map +1 -1
- package/dist/version-manager.test.mjs +3 -3
- package/dist/version-manager.test.mjs.map +1 -1
- package/dist/zeroclaw-B-0TuOfZ.d.mts +7 -0
- package/dist/zeroclaw-B-0TuOfZ.d.mts.map +1 -0
- package/dist/zeroclaw-BvKpDHKe.d.cts +7 -0
- package/dist/zeroclaw-BvKpDHKe.d.cts.map +1 -0
- package/package.json +6 -2
- package/src/addon-stack.test.ts +19 -23
- package/src/addon-stack.ts +67 -44
- package/src/composer.test.ts +59 -0
- package/src/composer.ts +135 -194
- package/src/deployers/coolify.test.ts +180 -0
- package/src/deployers/coolify.ts +38 -0
- package/src/deployers/dokploy.test.ts +120 -0
- package/src/deployers/dokploy.ts +38 -0
- package/src/deployers/types.ts +2 -0
- package/src/frameworks/claude-code-fw.ts +118 -0
- package/src/frameworks/codex-fw.ts +102 -0
- package/src/frameworks/copaw.ts +154 -0
- package/src/frameworks/frameworks.test.ts +119 -0
- package/src/frameworks/index.ts +46 -0
- package/src/frameworks/memu.ts +149 -0
- package/src/frameworks/nanobot.ts +156 -0
- package/src/frameworks/nanoclaw.ts +126 -0
- package/src/frameworks/openclaw.ts +325 -0
- package/src/frameworks/registry.test.ts +131 -0
- package/src/frameworks/registry.ts +28 -0
- package/src/frameworks/types.ts +146 -0
- package/src/frameworks/zeroclaw.ts +148 -0
- package/src/generate.test.ts +55 -4
- package/src/generate.ts +67 -14
- package/src/generators/caddy.test.ts +41 -1
- package/src/generators/caddy.ts +16 -2
- package/src/generators/clone-repos.test.ts +1 -1
- package/src/generators/clone-repos.ts +7 -2
- package/src/generators/cloud-init.test.ts +70 -0
- package/src/generators/env.test.ts +2 -2
- package/src/generators/env.ts +30 -180
- package/src/generators/get-shit-done.test.ts +54 -0
- package/src/generators/grafana.test.ts +90 -0
- package/src/generators/health-check.ts +4 -4
- package/src/generators/n8n-workflows.test.ts +80 -0
- package/src/generators/openclaw-install-script.test.ts +42 -0
- package/src/generators/openclaw-json.ts +57 -5
- package/src/generators/postgres-init.test.ts +116 -0
- package/src/generators/postgres-init.ts +9 -0
- package/src/generators/prometheus.test.ts +108 -0
- package/src/generators/readme.ts +75 -9
- package/src/generators/scripts.test.ts +1 -1
- package/src/generators/skills.ts +316 -0
- package/src/generators/stack-manifest.test.ts +104 -0
- package/src/generators/traefik.test.ts +13 -13
- package/src/index.ts +47 -7
- package/src/logger/__tests__/logger.test.ts +388 -0
- package/src/logger/index.ts +15 -0
- package/src/logger/logger.ts +326 -0
- package/src/logger/sinks/callback-sink.ts +13 -0
- package/src/logger/sinks/console-sink.ts +51 -0
- package/src/logger/sinks/file-sink.ts +121 -0
- package/src/logger/types.ts +90 -0
- package/src/migrations.ts +8 -1
- package/src/port-scanner.test.ts +167 -0
- package/src/presets/presets.test.ts +4 -4
- package/src/presets/registry.test.ts +6 -6
- package/src/resolver.test.ts +31 -3
- package/src/resolver.ts +19 -3
- package/src/schema.test.ts +2 -2
- package/src/schema.ts +58 -17
- package/src/services/definitions/agent-browser.ts +177 -0
- package/src/services/definitions/apptension-saas.ts +2 -1
- package/src/services/definitions/chromadb.ts +1 -1
- package/src/services/definitions/claude-code.ts +1 -1
- package/src/services/definitions/clawrouter.ts +141 -0
- package/src/services/definitions/codex.ts +1 -1
- package/src/services/definitions/convex.ts +1 -2
- package/src/services/definitions/copaw.ts +101 -0
- package/src/services/definitions/desktop-environment.ts +1 -0
- package/src/services/definitions/hindsight.ts +3 -2
- package/src/services/definitions/index.ts +53 -16
- package/src/services/definitions/mem0.ts +132 -0
- package/src/services/definitions/memu.ts +96 -0
- package/src/services/definitions/milvus.ts +1 -1
- package/src/services/definitions/nanobot.ts +89 -0
- package/src/services/definitions/nanoclaw.ts +78 -0
- package/src/services/definitions/opensandbox.ts +6 -15
- package/src/services/definitions/relaticle-horizon.ts +48 -0
- package/src/services/definitions/relaticle-scheduler.ts +42 -0
- package/src/services/definitions/relaticle.ts +142 -0
- package/src/services/definitions/twenty-worker.ts +70 -0
- package/src/services/definitions/twenty.ts +16 -2
- package/src/services/definitions/weaviate.ts +1 -1
- package/src/services/definitions/zeroclaw.ts +102 -0
- package/src/services/registry.test.ts +7 -7
- package/src/skills/registry.ts +10 -0
- package/src/types.ts +11 -1
- package/src/version-manager.test.ts +2 -2
- package/dist/schema-BQnZrcw8.d.cts.map +0 -1
- package/dist/schema-SBpL0bdI.d.mts.map +0 -1
- package/dist/skills-BSF7iNa4.cjs.map +0 -1
- package/dist/types-CR83OJiq.d.cts.map +0 -1
- package/dist/types-zYjGTuyn.d.mts.map +0 -1
- package/dist/types.d.cts.map +0 -1
- package/dist/types.d.mts.map +0 -1
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
const require_test_CTcmp4Su = require("../test.CTcmp4Su-BWSPM8ZQ.cjs");
|
|
2
|
+
//#region src/deployers/coolify.test.ts
|
|
3
|
+
/**
|
|
4
|
+
* Tests for Coolify deployer utility functions and deploy orchestration.
|
|
5
|
+
*
|
|
6
|
+
* We mock `fetch` to simulate Coolify API responses and test the
|
|
7
|
+
* multi-step deployment flow without making real HTTP requests.
|
|
8
|
+
*/
|
|
9
|
+
function hashString(str) {
|
|
10
|
+
let hash = 0;
|
|
11
|
+
for (let i = 0; i < str.length; i++) {
|
|
12
|
+
hash = (hash << 5) - hash + str.charCodeAt(i);
|
|
13
|
+
hash |= 0;
|
|
14
|
+
}
|
|
15
|
+
return hash;
|
|
16
|
+
}
|
|
17
|
+
function parseEnvContent(envContent) {
|
|
18
|
+
if (!envContent) return [];
|
|
19
|
+
const result = [];
|
|
20
|
+
for (const line of envContent.split("\n")) {
|
|
21
|
+
const trimmed = line.trim();
|
|
22
|
+
if (!trimmed || trimmed.startsWith("#")) continue;
|
|
23
|
+
const idx = trimmed.indexOf("=");
|
|
24
|
+
if (idx <= 0) continue;
|
|
25
|
+
const key = trimmed.slice(0, idx);
|
|
26
|
+
const value = trimmed.slice(idx + 1);
|
|
27
|
+
result.push({
|
|
28
|
+
key,
|
|
29
|
+
value,
|
|
30
|
+
is_preview: false,
|
|
31
|
+
is_build_time: false,
|
|
32
|
+
is_literal: true
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
return result;
|
|
36
|
+
}
|
|
37
|
+
require_test_CTcmp4Su.describe("hashString", () => {
|
|
38
|
+
require_test_CTcmp4Su.it("returns 0 for empty string", () => {
|
|
39
|
+
require_test_CTcmp4Su.globalExpect(hashString("")).toBe(0);
|
|
40
|
+
});
|
|
41
|
+
require_test_CTcmp4Su.it("returns same hash for same input", () => {
|
|
42
|
+
require_test_CTcmp4Su.globalExpect(hashString("hello")).toBe(hashString("hello"));
|
|
43
|
+
});
|
|
44
|
+
require_test_CTcmp4Su.it("returns different hash for different input", () => {
|
|
45
|
+
require_test_CTcmp4Su.globalExpect(hashString("hello")).not.toBe(hashString("world"));
|
|
46
|
+
});
|
|
47
|
+
require_test_CTcmp4Su.it("detects compose changes", () => {
|
|
48
|
+
require_test_CTcmp4Su.globalExpect(hashString("version: '3'\nservices:\n redis:\n image: redis:7")).not.toBe(hashString("version: '3'\nservices:\n redis:\n image: redis:8"));
|
|
49
|
+
});
|
|
50
|
+
});
|
|
51
|
+
require_test_CTcmp4Su.describe("parseEnvContent", () => {
|
|
52
|
+
require_test_CTcmp4Su.it("returns empty array for undefined input", () => {
|
|
53
|
+
require_test_CTcmp4Su.globalExpect(parseEnvContent(void 0)).toEqual([]);
|
|
54
|
+
});
|
|
55
|
+
require_test_CTcmp4Su.it("returns empty array for empty string", () => {
|
|
56
|
+
require_test_CTcmp4Su.globalExpect(parseEnvContent("")).toEqual([]);
|
|
57
|
+
});
|
|
58
|
+
require_test_CTcmp4Su.it("parses simple key=value pairs", () => {
|
|
59
|
+
const result = parseEnvContent("FOO=bar\nBAZ=qux");
|
|
60
|
+
require_test_CTcmp4Su.globalExpect(result).toHaveLength(2);
|
|
61
|
+
require_test_CTcmp4Su.globalExpect(result[0]).toEqual({
|
|
62
|
+
key: "FOO",
|
|
63
|
+
value: "bar",
|
|
64
|
+
is_preview: false,
|
|
65
|
+
is_build_time: false,
|
|
66
|
+
is_literal: true
|
|
67
|
+
});
|
|
68
|
+
});
|
|
69
|
+
require_test_CTcmp4Su.it("skips comments", () => {
|
|
70
|
+
const result = parseEnvContent("# This is a comment\nFOO=bar");
|
|
71
|
+
require_test_CTcmp4Su.globalExpect(result).toHaveLength(1);
|
|
72
|
+
require_test_CTcmp4Su.globalExpect(result[0].key).toBe("FOO");
|
|
73
|
+
});
|
|
74
|
+
require_test_CTcmp4Su.it("skips blank lines", () => {
|
|
75
|
+
require_test_CTcmp4Su.globalExpect(parseEnvContent("FOO=bar\n\n\nBAZ=qux")).toHaveLength(2);
|
|
76
|
+
});
|
|
77
|
+
require_test_CTcmp4Su.it("handles values containing equals signs", () => {
|
|
78
|
+
const result = parseEnvContent("DATABASE_URL=postgres://user:pass@host:5432/db?sslmode=require");
|
|
79
|
+
require_test_CTcmp4Su.globalExpect(result).toHaveLength(1);
|
|
80
|
+
require_test_CTcmp4Su.globalExpect(result[0].key).toBe("DATABASE_URL");
|
|
81
|
+
require_test_CTcmp4Su.globalExpect(result[0].value).toBe("postgres://user:pass@host:5432/db?sslmode=require");
|
|
82
|
+
});
|
|
83
|
+
require_test_CTcmp4Su.it("handles empty values", () => {
|
|
84
|
+
const result = parseEnvContent("EMPTY_VAR=");
|
|
85
|
+
require_test_CTcmp4Su.globalExpect(result).toHaveLength(1);
|
|
86
|
+
require_test_CTcmp4Su.globalExpect(result[0].key).toBe("EMPTY_VAR");
|
|
87
|
+
require_test_CTcmp4Su.globalExpect(result[0].value).toBe("");
|
|
88
|
+
});
|
|
89
|
+
require_test_CTcmp4Su.it("skips lines without = sign", () => {
|
|
90
|
+
const result = parseEnvContent("INVALID_LINE\nVALID=yes");
|
|
91
|
+
require_test_CTcmp4Su.globalExpect(result).toHaveLength(1);
|
|
92
|
+
require_test_CTcmp4Su.globalExpect(result[0].key).toBe("VALID");
|
|
93
|
+
});
|
|
94
|
+
require_test_CTcmp4Su.it("handles quoted values", () => {
|
|
95
|
+
const result = parseEnvContent("PASSWORD=\"my secret\"");
|
|
96
|
+
require_test_CTcmp4Su.globalExpect(result[0].key).toBe("PASSWORD");
|
|
97
|
+
require_test_CTcmp4Su.globalExpect(result[0].value).toBe("\"my secret\"");
|
|
98
|
+
});
|
|
99
|
+
});
|
|
100
|
+
require_test_CTcmp4Su.describe("CoolifyDeployer", () => {
|
|
101
|
+
require_test_CTcmp4Su.beforeEach(() => {
|
|
102
|
+
require_test_CTcmp4Su.vi.restoreAllMocks();
|
|
103
|
+
});
|
|
104
|
+
require_test_CTcmp4Su.it("can be imported and instantiated", async () => {
|
|
105
|
+
const { CoolifyDeployer } = await Promise.resolve().then(() => require("./coolify.cjs"));
|
|
106
|
+
const deployer = new CoolifyDeployer();
|
|
107
|
+
require_test_CTcmp4Su.globalExpect(deployer.name).toBe("Coolify");
|
|
108
|
+
require_test_CTcmp4Su.globalExpect(deployer.id).toBe("coolify");
|
|
109
|
+
});
|
|
110
|
+
require_test_CTcmp4Su.it("testConnection returns error on network failure", async () => {
|
|
111
|
+
require_test_CTcmp4Su.vi.stubGlobal("fetch", require_test_CTcmp4Su.vi.fn().mockRejectedValue(/* @__PURE__ */ new Error("Connection refused")));
|
|
112
|
+
const { CoolifyDeployer } = await Promise.resolve().then(() => require("./coolify.cjs"));
|
|
113
|
+
const result = await new CoolifyDeployer().testConnection({
|
|
114
|
+
instanceUrl: "https://coolify.example.com",
|
|
115
|
+
apiKey: "test-key"
|
|
116
|
+
});
|
|
117
|
+
require_test_CTcmp4Su.globalExpect(result.ok).toBe(false);
|
|
118
|
+
require_test_CTcmp4Su.globalExpect(result.error).toContain("Connection refused");
|
|
119
|
+
require_test_CTcmp4Su.vi.unstubAllGlobals();
|
|
120
|
+
});
|
|
121
|
+
require_test_CTcmp4Su.it("testConnection returns ok on successful version response", async () => {
|
|
122
|
+
require_test_CTcmp4Su.vi.stubGlobal("fetch", require_test_CTcmp4Su.vi.fn().mockResolvedValue({
|
|
123
|
+
ok: true,
|
|
124
|
+
text: () => Promise.resolve("\"v4.0.0\"")
|
|
125
|
+
}));
|
|
126
|
+
const { CoolifyDeployer } = await Promise.resolve().then(() => require("./coolify.cjs"));
|
|
127
|
+
require_test_CTcmp4Su.globalExpect((await new CoolifyDeployer().testConnection({
|
|
128
|
+
instanceUrl: "https://coolify.example.com",
|
|
129
|
+
apiKey: "test-key"
|
|
130
|
+
})).ok).toBe(true);
|
|
131
|
+
require_test_CTcmp4Su.vi.unstubAllGlobals();
|
|
132
|
+
});
|
|
133
|
+
require_test_CTcmp4Su.it("deploy returns error when no servers available", async () => {
|
|
134
|
+
require_test_CTcmp4Su.vi.stubGlobal("fetch", require_test_CTcmp4Su.vi.fn().mockResolvedValue({
|
|
135
|
+
ok: true,
|
|
136
|
+
text: () => Promise.resolve("[]")
|
|
137
|
+
}));
|
|
138
|
+
const { CoolifyDeployer } = await Promise.resolve().then(() => require("./coolify.cjs"));
|
|
139
|
+
const result = await new CoolifyDeployer().deploy({
|
|
140
|
+
target: {
|
|
141
|
+
instanceUrl: "https://coolify.example.com",
|
|
142
|
+
apiKey: "test-key"
|
|
143
|
+
},
|
|
144
|
+
projectName: "test-project",
|
|
145
|
+
composeYaml: "version: '3'",
|
|
146
|
+
envContent: ""
|
|
147
|
+
});
|
|
148
|
+
require_test_CTcmp4Su.globalExpect(result.success).toBe(false);
|
|
149
|
+
require_test_CTcmp4Su.globalExpect(result.error).toContain("No Coolify servers");
|
|
150
|
+
require_test_CTcmp4Su.globalExpect(result.steps[0].status).toBe("error");
|
|
151
|
+
require_test_CTcmp4Su.vi.unstubAllGlobals();
|
|
152
|
+
});
|
|
153
|
+
});
|
|
154
|
+
//#endregion
|
|
155
|
+
|
|
156
|
+
//# sourceMappingURL=coolify.test.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"coolify.test.cjs","names":["describe","vi"],"sources":["../../src/deployers/coolify.test.ts"],"sourcesContent":["import { beforeEach, describe, expect, it, vi } from \"vitest\";\n\n/**\n * Tests for Coolify deployer utility functions and deploy orchestration.\n *\n * We mock `fetch` to simulate Coolify API responses and test the\n * multi-step deployment flow without making real HTTP requests.\n */\n\n// Inline the utility functions for direct testing\nfunction hashString(str: string) {\n\tlet hash = 0;\n\tfor (let i = 0; i < str.length; i++) {\n\t\thash = (hash << 5) - hash + str.charCodeAt(i);\n\t\thash |= 0;\n\t}\n\treturn hash;\n}\n\nfunction parseEnvContent(envContent?: string) {\n\tif (!envContent) return [];\n\tconst result = [];\n\tfor (const line of envContent.split(\"\\n\")) {\n\t\tconst trimmed = line.trim();\n\t\tif (!trimmed || trimmed.startsWith(\"#\")) continue;\n\t\tconst idx = trimmed.indexOf(\"=\");\n\t\tif (idx <= 0) continue;\n\t\tconst key = trimmed.slice(0, idx);\n\t\tconst value = trimmed.slice(idx + 1);\n\t\tresult.push({ key, value, is_preview: false, is_build_time: false, is_literal: true });\n\t}\n\treturn result;\n}\n\ndescribe(\"hashString\", () => {\n\tit(\"returns 0 for empty string\", () => {\n\t\texpect(hashString(\"\")).toBe(0);\n\t});\n\n\tit(\"returns same hash for same input\", () => {\n\t\texpect(hashString(\"hello\")).toBe(hashString(\"hello\"));\n\t});\n\n\tit(\"returns different hash for different input\", () => {\n\t\texpect(hashString(\"hello\")).not.toBe(hashString(\"world\"));\n\t});\n\n\tit(\"detects compose changes\", () => {\n\t\tconst v1 = \"version: '3'\\nservices:\\n redis:\\n image: redis:7\";\n\t\tconst v2 = \"version: '3'\\nservices:\\n redis:\\n image: redis:8\";\n\t\texpect(hashString(v1)).not.toBe(hashString(v2));\n\t});\n});\n\ndescribe(\"parseEnvContent\", () => {\n\tit(\"returns empty array for undefined input\", () => {\n\t\texpect(parseEnvContent(undefined)).toEqual([]);\n\t});\n\n\tit(\"returns empty array for empty string\", () => {\n\t\texpect(parseEnvContent(\"\")).toEqual([]);\n\t});\n\n\tit(\"parses simple key=value pairs\", () => {\n\t\tconst result = parseEnvContent(\"FOO=bar\\nBAZ=qux\");\n\t\texpect(result).toHaveLength(2);\n\t\texpect(result[0]).toEqual({\n\t\t\tkey: \"FOO\",\n\t\t\tvalue: \"bar\",\n\t\t\tis_preview: false,\n\t\t\tis_build_time: false,\n\t\t\tis_literal: true,\n\t\t});\n\t});\n\n\tit(\"skips comments\", () => {\n\t\tconst result = parseEnvContent(\"# This is a comment\\nFOO=bar\");\n\t\texpect(result).toHaveLength(1);\n\t\texpect(result[0]!.key).toBe(\"FOO\");\n\t});\n\n\tit(\"skips blank lines\", () => {\n\t\tconst result = parseEnvContent(\"FOO=bar\\n\\n\\nBAZ=qux\");\n\t\texpect(result).toHaveLength(2);\n\t});\n\n\tit(\"handles values containing equals signs\", () => {\n\t\tconst result = parseEnvContent(\n\t\t\t\"DATABASE_URL=postgres://user:pass@host:5432/db?sslmode=require\",\n\t\t);\n\t\texpect(result).toHaveLength(1);\n\t\texpect(result[0]!.key).toBe(\"DATABASE_URL\");\n\t\texpect(result[0]!.value).toBe(\"postgres://user:pass@host:5432/db?sslmode=require\");\n\t});\n\n\tit(\"handles empty values\", () => {\n\t\tconst result = parseEnvContent(\"EMPTY_VAR=\");\n\t\texpect(result).toHaveLength(1);\n\t\texpect(result[0]!.key).toBe(\"EMPTY_VAR\");\n\t\texpect(result[0]!.value).toBe(\"\");\n\t});\n\n\tit(\"skips lines without = sign\", () => {\n\t\tconst result = parseEnvContent(\"INVALID_LINE\\nVALID=yes\");\n\t\texpect(result).toHaveLength(1);\n\t\texpect(result[0]!.key).toBe(\"VALID\");\n\t});\n\n\tit(\"handles quoted values\", () => {\n\t\tconst result = parseEnvContent('PASSWORD=\"my secret\"');\n\t\texpect(result[0]!.key).toBe(\"PASSWORD\");\n\t\texpect(result[0]!.value).toBe('\"my secret\"');\n\t});\n});\n\ndescribe(\"CoolifyDeployer\", () => {\n\tbeforeEach(() => {\n\t\tvi.restoreAllMocks();\n\t});\n\n\tit(\"can be imported and instantiated\", async () => {\n\t\tconst { CoolifyDeployer } = await import(\"./coolify.js\");\n\t\tconst deployer = new CoolifyDeployer();\n\t\texpect(deployer.name).toBe(\"Coolify\");\n\t\texpect(deployer.id).toBe(\"coolify\");\n\t});\n\n\tit(\"testConnection returns error on network failure\", async () => {\n\t\tvi.stubGlobal(\"fetch\", vi.fn().mockRejectedValue(new Error(\"Connection refused\")));\n\t\tconst { CoolifyDeployer } = await import(\"./coolify.js\");\n\t\tconst deployer = new CoolifyDeployer();\n\t\tconst result = await deployer.testConnection({\n\t\t\tinstanceUrl: \"https://coolify.example.com\",\n\t\t\tapiKey: \"test-key\",\n\t\t});\n\t\texpect(result.ok).toBe(false);\n\t\texpect(result.error).toContain(\"Connection refused\");\n\t\tvi.unstubAllGlobals();\n\t});\n\n\tit(\"testConnection returns ok on successful version response\", async () => {\n\t\tvi.stubGlobal(\n\t\t\t\"fetch\",\n\t\t\tvi.fn().mockResolvedValue({\n\t\t\t\tok: true,\n\t\t\t\ttext: () => Promise.resolve('\"v4.0.0\"'),\n\t\t\t}),\n\t\t);\n\t\tconst { CoolifyDeployer } = await import(\"./coolify.js\");\n\t\tconst deployer = new CoolifyDeployer();\n\t\tconst result = await deployer.testConnection({\n\t\t\tinstanceUrl: \"https://coolify.example.com\",\n\t\t\tapiKey: \"test-key\",\n\t\t});\n\t\texpect(result.ok).toBe(true);\n\t\tvi.unstubAllGlobals();\n\t});\n\n\tit(\"deploy returns error when no servers available\", async () => {\n\t\tvi.stubGlobal(\n\t\t\t\"fetch\",\n\t\t\tvi.fn().mockResolvedValue({\n\t\t\t\tok: true,\n\t\t\t\ttext: () => Promise.resolve(\"[]\"),\n\t\t\t}),\n\t\t);\n\t\tconst { CoolifyDeployer } = await import(\"./coolify.js\");\n\t\tconst deployer = new CoolifyDeployer();\n\t\tconst result = await deployer.deploy({\n\t\t\ttarget: { instanceUrl: \"https://coolify.example.com\", apiKey: \"test-key\" },\n\t\t\tprojectName: \"test-project\",\n\t\t\tcomposeYaml: \"version: '3'\",\n\t\t\tenvContent: \"\",\n\t\t});\n\t\texpect(result.success).toBe(false);\n\t\texpect(result.error).toContain(\"No Coolify servers\");\n\t\texpect(result.steps[0]!.status).toBe(\"error\");\n\t\tvi.unstubAllGlobals();\n\t});\n});\n"],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { };
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
import { a as describe, i as beforeEach, n as vi, o as it, t as globalExpect } from "../test.CTcmp4Su-BRa7-bTj.mjs";
|
|
2
|
+
//#region src/deployers/coolify.test.ts
|
|
3
|
+
/**
|
|
4
|
+
* Tests for Coolify deployer utility functions and deploy orchestration.
|
|
5
|
+
*
|
|
6
|
+
* We mock `fetch` to simulate Coolify API responses and test the
|
|
7
|
+
* multi-step deployment flow without making real HTTP requests.
|
|
8
|
+
*/
|
|
9
|
+
function hashString(str) {
|
|
10
|
+
let hash = 0;
|
|
11
|
+
for (let i = 0; i < str.length; i++) {
|
|
12
|
+
hash = (hash << 5) - hash + str.charCodeAt(i);
|
|
13
|
+
hash |= 0;
|
|
14
|
+
}
|
|
15
|
+
return hash;
|
|
16
|
+
}
|
|
17
|
+
function parseEnvContent(envContent) {
|
|
18
|
+
if (!envContent) return [];
|
|
19
|
+
const result = [];
|
|
20
|
+
for (const line of envContent.split("\n")) {
|
|
21
|
+
const trimmed = line.trim();
|
|
22
|
+
if (!trimmed || trimmed.startsWith("#")) continue;
|
|
23
|
+
const idx = trimmed.indexOf("=");
|
|
24
|
+
if (idx <= 0) continue;
|
|
25
|
+
const key = trimmed.slice(0, idx);
|
|
26
|
+
const value = trimmed.slice(idx + 1);
|
|
27
|
+
result.push({
|
|
28
|
+
key,
|
|
29
|
+
value,
|
|
30
|
+
is_preview: false,
|
|
31
|
+
is_build_time: false,
|
|
32
|
+
is_literal: true
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
return result;
|
|
36
|
+
}
|
|
37
|
+
describe("hashString", () => {
|
|
38
|
+
it("returns 0 for empty string", () => {
|
|
39
|
+
globalExpect(hashString("")).toBe(0);
|
|
40
|
+
});
|
|
41
|
+
it("returns same hash for same input", () => {
|
|
42
|
+
globalExpect(hashString("hello")).toBe(hashString("hello"));
|
|
43
|
+
});
|
|
44
|
+
it("returns different hash for different input", () => {
|
|
45
|
+
globalExpect(hashString("hello")).not.toBe(hashString("world"));
|
|
46
|
+
});
|
|
47
|
+
it("detects compose changes", () => {
|
|
48
|
+
globalExpect(hashString("version: '3'\nservices:\n redis:\n image: redis:7")).not.toBe(hashString("version: '3'\nservices:\n redis:\n image: redis:8"));
|
|
49
|
+
});
|
|
50
|
+
});
|
|
51
|
+
describe("parseEnvContent", () => {
|
|
52
|
+
it("returns empty array for undefined input", () => {
|
|
53
|
+
globalExpect(parseEnvContent(void 0)).toEqual([]);
|
|
54
|
+
});
|
|
55
|
+
it("returns empty array for empty string", () => {
|
|
56
|
+
globalExpect(parseEnvContent("")).toEqual([]);
|
|
57
|
+
});
|
|
58
|
+
it("parses simple key=value pairs", () => {
|
|
59
|
+
const result = parseEnvContent("FOO=bar\nBAZ=qux");
|
|
60
|
+
globalExpect(result).toHaveLength(2);
|
|
61
|
+
globalExpect(result[0]).toEqual({
|
|
62
|
+
key: "FOO",
|
|
63
|
+
value: "bar",
|
|
64
|
+
is_preview: false,
|
|
65
|
+
is_build_time: false,
|
|
66
|
+
is_literal: true
|
|
67
|
+
});
|
|
68
|
+
});
|
|
69
|
+
it("skips comments", () => {
|
|
70
|
+
const result = parseEnvContent("# This is a comment\nFOO=bar");
|
|
71
|
+
globalExpect(result).toHaveLength(1);
|
|
72
|
+
globalExpect(result[0].key).toBe("FOO");
|
|
73
|
+
});
|
|
74
|
+
it("skips blank lines", () => {
|
|
75
|
+
globalExpect(parseEnvContent("FOO=bar\n\n\nBAZ=qux")).toHaveLength(2);
|
|
76
|
+
});
|
|
77
|
+
it("handles values containing equals signs", () => {
|
|
78
|
+
const result = parseEnvContent("DATABASE_URL=postgres://user:pass@host:5432/db?sslmode=require");
|
|
79
|
+
globalExpect(result).toHaveLength(1);
|
|
80
|
+
globalExpect(result[0].key).toBe("DATABASE_URL");
|
|
81
|
+
globalExpect(result[0].value).toBe("postgres://user:pass@host:5432/db?sslmode=require");
|
|
82
|
+
});
|
|
83
|
+
it("handles empty values", () => {
|
|
84
|
+
const result = parseEnvContent("EMPTY_VAR=");
|
|
85
|
+
globalExpect(result).toHaveLength(1);
|
|
86
|
+
globalExpect(result[0].key).toBe("EMPTY_VAR");
|
|
87
|
+
globalExpect(result[0].value).toBe("");
|
|
88
|
+
});
|
|
89
|
+
it("skips lines without = sign", () => {
|
|
90
|
+
const result = parseEnvContent("INVALID_LINE\nVALID=yes");
|
|
91
|
+
globalExpect(result).toHaveLength(1);
|
|
92
|
+
globalExpect(result[0].key).toBe("VALID");
|
|
93
|
+
});
|
|
94
|
+
it("handles quoted values", () => {
|
|
95
|
+
const result = parseEnvContent("PASSWORD=\"my secret\"");
|
|
96
|
+
globalExpect(result[0].key).toBe("PASSWORD");
|
|
97
|
+
globalExpect(result[0].value).toBe("\"my secret\"");
|
|
98
|
+
});
|
|
99
|
+
});
|
|
100
|
+
describe("CoolifyDeployer", () => {
|
|
101
|
+
beforeEach(() => {
|
|
102
|
+
vi.restoreAllMocks();
|
|
103
|
+
});
|
|
104
|
+
it("can be imported and instantiated", async () => {
|
|
105
|
+
const { CoolifyDeployer } = await import("./coolify.mjs");
|
|
106
|
+
const deployer = new CoolifyDeployer();
|
|
107
|
+
globalExpect(deployer.name).toBe("Coolify");
|
|
108
|
+
globalExpect(deployer.id).toBe("coolify");
|
|
109
|
+
});
|
|
110
|
+
it("testConnection returns error on network failure", async () => {
|
|
111
|
+
vi.stubGlobal("fetch", vi.fn().mockRejectedValue(/* @__PURE__ */ new Error("Connection refused")));
|
|
112
|
+
const { CoolifyDeployer } = await import("./coolify.mjs");
|
|
113
|
+
const result = await new CoolifyDeployer().testConnection({
|
|
114
|
+
instanceUrl: "https://coolify.example.com",
|
|
115
|
+
apiKey: "test-key"
|
|
116
|
+
});
|
|
117
|
+
globalExpect(result.ok).toBe(false);
|
|
118
|
+
globalExpect(result.error).toContain("Connection refused");
|
|
119
|
+
vi.unstubAllGlobals();
|
|
120
|
+
});
|
|
121
|
+
it("testConnection returns ok on successful version response", async () => {
|
|
122
|
+
vi.stubGlobal("fetch", vi.fn().mockResolvedValue({
|
|
123
|
+
ok: true,
|
|
124
|
+
text: () => Promise.resolve("\"v4.0.0\"")
|
|
125
|
+
}));
|
|
126
|
+
const { CoolifyDeployer } = await import("./coolify.mjs");
|
|
127
|
+
globalExpect((await new CoolifyDeployer().testConnection({
|
|
128
|
+
instanceUrl: "https://coolify.example.com",
|
|
129
|
+
apiKey: "test-key"
|
|
130
|
+
})).ok).toBe(true);
|
|
131
|
+
vi.unstubAllGlobals();
|
|
132
|
+
});
|
|
133
|
+
it("deploy returns error when no servers available", async () => {
|
|
134
|
+
vi.stubGlobal("fetch", vi.fn().mockResolvedValue({
|
|
135
|
+
ok: true,
|
|
136
|
+
text: () => Promise.resolve("[]")
|
|
137
|
+
}));
|
|
138
|
+
const { CoolifyDeployer } = await import("./coolify.mjs");
|
|
139
|
+
const result = await new CoolifyDeployer().deploy({
|
|
140
|
+
target: {
|
|
141
|
+
instanceUrl: "https://coolify.example.com",
|
|
142
|
+
apiKey: "test-key"
|
|
143
|
+
},
|
|
144
|
+
projectName: "test-project",
|
|
145
|
+
composeYaml: "version: '3'",
|
|
146
|
+
envContent: ""
|
|
147
|
+
});
|
|
148
|
+
globalExpect(result.success).toBe(false);
|
|
149
|
+
globalExpect(result.error).toContain("No Coolify servers");
|
|
150
|
+
globalExpect(result.steps[0].status).toBe("error");
|
|
151
|
+
vi.unstubAllGlobals();
|
|
152
|
+
});
|
|
153
|
+
});
|
|
154
|
+
//#endregion
|
|
155
|
+
export {};
|
|
156
|
+
|
|
157
|
+
//# sourceMappingURL=coolify.test.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"coolify.test.mjs","names":[],"sources":["../../src/deployers/coolify.test.ts"],"sourcesContent":["import { beforeEach, describe, expect, it, vi } from \"vitest\";\n\n/**\n * Tests for Coolify deployer utility functions and deploy orchestration.\n *\n * We mock `fetch` to simulate Coolify API responses and test the\n * multi-step deployment flow without making real HTTP requests.\n */\n\n// Inline the utility functions for direct testing\nfunction hashString(str: string) {\n\tlet hash = 0;\n\tfor (let i = 0; i < str.length; i++) {\n\t\thash = (hash << 5) - hash + str.charCodeAt(i);\n\t\thash |= 0;\n\t}\n\treturn hash;\n}\n\nfunction parseEnvContent(envContent?: string) {\n\tif (!envContent) return [];\n\tconst result = [];\n\tfor (const line of envContent.split(\"\\n\")) {\n\t\tconst trimmed = line.trim();\n\t\tif (!trimmed || trimmed.startsWith(\"#\")) continue;\n\t\tconst idx = trimmed.indexOf(\"=\");\n\t\tif (idx <= 0) continue;\n\t\tconst key = trimmed.slice(0, idx);\n\t\tconst value = trimmed.slice(idx + 1);\n\t\tresult.push({ key, value, is_preview: false, is_build_time: false, is_literal: true });\n\t}\n\treturn result;\n}\n\ndescribe(\"hashString\", () => {\n\tit(\"returns 0 for empty string\", () => {\n\t\texpect(hashString(\"\")).toBe(0);\n\t});\n\n\tit(\"returns same hash for same input\", () => {\n\t\texpect(hashString(\"hello\")).toBe(hashString(\"hello\"));\n\t});\n\n\tit(\"returns different hash for different input\", () => {\n\t\texpect(hashString(\"hello\")).not.toBe(hashString(\"world\"));\n\t});\n\n\tit(\"detects compose changes\", () => {\n\t\tconst v1 = \"version: '3'\\nservices:\\n redis:\\n image: redis:7\";\n\t\tconst v2 = \"version: '3'\\nservices:\\n redis:\\n image: redis:8\";\n\t\texpect(hashString(v1)).not.toBe(hashString(v2));\n\t});\n});\n\ndescribe(\"parseEnvContent\", () => {\n\tit(\"returns empty array for undefined input\", () => {\n\t\texpect(parseEnvContent(undefined)).toEqual([]);\n\t});\n\n\tit(\"returns empty array for empty string\", () => {\n\t\texpect(parseEnvContent(\"\")).toEqual([]);\n\t});\n\n\tit(\"parses simple key=value pairs\", () => {\n\t\tconst result = parseEnvContent(\"FOO=bar\\nBAZ=qux\");\n\t\texpect(result).toHaveLength(2);\n\t\texpect(result[0]).toEqual({\n\t\t\tkey: \"FOO\",\n\t\t\tvalue: \"bar\",\n\t\t\tis_preview: false,\n\t\t\tis_build_time: false,\n\t\t\tis_literal: true,\n\t\t});\n\t});\n\n\tit(\"skips comments\", () => {\n\t\tconst result = parseEnvContent(\"# This is a comment\\nFOO=bar\");\n\t\texpect(result).toHaveLength(1);\n\t\texpect(result[0]!.key).toBe(\"FOO\");\n\t});\n\n\tit(\"skips blank lines\", () => {\n\t\tconst result = parseEnvContent(\"FOO=bar\\n\\n\\nBAZ=qux\");\n\t\texpect(result).toHaveLength(2);\n\t});\n\n\tit(\"handles values containing equals signs\", () => {\n\t\tconst result = parseEnvContent(\n\t\t\t\"DATABASE_URL=postgres://user:pass@host:5432/db?sslmode=require\",\n\t\t);\n\t\texpect(result).toHaveLength(1);\n\t\texpect(result[0]!.key).toBe(\"DATABASE_URL\");\n\t\texpect(result[0]!.value).toBe(\"postgres://user:pass@host:5432/db?sslmode=require\");\n\t});\n\n\tit(\"handles empty values\", () => {\n\t\tconst result = parseEnvContent(\"EMPTY_VAR=\");\n\t\texpect(result).toHaveLength(1);\n\t\texpect(result[0]!.key).toBe(\"EMPTY_VAR\");\n\t\texpect(result[0]!.value).toBe(\"\");\n\t});\n\n\tit(\"skips lines without = sign\", () => {\n\t\tconst result = parseEnvContent(\"INVALID_LINE\\nVALID=yes\");\n\t\texpect(result).toHaveLength(1);\n\t\texpect(result[0]!.key).toBe(\"VALID\");\n\t});\n\n\tit(\"handles quoted values\", () => {\n\t\tconst result = parseEnvContent('PASSWORD=\"my secret\"');\n\t\texpect(result[0]!.key).toBe(\"PASSWORD\");\n\t\texpect(result[0]!.value).toBe('\"my secret\"');\n\t});\n});\n\ndescribe(\"CoolifyDeployer\", () => {\n\tbeforeEach(() => {\n\t\tvi.restoreAllMocks();\n\t});\n\n\tit(\"can be imported and instantiated\", async () => {\n\t\tconst { CoolifyDeployer } = await import(\"./coolify.js\");\n\t\tconst deployer = new CoolifyDeployer();\n\t\texpect(deployer.name).toBe(\"Coolify\");\n\t\texpect(deployer.id).toBe(\"coolify\");\n\t});\n\n\tit(\"testConnection returns error on network failure\", async () => {\n\t\tvi.stubGlobal(\"fetch\", vi.fn().mockRejectedValue(new Error(\"Connection refused\")));\n\t\tconst { CoolifyDeployer } = await import(\"./coolify.js\");\n\t\tconst deployer = new CoolifyDeployer();\n\t\tconst result = await deployer.testConnection({\n\t\t\tinstanceUrl: \"https://coolify.example.com\",\n\t\t\tapiKey: \"test-key\",\n\t\t});\n\t\texpect(result.ok).toBe(false);\n\t\texpect(result.error).toContain(\"Connection refused\");\n\t\tvi.unstubAllGlobals();\n\t});\n\n\tit(\"testConnection returns ok on successful version response\", async () => {\n\t\tvi.stubGlobal(\n\t\t\t\"fetch\",\n\t\t\tvi.fn().mockResolvedValue({\n\t\t\t\tok: true,\n\t\t\t\ttext: () => Promise.resolve('\"v4.0.0\"'),\n\t\t\t}),\n\t\t);\n\t\tconst { CoolifyDeployer } = await import(\"./coolify.js\");\n\t\tconst deployer = new CoolifyDeployer();\n\t\tconst result = await deployer.testConnection({\n\t\t\tinstanceUrl: \"https://coolify.example.com\",\n\t\t\tapiKey: \"test-key\",\n\t\t});\n\t\texpect(result.ok).toBe(true);\n\t\tvi.unstubAllGlobals();\n\t});\n\n\tit(\"deploy returns error when no servers available\", async () => {\n\t\tvi.stubGlobal(\n\t\t\t\"fetch\",\n\t\t\tvi.fn().mockResolvedValue({\n\t\t\t\tok: true,\n\t\t\t\ttext: () => Promise.resolve(\"[]\"),\n\t\t\t}),\n\t\t);\n\t\tconst { CoolifyDeployer } = await import(\"./coolify.js\");\n\t\tconst deployer = new CoolifyDeployer();\n\t\tconst result = await deployer.deploy({\n\t\t\ttarget: { instanceUrl: \"https://coolify.example.com\", apiKey: \"test-key\" },\n\t\t\tprojectName: \"test-project\",\n\t\t\tcomposeYaml: \"version: '3'\",\n\t\t\tenvContent: \"\",\n\t\t});\n\t\texpect(result.success).toBe(false);\n\t\texpect(result.error).toContain(\"No Coolify servers\");\n\t\texpect(result.steps[0]!.status).toBe(\"error\");\n\t\tvi.unstubAllGlobals();\n\t});\n});\n"],"mappings":"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"}
|
|
@@ -84,6 +84,10 @@ var DokployDeployer = class {
|
|
|
84
84
|
}
|
|
85
85
|
}
|
|
86
86
|
async deploy(input) {
|
|
87
|
+
input.logger?.info("deployment", `Starting deployment to Dokploy`, {
|
|
88
|
+
projectName: input.projectName,
|
|
89
|
+
instanceUrl: input.target.instanceUrl
|
|
90
|
+
});
|
|
87
91
|
const step1 = {
|
|
88
92
|
step: "Find or create project",
|
|
89
93
|
status: "pending"
|
|
@@ -203,6 +207,23 @@ var DokployDeployer = class {
|
|
|
203
207
|
step5.status = "done";
|
|
204
208
|
result.success = true;
|
|
205
209
|
result.dashboardUrl = `${input.target.instanceUrl.replace(/\/+$/, "")}/dashboard/project/${project.projectId}/environment/${env.environmentId}/services/compose/${stack?.composeId}?tab=deployments`;
|
|
210
|
+
input.logger?.log({
|
|
211
|
+
level: "info",
|
|
212
|
+
category: "deployment",
|
|
213
|
+
message: `Deployment to Dokploy succeeded`,
|
|
214
|
+
outcome: "success",
|
|
215
|
+
context: {
|
|
216
|
+
projectId: project.projectId,
|
|
217
|
+
composeId: stack?.composeId,
|
|
218
|
+
dashboardUrl: result.dashboardUrl
|
|
219
|
+
},
|
|
220
|
+
steps: steps.map((s) => ({
|
|
221
|
+
name: s.step,
|
|
222
|
+
status: s.status === "done" ? "success" : s.status === "error" ? "failure" : "in_progress",
|
|
223
|
+
detail: s.detail,
|
|
224
|
+
startedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
225
|
+
}))
|
|
226
|
+
});
|
|
206
227
|
return result;
|
|
207
228
|
} catch (err) {
|
|
208
229
|
const running = steps.find((s) => s.status === "running");
|
|
@@ -211,6 +232,10 @@ var DokployDeployer = class {
|
|
|
211
232
|
running.detail = err instanceof Error ? err.message : String(err);
|
|
212
233
|
}
|
|
213
234
|
result.error = err instanceof Error ? err.message : String(err);
|
|
235
|
+
input.logger?.error("deployment", `Deployment to Dokploy failed`, err instanceof Error ? err : null, {
|
|
236
|
+
projectName: input.projectName,
|
|
237
|
+
failedStep: running?.step
|
|
238
|
+
});
|
|
214
239
|
return result;
|
|
215
240
|
}
|
|
216
241
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dokploy.cjs","names":["sanitizeComposeForPaas"],"sources":["../../src/deployers/dokploy.ts"],"sourcesContent":["/**\n * Dokploy PaaS deployer — deploys Docker Compose stacks via the Dokploy REST API.\n *\n * API docs: https://docs.dokploy.com/docs/api\n * Auth: x-api-key header\n * Endpoints use dot-notation (e.g. /api/project.create, /api/compose.deploy)\n */\n\nimport { sanitizeComposeForPaas } from \"./strip-host-ports.js\";\nimport type {\n\tDeployInput,\n\tDeployResult,\n\tDeployStep,\n\tDeployTarget,\n\tDokployEnvironment,\n\tPaasDeployer,\n\tPaasServer,\n} from \"./types.js\";\n\ninterface DokployProject {\n\tprojectId: string;\n\tname: string;\n\tdescription: string;\n\tenvironments?: DokployEnvironment[];\n}\n\ninterface DokployCompose {\n\tcomposeId: string;\n\tname: string;\n\tstatus?: string;\n\tcompose?: string;\n}\n\ninterface ProjectCreateResult {\n\tproject: DokployProject;\n\tprojectId: string;\n\tname: string;\n\tdescription: string;\n\tenvironments?: { environmentId: string; name: string }[];\n}\n\n/** Build a full Dokploy API URL from a dot-notation endpoint (e.g. \"project.create\"). */\nfunction apiUrl(target: DeployTarget, endpoint: string): string {\n\tconst base = target.instanceUrl.replace(/\\/+$/, \"\");\n\treturn `${base}/api/${endpoint}`;\n}\n/**\n * Typed fetch wrapper for the Dokploy API.\n * Handles JSON serialisation, x-api-key auth, and error extraction.\n */\nasync function dokployFetch<T>(\n\ttarget: DeployTarget,\n\tendpoint: string,\n\toptions: { method?: string; body?: unknown } = {},\n): Promise<T> {\n\tconst res = await fetch(apiUrl(target, endpoint), {\n\t\tmethod: options.method ?? \"GET\",\n\t\theaders: {\n\t\t\t\"Content-Type\": \"application/json\",\n\t\t\t\"x-api-key\": target.apiKey,\n\t\t},\n\t\tbody: options.body ? JSON.stringify(options.body) : undefined,\n\t});\n\n\tif (!res.ok) {\n\t\tconst text = await res.text().catch(() => \"\");\n\t\tlet detail = text;\n\n\t\ttry {\n\t\t\tconst json = JSON.parse(text);\n\t\t\tdetail = json.message || json.error || text;\n\t\t} catch {}\n\n\t\tthrow new Error(`Dokploy API ${res.status}: ${detail}`);\n\t}\n\n\tconst text = await res.text();\n\tif (!text) return undefined as T;\n\n\treturn JSON.parse(text) as T;\n}\n\n/**\n * Simple hash for compose diff detection\n */\nfunction hashString(str: string) {\n\tlet hash = 0;\n\n\tfor (let i = 0; i < str.length; i++) {\n\t\thash = (hash << 5) - hash + str.charCodeAt(i);\n\t\thash |= 0;\n\t}\n\n\treturn hash;\n}\n\n/**\n * Deploys Docker Compose stacks to a Dokploy instance.\n *\n * Deploy flow (4 steps):\n * 1. Create a Dokploy project\n * 2. Create a compose stack inside the project's default environment\n * 3. Push .env variables to the compose stack\n * 4. Trigger the deployment\n */\n\nexport class DokployDeployer implements PaasDeployer {\n\treadonly name = \"Dokploy\";\n\treadonly id = \"dokploy\";\n\n\tasync testConnection(target: DeployTarget): Promise<{ ok: boolean; error?: string }> {\n\t\ttry {\n\t\t\tawait dokployFetch<DokployProject[]>(target, \"project.all\");\n\n\t\t\treturn { ok: true };\n\t\t} catch (err) {\n\t\t\treturn {\n\t\t\t\tok: false,\n\t\t\t\terror: err instanceof Error ? err.message : String(err),\n\t\t\t};\n\t\t}\n\t}\n\n\tasync listServers(target: DeployTarget): Promise<PaasServer[]> {\n\t\ttry {\n\t\t\tconst servers = await dokployFetch<{ serverId: string; name: string; ipAddress: string }[]>(\n\t\t\t\ttarget,\n\t\t\t\t\"server.all\",\n\t\t\t);\n\t\t\treturn servers.map((s) => ({\n\t\t\t\tid: s.serverId,\n\t\t\t\tname: s.name,\n\t\t\t\tip: s.ipAddress,\n\t\t\t}));\n\t\t} catch {\n\t\t\t// Return empty list if server API is not available\n\t\t\treturn [];\n\t\t}\n\t}\n\n\tasync deploy(input: DeployInput): Promise<DeployResult> {\n\t\tconst step1: DeployStep = {\n\t\t\tstep: \"Find or create project\",\n\t\t\tstatus: \"pending\",\n\t\t};\n\t\tconst step2: DeployStep = {\n\t\t\tstep: \"Find default environment\",\n\t\t\tstatus: \"pending\",\n\t\t};\n\t\tconst step3: DeployStep = {\n\t\t\tstep: \"Find or create compose stack\",\n\t\t\tstatus: \"pending\",\n\t\t};\n\t\tconst step4: DeployStep = {\n\t\t\tstep: \"Update stack configuration\",\n\t\t\tstatus: \"pending\",\n\t\t};\n\t\tconst step5: DeployStep = { step: \"Deploy stack\", status: \"pending\" };\n\t\tconst steps: DeployStep[] = [step1, step2, step3, step4, step5];\n\n\t\tconst result: DeployResult = { success: false, steps };\n\n\t\t// Strip host port bindings — Dokploy routes via Traefik,\n\t\t// so host ports are unnecessary and cause \"port already allocated\" errors.\n\t\tconst composeYaml = sanitizeComposeForPaas(input.composeYaml);\n\n\t\ttry {\n\t\t\t/**\n\t\t\t * STEP 1\n\t\t\t * Find or create project\n\t\t\t */\n\n\t\t\tstep1.status = \"running\";\n\n\t\t\tconst projects = await dokployFetch<DokployProject[]>(input.target, \"project.all\");\n\n\t\t\tlet project = projects.find((p) => p.name === input.projectName);\n\n\t\t\tif (!project) {\n\t\t\t\tconst created = await dokployFetch<ProjectCreateResult>(input.target, \"project.create\", {\n\t\t\t\t\tmethod: \"POST\",\n\t\t\t\t\tbody: {\n\t\t\t\t\t\tname: input.projectName,\n\t\t\t\t\t\tdescription: input.description ?? `OpenClaw stack: ${input.projectName}`,\n\t\t\t\t\t},\n\t\t\t\t});\n\n\t\t\t\tproject = created.project;\n\t\t\t}\n\n\t\t\tresult.projectId = project.projectId;\n\n\t\t\tstep1.status = \"done\";\n\t\t\tstep1.detail = `Project ID: ${project.projectId}`;\n\n\t\t\t/**\n\t\t\t * STEP 2\n\t\t\t * Find default environment\n\t\t\t */\n\n\t\t\tstep2.status = \"running\";\n\n\t\t\tconst projectDetail = await dokployFetch<DokployProject>(\n\t\t\t\tinput.target,\n\t\t\t\t`project.one?projectId=${project.projectId}`,\n\t\t\t);\n\n\t\t\tconst env = projectDetail.environments?.find((e) => e.isDefault);\n\n\t\t\tif (!env) throw new Error(\"No default environment\");\n\n\t\t\tstep2.status = \"done\";\n\t\t\tstep2.detail = env.environmentId;\n\n\t\t\t/**\n\t\t\t * STEP 3\n\t\t\t * Find or create compose stack\n\t\t\t */\n\n\t\t\tstep3.status = \"running\";\n\n\t\t\tlet stack: DokployCompose | null = null;\n\n\t\t\tstack = await dokployFetch<DokployCompose>(input.target, \"compose.create\", {\n\t\t\t\tmethod: \"POST\",\n\t\t\t\tbody: {\n\t\t\t\t\tname: input.projectName,\n\t\t\t\t\tdescription: input.description ?? `Stack ${input.projectName}`,\n\t\t\t\t\tenvironmentId: env.environmentId,\n\t\t\t\t\tcomposeType: \"docker-compose\",\n\t\t\t\t\tcomposeFile: composeYaml,\n\t\t\t\t\t...(input.serverId ? { serverId: input.serverId } : {}),\n\t\t\t\t},\n\t\t\t});\n\n\t\t\t// Dokploy's compose.create schema does NOT accept sourceType;\n\t\t\t// it defaults to \"github\". We must update it to \"raw\" so the\n\t\t\t// deploy step writes the compose file from the stored YAML\n\t\t\t// instead of attempting to clone from a Git provider.\n\t\t\tif (stack?.composeId) {\n\t\t\t\tawait dokployFetch(input.target, \"compose.update\", {\n\t\t\t\t\tmethod: \"POST\",\n\t\t\t\t\tbody: {\n\t\t\t\t\t\tcomposeId: stack.composeId,\n\t\t\t\t\t\tsourceType: \"raw\",\n\t\t\t\t\t},\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tresult.composeId = stack?.composeId;\n\t\t\tstep3.status = \"done\";\n\t\t\tstep3.detail = stack?.composeId;\n\n\t\t\t/**\n\t\t\t * STEP 4\n\t\t\t * Update stack if compose changed\n\t\t\t */\n\n\t\t\tstep4.status = \"running\";\n\n\t\t\tconst existingStack = await dokployFetch<DokployCompose>(\n\t\t\t\tinput.target,\n\t\t\t\t`compose.one?composeId=${stack?.composeId}`,\n\t\t\t);\n\n\t\t\tconst newHash = hashString(composeYaml);\n\t\t\tconst oldHash = hashString(existingStack.compose ?? \"\");\n\n\t\t\tif (newHash !== oldHash) {\n\t\t\t\tawait dokployFetch(input.target, \"compose.update\", {\n\t\t\t\t\tmethod: \"POST\",\n\t\t\t\t\tbody: {\n\t\t\t\t\t\tcomposeId: stack?.composeId,\n\t\t\t\t\t\tcomposeFile: composeYaml,\n\t\t\t\t\t\tenv: input.envContent ?? \"\",\n\t\t\t\t\t},\n\t\t\t\t});\n\n\t\t\t\tstep4.detail = \"Stack updated\";\n\t\t\t} else {\n\t\t\t\tstep4.detail = \"No compose changes\";\n\t\t\t}\n\n\t\t\tstep4.status = \"done\";\n\n\t\t\t/**\n\t\t\t * STEP 5\n\t\t\t * Deploy\n\t\t\t */\n\n\t\t\tstep5.status = \"running\";\n\n\t\t\tawait dokployFetch(input.target, \"compose.deploy\", {\n\t\t\t\tmethod: \"POST\",\n\t\t\t\tbody: {\n\t\t\t\t\tcomposeId: stack?.composeId,\n\n\t\t\t\t\ttitle: `Deploy ${input.projectName}`,\n\n\t\t\t\t\tdescription: \"CI deployment\",\n\t\t\t\t},\n\t\t\t});\n\n\t\t\tstep5.status = \"done\";\n\n\t\t\tresult.success = true;\n\n\t\t\tconst base = input.target.instanceUrl.replace(/\\/+$/, \"\");\n\n\t\t\tresult.dashboardUrl = `${base}/dashboard/project/${project.projectId}/environment/${env.environmentId}/services/compose/${stack?.composeId}?tab=deployments`;\n\n\t\t\treturn result;\n\t\t} catch (err) {\n\t\t\tconst running = steps.find((s) => s.status === \"running\");\n\n\t\t\tif (running) {\n\t\t\t\trunning.status = \"error\";\n\n\t\t\t\trunning.detail = err instanceof Error ? err.message : String(err);\n\t\t\t}\n\n\t\t\tresult.error = err instanceof Error ? err.message : String(err);\n\n\t\t\treturn result;\n\t\t}\n\t}\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"dokploy.cjs","names":["sanitizeComposeForPaas"],"sources":["../../src/deployers/dokploy.ts"],"sourcesContent":["/**\n * Dokploy PaaS deployer — deploys Docker Compose stacks via the Dokploy REST API.\n *\n * API docs: https://docs.dokploy.com/docs/api\n * Auth: x-api-key header\n * Endpoints use dot-notation (e.g. /api/project.create, /api/compose.deploy)\n */\n\nimport { sanitizeComposeForPaas } from \"./strip-host-ports.js\";\nimport type {\n\tDeployInput,\n\tDeployResult,\n\tDeployStep,\n\tDeployTarget,\n\tDokployEnvironment,\n\tPaasDeployer,\n\tPaasServer,\n} from \"./types.js\";\n\ninterface DokployProject {\n\tprojectId: string;\n\tname: string;\n\tdescription: string;\n\tenvironments?: DokployEnvironment[];\n}\n\ninterface DokployCompose {\n\tcomposeId: string;\n\tname: string;\n\tstatus?: string;\n\tcompose?: string;\n}\n\ninterface ProjectCreateResult {\n\tproject: DokployProject;\n\tprojectId: string;\n\tname: string;\n\tdescription: string;\n\tenvironments?: { environmentId: string; name: string }[];\n}\n\n/** Build a full Dokploy API URL from a dot-notation endpoint (e.g. \"project.create\"). */\nfunction apiUrl(target: DeployTarget, endpoint: string): string {\n\tconst base = target.instanceUrl.replace(/\\/+$/, \"\");\n\treturn `${base}/api/${endpoint}`;\n}\n/**\n * Typed fetch wrapper for the Dokploy API.\n * Handles JSON serialisation, x-api-key auth, and error extraction.\n */\nasync function dokployFetch<T>(\n\ttarget: DeployTarget,\n\tendpoint: string,\n\toptions: { method?: string; body?: unknown } = {},\n): Promise<T> {\n\tconst res = await fetch(apiUrl(target, endpoint), {\n\t\tmethod: options.method ?? \"GET\",\n\t\theaders: {\n\t\t\t\"Content-Type\": \"application/json\",\n\t\t\t\"x-api-key\": target.apiKey,\n\t\t},\n\t\tbody: options.body ? JSON.stringify(options.body) : undefined,\n\t});\n\n\tif (!res.ok) {\n\t\tconst text = await res.text().catch(() => \"\");\n\t\tlet detail = text;\n\n\t\ttry {\n\t\t\tconst json = JSON.parse(text);\n\t\t\tdetail = json.message || json.error || text;\n\t\t} catch {}\n\n\t\tthrow new Error(`Dokploy API ${res.status}: ${detail}`);\n\t}\n\n\tconst text = await res.text();\n\tif (!text) return undefined as T;\n\n\treturn JSON.parse(text) as T;\n}\n\n/**\n * Simple hash for compose diff detection\n */\nfunction hashString(str: string) {\n\tlet hash = 0;\n\n\tfor (let i = 0; i < str.length; i++) {\n\t\thash = (hash << 5) - hash + str.charCodeAt(i);\n\t\thash |= 0;\n\t}\n\n\treturn hash;\n}\n\n/**\n * Deploys Docker Compose stacks to a Dokploy instance.\n *\n * Deploy flow (4 steps):\n * 1. Create a Dokploy project\n * 2. Create a compose stack inside the project's default environment\n * 3. Push .env variables to the compose stack\n * 4. Trigger the deployment\n */\n\nexport class DokployDeployer implements PaasDeployer {\n\treadonly name = \"Dokploy\";\n\treadonly id = \"dokploy\";\n\n\tasync testConnection(target: DeployTarget): Promise<{ ok: boolean; error?: string }> {\n\t\ttry {\n\t\t\tawait dokployFetch<DokployProject[]>(target, \"project.all\");\n\n\t\t\treturn { ok: true };\n\t\t} catch (err) {\n\t\t\treturn {\n\t\t\t\tok: false,\n\t\t\t\terror: err instanceof Error ? err.message : String(err),\n\t\t\t};\n\t\t}\n\t}\n\n\tasync listServers(target: DeployTarget): Promise<PaasServer[]> {\n\t\ttry {\n\t\t\tconst servers = await dokployFetch<{ serverId: string; name: string; ipAddress: string }[]>(\n\t\t\t\ttarget,\n\t\t\t\t\"server.all\",\n\t\t\t);\n\t\t\treturn servers.map((s) => ({\n\t\t\t\tid: s.serverId,\n\t\t\t\tname: s.name,\n\t\t\t\tip: s.ipAddress,\n\t\t\t}));\n\t\t} catch {\n\t\t\t// Return empty list if server API is not available\n\t\t\treturn [];\n\t\t}\n\t}\n\n\tasync deploy(input: DeployInput): Promise<DeployResult> {\n\t\tinput.logger?.info(\"deployment\", `Starting deployment to Dokploy`, {\n\t\t\tprojectName: input.projectName,\n\t\t\tinstanceUrl: input.target.instanceUrl,\n\t\t});\n\n\t\tconst step1: DeployStep = {\n\t\t\tstep: \"Find or create project\",\n\t\t\tstatus: \"pending\",\n\t\t};\n\t\tconst step2: DeployStep = {\n\t\t\tstep: \"Find default environment\",\n\t\t\tstatus: \"pending\",\n\t\t};\n\t\tconst step3: DeployStep = {\n\t\t\tstep: \"Find or create compose stack\",\n\t\t\tstatus: \"pending\",\n\t\t};\n\t\tconst step4: DeployStep = {\n\t\t\tstep: \"Update stack configuration\",\n\t\t\tstatus: \"pending\",\n\t\t};\n\t\tconst step5: DeployStep = { step: \"Deploy stack\", status: \"pending\" };\n\t\tconst steps: DeployStep[] = [step1, step2, step3, step4, step5];\n\n\t\tconst result: DeployResult = { success: false, steps };\n\n\t\t// Strip host port bindings — Dokploy routes via Traefik,\n\t\t// so host ports are unnecessary and cause \"port already allocated\" errors.\n\t\tconst composeYaml = sanitizeComposeForPaas(input.composeYaml);\n\n\t\ttry {\n\t\t\t/**\n\t\t\t * STEP 1\n\t\t\t * Find or create project\n\t\t\t */\n\n\t\t\tstep1.status = \"running\";\n\n\t\t\tconst projects = await dokployFetch<DokployProject[]>(input.target, \"project.all\");\n\n\t\t\tlet project = projects.find((p) => p.name === input.projectName);\n\n\t\t\tif (!project) {\n\t\t\t\tconst created = await dokployFetch<ProjectCreateResult>(input.target, \"project.create\", {\n\t\t\t\t\tmethod: \"POST\",\n\t\t\t\t\tbody: {\n\t\t\t\t\t\tname: input.projectName,\n\t\t\t\t\t\tdescription: input.description ?? `OpenClaw stack: ${input.projectName}`,\n\t\t\t\t\t},\n\t\t\t\t});\n\n\t\t\t\tproject = created.project;\n\t\t\t}\n\n\t\t\tresult.projectId = project.projectId;\n\n\t\t\tstep1.status = \"done\";\n\t\t\tstep1.detail = `Project ID: ${project.projectId}`;\n\n\t\t\t/**\n\t\t\t * STEP 2\n\t\t\t * Find default environment\n\t\t\t */\n\n\t\t\tstep2.status = \"running\";\n\n\t\t\tconst projectDetail = await dokployFetch<DokployProject>(\n\t\t\t\tinput.target,\n\t\t\t\t`project.one?projectId=${project.projectId}`,\n\t\t\t);\n\n\t\t\tconst env = projectDetail.environments?.find((e) => e.isDefault);\n\n\t\t\tif (!env) throw new Error(\"No default environment\");\n\n\t\t\tstep2.status = \"done\";\n\t\t\tstep2.detail = env.environmentId;\n\n\t\t\t/**\n\t\t\t * STEP 3\n\t\t\t * Find or create compose stack\n\t\t\t */\n\n\t\t\tstep3.status = \"running\";\n\n\t\t\tlet stack: DokployCompose | null = null;\n\n\t\t\tstack = await dokployFetch<DokployCompose>(input.target, \"compose.create\", {\n\t\t\t\tmethod: \"POST\",\n\t\t\t\tbody: {\n\t\t\t\t\tname: input.projectName,\n\t\t\t\t\tdescription: input.description ?? `Stack ${input.projectName}`,\n\t\t\t\t\tenvironmentId: env.environmentId,\n\t\t\t\t\tcomposeType: \"docker-compose\",\n\t\t\t\t\tcomposeFile: composeYaml,\n\t\t\t\t\t...(input.serverId ? { serverId: input.serverId } : {}),\n\t\t\t\t},\n\t\t\t});\n\n\t\t\t// Dokploy's compose.create schema does NOT accept sourceType;\n\t\t\t// it defaults to \"github\". We must update it to \"raw\" so the\n\t\t\t// deploy step writes the compose file from the stored YAML\n\t\t\t// instead of attempting to clone from a Git provider.\n\t\t\tif (stack?.composeId) {\n\t\t\t\tawait dokployFetch(input.target, \"compose.update\", {\n\t\t\t\t\tmethod: \"POST\",\n\t\t\t\t\tbody: {\n\t\t\t\t\t\tcomposeId: stack.composeId,\n\t\t\t\t\t\tsourceType: \"raw\",\n\t\t\t\t\t},\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tresult.composeId = stack?.composeId;\n\t\t\tstep3.status = \"done\";\n\t\t\tstep3.detail = stack?.composeId;\n\n\t\t\t/**\n\t\t\t * STEP 4\n\t\t\t * Update stack if compose changed\n\t\t\t */\n\n\t\t\tstep4.status = \"running\";\n\n\t\t\tconst existingStack = await dokployFetch<DokployCompose>(\n\t\t\t\tinput.target,\n\t\t\t\t`compose.one?composeId=${stack?.composeId}`,\n\t\t\t);\n\n\t\t\tconst newHash = hashString(composeYaml);\n\t\t\tconst oldHash = hashString(existingStack.compose ?? \"\");\n\n\t\t\tif (newHash !== oldHash) {\n\t\t\t\tawait dokployFetch(input.target, \"compose.update\", {\n\t\t\t\t\tmethod: \"POST\",\n\t\t\t\t\tbody: {\n\t\t\t\t\t\tcomposeId: stack?.composeId,\n\t\t\t\t\t\tcomposeFile: composeYaml,\n\t\t\t\t\t\tenv: input.envContent ?? \"\",\n\t\t\t\t\t},\n\t\t\t\t});\n\n\t\t\t\tstep4.detail = \"Stack updated\";\n\t\t\t} else {\n\t\t\t\tstep4.detail = \"No compose changes\";\n\t\t\t}\n\n\t\t\tstep4.status = \"done\";\n\n\t\t\t/**\n\t\t\t * STEP 5\n\t\t\t * Deploy\n\t\t\t */\n\n\t\t\tstep5.status = \"running\";\n\n\t\t\tawait dokployFetch(input.target, \"compose.deploy\", {\n\t\t\t\tmethod: \"POST\",\n\t\t\t\tbody: {\n\t\t\t\t\tcomposeId: stack?.composeId,\n\n\t\t\t\t\ttitle: `Deploy ${input.projectName}`,\n\n\t\t\t\t\tdescription: \"CI deployment\",\n\t\t\t\t},\n\t\t\t});\n\n\t\t\tstep5.status = \"done\";\n\n\t\t\tresult.success = true;\n\n\t\t\tconst base = input.target.instanceUrl.replace(/\\/+$/, \"\");\n\n\t\t\tresult.dashboardUrl = `${base}/dashboard/project/${project.projectId}/environment/${env.environmentId}/services/compose/${stack?.composeId}?tab=deployments`;\n\n\t\t\tinput.logger?.log({\n\t\t\t\tlevel: \"info\",\n\t\t\t\tcategory: \"deployment\",\n\t\t\t\tmessage: `Deployment to Dokploy succeeded`,\n\t\t\t\toutcome: \"success\",\n\t\t\t\tcontext: {\n\t\t\t\t\tprojectId: project.projectId,\n\t\t\t\t\tcomposeId: stack?.composeId,\n\t\t\t\t\tdashboardUrl: result.dashboardUrl,\n\t\t\t\t},\n\t\t\t\tsteps: steps.map((s) => ({\n\t\t\t\t\tname: s.step,\n\t\t\t\t\tstatus:\n\t\t\t\t\t\ts.status === \"done\"\n\t\t\t\t\t\t\t? (\"success\" as const)\n\t\t\t\t\t\t\t: s.status === \"error\"\n\t\t\t\t\t\t\t\t? (\"failure\" as const)\n\t\t\t\t\t\t\t\t: (\"in_progress\" as const),\n\t\t\t\t\tdetail: s.detail,\n\t\t\t\t\tstartedAt: new Date().toISOString(),\n\t\t\t\t})),\n\t\t\t});\n\n\t\t\treturn result;\n\t\t} catch (err) {\n\t\t\tconst running = steps.find((s) => s.status === \"running\");\n\n\t\t\tif (running) {\n\t\t\t\trunning.status = \"error\";\n\n\t\t\t\trunning.detail = err instanceof Error ? err.message : String(err);\n\t\t\t}\n\n\t\t\tresult.error = err instanceof Error ? err.message : String(err);\n\n\t\t\tinput.logger?.error(\n\t\t\t\t\"deployment\",\n\t\t\t\t`Deployment to Dokploy failed`,\n\t\t\t\terr instanceof Error ? err : null,\n\t\t\t\t{\n\t\t\t\t\tprojectName: input.projectName,\n\t\t\t\t\tfailedStep: running?.step,\n\t\t\t\t},\n\t\t\t);\n\n\t\t\treturn result;\n\t\t}\n\t}\n}\n"],"mappings":"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"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { t as DokployDeployer } from "../dokploy-
|
|
1
|
+
import { t as DokployDeployer } from "../dokploy-BnVDjWCV.cjs";
|
|
2
2
|
export { DokployDeployer };
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { t as DokployDeployer } from "../dokploy-
|
|
1
|
+
import { t as DokployDeployer } from "../dokploy-BqLdCfyR.mjs";
|
|
2
2
|
export { DokployDeployer };
|
|
@@ -83,6 +83,10 @@ var DokployDeployer = class {
|
|
|
83
83
|
}
|
|
84
84
|
}
|
|
85
85
|
async deploy(input) {
|
|
86
|
+
input.logger?.info("deployment", `Starting deployment to Dokploy`, {
|
|
87
|
+
projectName: input.projectName,
|
|
88
|
+
instanceUrl: input.target.instanceUrl
|
|
89
|
+
});
|
|
86
90
|
const step1 = {
|
|
87
91
|
step: "Find or create project",
|
|
88
92
|
status: "pending"
|
|
@@ -202,6 +206,23 @@ var DokployDeployer = class {
|
|
|
202
206
|
step5.status = "done";
|
|
203
207
|
result.success = true;
|
|
204
208
|
result.dashboardUrl = `${input.target.instanceUrl.replace(/\/+$/, "")}/dashboard/project/${project.projectId}/environment/${env.environmentId}/services/compose/${stack?.composeId}?tab=deployments`;
|
|
209
|
+
input.logger?.log({
|
|
210
|
+
level: "info",
|
|
211
|
+
category: "deployment",
|
|
212
|
+
message: `Deployment to Dokploy succeeded`,
|
|
213
|
+
outcome: "success",
|
|
214
|
+
context: {
|
|
215
|
+
projectId: project.projectId,
|
|
216
|
+
composeId: stack?.composeId,
|
|
217
|
+
dashboardUrl: result.dashboardUrl
|
|
218
|
+
},
|
|
219
|
+
steps: steps.map((s) => ({
|
|
220
|
+
name: s.step,
|
|
221
|
+
status: s.status === "done" ? "success" : s.status === "error" ? "failure" : "in_progress",
|
|
222
|
+
detail: s.detail,
|
|
223
|
+
startedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
224
|
+
}))
|
|
225
|
+
});
|
|
205
226
|
return result;
|
|
206
227
|
} catch (err) {
|
|
207
228
|
const running = steps.find((s) => s.status === "running");
|
|
@@ -210,6 +231,10 @@ var DokployDeployer = class {
|
|
|
210
231
|
running.detail = err instanceof Error ? err.message : String(err);
|
|
211
232
|
}
|
|
212
233
|
result.error = err instanceof Error ? err.message : String(err);
|
|
234
|
+
input.logger?.error("deployment", `Deployment to Dokploy failed`, err instanceof Error ? err : null, {
|
|
235
|
+
projectName: input.projectName,
|
|
236
|
+
failedStep: running?.step
|
|
237
|
+
});
|
|
213
238
|
return result;
|
|
214
239
|
}
|
|
215
240
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dokploy.mjs","names":[],"sources":["../../src/deployers/dokploy.ts"],"sourcesContent":["/**\n * Dokploy PaaS deployer — deploys Docker Compose stacks via the Dokploy REST API.\n *\n * API docs: https://docs.dokploy.com/docs/api\n * Auth: x-api-key header\n * Endpoints use dot-notation (e.g. /api/project.create, /api/compose.deploy)\n */\n\nimport { sanitizeComposeForPaas } from \"./strip-host-ports.js\";\nimport type {\n\tDeployInput,\n\tDeployResult,\n\tDeployStep,\n\tDeployTarget,\n\tDokployEnvironment,\n\tPaasDeployer,\n\tPaasServer,\n} from \"./types.js\";\n\ninterface DokployProject {\n\tprojectId: string;\n\tname: string;\n\tdescription: string;\n\tenvironments?: DokployEnvironment[];\n}\n\ninterface DokployCompose {\n\tcomposeId: string;\n\tname: string;\n\tstatus?: string;\n\tcompose?: string;\n}\n\ninterface ProjectCreateResult {\n\tproject: DokployProject;\n\tprojectId: string;\n\tname: string;\n\tdescription: string;\n\tenvironments?: { environmentId: string; name: string }[];\n}\n\n/** Build a full Dokploy API URL from a dot-notation endpoint (e.g. \"project.create\"). */\nfunction apiUrl(target: DeployTarget, endpoint: string): string {\n\tconst base = target.instanceUrl.replace(/\\/+$/, \"\");\n\treturn `${base}/api/${endpoint}`;\n}\n/**\n * Typed fetch wrapper for the Dokploy API.\n * Handles JSON serialisation, x-api-key auth, and error extraction.\n */\nasync function dokployFetch<T>(\n\ttarget: DeployTarget,\n\tendpoint: string,\n\toptions: { method?: string; body?: unknown } = {},\n): Promise<T> {\n\tconst res = await fetch(apiUrl(target, endpoint), {\n\t\tmethod: options.method ?? \"GET\",\n\t\theaders: {\n\t\t\t\"Content-Type\": \"application/json\",\n\t\t\t\"x-api-key\": target.apiKey,\n\t\t},\n\t\tbody: options.body ? JSON.stringify(options.body) : undefined,\n\t});\n\n\tif (!res.ok) {\n\t\tconst text = await res.text().catch(() => \"\");\n\t\tlet detail = text;\n\n\t\ttry {\n\t\t\tconst json = JSON.parse(text);\n\t\t\tdetail = json.message || json.error || text;\n\t\t} catch {}\n\n\t\tthrow new Error(`Dokploy API ${res.status}: ${detail}`);\n\t}\n\n\tconst text = await res.text();\n\tif (!text) return undefined as T;\n\n\treturn JSON.parse(text) as T;\n}\n\n/**\n * Simple hash for compose diff detection\n */\nfunction hashString(str: string) {\n\tlet hash = 0;\n\n\tfor (let i = 0; i < str.length; i++) {\n\t\thash = (hash << 5) - hash + str.charCodeAt(i);\n\t\thash |= 0;\n\t}\n\n\treturn hash;\n}\n\n/**\n * Deploys Docker Compose stacks to a Dokploy instance.\n *\n * Deploy flow (4 steps):\n * 1. Create a Dokploy project\n * 2. Create a compose stack inside the project's default environment\n * 3. Push .env variables to the compose stack\n * 4. Trigger the deployment\n */\n\nexport class DokployDeployer implements PaasDeployer {\n\treadonly name = \"Dokploy\";\n\treadonly id = \"dokploy\";\n\n\tasync testConnection(target: DeployTarget): Promise<{ ok: boolean; error?: string }> {\n\t\ttry {\n\t\t\tawait dokployFetch<DokployProject[]>(target, \"project.all\");\n\n\t\t\treturn { ok: true };\n\t\t} catch (err) {\n\t\t\treturn {\n\t\t\t\tok: false,\n\t\t\t\terror: err instanceof Error ? err.message : String(err),\n\t\t\t};\n\t\t}\n\t}\n\n\tasync listServers(target: DeployTarget): Promise<PaasServer[]> {\n\t\ttry {\n\t\t\tconst servers = await dokployFetch<{ serverId: string; name: string; ipAddress: string }[]>(\n\t\t\t\ttarget,\n\t\t\t\t\"server.all\",\n\t\t\t);\n\t\t\treturn servers.map((s) => ({\n\t\t\t\tid: s.serverId,\n\t\t\t\tname: s.name,\n\t\t\t\tip: s.ipAddress,\n\t\t\t}));\n\t\t} catch {\n\t\t\t// Return empty list if server API is not available\n\t\t\treturn [];\n\t\t}\n\t}\n\n\tasync deploy(input: DeployInput): Promise<DeployResult> {\n\t\tconst step1: DeployStep = {\n\t\t\tstep: \"Find or create project\",\n\t\t\tstatus: \"pending\",\n\t\t};\n\t\tconst step2: DeployStep = {\n\t\t\tstep: \"Find default environment\",\n\t\t\tstatus: \"pending\",\n\t\t};\n\t\tconst step3: DeployStep = {\n\t\t\tstep: \"Find or create compose stack\",\n\t\t\tstatus: \"pending\",\n\t\t};\n\t\tconst step4: DeployStep = {\n\t\t\tstep: \"Update stack configuration\",\n\t\t\tstatus: \"pending\",\n\t\t};\n\t\tconst step5: DeployStep = { step: \"Deploy stack\", status: \"pending\" };\n\t\tconst steps: DeployStep[] = [step1, step2, step3, step4, step5];\n\n\t\tconst result: DeployResult = { success: false, steps };\n\n\t\t// Strip host port bindings — Dokploy routes via Traefik,\n\t\t// so host ports are unnecessary and cause \"port already allocated\" errors.\n\t\tconst composeYaml = sanitizeComposeForPaas(input.composeYaml);\n\n\t\ttry {\n\t\t\t/**\n\t\t\t * STEP 1\n\t\t\t * Find or create project\n\t\t\t */\n\n\t\t\tstep1.status = \"running\";\n\n\t\t\tconst projects = await dokployFetch<DokployProject[]>(input.target, \"project.all\");\n\n\t\t\tlet project = projects.find((p) => p.name === input.projectName);\n\n\t\t\tif (!project) {\n\t\t\t\tconst created = await dokployFetch<ProjectCreateResult>(input.target, \"project.create\", {\n\t\t\t\t\tmethod: \"POST\",\n\t\t\t\t\tbody: {\n\t\t\t\t\t\tname: input.projectName,\n\t\t\t\t\t\tdescription: input.description ?? `OpenClaw stack: ${input.projectName}`,\n\t\t\t\t\t},\n\t\t\t\t});\n\n\t\t\t\tproject = created.project;\n\t\t\t}\n\n\t\t\tresult.projectId = project.projectId;\n\n\t\t\tstep1.status = \"done\";\n\t\t\tstep1.detail = `Project ID: ${project.projectId}`;\n\n\t\t\t/**\n\t\t\t * STEP 2\n\t\t\t * Find default environment\n\t\t\t */\n\n\t\t\tstep2.status = \"running\";\n\n\t\t\tconst projectDetail = await dokployFetch<DokployProject>(\n\t\t\t\tinput.target,\n\t\t\t\t`project.one?projectId=${project.projectId}`,\n\t\t\t);\n\n\t\t\tconst env = projectDetail.environments?.find((e) => e.isDefault);\n\n\t\t\tif (!env) throw new Error(\"No default environment\");\n\n\t\t\tstep2.status = \"done\";\n\t\t\tstep2.detail = env.environmentId;\n\n\t\t\t/**\n\t\t\t * STEP 3\n\t\t\t * Find or create compose stack\n\t\t\t */\n\n\t\t\tstep3.status = \"running\";\n\n\t\t\tlet stack: DokployCompose | null = null;\n\n\t\t\tstack = await dokployFetch<DokployCompose>(input.target, \"compose.create\", {\n\t\t\t\tmethod: \"POST\",\n\t\t\t\tbody: {\n\t\t\t\t\tname: input.projectName,\n\t\t\t\t\tdescription: input.description ?? `Stack ${input.projectName}`,\n\t\t\t\t\tenvironmentId: env.environmentId,\n\t\t\t\t\tcomposeType: \"docker-compose\",\n\t\t\t\t\tcomposeFile: composeYaml,\n\t\t\t\t\t...(input.serverId ? { serverId: input.serverId } : {}),\n\t\t\t\t},\n\t\t\t});\n\n\t\t\t// Dokploy's compose.create schema does NOT accept sourceType;\n\t\t\t// it defaults to \"github\". We must update it to \"raw\" so the\n\t\t\t// deploy step writes the compose file from the stored YAML\n\t\t\t// instead of attempting to clone from a Git provider.\n\t\t\tif (stack?.composeId) {\n\t\t\t\tawait dokployFetch(input.target, \"compose.update\", {\n\t\t\t\t\tmethod: \"POST\",\n\t\t\t\t\tbody: {\n\t\t\t\t\t\tcomposeId: stack.composeId,\n\t\t\t\t\t\tsourceType: \"raw\",\n\t\t\t\t\t},\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tresult.composeId = stack?.composeId;\n\t\t\tstep3.status = \"done\";\n\t\t\tstep3.detail = stack?.composeId;\n\n\t\t\t/**\n\t\t\t * STEP 4\n\t\t\t * Update stack if compose changed\n\t\t\t */\n\n\t\t\tstep4.status = \"running\";\n\n\t\t\tconst existingStack = await dokployFetch<DokployCompose>(\n\t\t\t\tinput.target,\n\t\t\t\t`compose.one?composeId=${stack?.composeId}`,\n\t\t\t);\n\n\t\t\tconst newHash = hashString(composeYaml);\n\t\t\tconst oldHash = hashString(existingStack.compose ?? \"\");\n\n\t\t\tif (newHash !== oldHash) {\n\t\t\t\tawait dokployFetch(input.target, \"compose.update\", {\n\t\t\t\t\tmethod: \"POST\",\n\t\t\t\t\tbody: {\n\t\t\t\t\t\tcomposeId: stack?.composeId,\n\t\t\t\t\t\tcomposeFile: composeYaml,\n\t\t\t\t\t\tenv: input.envContent ?? \"\",\n\t\t\t\t\t},\n\t\t\t\t});\n\n\t\t\t\tstep4.detail = \"Stack updated\";\n\t\t\t} else {\n\t\t\t\tstep4.detail = \"No compose changes\";\n\t\t\t}\n\n\t\t\tstep4.status = \"done\";\n\n\t\t\t/**\n\t\t\t * STEP 5\n\t\t\t * Deploy\n\t\t\t */\n\n\t\t\tstep5.status = \"running\";\n\n\t\t\tawait dokployFetch(input.target, \"compose.deploy\", {\n\t\t\t\tmethod: \"POST\",\n\t\t\t\tbody: {\n\t\t\t\t\tcomposeId: stack?.composeId,\n\n\t\t\t\t\ttitle: `Deploy ${input.projectName}`,\n\n\t\t\t\t\tdescription: \"CI deployment\",\n\t\t\t\t},\n\t\t\t});\n\n\t\t\tstep5.status = \"done\";\n\n\t\t\tresult.success = true;\n\n\t\t\tconst base = input.target.instanceUrl.replace(/\\/+$/, \"\");\n\n\t\t\tresult.dashboardUrl = `${base}/dashboard/project/${project.projectId}/environment/${env.environmentId}/services/compose/${stack?.composeId}?tab=deployments`;\n\n\t\t\treturn result;\n\t\t} catch (err) {\n\t\t\tconst running = steps.find((s) => s.status === \"running\");\n\n\t\t\tif (running) {\n\t\t\t\trunning.status = \"error\";\n\n\t\t\t\trunning.detail = err instanceof Error ? err.message : String(err);\n\t\t\t}\n\n\t\t\tresult.error = err instanceof Error ? err.message : String(err);\n\n\t\t\treturn result;\n\t\t}\n\t}\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"dokploy.mjs","names":[],"sources":["../../src/deployers/dokploy.ts"],"sourcesContent":["/**\n * Dokploy PaaS deployer — deploys Docker Compose stacks via the Dokploy REST API.\n *\n * API docs: https://docs.dokploy.com/docs/api\n * Auth: x-api-key header\n * Endpoints use dot-notation (e.g. /api/project.create, /api/compose.deploy)\n */\n\nimport { sanitizeComposeForPaas } from \"./strip-host-ports.js\";\nimport type {\n\tDeployInput,\n\tDeployResult,\n\tDeployStep,\n\tDeployTarget,\n\tDokployEnvironment,\n\tPaasDeployer,\n\tPaasServer,\n} from \"./types.js\";\n\ninterface DokployProject {\n\tprojectId: string;\n\tname: string;\n\tdescription: string;\n\tenvironments?: DokployEnvironment[];\n}\n\ninterface DokployCompose {\n\tcomposeId: string;\n\tname: string;\n\tstatus?: string;\n\tcompose?: string;\n}\n\ninterface ProjectCreateResult {\n\tproject: DokployProject;\n\tprojectId: string;\n\tname: string;\n\tdescription: string;\n\tenvironments?: { environmentId: string; name: string }[];\n}\n\n/** Build a full Dokploy API URL from a dot-notation endpoint (e.g. \"project.create\"). */\nfunction apiUrl(target: DeployTarget, endpoint: string): string {\n\tconst base = target.instanceUrl.replace(/\\/+$/, \"\");\n\treturn `${base}/api/${endpoint}`;\n}\n/**\n * Typed fetch wrapper for the Dokploy API.\n * Handles JSON serialisation, x-api-key auth, and error extraction.\n */\nasync function dokployFetch<T>(\n\ttarget: DeployTarget,\n\tendpoint: string,\n\toptions: { method?: string; body?: unknown } = {},\n): Promise<T> {\n\tconst res = await fetch(apiUrl(target, endpoint), {\n\t\tmethod: options.method ?? \"GET\",\n\t\theaders: {\n\t\t\t\"Content-Type\": \"application/json\",\n\t\t\t\"x-api-key\": target.apiKey,\n\t\t},\n\t\tbody: options.body ? JSON.stringify(options.body) : undefined,\n\t});\n\n\tif (!res.ok) {\n\t\tconst text = await res.text().catch(() => \"\");\n\t\tlet detail = text;\n\n\t\ttry {\n\t\t\tconst json = JSON.parse(text);\n\t\t\tdetail = json.message || json.error || text;\n\t\t} catch {}\n\n\t\tthrow new Error(`Dokploy API ${res.status}: ${detail}`);\n\t}\n\n\tconst text = await res.text();\n\tif (!text) return undefined as T;\n\n\treturn JSON.parse(text) as T;\n}\n\n/**\n * Simple hash for compose diff detection\n */\nfunction hashString(str: string) {\n\tlet hash = 0;\n\n\tfor (let i = 0; i < str.length; i++) {\n\t\thash = (hash << 5) - hash + str.charCodeAt(i);\n\t\thash |= 0;\n\t}\n\n\treturn hash;\n}\n\n/**\n * Deploys Docker Compose stacks to a Dokploy instance.\n *\n * Deploy flow (4 steps):\n * 1. Create a Dokploy project\n * 2. Create a compose stack inside the project's default environment\n * 3. Push .env variables to the compose stack\n * 4. Trigger the deployment\n */\n\nexport class DokployDeployer implements PaasDeployer {\n\treadonly name = \"Dokploy\";\n\treadonly id = \"dokploy\";\n\n\tasync testConnection(target: DeployTarget): Promise<{ ok: boolean; error?: string }> {\n\t\ttry {\n\t\t\tawait dokployFetch<DokployProject[]>(target, \"project.all\");\n\n\t\t\treturn { ok: true };\n\t\t} catch (err) {\n\t\t\treturn {\n\t\t\t\tok: false,\n\t\t\t\terror: err instanceof Error ? err.message : String(err),\n\t\t\t};\n\t\t}\n\t}\n\n\tasync listServers(target: DeployTarget): Promise<PaasServer[]> {\n\t\ttry {\n\t\t\tconst servers = await dokployFetch<{ serverId: string; name: string; ipAddress: string }[]>(\n\t\t\t\ttarget,\n\t\t\t\t\"server.all\",\n\t\t\t);\n\t\t\treturn servers.map((s) => ({\n\t\t\t\tid: s.serverId,\n\t\t\t\tname: s.name,\n\t\t\t\tip: s.ipAddress,\n\t\t\t}));\n\t\t} catch {\n\t\t\t// Return empty list if server API is not available\n\t\t\treturn [];\n\t\t}\n\t}\n\n\tasync deploy(input: DeployInput): Promise<DeployResult> {\n\t\tinput.logger?.info(\"deployment\", `Starting deployment to Dokploy`, {\n\t\t\tprojectName: input.projectName,\n\t\t\tinstanceUrl: input.target.instanceUrl,\n\t\t});\n\n\t\tconst step1: DeployStep = {\n\t\t\tstep: \"Find or create project\",\n\t\t\tstatus: \"pending\",\n\t\t};\n\t\tconst step2: DeployStep = {\n\t\t\tstep: \"Find default environment\",\n\t\t\tstatus: \"pending\",\n\t\t};\n\t\tconst step3: DeployStep = {\n\t\t\tstep: \"Find or create compose stack\",\n\t\t\tstatus: \"pending\",\n\t\t};\n\t\tconst step4: DeployStep = {\n\t\t\tstep: \"Update stack configuration\",\n\t\t\tstatus: \"pending\",\n\t\t};\n\t\tconst step5: DeployStep = { step: \"Deploy stack\", status: \"pending\" };\n\t\tconst steps: DeployStep[] = [step1, step2, step3, step4, step5];\n\n\t\tconst result: DeployResult = { success: false, steps };\n\n\t\t// Strip host port bindings — Dokploy routes via Traefik,\n\t\t// so host ports are unnecessary and cause \"port already allocated\" errors.\n\t\tconst composeYaml = sanitizeComposeForPaas(input.composeYaml);\n\n\t\ttry {\n\t\t\t/**\n\t\t\t * STEP 1\n\t\t\t * Find or create project\n\t\t\t */\n\n\t\t\tstep1.status = \"running\";\n\n\t\t\tconst projects = await dokployFetch<DokployProject[]>(input.target, \"project.all\");\n\n\t\t\tlet project = projects.find((p) => p.name === input.projectName);\n\n\t\t\tif (!project) {\n\t\t\t\tconst created = await dokployFetch<ProjectCreateResult>(input.target, \"project.create\", {\n\t\t\t\t\tmethod: \"POST\",\n\t\t\t\t\tbody: {\n\t\t\t\t\t\tname: input.projectName,\n\t\t\t\t\t\tdescription: input.description ?? `OpenClaw stack: ${input.projectName}`,\n\t\t\t\t\t},\n\t\t\t\t});\n\n\t\t\t\tproject = created.project;\n\t\t\t}\n\n\t\t\tresult.projectId = project.projectId;\n\n\t\t\tstep1.status = \"done\";\n\t\t\tstep1.detail = `Project ID: ${project.projectId}`;\n\n\t\t\t/**\n\t\t\t * STEP 2\n\t\t\t * Find default environment\n\t\t\t */\n\n\t\t\tstep2.status = \"running\";\n\n\t\t\tconst projectDetail = await dokployFetch<DokployProject>(\n\t\t\t\tinput.target,\n\t\t\t\t`project.one?projectId=${project.projectId}`,\n\t\t\t);\n\n\t\t\tconst env = projectDetail.environments?.find((e) => e.isDefault);\n\n\t\t\tif (!env) throw new Error(\"No default environment\");\n\n\t\t\tstep2.status = \"done\";\n\t\t\tstep2.detail = env.environmentId;\n\n\t\t\t/**\n\t\t\t * STEP 3\n\t\t\t * Find or create compose stack\n\t\t\t */\n\n\t\t\tstep3.status = \"running\";\n\n\t\t\tlet stack: DokployCompose | null = null;\n\n\t\t\tstack = await dokployFetch<DokployCompose>(input.target, \"compose.create\", {\n\t\t\t\tmethod: \"POST\",\n\t\t\t\tbody: {\n\t\t\t\t\tname: input.projectName,\n\t\t\t\t\tdescription: input.description ?? `Stack ${input.projectName}`,\n\t\t\t\t\tenvironmentId: env.environmentId,\n\t\t\t\t\tcomposeType: \"docker-compose\",\n\t\t\t\t\tcomposeFile: composeYaml,\n\t\t\t\t\t...(input.serverId ? { serverId: input.serverId } : {}),\n\t\t\t\t},\n\t\t\t});\n\n\t\t\t// Dokploy's compose.create schema does NOT accept sourceType;\n\t\t\t// it defaults to \"github\". We must update it to \"raw\" so the\n\t\t\t// deploy step writes the compose file from the stored YAML\n\t\t\t// instead of attempting to clone from a Git provider.\n\t\t\tif (stack?.composeId) {\n\t\t\t\tawait dokployFetch(input.target, \"compose.update\", {\n\t\t\t\t\tmethod: \"POST\",\n\t\t\t\t\tbody: {\n\t\t\t\t\t\tcomposeId: stack.composeId,\n\t\t\t\t\t\tsourceType: \"raw\",\n\t\t\t\t\t},\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tresult.composeId = stack?.composeId;\n\t\t\tstep3.status = \"done\";\n\t\t\tstep3.detail = stack?.composeId;\n\n\t\t\t/**\n\t\t\t * STEP 4\n\t\t\t * Update stack if compose changed\n\t\t\t */\n\n\t\t\tstep4.status = \"running\";\n\n\t\t\tconst existingStack = await dokployFetch<DokployCompose>(\n\t\t\t\tinput.target,\n\t\t\t\t`compose.one?composeId=${stack?.composeId}`,\n\t\t\t);\n\n\t\t\tconst newHash = hashString(composeYaml);\n\t\t\tconst oldHash = hashString(existingStack.compose ?? \"\");\n\n\t\t\tif (newHash !== oldHash) {\n\t\t\t\tawait dokployFetch(input.target, \"compose.update\", {\n\t\t\t\t\tmethod: \"POST\",\n\t\t\t\t\tbody: {\n\t\t\t\t\t\tcomposeId: stack?.composeId,\n\t\t\t\t\t\tcomposeFile: composeYaml,\n\t\t\t\t\t\tenv: input.envContent ?? \"\",\n\t\t\t\t\t},\n\t\t\t\t});\n\n\t\t\t\tstep4.detail = \"Stack updated\";\n\t\t\t} else {\n\t\t\t\tstep4.detail = \"No compose changes\";\n\t\t\t}\n\n\t\t\tstep4.status = \"done\";\n\n\t\t\t/**\n\t\t\t * STEP 5\n\t\t\t * Deploy\n\t\t\t */\n\n\t\t\tstep5.status = \"running\";\n\n\t\t\tawait dokployFetch(input.target, \"compose.deploy\", {\n\t\t\t\tmethod: \"POST\",\n\t\t\t\tbody: {\n\t\t\t\t\tcomposeId: stack?.composeId,\n\n\t\t\t\t\ttitle: `Deploy ${input.projectName}`,\n\n\t\t\t\t\tdescription: \"CI deployment\",\n\t\t\t\t},\n\t\t\t});\n\n\t\t\tstep5.status = \"done\";\n\n\t\t\tresult.success = true;\n\n\t\t\tconst base = input.target.instanceUrl.replace(/\\/+$/, \"\");\n\n\t\t\tresult.dashboardUrl = `${base}/dashboard/project/${project.projectId}/environment/${env.environmentId}/services/compose/${stack?.composeId}?tab=deployments`;\n\n\t\t\tinput.logger?.log({\n\t\t\t\tlevel: \"info\",\n\t\t\t\tcategory: \"deployment\",\n\t\t\t\tmessage: `Deployment to Dokploy succeeded`,\n\t\t\t\toutcome: \"success\",\n\t\t\t\tcontext: {\n\t\t\t\t\tprojectId: project.projectId,\n\t\t\t\t\tcomposeId: stack?.composeId,\n\t\t\t\t\tdashboardUrl: result.dashboardUrl,\n\t\t\t\t},\n\t\t\t\tsteps: steps.map((s) => ({\n\t\t\t\t\tname: s.step,\n\t\t\t\t\tstatus:\n\t\t\t\t\t\ts.status === \"done\"\n\t\t\t\t\t\t\t? (\"success\" as const)\n\t\t\t\t\t\t\t: s.status === \"error\"\n\t\t\t\t\t\t\t\t? (\"failure\" as const)\n\t\t\t\t\t\t\t\t: (\"in_progress\" as const),\n\t\t\t\t\tdetail: s.detail,\n\t\t\t\t\tstartedAt: new Date().toISOString(),\n\t\t\t\t})),\n\t\t\t});\n\n\t\t\treturn result;\n\t\t} catch (err) {\n\t\t\tconst running = steps.find((s) => s.status === \"running\");\n\n\t\t\tif (running) {\n\t\t\t\trunning.status = \"error\";\n\n\t\t\t\trunning.detail = err instanceof Error ? err.message : String(err);\n\t\t\t}\n\n\t\t\tresult.error = err instanceof Error ? err.message : String(err);\n\n\t\t\tinput.logger?.error(\n\t\t\t\t\"deployment\",\n\t\t\t\t`Deployment to Dokploy failed`,\n\t\t\t\terr instanceof Error ? err : null,\n\t\t\t\t{\n\t\t\t\t\tprojectName: input.projectName,\n\t\t\t\t\tfailedStep: running?.step,\n\t\t\t\t},\n\t\t\t);\n\n\t\t\treturn result;\n\t\t}\n\t}\n}\n"],"mappings":";;;;;;;;;;AA0CA,SAAS,OAAO,QAAsB,UAA0B;AAE/D,QAAO,GADM,OAAO,YAAY,QAAQ,QAAQ,GAAG,CACpC,OAAO;;;;;;AAMvB,eAAe,aACd,QACA,UACA,UAA+C,EAAE,EACpC;CACb,MAAM,MAAM,MAAM,MAAM,OAAO,QAAQ,SAAS,EAAE;EACjD,QAAQ,QAAQ,UAAU;EAC1B,SAAS;GACR,gBAAgB;GAChB,aAAa,OAAO;GACpB;EACD,MAAM,QAAQ,OAAO,KAAK,UAAU,QAAQ,KAAK,GAAG,KAAA;EACpD,CAAC;AAEF,KAAI,CAAC,IAAI,IAAI;EACZ,MAAM,OAAO,MAAM,IAAI,MAAM,CAAC,YAAY,GAAG;EAC7C,IAAI,SAAS;AAEb,MAAI;GACH,MAAM,OAAO,KAAK,MAAM,KAAK;AAC7B,YAAS,KAAK,WAAW,KAAK,SAAS;UAChC;AAER,QAAM,IAAI,MAAM,eAAe,IAAI,OAAO,IAAI,SAAS;;CAGxD,MAAM,OAAO,MAAM,IAAI,MAAM;AAC7B,KAAI,CAAC,KAAM,QAAO,KAAA;AAElB,QAAO,KAAK,MAAM,KAAK;;;;;AAMxB,SAAS,WAAW,KAAa;CAChC,IAAI,OAAO;AAEX,MAAK,IAAI,IAAI,GAAG,IAAI,IAAI,QAAQ,KAAK;AACpC,UAAQ,QAAQ,KAAK,OAAO,IAAI,WAAW,EAAE;AAC7C,UAAQ;;AAGT,QAAO;;;;;;;;;;;AAaR,IAAa,kBAAb,MAAqD;CACpD,OAAgB;CAChB,KAAc;CAEd,MAAM,eAAe,QAAgE;AACpF,MAAI;AACH,SAAM,aAA+B,QAAQ,cAAc;AAE3D,UAAO,EAAE,IAAI,MAAM;WACX,KAAK;AACb,UAAO;IACN,IAAI;IACJ,OAAO,eAAe,QAAQ,IAAI,UAAU,OAAO,IAAI;IACvD;;;CAIH,MAAM,YAAY,QAA6C;AAC9D,MAAI;AAKH,WAJgB,MAAM,aACrB,QACA,aACA,EACc,KAAK,OAAO;IAC1B,IAAI,EAAE;IACN,MAAM,EAAE;IACR,IAAI,EAAE;IACN,EAAE;UACI;AAEP,UAAO,EAAE;;;CAIX,MAAM,OAAO,OAA2C;AACvD,QAAM,QAAQ,KAAK,cAAc,kCAAkC;GAClE,aAAa,MAAM;GACnB,aAAa,MAAM,OAAO;GAC1B,CAAC;EAEF,MAAM,QAAoB;GACzB,MAAM;GACN,QAAQ;GACR;EACD,MAAM,QAAoB;GACzB,MAAM;GACN,QAAQ;GACR;EACD,MAAM,QAAoB;GACzB,MAAM;GACN,QAAQ;GACR;EACD,MAAM,QAAoB;GACzB,MAAM;GACN,QAAQ;GACR;EACD,MAAM,QAAoB;GAAE,MAAM;GAAgB,QAAQ;GAAW;EACrE,MAAM,QAAsB;GAAC;GAAO;GAAO;GAAO;GAAO;GAAM;EAE/D,MAAM,SAAuB;GAAE,SAAS;GAAO;GAAO;EAItD,MAAM,cAAc,uBAAuB,MAAM,YAAY;AAE7D,MAAI;;;;;AAMH,SAAM,SAAS;GAIf,IAAI,WAFa,MAAM,aAA+B,MAAM,QAAQ,cAAc,EAE3D,MAAM,MAAM,EAAE,SAAS,MAAM,YAAY;AAEhE,OAAI,CAAC,QASJ,YARgB,MAAM,aAAkC,MAAM,QAAQ,kBAAkB;IACvF,QAAQ;IACR,MAAM;KACL,MAAM,MAAM;KACZ,aAAa,MAAM,eAAe,mBAAmB,MAAM;KAC3D;IACD,CAAC,EAEgB;AAGnB,UAAO,YAAY,QAAQ;AAE3B,SAAM,SAAS;AACf,SAAM,SAAS,eAAe,QAAQ;;;;;AAOtC,SAAM,SAAS;GAOf,MAAM,OALgB,MAAM,aAC3B,MAAM,QACN,yBAAyB,QAAQ,YACjC,EAEyB,cAAc,MAAM,MAAM,EAAE,UAAU;AAEhE,OAAI,CAAC,IAAK,OAAM,IAAI,MAAM,yBAAyB;AAEnD,SAAM,SAAS;AACf,SAAM,SAAS,IAAI;;;;;AAOnB,SAAM,SAAS;GAEf,IAAI,QAA+B;AAEnC,WAAQ,MAAM,aAA6B,MAAM,QAAQ,kBAAkB;IAC1E,QAAQ;IACR,MAAM;KACL,MAAM,MAAM;KACZ,aAAa,MAAM,eAAe,SAAS,MAAM;KACjD,eAAe,IAAI;KACnB,aAAa;KACb,aAAa;KACb,GAAI,MAAM,WAAW,EAAE,UAAU,MAAM,UAAU,GAAG,EAAE;KACtD;IACD,CAAC;AAMF,OAAI,OAAO,UACV,OAAM,aAAa,MAAM,QAAQ,kBAAkB;IAClD,QAAQ;IACR,MAAM;KACL,WAAW,MAAM;KACjB,YAAY;KACZ;IACD,CAAC;AAGH,UAAO,YAAY,OAAO;AAC1B,SAAM,SAAS;AACf,SAAM,SAAS,OAAO;;;;;AAOtB,SAAM,SAAS;GAEf,MAAM,gBAAgB,MAAM,aAC3B,MAAM,QACN,yBAAyB,OAAO,YAChC;AAKD,OAHgB,WAAW,YAAY,KACvB,WAAW,cAAc,WAAW,GAAG,EAE9B;AACxB,UAAM,aAAa,MAAM,QAAQ,kBAAkB;KAClD,QAAQ;KACR,MAAM;MACL,WAAW,OAAO;MAClB,aAAa;MACb,KAAK,MAAM,cAAc;MACzB;KACD,CAAC;AAEF,UAAM,SAAS;SAEf,OAAM,SAAS;AAGhB,SAAM,SAAS;;;;;AAOf,SAAM,SAAS;AAEf,SAAM,aAAa,MAAM,QAAQ,kBAAkB;IAClD,QAAQ;IACR,MAAM;KACL,WAAW,OAAO;KAElB,OAAO,UAAU,MAAM;KAEvB,aAAa;KACb;IACD,CAAC;AAEF,SAAM,SAAS;AAEf,UAAO,UAAU;AAIjB,UAAO,eAAe,GAFT,MAAM,OAAO,YAAY,QAAQ,QAAQ,GAAG,CAE3B,qBAAqB,QAAQ,UAAU,eAAe,IAAI,cAAc,oBAAoB,OAAO,UAAU;AAE3I,SAAM,QAAQ,IAAI;IACjB,OAAO;IACP,UAAU;IACV,SAAS;IACT,SAAS;IACT,SAAS;KACR,WAAW,QAAQ;KACnB,WAAW,OAAO;KAClB,cAAc,OAAO;KACrB;IACD,OAAO,MAAM,KAAK,OAAO;KACxB,MAAM,EAAE;KACR,QACC,EAAE,WAAW,SACT,YACD,EAAE,WAAW,UACX,YACA;KACN,QAAQ,EAAE;KACV,4BAAW,IAAI,MAAM,EAAC,aAAa;KACnC,EAAE;IACH,CAAC;AAEF,UAAO;WACC,KAAK;GACb,MAAM,UAAU,MAAM,MAAM,MAAM,EAAE,WAAW,UAAU;AAEzD,OAAI,SAAS;AACZ,YAAQ,SAAS;AAEjB,YAAQ,SAAS,eAAe,QAAQ,IAAI,UAAU,OAAO,IAAI;;AAGlE,UAAO,QAAQ,eAAe,QAAQ,IAAI,UAAU,OAAO,IAAI;AAE/D,SAAM,QAAQ,MACb,cACA,gCACA,eAAe,QAAQ,MAAM,MAC7B;IACC,aAAa,MAAM;IACnB,YAAY,SAAS;IACrB,CACD;AAED,UAAO"}
|