Type Generation

Lucent automatically generates TypeScript types from your collections and custom endpoints into a single lucent-types.ts file. This enables end-to-end type safety for both the REST API client (via Eden Treaty) and the server-side programmatic API.

Running Type Generation

Types are automatically generated each time lucent dev starts. You can also trigger generation manually:

lucent build   # generate types + validate config
lucent typegen # generate types only

Configuration

Configure the output path and optional custom type files in lucent.config.ts:

import { defineLucentConfig } from "@codesordinatestudio/lucent";

export default defineLucentConfig({
  /* ... */
  typegen: {
    output: "./lucent-types.ts", // where to write the file
    customTypes: ["./utils/my.types.ts"], // optional extra type files to inline
  },
  sdk: {
    enabled: true,
    manifest: {
      output: "./sdk.json",
      route: "/api/sdk.json",
      exposeInDev: true,
      exposeInProduction: false,
    },
  },
});

What Gets Generated

Collection interfaces

For every collection Lucent generates:

  • <Slug>Config — full document shape including timestamps
  • <Slug>CreateInput — fields accepted on create
  • <Slug>UpdateInputPartial<CreateInput> for PATCH
  • <Slug>ListResponse, <Slug>ItemResponse, <Slug>CreateResponse, etc.
  • <Slug>WhereClause / <Slug>QueryArgs for typed filtering

For auth-enabled collections it also generates <Slug>RegisterInput, <Slug>LoginInput, and the corresponding response types.

Custom endpoint schemas

Export any TypeBox t.Object(...) schema from an endpoint file and Lucent will automatically generate a matching TypeScript interface for it — using the exact export name, with no renaming:

// src/endpoints/auth.ts
import { t } from "elysia";
import type { LucentEndpoint } from "../lucent-types";

export const AuthBodySchema = t.Object({
  name: t.String(),
  file: t.File(),
});

export const myAuth: LucentEndpoint = (app) => {
  app.post(
    "/auth/upload",
    ({ body }) => {
      /* ... */
    },
    {
      body: AuthBodySchema,
    },
  );
};

After lucent build (or on next lucent dev start), lucent-types.ts will contain:

export interface AuthBodySchema {
  name: string;
  file: File;
}

No extra config is needed — Lucent discovers the endpoint files automatically from the endpoints array in your config.

Eden Treaty app type

A _buildLucentApp() phantom builder and LucentApp type are generated so you can wire up a Lucent client with full route type safety:

import { lucent } from "@codesordinatestudio/lucent";
import type { LucentApp } from "./lucent-types";

const api = lucent.client<LucentApp>({
  url: "http://localhost:3000",
});

// Fully typed — body, response, query params
const { data } = await api.api.posts.get({ query: { page: 1 } });

lucent.client() uses Eden Treaty under the hood, sends cookies by default with credentials: "include", and can attach a bearer token plus an onResponse callback when needed.

Portable SDK manifest

When sdk.enabled is set, Lucent also generates a portable sdk.json manifest from the same metadata pipeline used by lucent-types.ts.

This file is intended to be copied, downloaded, or bundled into a client application that uses the standalone fetch-based lucent-sdk package. The optional manifest route is mainly useful for local development and tooling.

LucentEndpoint type

The generated file also exports a LucentEndpoint type that is pre-wired with your project's collection types:

import type { LucentEndpoint } from "./lucent-types"; // ← use this, not the package

export const myEndpoint: LucentEndpoint = (app) => {
  // `lucent` and `user` are fully typed with your collections
  app.get("/hello", ({ lucent, user }) => {
    /* ... */
  });
};