Authorization is part of the data definition, not a layer above it.
$ npm i @frontierjs/litestone
Shape
Models · enums · relations · reusable functions
One declarative file describes your data. Functions are reusable expressions you can call from defaults and policies, so logic lives beside the data it governs.
modelInvoice{
id Int
total Float(0)
ownerId Int
owner User(ownerId)}
Replaces
Prisma schemaDrizzle schemaTypeORM entities
Types
Int String Float Bool DateTime Json Bytes
Seven scalars, mapped to SQLite storage classes and to TypeScript. Optionality is a trailing ? and it means the same thing in the database, the API and the editor.
Replaces
Nothing — there is no common equivalent to swap out.
Access
Gates on a 0–9 scale · policies compiled into WHERE
A gate grades each operation against a trust level. A policy is a row predicate compiled into the query itself — so there is no code path that can forget to apply it.
(0.4.4.5)// read.create.update.delete(read,ownerId==auth().id)-- every read becomes:SELECT*FROM invoices WHEREownerId=?
Replaces
CASLOsoPostgres RLShand-rolled middleware
Fields
@guarded · @secret · @encrypted at rest
Field-level protection travels with the field. Guarded fields never leave the data layer, secrets are redacted from logs and responses, and encrypted fields are ciphertext on disk.
What happens automatically over a row's life, declared once. Transforms like @trim and @lower run on the way in, so the database never holds the unnormalized version.
Mark a model and every write is recorded with the actor, the operation and the before/after. No decorator on every mutation, no forgetting the one that matters.
A full query API with nested reads, aggregates, windowing and distinct — plus a documented raw escape hatch for the cases a builder should not try to own.
Route models to separate databases from the schema, and get database-per-tenant isolation from one accessor rather than a connection-juggling layer of your own.
Describe a table another system owns and query it with the same client. Migrations leave it alone, so you get typed reads without claiming responsibility for the schema.
Replaces
a second read-only ORM client
Migrations
Diffed from the schema as reviewable SQL
Change the schema, and the diff against the live database becomes a migration file you read before applying. Drift between file and database is a command, not a surprise.
$flidb:migrate
+ALTERTABLE invoices ADD COLUMN company TEXT✓ migrations/0002_company.sql applied
$flidb:status
✓ live database matches the schema
A local web UI over your data, an interactive shell against the live client, a health check for your setup, and seeding and backup as first-class commands.