nikcli 0.0.6
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/.turbo/turbo-typecheck.log +1 -0
- package/AGENTS.md +27 -0
- package/Dockerfile +18 -0
- package/README.md +15 -0
- package/bin/nikcli +84 -0
- package/config.json +13 -0
- package/docs/tailscale-mobile/01-tailscale-setup.md +94 -0
- package/docs/tailscale-mobile/02-host-setup.md +115 -0
- package/docs/tailscale-mobile/03-phone-and-serve.md +134 -0
- package/docs/tailscale-mobile/README.md +59 -0
- package/examples/README.md +54 -0
- package/package.json +147 -0
- package/parsers-config.ts +253 -0
- package/script/build.ts +179 -0
- package/script/postinstall.mjs +125 -0
- package/script/publish-registries.ts +187 -0
- package/script/publish.ts +100 -0
- package/script/schema.ts +47 -0
- package/script/seed-e2e.ts +50 -0
- package/sequential-prancing-forest.md +373 -0
- package/src/acp/README.md +164 -0
- package/src/acp/agent.ts +1303 -0
- package/src/acp/session.ts +105 -0
- package/src/acp/types.ts +22 -0
- package/src/agent/agent.ts +528 -0
- package/src/agent/generate.txt +32 -0
- package/src/agent/prompt/compaction.txt +14 -0
- package/src/agent/prompt/explore.txt +18 -0
- package/src/agent/prompt/summary.txt +11 -0
- package/src/agent/prompt/title.txt +44 -0
- package/src/auth/index.ts +73 -0
- package/src/bun/index.ts +119 -0
- package/src/bun/registry.ts +54 -0
- package/src/bus/bus-event.ts +43 -0
- package/src/bus/global.ts +10 -0
- package/src/bus/index.ts +105 -0
- package/src/chatbot/handlers.ts +150 -0
- package/src/chatbot/index.ts +132 -0
- package/src/cli/bootstrap.ts +17 -0
- package/src/cli/cmd/acp.ts +69 -0
- package/src/cli/cmd/ads.ts +377 -0
- package/src/cli/cmd/agent.ts +259 -0
- package/src/cli/cmd/auth.ts +400 -0
- package/src/cli/cmd/chatbot.ts +420 -0
- package/src/cli/cmd/cmd.ts +7 -0
- package/src/cli/cmd/companion.ts +81 -0
- package/src/cli/cmd/connectors.ts +593 -0
- package/src/cli/cmd/debug/agent.ts +166 -0
- package/src/cli/cmd/debug/config.ts +16 -0
- package/src/cli/cmd/debug/file.ts +97 -0
- package/src/cli/cmd/debug/index.ts +48 -0
- package/src/cli/cmd/debug/lsp.ts +52 -0
- package/src/cli/cmd/debug/ripgrep.ts +87 -0
- package/src/cli/cmd/debug/scrap.ts +16 -0
- package/src/cli/cmd/debug/skill.ts +16 -0
- package/src/cli/cmd/debug/snapshot.ts +52 -0
- package/src/cli/cmd/export.ts +88 -0
- package/src/cli/cmd/generate.ts +38 -0
- package/src/cli/cmd/github.ts +412 -0
- package/src/cli/cmd/image-model.ts +128 -0
- package/src/cli/cmd/import.ts +201 -0
- package/src/cli/cmd/lovable.ts +128 -0
- package/src/cli/cmd/mcp.ts +738 -0
- package/src/cli/cmd/mobile.ts +223 -0
- package/src/cli/cmd/models.ts +77 -0
- package/src/cli/cmd/plug.ts +231 -0
- package/src/cli/cmd/pr.ts +104 -0
- package/src/cli/cmd/rag-model.ts +167 -0
- package/src/cli/cmd/remote.ts +416 -0
- package/src/cli/cmd/run.ts +589 -0
- package/src/cli/cmd/serve.ts +51 -0
- package/src/cli/cmd/session.ts +133 -0
- package/src/cli/cmd/speak-model.ts +204 -0
- package/src/cli/cmd/stats.ts +402 -0
- package/src/cli/cmd/tui/app.tsx +841 -0
- package/src/cli/cmd/tui/attach.ts +31 -0
- package/src/cli/cmd/tui/component/border.tsx +75 -0
- package/src/cli/cmd/tui/component/dialog-agent.tsx +31 -0
- package/src/cli/cmd/tui/component/dialog-command.tsx +172 -0
- package/src/cli/cmd/tui/component/dialog-config.tsx +291 -0
- package/src/cli/cmd/tui/component/dialog-connectors.tsx +440 -0
- package/src/cli/cmd/tui/component/dialog-image-model.tsx +97 -0
- package/src/cli/cmd/tui/component/dialog-mcp.tsx +86 -0
- package/src/cli/cmd/tui/component/dialog-model.tsx +234 -0
- package/src/cli/cmd/tui/component/dialog-provider.tsx +260 -0
- package/src/cli/cmd/tui/component/dialog-rag-model.tsx +217 -0
- package/src/cli/cmd/tui/component/dialog-remote.tsx +489 -0
- package/src/cli/cmd/tui/component/dialog-session-list.tsx +170 -0
- package/src/cli/cmd/tui/component/dialog-session-rename.tsx +31 -0
- package/src/cli/cmd/tui/component/dialog-settings/index.tsx +59 -0
- package/src/cli/cmd/tui/component/dialog-settings/prompt.tsx +40 -0
- package/src/cli/cmd/tui/component/dialog-settings/sidebar.tsx +39 -0
- package/src/cli/cmd/tui/component/dialog-settings/spinner.tsx +62 -0
- package/src/cli/cmd/tui/component/dialog-settings/ui.tsx +58 -0
- package/src/cli/cmd/tui/component/dialog-skills.tsx +117 -0
- package/src/cli/cmd/tui/component/dialog-speak-model.tsx +304 -0
- package/src/cli/cmd/tui/component/dialog-stash.tsx +87 -0
- package/src/cli/cmd/tui/component/dialog-status.tsx +165 -0
- package/src/cli/cmd/tui/component/dialog-tag.tsx +44 -0
- package/src/cli/cmd/tui/component/dialog-theme-create.tsx +717 -0
- package/src/cli/cmd/tui/component/dialog-theme-list.tsx +52 -0
- package/src/cli/cmd/tui/component/dialog-workspace-list.tsx +350 -0
- package/src/cli/cmd/tui/component/error-component.tsx +91 -0
- package/src/cli/cmd/tui/component/logo.tsx +103 -0
- package/src/cli/cmd/tui/component/plugin-route-missing.tsx +14 -0
- package/src/cli/cmd/tui/component/prompt/autocomplete.tsx +669 -0
- package/src/cli/cmd/tui/component/prompt/frecency.tsx +89 -0
- package/src/cli/cmd/tui/component/prompt/history.tsx +108 -0
- package/src/cli/cmd/tui/component/prompt/index.tsx +2165 -0
- package/src/cli/cmd/tui/component/prompt/stash.tsx +63 -0
- package/src/cli/cmd/tui/component/spinner.tsx +24 -0
- package/src/cli/cmd/tui/component/startup-loading.tsx +63 -0
- package/src/cli/cmd/tui/component/table/markdown-table.tsx +267 -0
- package/src/cli/cmd/tui/component/table-db/db/connections.ts +75 -0
- package/src/cli/cmd/tui/component/table-db/db/db-connection.ts +223 -0
- package/src/cli/cmd/tui/component/table-db/db/db-preview.ts +202 -0
- package/src/cli/cmd/tui/component/table-db/db/factory.ts +77 -0
- package/src/cli/cmd/tui/component/table-db/db/index.ts +9 -0
- package/src/cli/cmd/tui/component/table-db/db/mysql-connection.ts +330 -0
- package/src/cli/cmd/tui/component/table-db/db/postgres-connection.ts +338 -0
- package/src/cli/cmd/tui/component/table-db/db/sqlite-connection.ts +302 -0
- package/src/cli/cmd/tui/component/table-db/db/types.ts +108 -0
- package/src/cli/cmd/tui/component/table-db/table/dbedit-hooks.ts +74 -0
- package/src/cli/cmd/tui/component/table-db/table/index.ts +15 -0
- package/src/cli/cmd/tui/component/table-db/table/table-events.ts +54 -0
- package/src/cli/cmd/tui/component/table-db/table/table-formatters.ts +191 -0
- package/src/cli/cmd/tui/component/table-db/table/table-hooks.ts +105 -0
- package/src/cli/cmd/tui/component/table-db/table/table-keyboard-handler.ts +255 -0
- package/src/cli/cmd/tui/component/table-db/table/table-layout-engine.ts +208 -0
- package/src/cli/cmd/tui/component/table-db/table/table-renderable.ts +486 -0
- package/src/cli/cmd/tui/component/table-db/table/table-selection-manager.ts +136 -0
- package/src/cli/cmd/tui/component/table-db/table/table-state.ts +198 -0
- package/src/cli/cmd/tui/component/table-db/table/types.ts +69 -0
- package/src/cli/cmd/tui/component/table-db/ui/db-visualizer.tsx +71 -0
- package/src/cli/cmd/tui/component/table-db/ui/index.ts +2 -0
- package/src/cli/cmd/tui/component/table-db/ui/table-renderer.ts +607 -0
- package/src/cli/cmd/tui/component/textarea-keybindings.ts +73 -0
- package/src/cli/cmd/tui/component/tips.tsx +195 -0
- package/src/cli/cmd/tui/component/todo-item.tsx +32 -0
- package/src/cli/cmd/tui/context/args.tsx +14 -0
- package/src/cli/cmd/tui/context/directory.ts +13 -0
- package/src/cli/cmd/tui/context/exit.tsx +24 -0
- package/src/cli/cmd/tui/context/helper.tsx +25 -0
- package/src/cli/cmd/tui/context/keybind.tsx +102 -0
- package/src/cli/cmd/tui/context/kv.tsx +52 -0
- package/src/cli/cmd/tui/context/local.tsx +458 -0
- package/src/cli/cmd/tui/context/plugin-keybinds.ts +41 -0
- package/src/cli/cmd/tui/context/prompt.tsx +18 -0
- package/src/cli/cmd/tui/context/route.tsx +54 -0
- package/src/cli/cmd/tui/context/sdk.tsx +128 -0
- package/src/cli/cmd/tui/context/server.tsx +8 -0
- package/src/cli/cmd/tui/context/sync.tsx +510 -0
- package/src/cli/cmd/tui/context/theme/abyss.json +233 -0
- package/src/cli/cmd/tui/context/theme/apple.json +235 -0
- package/src/cli/cmd/tui/context/theme/arctic.json +232 -0
- package/src/cli/cmd/tui/context/theme/aura.json +69 -0
- package/src/cli/cmd/tui/context/theme/ayu.json +80 -0
- package/src/cli/cmd/tui/context/theme/ayuai.json +229 -0
- package/src/cli/cmd/tui/context/theme/blood.json +229 -0
- package/src/cli/cmd/tui/context/theme/carbonfox.json +248 -0
- package/src/cli/cmd/tui/context/theme/catmoe.json +235 -0
- package/src/cli/cmd/tui/context/theme/catppuccin-frappe.json +233 -0
- package/src/cli/cmd/tui/context/theme/catppuccin-latte.json +233 -0
- package/src/cli/cmd/tui/context/theme/catppuccin-macchiato.json +233 -0
- package/src/cli/cmd/tui/context/theme/catppuccin.json +259 -0
- package/src/cli/cmd/tui/context/theme/charcoal.json +230 -0
- package/src/cli/cmd/tui/context/theme/chromatic.json +235 -0
- package/src/cli/cmd/tui/context/theme/cobalt2.json +228 -0
- package/src/cli/cmd/tui/context/theme/cosmic.json +234 -0
- package/src/cli/cmd/tui/context/theme/cursor.json +249 -0
- package/src/cli/cmd/tui/context/theme/cyber.json +235 -0
- package/src/cli/cmd/tui/context/theme/dawnfox.json +229 -0
- package/src/cli/cmd/tui/context/theme/dimension.json +235 -0
- package/src/cli/cmd/tui/context/theme/dracula-official.json +222 -0
- package/src/cli/cmd/tui/context/theme/dracula.json +219 -0
- package/src/cli/cmd/tui/context/theme/dream.json +235 -0
- package/src/cli/cmd/tui/context/theme/duo.json +235 -0
- package/src/cli/cmd/tui/context/theme/dusk.json +235 -0
- package/src/cli/cmd/tui/context/theme/ebony.json +232 -0
- package/src/cli/cmd/tui/context/theme/equilibrium.json +232 -0
- package/src/cli/cmd/tui/context/theme/ethereal.json +235 -0
- package/src/cli/cmd/tui/context/theme/everforest.json +241 -0
- package/src/cli/cmd/tui/context/theme/flexoki.json +237 -0
- package/src/cli/cmd/tui/context/theme/fusion.json +235 -0
- package/src/cli/cmd/tui/context/theme/ghost.json +235 -0
- package/src/cli/cmd/tui/context/theme/github-dark.json +229 -0
- package/src/cli/cmd/tui/context/theme/github-dimmed.json +231 -0
- package/src/cli/cmd/tui/context/theme/github-light.json +229 -0
- package/src/cli/cmd/tui/context/theme/github.json +233 -0
- package/src/cli/cmd/tui/context/theme/glass.json +235 -0
- package/src/cli/cmd/tui/context/theme/gold.json +235 -0
- package/src/cli/cmd/tui/context/theme/gone.json +234 -0
- package/src/cli/cmd/tui/context/theme/greyscale.json +229 -0
- package/src/cli/cmd/tui/context/theme/gruvbox.json +242 -0
- package/src/cli/cmd/tui/context/theme/hacker.json +229 -0
- package/src/cli/cmd/tui/context/theme/holo.json +235 -0
- package/src/cli/cmd/tui/context/theme/ink.json +235 -0
- package/src/cli/cmd/tui/context/theme/jet.json +233 -0
- package/src/cli/cmd/tui/context/theme/kanagawa.json +227 -0
- package/src/cli/cmd/tui/context/theme/lavender.json +236 -0
- package/src/cli/cmd/tui/context/theme/lightph.json +235 -0
- package/src/cli/cmd/tui/context/theme/lucent-orng.json +237 -0
- package/src/cli/cmd/tui/context/theme/material-ocean.json +230 -0
- package/src/cli/cmd/tui/context/theme/material.json +235 -0
- package/src/cli/cmd/tui/context/theme/matrix.json +227 -0
- package/src/cli/cmd/tui/context/theme/mercury.json +245 -0
- package/src/cli/cmd/tui/context/theme/midnight.json +235 -0
- package/src/cli/cmd/tui/context/theme/modern.json +235 -0
- package/src/cli/cmd/tui/context/theme/monokai.json +221 -0
- package/src/cli/cmd/tui/context/theme/muted.json +229 -0
- package/src/cli/cmd/tui/context/theme/neon.json +229 -0
- package/src/cli/cmd/tui/context/theme/neonfusion.json +235 -0
- package/src/cli/cmd/tui/context/theme/neutral.json +235 -0
- package/src/cli/cmd/tui/context/theme/nightowl.json +221 -0
- package/src/cli/cmd/tui/context/theme/nikcli.json +245 -0
- package/src/cli/cmd/tui/context/theme/nord.json +223 -0
- package/src/cli/cmd/tui/context/theme/nordic.json +235 -0
- package/src/cli/cmd/tui/context/theme/nova.json +235 -0
- package/src/cli/cmd/tui/context/theme/obsidian.json +234 -0
- package/src/cli/cmd/tui/context/theme/one-dark.json +231 -0
- package/src/cli/cmd/tui/context/theme/one-pro.json +229 -0
- package/src/cli/cmd/tui/context/theme/onyx.json +233 -0
- package/src/cli/cmd/tui/context/theme/orng.json +249 -0
- package/src/cli/cmd/tui/context/theme/osaka-jade.json +240 -0
- package/src/cli/cmd/tui/context/theme/oxocarbon.json +229 -0
- package/src/cli/cmd/tui/context/theme/palenight.json +222 -0
- package/src/cli/cmd/tui/context/theme/poimandres.json +230 -0
- package/src/cli/cmd/tui/context/theme/prism.json +235 -0
- package/src/cli/cmd/tui/context/theme/radiant.json +235 -0
- package/src/cli/cmd/tui/context/theme/rosepine.json +234 -0
- package/src/cli/cmd/tui/context/theme/shadow.json +235 -0
- package/src/cli/cmd/tui/context/theme/silicon.json +235 -0
- package/src/cli/cmd/tui/context/theme/slate.json +233 -0
- package/src/cli/cmd/tui/context/theme/soft.json +235 -0
- package/src/cli/cmd/tui/context/theme/solarized.json +223 -0
- package/src/cli/cmd/tui/context/theme/spectrum.json +235 -0
- package/src/cli/cmd/tui/context/theme/starlight.json +233 -0
- package/src/cli/cmd/tui/context/theme/sunrise.json +235 -0
- package/src/cli/cmd/tui/context/theme/synthwave84.json +226 -0
- package/src/cli/cmd/tui/context/theme/tech.json +235 -0
- package/src/cli/cmd/tui/context/theme/tokyonight-storm.json +245 -0
- package/src/cli/cmd/tui/context/theme/tokyonight.json +243 -0
- package/src/cli/cmd/tui/context/theme/vapor.json +235 -0
- package/src/cli/cmd/tui/context/theme/vercel.json +245 -0
- package/src/cli/cmd/tui/context/theme/vesper.json +218 -0
- package/src/cli/cmd/tui/context/theme/vivid.json +232 -0
- package/src/cli/cmd/tui/context/theme/void.json +235 -0
- package/src/cli/cmd/tui/context/theme/vscode.json +235 -0
- package/src/cli/cmd/tui/context/theme/zenburn.json +223 -0
- package/src/cli/cmd/tui/context/theme/zinc.json +236 -0
- package/src/cli/cmd/tui/context/theme.tsx +1303 -0
- package/src/cli/cmd/tui/event.ts +48 -0
- package/src/cli/cmd/tui/feature-plugins/home/tips-view.tsx +152 -0
- package/src/cli/cmd/tui/feature-plugins/home/tips.tsx +50 -0
- package/src/cli/cmd/tui/feature-plugins/sidebar/context.tsx +63 -0
- package/src/cli/cmd/tui/feature-plugins/sidebar/files.tsx +62 -0
- package/src/cli/cmd/tui/feature-plugins/sidebar/footer.tsx +93 -0
- package/src/cli/cmd/tui/feature-plugins/sidebar/lsp.tsx +66 -0
- package/src/cli/cmd/tui/feature-plugins/sidebar/mcp.tsx +96 -0
- package/src/cli/cmd/tui/feature-plugins/sidebar/todo.tsx +48 -0
- package/src/cli/cmd/tui/feature-plugins/system/plugins.tsx +288 -0
- package/src/cli/cmd/tui/plugin/api.tsx +407 -0
- package/src/cli/cmd/tui/plugin/index.ts +3 -0
- package/src/cli/cmd/tui/plugin/internal.ts +25 -0
- package/src/cli/cmd/tui/plugin/runtime.ts +1048 -0
- package/src/cli/cmd/tui/plugin/slots.tsx +61 -0
- package/src/cli/cmd/tui/routes/home.tsx +153 -0
- package/src/cli/cmd/tui/routes/session/dbedit.tsx +474 -0
- package/src/cli/cmd/tui/routes/session/dialog-fork-from-timeline.tsx +65 -0
- package/src/cli/cmd/tui/routes/session/dialog-message.tsx +110 -0
- package/src/cli/cmd/tui/routes/session/dialog-subagent.tsx +105 -0
- package/src/cli/cmd/tui/routes/session/dialog-timeline.tsx +47 -0
- package/src/cli/cmd/tui/routes/session/footer.tsx +75 -0
- package/src/cli/cmd/tui/routes/session/header.tsx +177 -0
- package/src/cli/cmd/tui/routes/session/index.tsx +2280 -0
- package/src/cli/cmd/tui/routes/session/permission.tsx +540 -0
- package/src/cli/cmd/tui/routes/session/question.tsx +435 -0
- package/src/cli/cmd/tui/routes/session/sidebar.tsx +313 -0
- package/src/cli/cmd/tui/thread.ts +174 -0
- package/src/cli/cmd/tui/ui/dialog-alert.tsx +57 -0
- package/src/cli/cmd/tui/ui/dialog-confirm.tsx +83 -0
- package/src/cli/cmd/tui/ui/dialog-export-options.tsx +204 -0
- package/src/cli/cmd/tui/ui/dialog-help.tsx +38 -0
- package/src/cli/cmd/tui/ui/dialog-prompt.tsx +102 -0
- package/src/cli/cmd/tui/ui/dialog-select.tsx +389 -0
- package/src/cli/cmd/tui/ui/dialog.tsx +180 -0
- package/src/cli/cmd/tui/ui/link.tsx +34 -0
- package/src/cli/cmd/tui/ui/spinner.ts +368 -0
- package/src/cli/cmd/tui/ui/toast.tsx +138 -0
- package/src/cli/cmd/tui/util/clipboard.ts +154 -0
- package/src/cli/cmd/tui/util/editor.ts +32 -0
- package/src/cli/cmd/tui/util/signal.ts +7 -0
- package/src/cli/cmd/tui/util/terminal.ts +114 -0
- package/src/cli/cmd/tui/util/transcript.ts +98 -0
- package/src/cli/cmd/tui/win32.ts +110 -0
- package/src/cli/cmd/tui/worker.ts +156 -0
- package/src/cli/cmd/uninstall.ts +357 -0
- package/src/cli/cmd/upgrade.ts +72 -0
- package/src/cli/cmd/web.ts +87 -0
- package/src/cli/cmd/workspace-serve.ts +16 -0
- package/src/cli/error.ts +57 -0
- package/src/cli/network.ts +55 -0
- package/src/cli/remote/index.ts +36 -0
- package/src/cli/remote/notifications.ts +104 -0
- package/src/cli/remote/qr-renderer.ts +86 -0
- package/src/cli/remote/remote-service.ts +757 -0
- package/src/cli/remote/session-manager.ts +284 -0
- package/src/cli/remote/subagent-hooks.ts +151 -0
- package/src/cli/remote/types.ts +121 -0
- package/src/cli/ui.ts +96 -0
- package/src/cli/upgrade.ts +25 -0
- package/src/command/index.ts +174 -0
- package/src/command/template/initialize.txt +10 -0
- package/src/command/template/review.txt +99 -0
- package/src/config/config.ts +1760 -0
- package/src/config/markdown.ts +88 -0
- package/src/config/migrate-tui-config.ts +155 -0
- package/src/config/paths.ts +174 -0
- package/src/config/tui-schema.ts +36 -0
- package/src/config/tui.ts +209 -0
- package/src/connectors/api/base.ts +75 -0
- package/src/connectors/api/figma.ts +103 -0
- package/src/connectors/api/github.ts +247 -0
- package/src/connectors/api/lovable.ts +126 -0
- package/src/connectors/api/slack.ts +137 -0
- package/src/connectors/auth.ts +68 -0
- package/src/connectors/cache.ts +119 -0
- package/src/connectors/credentials.ts +81 -0
- package/src/connectors/index.ts +202 -0
- package/src/connectors/registry.ts +358 -0
- package/src/docs/context.ts +120 -0
- package/src/docs/library.ts +189 -0
- package/src/env/index.ts +26 -0
- package/src/file/ignore.ts +83 -0
- package/src/file/index.ts +411 -0
- package/src/file/ripgrep.ts +402 -0
- package/src/file/time.ts +65 -0
- package/src/file/watcher.ts +127 -0
- package/src/flag/flag.ts +128 -0
- package/src/format/formatter.ts +356 -0
- package/src/format/index.ts +137 -0
- package/src/global/index.ts +57 -0
- package/src/id/id.ts +83 -0
- package/src/ide/index.ts +76 -0
- package/src/index.ts +184 -0
- package/src/installation/index.ts +246 -0
- package/src/lsp/client.ts +250 -0
- package/src/lsp/index.ts +483 -0
- package/src/lsp/language.ts +119 -0
- package/src/lsp/server.ts +2046 -0
- package/src/mcp/auth.ts +121 -0
- package/src/mcp/index.ts +860 -0
- package/src/mcp/oauth-callback.ts +198 -0
- package/src/mcp/oauth-provider.ts +148 -0
- package/src/mobile/auth.ts +97 -0
- package/src/mobile/github-repo.ts +185 -0
- package/src/patch/index.ts +631 -0
- package/src/permission/arity.ts +150 -0
- package/src/permission/dbedit.ts +236 -0
- package/src/permission/index.ts +210 -0
- package/src/permission/next.ts +287 -0
- package/src/plugin/codex.ts +493 -0
- package/src/plugin/copilot.ts +261 -0
- package/src/plugin/index.ts +714 -0
- package/src/plugin/install.ts +379 -0
- package/src/plugin/meta.ts +165 -0
- package/src/plugin/shared.ts +188 -0
- package/src/project/bootstrap.ts +35 -0
- package/src/project/instance.ts +84 -0
- package/src/project/project.ts +373 -0
- package/src/project/state.ts +66 -0
- package/src/project/vcs.ts +76 -0
- package/src/prompt/stash-store.ts +93 -0
- package/src/provider/auth.ts +147 -0
- package/src/provider/models-macro.ts +22 -0
- package/src/provider/models.ts +216 -0
- package/src/provider/provider.ts +1483 -0
- package/src/provider/sdk/openai-compatible/src/README.md +5 -0
- package/src/provider/sdk/openai-compatible/src/index.ts +2 -0
- package/src/provider/sdk/openai-compatible/src/openai-compatible-provider.ts +100 -0
- package/src/provider/sdk/openai-compatible/src/responses/convert-to-openai-responses-input.ts +303 -0
- package/src/provider/sdk/openai-compatible/src/responses/map-openai-responses-finish-reason.ts +22 -0
- package/src/provider/sdk/openai-compatible/src/responses/openai-config.ts +18 -0
- package/src/provider/sdk/openai-compatible/src/responses/openai-error.ts +22 -0
- package/src/provider/sdk/openai-compatible/src/responses/openai-responses-api-types.ts +207 -0
- package/src/provider/sdk/openai-compatible/src/responses/openai-responses-language-model.ts +1732 -0
- package/src/provider/sdk/openai-compatible/src/responses/openai-responses-prepare-tools.ts +177 -0
- package/src/provider/sdk/openai-compatible/src/responses/openai-responses-settings.ts +1 -0
- package/src/provider/sdk/openai-compatible/src/responses/tool/code-interpreter.ts +88 -0
- package/src/provider/sdk/openai-compatible/src/responses/tool/file-search.ts +128 -0
- package/src/provider/sdk/openai-compatible/src/responses/tool/image-generation.ts +115 -0
- package/src/provider/sdk/openai-compatible/src/responses/tool/local-shell.ts +65 -0
- package/src/provider/sdk/openai-compatible/src/responses/tool/web-search-preview.ts +104 -0
- package/src/provider/sdk/openai-compatible/src/responses/tool/web-search.ts +103 -0
- package/src/provider/transform.ts +828 -0
- package/src/pty/index.ts +241 -0
- package/src/question/index.ts +171 -0
- package/src/rag/chunk.ts +43 -0
- package/src/rag/embed.ts +179 -0
- package/src/rag/index.ts +376 -0
- package/src/rag/storage.ts +76 -0
- package/src/scheduler/index.ts +61 -0
- package/src/server/error.ts +36 -0
- package/src/server/event.ts +7 -0
- package/src/server/mdns.ts +59 -0
- package/src/server/routes/chatbot.ts +205 -0
- package/src/server/routes/companion.ts +729 -0
- package/src/server/routes/config.ts +92 -0
- package/src/server/routes/connectors.ts +121 -0
- package/src/server/routes/dbedit.ts +76 -0
- package/src/server/routes/experimental.ts +210 -0
- package/src/server/routes/file.ts +197 -0
- package/src/server/routes/global.ts +135 -0
- package/src/server/routes/mcp.ts +225 -0
- package/src/server/routes/mobile.ts +2044 -0
- package/src/server/routes/permission.ts +68 -0
- package/src/server/routes/project.ts +82 -0
- package/src/server/routes/provider.ts +235 -0
- package/src/server/routes/pty.ts +169 -0
- package/src/server/routes/question.ts +98 -0
- package/src/server/routes/session.ts +968 -0
- package/src/server/routes/tui.ts +379 -0
- package/src/server/routes/workspace.ts +104 -0
- package/src/server/server.ts +761 -0
- package/src/server/ssh.ts +207 -0
- package/src/session/auth.ts +402 -0
- package/src/session/compaction.ts +253 -0
- package/src/session/generate.ts +38 -0
- package/src/session/index.ts +598 -0
- package/src/session/llm.ts +273 -0
- package/src/session/message-v2.ts +836 -0
- package/src/session/message.ts +189 -0
- package/src/session/processor.ts +408 -0
- package/src/session/prompt/anthropic-20250930.txt +165 -0
- package/src/session/prompt/anthropic.txt +105 -0
- package/src/session/prompt/anthropic_spoof.txt +1 -0
- package/src/session/prompt/beast.txt +147 -0
- package/src/session/prompt/build-switch.txt +5 -0
- package/src/session/prompt/codex_header.txt +79 -0
- package/src/session/prompt/copilot-gpt-5.txt +143 -0
- package/src/session/prompt/gemini.txt +155 -0
- package/src/session/prompt/max-steps.txt +16 -0
- package/src/session/prompt/plan-reminder-anthropic.txt +67 -0
- package/src/session/prompt/plan.txt +25 -0
- package/src/session/prompt/qwen.txt +108 -0
- package/src/session/prompt.ts +1942 -0
- package/src/session/retry.ts +90 -0
- package/src/session/revert.ts +120 -0
- package/src/session/stats.ts +404 -0
- package/src/session/status.ts +84 -0
- package/src/session/summary.ts +184 -0
- package/src/session/system.ts +195 -0
- package/src/session/toast.tsx +105 -0
- package/src/session/todo.ts +258 -0
- package/src/session/uninstall.ts +357 -0
- package/src/share/share-next.ts +421 -0
- package/src/share/share.ts +92 -0
- package/src/shell/shell.ts +65 -0
- package/src/skill/index.ts +1 -0
- package/src/skill/skill.ts +232 -0
- package/src/snapshot/index.ts +297 -0
- package/src/storage/storage.ts +227 -0
- package/src/tool/apply_patch.ts +288 -0
- package/src/tool/apply_patch.txt +33 -0
- package/src/tool/bash.ts +252 -0
- package/src/tool/bash.txt +115 -0
- package/src/tool/batch.ts +175 -0
- package/src/tool/batch.txt +24 -0
- package/src/tool/codesearch.ts +132 -0
- package/src/tool/codesearch.txt +12 -0
- package/src/tool/context_collect.ts +152 -0
- package/src/tool/context_collect.txt +9 -0
- package/src/tool/context_diagnostics.ts +81 -0
- package/src/tool/context_diagnostics.txt +5 -0
- package/src/tool/context_related.ts +117 -0
- package/src/tool/context_related.txt +5 -0
- package/src/tool/context_search.ts +108 -0
- package/src/tool/context_search.txt +8 -0
- package/src/tool/db-diff.ts +434 -0
- package/src/tool/db-table.txt +15 -0
- package/src/tool/docs_add.ts +50 -0
- package/src/tool/docs_add.txt +5 -0
- package/src/tool/docs_context.ts +56 -0
- package/src/tool/docs_context.txt +4 -0
- package/src/tool/docs_gap_report.ts +79 -0
- package/src/tool/docs_gap_report.txt +7 -0
- package/src/tool/docs_load.ts +41 -0
- package/src/tool/docs_load.txt +4 -0
- package/src/tool/docs_request.ts +129 -0
- package/src/tool/docs_request.txt +7 -0
- package/src/tool/docs_search.ts +51 -0
- package/src/tool/docs_search.txt +6 -0
- package/src/tool/docs_unload.ts +38 -0
- package/src/tool/docs_unload.txt +5 -0
- package/src/tool/edit.ts +614 -0
- package/src/tool/edit.txt +10 -0
- package/src/tool/external-directory.ts +32 -0
- package/src/tool/generate_image.ts +174 -0
- package/src/tool/generate_image.txt +12 -0
- package/src/tool/glob.ts +79 -0
- package/src/tool/glob.txt +6 -0
- package/src/tool/grep.ts +153 -0
- package/src/tool/grep.txt +8 -0
- package/src/tool/invalid.ts +17 -0
- package/src/tool/ls.ts +116 -0
- package/src/tool/ls.txt +1 -0
- package/src/tool/lsp.ts +96 -0
- package/src/tool/lsp.txt +19 -0
- package/src/tool/memory_search.ts +141 -0
- package/src/tool/memory_search.txt +8 -0
- package/src/tool/multiedit.ts +46 -0
- package/src/tool/multiedit.txt +41 -0
- package/src/tool/plan-enter.txt +14 -0
- package/src/tool/plan-exit.txt +13 -0
- package/src/tool/plan.ts +130 -0
- package/src/tool/question.ts +33 -0
- package/src/tool/question.txt +10 -0
- package/src/tool/rag_index.ts +77 -0
- package/src/tool/rag_index.txt +10 -0
- package/src/tool/rag_reset.ts +26 -0
- package/src/tool/rag_reset.txt +4 -0
- package/src/tool/rag_search.ts +62 -0
- package/src/tool/rag_search.txt +6 -0
- package/src/tool/rag_status.ts +45 -0
- package/src/tool/rag_status.txt +4 -0
- package/src/tool/read.ts +203 -0
- package/src/tool/read.txt +12 -0
- package/src/tool/registry.ts +214 -0
- package/src/tool/skill.ts +169 -0
- package/src/tool/skill.txt +3 -0
- package/src/tool/smart_docs.ts +74 -0
- package/src/tool/smart_docs.txt +7 -0
- package/src/tool/speak/elevenlabs.ts +201 -0
- package/src/tool/speak/openrouter.ts +240 -0
- package/src/tool/speak/provider.ts +83 -0
- package/src/tool/speak.ts +440 -0
- package/src/tool/task.ts +194 -0
- package/src/tool/task.txt +60 -0
- package/src/tool/todo.ts +53 -0
- package/src/tool/todoread.txt +14 -0
- package/src/tool/todowrite.txt +167 -0
- package/src/tool/tool.ts +87 -0
- package/src/tool/tree.ts +218 -0
- package/src/tool/tree.txt +8 -0
- package/src/tool/truncation.ts +106 -0
- package/src/tool/use-connector.ts +47 -0
- package/src/tool/voice.ts +188 -0
- package/src/tool/webfetch.ts +205 -0
- package/src/tool/webfetch.txt +13 -0
- package/src/tool/websearch.ts +150 -0
- package/src/tool/websearch.txt +14 -0
- package/src/tool/write.ts +80 -0
- package/src/tool/write.txt +8 -0
- package/src/util/archive.ts +16 -0
- package/src/util/color.ts +19 -0
- package/src/util/context.ts +25 -0
- package/src/util/defer.ts +12 -0
- package/src/util/error.ts +77 -0
- package/src/util/eventloop.ts +20 -0
- package/src/util/filesystem.ts +125 -0
- package/src/util/flock.ts +329 -0
- package/src/util/fn.ts +11 -0
- package/src/util/format.ts +20 -0
- package/src/util/hash.ts +7 -0
- package/src/util/iife.ts +3 -0
- package/src/util/keybind.ts +103 -0
- package/src/util/lazy.ts +18 -0
- package/src/util/locale.ts +81 -0
- package/src/util/lock.ts +98 -0
- package/src/util/log.ts +180 -0
- package/src/util/network.ts +9 -0
- package/src/util/process.ts +15 -0
- package/src/util/queue.ts +32 -0
- package/src/util/record.ts +3 -0
- package/src/util/rpc.ts +66 -0
- package/src/util/scrap.ts +10 -0
- package/src/util/signal.ts +12 -0
- package/src/util/timeout.ts +14 -0
- package/src/util/token.ts +7 -0
- package/src/util/wildcard.ts +56 -0
- package/src/workspace/adaptors/index.ts +271 -0
- package/src/workspace/adaptors/types.ts +14 -0
- package/src/workspace/adaptors/worktree.ts +31 -0
- package/src/workspace/config.ts +19 -0
- package/src/workspace/index.ts +223 -0
- package/src/workspace/session-proxy-middleware.ts +97 -0
- package/src/workspace/sse.ts +66 -0
- package/src/workspace/workspace-context.ts +23 -0
- package/src/workspace/workspace-server/routes.ts +33 -0
- package/src/workspace/workspace-server/server.ts +47 -0
- package/src/worktree/index.ts +487 -0
- package/sst-env.d.ts +10 -0
- package/test/benchmark.test.ts +121 -0
- package/test/build-optimizations.test.ts +124 -0
- package/test/id-benchmark.test.ts +132 -0
- package/test/optimizations.test.ts +302 -0
- package/test/preload.ts +1 -0
- package/test/solidjs-benchmark.test.ts +262 -0
- package/test/solidjs-optimizations.test.ts +259 -0
- package/test/tui-benchmark.test.ts +230 -0
- package/test/wildcard-benchmark.test.ts +180 -0
- package/tsconfig.json +26 -0
|
@@ -0,0 +1,330 @@
|
|
|
1
|
+
import type { DBSchema, DBTable, DBColumn, DBForeignKey, DBIndex, TablePreview, QueryResult } from "./types"
|
|
2
|
+
import type { IDBConnection, ConnectionConfig } from "./connections"
|
|
3
|
+
|
|
4
|
+
export class MySQLConnection implements IDBConnection {
|
|
5
|
+
readonly type = "mysql"
|
|
6
|
+
private _config: ConnectionConfig
|
|
7
|
+
private _connection: any = null
|
|
8
|
+
|
|
9
|
+
constructor(config: ConnectionConfig) {
|
|
10
|
+
this._config = config
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
get connected(): boolean {
|
|
14
|
+
return this._connection !== null
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
private async _getConnection(): Promise<any> {
|
|
18
|
+
if (!this._connection) {
|
|
19
|
+
const mysql = await import("mysql2/promise")
|
|
20
|
+
this._connection = await mysql.default.createConnection({
|
|
21
|
+
host: this._config.host,
|
|
22
|
+
port: this._config.port || 3306,
|
|
23
|
+
database: this._config.database,
|
|
24
|
+
user: this._config.username,
|
|
25
|
+
password: this._config.password,
|
|
26
|
+
})
|
|
27
|
+
}
|
|
28
|
+
return this._connection
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
async getSchema(): Promise<DBSchema> {
|
|
32
|
+
const conn = await this._getConnection()
|
|
33
|
+
const tables = await this._getMySQLTables(conn)
|
|
34
|
+
const views = await this._getMySQLViews(conn)
|
|
35
|
+
const indexes = await this._getMySQLIndexes(conn)
|
|
36
|
+
return { tables, views, indexes }
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
private async _getMySQLTables(conn: any): Promise<DBTable[]> {
|
|
40
|
+
const [rows] = await conn.query(`
|
|
41
|
+
SELECT table_name
|
|
42
|
+
FROM information_schema.tables
|
|
43
|
+
WHERE table_schema = DATABASE() AND table_type = 'BASE TABLE'
|
|
44
|
+
ORDER BY table_name
|
|
45
|
+
`)
|
|
46
|
+
|
|
47
|
+
const tables: DBTable[] = []
|
|
48
|
+
for (const row of rows as any[]) {
|
|
49
|
+
const tableName = row.TABLE_NAME
|
|
50
|
+
const columns = await this._getMySQLTableInfo(conn, tableName)
|
|
51
|
+
const rowCount = await this._getMySQLRowCount(conn, tableName)
|
|
52
|
+
const foreignKeys = await this._getMySQLForeignKeys(conn, tableName)
|
|
53
|
+
|
|
54
|
+
tables.push({
|
|
55
|
+
name: tableName,
|
|
56
|
+
columns,
|
|
57
|
+
primaryKey: columns.filter((c) => c.primaryKey).map((c) => c.name),
|
|
58
|
+
foreignKeys,
|
|
59
|
+
rowCount,
|
|
60
|
+
})
|
|
61
|
+
}
|
|
62
|
+
return tables
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
private async _getMySQLTableInfo(conn: any, tableName: string): Promise<DBColumn[]> {
|
|
66
|
+
const [rows] = await conn.query(
|
|
67
|
+
`
|
|
68
|
+
SELECT column_name, data_type, is_nullable, column_default, extra
|
|
69
|
+
FROM information_schema.columns
|
|
70
|
+
WHERE table_schema = DATABASE() AND table_name = ?
|
|
71
|
+
ORDER BY ordinal_position
|
|
72
|
+
`,
|
|
73
|
+
[tableName],
|
|
74
|
+
)
|
|
75
|
+
|
|
76
|
+
const pkResult = await conn.query(
|
|
77
|
+
`
|
|
78
|
+
SELECT column_name
|
|
79
|
+
FROM information_schema.key_column_usage
|
|
80
|
+
WHERE table_schema = DATABASE() AND table_name = ? AND constraint_name = 'PRIMARY'
|
|
81
|
+
`,
|
|
82
|
+
[tableName],
|
|
83
|
+
)
|
|
84
|
+
|
|
85
|
+
const pkColumns = new Set((pkResult[0] as any[]).map((r: any) => r.column_name))
|
|
86
|
+
|
|
87
|
+
return (rows as any[]).map((col: any) => ({
|
|
88
|
+
name: col.COLUMN_NAME,
|
|
89
|
+
type: col.DATA_TYPE.toUpperCase(),
|
|
90
|
+
notNull: col.IS_NULLABLE === "NO",
|
|
91
|
+
defaultValue: col.COLUMN_DEFAULT || undefined,
|
|
92
|
+
primaryKey: pkColumns.has(col.COLUMN_NAME),
|
|
93
|
+
}))
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
private async _getMySQLRowCount(conn: any, tableName: string): Promise<number> {
|
|
97
|
+
try {
|
|
98
|
+
const [rows] = await conn.query(`SELECT COUNT(*) as count FROM ${tableName}`)
|
|
99
|
+
return (rows as any[])[0]?.count || 0
|
|
100
|
+
} catch {
|
|
101
|
+
return 0
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
private async _getMySQLForeignKeys(conn: any, tableName: string): Promise<DBForeignKey[]> {
|
|
106
|
+
const [rows] = await conn.query(
|
|
107
|
+
`
|
|
108
|
+
SELECT
|
|
109
|
+
column_name,
|
|
110
|
+
referenced_table_name,
|
|
111
|
+
referenced_column_name,
|
|
112
|
+
delete_rule
|
|
113
|
+
FROM information_schema.key_column_usage
|
|
114
|
+
WHERE table_schema = DATABASE()
|
|
115
|
+
AND table_name = ?
|
|
116
|
+
AND referenced_table_name IS NOT NULL
|
|
117
|
+
`,
|
|
118
|
+
[tableName],
|
|
119
|
+
)
|
|
120
|
+
|
|
121
|
+
return (rows as any[]).map((row: any) => ({
|
|
122
|
+
table: tableName,
|
|
123
|
+
column: row.COLUMN_NAME,
|
|
124
|
+
referencedTable: row.REFERENCED_TABLE_NAME,
|
|
125
|
+
referencedColumn: row.REFERENCED_COLUMN_NAME,
|
|
126
|
+
onDelete: this._mapMySQLOnDelete(row.DELETE_RULE),
|
|
127
|
+
}))
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
private _mapMySQLOnDelete(rule: string): "CASCADE" | "RESTRICT" | "SET NULL" | "NO ACTION" {
|
|
131
|
+
switch (rule) {
|
|
132
|
+
case "CASCADE":
|
|
133
|
+
return "CASCADE"
|
|
134
|
+
case "RESTRICT":
|
|
135
|
+
return "RESTRICT"
|
|
136
|
+
case "SET NULL":
|
|
137
|
+
return "SET NULL"
|
|
138
|
+
default:
|
|
139
|
+
return "NO ACTION"
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
private async _getMySQLViews(conn: any): Promise<Array<{ name: string; sql: string }>> {
|
|
144
|
+
const [rows] = await conn.query(`
|
|
145
|
+
SELECT table_name AS name, view_definition
|
|
146
|
+
FROM information_schema.views
|
|
147
|
+
WHERE table_schema = DATABASE()
|
|
148
|
+
ORDER BY table_name
|
|
149
|
+
`)
|
|
150
|
+
|
|
151
|
+
return (rows as any[]).map((row: any) => ({
|
|
152
|
+
name: row.name,
|
|
153
|
+
sql: row.view_definition || "",
|
|
154
|
+
}))
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
private async _getMySQLIndexes(conn: any): Promise<DBIndex[]> {
|
|
158
|
+
const [rows] = await conn.query(`
|
|
159
|
+
SELECT index_name, table_name, non_unique, index_columns
|
|
160
|
+
FROM information_schema.statistics
|
|
161
|
+
WHERE table_schema = DATABASE()
|
|
162
|
+
ORDER BY table_name, index_name
|
|
163
|
+
`)
|
|
164
|
+
|
|
165
|
+
const indexMap = new Map<string, DBIndex>()
|
|
166
|
+
for (const row of rows as any[]) {
|
|
167
|
+
const key = `${row.TABLE_NAME}_${row.INDEX_NAME}`
|
|
168
|
+
if (!indexMap.has(key)) {
|
|
169
|
+
indexMap.set(key, {
|
|
170
|
+
name: row.INDEX_NAME,
|
|
171
|
+
tableName: row.TABLE_NAME,
|
|
172
|
+
columns: [],
|
|
173
|
+
unique: row.NON_UNIQUE === 0,
|
|
174
|
+
})
|
|
175
|
+
}
|
|
176
|
+
indexMap.get(key)!.columns.push(row.COLUMN_NAME)
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
return Array.from(indexMap.values())
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
async getTablePreview(tableName: string, limit: number = 10): Promise<TablePreview> {
|
|
183
|
+
const conn = await this._getConnection()
|
|
184
|
+
const schema = await this.getSchema()
|
|
185
|
+
const table = schema.tables.find((t) => t.name === tableName)
|
|
186
|
+
|
|
187
|
+
if (!table) {
|
|
188
|
+
return { tableName, columns: [], sampleData: [], rowCount: 0 }
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
const [rows] = await conn.query(`SELECT * FROM ${tableName} LIMIT ?`, [limit])
|
|
192
|
+
|
|
193
|
+
return {
|
|
194
|
+
tableName,
|
|
195
|
+
columns: table.columns,
|
|
196
|
+
sampleData: rows as any[],
|
|
197
|
+
rowCount: table.rowCount ?? 0,
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
async executeQuery(sql: string): Promise<QueryResult> {
|
|
202
|
+
const conn = await this._getConnection()
|
|
203
|
+
const startTime = Date.now()
|
|
204
|
+
|
|
205
|
+
try {
|
|
206
|
+
const isSelect = sql.trim().toUpperCase().startsWith("SELECT")
|
|
207
|
+
|
|
208
|
+
if (isSelect) {
|
|
209
|
+
const [rows, fields] = await conn.query(sql)
|
|
210
|
+
const columns = fields ? fields.map((f: any) => f.name) : []
|
|
211
|
+
|
|
212
|
+
return {
|
|
213
|
+
columns,
|
|
214
|
+
rows: rows as any[],
|
|
215
|
+
rowCount: Array.isArray(rows) ? rows.length : 0,
|
|
216
|
+
executionTime: Date.now() - startTime,
|
|
217
|
+
}
|
|
218
|
+
} else {
|
|
219
|
+
const [result] = await conn.query(sql)
|
|
220
|
+
return {
|
|
221
|
+
columns: ["affected_rows"],
|
|
222
|
+
rows: [{ affected_rows: (result as any).affectedRows || 0 }],
|
|
223
|
+
rowCount: 1,
|
|
224
|
+
executionTime: Date.now() - startTime,
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
} catch (error) {
|
|
228
|
+
throw new Error(`Query failed: ${error}`)
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
async executeCommand(sql: string): Promise<void> {
|
|
233
|
+
const conn = await this._getConnection()
|
|
234
|
+
await conn.query(sql)
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
async createTable(name: string, columns: DBColumn[], foreignKeys?: DBForeignKey[]): Promise<void> {
|
|
238
|
+
const columnDefs = columns.map((col) => {
|
|
239
|
+
let def = `${col.name} ${col.type}`
|
|
240
|
+
if (col.notNull) def += " NOT NULL"
|
|
241
|
+
if (col.defaultValue) def += ` DEFAULT ${col.defaultValue}`
|
|
242
|
+
return def
|
|
243
|
+
})
|
|
244
|
+
|
|
245
|
+
const fkDefs =
|
|
246
|
+
foreignKeys?.map(
|
|
247
|
+
(fk) =>
|
|
248
|
+
`FOREIGN KEY (${fk.column}) REFERENCES ${fk.referencedTable}(${fk.referencedColumn}) ON DELETE ${fk.onDelete}`,
|
|
249
|
+
) || []
|
|
250
|
+
|
|
251
|
+
const pkColumns = columns.filter((c) => c.primaryKey).map((c) => c.name)
|
|
252
|
+
const pkDef = pkColumns.length > 0 ? `, PRIMARY KEY (${pkColumns.join(", ")})` : ""
|
|
253
|
+
|
|
254
|
+
const sql = `CREATE TABLE ${name} (${columnDefs.concat(fkDefs).join(", ")}${pkDef})`
|
|
255
|
+
await this.executeCommand(sql)
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
async dropTable(name: string): Promise<void> {
|
|
259
|
+
await this.executeCommand(`DROP TABLE IF EXISTS ${name}`)
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
async addColumn(tableName: string, column: DBColumn): Promise<void> {
|
|
263
|
+
let sql = `ALTER TABLE ${tableName} ADD COLUMN ${column.name} ${column.type}`
|
|
264
|
+
if (column.notNull) sql += " NOT NULL"
|
|
265
|
+
if (column.defaultValue) sql += ` DEFAULT ${column.defaultValue}`
|
|
266
|
+
await this.executeCommand(sql)
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
async dropColumn(tableName: string, columnName: string): Promise<void> {
|
|
270
|
+
await this.executeCommand(`ALTER TABLE ${tableName} DROP COLUMN ${columnName}`)
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
async modifyColumn(tableName: string, columnName: string, newDef: DBColumn): Promise<void> {
|
|
274
|
+
await this.executeCommand(`ALTER TABLE ${tableName} CHANGE ${columnName} ${newDef.name} ${newDef.type}`)
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
async getIndexes(): Promise<DBIndex[]> {
|
|
278
|
+
return this._getMySQLIndexes(await this._getConnection())
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
async createIndex(name: string, tableName: string, columns: string[], unique: boolean = false): Promise<void> {
|
|
282
|
+
const uniqueStr = unique ? " UNIQUE" : ""
|
|
283
|
+
const cols = columns.join(", ")
|
|
284
|
+
await this.executeCommand(`CREATE${uniqueStr} INDEX ${name} ON ${tableName} (${cols})`)
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
async dropIndex(name: string): Promise<void> {
|
|
288
|
+
await this.executeCommand(`DROP INDEX IF EXISTS ${name}`)
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
async beginTransaction(): Promise<void> {
|
|
292
|
+
const conn = await this._getConnection()
|
|
293
|
+
await conn.beginTransaction()
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
async commit(): Promise<void> {
|
|
297
|
+
const conn = await this._getConnection()
|
|
298
|
+
await conn.commit()
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
async rollback(): Promise<void> {
|
|
302
|
+
const conn = await this._getConnection()
|
|
303
|
+
await conn.rollback()
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
async close(): Promise<void> {
|
|
307
|
+
if (this._connection) {
|
|
308
|
+
await this._connection.end()
|
|
309
|
+
this._connection = null
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
static async testConnection(config: ConnectionConfig): Promise<boolean> {
|
|
314
|
+
try {
|
|
315
|
+
const mysql = await import("mysql2/promise")
|
|
316
|
+
const conn = await mysql.default.createConnection({
|
|
317
|
+
host: config.host,
|
|
318
|
+
port: config.port || 3306,
|
|
319
|
+
database: config.database,
|
|
320
|
+
user: config.username,
|
|
321
|
+
password: config.password,
|
|
322
|
+
})
|
|
323
|
+
await conn.query("SELECT 1")
|
|
324
|
+
await conn.end()
|
|
325
|
+
return true
|
|
326
|
+
} catch {
|
|
327
|
+
return false
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
}
|
|
@@ -0,0 +1,338 @@
|
|
|
1
|
+
import type { DBSchema, DBTable, DBColumn, DBForeignKey, DBIndex, TablePreview, QueryResult } from "./types"
|
|
2
|
+
import type { IDBConnection, ConnectionConfig } from "./connections"
|
|
3
|
+
|
|
4
|
+
export class PostgresConnection implements IDBConnection {
|
|
5
|
+
readonly type = "postgres"
|
|
6
|
+
private _config: ConnectionConfig
|
|
7
|
+
private _pool: any = null
|
|
8
|
+
|
|
9
|
+
constructor(config: ConnectionConfig) {
|
|
10
|
+
this._config = config
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
get connected(): boolean {
|
|
14
|
+
return this._pool !== null
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
private async _getPool(): Promise<any> {
|
|
18
|
+
if (!this._pool) {
|
|
19
|
+
const { default: pg } = await import("pg")
|
|
20
|
+
const { Pool } = pg
|
|
21
|
+
this._pool = new Pool({
|
|
22
|
+
host: this._config.host,
|
|
23
|
+
port: this._config.port || 5432,
|
|
24
|
+
database: this._config.database,
|
|
25
|
+
user: this._config.username,
|
|
26
|
+
password: this._config.password,
|
|
27
|
+
})
|
|
28
|
+
}
|
|
29
|
+
return this._pool
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
async getSchema(): Promise<DBSchema> {
|
|
33
|
+
const pool = await this._getPool()
|
|
34
|
+
const tables = await this._getPgTables(pool)
|
|
35
|
+
const views = await this._getPgViews(pool)
|
|
36
|
+
const indexes = await this._getPgIndexes(pool)
|
|
37
|
+
return { tables, views, indexes }
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
private async _getPgTables(pool: any): Promise<DBTable[]> {
|
|
41
|
+
const result = await pool.query(`
|
|
42
|
+
SELECT table_name, table_schema
|
|
43
|
+
FROM information_schema.tables
|
|
44
|
+
WHERE table_schema = 'public' AND table_type = 'BASE TABLE'
|
|
45
|
+
ORDER BY table_name
|
|
46
|
+
`)
|
|
47
|
+
|
|
48
|
+
const tables: DBTable[] = []
|
|
49
|
+
for (const row of result.rows) {
|
|
50
|
+
const tableName = row.table_name
|
|
51
|
+
const columns = await this._getPgTableInfo(pool, tableName)
|
|
52
|
+
const rowCount = await this._getPgRowCount(pool, tableName)
|
|
53
|
+
const foreignKeys = await this._getPgForeignKeys(pool, tableName)
|
|
54
|
+
|
|
55
|
+
tables.push({
|
|
56
|
+
name: tableName,
|
|
57
|
+
columns,
|
|
58
|
+
primaryKey: columns.filter((c) => c.primaryKey).map((c) => c.name),
|
|
59
|
+
foreignKeys,
|
|
60
|
+
rowCount,
|
|
61
|
+
})
|
|
62
|
+
}
|
|
63
|
+
return tables
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
private async _getPgTableInfo(pool: any, tableName: string): Promise<DBColumn[]> {
|
|
67
|
+
const result = await pool.query(
|
|
68
|
+
`
|
|
69
|
+
SELECT column_name, data_type, is_nullable, column_default, is_identity
|
|
70
|
+
FROM information_schema.columns
|
|
71
|
+
WHERE table_name = $1
|
|
72
|
+
ORDER BY ordinal_position
|
|
73
|
+
`,
|
|
74
|
+
[tableName],
|
|
75
|
+
)
|
|
76
|
+
|
|
77
|
+
const pkResult = await pool.query(
|
|
78
|
+
`
|
|
79
|
+
SELECT a.attname as column_name
|
|
80
|
+
FROM pg_index i
|
|
81
|
+
JOIN pg_attribute a ON a.attrelid = i.indrelid AND a.attnum = ANY(i.indkey)
|
|
82
|
+
WHERE i.indrelid = $1::regclass AND i.indisprimary
|
|
83
|
+
`,
|
|
84
|
+
[tableName],
|
|
85
|
+
)
|
|
86
|
+
|
|
87
|
+
const pkColumns = new Set(pkResult.rows.map((r: any) => r.column_name))
|
|
88
|
+
|
|
89
|
+
return result.rows.map((col: any) => ({
|
|
90
|
+
name: col.column_name,
|
|
91
|
+
type: col.data_type.toUpperCase(),
|
|
92
|
+
notNull: col.is_nullable === "NO",
|
|
93
|
+
defaultValue: col.column_default || undefined,
|
|
94
|
+
primaryKey: pkColumns.has(col.column_name),
|
|
95
|
+
}))
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
private async _getPgRowCount(pool: any, tableName: string): Promise<number> {
|
|
99
|
+
try {
|
|
100
|
+
const result = await pool.query(`SELECT COUNT(*) as count FROM ${tableName}`)
|
|
101
|
+
return parseInt(result.rows[0].count) || 0
|
|
102
|
+
} catch {
|
|
103
|
+
return 0
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
private async _getPgForeignKeys(pool: any, tableName: string): Promise<DBForeignKey[]> {
|
|
108
|
+
const result = await pool.query(
|
|
109
|
+
`
|
|
110
|
+
SELECT
|
|
111
|
+
kcu.column_name,
|
|
112
|
+
ccu.table_name AS referenced_table,
|
|
113
|
+
kcu.column_name AS referenced_column,
|
|
114
|
+
rc.delete_rule AS on_delete
|
|
115
|
+
FROM information_schema.table_constraints AS tc
|
|
116
|
+
JOIN information_schema.key_column_usage AS kcu
|
|
117
|
+
ON tc.constraint_name = kcu.constraint_name
|
|
118
|
+
AND tc.table_schema = kcu.table_schema
|
|
119
|
+
JOIN information_schema.constraint_column_usage AS ccu
|
|
120
|
+
ON ccu.constraint_name = tc.constraint_name
|
|
121
|
+
AND ccu.table_schema = tc.table_schema
|
|
122
|
+
WHERE tc.constraint_type = 'FOREIGN KEY'
|
|
123
|
+
AND tc.table_name = $1
|
|
124
|
+
`,
|
|
125
|
+
[tableName],
|
|
126
|
+
)
|
|
127
|
+
|
|
128
|
+
return result.rows.map((row: any) => ({
|
|
129
|
+
table: tableName,
|
|
130
|
+
column: row.column_name,
|
|
131
|
+
referencedTable: row.referenced_table,
|
|
132
|
+
referencedColumn: row.referenced_column,
|
|
133
|
+
onDelete: this._mapPgOnDelete(row.on_delete),
|
|
134
|
+
}))
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
private _mapPgOnDelete(rule: string): "CASCADE" | "RESTRICT" | "SET NULL" | "NO ACTION" {
|
|
138
|
+
switch (rule) {
|
|
139
|
+
case "CASCADE":
|
|
140
|
+
return "CASCADE"
|
|
141
|
+
case "RESTRICT":
|
|
142
|
+
return "RESTRICT"
|
|
143
|
+
case "SET NULL":
|
|
144
|
+
return "SET NULL"
|
|
145
|
+
default:
|
|
146
|
+
return "NO ACTION"
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
private async _getPgViews(pool: any): Promise<Array<{ name: string; sql: string }>> {
|
|
151
|
+
const result = await pool.query(`
|
|
152
|
+
SELECT table_name AS name, view_definition
|
|
153
|
+
FROM information_schema.views
|
|
154
|
+
WHERE table_schema = 'public'
|
|
155
|
+
ORDER BY table_name
|
|
156
|
+
`)
|
|
157
|
+
|
|
158
|
+
return result.rows.map((row: any) => ({
|
|
159
|
+
name: row.name,
|
|
160
|
+
sql: row.view_definition || "",
|
|
161
|
+
}))
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
private async _getPgIndexes(pool: any): Promise<DBIndex[]> {
|
|
165
|
+
const result = await pool.query(`
|
|
166
|
+
SELECT indexname, tablename, indexdef
|
|
167
|
+
FROM pg_indexes
|
|
168
|
+
WHERE schemaname = 'public'
|
|
169
|
+
ORDER BY tablename, indexname
|
|
170
|
+
`)
|
|
171
|
+
|
|
172
|
+
return result.rows.map((row: any) => {
|
|
173
|
+
const columns = this._extractPgIndexColumns(row.indexdef)
|
|
174
|
+
return {
|
|
175
|
+
name: row.indexname,
|
|
176
|
+
tableName: row.tablename,
|
|
177
|
+
columns,
|
|
178
|
+
unique: row.indexdef.toUpperCase().includes("UNIQUE"),
|
|
179
|
+
}
|
|
180
|
+
})
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
private _extractPgIndexColumns(indexDef: string): string[] {
|
|
184
|
+
const match = indexDef.match(/\(([^)]+)\)/)
|
|
185
|
+
if (!match) return []
|
|
186
|
+
return match[1].split(",").map((c) => c.trim())
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
async getTablePreview(tableName: string, limit: number = 10): Promise<TablePreview> {
|
|
190
|
+
const pool = await this._getPool()
|
|
191
|
+
const schema = await this.getSchema()
|
|
192
|
+
const table = schema.tables.find((t) => t.name === tableName)
|
|
193
|
+
|
|
194
|
+
if (!table) {
|
|
195
|
+
return { tableName, columns: [], sampleData: [], rowCount: 0 }
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
const result = await pool.query(`SELECT * FROM ${tableName} LIMIT $1`, [limit])
|
|
199
|
+
|
|
200
|
+
return {
|
|
201
|
+
tableName,
|
|
202
|
+
columns: table.columns,
|
|
203
|
+
sampleData: result.rows as any[],
|
|
204
|
+
rowCount: table.rowCount ?? 0,
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
async executeQuery(sql: string): Promise<QueryResult> {
|
|
209
|
+
const pool = await this._getPool()
|
|
210
|
+
const startTime = Date.now()
|
|
211
|
+
|
|
212
|
+
try {
|
|
213
|
+
const isSelect = sql.trim().toUpperCase().startsWith("SELECT")
|
|
214
|
+
|
|
215
|
+
if (isSelect) {
|
|
216
|
+
const result = await pool.query(sql)
|
|
217
|
+
const columns = result.fields.map((f: any) => f.name)
|
|
218
|
+
|
|
219
|
+
return {
|
|
220
|
+
columns,
|
|
221
|
+
rows: result.rows as any[],
|
|
222
|
+
rowCount: result.rowCount || 0,
|
|
223
|
+
executionTime: Date.now() - startTime,
|
|
224
|
+
}
|
|
225
|
+
} else {
|
|
226
|
+
const result = await pool.query(sql)
|
|
227
|
+
return {
|
|
228
|
+
columns: ["affected_rows"],
|
|
229
|
+
rows: [{ affected_rows: result.rowCount || 0 }],
|
|
230
|
+
rowCount: 1,
|
|
231
|
+
executionTime: Date.now() - startTime,
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
} catch (error) {
|
|
235
|
+
throw new Error(`Query failed: ${error}`)
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
async executeCommand(sql: string): Promise<void> {
|
|
240
|
+
const pool = await this._getPool()
|
|
241
|
+
await pool.query(sql)
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
async createTable(name: string, columns: DBColumn[], foreignKeys?: DBForeignKey[]): Promise<void> {
|
|
245
|
+
const columnDefs = columns.map((col) => {
|
|
246
|
+
let def = `${col.name} ${col.type}`
|
|
247
|
+
if (col.notNull) def += " NOT NULL"
|
|
248
|
+
if (col.defaultValue) def += ` DEFAULT ${col.defaultValue}`
|
|
249
|
+
return def
|
|
250
|
+
})
|
|
251
|
+
|
|
252
|
+
const fkDefs =
|
|
253
|
+
foreignKeys?.map(
|
|
254
|
+
(fk) =>
|
|
255
|
+
`FOREIGN KEY (${fk.column}) REFERENCES ${fk.referencedTable}(${fk.referencedColumn}) ON DELETE ${fk.onDelete}`,
|
|
256
|
+
) || []
|
|
257
|
+
|
|
258
|
+
const pkColumns = columns.filter((c) => c.primaryKey).map((c) => c.name)
|
|
259
|
+
const pkDef = pkColumns.length > 0 ? `, PRIMARY KEY (${pkColumns.join(", ")})` : ""
|
|
260
|
+
|
|
261
|
+
const sql = `CREATE TABLE ${name} (${columnDefs.concat(fkDefs).join(", ")}${pkDef})`
|
|
262
|
+
await this.executeCommand(sql)
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
async dropTable(name: string): Promise<void> {
|
|
266
|
+
await this.executeCommand(`DROP TABLE IF EXISTS ${name}`)
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
async addColumn(tableName: string, column: DBColumn): Promise<void> {
|
|
270
|
+
let sql = `ALTER TABLE ${tableName} ADD COLUMN ${column.name} ${column.type}`
|
|
271
|
+
if (column.notNull) sql += " NOT NULL"
|
|
272
|
+
if (column.defaultValue) sql += ` DEFAULT ${column.defaultValue}`
|
|
273
|
+
await this.executeCommand(sql)
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
async dropColumn(tableName: string, columnName: string): Promise<void> {
|
|
277
|
+
await this.executeCommand(`ALTER TABLE ${tableName} DROP COLUMN ${columnName}`)
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
async modifyColumn(tableName: string, columnName: string, newDef: DBColumn): Promise<void> {
|
|
281
|
+
await this.executeCommand(`ALTER TABLE ${tableName} RENAME COLUMN ${columnName} TO ${newDef.name}`)
|
|
282
|
+
if (newDef.type !== "TEXT") {
|
|
283
|
+
await this.executeCommand(`ALTER TABLE ${tableName} ALTER COLUMN ${newDef.name} TYPE ${newDef.type}`)
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
async getIndexes(): Promise<DBIndex[]> {
|
|
288
|
+
return this._getPgIndexes(await this._getPool())
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
async createIndex(name: string, tableName: string, columns: string[], unique: boolean = false): Promise<void> {
|
|
292
|
+
const uniqueStr = unique ? " UNIQUE" : ""
|
|
293
|
+
const cols = columns.join(", ")
|
|
294
|
+
await this.executeCommand(`CREATE${uniqueStr} INDEX IF NOT EXISTS ${name} ON ${tableName} (${cols})`)
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
async dropIndex(name: string): Promise<void> {
|
|
298
|
+
await this.executeCommand(`DROP INDEX IF EXISTS ${name}`)
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
async beginTransaction(): Promise<void> {
|
|
302
|
+
await this.executeCommand("BEGIN")
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
async commit(): Promise<void> {
|
|
306
|
+
await this.executeCommand("COMMIT")
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
async rollback(): Promise<void> {
|
|
310
|
+
await this.executeCommand("ROLLBACK")
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
async close(): Promise<void> {
|
|
314
|
+
if (this._pool) {
|
|
315
|
+
await this._pool.end()
|
|
316
|
+
this._pool = null
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
static async testConnection(config: ConnectionConfig): Promise<boolean> {
|
|
321
|
+
try {
|
|
322
|
+
const { default: pg } = await import("pg")
|
|
323
|
+
const { Pool } = pg
|
|
324
|
+
const pool = new Pool({
|
|
325
|
+
host: config.host,
|
|
326
|
+
port: config.port || 5432,
|
|
327
|
+
database: config.database,
|
|
328
|
+
user: config.username,
|
|
329
|
+
password: config.password,
|
|
330
|
+
})
|
|
331
|
+
await pool.query("SELECT 1")
|
|
332
|
+
await pool.end()
|
|
333
|
+
return true
|
|
334
|
+
} catch {
|
|
335
|
+
return false
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
}
|