Skip to content

Getting Started

Welcome to Sleet ORM! This guide will help you get up and running with Sleet in just a few minutes.

What is Sleet ORM?

Sleet brings the schema-as-code philosophy of Drizzle ORM to FiveM's Lua scripting environment. Define your tables once in Lua, get type-safe queries with zero raw SQL strings.

Key Features

  • Schema as code — define tables in Lua, not SQL strings
  • Chainable query builder — SELECT / INSERT / UPDATE / DELETE with fluent dot-notation chaining
  • Full type inference — after running sleet generate, LuaLS infers XxxRecord[] from .execute() without any manual ---@type
  • Column comments.comment('description') propagates to IDE hover hints and SQL COMMENT clauses
  • Safe by default — all values use parameterized ? placeholders; SQL injection is impossible
  • Transparent — every query has a .toSQL() debug method
  • Raw SQL escape hatchsl.sql() for expressions like COUNT(*), atomic increments, etc.
  • Zero runtime dependencies — only requires oxmysql

Prerequisites

  • FiveM server
  • oxmysql resource
  • Basic knowledge of Lua and SQL

Installation

1. Download Sleet

bash
git clone https://github.com/SleetCo/sleet-orm [sleet]/sleet

2. Configure server.cfg

cfg
ensure oxmysql
ensure your_sleet_user_resource

3. Your resource's fxmanifest.lua

lua
fx_version 'cerulean'
game 'gta5'

server_scripts {
    '@oxmysql/lib/MySQL.lua',
    '@sleet/sleet.lua',    -- injects global `Sleet` + installs package/require shim
    'server/main.lua',     -- use require 'server.schema' inside scripts
}

Your First Schema

Create a schema file to define your database structure:

lua
-- server/schema.lua
local sl = Sleet  -- global injected by @sleet/sleet.lua

local players = sl.table('players', {
    id         = sl.serial().primaryKey().comment('Auto-increment player ID'),
    identifier = sl.varchar(64).notNull().unique().comment('Steam / Discord identifier'),
    name       = sl.varchar(255).notNull().comment('Player display name'),
    money      = sl.int().default(500).comment('Cash on hand'),
    bank       = sl.int().default(2500).comment('Bank balance'),
    is_admin   = sl.boolean().default(false).comment('Admin flag'),
    metadata   = sl.json().comment('Extended data'),
    last_seen  = sl.timestamp().defaultNow().comment('Last online'),
})

-- Return the module — loaded via require 'server.schema' from other scripts
return { players = players }

Your First Queries

Now you can use your schema to perform database operations:

lua
-- server/main.lua
local sl = Sleet
local s  = require 'server.schema'
local db = sl.connect()

-- SELECT — LuaLS infers PlayersRecord[] automatically after running `sleet generate`
local rows = db.select()
    .from(s.players)
    .where(sl.eq(s.players.identifier, identifier))
    .limit(1)
    .execute()

local player = rows[1]  -- player: PlayersRecord ✓

-- INSERT — returns insertId
local newId = db.insert(s.players)
    .values({ identifier = 'steam:xxx', name = GetPlayerName(source) })
    .execute()

-- UPDATE — returns rowsChanged
db.update(s.players)
    .set({ money = sl.sql('`money` + 500') })
    .where(sl.eq(s.players.id, player.id))
    .execute()

-- DELETE
db.delete(s.players)
    .where(sl.eq(s.players.id, newId))
    .execute()

Enable Type Inference

To get full type inference support:

  1. Install the CLI tool (see CLI documentation)
  2. Generate types:
    bash
    sleet generate server/schema.lua
    # → .sleet/types.lua
  3. Configure LuaLS to include the generated types

After this setup, you'll get complete type safety and IntelliSense support!

What's Next?

Need Help?

Released under the MIT License.