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
| Type | Description |
|---|---|
str | String value |
int | Integer number |
num | Any number |
bool | Boolean |
auto | Auto-generated UUID |
timestamp | Auto-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:
| Method | Path | Action |
|---|---|---|
GET | /api/users | List all (with pagination) |
GET | /api/users/:id | Get by ID |
POST | /api/users | Create (with validation) |
PUT | /api/users/:id | Update |
DELETE | /api/users/:id | Delete |
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.