superapp
ReferenceServer API

createEngine Options

Complete configuration reference.

Chat in Claude

createEngine accepts a single configuration object and returns an engine instance. This page documents every available option.

import { createEngine } from '@superapp/backend'

const engine = createEngine({
  connections: {
    main: 'postgres://localhost:5432/mydb',
  },
})

Top-Level Options

Prop

Type

connections

Each connection maps a name to a database URL or config object. The engine infers the database type from the URL protocol — no explicit type field needed.

connections: {
  main: 'postgres://localhost:5432/mydb',           // postgres
  warehouse: 'mysql://localhost:3306/warehouse',     // mysql
  legacy: './legacy.db',                             // sqlite
  imports: { directory: './data/imports/' },          // csv
}

Type Inference

URL / ConfigInferred Type
postgres://... or postgresql://...PostgreSQL
mysql://...MySQL
File path (.db, .sqlite) or file:...SQLite
libsql://... or Turso URLSQLite (Turso)
{ directory: string }CSV

Examples

// Single Postgres
connections: {
  main: process.env.PG_URL!,
}

// Multiple databases
connections: {
  main: process.env.PG_URL!,
  warehouse: process.env.MYSQL_URL!,
  legacy: './legacy.db',
  imports: { directory: './data/imports/' },
}

permissions

Permission definitions using Drizzle-like syntax. Each permission targets a table, declares which roles have access, and configures operations (select, insert, update, delete) individually.

permissions: {
  view_own_orders: {
    table: 'main.orders',
    roles: ['viewer', 'editor', 'admin'],
    select: {
      columns: ['id', 'amount', 'status', 'created_at'],
      where: { customer_id: { $eq: '$user.customer_id' } },
    },
  },
}

See Permission Object for the complete shape reference.

actions

Typed server-side functions with inline roles. Each action defines its allowed roles directly.

actions: {
  incrementStock: {
    roles: ['warehouse_manager', 'admin'],
    input: z.object({ productId: z.string(), amount: z.number().positive() }),
    output: z.object({ id: z.string(), stock: z.number() }),
    run: async ({ user, db }, { productId, amount }) => {
      const [updated] = await db
        .update(products)
        .set({ stock: sql`stock + ${amount}` })
        .where(eq(products.id, productId))
        .returning({ id: products.id, stock: products.stock })
      return updated
    },
  },
},

See Actions for full documentation.

limits

Query complexity and rate limit constraints to prevent abuse and protect your databases.

Prop

Type

Prop

Type

Prop

Type

limits: {
  maxRows: 5000,              // max rows a query can return
  maxRelationDepth: 2,        // orders → items = depth 2
  maxFilterNesting: 4,        // nested $and/$or/$not levels
  maxFilterConditions: 30,    // total conditions per query
  maxRequestBodySize: '2mb',  // max JSON body size
  queryTimeout: 15_000,       // kill slow queries (ms)
  rateLimitPerUser: 100,      // req/min per user
  rateLimitPerIP: 300,        // req/min per IP
}

audit

Configure audit logging for queries, permission denials, and admin actions.

Prop

Type

Prop

Type

audit: {
  enabled: true,           // turn logging on/off
  logQuery: true,          // log SQL statements
  logParams: false,        // log query params (may contain sensitive data)
  logDuration: true,       // log query time (ms)
  logUser: true,           // log who ran each query
  logDenied: true,         // log permission denials
  logAdminActions: true,   // log admin UI changes
  retention: '90d',        // auto-delete after 90 days
  piiRedaction: true,      // strip emails & phone numbers
}

jwt

JWT verification settings. These configure how the auth provider validates incoming tokens.

Prop

Type

jwt: {
  algorithms: ['RS256', 'ES256'],        // allowed signing algorithms
  issuer: 'https://auth.myapp.com',      // reject tokens from other issuers
  audience: 'https://api.myapp.com',     // reject tokens for other audiences
  clockSkewSeconds: 10,                  // clock drift tolerance (seconds)
}

security

Network security, CORS, and access control settings.

Prop

Type

Prop

Type

security: {
  cors: {
    origin: ['https://myapp.com', 'https://admin.myapp.com'], // allowed origins
    credentials: true,                                         // allow cookies
    maxAge: 86400,                                             // preflight cache (seconds)
  },
  csp: "default-src 'self'; script-src 'self'",  // CSP header for admin UI
  adminIpAllowlist: ['10.0.0.0/8', '192.168.1.0/24'], // restrict /admin access
}

schemaEndpoint

Enable the GET /schema endpoint for schema introspection.

Prop

Type

schemaEndpoint: true // shorthand — enable with defaults

schemaEndpoint: {
  enabled: true,                          // expose GET /schema
  token: process.env.SCHEMA_API_TOKEN,    // require token for access
}

pgWire

Configure the PostgreSQL wire protocol server. When configured, calling engine.startPgWire() starts a TCP server that speaks the PostgreSQL wire protocol.

Prop

Type

Prop

Type

Prop

Type

// Shorthand — enable with defaults (port 5433, trust auth)
pgWire: true

// Full configuration
pgWire: {
  port: 5433,
  auth: { strategy: ['jwt', 'apiKey'] },
  tls: {
    key: fs.readFileSync('server.key'),
    cert: fs.readFileSync('server.crt'),
  },
  serverVersion: '16.3 (superapp)',
}

See PostgreSQL Wire Protocol for usage guide.

Full Example

import { createEngine } from '@superapp/backend'
import { betterAuthProvider } from '@superapp/backend/auth/better-auth'

const engine = createEngine({
  mode: 'programmatic',                              // config in code (or 'interactive')
  superapp_db: process.env.TURSO_URL ?? './superapp.db', // internal tables storage
  masterKey: process.env.SUPERAPP_MASTER_KEY!,       // admin API key (use env var)

  connections: {
    main: process.env.PG_URL!,                       // namespace: main.*
    warehouse: process.env.MYSQL_URL!,               // namespace: warehouse.*
  },

  auth: betterAuthProvider({                         // omit for open mode (no auth)
    secret: process.env.AUTH_SECRET!,
    userTable: {
      table: 'main.users',
      matchOn: { column: 'id', jwtField: 'id' },
      columns: ['id', 'email', 'name'],
    },
  }),

  jwt: {
    algorithms: ['RS256'],                           // allowed signing algorithms
    issuer: 'https://auth.myapp.com',                // reject other issuers
    audience: 'https://api.myapp.com',               // reject other audiences
    clockSkewSeconds: 5,                             // clock drift tolerance
  },

  limits: {
    maxRows: 10_000,              // max rows a query can return
    maxRelationDepth: 3,          // orders → items → product = depth 3
    maxFilterNesting: 5,          // nested $and/$or/$not levels
    maxFilterConditions: 50,      // total conditions per query
    maxRequestBodySize: '1mb',    // max JSON body size
    queryTimeout: 30_000,         // kill slow queries (ms)
    rateLimitPerUser: 200,        // req/min per user
    rateLimitPerIP: 500,          // req/min per IP
  },

  audit: {
    enabled: true,                // turn logging on/off
    logQuery: true,               // log SQL statements
    logParams: false,             // log query params (may contain sensitive data)
    logDuration: true,            // log query time (ms)
    logUser: true,                // log who ran each query
    logDenied: true,              // log permission denials
    logAdminActions: true,        // log admin UI changes
    retention: '90d',             // auto-delete after 90 days
    piiRedaction: true,           // strip emails & phone numbers
  },

  security: {
    cors: {
      origin: ['https://myapp.com'],  // allowed origins (never '*' in prod)
      credentials: true,              // allow cookies
    },
    adminIpAllowlist: ['10.0.0.0/8'], // restrict /admin access
  },

  schemaEndpoint: {
    enabled: true,                            // expose GET /schema
    token: process.env.SCHEMA_API_TOKEN,      // require token for access
  },

  permissions: {
    view_own_orders: {
      table: 'main.orders',
      roles: ['viewer', 'warehouse_manager'],
      select: {
        columns: ['id', 'amount', 'status', 'created_at'],
        where: { customer_id: { $eq: '$user.customer_id' } },
      },
    },
  },

  actions: {
    incrementStock: {
      roles: ['warehouse_manager'],
      input: z.object({ productId: z.string(), amount: z.number().positive() }),
      output: z.object({ id: z.string(), stock: z.number() }),
      run: async ({ user, db }, { productId, amount }) => {
        const [updated] = await db
          .update(products)
          .set({ stock: sql`stock + ${amount}` })
          .where(eq(products.id, productId))
          .returning({ id: products.id, stock: products.stock })
        return updated
      },
    },
  },

  pgWire: {
    port: 5433,                              // TCP port for wire protocol
    auth: { strategy: ['jwt', 'apiKey'] },   // auth strategies (try in order)
    serverVersion: '16.3 (superapp)',        // version string for clients
  },
})

engine.startPgWire()

On this page