Database
Code generation
Generate typed database imports and browser functions from your schema.
On this page
Run hulla-db generate to create typed imports from your schema and function declarations. Server code gets database builders, and browser code gets functions it can call without importing server handlers.
Generation requires Bun and TypeScript 7.0.2. If they aren’t installed yet, follow installation.
bun --bun hulla-db generateA successful run prints Generated database entrypoints. By default, it reads db.config.ts, loads db/schema.ts, and discovers query and mutation declarations beside the schema.
On a first run with no declarations, it creates the constructors you’ll use to write them.
Choose the module for where the importing file runs. These paths start at the project root; adjust them from nested files.
| You want to | Import |
|---|---|
| Declare queries and mutations | ./db/_generated/functions |
| Read or write directly on the server | ./db/_generated/server |
Call functions from db/tasks.ts in a browser | ./db/_generated/client/tasks |
| Configure browser auth and connection settings | ./db/_generated/client/runtime |
| Refer to tables and fields | ./db/_generated/tables |
| Type rows, inserts, patches, and IDs | ./db/_generated/types |
Browser modules contain calling code and contracts. They do not ship server handlers to the browser. Generated worker files are service artifacts, not application entrypoints.
When to use a package import
Use @hulla/db/schema to define storage and @hulla/db/config for connection and service settings. The package root supplies shared helpers such as Input, Output, and DatabaseError.
For schema-typed query and mutation constructors, import _generated/functions instead of the package root.
Export a query(...) or mutation(...) declaration to make it callable. Ordinary exported functions remain helpers, even when a declaration imports them. Declarations derived with .extend(...) are discovered too.
Nested modules keep their relative paths:
db/tasks.ts → db/_generated/client/tasks.ts
db/admin/reports.ts → db/_generated/client/admin/reports.tsYou don’t need a manual function registry or another api.ts file. Keep the schema, config, helpers, and generated files out of blanket declaration re-exports.
Use a different source directory
Only set functions when discovery needs to start somewhere other than beside the schema:
import { defineConfig } from '@hulla/db/config'
export default defineConfig({
database: {
server: { url: process.env.DATABASE_URL! },
client: { url: 'http://localhost:3001', credentials: 'include' },
},
schema: 'data/schema.ts',
functions: 'data/functions',
})Paths resolve relative to the config. Generated output stays beside the resolved schema in _generated/.
bun --bun hulla-db devThe watcher regenerates code and restarts the service when source files change.
Generation evaluates your trusted schema and declaration modules. Keep database calls and request-specific work inside handlers, rather than at module initialization. Unsupported handler imports produce a diagnostic.
Generate during your build:
bun --bun hulla-db generateThen start the service from the prepared artifacts:
node node_modules/@hulla/db/dist/cli.js serveserve loads the existing output under Node. It does not run generation or start a watcher. Deploy the config, schema, generated files, runtime dependencies, and native assets together.
Generated files have ownership headers. Keep application code outside _generated/ and leave generated files unedited; the generator protects authored files and removes only its own obsolete output.
See the reference for lower-level generation APIs. Most applications only need the commands on this page.