FumaDB

Setup FumaDB

Setup FumaDB for your package.

Installation

Install it to your package.

npm i fumadb

Node.js

Node.js 22 or above recommended.

How to Use

FumaDB expects a schema file for each version, create a schema/v1.ts file:

schema/v1.ts
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:

db.ts
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.

lib/chat.ts
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:

index.ts
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:

cli.ts
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.

scripts/chat.mjs
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:

package.json
{
  "scripts": {
    "postinstall": "..."
  }
}

The content of postinstall command is up to you (e.g. printing a notification).