Use when adding a field to an existing Bknd entity...
Add a new field (column) to an existing entity in Bknd.
bknd-create-entity)npx bknd runhttp://localhost:1337posts)first_name, created_at)Based on field type, configure:
All Types:
Text:
Number:
Enum:
Find your entity in the schema:
const schema = em({
posts: entity("posts", {
title: text().required(),
// Add new fields here
}),
});
Add the new field to the entity's field object:
const schema = em({
posts: entity("posts", {
title: text().required(),
subtitle: text(), // NEW: optional text field
view_count: number(), // NEW: optional number field
}),
});
Bknd auto-syncs schema on startup. Restart your server to apply changes.
import { text } from "bknd";
entity("users", {
// Basic optional text
bio: text(),
// Required text
email: text().required(),
// Unique constraint
username: text().unique(),
// With validation
slug: text({
minLength: 3,
maxLength: 100,
pattern: "^[a-z0-9-]+$",
}).required(),
// With default value
status: text({ default_value: "active" }),
})
import { number } from "bknd";
entity("products", {
// Basic number
quantity: number(),
// Required with validation
price: number({
minimum: 0,
maximum: 99999.99,
}).required(),
// Integer only (multipleOf: 1)
rating: number({
minimum: 1,
maximum: 5,
multipleOf: 1,
}),
})
import { boolean } from "bknd";
entity("posts", {
// Defaults to false
published: boolean(),
// Default true
active: boolean({ default_value: true }),
})
import { date } from "bknd";
entity("events", {
// Basic date
start_date: date().required(),
// Auto-set to current time
created_at: date({ default_value: "now" }),
})
Note: Import is enumm (double 'm') to avoid JS reserved word.
import { enumm } from "bknd";
entity("posts", {
// Array syntax
status: enumm({
enum: ["draft", "published", "archived"],
default_value: "draft",
}).required(),
// Object syntax (key-value)
priority: enumm({
enum: {
LOW: "low",
MEDIUM: "medium",
HIGH: "high",
},
default_value: "MEDIUM",
}),
})
import { json } from "bknd";
entity("users", {
// Untyped JSON
metadata: json(),
// Typed JSON (TypeScript only, no runtime validation)
preferences: json<{
theme: "light" | "dark";
notifications: boolean;
}>(),
// With default
tags: json<string[]>({ default_value: [] }),
})
For runtime-validated JSON:
import { jsonschema } from "bknd";
entity("webhooks", {
payload: jsonschema({
type: "object",
properties: {
event: { type: "string" },
timestamp: { type: "number" },
},
required: ["event", "timestamp"],
}),
})
For file attachments:
import { media } from "bknd";
entity("posts", {
// Single file
cover_image: media({ entity: "posts" }),
// Multiple files with constraints
gallery: media({
entity: "posts",
min_items: 1,
max_items: 10,
mime_types: ["image/jpeg", "image/png", "image/webp"],
}),
})
Chain modifiers after field type:
| Modifier | Description | Example |
|---|---|---|
.required() |
Cannot be null | text().required() |
.unique() |
Unique constraint | text().unique() |
.default(value) |
Default value | text().default("pending") |
.references(target) |
Foreign key | number().references("users.id") |
Chaining example:
entity("users", {
email: text().required().unique(),
role: text().default("user"),
org_id: number().references("organizations.id"),
})
| Convention | Example | Notes |
|---|---|---|
| snake_case | first_name |
NOT firstName |
| Lowercase | created_at |
NOT CreatedAt |
| Descriptive | published_at |
NOT pub |
Error: Field "title" already exists on entity "posts"
Fix: Each field name must be unique within an entity. Choose a different name.
Error: Invalid field name
Fix: Use lowercase letters, numbers, and underscores. Must start with letter.
// Valid
title: text()
first_name: text()
item_2: text()
// Invalid
Title: text() // No uppercase
2_item: text() // Can't start with number
first-name: text() // No hyphens
Error: enum is a reserved word
Fix: Import and use enumm (double 'm'):
// Wrong
import { enum } from "bknd";
// Correct
import { enumm } from "bknd";
status: enumm({ enum: ["a", "b"] })
Problem: Adding .required() to field on entity with existing null values.
Fix: Either:
text({ default_value: "N/A" }).required()Problem: Added field in code but not appearing.
Fixes:
const api = app.getApi();
// Create record with new field
const result = await api.data.createOne("posts", {
title: "Test",
subtitle: "New field test", // Your new field
});
console.log(result);
npx bknd debug paths
# Check entity fields in output
DO:
DON'T:
enum import (use enumm).required() to existing entities without defaultsid is auto-generated)