sqlit-tui 1.0.2__tar.gz → 1.1__tar.gz
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.
- {sqlit_tui-1.0.2 → sqlit_tui-1.1}/.github/workflows/release.yml +34 -33
- {sqlit_tui-1.0.2 → sqlit_tui-1.1}/PKG-INFO +102 -7
- {sqlit_tui-1.0.2 → sqlit_tui-1.1}/README.md +91 -0
- sqlit_tui-1.1/demo-d1.gif +0 -0
- sqlit_tui-1.1/demos/d1-demo.json +185 -0
- sqlit_tui-1.1/demos/demo-docker-picker.gif +0 -0
- sqlit_tui-1.1/demos/demo-filter/demo-filter.gif +0 -0
- {sqlit_tui-1.0.2 → sqlit_tui-1.1}/pyproject.toml +17 -8
- {sqlit_tui-1.0.2 → sqlit_tui-1.1}/settings.template.json +1 -0
- {sqlit_tui-1.0.2 → sqlit_tui-1.1}/sqlit/app.py +107 -20
- {sqlit_tui-1.0.2 → sqlit_tui-1.1}/sqlit/cli.py +106 -2
- {sqlit_tui-1.0.2 → sqlit_tui-1.1}/sqlit/cli_helpers.py +1 -0
- {sqlit_tui-1.0.2 → sqlit_tui-1.1}/sqlit/commands.py +37 -1
- {sqlit_tui-1.0.2 → sqlit_tui-1.1}/sqlit/config.py +54 -0
- {sqlit_tui-1.0.2 → sqlit_tui-1.1}/sqlit/db/adapters/base.py +415 -0
- {sqlit_tui-1.0.2 → sqlit_tui-1.1}/sqlit/db/adapters/cockroachdb.py +5 -0
- {sqlit_tui-1.0.2 → sqlit_tui-1.1}/sqlit/db/adapters/d1.py +73 -1
- {sqlit_tui-1.0.2 → sqlit_tui-1.1}/sqlit/db/adapters/duckdb.py +87 -1
- sqlit_tui-1.1/sqlit/db/adapters/mariadb.py +343 -0
- {sqlit_tui-1.0.2 → sqlit_tui-1.1}/sqlit/db/adapters/mssql.py +190 -1
- sqlit_tui-1.1/sqlit/db/adapters/oracle.py +298 -0
- {sqlit_tui-1.0.2 → sqlit_tui-1.1}/sqlit/db/adapters/sqlite.py +109 -1
- {sqlit_tui-1.0.2 → sqlit_tui-1.1}/sqlit/db/adapters/turso.py +33 -1
- {sqlit_tui-1.0.2 → sqlit_tui-1.1}/sqlit/db/schema.py +15 -0
- {sqlit_tui-1.0.2 → sqlit_tui-1.1}/sqlit/mock_settings.py +86 -7
- {sqlit_tui-1.0.2 → sqlit_tui-1.1}/sqlit/mocks.py +211 -1
- sqlit_tui-1.1/sqlit/omarchy.py +92 -0
- {sqlit_tui-1.0.2 → sqlit_tui-1.1}/sqlit/services/__init__.py +15 -0
- {sqlit_tui-1.0.2 → sqlit_tui-1.1}/sqlit/services/cancellable.py +17 -8
- sqlit_tui-1.1/sqlit/services/docker_detector.py +489 -0
- {sqlit_tui-1.0.2 → sqlit_tui-1.1}/sqlit/services/query.py +37 -0
- {sqlit_tui-1.0.2 → sqlit_tui-1.1}/sqlit/state_machine.py +121 -12
- {sqlit_tui-1.0.2 → sqlit_tui-1.1}/sqlit/stores/__init__.py +2 -0
- {sqlit_tui-1.0.2 → sqlit_tui-1.1}/sqlit/stores/history.py +2 -0
- sqlit_tui-1.1/sqlit/stores/starred.py +162 -0
- {sqlit_tui-1.0.2 → sqlit_tui-1.1}/sqlit/ui/mixins/__init__.py +2 -0
- {sqlit_tui-1.0.2 → sqlit_tui-1.1}/sqlit/ui/mixins/connection.py +163 -20
- {sqlit_tui-1.0.2 → sqlit_tui-1.1}/sqlit/ui/mixins/protocols.py +3 -2
- {sqlit_tui-1.0.2 → sqlit_tui-1.1}/sqlit/ui/mixins/query.py +120 -30
- {sqlit_tui-1.0.2 → sqlit_tui-1.1}/sqlit/ui/mixins/results.py +3 -4
- sqlit_tui-1.1/sqlit/ui/mixins/results_filter.py +359 -0
- {sqlit_tui-1.0.2 → sqlit_tui-1.1}/sqlit/ui/mixins/tree.py +235 -34
- {sqlit_tui-1.0.2 → sqlit_tui-1.1}/sqlit/ui/mixins/tree_filter.py +14 -3
- {sqlit_tui-1.0.2 → sqlit_tui-1.1}/sqlit/ui/mixins/ui_navigation.py +28 -6
- {sqlit_tui-1.0.2 → sqlit_tui-1.1}/sqlit/ui/protocols.py +18 -2
- {sqlit_tui-1.0.2 → sqlit_tui-1.1}/sqlit/ui/screens/connection.py +27 -11
- sqlit_tui-1.1/sqlit/ui/screens/connection_picker.py +575 -0
- {sqlit_tui-1.0.2 → sqlit_tui-1.1}/sqlit/ui/screens/help.py +2 -2
- sqlit_tui-1.1/sqlit/ui/screens/query_history.py +238 -0
- {sqlit_tui-1.0.2 → sqlit_tui-1.1}/sqlit/ui/tree_nodes.py +31 -2
- sqlit_tui-1.1/sqlit/url_parser.py +179 -0
- {sqlit_tui-1.0.2 → sqlit_tui-1.1}/sqlit/widgets.py +71 -6
- {sqlit_tui-1.0.2 → sqlit_tui-1.1}/tests/conftest.py +180 -0
- sqlit_tui-1.1/tests/integration/docker_detect/__init__.py +1 -0
- sqlit_tui-1.1/tests/integration/docker_detect/conftest.py +25 -0
- sqlit_tui-1.1/tests/integration/docker_detect/test_all_databases.py +521 -0
- sqlit_tui-1.1/tests/integration/docker_detect/test_docker_detection.py +245 -0
- sqlit_tui-1.1/tests/performance/__init__.py +1 -0
- sqlit_tui-1.1/tests/performance/test_large_dataset_rendering.py +311 -0
- {sqlit_tui-1.0.2 → sqlit_tui-1.1}/tests/test_database_base.py +131 -0
- sqlit_tui-1.1/tests/test_docker_detector.py +439 -0
- {sqlit_tui-1.0.2 → sqlit_tui-1.1}/tests/test_oracle.py +77 -0
- sqlit_tui-1.1/tests/ui/test_connect_action.py +344 -0
- sqlit_tui-1.1/tests/unit/__init__.py +0 -0
- sqlit_tui-1.1/tests/unit/test_docker_credential_parsing.py +402 -0
- sqlit_tui-1.1/tests/unit/test_oracle_adapter.py +130 -0
- sqlit_tui-1.1/tests/unit/test_starred.py +141 -0
- sqlit_tui-1.1/uv.lock +3369 -0
- sqlit_tui-1.1//342/224/202 +0 -0
- sqlit_tui-1.0.2/sqlit/db/adapters/mariadb.py +0 -143
- sqlit_tui-1.0.2/sqlit/db/adapters/oracle.py +0 -149
- sqlit_tui-1.0.2/sqlit/ui/screens/connection_picker.py +0 -161
- sqlit_tui-1.0.2/sqlit/ui/screens/query_history.py +0 -170
- sqlit_tui-1.0.2/tests/ui/test_connect_action.py +0 -85
- sqlit_tui-1.0.2/uv.lock +0 -1014
- {sqlit_tui-1.0.2 → sqlit_tui-1.1}/.github/workflows/ci.yml +0 -0
- {sqlit_tui-1.0.2 → sqlit_tui-1.1}/.gitignore +0 -0
- {sqlit_tui-1.0.2 → sqlit_tui-1.1}/.pre-commit-config.yaml +0 -0
- {sqlit_tui-1.0.2 → sqlit_tui-1.1}/.sqlit-config/settings.json +0 -0
- {sqlit_tui-1.0.2 → sqlit_tui-1.1}/CONTRIBUTING.md +0 -0
- {sqlit_tui-1.0.2 → sqlit_tui-1.1}/LICENSE +0 -0
- {sqlit_tui-1.0.2 → sqlit_tui-1.1}/aur/.SRCINFO +0 -0
- {sqlit_tui-1.0.2 → sqlit_tui-1.1}/aur/PKGBUILD +0 -0
- {sqlit_tui-1.0.2 → sqlit_tui-1.1}/demos/demo-connect.gif +0 -0
- {sqlit_tui-1.0.2 → sqlit_tui-1.1}/demos/demo-history.gif +0 -0
- {sqlit_tui-1.0.2 → sqlit_tui-1.1}/demos/demo-providers.gif +0 -0
- {sqlit_tui-1.0.2 → sqlit_tui-1.1}/demos/demo-query.gif +0 -0
- {sqlit_tui-1.0.2 → sqlit_tui-1.1}/demos/demo-sqlite.gif +0 -0
- {sqlit_tui-1.0.2 → sqlit_tui-1.1}/docker-compose.test.yml +0 -0
- {sqlit_tui-1.0.2 → sqlit_tui-1.1}/mock-ssh-missing.json +0 -0
- {sqlit_tui-1.0.2 → sqlit_tui-1.1}/mypy-errors.txt +0 -0
- {sqlit_tui-1.0.2 → sqlit_tui-1.1}/mypy-summary.md +0 -0
- {sqlit_tui-1.0.2 → sqlit_tui-1.1}/pyrightconfig.json +0 -0
- {sqlit_tui-1.0.2 → sqlit_tui-1.1}/sqlit/__init__.py +0 -0
- {sqlit_tui-1.0.2 → sqlit_tui-1.1}/sqlit/db/__init__.py +0 -0
- {sqlit_tui-1.0.2 → sqlit_tui-1.1}/sqlit/db/adapters/__init__.py +0 -0
- {sqlit_tui-1.0.2 → sqlit_tui-1.1}/sqlit/db/adapters/mysql.py +0 -0
- {sqlit_tui-1.0.2 → sqlit_tui-1.1}/sqlit/db/adapters/postgresql.py +0 -0
- {sqlit_tui-1.0.2 → sqlit_tui-1.1}/sqlit/db/adapters/supabase.py +0 -0
- {sqlit_tui-1.0.2 → sqlit_tui-1.1}/sqlit/db/exceptions.py +0 -0
- {sqlit_tui-1.0.2 → sqlit_tui-1.1}/sqlit/db/providers.py +0 -0
- {sqlit_tui-1.0.2 → sqlit_tui-1.1}/sqlit/db/tunnel.py +0 -0
- {sqlit_tui-1.0.2 → sqlit_tui-1.1}/sqlit/drivers.py +0 -0
- {sqlit_tui-1.0.2 → sqlit_tui-1.1}/sqlit/fields.py +0 -0
- {sqlit_tui-1.0.2 → sqlit_tui-1.1}/sqlit/install_strategy.py +0 -0
- {sqlit_tui-1.0.2 → sqlit_tui-1.1}/sqlit/keymap.py +0 -0
- {sqlit_tui-1.0.2 → sqlit_tui-1.1}/sqlit/services/credentials.py +0 -0
- {sqlit_tui-1.0.2 → sqlit_tui-1.1}/sqlit/services/executor.py +0 -0
- {sqlit_tui-1.0.2 → sqlit_tui-1.1}/sqlit/services/installer.py +0 -0
- {sqlit_tui-1.0.2 → sqlit_tui-1.1}/sqlit/services/protocols.py +0 -0
- {sqlit_tui-1.0.2 → sqlit_tui-1.1}/sqlit/services/session.py +0 -0
- {sqlit_tui-1.0.2 → sqlit_tui-1.1}/sqlit/stores/base.py +0 -0
- {sqlit_tui-1.0.2 → sqlit_tui-1.1}/sqlit/stores/connections.py +0 -0
- {sqlit_tui-1.0.2 → sqlit_tui-1.1}/sqlit/stores/settings.py +0 -0
- {sqlit_tui-1.0.2 → sqlit_tui-1.1}/sqlit/terminal.py +0 -0
- {sqlit_tui-1.0.2 → sqlit_tui-1.1}/sqlit/ui/__init__.py +0 -0
- {sqlit_tui-1.0.2 → sqlit_tui-1.1}/sqlit/ui/mixins/autocomplete.py +0 -0
- {sqlit_tui-1.0.2 → sqlit_tui-1.1}/sqlit/ui/screens/__init__.py +0 -0
- {sqlit_tui-1.0.2 → sqlit_tui-1.1}/sqlit/ui/screens/confirm.py +0 -0
- {sqlit_tui-1.0.2 → sqlit_tui-1.1}/sqlit/ui/screens/driver_setup.py +0 -0
- {sqlit_tui-1.0.2 → sqlit_tui-1.1}/sqlit/ui/screens/error.py +0 -0
- {sqlit_tui-1.0.2 → sqlit_tui-1.1}/sqlit/ui/screens/leader_menu.py +0 -0
- {sqlit_tui-1.0.2 → sqlit_tui-1.1}/sqlit/ui/screens/loading.py +0 -0
- {sqlit_tui-1.0.2 → sqlit_tui-1.1}/sqlit/ui/screens/message.py +0 -0
- {sqlit_tui-1.0.2 → sqlit_tui-1.1}/sqlit/ui/screens/package_setup.py +0 -0
- {sqlit_tui-1.0.2 → sqlit_tui-1.1}/sqlit/ui/screens/password_input.py +0 -0
- {sqlit_tui-1.0.2 → sqlit_tui-1.1}/sqlit/ui/screens/theme.py +0 -0
- {sqlit_tui-1.0.2 → sqlit_tui-1.1}/sqlit/ui/screens/value_view.py +0 -0
- {sqlit_tui-1.0.2 → sqlit_tui-1.1}/sqlit/utils.py +0 -0
- {sqlit_tui-1.0.2 → sqlit_tui-1.1}/sqlit/validation.py +0 -0
- {sqlit_tui-1.0.2 → sqlit_tui-1.1}/tests/__init__.py +0 -0
- {sqlit_tui-1.0.2 → sqlit_tui-1.1}/tests/fixtures/99-fix-sshd-config.sh +0 -0
- {sqlit_tui-1.0.2 → sqlit_tui-1.1}/tests/fixtures/d1/Dockerfile +0 -0
- {sqlit_tui-1.0.2 → sqlit_tui-1.1}/tests/fixtures/d1/index.js +0 -0
- {sqlit_tui-1.0.2 → sqlit_tui-1.1}/tests/fixtures/d1/wrangler.toml +0 -0
- {sqlit_tui-1.0.2 → sqlit_tui-1.1}/tests/fixtures/sshd_config +0 -0
- {sqlit_tui-1.0.2 → sqlit_tui-1.1}/tests/integration/drivers/README.md +0 -0
- {sqlit_tui-1.0.2 → sqlit_tui-1.1}/tests/integration/drivers/artifacts/.gitkeep +0 -0
- {sqlit_tui-1.0.2 → sqlit_tui-1.1}/tests/integration/drivers/artifacts/mssql-01-connection.png +0 -0
- {sqlit_tui-1.0.2 → sqlit_tui-1.1}/tests/integration/drivers/artifacts/mssql-01-connection.svg +0 -0
- {sqlit_tui-1.0.2 → sqlit_tui-1.1}/tests/integration/drivers/artifacts/mssql-02-advanced.png +0 -0
- {sqlit_tui-1.0.2 → sqlit_tui-1.1}/tests/integration/drivers/artifacts/mssql-02-advanced.svg +0 -0
- {sqlit_tui-1.0.2 → sqlit_tui-1.1}/tests/integration/drivers/artifacts/mssql-03-driver-setup-empty.png +0 -0
- {sqlit_tui-1.0.2 → sqlit_tui-1.1}/tests/integration/drivers/artifacts/mssql-03-driver-setup-empty.svg +0 -0
- {sqlit_tui-1.0.2 → sqlit_tui-1.1}/tests/integration/drivers/artifacts/mssql-04-install-message.png +0 -0
- {sqlit_tui-1.0.2 → sqlit_tui-1.1}/tests/integration/drivers/artifacts/mssql-04-install-message.svg +0 -0
- {sqlit_tui-1.0.2 → sqlit_tui-1.1}/tests/integration/drivers/artifacts/mssql-05-back-to-connection.png +0 -0
- {sqlit_tui-1.0.2 → sqlit_tui-1.1}/tests/integration/drivers/artifacts/mssql-05-back-to-connection.svg +0 -0
- {sqlit_tui-1.0.2 → sqlit_tui-1.1}/tests/integration/drivers/artifacts/mssql-05-back-to-setup.svg +0 -0
- {sqlit_tui-1.0.2 → sqlit_tui-1.1}/tests/integration/drivers/artifacts/mssql-06-back-to-connection.svg +0 -0
- {sqlit_tui-1.0.2 → sqlit_tui-1.1}/tests/integration/drivers/artifacts/mssql-06-driver-setup-installed.png +0 -0
- {sqlit_tui-1.0.2 → sqlit_tui-1.1}/tests/integration/drivers/artifacts/mssql-06-driver-setup-installed.svg +0 -0
- {sqlit_tui-1.0.2 → sqlit_tui-1.1}/tests/integration/drivers/artifacts/mssql-07-driver-selected.png +0 -0
- {sqlit_tui-1.0.2 → sqlit_tui-1.1}/tests/integration/drivers/artifacts/mssql-07-driver-selected.svg +0 -0
- {sqlit_tui-1.0.2 → sqlit_tui-1.1}/tests/integration/drivers/artifacts/terminal-found/mssql-01-advanced.png +0 -0
- {sqlit_tui-1.0.2 → sqlit_tui-1.1}/tests/integration/drivers/artifacts/terminal-found/mssql-01-advanced.svg +0 -0
- {sqlit_tui-1.0.2 → sqlit_tui-1.1}/tests/integration/drivers/artifacts/terminal-found/mssql-02-driver-setup-empty.png +0 -0
- {sqlit_tui-1.0.2 → sqlit_tui-1.1}/tests/integration/drivers/artifacts/terminal-found/mssql-02-driver-setup-empty.svg +0 -0
- {sqlit_tui-1.0.2 → sqlit_tui-1.1}/tests/integration/drivers/artifacts/terminal-found/mssql-03-install-message-terminal-found.png +0 -0
- {sqlit_tui-1.0.2 → sqlit_tui-1.1}/tests/integration/drivers/artifacts/terminal-found/mssql-03-install-message-terminal-found.svg +0 -0
- {sqlit_tui-1.0.2 → sqlit_tui-1.1}/tests/integration/drivers/artifacts/terminal-found/mssql-04-back-to-connection.png +0 -0
- {sqlit_tui-1.0.2 → sqlit_tui-1.1}/tests/integration/drivers/artifacts/terminal-found/mssql-04-back-to-connection.svg +0 -0
- {sqlit_tui-1.0.2 → sqlit_tui-1.1}/tests/integration/drivers/artifacts/terminal-found/mssql-06-driver-setup-installed.png +0 -0
- {sqlit_tui-1.0.2 → sqlit_tui-1.1}/tests/integration/drivers/artifacts/terminal-found/mssql-06-driver-setup-installed.svg +0 -0
- {sqlit_tui-1.0.2 → sqlit_tui-1.1}/tests/integration/drivers/artifacts/terminal-found/mssql-07-driver-selected.png +0 -0
- {sqlit_tui-1.0.2 → sqlit_tui-1.1}/tests/integration/drivers/artifacts/terminal-found/mssql-07-driver-selected.svg +0 -0
- {sqlit_tui-1.0.2 → sqlit_tui-1.1}/tests/integration/drivers/artifacts/terminal-found/mssql-07-driver-setup-installed.png +0 -0
- {sqlit_tui-1.0.2 → sqlit_tui-1.1}/tests/integration/drivers/artifacts/terminal-found/mssql-07-driver-setup-installed.svg +0 -0
- {sqlit_tui-1.0.2 → sqlit_tui-1.1}/tests/integration/drivers/artifacts/terminal-found/mssql-08-driver-selected.png +0 -0
- {sqlit_tui-1.0.2 → sqlit_tui-1.1}/tests/integration/drivers/artifacts/terminal-found/mssql-08-driver-selected.svg +0 -0
- {sqlit_tui-1.0.2 → sqlit_tui-1.1}/tests/integration/drivers/docker-compose.ui.yml +0 -0
- {sqlit_tui-1.0.2 → sqlit_tui-1.1}/tests/integration/drivers/dockerfiles/alpine.Dockerfile +0 -0
- {sqlit_tui-1.0.2 → sqlit_tui-1.1}/tests/integration/drivers/dockerfiles/arch.Dockerfile +0 -0
- {sqlit_tui-1.0.2 → sqlit_tui-1.1}/tests/integration/drivers/dockerfiles/debian.Dockerfile +0 -0
- {sqlit_tui-1.0.2 → sqlit_tui-1.1}/tests/integration/drivers/dockerfiles/fedora.Dockerfile +0 -0
- {sqlit_tui-1.0.2 → sqlit_tui-1.1}/tests/integration/drivers/dockerfiles/opensuse.Dockerfile +0 -0
- {sqlit_tui-1.0.2 → sqlit_tui-1.1}/tests/integration/drivers/dockerfiles/rocky.Dockerfile +0 -0
- {sqlit_tui-1.0.2 → sqlit_tui-1.1}/tests/integration/drivers/dockerfiles/ubuntu.Dockerfile +0 -0
- {sqlit_tui-1.0.2 → sqlit_tui-1.1}/tests/integration/drivers/dockerfiles/ui.Dockerfile +0 -0
- {sqlit_tui-1.0.2 → sqlit_tui-1.1}/tests/integration/drivers/run_tests.sh +0 -0
- {sqlit_tui-1.0.2 → sqlit_tui-1.1}/tests/integration/drivers/run_ui_tests.sh +0 -0
- {sqlit_tui-1.0.2 → sqlit_tui-1.1}/tests/integration/drivers/test_driver_install.py +0 -0
- {sqlit_tui-1.0.2 → sqlit_tui-1.1}/tests/integration/drivers/test_driver_setup_ui_flow.py +0 -0
- {sqlit_tui-1.0.2 → sqlit_tui-1.1}/tests/integration/python_packages/README.md +0 -0
- {sqlit_tui-1.0.2 → sqlit_tui-1.1}/tests/integration/python_packages/dockerfiles/debian.Dockerfile +0 -0
- {sqlit_tui-1.0.2 → sqlit_tui-1.1}/tests/integration/python_packages/run_tests.sh +0 -0
- {sqlit_tui-1.0.2 → sqlit_tui-1.1}/tests/integration/python_packages/test_package_install_flow.py +0 -0
- {sqlit_tui-1.0.2 → sqlit_tui-1.1}/tests/integration/test_database_browsing_flow.py +0 -0
- {sqlit_tui-1.0.2 → sqlit_tui-1.1}/tests/test_cockroachdb.py +0 -0
- {sqlit_tui-1.0.2 → sqlit_tui-1.1}/tests/test_credentials_service.py +0 -0
- {sqlit_tui-1.0.2 → sqlit_tui-1.1}/tests/test_d1.py +0 -0
- {sqlit_tui-1.0.2 → sqlit_tui-1.1}/tests/test_duckdb.py +0 -0
- {sqlit_tui-1.0.2 → sqlit_tui-1.1}/tests/test_install_strategy.py +0 -0
- {sqlit_tui-1.0.2 → sqlit_tui-1.1}/tests/test_installer_cancel.py +0 -0
- {sqlit_tui-1.0.2 → sqlit_tui-1.1}/tests/test_mariadb.py +0 -0
- {sqlit_tui-1.0.2 → sqlit_tui-1.1}/tests/test_mocks.py +0 -0
- {sqlit_tui-1.0.2 → sqlit_tui-1.1}/tests/test_mssql.py +0 -0
- {sqlit_tui-1.0.2 → sqlit_tui-1.1}/tests/test_mysql.py +0 -0
- {sqlit_tui-1.0.2 → sqlit_tui-1.1}/tests/test_password_prompts.py +0 -0
- {sqlit_tui-1.0.2 → sqlit_tui-1.1}/tests/test_postgresql.py +0 -0
- {sqlit_tui-1.0.2 → sqlit_tui-1.1}/tests/test_schema_capabilities.py +0 -0
- {sqlit_tui-1.0.2 → sqlit_tui-1.1}/tests/test_sqlite.py +0 -0
- {sqlit_tui-1.0.2 → sqlit_tui-1.1}/tests/test_ssh.py +0 -0
- {sqlit_tui-1.0.2 → sqlit_tui-1.1}/tests/test_turso.py +0 -0
- {sqlit_tui-1.0.2 → sqlit_tui-1.1}/tests/test_validation.py +0 -0
- {sqlit_tui-1.0.2 → sqlit_tui-1.1}/tests/ui/__init__.py +0 -0
- {sqlit_tui-1.0.2 → sqlit_tui-1.1}/tests/ui/conftest.py +0 -0
- {sqlit_tui-1.0.2 → sqlit_tui-1.1}/tests/ui/explorer/__init__.py +0 -0
- {sqlit_tui-1.0.2 → sqlit_tui-1.1}/tests/ui/explorer/test_markup_escaping.py +0 -0
- {sqlit_tui-1.0.2 → sqlit_tui-1.1}/tests/ui/explorer/test_tree_expansion.py +0 -0
- {sqlit_tui-1.0.2 → sqlit_tui-1.1}/tests/ui/keybindings/__init__.py +0 -0
- {sqlit_tui-1.0.2 → sqlit_tui-1.1}/tests/ui/keybindings/conftest.py +0 -0
- {sqlit_tui-1.0.2 → sqlit_tui-1.1}/tests/ui/keybindings/test_contextual.py +0 -0
- {sqlit_tui-1.0.2 → sqlit_tui-1.1}/tests/ui/keybindings/test_dialogs.py +0 -0
- {sqlit_tui-1.0.2 → sqlit_tui-1.1}/tests/ui/keybindings/test_insert_mode.py +0 -0
- {sqlit_tui-1.0.2 → sqlit_tui-1.1}/tests/ui/keybindings/test_keymap_provider.py +0 -0
- {sqlit_tui-1.0.2 → sqlit_tui-1.1}/tests/ui/keybindings/test_leader.py +0 -0
- {sqlit_tui-1.0.2 → sqlit_tui-1.1}/tests/ui/keybindings/test_state_machine.py +0 -0
- {sqlit_tui-1.0.2 → sqlit_tui-1.1}/tests/ui/mocks.py +0 -0
- {sqlit_tui-1.0.2 → sqlit_tui-1.1}/tests/ui/snapshots/01_default_sqlite_screen.svg +0 -0
- {sqlit_tui-1.0.2 → sqlit_tui-1.1}/tests/ui/snapshots/02_edit_mode_postgresql.svg +0 -0
- {sqlit_tui-1.0.2 → sqlit_tui-1.1}/tests/ui/snapshots/03_before_cancel.svg +0 -0
- {sqlit_tui-1.0.2 → sqlit_tui-1.1}/tests/ui/snapshots/04_empty_name_after_save_attempt.svg +0 -0
- {sqlit_tui-1.0.2 → sqlit_tui-1.1}/tests/ui/snapshots/04_empty_name_before_save.svg +0 -0
- {sqlit_tui-1.0.2 → sqlit_tui-1.1}/tests/ui/snapshots/05_after_switch_to_postgresql.svg +0 -0
- {sqlit_tui-1.0.2 → sqlit_tui-1.1}/tests/ui/snapshots/05_before_switch_to_postgresql.svg +0 -0
- {sqlit_tui-1.0.2 → sqlit_tui-1.1}/tests/ui/snapshots/06_sqlite_file_path_field.svg +0 -0
- {sqlit_tui-1.0.2 → sqlit_tui-1.1}/tests/ui/snapshots/07_sqlite_filled_form.svg +0 -0
- {sqlit_tui-1.0.2 → sqlit_tui-1.1}/tests/ui/snapshots/08_postgresql_after_switch.svg +0 -0
- {sqlit_tui-1.0.2 → sqlit_tui-1.1}/tests/ui/snapshots/08_postgresql_filled_form.svg +0 -0
- {sqlit_tui-1.0.2 → sqlit_tui-1.1}/tests/ui/snapshots/09_duplicate_name_validation.svg +0 -0
- {sqlit_tui-1.0.2 → sqlit_tui-1.1}/tests/ui/snapshots/10_after_test_connection.svg +0 -0
- {sqlit_tui-1.0.2 → sqlit_tui-1.1}/tests/ui/snapshots/10_before_test_connection.svg +0 -0
- {sqlit_tui-1.0.2 → sqlit_tui-1.1}/tests/ui/snapshots/11_navigation_after_tab.svg +0 -0
- {sqlit_tui-1.0.2 → sqlit_tui-1.1}/tests/ui/snapshots/11_navigation_initial_focus.svg +0 -0
- {sqlit_tui-1.0.2 → sqlit_tui-1.1}/tests/ui/snapshots/12_navigation_after_shift_tab.svg +0 -0
- {sqlit_tui-1.0.2 → sqlit_tui-1.1}/tests/ui/snapshots/12_navigation_after_two_tabs.svg +0 -0
- {sqlit_tui-1.0.2 → sqlit_tui-1.1}/tests/ui/snapshots/13_ssh_fields_hidden.svg +0 -0
- {sqlit_tui-1.0.2 → sqlit_tui-1.1}/tests/ui/test_connection_screen.py +0 -0
- {sqlit_tui-1.0.2 → sqlit_tui-1.1}/tests/ui/test_explorer_toggle.py +0 -0
- {sqlit_tui-1.0.2 → sqlit_tui-1.1}/tests/ui/test_password_input.py +0 -0
- {sqlit_tui-1.0.2 → sqlit_tui-1.1}/tests/ui/test_query_history.py +0 -0
- {sqlit_tui-1.0.2 → sqlit_tui-1.1}/tests/ui/test_tree_schema_grouping.py +0 -0
|
@@ -101,47 +101,48 @@ jobs:
|
|
|
101
101
|
echo "VERSION=${GITHUB_REF#refs/tags/v}" >> $GITHUB_OUTPUT
|
|
102
102
|
fi
|
|
103
103
|
|
|
104
|
-
- name:
|
|
104
|
+
- name: Wait for PyPI and get checksum
|
|
105
|
+
id: pypi
|
|
105
106
|
run: |
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
107
|
+
VERSION=${{ steps.version.outputs.VERSION }}
|
|
108
|
+
URL="https://files.pythonhosted.org/packages/source/s/sqlit-tui/sqlit_tui-${VERSION}.tar.gz"
|
|
109
|
+
|
|
110
|
+
echo "Waiting for package to be available on PyPI..."
|
|
111
|
+
for i in {1..20}; do
|
|
112
|
+
HTTP_CODE=$(curl -sI -o /dev/null -w "%{http_code}" "$URL")
|
|
113
|
+
if [ "$HTTP_CODE" = "200" ]; then
|
|
114
|
+
echo "Package available on PyPI (attempt $i)"
|
|
115
|
+
break
|
|
116
|
+
fi
|
|
117
|
+
echo "Waiting for PyPI... attempt $i (got HTTP $HTTP_CODE)"
|
|
118
|
+
sleep 30
|
|
119
|
+
done
|
|
120
|
+
|
|
121
|
+
# Download and compute checksum
|
|
122
|
+
curl -sL "$URL" -o /tmp/pkg.tar.gz
|
|
123
|
+
CHECKSUM=$(sha256sum /tmp/pkg.tar.gz | cut -d' ' -f1)
|
|
124
|
+
echo "CHECKSUM=${CHECKSUM}" >> $GITHUB_OUTPUT
|
|
125
|
+
echo "Checksum: ${CHECKSUM}"
|
|
117
126
|
|
|
118
127
|
- name: Update PKGBUILD
|
|
119
128
|
run: |
|
|
120
|
-
cd aur-repo
|
|
121
129
|
VERSION=${{ steps.version.outputs.VERSION }}
|
|
130
|
+
CHECKSUM=${{ steps.pypi.outputs.CHECKSUM }}
|
|
122
131
|
|
|
123
|
-
|
|
124
|
-
sleep 30
|
|
125
|
-
|
|
126
|
-
# Download new tarball and get checksum
|
|
127
|
-
curl -sL "https://files.pythonhosted.org/packages/source/s/sqlit-tui/sqlit_tui-${VERSION}.tar.gz" -o /tmp/pkg.tar.gz
|
|
128
|
-
CHECKSUM=$(sha256sum /tmp/pkg.tar.gz | cut -d' ' -f1)
|
|
129
|
-
|
|
130
|
-
# Update version and checksum in PKGBUILD
|
|
132
|
+
cd aur
|
|
131
133
|
sed -i "s/^pkgver=.*/pkgver=${VERSION}/" PKGBUILD
|
|
132
134
|
sed -i "s/^pkgrel=.*/pkgrel=1/" PKGBUILD
|
|
133
135
|
sed -i "s/^sha256sums=.*/sha256sums=('${CHECKSUM}')/" PKGBUILD
|
|
134
136
|
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
sed -i "s/sqlit_tui-[0-9.]*/sqlit_tui-${VERSION}/g" .SRCINFO
|
|
138
|
-
sed -i "s/sha256sums = .*/sha256sums = ${CHECKSUM}/" .SRCINFO
|
|
137
|
+
echo "Updated PKGBUILD:"
|
|
138
|
+
cat PKGBUILD
|
|
139
139
|
|
|
140
|
-
- name:
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
140
|
+
- name: Publish to AUR
|
|
141
|
+
uses: KSXGitHub/github-actions-deploy-aur@v3.0.1
|
|
142
|
+
with:
|
|
143
|
+
pkgname: python-sqlit-tui
|
|
144
|
+
pkgbuild: ./aur/PKGBUILD
|
|
145
|
+
commit_username: Peter
|
|
146
|
+
commit_email: peter.w.adams96@gmail.com
|
|
147
|
+
ssh_private_key: ${{ secrets.AUR_SSH_PRIVATE_KEY }}
|
|
148
|
+
commit_message: "Update to v${{ steps.version.outputs.VERSION }}"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: sqlit-tui
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.1
|
|
4
4
|
Summary: A terminal UI for SQL Server, PostgreSQL, MySQL, SQLite, and Oracle
|
|
5
5
|
Project-URL: Homepage, https://github.com/Maxteabag/sqlit
|
|
6
6
|
Project-URL: Repository, https://github.com/Maxteabag/sqlit
|
|
@@ -21,41 +21,45 @@ Classifier: Programming Language :: Python :: 3.12
|
|
|
21
21
|
Classifier: Programming Language :: Python :: 3.13
|
|
22
22
|
Classifier: Topic :: Database
|
|
23
23
|
Requires-Python: >=3.10
|
|
24
|
+
Requires-Dist: docker>=7.0.0
|
|
24
25
|
Requires-Dist: keyring>=24.0.0
|
|
25
26
|
Requires-Dist: pyperclip>=1.8.2
|
|
27
|
+
Requires-Dist: textual-fastdatatable>=0.14.0
|
|
26
28
|
Requires-Dist: textual[syntax]>=6.10.0
|
|
27
29
|
Provides-Extra: all
|
|
28
|
-
Requires-Dist: duckdb>=
|
|
30
|
+
Requires-Dist: duckdb>=1.1.0; extra == 'all'
|
|
29
31
|
Requires-Dist: libsql-client>=0.1.0; extra == 'all'
|
|
30
32
|
Requires-Dist: mariadb>=1.1.0; extra == 'all'
|
|
31
|
-
Requires-Dist: mysql-connector-python>=
|
|
33
|
+
Requires-Dist: mysql-connector-python>=9.1.0; extra == 'all'
|
|
32
34
|
Requires-Dist: oracledb>=2.0.0; extra == 'all'
|
|
33
35
|
Requires-Dist: paramiko<4.0.0,>=2.0.0; extra == 'all'
|
|
34
36
|
Requires-Dist: psycopg2-binary>=2.9.0; extra == 'all'
|
|
35
37
|
Requires-Dist: pyodbc>=5.0.0; extra == 'all'
|
|
36
|
-
Requires-Dist: requests>=2.
|
|
38
|
+
Requires-Dist: requests>=2.32.4; extra == 'all'
|
|
37
39
|
Requires-Dist: sshtunnel>=0.4.0; extra == 'all'
|
|
38
40
|
Provides-Extra: cockroachdb
|
|
39
41
|
Requires-Dist: psycopg2-binary>=2.9.0; extra == 'cockroachdb'
|
|
40
42
|
Provides-Extra: d1
|
|
41
|
-
Requires-Dist: requests>=2.
|
|
43
|
+
Requires-Dist: requests>=2.32.4; extra == 'd1'
|
|
42
44
|
Provides-Extra: dev
|
|
43
45
|
Requires-Dist: build; extra == 'dev'
|
|
46
|
+
Requires-Dist: faker>=28.0; extra == 'dev'
|
|
44
47
|
Requires-Dist: mypy>=1.0; extra == 'dev'
|
|
45
48
|
Requires-Dist: pre-commit>=3.0; extra == 'dev'
|
|
46
49
|
Requires-Dist: pytest-asyncio>=0.23.0; extra == 'dev'
|
|
50
|
+
Requires-Dist: pytest-benchmark>=4.0; extra == 'dev'
|
|
47
51
|
Requires-Dist: pytest-cov>=4.0; extra == 'dev'
|
|
48
52
|
Requires-Dist: pytest-timeout>=2.0; extra == 'dev'
|
|
49
53
|
Requires-Dist: pytest>=7.0; extra == 'dev'
|
|
50
54
|
Requires-Dist: ruff>=0.8.0; extra == 'dev'
|
|
51
55
|
Provides-Extra: duckdb
|
|
52
|
-
Requires-Dist: duckdb>=
|
|
56
|
+
Requires-Dist: duckdb>=1.1.0; extra == 'duckdb'
|
|
53
57
|
Provides-Extra: mariadb
|
|
54
58
|
Requires-Dist: mariadb>=1.1.0; extra == 'mariadb'
|
|
55
59
|
Provides-Extra: mssql
|
|
56
60
|
Requires-Dist: pyodbc>=5.0.0; extra == 'mssql'
|
|
57
61
|
Provides-Extra: mysql
|
|
58
|
-
Requires-Dist: mysql-connector-python>=
|
|
62
|
+
Requires-Dist: mysql-connector-python>=9.1.0; extra == 'mysql'
|
|
59
63
|
Provides-Extra: oracle
|
|
60
64
|
Requires-Dist: oracledb>=2.0.0; extra == 'oracle'
|
|
61
65
|
Provides-Extra: postgres
|
|
@@ -86,6 +90,8 @@ A lightweight TUI for people who just want to run some queries fast.
|
|
|
86
90
|
|
|
87
91
|
### Query History
|
|
88
92
|

|
|
93
|
+
**Filter results**
|
|
94
|
+

|
|
89
95
|
|
|
90
96
|
|
|
91
97
|
## Features
|
|
@@ -93,11 +99,14 @@ A lightweight TUI for people who just want to run some queries fast.
|
|
|
93
99
|
- **Connection manager UI** - Save connections, switch between databases without CLI args
|
|
94
100
|
- **Just run `sqlit`** - No CLI config needed, pick a connection and go
|
|
95
101
|
- **Multi-database out of the box** - SQL Server, PostgreSQL, MySQL, SQLite, MariaDB, Oracle, DuckDB, CockroachDB, Supabase, Turso - no adapters to install
|
|
102
|
+
- Connect directly to database docker container
|
|
96
103
|
- **SSH tunnels built-in** - Connect to remote databases securely with password or key auth
|
|
97
104
|
- **Vim-style editing** - Modal editing for terminal purists
|
|
98
105
|
- **Query history** - Automatically saves queries per connection, searchable and sortable
|
|
106
|
+
- Filter results
|
|
99
107
|
- Context-aware help (no need to memorize keybindings)
|
|
100
108
|
- Browse databases, tables, views, and stored procedures
|
|
109
|
+
- Indexes, Triggers and Sequences
|
|
101
110
|
- SQL autocomplete for tables, columns, and procedures
|
|
102
111
|
- Multiple auth methods (Windows, SQL Server, Entra ID)
|
|
103
112
|
- CLI mode for scripting and AI agents
|
|
@@ -177,6 +186,14 @@ sqlit connections add postgresql --name "RemoteDB" --server "db-host" --username
|
|
|
177
186
|
# Temporary (not saved) connection
|
|
178
187
|
sqlit connect sqlite --file-path "/path/to/database.db"
|
|
179
188
|
|
|
189
|
+
# Connect via URL - scheme determines database type (postgresql://, mysql://, sqlite://, etc.)
|
|
190
|
+
sqlit postgresql://user:pass@localhost:5432/mydb
|
|
191
|
+
sqlit mysql://root@localhost/testdb
|
|
192
|
+
sqlit sqlite:///path/to/database.db
|
|
193
|
+
|
|
194
|
+
# Save a connection via URL
|
|
195
|
+
sqlit connections add --url dbtype://user:pass@host/db --name "MyDB"
|
|
196
|
+
|
|
180
197
|
# Provider-specific CLI help
|
|
181
198
|
sqlit connect -h
|
|
182
199
|
sqlit connect supabase -h
|
|
@@ -282,6 +299,84 @@ SSH tunnel functionality requires additional dependencies. Install with the `ssh
|
|
|
282
299
|
|
|
283
300
|
If you try to create an SSH connection without these dependencies, sqlit will detect this and show you the exact command to install them for your environment.
|
|
284
301
|
|
|
302
|
+
### Vision
|
|
303
|
+
|
|
304
|
+
The core purpose of this application is to read Read&Write to a SQL database.
|
|
305
|
+
The core elements to achieve this purpose is: CEQR:
|
|
306
|
+
|
|
307
|
+
- C: Connecting
|
|
308
|
+
- E: Exploring
|
|
309
|
+
- Q: Querying
|
|
310
|
+
- R: Viewing results
|
|
311
|
+
|
|
312
|
+
Connecting: Connecting to a server
|
|
313
|
+
Exploring: Understanding the structure and content of the databases
|
|
314
|
+
Querying: Executing SQL queries
|
|
315
|
+
D: Viewing the results of SQL queries
|
|
316
|
+
|
|
317
|
+
Additionally, we have requirements 'EAFF':
|
|
318
|
+
|
|
319
|
+
- E: Easy
|
|
320
|
+
- A: Aesthetically pleasing
|
|
321
|
+
- F: Fun
|
|
322
|
+
- F: Fast
|
|
323
|
+
|
|
324
|
+
If an idea or feature does *not* achieve any of the 'CBQV' elements adhering to all of the 'EAFF' requirements. It does not belong to sqlit.
|
|
325
|
+
|
|
326
|
+
**[E]asy:**
|
|
327
|
+
Sqlit should not require any external documentation at all. It must prioritize intuitiveness above all.
|
|
328
|
+
|
|
329
|
+
**[A]esthetically pleasing:**
|
|
330
|
+
Sqlit should not render one unnecessary pixel. It should prioritize beauty above anything. Minimalism over bloat.
|
|
331
|
+
|
|
332
|
+
**Fun:**
|
|
333
|
+
Sqlit aims make fulfilling its core purpose be an enjoyable experience for the user, even a source of pleasure.
|
|
334
|
+
|
|
335
|
+
**Fast:**
|
|
336
|
+
Sqlit aims to fulfill its core purpose for the user, with intention to giving the user the results they want with as few actions as possible.
|
|
337
|
+
|
|
338
|
+
Essentially, sqlit aims to do CRUD on SQL really well.
|
|
339
|
+
|
|
340
|
+
This implies this tool is more suited for developer's daily use than an database administrator.
|
|
341
|
+
Every feature in sqlit should have a target audience in which they will use it every time they use sqlit.
|
|
342
|
+
If nobody is going to a feature every day. It does not belong to sqlit.
|
|
343
|
+
E.g.
|
|
344
|
+
|
|
345
|
+
1) advanced query performance debugging -> rarely used -> does not belong in sqlit
|
|
346
|
+
2) edit cell key-binding -> a audience who will use this every day -> belongs to sqlit
|
|
347
|
+
|
|
348
|
+
**On complexity:**
|
|
349
|
+
Minimalism: sqlit aims to abstract away as much complexity as possible from the user, while giving them enough control to achieve CBQV. sqlit should never do anything under the hood that the user might have interest in understanding. Universal state problems deem for magical fixes. Conditional state problems, explicit user awareness. User should never ask "wait, how did it know?" "why is this here?" "why did it work then, but not now?"
|
|
350
|
+
|
|
351
|
+
Voluntary advanced usage: Anything beyond most essentials to achieve CEQR should be voluntary to be exposed to. Minimal cogntive overhead. Always assume by default our user just wants to perform CRUD with SQL.
|
|
352
|
+
|
|
353
|
+
The idea is the user is exposed to an interface that's minimalistic and easy, but if they want to become 'power users' they may dig into command menu or see help and memorize.
|
|
354
|
+
|
|
355
|
+
Advances features should not be advertised on the main tool bar or anywhere else where the user has no say in whether it's rendered, as they take up space and distract from the most essential features for crud.
|
|
356
|
+
|
|
357
|
+
One state: There should be no settings or preferences with important exception of interface (aesthetics, keyboard bindings). No settings to enable or disable features for conditional behaviour. Do not include a feature that a user finds annoying. Settings to disable a feature is a symptom of this. Anything beyond essential must be sought after if needed, not disabled if unwanted.
|
|
358
|
+
|
|
359
|
+
**Keybindings philosophy:**
|
|
360
|
+
To make sqlit as fast' as possible, sqlit has a large focus on keybindings.
|
|
361
|
+
To make sqlit as 'easy' as possible, all necessary keybindings to do 'CEQR' well, must be visible at all times.
|
|
362
|
+
To make sqlit as 'aesthetically pleasing' any keybinding not strictly necessary to perform 'CEQR' in a 'easy' and 'fast' way will be hidden behind help <?> or command menu <space>
|
|
363
|
+
Keybindings will favour 'vim' traditions as the core audience is developers who enjoy working in terminals.
|
|
364
|
+
We shy away from ^+ commands and will only use them where it is not natural to have a "insert/normal" mode and where input is crucial. (Typical is pop up modals)
|
|
365
|
+
|
|
366
|
+
**Ideal:**
|
|
367
|
+
It should be easy to use for someone who just started using sqlit.
|
|
368
|
+
sqlit should provide fun and a feeling of mastery and satisfaction for those who want to achieve it, by becoming a sql-manipulating wizard with creative keybinding combos.
|
|
369
|
+
|
|
370
|
+
**Designing keybindings decision hierarchy:**
|
|
371
|
+
|
|
372
|
+
1. Intuitive to learn
|
|
373
|
+
2. Harmony (we should think about which keybindings are used in sequence, in typical to flow and maximize user mastery satisfaction and opportunity to combine them fast)
|
|
374
|
+
3. Traditions (vim, specifically)
|
|
375
|
+
|
|
376
|
+
**Example:**
|
|
377
|
+
<e> = explorer pane, <q> = query pane, <r> = results pane.
|
|
378
|
+
Rationale: E;Q;R satisfies both intuitiveness (each binding is the first letter of the pane), harmony (proximity: qwerty speaks for itself)
|
|
379
|
+
|
|
285
380
|
## License
|
|
286
381
|
|
|
287
382
|
MIT
|
|
@@ -12,6 +12,8 @@ A lightweight TUI for people who just want to run some queries fast.
|
|
|
12
12
|
|
|
13
13
|
### Query History
|
|
14
14
|

|
|
15
|
+
**Filter results**
|
|
16
|
+

|
|
15
17
|
|
|
16
18
|
|
|
17
19
|
## Features
|
|
@@ -19,11 +21,14 @@ A lightweight TUI for people who just want to run some queries fast.
|
|
|
19
21
|
- **Connection manager UI** - Save connections, switch between databases without CLI args
|
|
20
22
|
- **Just run `sqlit`** - No CLI config needed, pick a connection and go
|
|
21
23
|
- **Multi-database out of the box** - SQL Server, PostgreSQL, MySQL, SQLite, MariaDB, Oracle, DuckDB, CockroachDB, Supabase, Turso - no adapters to install
|
|
24
|
+
- Connect directly to database docker container
|
|
22
25
|
- **SSH tunnels built-in** - Connect to remote databases securely with password or key auth
|
|
23
26
|
- **Vim-style editing** - Modal editing for terminal purists
|
|
24
27
|
- **Query history** - Automatically saves queries per connection, searchable and sortable
|
|
28
|
+
- Filter results
|
|
25
29
|
- Context-aware help (no need to memorize keybindings)
|
|
26
30
|
- Browse databases, tables, views, and stored procedures
|
|
31
|
+
- Indexes, Triggers and Sequences
|
|
27
32
|
- SQL autocomplete for tables, columns, and procedures
|
|
28
33
|
- Multiple auth methods (Windows, SQL Server, Entra ID)
|
|
29
34
|
- CLI mode for scripting and AI agents
|
|
@@ -103,6 +108,14 @@ sqlit connections add postgresql --name "RemoteDB" --server "db-host" --username
|
|
|
103
108
|
# Temporary (not saved) connection
|
|
104
109
|
sqlit connect sqlite --file-path "/path/to/database.db"
|
|
105
110
|
|
|
111
|
+
# Connect via URL - scheme determines database type (postgresql://, mysql://, sqlite://, etc.)
|
|
112
|
+
sqlit postgresql://user:pass@localhost:5432/mydb
|
|
113
|
+
sqlit mysql://root@localhost/testdb
|
|
114
|
+
sqlit sqlite:///path/to/database.db
|
|
115
|
+
|
|
116
|
+
# Save a connection via URL
|
|
117
|
+
sqlit connections add --url dbtype://user:pass@host/db --name "MyDB"
|
|
118
|
+
|
|
106
119
|
# Provider-specific CLI help
|
|
107
120
|
sqlit connect -h
|
|
108
121
|
sqlit connect supabase -h
|
|
@@ -208,6 +221,84 @@ SSH tunnel functionality requires additional dependencies. Install with the `ssh
|
|
|
208
221
|
|
|
209
222
|
If you try to create an SSH connection without these dependencies, sqlit will detect this and show you the exact command to install them for your environment.
|
|
210
223
|
|
|
224
|
+
### Vision
|
|
225
|
+
|
|
226
|
+
The core purpose of this application is to read Read&Write to a SQL database.
|
|
227
|
+
The core elements to achieve this purpose is: CEQR:
|
|
228
|
+
|
|
229
|
+
- C: Connecting
|
|
230
|
+
- E: Exploring
|
|
231
|
+
- Q: Querying
|
|
232
|
+
- R: Viewing results
|
|
233
|
+
|
|
234
|
+
Connecting: Connecting to a server
|
|
235
|
+
Exploring: Understanding the structure and content of the databases
|
|
236
|
+
Querying: Executing SQL queries
|
|
237
|
+
D: Viewing the results of SQL queries
|
|
238
|
+
|
|
239
|
+
Additionally, we have requirements 'EAFF':
|
|
240
|
+
|
|
241
|
+
- E: Easy
|
|
242
|
+
- A: Aesthetically pleasing
|
|
243
|
+
- F: Fun
|
|
244
|
+
- F: Fast
|
|
245
|
+
|
|
246
|
+
If an idea or feature does *not* achieve any of the 'CBQV' elements adhering to all of the 'EAFF' requirements. It does not belong to sqlit.
|
|
247
|
+
|
|
248
|
+
**[E]asy:**
|
|
249
|
+
Sqlit should not require any external documentation at all. It must prioritize intuitiveness above all.
|
|
250
|
+
|
|
251
|
+
**[A]esthetically pleasing:**
|
|
252
|
+
Sqlit should not render one unnecessary pixel. It should prioritize beauty above anything. Minimalism over bloat.
|
|
253
|
+
|
|
254
|
+
**Fun:**
|
|
255
|
+
Sqlit aims make fulfilling its core purpose be an enjoyable experience for the user, even a source of pleasure.
|
|
256
|
+
|
|
257
|
+
**Fast:**
|
|
258
|
+
Sqlit aims to fulfill its core purpose for the user, with intention to giving the user the results they want with as few actions as possible.
|
|
259
|
+
|
|
260
|
+
Essentially, sqlit aims to do CRUD on SQL really well.
|
|
261
|
+
|
|
262
|
+
This implies this tool is more suited for developer's daily use than an database administrator.
|
|
263
|
+
Every feature in sqlit should have a target audience in which they will use it every time they use sqlit.
|
|
264
|
+
If nobody is going to a feature every day. It does not belong to sqlit.
|
|
265
|
+
E.g.
|
|
266
|
+
|
|
267
|
+
1) advanced query performance debugging -> rarely used -> does not belong in sqlit
|
|
268
|
+
2) edit cell key-binding -> a audience who will use this every day -> belongs to sqlit
|
|
269
|
+
|
|
270
|
+
**On complexity:**
|
|
271
|
+
Minimalism: sqlit aims to abstract away as much complexity as possible from the user, while giving them enough control to achieve CBQV. sqlit should never do anything under the hood that the user might have interest in understanding. Universal state problems deem for magical fixes. Conditional state problems, explicit user awareness. User should never ask "wait, how did it know?" "why is this here?" "why did it work then, but not now?"
|
|
272
|
+
|
|
273
|
+
Voluntary advanced usage: Anything beyond most essentials to achieve CEQR should be voluntary to be exposed to. Minimal cogntive overhead. Always assume by default our user just wants to perform CRUD with SQL.
|
|
274
|
+
|
|
275
|
+
The idea is the user is exposed to an interface that's minimalistic and easy, but if they want to become 'power users' they may dig into command menu or see help and memorize.
|
|
276
|
+
|
|
277
|
+
Advances features should not be advertised on the main tool bar or anywhere else where the user has no say in whether it's rendered, as they take up space and distract from the most essential features for crud.
|
|
278
|
+
|
|
279
|
+
One state: There should be no settings or preferences with important exception of interface (aesthetics, keyboard bindings). No settings to enable or disable features for conditional behaviour. Do not include a feature that a user finds annoying. Settings to disable a feature is a symptom of this. Anything beyond essential must be sought after if needed, not disabled if unwanted.
|
|
280
|
+
|
|
281
|
+
**Keybindings philosophy:**
|
|
282
|
+
To make sqlit as fast' as possible, sqlit has a large focus on keybindings.
|
|
283
|
+
To make sqlit as 'easy' as possible, all necessary keybindings to do 'CEQR' well, must be visible at all times.
|
|
284
|
+
To make sqlit as 'aesthetically pleasing' any keybinding not strictly necessary to perform 'CEQR' in a 'easy' and 'fast' way will be hidden behind help <?> or command menu <space>
|
|
285
|
+
Keybindings will favour 'vim' traditions as the core audience is developers who enjoy working in terminals.
|
|
286
|
+
We shy away from ^+ commands and will only use them where it is not natural to have a "insert/normal" mode and where input is crucial. (Typical is pop up modals)
|
|
287
|
+
|
|
288
|
+
**Ideal:**
|
|
289
|
+
It should be easy to use for someone who just started using sqlit.
|
|
290
|
+
sqlit should provide fun and a feeling of mastery and satisfaction for those who want to achieve it, by becoming a sql-manipulating wizard with creative keybinding combos.
|
|
291
|
+
|
|
292
|
+
**Designing keybindings decision hierarchy:**
|
|
293
|
+
|
|
294
|
+
1. Intuitive to learn
|
|
295
|
+
2. Harmony (we should think about which keybindings are used in sequence, in typical to flow and maximize user mastery satisfaction and opportunity to combine them fast)
|
|
296
|
+
3. Traditions (vim, specifically)
|
|
297
|
+
|
|
298
|
+
**Example:**
|
|
299
|
+
<e> = explorer pane, <q> = query pane, <r> = results pane.
|
|
300
|
+
Rationale: E;Q;R satisfies both intuitiveness (each binding is the first letter of the pane), harmony (proximity: qwerty speaks for itself)
|
|
301
|
+
|
|
211
302
|
## License
|
|
212
303
|
|
|
213
304
|
MIT
|
|
Binary file
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
{
|
|
2
|
+
"mock": {
|
|
3
|
+
"enabled": true,
|
|
4
|
+
"profile": "d1-demo",
|
|
5
|
+
"connections": [],
|
|
6
|
+
"adapters": {
|
|
7
|
+
"d1": {
|
|
8
|
+
"name": "Cloudflare D1",
|
|
9
|
+
"default_schema": "main",
|
|
10
|
+
"connect": {
|
|
11
|
+
"result": "success"
|
|
12
|
+
},
|
|
13
|
+
"schemas": {
|
|
14
|
+
"main": {
|
|
15
|
+
"tables": {
|
|
16
|
+
"users": {
|
|
17
|
+
"columns": [
|
|
18
|
+
{
|
|
19
|
+
"name": "id",
|
|
20
|
+
"type": "INTEGER"
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
"name": "email",
|
|
24
|
+
"type": "TEXT"
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
"name": "name",
|
|
28
|
+
"type": "TEXT"
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
"name": "created_at",
|
|
32
|
+
"type": "TEXT"
|
|
33
|
+
}
|
|
34
|
+
],
|
|
35
|
+
"rows": [
|
|
36
|
+
[
|
|
37
|
+
1,
|
|
38
|
+
"alice@example.com",
|
|
39
|
+
"Alice Chen",
|
|
40
|
+
"2024-11-01"
|
|
41
|
+
],
|
|
42
|
+
[
|
|
43
|
+
2,
|
|
44
|
+
"bob@example.com",
|
|
45
|
+
"Bob Smith",
|
|
46
|
+
"2024-11-05"
|
|
47
|
+
],
|
|
48
|
+
[
|
|
49
|
+
3,
|
|
50
|
+
"carol@example.com",
|
|
51
|
+
"Carol Davis",
|
|
52
|
+
"2024-11-10"
|
|
53
|
+
]
|
|
54
|
+
]
|
|
55
|
+
},
|
|
56
|
+
"posts": {
|
|
57
|
+
"columns": [
|
|
58
|
+
{
|
|
59
|
+
"name": "id",
|
|
60
|
+
"type": "INTEGER"
|
|
61
|
+
},
|
|
62
|
+
{
|
|
63
|
+
"name": "user_id",
|
|
64
|
+
"type": "INTEGER"
|
|
65
|
+
},
|
|
66
|
+
{
|
|
67
|
+
"name": "title",
|
|
68
|
+
"type": "TEXT"
|
|
69
|
+
},
|
|
70
|
+
{
|
|
71
|
+
"name": "published",
|
|
72
|
+
"type": "INTEGER"
|
|
73
|
+
}
|
|
74
|
+
],
|
|
75
|
+
"rows": [
|
|
76
|
+
[
|
|
77
|
+
1,
|
|
78
|
+
1,
|
|
79
|
+
"Getting Started with D1",
|
|
80
|
+
1
|
|
81
|
+
],
|
|
82
|
+
[
|
|
83
|
+
2,
|
|
84
|
+
1,
|
|
85
|
+
"Edge Computing Basics",
|
|
86
|
+
1
|
|
87
|
+
],
|
|
88
|
+
[
|
|
89
|
+
3,
|
|
90
|
+
2,
|
|
91
|
+
"Workers and D1",
|
|
92
|
+
0
|
|
93
|
+
],
|
|
94
|
+
[
|
|
95
|
+
4,
|
|
96
|
+
3,
|
|
97
|
+
"SQLite at the Edge",
|
|
98
|
+
1
|
|
99
|
+
]
|
|
100
|
+
]
|
|
101
|
+
},
|
|
102
|
+
"analytics": {
|
|
103
|
+
"columns": [
|
|
104
|
+
{
|
|
105
|
+
"name": "id",
|
|
106
|
+
"type": "INTEGER"
|
|
107
|
+
},
|
|
108
|
+
{
|
|
109
|
+
"name": "post_id",
|
|
110
|
+
"type": "INTEGER"
|
|
111
|
+
},
|
|
112
|
+
{
|
|
113
|
+
"name": "views",
|
|
114
|
+
"type": "INTEGER"
|
|
115
|
+
},
|
|
116
|
+
{
|
|
117
|
+
"name": "date",
|
|
118
|
+
"type": "TEXT"
|
|
119
|
+
}
|
|
120
|
+
],
|
|
121
|
+
"rows": [
|
|
122
|
+
[
|
|
123
|
+
1,
|
|
124
|
+
1,
|
|
125
|
+
1250,
|
|
126
|
+
"2024-12-01"
|
|
127
|
+
],
|
|
128
|
+
[
|
|
129
|
+
2,
|
|
130
|
+
2,
|
|
131
|
+
890,
|
|
132
|
+
"2024-12-01"
|
|
133
|
+
],
|
|
134
|
+
[
|
|
135
|
+
3,
|
|
136
|
+
4,
|
|
137
|
+
445,
|
|
138
|
+
"2024-12-01"
|
|
139
|
+
],
|
|
140
|
+
[
|
|
141
|
+
4,
|
|
142
|
+
1,
|
|
143
|
+
320,
|
|
144
|
+
"2024-12-02"
|
|
145
|
+
]
|
|
146
|
+
]
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
},
|
|
151
|
+
"query_results": {
|
|
152
|
+
"join": {
|
|
153
|
+
"columns": [
|
|
154
|
+
"author",
|
|
155
|
+
"title",
|
|
156
|
+
"total_views"
|
|
157
|
+
],
|
|
158
|
+
"rows": [
|
|
159
|
+
[
|
|
160
|
+
"Alice Chen",
|
|
161
|
+
"Getting Started with D1",
|
|
162
|
+
1570
|
|
163
|
+
],
|
|
164
|
+
[
|
|
165
|
+
"Alice Chen",
|
|
166
|
+
"Edge Computing Basics",
|
|
167
|
+
890
|
|
168
|
+
],
|
|
169
|
+
[
|
|
170
|
+
"Carol Davis",
|
|
171
|
+
"SQLite at the Edge",
|
|
172
|
+
445
|
|
173
|
+
]
|
|
174
|
+
]
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
},
|
|
180
|
+
"theme": "sqlit",
|
|
181
|
+
"expanded_nodes": [
|
|
182
|
+
"conn:My D1 Database",
|
|
183
|
+
"conn:My D1 Database/folder:tables"
|
|
184
|
+
]
|
|
185
|
+
}
|
|
Binary file
|
|
Binary file
|
|
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "sqlit-tui"
|
|
7
|
-
version = "1.
|
|
7
|
+
version = "1.1"
|
|
8
8
|
description = "A terminal UI for SQL Server, PostgreSQL, MySQL, SQLite, and Oracle"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
license = "MIT"
|
|
@@ -28,19 +28,21 @@ classifiers = [
|
|
|
28
28
|
]
|
|
29
29
|
dependencies = [
|
|
30
30
|
"textual[syntax]>=6.10.0",
|
|
31
|
+
"textual-fastdatatable>=0.14.0",
|
|
31
32
|
"pyperclip>=1.8.2",
|
|
32
33
|
"keyring>=24.0.0",
|
|
34
|
+
"docker>=7.0.0", # Docker container auto-detection (lazy loaded)
|
|
33
35
|
]
|
|
34
36
|
|
|
35
37
|
[project.optional-dependencies]
|
|
36
38
|
all = [
|
|
37
39
|
"psycopg2-binary>=2.9.0",
|
|
38
40
|
"pyodbc>=5.0.0",
|
|
39
|
-
"mysql-connector-python>=
|
|
41
|
+
"mysql-connector-python>=9.1.0", # min avoids known CVEs
|
|
40
42
|
"mariadb>=1.1.0",
|
|
41
43
|
"oracledb>=2.0.0",
|
|
42
|
-
"duckdb>=
|
|
43
|
-
"requests>=2.
|
|
44
|
+
"duckdb>=1.1.0", # min avoids known CVEs
|
|
45
|
+
"requests>=2.32.4", # min avoids known CVEs
|
|
44
46
|
"libsql-client>=0.1.0",
|
|
45
47
|
"sshtunnel>=0.4.0",
|
|
46
48
|
"paramiko>=2.0.0,<4.0.0",
|
|
@@ -48,11 +50,11 @@ all = [
|
|
|
48
50
|
postgres = ["psycopg2-binary>=2.9.0"]
|
|
49
51
|
cockroachdb = ["psycopg2-binary>=2.9.0"]
|
|
50
52
|
mssql = ["pyodbc>=5.0.0"]
|
|
51
|
-
mysql = ["mysql-connector-python>=
|
|
53
|
+
mysql = ["mysql-connector-python>=9.1.0"] # min avoids known CVEs
|
|
52
54
|
mariadb = ["mariadb>=1.1.0"]
|
|
53
55
|
oracle = ["oracledb>=2.0.0"]
|
|
54
|
-
duckdb = ["duckdb>=
|
|
55
|
-
d1 = ["requests>=2.
|
|
56
|
+
duckdb = ["duckdb>=1.1.0"] # min avoids known CVEs
|
|
57
|
+
d1 = ["requests>=2.32.4"] # min avoids known CVEs
|
|
56
58
|
turso = ["libsql-client>=0.1.0"]
|
|
57
59
|
ssh = [
|
|
58
60
|
"sshtunnel>=0.4.0",
|
|
@@ -69,6 +71,8 @@ dev = [
|
|
|
69
71
|
"pytest-timeout>=2.0",
|
|
70
72
|
"pytest-asyncio>=0.23.0",
|
|
71
73
|
"pytest-cov>=4.0",
|
|
74
|
+
"pytest-benchmark>=4.0",
|
|
75
|
+
"Faker>=28.0",
|
|
72
76
|
"build",
|
|
73
77
|
"ruff>=0.8.0",
|
|
74
78
|
"mypy>=1.0",
|
|
@@ -107,6 +111,7 @@ markers = [
|
|
|
107
111
|
"mysql: MySQL database tests",
|
|
108
112
|
"oracle: Oracle database tests",
|
|
109
113
|
"asyncio: async tests",
|
|
114
|
+
"integration: integration tests (may require external services)",
|
|
110
115
|
]
|
|
111
116
|
|
|
112
117
|
[tool.coverage.run]
|
|
@@ -138,7 +143,11 @@ module = [
|
|
|
138
143
|
"oracledb",
|
|
139
144
|
"duckdb",
|
|
140
145
|
"libsql_client",
|
|
141
|
-
"sshtunnel"
|
|
146
|
+
"sshtunnel",
|
|
147
|
+
"docker",
|
|
148
|
+
"docker.errors",
|
|
149
|
+
"pyarrow",
|
|
150
|
+
"textual_fastdatatable"
|
|
142
151
|
]
|
|
143
152
|
ignore_missing_imports = true
|
|
144
153
|
|