zokor

Zokor documentation

Project structure

Explore Zokor's project structure, testing approach, dependency ports and fakes, agent guide, and framework design.

Markdown · llms.txt · api.json

Testing#

A request builder and response readers, so a test says what it means instead of assembling an http.Request by hand:

let resp = r.serve(zokor.request(zokor.Method.POST, "/api/orgs")
    .bearer("token")
    .json_body("{\"name\":\"acme\"}")
    .build());

assert(zokor.resp_status(resp) == 201);
assert(zokor.resp_json(resp).get("id").str_or("") == "org_7");
assert(zokor.resp_error_code(denied) == "unauthorized");
assert(zokor.resp_error_fields(invalid)[0] == "seats");

request, get_request, .header, .bearer, .basic, .content_type, .json, .json_body, .body_str, .multipart (with upload_part), and on the way back resp_status, resp_text, resp_header, resp_json, resp_error_code, resp_error_fields. It ships in the package because your service's tests need it too.

Layout#

zokor/            the package your service imports
  router.sl       Router[S], Route[S], Ctx[S]
  errors.sl       Registry, Code, ErrorView, the envelope
  config.sl       Config, load_config, require_*
  respond.sl      success responses
  ids.sl          request and session ids
  json.sl         Json, the checker, DTO helpers
  testkit.sl      the request builder and response readers
  upload.sl       uploads: rules, Form, Upload, safe filenames
  ratelimit.sl    RateLimiter, rate_limit
  tokens.sl       TokenStore, bearer_subject
  ws.sl           WebSocket connections and Socket.IO
  socket.sl       Socket, Hub: a served connection and its rooms
  ws_serve.sl     r.websocket: the handshake and a connection's two tasks
  sio_serve.sl    r.socketio: Engine.IO sessions over the WebSocket
  internal/
    path/         split, query parsing, percent-decoding
    envfile/      .env parsing
    validate/     the value rules
    multipart/    the multipart/form-data parser
    ws/           RFC 6455 frames and the handshake
    sio/          Engine.IO and Socket.IO packets
examples/
  hello/          routes, config, errors, DTOs, uploads
  chat/           WebSocket and socket.io
www/              docs-site builder, theme and resized logo assets
assets/           the logo
todo.md           what is next, checkable
docs/             generated site, benchmarks, llms-small.txt (the agent
                guide: every snippet compile-checked by `make snippets`),
                api.txt (every public symbol, generated by gen_api.sh)
.github/          CI: tests, guide snippets, API and site freshness

internal/ holds the pure parts: no sockets, no clock, no environment. That is where the tests are cheapest and the hot paths easiest to keep honest.

Tests#

make test

make check runs the tests, all examples, the agent guide's snippets (docs/llms-small.txt, via make snippets), and the API and site freshness checks. CI runs the same against slangc built from slang dev.

Dependencies: ports and fakes#

Use a struct of function values, wired once at startup. A service holds that port and calls it; concrete database or HTTP clients live in adapters. Slang has no closures, so pass adapter state explicitly rather than hiding it in globals:

pub gc struct StockPort[C] {
    context: C,
    lookup: fn(C, str, str) -> result[opt[Stock], str],
}
// A top-level adapter function has the same signature:
// lookup(context, tenant_id, sku). Startup injects its function and context.

The application defines the port. Infrastructure imports that definition and implements it; application code imports domain types and never the adapter. The bootstrap imports both and connects them. Tenant identity remains an explicit argument through each call. An optional result separates a missing record from an unavailable dependency. The HTTP edge maps failures to registered errors without exposing adapter diagnostics.

examples/ports/src/main.sl is the worked example: a tenant-scoped stock service, an immutable memory adapter, a protected route, and startup configuration. make example-ports drives the real router pipeline without opening sockets. It prints an unauthenticated 401, the seeded stock, and a registered missing-stock 404. The existing hello/chat examples keep their behavior.

Application fakes live in fakes_test.sl, so the compiler excludes them from service builds. They supply the same function signature with their own explicit state, return canned success/absence/failure, and record calls. Tests prove that invalid input never reaches a port, tenant identity is passed through, another tenant's record is rejected, unauthenticated HTTP requests cannot invoke the port, and adapter details do not reach clients. make test lists all four example packages; make check also runs its startup wiring.

For generic application services, use small concrete top-level route functions in the bootstrap to call the generic HTTP helpers. The example uses this ordinary function-value pattern for registration and gives tests their own wrappers. Each adapter owns its concurrency rules: the example copies its seed data once and never mutates it after startup; a mutable adapter must synchronize its state.

Agent guide#

An agent writing a service reads slang's llms-small.txt then docs/llms-small.txt: one page, example-first, with the one way for errors, config, validation, routing and tests, and recipes for headers, rate limits, bearer tokens, uploads, shared state, background workers and graceful shutdown. Every snippet in it is a whole program that compiles and runs; make snippets proves it.

docs/api.txt is the companion: every public symbol, its signature and one line, small enough to keep in context instead of reading zokor/. It is generated (make api, which runs docs/gen_api.sh); CI fails if it is stale.

make docs builds the static site at docs/index.html from this README, the generated API reference and the service examples. make docs-check fails when the committed site is stale.

Not yet#

The full list, ordered and checkable, is todo.md. The remaining work is the v0.2.0 release after slang ships the required compiler and package features, the measured performance gap described in docs/benchmarks.md, and the MongoDB adapter, which is currently deferred. The HTTP, realtime, migrations, metrics, tracing, pagination and OpenAPI work listed earlier in this README is implemented.

Contributing and licence#

zokor is MIT-licensed (LICENSE), by Dolph Tech Limited. CONTRIBUTING.md says how to build, test and send a change; report security problems privately as SECURITY.md describes; everyone taking part follows the Code of Conduct.