Defining Schema
You can define FumaDB schema similar to Drizzle ORM.
Table Definition
Use table(name, columns)
to define a table. Columns are defined as an object, where each key is the column name.
import { table, column, idColumn } from "fumadb/schema";
const users = table("users", {
id: idColumn("id", "varchar(255)", { default: "auto" }),
name: column("name", "string"),
email: column("email", "string", { nullable: true }),
});
Columns
The first argument is database name.
column("content", "varchar(200)");
While FumaDB uses column name to interact with ORMs and MongoDB, database name defines the underlying name for SQL database.
You can mark columns nullable:
column("email", "string", { nullable: true });
The default
option sets a default value:
column("email", "string", {
nullable: true,
// Literal Value
default: {
value: "foo",
},
// special values
default: "now",
});
Unique Constraint
Define a unique constraint, it allows duplicated null values even for MongoDB.
column("email", "string", { nullable: true, unique: true });
ID Columns
You can have only one ID column per table, its type can be:
varchar(n)
, (recommended:varchar(255)
).
For ID columns, you can define auto-generated ID columns with default set to auto
.
FumaDB will generate it using CUID or database's built-in function.
Why no multiple ID columns?
This is because MongoDB doesn't support composable primary keys.
Relations
Relations are defined in the relations
field of the schema.
import { schema } from "fumadb/schema";
export const v1 = schema({
version: "1.0.0",
tables: { users, posts },
relations: {
users: ({ many }) => ({
// implicit
posts: many("posts"),
}),
posts: ({ one }) => ({
author: one("users", ["user", "id"]).foreignKey({
// you can define actions for `onDelete` and `onUpdate`
}),
}),
},
});
Additionally, you can call imply()
to disambiguate relations.
import { schema } from "fumadb/schema";
export const v1 = schema({
version: "1.0.0",
tables: { users, posts },
relations: {
users: ({ many }) => ({
posts: many("posts"),
}),
posts: ({ one }) => ({
author: one("users", ["user", "id"]).foreignKey().imply("posts"),
}),
},
});
one(targetTable, ...[field, reference])
: Defines a one-to-one or many-to-one explicit relation.
For each explicit relation, you can declare an implicit relation in the referenced table.
one(targetTable)
: Defines a one-to-one implicit relation.many(targetTable)
: Defines a one-to-many implicit relation.
Foreign key required
For explicit relations, .foreignKey()
is required due to the limitations of
Prisma.
Schema Variant
You can create schema variant based on another schema, useful for extending existing schemas.
import { schema, table, column, idColumn, variantSchema } from "fumadb/schema";
export const v1 = schema({
version: "1.0.0",
tables: {
users: table("users", {
id: idColumn("id", "varchar(255)", { default: "auto" }),
name: column("name", "string"),
}),
},
});
export const v1WithAdmin = variantSchema("with-admin", v1, {
tables: {
admin: table("admin", {
id: idColumn("id", "varchar(255)"),
}),
// additionally, you can disable tables
users: false,
// or replace them
users: table("users", {
id: idColumn("id", "varchar(255)", { default: "auto" }),
email: column("email", "string"),
}),
},
});
The schema will be available as 1.0.0-with-admin
, consumer to choose to use it instead of 1.0.0
.