Python async HTTP driver for LioranDB.
This repo implements a Python package that mirrors the API shape of the Node.js driver shown in log.txt (the @liorandb/driver TypeScript driver). The Python version is designed so you can write code that looks almost identical to the TS examples.
- Implemented:
LioranClient,LioranManager,DB,Collection, HTTP auth (JWT + connection-string header), URI parsing (http(s)://,lioran://,liorandb(s)://), and the main database/collection endpoints from the log. - Not a 1:1 clone: the TypeScript
types.tsresponse/DTO typing is not fully replicated (Python returnsdict/list), and the library is async-first (useshttpx.AsyncClient).
If you want strict, fully-typed Python models matching types.ts, tell me and I’ll generate pydantic models for every response type in the log.
pip install liorandb-driverimport asyncio
from liorandb_driver import LioranClient
async def main():
client = LioranClient("lioran://username:password@localhost:4000")
await client.connect()
db = client.db("mydb")
users = db.collection("users")
await users.insertOne({"name": "Ada"})
print(await users.find({}))
await client.aclose()
asyncio.run(main())Use this if you want to call login() manually (or set a token later).
http://host:porthttps://host:port
Example:
client = LioranClient("http://localhost:4000")
auth = await client.login("admin", "password")Same behavior as the TS parseLegacyLioranUri:
lioran://host:port(no creds in URI; you mustlogin()/setToken()later)lioran://username:password@host:port(creds in URI;connect()logs in)
Example:
client = LioranClient("lioran://admin:password@localhost:4000")
await client.connect()Same idea as TS liorandb:// parsing: it stores the full connection string and sends it as a header for auth.
liorandb://username:password@host:port/<database>(defaults port to4000if not provided)liorandbs://...uses HTTPS when building the base URL
Example:
client = LioranClient("liorandb://user:pass@localhost:4000/mydb")
await client.connect() # sets connection-string auth mode
db = client.db("mydb")This library provides snake_case methods and TypeScript-style camelCase aliases so you can keep the same syntax as the Node driver.
Auth/session:
await client.connect()await client.login(username, password)await client.super_admin_login(secret)/await client.superAdminLogin(secret)client.set_token(token)/client.setToken(token)client.set_connection_string(cs)/client.setConnectionString(cs)client.logout()client.is_authenticated()/client.isAuthenticated()await client.aclose()(closes the underlying HTTP client)
User/admin endpoints:
await client.me()await client.register(user_id, username=None, password=None, role="user", external_user_id=None)await client.list_users()/await client.listUsers()await client.issue_user_token(user_id)/await client.issueUserToken(user_id)await client.update_my_cors(origins)/await client.updateMyCors(origins)await client.update_user_cors(user_id, origins)/await client.updateUserCors(user_id, origins)
Info/health/docs:
await client.health()await client.info()await client.list_docs()/await client.listDocs()await client.get_doc(id)/await client.getDoc(id)
Databases:
db = client.db(name)await client.list_databases()/await client.listDatabases()await client.count_databases(user_id=None)/await client.countDatabases(user_id=None)await client.list_user_databases(user_id)/await client.listUserDatabases(user_id)await client.create_database(name, owner_user_id=None)/await client.createDatabase(name, ownerUserId=None)await client.drop_database(name)/await client.dropDatabase(name)await client.database_stats(name)/await client.databaseStats(name)
Maintenance:
await client.maintenance_status()/await client.maintenanceStatus()await client.list_snapshots()/await client.listSnapshots()await client.create_snapshot_now()/await client.createSnapshotNow()await client.compact_all_databases()/await client.compactAllDatabases()
col = db.collection(name)await db.list_collections()/await db.listCollections()await db.create_collection(name)/await db.createCollection(name)await db.drop_collection(name)/await db.dropCollection(name)await db.rename_collection(old, new)/await db.renameCollection(oldName, newName)await db.stats()await db.compact_all()/await db.compactAll()await db.compact_collection(name)/await db.compactCollection(name)await db.create_index(collection, field, unique=False)/await db.createIndex(collection, field, options={"unique": True})await db.list_indexes(collection)/await db.listIndexes(collection)await db.drop_index(collection, field)/await db.dropIndex(collection, field)await db.rebuild_index(collection, field)/await db.rebuildIndex(collection, field)await db.rebuild_indexes(collection)/await db.rebuildIndexes(collection)await db.explain(collection, query={}, options=None)await db.transaction([...])orawait db.transaction(async_fn)(matches the TS “ops or function” pattern)await db.get_credentials()/await db.getCredentials()await db.set_credentials(username, password)/await db.setCredentials({"username": "...", "password": "..."})await db.get_connection_string()/await db.getConnectionString()
await col.insert_one(doc)/await col.insertOne(doc)await col.insert_many(docs)/await col.insertMany(docs)await col.find(filter={}, options=None)await col.find_one(filter={}, options=None)/await col.findOne(filter={}, options=None)await col.update_one(filter, update, options=None)/await col.updateOne(filter, update, options=None)await col.update_many(filter, update)/await col.updateMany(filter, update)await col.delete_one(filter)/await col.deleteOne(filter)await col.delete_many(filter)/await col.deleteMany(filter)await col.count(filter={})await col.count_documents(filter={})/await col.countDocuments(filter={})await col.aggregate(pipeline=[])await col.list_indexes()/await col.listIndexes()await col.create_index(field, unique=False)/await col.createIndex(field, options={"unique": True})await col.drop_index(field)/await col.dropIndex(field)await col.rebuild_index(field)/await col.rebuildIndex(field)await col.rebuild_indexes()/await col.rebuildIndexes()await col.explain(query={}, options=None)await col.stats()await col.compact()
All non-2xx responses raise liorandb_driver.HttpError which includes:
status(HTTP status code)data(parsed JSON if possible, otherwise text)
This repo is set up for PEP 517 builds via pyproject.toml.
python -m pip install -U build twine
python -m build
python -m twine upload dist/*