-
Notifications
You must be signed in to change notification settings - Fork 0
Getting Started
Source of truth:
docs/getting-started.md. This wiki page mirrors it; the repo doc wins on drift.
bun add lugas@betaLugas requires Bun 1.4.x. TypeScript 7.0.2 is the verified toolchain for the full compile-time contract experience.
The
v0.1.0-beta.1candidate is attested but not yet published — npm publication is an explicit owner action. Until it is announced, the package should not be assumed available.
// app.ts
import { defineApp, json, route } from "lugas";
const app = defineApp({
routes: {
"/hello": {
GET: route({
handler: () => json(200, { message: "Hello from Lugas" }),
}),
},
},
});
export default app;// server.ts
import app from "./app";
const server = app.serve({ port: 3000 });
console.log(`Lugas is listening on ${server.url}`);bun run server.ts
curl http://localhost:3000/helloLugas accepts validators implementing Standard Schema v1 (Zod, Valibot, or any conforming implementation). Validation outputs are typed on the handler context (ctx.body, ctx.query, ctx.params, ctx.headers).
import { defineApp, defineModule, guard, json, route } from "lugas";
import { z } from "zod";
const authGuard = guard({
name: "auth",
handler: (ctx) => {
const authorization = ctx.request.headers.get("authorization");
if (!authorization) return json(401, { error: "unauthorized" });
return { user: { id: "usr_123" } };
},
});
const invoices = defineModule({
name: "invoices",
routes: {
"/invoices": {
POST: route({
before: [authGuard],
body: z.object({
amount: z.number().positive(),
currency: z.string().length(3),
}),
handler: (ctx) => json(201, {
id: "inv_123",
amount: ctx.body.amount,
currency: ctx.body.currency,
createdBy: ctx.user.id,
}),
}),
},
},
});
export default defineApp({ modules: [invoices] });A guard may either return context (merged in declaration order, available to later guards and the handler) or return a typed Response and short-circuit the route.
import type { AppContract } from "lugas";
import { createClient } from "lugas/client";
import type app from "./app";
type API = AppContract<typeof app>;
const api = createClient<API>({ baseUrl: "https://api.example.com" });
const result = await api.post("/invoices", {
body: { amount: 125, currency: "USD" },
headers: { authorization: "Bearer token" },
});
if (result.ok) console.log(result.data.id);
else console.error(result.status, result.error);Compile-time checks cover supported paths and methods, route parameters, query values, headers, request bodies, and success/error statuses. Explicit method calls and path strings — no runtime Proxy, no generated SDK. Response types model JSON serialization truth ("wire-honest types"): Date → string, non-finite numbers → null | number, toJSON drops modeled.
The package ships a prebuilt browser ESM artifact: lugas/client/browser (build/lugas-client.esm.js). Three consumption arrangements: same-origin serving via assets.files, an import map, or continued bundler use. The artifact lane is same-origin only; for cross-origin frontends pair it with CORS.
import { expect, test } from "bun:test";
import { createTestServer } from "lugas/testing";
import app from "./app";
test("creates an invoice", async () => {
const server = createTestServer(app, { port: 0 });
try {
const response = await server.fetch("/invoices", {
method: "POST",
headers: { authorization: "Bearer test-token", "content-type": "application/json" },
body: JSON.stringify({ amount: 125, currency: "USD" }),
});
expect(response.status).toBe(201);
} finally {
await server.stop();
}
});bunx lugas routes ./app.ts # human-readable route table
bunx lugas inspect ./app.ts # full lugas-manifest-v1 JSONRFC 9457 Problem Details (application/problem+json) for structured errors:
| Condition | Status | Code |
|---|---|---|
| Malformed JSON | 400 |
MALFORMED_JSON |
| Unsupported media type | 415 |
UNSUPPORTED_MEDIA_TYPE |
| Validation failure | 422 |
VALIDATION_FAILED |
| Unhandled internal error | 500 |
redacted — no stack traces or internals reach the client |
Typed response helpers: json(status, body), text(status, body), problem(status, fields), empty(status).
- CORS · Server-Sent Events · Structured Logging · OpenAPI and Scalar · Service Lifecycle · Assets and Body Limits
- Runnable examples:
examples/ - Diagnostic catalog:
docs/diagnostics.md
LugasJS Wiki
Server facilities
- CORS
- Server-Sent Events
- Structured Logging
- OpenAPI and Scalar
- Drizzle
- Service Lifecycle
- Assets and Body Limits
Reference
Repository