An open API service indexing awesome lists of open source software.

https://github.com/beyondlex/poste


https://github.com/beyondlex/poste

Last synced: about 1 month ago
JSON representation

Awesome Lists containing this project

README

          

# Poste

**Send requests from files. Keyboard-first. Multi-protocol.**

A Neovim plugin and Rust CLI for executing HTTP, Redis, SQL (PostgreSQL / MySQL / SQLite) requests from plain text files. Inspired by JetBrains HTTP Client, with focus on keyboard-driven workflows and dataset manipulation.

## Features

- **File-based requests** — Define requests in `.http`/`.rest`, `.sql`, `.sqlite`, `.redis`, `.mongo` files
- **Environment variables** — JetBrains-style `env.json` with `{{var}}` substitution
- **Named connections** — `connections.json` for database credentials; supports env var references
- **Keyboard-first** — Execute at cursor, navigate results with Vim keys, never leave home row
- **Multi-protocol** — HTTP, Redis, PostgreSQL, MySQL, SQLite (MongoDB/AMQP stubs)
- **SQL dataset buffer** — Paginated results, cell navigation (hjkl), vim-style search/filter, sorting, inline editing
- **Dataset manipulation** — Edit cells inline, generate DML (INSERT/UPDATE/DELETE) from changes, commit with transaction support
- **Data import/export** — CSV, JSON, SQL INSERT statements
- **DB browser** — Tree-view of schemas, tables, columns; generate SELECT/DESCRIBE queries; DDL table operations
- **Completion** — HTTP methods/headers/values (nvim-cmp or blink.cmp); SQL keywords/identifiers/columns (blink.cmp)
- **Assertions & scripts** — Inline `> {% ... %}` assertions, pre/post-request scripts
- **Request chaining** — `{{RequestName.res.body.X}}` to extract values from prior responses

## Quick Start

### Install

```lua
-- lazy.nvim
{
"beyondlex/poste",
dependencies = {
"saghen/blink.cmp",
"stevearc/dressing.nvim",
"beyondlex/finder",
},
config = function()
require("poste").setup()
end,
}
```

```bash
# Rust CLI (optional — for standalone execution or to enable context-aware features)
cargo install --path crates/poste-cli
```

### Create a request file

`requests/api.http`:

```http
### List users
GET {{api_base}}/users
Authorization: Bearer {{api_token}}

### Create user
POST {{api_base}}/users
Content-Type: application/json

{"name": "John", "email": "john@test.com"}
```

`requests/queries.sql`:

```sql
-- @connection pg-dev

SELECT * FROM users WHERE active = true;
```

`requests/cache.redis`:

```redis
# @connection redis://localhost:6379

### Get user session
GET session:user:42

### Set cache
SET post:latest "active"
EXPIRE post:latest 3600
```

### Define environments

`env.json` (walk-up discovery from file directory):

```json
{
"dev": {
"api_base": "http://localhost:8080",
"api_token": "dev-token-xxx",
"db_host": "127.0.0.1",
"db_port": "5432",
"db_user": "app_user",
"db_pass": "local-pass"
},
"prod": {
"api_base": "https://api.example.com",
"api_token": "prod-token-xxx"
}
}
```

### Define connections

`connections.json` (walk-up discovery; supports `{{var}}`):

```json
{
"pg-dev": {
"dialect": "postgres",
"host": "{{db_host}}",
"port": "{{db_port}}",
"database": "myapp",
"user": "{{db_user}}",
"password": "{{db_pass}}"
},
"my-blog": {
"dialect": "mysql",
"host": "localhost",
"port": 3306,
"database": "blog",
"user": "root",
"password": ""
}
}
```

### Execute

In Neovim, open any supported file. With cursor on a request block, press `` to execute. Results open in a side panel.

Default keymaps →

### Source buffer (`.http`, `.sql`, `.redis`)

| Key | Action |
|-----|--------|
| `` | Execute request at cursor |
| `]]` / `[[` | Jump next/previous block |
| `gd` | Go to definition |
| `grr` | Go to references |
| `gs` | Symbol outline (Telescope fallback to `vim.ui.select`) |
| `rp` | Paste curl from clipboard |
| `rc` | Copy request as curl |

### HTTP response buffer

| Key | Action |
|-----|--------|
| `q` | Close |
| `B` / `I` | View Body / Verbose |
| `A` / `S` | View Assertions / Script logs |
| `` / `` | Next/previous tab |

### SQL source buffer (additional)

| Key | Action |
|-----|--------|
| `K` | Show DDL for table under cursor |
| `db` | Toggle DB browser |
| `cr` | Clear filter/search in dataset |
| `` | Trigger completion (i mode) |

### SQL dataset buffer

| Key | Action |
|-----|--------|
| `q` | Close |
| `h`/`j`/`k`/`l` | Move cell left/down/up/right |
| `0`/`$` | First/last column |
| `gg`/`G` | First/last row |
| `H`/`L` | Previous/next page |
| `K` | Preview cell content in float |
| `yy` / `yc` | Yank cell / yank column |
| `s` | Sort by current column (toggle asc/desc) |
| `zh` | Toggle cell highlight |
| `zH` | Toggle header float |
| `zN` | Toggle row numbers |
| `R` | Re-run query |
| ``/`` | Next/previous result tab |
| `n`/`N` | Next/previous search match |
| `/` | Search |
| `cr` | Clear search/filter |
| `fc` | Find column |
| `ce` | Filter by current cell |
| `hh`/`ll` | First/last page |
| `pa` | Toggle pagination |
| `gp` | Toggle raw mode |
| `i` / `a` | Enter edit mode (insert/append) |
| `dd` | Delete row |
| `o` / `O` | Insert row below/above |
| `u` | Undo edit |
| `w` / `:W` | Commit changes (generate & execute DML) |
| `ec` | Export as CSV |
| `ej` | Export as JSON |
| `es` | Export as SQL INSERT |

### DB browser

| Key | Action |
|-----|--------|
| `` | Toggle node expand/collapse |
| `x` | Open context menu (node-specific actions) |
| `r` | Refresh node |
| `/` | Search filter |
| `s` | Generate SELECT * query |
| `d` | Generate DESCRIBE query |
| `q` | Close |
| `ma`/`mr`/`md`/`mt` | Table ops: add/rename/drop/alter column |

### Commands

| Command | Description |
|---------|-------------|
| `:PosteRun` | Execute request at cursor |
| `:PosteEnv [name]` | Switch or show current environment |
| `:PostePasteCurl` | Paste curl from clipboard |
| `:PosteCopyAsCurl` | Copy request as curl |
| `:PosteCmpStatus` | Show HTTP completion status |
| `:PosteSQLCmpStatus` | Show SQL completion status |
| `:PosteImport ` | Import data from CSV/JSON file into dataset |
| `:PosteExport {csv\|json\|sql}` | Export current dataset |

## Configuration

```lua
require("poste").setup({
-- Binary path (default: stdpath("data")/poste/bin/poste)
poste_binary = vim.fn.stdpath("data") .. "/poste/bin/poste",

-- Default environment
default_env = "dev",

-- Response window
split_direction = "vertical", -- "vertical" | "horizontal"
split_size = 80, -- columns (vertical) or rows (horizontal)

-- Log file (set to "" to disable)
log_file = vim.fn.stdpath("cache") .. "/poste.log",

-- Customize keymaps — set to false to disable
keymaps = {
source_buffer = {
run = "",
jump_next = "]]",
jump_prev = "[[",
goto_definition = "gd",
goto_references = "grr",
quickfix_next = "]q",
quickfix_prev = "[q",
paste_curl = "rp",
copy_as_curl = "rc",
show_symbols = "gs",
},
http_response = {
close = "q",
view_body = "B",
view_verbose = "I",
view_assertions = "A",
view_script_logs = "S",
next_tab = "",
prev_tab = "",
},
sql_source = {
run = "",
show_ddl = "K",
clear_filter = "cr",
toggle_db_browser = "db",
trigger_completion = "",
},
sql_dataset = {
close = "q",
move_left = "h", move_down = "j", move_up = "k", move_right = "l",
prev_page = "H", next_page = "L",
first_col = "0", last_col = "$",
first_row = "gg", last_row = "G",
preview_cell = "K",
yank_cell = "yy", yank_column = "yc",
sort_column = "s",
toggle_cell_highlight = "zh",
toggle_header_float = "zH",
toggle_row_numbers = "zN",
toggle_raw_mode = "gp",
next_tab = "", prev_tab = "",
rerun = "R",
goto_first_page = "hh", goto_last_page = "ll",
toggle_pagination = "pa",
find_column = "fc", filter_by_cell = "ce",
show_search = "/", clear_filter_search = "cr",
next_search = "n", prev_search = "N",
-- Editing
edit_insert = "i",
edit_append = "a",
edit_delete_row = "dd",
edit_insert_row_above = "O",
edit_insert_row_below = "o",
edit_undo = "u",
edit_commit = "w",
-- Export
export_csv = "ec",
export_json = "ej",
export_sql = "es",
},
sql_table_ops = {
select_all = "ma",
refresh_all = "mr",
describe_all = "md",
toggle_menu = "mt",
},
db_browser = {
toggle_node = "",
context_menu = "x",
refresh_node = "r",
search_filter = "/",
select_query = "s",
describe_query = "d",
close = "q",
},
introspect_float = {
close = "q",
close_alt = "",
},
},

-- Override highlight group colors
highlights = {
-- Example: change HTTP method colors
-- PosteMethodGET = { fg = "#00ff00", bold = true },
-- PosteMethodPOST = { fg = "#ffff00", bold = true },
-- PosteMethodDELETE = { fg = "#ff0000", bold = true },
--
-- Example: customize SQL dataset look
-- PosteSqlHeader = { fg = "#ff8800", bold = true },
-- PosteSqlCellSelected = { bg = "#334455", fg = "#ffffff", bold = true },
},
})
```

Full list of highlight groups you can override: `PosteLatency`, `PosteSpinner`, `PosteSuccess`, `PosteError`, `PosteSeparator`, `PosteRequestName`, `PosteVarRef`, `PosteMagicVar`, `PosteMethodGET[...]`

## Completion

Poste provides context-aware completions.

### HTTP (`.http`/`.rest`)

- **HTTP methods** — `GET`, `POST`, `PUT`, `DELETE`, etc.
- **Header names** — `Content-Type`, `Authorization`, `Accept-Encoding`, etc.
- **Header values** — `application/json`, `Bearer `, `gzip`, etc.
- **Variables / env vars** — `{{...}}` references from env.json

Works with both **nvim-cmp** and **blink.cmp**. Registration is automatic.

### SQL (`.sql`/`.sqlite`)

- **SQL keywords** — `SELECT`, `FROM`, `WHERE`, `JOIN`, etc.
- **Tables, columns, schemas** — introspected from your database
- **Functions** — aggregate and scalar functions per dialect
- **Connection-aware** — completions reflect the actual schema

Requires **blink.cmp**. Auto-registers as `poste_sql` source provider.

```vim
:PosteCmpStatus " HTTP completion status
:PosteSQLCmpStatus " SQL completion status
```

## SQL Features

### Connection management

Connections are defined in `connections.json` (walked up from the SQL file). Reference them in your `.sql` files:

```sql
-- @connection pg-dev
-- @connection my-blog
```

The `USE database;` statement switches the active database for parsing/completion context.

### Dataset buffer

Query results render in a rich dataset buffer with:
- **Cell navigation** — hjkl to move between cells
- **Sorting** — press `s` on any column
- **Search & filter** — `/` for search, `ce` to filter by cell value
- **Pagination** — configurable page size, `pa` to toggle
- **Multi-result tabs** — each statement gets its own tab, ``/`` to switch
- **Raw mode** — `gp` to toggle compact view

### Dataset editing

Inline editing directly in the dataset buffer:
- **Enter edit mode** — `i` to insert before cursor, `a` to append after
- **Edit cells** — Type to modify, `` to exit edit, `` to confirm
- **Manage rows** — `dd` to delete, `o`/`O` to insert below/above
- **Undo changes** — `u` to undo edits (before commit)
- **Generate & commit DML** — `w` or `:W` to auto-generate UPDATE/INSERT/DELETE statements and execute with transaction

### DB Browser

Press `db` in a SQL file to open the database tree browser. Navigate schemas, tables, and columns. Press `s` to generate a `SELECT *` query or `d` for `DESCRIBE`.

### Data import/export

**Export current dataset:**
- `ec` — CSV (RFC 4180 compliant)
- `ej` — JSON (array of objects)
- `es` — SQL INSERT statements (dialect-aware)

**Import data:**
- `:PosteImport ` — Load CSV/JSON data into a new result tab

### SQL Integration Tests

```bash
# Start test databases (PG 16 on 15432, MySQL 8.0 on 13306)
cd tests/sql && docker compose up -d

# Run queries
cargo run -- run tests/sql/queries/postgres.sql --line 4 --env dev

# Run Lua tests
tests/run.sh
```

## CLI

```bash
# Execute a specific request by line number
poste run requests/api.http --line 4 --env dev

# Introspect database schema
poste introspect --connection pg-dev --env dev

# List available connections
poste connection list --env dev
```

## Architecture

```
poste/
├── crates/
│ ├── poste-core/ # Request parsing, SQL parsing, env management (no I/O)
│ ├── poste-exec/ # Protocol execution, SQL connection/dialect, response
│ └── poste-cli/ # CLI binary (poste run / connection / introspect)
├── lua/
│ └── poste/
│ ├── http/ # HTTP protocol handling
│ └── sql/ # SQL protocol handling (buffer, editor, export, import, etc.)
└── tests/
├── run.sh # Lua tests
└── sql/ # Docker Compose + SQL integration tests
```

## Development Status

**Progress: 34/38 steps completed** (~90%)

| Phase | Description | Status |
|-------|-------------|--------|
| **1A** | Rust infrastructure | ✅ Complete |
| **1B** | Lua dataset panel | ✅ Complete |
| **1C** | MySQL/SQLite executors | ✅ Complete |
| **2** | Connection & context management | ✅ Complete |
| **3** | DB structure browser | ✅ Complete |
| **4** | Table operations + DDL + completion | ✅ Complete |
| **5** | Import/export + pagination | ✅ Complete |
| **6** | Advanced features (editor, transactions) | ✅ Complete |

**Tests:** 300+ passing (230 Rust + 70 Lua)

## License

MIT