Skip to content

Commit 3ab9336

Browse files
committed
fix docs
1 parent 81d0613 commit 3ab9336

9 files changed

Lines changed: 157 additions & 4 deletions

File tree

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@
2727

2828
---
2929

30-
> Note: This Project is in active development. Breaking changes may occur in minor releases.
30+
> Note: This Project is in active development. Currently, Breaking changes may occur in every commit. Use at your own risk.
3131
3232
## ✨ Features
3333

docs/guide/caching.md

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
# Caching
2+
3+
api.zig provides in-memory caching primitives geared for HTTP responses and application data.
4+
5+
## Features
6+
7+
- LRU eviction
8+
- TTL expiration
9+
- Response caching middleware with ETag support
10+
11+
## Example
12+
13+
```zig
14+
var cache = ResponseCache.init(allocator, .{ .max_size = 1000 });
15+
app.addMiddleware(cache.cacheMiddleware(&cache));
16+
```
17+
18+
See `src/cache.zig` for cache configuration, invalidation, and helper utilities.

docs/guide/deployment.md

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
# Deployment
2+
3+
Guidance for deploying `api.zig` applications in production.
4+
5+
## Recommendations
6+
7+
- Run behind a reverse proxy (nginx, Caddy) or a load-balancer for TLS termination.
8+
- Use systemd or container orchestrators (Docker, Kubernetes) for process supervision.
9+
- Configure environment variables for runtime config (port, address, feature flags).
10+
11+
## Example systemd unit
12+
13+
```
14+
[Unit]
15+
Description=api.zig service
16+
After=network.target
17+
18+
[Service]
19+
Type=simple
20+
User=www-data
21+
ExecStart=/opt/myapp/bin/myapp
22+
Restart=on-failure
23+
24+
[Install]
25+
WantedBy=multi-user.target
26+
```
27+
28+
## Containers
29+
30+
- Build small images (static binary will help) and use health and readiness probes in orchestrators.
31+
- For multi-replica setups, use an external session store (Redis) and centralized logs/metrics.
32+
33+
Refer to the docs above (Metrics, Health Checks, Caching) for production concerns.

docs/guide/health-checks.md

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
# Health Checks
2+
3+
api.zig supports health checks for production readiness and liveness probes.
4+
5+
## Built-in Checks
6+
7+
- Aggregated health status (ok/warning/fail)
8+
- Custom checks (database, caches, external services)
9+
10+
Example:
11+
12+
```zig
13+
var hc = try metrics.HealthChecks.init(allocator);
14+
hc.addCheck("postgres", checkPostgresFn);
15+
app.get("/health", (ctx) => Response.json(hc.statusJson()));
16+
```
17+
18+
See `src/metrics.zig` for health check utilities and JSON output format.

docs/guide/metrics.md

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
# Metrics
2+
3+
Collect metrics and export Prometheus-compatible metrics with the built-in registry.
4+
5+
## Exporting Metrics
6+
7+
- Use `metrics.Registry` to register counters, gauges and histograms.
8+
- Expose metrics endpoint and call `registry.scrape()` to generate Prometheus text.
9+
10+
Example:
11+
12+
```zig
13+
var registry = try metrics.Registry.init(allocator);
14+
registry.registerCounter("requests_total", "Total requests");
15+
app.get("/metrics", (ctx) => Response.text(registry.scrape()))
16+
```
17+
18+
See `src/metrics.zig` for implementation details and health check integrations.

docs/guide/sessions.md

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
# Sessions
2+
3+
api.zig provides a secure session management system with pluggable backends (in-memory, Redis, etc.).
4+
5+
## Basics
6+
7+
- Create a `Session.Manager` and configure cookie name, TTL, secure flag, and storage backend.
8+
- Use `sessionMiddleware(manager)` to enable automatic session loading/saving for requests.
9+
10+
## Example
11+
12+
```zig
13+
const manager = try session.Manager.init(allocator, manager_config);
14+
app.addMiddleware(sessionMiddleware(&manager));
15+
```
16+
17+
## Tips
18+
19+
- Use secure cookies (`Secure=true`) in production and set `SameSite` appropriately.
20+
- Use server-side stores (e.g., Redis) for multi-process deployments.
21+
22+
See the `src/session.zig` API docs for configuration options and storage interfaces.

docs/guide/websocket.md

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
# WebSocket
2+
3+
api.zig includes RFC-6455 WebSocket support with an extensible connection hub and handlers for real-time apps.
4+
5+
## Quick Start
6+
7+
- Create a `WebSocket.Hub` and register event handlers.
8+
- Use `app.upgradeToWebSocket(...)` (or the provided helper) in a route to accept WebSocket connections.
9+
10+
Example:
11+
12+
```zig
13+
const hub = try websocket.Hub.init(allocator);
14+
app.get("/ws", (ctx) => websocket.accept(ctx, &hub));
15+
```
16+
17+
## Features
18+
19+
- Ping/Pong heartbeats
20+
- Reconnection-friendly message framing
21+
- Room/channel broadcasting
22+
- GraphQL subscription integration (see GraphQL docs)
23+
24+
See `src/websocket.zig` for low-level details and available helpers.

examples/graphql.zig

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
const std = @import("std");
2+
const server = @import("graphql_server.zig");
3+
4+
pub fn main() !void {
5+
try server.main();
6+
}

src/app.zig

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -384,15 +384,21 @@ pub const App = struct {
384384

385385
// GraphQL endpoint handler with introspection support
386386
const GraphQLHandler = struct {
387+
var logger: ?*Logger = null;
387388
var cached_introspection: []const u8 = "";
388389

390+
fn setLogger(l: *Logger) void {
391+
logger = l;
392+
}
393+
389394
fn setCachedIntrospection(data: []const u8) void {
390395
cached_introspection = data;
391396
}
392397

393398
fn handle(ctx: *Context) Response {
394399
// Handle CORS preflight
395400
if (ctx.method() == .OPTIONS) {
401+
if (logger) |lg| lg.debug("[GraphQL] OPTIONS preflight received", null) catch {} else std.debug.print("[GraphQL] OPTIONS preflight received\n", .{});
396402
return Response.init()
397403
.setStatus(.no_content)
398404
.setHeader("Access-Control-Allow-Origin", "*")
@@ -403,29 +409,37 @@ pub const App = struct {
403409

404410
// For POST requests, check if it's an introspection query
405411
const body = ctx.body();
406-
if (body.len > 0 and std.mem.indexOf(u8, body, "__schema") != null) {
407-
return Response.jsonRaw(cached_introspection)
408-
.setHeader("Access-Control-Allow-Origin", "*");
412+
if (body.len > 0) {
413+
const snippet = if (body.len > 512) body[0..512] else body;
414+
if (logger) |lg| lg.debugf("[GraphQL] POST body (first 512 bytes): {s}", .{snippet}, null) catch {} else std.debug.print("[GraphQL] POST body (first 512 bytes): {s}\n", .{snippet});
415+
if (std.mem.indexOf(u8, body, "__schema") != null) {
416+
if (logger) |lg| lg.debug("[GraphQL] Detected introspection query in POST body", null) catch {} else std.debug.print("[GraphQL] Detected introspection query in POST body\n", .{});
417+
return Response.jsonRaw(cached_introspection)
418+
.setHeader("Access-Control-Allow-Origin", "*");
419+
}
409420
}
410421

411422
// For GET requests with introspection
412423
if (ctx.method() == .GET) {
413424
if (ctx.query("query")) |query| {
414425
if (std.mem.indexOf(u8, query, "__schema") != null) {
426+
if (logger) |lg| lg.debug("[GraphQL] Detected introspection query in GET", null) catch {} else std.debug.print("[GraphQL] Detected introspection query in GET\n", .{});
415427
return Response.jsonRaw(cached_introspection)
416428
.setHeader("Access-Control-Allow-Origin", "*");
417429
}
418430
}
419431
}
420432

421433
// Default response for non-introspection queries
434+
if (logger) |lg| lg.debug("[GraphQL] Non-introspection request received", null) catch {} else std.debug.print("[GraphQL] Non-introspection request received\n", .{});
422435
return Response.json(.{ .data = null, .message = "Query execution not yet implemented" })
423436
.setHeader("Access-Control-Allow-Origin", "*");
424437
}
425438
};
426439

427440
// Set the cached introspection data
428441
GraphQLHandler.setCachedIntrospection(introspection_json);
442+
GraphQLHandler.setLogger(self.logger);
429443

430444
const PlaygroundHandler = struct {
431445
fn handle(ctx: *Context) Response {

0 commit comments

Comments
 (0)