Skip to main content

Intro

Kikko allows you to run reactive SQLite queries on any platforms with any framework/lib. For the web apps it uses absurd-sql, for electron/react-native/ionic — native sqlite calls. It is actually lib-agnostic, so you can integrate it to any framework/render libs you want.

Actually, what kikko is:

  1. Correct transaction handling, with transaction and queries queue
  2. Middlewares api, to intercept all running queries
  3. Built-in profiler

And it also require db backend that should implement required interface. Other things, like reactivePlugin or migrationPlugin, are optional.

Features

Kikko
⚖️ Tiny size< 15kb size in gzip for @kikko-land/react!
📱 Wide platforms supportWeb, mobile(react-native, expo, cordova, ionic), desktop(electron, tauri).
🧰 Lib-agnosticUse with React, Vue, Svelte (WIP), Angular (WIP) or any other lib/framework you want.
🐛 Easy to debugKikko colorize queries, so, for example, you can easily understand to which transaction query belongs. He also meausures preparation, transfer and execution time.
🔐 Secured by defaultWith template literals, all vars that are used will be automatically marked as prepared statement variable that reduce chances of SQL injections a lot.
🛠 Plugin systemAllows you to integrate your own code on query/transaction run.
👯 Multi-tab support for webInsert row in one tab, and your data will be updated in the other.

Simple React component example

import {
makeId,
sql,
useDbQuery,
useFirstRowDbQuery,
useRunDbQuery,
} from "@kikko-land/react";

type Note = { id: string; title: string };
const notesTable = sql.table`notes`;

export const Notes = () => {
const notes = useDbQuery<Note>(sql`SELECT * FROM ${notesTable}`);
const notesCount = useFirstRowDbQuery<{ count: number }>(
sql`SELECT COUNT(*) FROM ${notesTable}`
);

const [addNote, addNoteState] = useRunDbQuery((db) => async () => {
const id = makeId();

await db.runQuery(
sql`INSERT INTO ${notesTable}(id, title) VALUES(${id}, ${`Note#${id}`})`
);
});

return (
<>
<button
onClick={addNote}
disabled={
addNoteState.type === "running" || addNoteState.type === "waitingDb"
}
>
Add note
</button>
<div>Add note result: {JSON.stringify(addNoteState)}</div>
<div>Query result (total notes count: {notesCount.data?.count})</div>
<pre>{JSON.stringify(notes)}</pre>
</>
);
};

Supported platforms

PlatformUsesPackageExampleDoc
Vite + React@kikko-land/better-absurd-sql@kikko-land/absurd-web-backendLinkLink
Tauri + Vite + Vuetauri-plugin-sqlite@kikko-land/tauri-backendLinkLink
Create-react-app@kikko-land/better-absurd-sql@kikko-land/absurd-web-backendLinkLink
Expo@kikko-land/better-absurd-sql for web, expo SQLite for native@kikko-land/absurd-web-backend
@kikko-land/native-expo-backend
LinkLink
Electronbetter-sqlite3@kikko-land/electron-better-sqlite3-backendLinkLink
Ionic@awesome-cordova-plugins/sqlite@kikko-land/absurd-web-backend
@kikko-land/native-ionic-backend
LinkLink
React Nativereact-native-sqlite-storage@kikko-land/react-native-backendLinkLink
Cloudflare D1Cloudflare D1@kikko-land/d1-backendLinkLink