djo

Exemplos

Programas pequenos e completos. Salve em um arquivo e rode com djo arquivo.djo, ou coloque numa pasta e use djo serve.

Structs

Campos tipados, valores padrão e métodos. O campo nocall fica fora do construtor.

struct Post{
    id[Int] nocall
    titulo[String]
    publicado[Bool] = false

    f link
        return "/post?id=" + (str:self.id)
}

var p = Post:"Olá"
p.id = 7
print p.link:          // /post?id=7

Uma API JSON

Páginas em modo código: o que print escreve é a resposta, ou use Http.json: para responder JSON com o status que quiser.

// api.djo: uma página que responde JSON
if
    cond[Http.method: == "POST"]
    var d = Http.json:
    Http.json:{"recebido": d["n"] + 1}:201
else
    Http.json:{"erro": "use POST"}:405

Banco de dados

SQLite embutido. Os valores vão sempre numa lista, ligados aos ?, o que evita SQL injection.

Db.open:"site.db"
Db.exec:"CREATE TABLE IF NOT EXISTS posts (id INTEGER PRIMARY KEY, titulo TEXT)"
Db.exec:"INSERT INTO posts (titulo) VALUES (?)":[Http.form:"titulo"]

var posts = Db.query:"SELECT * FROM posts ORDER BY id DESC LIMIT 10"
for{
    each[p in posts]
    print p["titulo"]
}

Sensor na placa

Lê uma linha da porta serial a cada segundo e envia para um servidor. Compile o perfil tiny ou nano para a sua placa.

// sensor.djo: lê a porta serial e envia a leitura para o servidor
var porta = Serial.open:"/dev/ttyUSB0":9600

while
    cond[true]
    var linha = Serial.readline:porta
    if
        cond[linha != nil]
        map leitura = {"sensor": "sala", "temp": float:linha, "hora": Time.now:}
        var r = Http.post:"http://192.168.0.10:8080/leituras":leitura
        if
            cond[not r["ok"]]
            print "não enviou: " + (r["error"] ?? str:r["status"])
    Time.sleep:1000

Tela e agente na mesma URL

No rotas.djo, a rota aponta para duas páginas. Quem pede application/json recebe a face de agente; o navegador recebe o HTML. Pedir um formato que a rota não tem dá 406.

// rotas.djo: a mesma URL tem uma face para pessoas e outra para agentes
Route.get:"/docs/{secao}":{"html": "paginas/doc.djo.html", "agent": "agentes/doc.djo"}

Uma ação para agentes

Com action, uma função com parâmetros tipados vira um endpoint POST em JSON. A entrada é validada contra os tipos antes de a função rodar (erro 422 com o detalhe de cada campo), e o servidor publica o manifesto em /.well-known/ai-manifest.json, com JSON Schema, para quem usa function calling ou MCP.

// core/posts.djo: a mesma função serve a tela e o agente
action criar_post
    "Cria um post novo"
    params[titulo[String], nota[Float]]
    Http.status:201
    return {"titulo": titulo, "nota": nota}

// rotas.djo
Route.action:"/posts":"criar_post"

Para ver o seu site como um agente: djo agent localhost:8080. Agentes

Este site

Você está lendo um site feito em djo. Estas páginas são templates .djo.html, o realce de código e o renderizador de Markdown da documentação são funções djo em core/, e as rotas são estas:

// Este site é feito em djo. Só existe o que está declarado aqui.
Route.get:"/":"paginas/inicio.djo.html"
Route.get:"/docs":{"html": "paginas/docs.djo.html", "agent": "agentes/docs.djo", "about": "Índice da documentação da djo", "cache": 60}
Route.get:"/docs/{secao}":{"html": "paginas/doc.djo.html", "agent": "agentes/doc.djo", "about": "Uma seção da documentação, em Markdown", "cache": 60}
Route.get:"/exemplos":"paginas/exemplos.djo.html"
Route.get:"/instalar":"paginas/instalar.djo.html"
Route.static:"/assets":"publico"

Teste a face de agente: /docs com Accept: application/json, ou leia o manifesto deste site.