Migrations
Generate and apply PostgreSQL migrations from your TypeScript schema.
KuraDB uses a schema-first migration workflow. You define tables in src/schema.ts, generate named SQL migration files, review them, and apply them from either the txAdmin console or the standalone CLI bundled in the release zip.
The same schema definition also drives the generated Lua ORM metadata under kura.db.tables.
Workflow
Define your schema
Edit src/schema.ts to add or modify tables:
export const users = defineTable('public', 'users', {
id: defineColumn('id', 'uuid', { primaryKey: true }),
username: defineColumn('username', 'string'),
createdAt: defineColumn('created_at', 'date', { defaultExpression: 'NOW()' }),
});Generate migrations
Run from the txAdmin console or from the extracted kuradb release directory:
kuradb generateOr give the migration a custom name:
kuradb generate add_users_tableIf you only want to refresh lib/schema.generated.lua without creating a migration:
kuradb generate --types-onlyThis updates:
migrations/0000_<name>.sqlmigrations/meta/_journal.jsonmigrations/meta/0000_snapshot.jsonlib/schema.generated.lua
✓ Generated migration: migrations/0000_init_users.sql
✓ Updated journal: migrations/meta/_journal.json
✓ Generated Lua types: lib/schema.generated.lua
✓ Schema generated: 3 tables ready
Run "kuradb migrate" to apply pending migration filesReview the SQL
Open the generated migration file and inspect it:
-- Auto-generated by kuradb
-- Tag: init_users
-- Generated at: 2026-04-22T12:00:00.000Z
CREATE TABLE IF NOT EXISTS "public"."users" (
"id" UUID PRIMARY KEY,
"username" VARCHAR(255) NOT NULL,
"created_at" TIMESTAMP NOT NULL DEFAULT NOW()
);Always review
Review generated SQL before applying it, especially in production. You can edit the generated .sql file to add ALTER TABLE statements or adjust anything the generator does not cover.
Apply migrations
kuradb migrateApplying 3 migration file(s)...
✓ Applied 0000_init_users.sql
✓ Applied 0001_add_posts.sql
✓ Applied 0002_add_comments.sql
✓ Updated Lua types
✓ Migration completeIf a migration fails, remaining migrations are skipped and the error is printed.
For the standalone CLI, set KURADB_CONNECTION_STRING first:
KURADB_CONNECTION_STRING="postgres://user:password@localhost:5432/fivem" kuradb migrateGenerated files
migrations/0000_<name>.sql
Plain SQL for a single migration. Safe to edit before running kuradb migrate.
migrations/meta/_journal.json
Tracks migration order and schema snapshots.
public.__kuradb_migrations
Applied migrations are tracked in PostgreSQL so the state survives resource restarts:
SELECT "id", "tag", "applied_at"
FROM "public"."__kuradb_migrations"
ORDER BY "applied_at" ASC;lib/schema.generated.lua
This is the generated Lua ORM metadata. It now includes:
- row / insert / update types
- generated tables under
kura.db.tables - string column maps under
table.columns - richer column refs under
table.columnRefs - direct aliases such as
users.idandusers.createdAtwhen the field name is safe
Excerpt:
---@class UsersColumns
---@field id KuraDBColumnRef<string>
---@field createdAt KuraDBColumnRef<number>
---@class UsersTable : KuraDBTable<UsersRow, UsersInsert, UsersUpdate>
---@field columnRefs UsersColumns
---@field id KuraDBColumnRef<string>
---@field createdAt KuraDBColumnRef<number>
local users = kura.db.tables.users
users.columns.createdAt -- "created_at"
users.columnRefs.createdAt.sqlName -- "created_at"
users.createdAt -- generated column refUse the generated metadata for autocomplete:
local users = kura.db.tables.users
local rows = kura.db.select({ users.id, users.createdAt })
:from(users)
:await()
print(rows[1].createdAt)The concrete table names under kura.db.tables come from your own schema.ts. If your schema exports characters and vehicles, those are the generated Lua tables you will see.
Listening for migrations
Other resources can react when migrations are applied:
AddEventHandler('kuradb:schemaMigrated', function(schema)
print('Schema updated')
end)Tips
- Always run
kuradb generatebeforekuradb migrate - Use
kuradb generate --types-onlywhen you only need fresh Lua types from the schema - Review generated SQL before applying it
- Applied migrations are tracked in
public.__kuradb_migrations - Lua types and generated table refs are regenerated on both
generateandmigrate - No resource restart is needed between
generateandmigrate