Server & API

All server features are zero-dependency — the runtime is bundled with the NAIDE package. No need to install Express or any other framework.

server — HTTP Server

The server keyword creates an HTTP server with route handlers:

server app port 3000:
  get "/":
    ret {message: "hello"}

  post "/api/data" (req, res):
    ret req.body

  put "/api/data/:id" (req, res):
    ret {updated: true}

  del "/api/data/:id":
    ret {deleted: true}

  patch "/api/data/:id" (req, res):
    ret {patched: true}

Supported HTTP methods: get, post, put, del, patch. The (req, res) parameters are optional — omit them if you only need to return data.

Response Helpers

The ret keyword supports several response modes:

ret {data: items}                        # JSON (default)
ret.status 404 {error: "nope"}          # status code
ret.redirect "/login"                    # redirect
ret.redirect 301 "/new-url"             # redirect with status
ret.html "<h1>Hello</h1>"               # HTML
ret.text "pong"                          # plain text
ret.file "/path/to/file"                # send file
ret.download "/path/to/file.zip"        # file download
ret.download "/file.zip" "custom.zip"   # download with filename
ret.render "template" {data}            # render template (requires view)

schema — Data Models

Define data schemas with types and validation rules:

schema User:
  id       auto
  name     str required min(2) max(50)
  email    str required email unique
  age      int optional min(0) max(150)
  role     enum("admin", "user") default("user")
  joined   timestamp auto

Schema Types

TypeDescription
strString value
intInteger number
numAny number
boolBoolean
autoAuto-generated UUID
timestampAuto-generated timestamp
enum(...)One of the listed values

Modifiers

required, optional, min(n), max(n), email, url, unique, auto, default(val)

crud — Auto-Generated REST Endpoints

server app port 3000:
  crud "/api/users" User

Generates these endpoints automatically:

MethodPathAction
GET/api/usersList all (with pagination)
GET/api/users/:idGet by ID
POST/api/usersCreate (with validation)
PUT/api/users/:idUpdate
DELETE/api/users/:idDelete

Built-in pagination, search, and sort via query parameters:

GET /api/users?page=2&limit=10&q=john&sort=name&order=asc

Response format: { data: [...], total, page, limit, pages }

validate — Request Validation

server app port 3000:
  validate "/api/users" User

  post "/api/users" (req, res):
    user = UserStore.create(req.body)   # body is pre-validated
    ret user

Auto-validates POST/PUT/PATCH request bodies against the schema. Returns 400 with error details if validation fails. Validated data replaces req.body.

auth — JWT Authentication

server app port 3000:
  auth JWT_SECRET:
    protect "/api/*"
    public "/api/auth/*"

  post "/api/auth/login" (req, res):
    token = auth.sign({id: user.id})
    ret {token}

Paths matching protect require a valid JWT in the Authorization: Bearer <token> header. Paths matching public are excluded. The decoded token is available on req.user.

Middleware

cors — Cross-Origin Requests

cors "*"                    # allow all origins

limit — Rate Limiting

limit "/api/*" 100 "1m"    # 100 requests per minute

cookie — Cookie Parser

cookie                     # parses cookies into req.cookies

session — Cookie Sessions

session "my-secret"        # enables req.session

mid — Custom Middleware

fn logger(req, res, next):
  log req.method, req.url
  next()

server app port 3000:
  mid logger               # apply globally
  mid logger "/api"        # apply to path only

Route-Level Middleware

Apply middleware to specific routes with bracket syntax:

get "/admin" [authCheck] (req, res):
  ret {admin: true}

post "/api/data" [auth, logger, validator] (req, res):
  ret req.body

Compiles to: app.get("/admin", authCheck, (req, res) => { ... })

upload — File Uploads

server app port 3000:
  upload "/api/upload" "avatar" (req, res):
    ret {filename: req.file.filename, size: req.file.size}

Zero-dependency multipart parser. req.file contains {filename, contentType, data, size}.

view — Template Rendering

server app port 3000:
  view "./views"

  get "/":
    ret.render "home" {title: "Welcome", items: ["a", "b"]}

Reads .html files with template syntax: {{variable}}, {{if key}}...{{/if}}, {{each item in list}}...{{/each}}.

static — Serve Static Files

static "/public"

group — Route Groups

server app port 3000:
  group "/api/v1":
    get "/users":
      ret users
    post "/users" (req, res):
      ret req.body

Groups routes under a common path prefix.

sse — Server-Sent Events

server app port 3000:
  sse "/events"

  post "/api/notify" (req, res):
    sse.broadcast req.body
    ret {ok: true}

Available functions: sse.send(data), sse.broadcast(data), sse.count.

ws — WebSocket

server app port 3000:
  ws "/chat":
    on "connect":
      send({type: "welcome"})
    on "message" (data):
      broadcast(data)
    on "close":
      log "client left"

Built-in send(data) and broadcast(data). Requires npm install ws.

cache — Response Caching

cache "/api/*" "5m"

Caches GET responses in memory with a TTL. Sets X-Cache: HIT/MISS header.

error — Error Handler

server app port 3000:
  error (err, req, res):
    log.error err.message
    ret.status 500 {error: "Internal error"}

Async route handlers are automatically wrapped with try/catch. Routes with explicit try/fail blocks are left as-is.

openapi — API Docs

openapi "/docs"

Auto-generates an OpenAPI 3.1 JSON spec from your schemas, served at the specified path.

queue — Job Queue

queue jobs:
  job "sendEmail" (data):
    log "sending to {data.to}"
  job "resize" (data):
    log "resizing {data.path}"

server app port 3000:
  post "/api/notify" (req, res):
    jobs.add("sendEmail", {to: req.body.email})
    ret {queued: true}

In-memory async job queue for background processing.

Scheduled Tasks & Events

every "5m":
  log "cleanup running"

watch User.create (event):
  log "new user: {event.data.name}"

Intervals: "30s", "5m", "1h", "1d". The watch keyword connects to crud events automatically.