SQLite-backed key-value store and persistent objects for Neovim
Inspired by my friends at freestyle, and by Cloudflare Durable Objects.
- Introduction
- 🚀 Features
- 🛠️ Installation
- 📖 Usage
- 🔧 Configuration
- 💡 Examples
- 🛣️ Roadmap
- 🤝 Contributing
- 📝 License
- 🙏 Acknowledgments
- 🐞 Issues and Support
durable.nvim
brings the power of persistent storage to your Neovim environment. By leveraging SQLite, it allows you to store and retrieve data across Neovim sessions effortlessly. Ideal for plugin developers and users who need a simple yet robust way to maintain state, cache data, or manage complex objects over time.
- ⚡ SQLite-backed key-value store: Fast and reliable data storage using SQLite.
- 💾 Persistent objects: Store Lua tables and objects persistently.
- 🛠️ Easy API: Simple functions to get you started quickly.
- 🪶 Lightweight: Minimal dependencies and overhead.
- 🔧 Customizable: Configure storage paths and settings.
- Neovim 0.10 or higher
- sqlite.lua
Using lazy.nvim:
{
"willothy/durable.nvim",
config = true,
}
durable.nvim
provides a simple API for key-value storage.
Keys should always be strings, but multiple value types are supported. durable.nvim
tracks
value types to provide type-safety between Lua and SQLite.
Supported types are string
, number
, boolean
, table
(json), and nil
.
Setting a value
local durable = require('durable')
local kv = durable.kv
-- Set a value
kv.set('theme', 'gruvbox')
Getting a value
-- Get a value
local theme = kv.get('theme') -- returns 'gruvbox'
Deleting a key
-- Delete a key
kv.delete('theme')
By default all operations happen in a global namespace, but all functions accept a namespace parameter which provides scoping/isolaiton for plugins and other use cases.
kv.set('enable_my_plugin', true, "my_plugin")
Store complex Lua tables, including nested tables and complex state.
Storing an object
---@class PersistentCounter
---@field count number
local PersistentCounter = {}
function PersistentCounter.new()
return {
count = 0
}
end
function PersistentCounter:increment()
self.count = self.count + 1
end
function PersistentCounter:decrement()
self.count = self.count - 1
end
-- state is automatically persistent across sessions using the given id,
-- in this case "counter"
local counter = durable.persist("counter", PersistentCounter)
counter:increment()
Customize the plugin by setting variables in your init.lua
or init.vim
.
require('durable').setup({
db_path = vim.fn.stdpath('data') .. '/databases/durable.db',
})
local http = require('socket.http')
local function get_data()
local cached = kv.get('api_response', "my_api_cache")
if cached then
return cached
else
local response = http.request('http://api.example.com/data')
kv.set('api_response', response, "my_api_cache")
return response
end
end
vim.print(get_data())
-- Save window layout or other state information
kv.set('window_state', vim.fn.getwininfo())
-- Later, restore the state
local window_state = kv.get('window_state')
-- Use vim.fn.winrestview(window_state) or similar functions
- Persistent objects (in progress)
- Add support for transactions
- Implement TTL (Time to Live) for keys
- Support for custom serialization methods
- Performance optimizations
See the open issues for a full list of proposed features (and known issues).
Contributions are what make the open-source community such an amazing place to be learn, inspire, and create. Any contributions you make are greatly appreciated.
- Fork the project.
- Create your feature branch (
git checkout -b feature/AmazingFeature
). - Commit your changes (
git commit -m 'Add some AmazingFeature'
). - Push to the branch (
git push origin feature/AmazingFeature
). - Open a pull request.
Please make sure to update tests as appropriate.
Distributed under the MIT License. See LICENSE for more information.
- Neovim Lua API
- sqlite.lua - SQLite/LuaJIT binding for Lua and Neovim
If you encounter any issues or have questions, feel free to open an issue on GitHub.