FrontierJS

Litestone

Data · Model@frontierjs/litestone

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.

model Invoice {
  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 WHERE ownerId = ?

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.

Replaces

manual redaction helpersfield-encryption libraries

Lifecycle

Defaults · transforms · @updatedAt · soft delete

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.

email     String     
updatedAt DateTime 
deletedAt DateTime?          // soft delete

Replaces

ORM lifecycle hooksparanoid / soft-delete plugins

Audit

@@trail(audit), per model

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.

Replaces

audit-trail librariesdatabase triggerstemporal tables

Querying

Relations · cursor pagination · transactions · $raw

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.

await db.invoice.findMany({
  where:   { total: { gte: 500 }, owner: { is: { active: true } } },
  orderBy: { createdAt: 'desc' },
  cursor:  { id: 120 },
  take:    20,
})

Replaces

KnexKyselyraw SQL scattered in handlers

Multi-db

@@db(name) · database-per-tenant registries

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.

Replaces

manual connection routingper-tenant connection pools

External

@@external mirrors tables you don't 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.

$ fli db:migrate
  + ALTER TABLE invoices ADD COLUMN company TEXT
  ✓ migrations/0002_company.sql applied

$ fli db:status
  ✓ live database matches the schema

Replaces

Prisma MigrateKnex migrationsFlywayhand-written SQL

Generates

TypeScript declarations · JSON Schema

The same file emits types for your editor and JSON Schema for validation and the browser — so the three can never describe different shapes.

$ litestone types ./types.d.ts =client

interface Invoice       { id: number; total: number }
interface InvoiceCreate { total: number }

Replaces

openapi-typescriptzod-to-tsorvalhand-written types

Tooling

Litestone Studio · REPL · doctor · seed · backup

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.

Replaces

Prisma StudioTablePlusad-hoc scripts