LightningDB is made up of a server and client library.
Typically LightningDB would be installed in a monorepo, with a folder for the server and a folder for the client. However you are free to disregard this.
See a working demo at https://github.com/lightningdatabase/lightning-demo.
We start by setting up the server. This includes the database schema, which is used to automatically generate the interface and client.
LightningDB is built on top of Zenstack, which is built on top of Prisma.
The easiest way to install ZenStack is to use the zenstack init command. In an existing TypeScript project folder, run the following command:
npx zenstack@latest init
The "init" command does the following things for you:
- Install Prisma if it's not already installed.
- Install the zenstack CLI package as a dev dependency.
- Install the @zenstackhq/runtime package - used for enhancing PrismaClient at the runtime.
- Copy the prisma/schema.prisma file to schema.zmodel if it exists; otherwise, create a new template schema.zmodel file.
You can always manually complete the steps above if you have a special project setup that the "init" command doesn't work with.
After the initialization, please remember that you should edit the schema.zmodel moving forward. The prisma/schema.prisma file will be automatically regenerated when you run zenstack generate.
LightningDB uses Postgres, to switch Prisma change the datasource to:
datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
}
Install the required packages
npm install @lightningdb/server @lightningdb/plugin
Edit the schema.zmodel file and add the plugin section
//schema.zmodel
...
plugin lightning {
provider = '@lightningdb/plugin'
}
...
You can now run the plugin to generate the server code
npx zenstack generate
LightningDB sends updates over a websocket.
See below for a sample express implementation with the websocket handler.
//index.ts
import dotenv from "dotenv";
dotenv.config();
import express from "express";
import { WebSocketServer } from "ws";
import http from "http";
import "@lightningdb/server/replication";
import handler from "@lightningdb/server";
const app = express();
app.use(express.json());
const server = http.createServer(app);
const wss = new WebSocketServer({ server });
wss.on("connection", handler);
server.listen(3000, () =>
console.log(`🚀 Server ready at: http://localhost:3000`)
);
LightningDB connects to the Postgres database and uses replication to catch any changes and update the frontend. This is achieved with the import "@lightningdb/server/src/replication"
import.
Run the following sql to setup a replication slot:
SELECT * FROM pg_create_logical_replication_slot('lightningdb_slot', 'wal2json');
The default name is "lightningdb_slot", however you can set the name with the
REPLICATION_SLOT
environment variable.
In the frontend project run:
npm install @lightningdb/client
Edit the schema.zmodel file and update the plugin section to add the path to the frontend project
//schema.zmodel
...
plugin lightning {
provider = '@lightningdb/plugin'
clientPath = '../client'
}
...
Run npx zenstack generate
to generate the frontend code.
Render a <DBProvider>
around your applciation:
import { StrictMode } from "react"
import { createRoot } from "react-dom/client"
import App from "./App.tsx"
import { DBProvider } from "../lightningdb"
createRoot(document.getElementById("root")!).render(
<StrictMode>
<DBProvider url="ws://localhost:3000">
<App />
</DBProvider>
</StrictMode>,
)
It is easy to query the data and LightningDB keeps the frontend up to date automatically.
To query data in a component add:
const { data, loading, error } = useQuery({
users: {},
});
return <pre>{JSON.stringify(data, null, 2)}</pre>;