Setup FumaDB
Setup FumaDB for your package.
Installation
Install it to your package.
npm i fumadb
Node.js
How to Use
FumaDB expects a schema file for each version, create a schema/v1.ts
file:
import { column, idColumn, schema, table } from "fumadb/schema";
const users = table("users", {
id: idColumn("id", "varchar(255)", { default: "auto" }),
name: column("name", "string"),
});
const messages = table("messages", {
id: idColumn("id", "varchar(255)", { default: "auto" }),
user: column("user", "varchar(255)"),
content: column("content", "string"),
});
export const v1 = schema({
version: "1.0.0", // should always start with v1
tables: {
users,
messages,
},
relations: {
users: ({ many }) => ({
messages: many("messages"),
}),
messages: ({ one }) => ({
author: one("users", ["user", "id"]).foreignKey(),
}),
},
});
Create a FumaDB factory, each factory manages the different versions of a schema, with its own versioning cycle:
import { fumadb } from "fumadb";
import { v1 } from "@/schema/v1";
const ChatDB = fumadb({
namespace: "fuma-chat",
schemas: [v1],
});
Please be careful that:
- Once your package is published,
namespace
must not be changed. - Once your package is published, do not change your existing schemas. See Versioning for details.
The consumer can create a FumaDB client using the factory. Then, your library can receive the FumaDB client to perform further actions.
import { ChatDB, myLibrary } from "your-library";
import { kyselyAdapter } from "fumadb/adapters/kysely";
export const client = ChatDB.client(
kyselyAdapter({
provider: "mysql",
db: kysely, // kysely instance
})
);
myLibrary(client);
Querying
On the FumaDB client, you can query using the ORM interface:
import { type InferFumaDB } from "fumadb";
export function myLibrary(db: InferFumaDB<typeof ChatDB>) {
const orm = db.abstract;
return {
async getUser() {
const result = await orm.findFirst("users", {
select: ["name"],
where: (b) => b.and(b.isNotNull("name"), b("id", "=", "test")),
});
return result;
},
};
}
CLI
FumaDB provides a CLI tool with interactive experience to initialize/migrate database, you can wrap it in your library:
import { type InferFumaDB } from "fumadb";
import { createCli } from "fumadb/cli";
import { type ChatDB } from "./db";
export function run(db: InferFumaDB<typeof ChatDB>) {
const { main } = createCli({
db,
command: "chat-lib",
// you can import the version from your package's `package.json`
version: "1.0.0",
});
return main();
}
And suggest the consumer to create a script to start the CLI app.
import { client } from "./lib/chat";
import { run } from "your-library/cli";
void run(client);
The consumer can run it with:
node ./scripts/chat.mjs
Good to Know
When your library updates, you can notify the consumers to migrate their database by hooking postinstall
.
In your library:
{
"scripts": {
"postinstall": "..."
}
}
The content of postinstall
command is up to you (e.g. printing a notification).