### Quick Start Server Setup
Source: https://github.com/cleverbrush/framework/blob/master/libs/server/README.md
A basic example demonstrating how to set up a server, define a user creation endpoint with body validation, and handle requests.
```typescript
import { ServerBuilder, endpoint, ActionResult } from '@cleverbrush/server';
import { object, string, number } from '@cleverbrush/schema';
const CreateUserBody = object({ name: string(), age: number() });
const createUser = endpoint
.post('/api/users')
.body(CreateUserBody);
const server = new ServerBuilder();
server.handle(createUser, ({ body }) => {
// body is fully typed: { name: string; age: number }
return ActionResult.created({ id: 1, ...body }, '/api/users/1');
});
await server.listen(3000);
```
--------------------------------
### Development Setup Commands
Source: https://github.com/cleverbrush/framework/blob/master/README.md
Provides essential commands for setting up the development environment, including installing dependencies, linting, building, and testing.
```bash
npm ci
npm run lint
npm run build
npm run test
```
--------------------------------
### Install Dependencies
Source: https://github.com/cleverbrush/framework/blob/master/AGENTS.md
Use this command to install dependencies, ensuring the lockfile is respected. Prefer `ci` over `install`.
```bash
npm ci
```
--------------------------------
### React Form Quick Start Example
Source: https://github.com/cleverbrush/framework/blob/master/libs/react-form/README.md
Set up a form with schema validation and custom UI renderers. Define your schema using '@cleverbrush/schema', register UI components via 'FormSystemProvider', and use 'useSchemaForm' to manage form state and submission.
```tsx
import { object, string, number } from '@cleverbrush/schema';
import { useSchemaForm, FormSystemProvider, Field } from '@cleverbrush/react-form';
// 1. Define schema — reuse across forms, API validation, mapping, etc.
const ContactSchema = object({
name: string().required('Name is required').minLength(2, 'Name must be at least 2 characters'),
email: string().required('Email is required'),
age: number().required('Age is required').min(18, 'Must be at least 18')
});
// 2. Define renderers once per app — maps schema types to UI components
const renderers = {
string: ({ value, onChange, onBlur, error, touched }) => (
)
};
// 3. Each form component only picks which fields to show — no boilerplate
function ContactForm() {
const form = useSchemaForm(ContactSchema);
const handleSubmit = async () => {
const result = await form.submit();
if (result.valid) {
console.log('Submitted:', result.object);
}
};
return (
);
}
// App — wrap with provider
function App() {
return (
);
}
```
--------------------------------
### Start Demo Application
Source: https://github.com/cleverbrush/framework/blob/master/README.md
Command to launch the demo application, which includes the backend, frontend, and local database stack for workflow testing.
```bash
npm run dev:demo
```
--------------------------------
### Install @cleverbrush/scheduler
Source: https://github.com/cleverbrush/framework/blob/master/libs/scheduler/README.md
Install the library using npm. This library requires Node.js v16+.
```bash
npm install @cleverbrush/scheduler
```
--------------------------------
### Attach Named Request Body Examples
Source: https://github.com/cleverbrush/framework/blob/master/libs/server-openapi/README.md
Use .examples() to provide multiple named examples with summaries and descriptions.
```ts
const CreateUser = endpoint
.post('/api/users')
.body(UserSchema)
.examples({
minimal: { summary: 'Minimal', value: { name: 'Alice' } },
full: {
summary: 'Complete',
description: 'A fully populated user',
value: { name: 'Alice', email: 'alice@example.com', age: 30 }
}
});
```
--------------------------------
### Install Cleverbrush Schema
Source: https://github.com/cleverbrush/framework/blob/master/libs/schema/README.md
Install the Cleverbrush Schema library using npm.
```bash
npm install @cleverbrush/schema
```
--------------------------------
### Install @cleverbrush/react-form
Source: https://github.com/cleverbrush/framework/blob/master/libs/react-form/README.md
Command to install the @cleverbrush/react-form package using npm.
```bash
npm install @cleverbrush/react-form
```
--------------------------------
### Install @cleverbrush/knex-clickhouse
Source: https://github.com/cleverbrush/framework/blob/master/libs/knex-clickhouse/README.md
Install the package using npm. Ensure you have Knex version 3.1.0 or higher installed as a peer dependency.
```bash
npm install @cleverbrush/knex-clickhouse
```
--------------------------------
### Quick Start: Basic Dependency Injection
Source: https://github.com/cleverbrush/framework/blob/master/libs/di/README.md
Demonstrates defining service contracts with schemas, registering services with different lifetimes, building a service provider, and resolving dependencies.
```typescript
import { ServiceCollection } from '@cleverbrush/di';
import { object, string, number, func } from '@cleverbrush/schema';
// 1. Define service contracts as schemas (used as keys)
const IConfig = object({ port: number(), host: string() });
const ILogger = object({ info: func().addParameter(string()) });
// 2. Register services
const services = new ServiceCollection();
services.addSingleton(IConfig, { port: 3000, host: 'localhost' });
services.addSingleton(ILogger, () => ({ info: (msg) => console.log(msg) }));
// 3. Build the provider
const provider = services.buildServiceProvider();
// 4. Resolve — fully typed, no explicit generics needed
const config = provider.get(IConfig);
config.port; // number
```
--------------------------------
### Install @cleverbrush/orm-cli
Source: https://github.com/cleverbrush/framework/blob/master/libs/orm-cli/README.md
Install the ORM CLI as a development dependency in your project.
```bash
npm install --save-dev @cleverbrush/orm-cli
```
--------------------------------
### Clone and Install Dependencies
Source: https://github.com/cleverbrush/framework/blob/master/CONTRIBUTING.md
Clone the repository and install project dependencies using npm ci.
```bash
git clone https://github.com/cleverbrush/framework.git
cd framework
npm ci
```
--------------------------------
### Install Playwright Chromium
Source: https://github.com/cleverbrush/framework/blob/master/demos/e2e/README.md
Install the Chromium browser required for UI tests. Run this command after `npm install` from the `demos/e2e` directory.
```bash
cd demos/e2e && npx playwright install chromium
```
--------------------------------
### Attach Single Request Body Example
Source: https://github.com/cleverbrush/framework/blob/master/libs/server-openapi/README.md
Use .example() to pre-fill the Swagger UI Try it out panel for an endpoint.
```ts
const CreateUser = endpoint
.post('/api/users')
.body(UserSchema)
.example({ name: 'Alice', email: 'alice@example.com' });
```
```yaml
requestBody:
content:
application/json:
schema: { ... }
example: { name: Alice, email: alice@example.com }
```
--------------------------------
### Attaching Example Values to Schemas
Source: https://github.com/cleverbrush/framework/blob/master/libs/schema/README.md
Use `.example(value)` to attach example data to schemas. Examples are purely metadata and do not affect validation. They are useful for documentation generation.
```typescript
import { string, number, object } from '@cleverbrush/schema';
const Email = string().example('user@example.com');
const Age = number().example(30);
const User = object({
email: Email,
age: Age,
}).example({ email: 'alice@example.com', age: 25 });
```
--------------------------------
### Real-World Example: Order Mapping
Source: https://github.com/cleverbrush/framework/blob/master/libs/mapper/README.md
An example demonstrating how to map API response data to a domain model using the mapper and various mapping strategies.
```APIDOC
## Real-World Example
A complete example mapping API responses through multiple layers:
```typescript
import { object, string, number } from '@cleverbrush/schema';
import { mapper } from '@cleverbrush/mapper';
// API response shape
const ApiOrderResponse = object({
order_id: string(),
customer_name: string(),
total_cents: number(),
status_code: number()
});
// Domain model
const Order = object({
id: string(),
customer: string(),
totalPrice: string(),
status: string()
});
const registry = mapper().configure(
ApiOrderResponse,
Order,
(m)
=>
m
.for((t) => t.id)
.from((s) => s.order_id)
.for((t) => t.customer)
.from((s) => s.customer_name)
.for((t) => t.totalPrice)
.compute((s) => `$${(s.total_cents / 100).toFixed(2)}`)
.for((t) => t.status)
.compute((s) => {
const statuses: Record = {
0: 'pending', 1: 'confirmed', 2: 'shipped', 3: 'delivered'
};
return statuses[s.status_code] ?? 'unknown';
})
);
const mapOrder = registry.getMapper(ApiOrderResponse, Order);
const order = await mapOrder({
order_id: 'ORD-123',
customer_name: 'Alice Smith',
total_cents: 4999,
status_code: 2
});
// { id: 'ORD-123', customer: 'Alice Smith', totalPrice: '$49.99', status: 'shipped' }
```
```
--------------------------------
### Attach Schema-level Examples
Source: https://github.com/cleverbrush/framework/blob/master/libs/server-openapi/README.md
Examples attached to schemas propagate to all parameters and responses using that schema.
```ts
const PageParam = number().example(1);
const UserResponse = object({ id: number(), name: string() }).example({ id: 1, name: 'Alice' });
```
--------------------------------
### Accessing Example Metadata
Source: https://github.com/cleverbrush/framework/blob/master/libs/schema/README.md
Retrieve example values attached to a schema using `.introspect().example`. This metadata is consumed by tools like `@cleverbrush/schema-json` and `@cleverbrush/server-openapi`.
```typescript
Email.introspect().example; // 'user@example.com'
```
--------------------------------
### Install @cleverbrush/mapper
Source: https://github.com/cleverbrush/framework/blob/master/libs/mapper/README.md
Install the @cleverbrush/mapper package using npm. Ensure you also have @cleverbrush/schema as a peer dependency.
```bash
npm install @cleverbrush/mapper
```
--------------------------------
### Quick Start JWT Authentication
Source: https://github.com/cleverbrush/framework/blob/master/libs/auth/README.md
Demonstrates setting up JWT authentication with a custom claims mapping and authenticating a request context.
```typescript
import { jwtScheme, Principal } from '@cleverbrush/auth';
type UserClaims = { sub: string; role: string };
const jwt = jwtScheme({
secret: process.env.JWT_SECRET!,
mapClaims: claims => ({
sub: claims.sub as string,
role: claims.role as string
})
});
// Authenticate a request context (built from HTTP headers)
const result = await jwt.authenticate({
headers: { authorization: 'Bearer ' },
cookies: {},
items: new Map()
});
if (result.succeeded) {
const principal: Principal = result.principal;
principal.isAuthenticated; // true
principal.hasRole('admin'); // boolean
principal.value.sub; // string
}
```
--------------------------------
### Quick start OpenAPI generation
Source: https://github.com/cleverbrush/framework/blob/master/libs/server-openapi/README.md
Initialize a server and expose an OpenAPI specification endpoint using serveOpenApi middleware.
```typescript
import { ServerBuilder, endpoint } from '@cleverbrush/server';
import { serveOpenApi } from '@cleverbrush/server-openapi';
import { object, string, number } from '@cleverbrush/schema';
const GetUser = endpoint
.get('/api/users/:id')
.summary('Get a user by ID')
.tags('users');
const server = new ServerBuilder();
server
.use(serveOpenApi({
server,
info: { title: 'My API', version: '1.0.0' }
}))
.handle(GetUser, ({ params }) => ({ id: params.id }));
await server.listen(3000);
// GET /openapi.json → OpenAPI 3.1 document
```
--------------------------------
### Complete API response to domain model mapping
Source: https://github.com/cleverbrush/framework/blob/master/libs/mapper/README.md
Full implementation example showing schema definition, registry configuration, and execution.
```typescript
import { object, string, number } from '@cleverbrush/schema';
import { mapper } from '@cleverbrush/mapper';
// API response shape
const ApiOrderResponse = object({
order_id: string(),
customer_name: string(),
total_cents: number(),
status_code: number()
});
// Domain model
const Order = object({
id: string(),
customer: string(),
totalPrice: string(),
status: string()
});
const registry = mapper().configure(
ApiOrderResponse,
Order,
(m) =>
m
.for((t) => t.id)
.from((s) => s.order_id)
.for((t) => t.customer)
.from((s) => s.customer_name)
.for((t) => t.totalPrice)
.compute((s) => `$${(s.total_cents / 100).toFixed(2)}`)
.for((t) => t.status)
.compute((s) => {
const statuses: Record = {
0: 'pending', 1: 'confirmed', 2: 'shipped', 3: 'delivered'
};
return statuses[s.status_code] ?? 'unknown';
})
);
const mapOrder = registry.getMapper(ApiOrderResponse, Order);
const order = await mapOrder({
order_id: 'ORD-123',
customer_name: 'Alice Smith',
total_cents: 4999,
status_code: 2
});
// { id: 'ORD-123', customer: 'Alice Smith', totalPrice: '$49.99', status: 'shipped' }
```
--------------------------------
### Headless Usage Example
Source: https://github.com/cleverbrush/framework/blob/master/libs/react-form/README.md
Example demonstrating how to use the `useSchemaForm` hook directly for full control over rendering without the `Field` component.
```APIDOC
## Headless Usage (without Field component)
For full control over rendering, use `form.useField()` directly:
```tsx
function UserForm() {
const form = useSchemaForm(UserSchema);
const name = form.useField((t) => t.name);
const email = form.useField((t) => t.email);
return (
<>
name.onChange(e.target.value)}
onBlur={name.onBlur}
/>
{name.touched && name.error && {name.error}}
email.onChange(e.target.value)}
onBlur={email.onBlur}
/>
>
);
}
```
```
--------------------------------
### OpenAPI Specification Configuration
Source: https://github.com/cleverbrush/framework/blob/master/libs/server-openapi/README.md
Configuration examples for defining OpenAPI metadata and path parameters.
```APIDOC
## OpenAPI Configuration
### Description
Defines how to register top-level tags and API information for OpenAPI spec generation.
### Request Example
```ts
generateOpenApiSpec({
registrations,
info: { title: 'My API', version: '1.0.0' },
tags: [
{
name: 'users',
description: 'User management endpoints',
externalDocs: { url: 'https://docs.example.com/users' }
}
]
});
```
```
--------------------------------
### Middleware Usage
Source: https://github.com/cleverbrush/framework/blob/master/libs/client/README.md
Example of configuring client with various middleware for enhanced request handling.
```APIDOC
## Client Configuration with Middlewares
### Description
Middlewares wrap the `fetch` call, allowing interception, modification, or short-circuiting of requests and responses. They compose like an onion.
### Example
```javascript
import { createClient } from '@cleverbrush/client';
import { retry } from '@cleverbrush/client/retry';
import { timeout } from '@cleverbrush/client/timeout';
import { dedupe } from '@cleverbrush/client/dedupe';
import { throttlingCache } from '@cleverbrush/client/cache';
const client = createClient(api, {
baseUrl: 'https://api.example.com',
middlewares: [
retry({ limit: 3 }),
timeout({ timeout: 10000 }),
dedupe(),
throttlingCache({ throttle: 2000 }),
],
});
```
```
--------------------------------
### Install Chromium for Playwright
Source: https://github.com/cleverbrush/framework/blob/master/demos/e2e/README.md
Command to install the Chromium browser, necessary for Playwright to run headless browser tests.
```bash
npx playwright install chromium
```
--------------------------------
### Project Directory Structure
Source: https://github.com/cleverbrush/framework/blob/master/demos/e2e/README.md
Overview of the project's directory layout, including setup, support utilities, API tests, and UI tests.
```tree
src/
setup/
global-setup.ts # docker compose orchestration + health waits
support/
auth.ts # createUser(), authedRequest()
clickhouse.ts # waitForRows(), pingClickhouse()
db.ts # pg pool + getUserByEmail / getTodoById / promoteToAdmin
env.ts # config object reading E2E_* vars
http.ts # request() / streamRequest() / json()
ids.ts # uniqueEmail(), uniqueTitle(), shortId()
playwright.ts # withPage(fn) — isolated browser context per test
ws.ts # connectWs(path, {token}) — WebSocket client wrapper
api/ # Vitest project: parallel; ~46 tests, ~70 s
*.api.test.ts # REST + import/export + admin + activity + telemetry
*.ws.test.ts # WebSocket subscriptions
ui/ # Vitest project: serial (singleFork); ~4 tests, ~25 s
*.ui.test.ts # Playwright UI smoke flows
```
--------------------------------
### Direct Fetch Example
Source: https://github.com/cleverbrush/framework/blob/master/libs/client/README.md
Demonstrates how to perform direct HTTP requests using the typed client. All parameters, bodies, and responses are fully type-safe.
```typescript
// Direct fetch (both clients)
const todos = await client.todos.list({ query: { page: 1, limit: 10 } });
// ^? TodoResponse[]
const todo = await client.todos.get({ params: { id: 1 } });
// ^? TodoResponse
const created = await client.todos.create({ body: { title: 'Buy milk' } });
// ^? TodoResponse
await client.todos.delete({ params: { id: 1 } });
// ^? undefined (204 No Content)
```
--------------------------------
### Custom Middleware Example
Source: https://github.com/cleverbrush/framework/blob/master/libs/client/README.md
Demonstrates how to create and use custom middleware to intercept and modify requests and responses.
```APIDOC
## Writing custom middleware
```ts
import type { Middleware } from '@cleverbrush/client';
const logger: Middleware = (next) => async (url, init) => {
console.log('→', init.method, url);
const res = await next(url, init);
console.log('←', res.status);
return res;
};
```
```
--------------------------------
### Quick Start Logger Configuration
Source: https://github.com/cleverbrush/framework/blob/master/libs/log/README.md
Create a logger with console output, hostname, and process ID enrichment. Logs messages at 'information' level or higher. Ensure to dispose of the logger when done.
```typescript
import {
createLogger,
consoleSink,
hostnameEnricher,
processIdEnricher,
} from '@cleverbrush/log';
const logger = createLogger({
minimumLevel: 'information',
sinks: [consoleSink({ theme: 'dark' })],
enrichers: [hostnameEnricher(), processIdEnricher()],
});
logger.info('Server started on port {Port}', { Port: 3000 });
logger.error(new Error('oops'), 'Request failed for {UserId}', { UserId: 42 });
await logger.dispose();
```
--------------------------------
### Resolving Services from the Provider
Source: https://github.com/cleverbrush/framework/blob/master/libs/di/README.md
Demonstrates how to retrieve registered services using `get()` and `getOptional()` from a built `ServiceProvider`.
```typescript
const provider = services.buildServiceProvider();
// Throws if not registered
const config = provider.get(IConfig);
// Returns undefined if not registered (no throw)
const mailer = provider.getOptional(IMailer);
```
--------------------------------
### Register and Handle Endpoints
Source: https://github.com/cleverbrush/framework/blob/master/libs/server/README.md
Initialize a `ServerBuilder` and use the `.handle()` method to register endpoint handlers. Middleware can be applied per-endpoint using an options object. Start the server using `.listen()`.
```typescript
const server = new ServerBuilder();
server.handle(CreateUser, ({ body, context }) => {
return ActionResult.created({ id: 42, ...body }, `/api/users/42`);
});
// Per-endpoint middleware
server.handle(AdminEp, ({ params }) => { /* … */ }, {
middlewares: [loggingMiddleware]
});
await server.listen(3000);
```
--------------------------------
### Defining HTTP Methods
Source: https://github.com/cleverbrush/framework/blob/master/libs/server/README.md
Use the `endpoint` singleton to start a builder chain for defining HTTP methods like GET, POST, PUT, and DELETE.
```APIDOC
## HTTP Methods
Use the `endpoint` singleton to start a builder chain:
```ts
import { endpoint } from '@cleverbrush/server';
const getUser = endpoint.get('/api/users/:id');
const postUser = endpoint.post('/api/users');
const putUser = endpoint.put('/api/users/:id');
const delUser = endpoint.delete('/api/users/:id');
```
```
--------------------------------
### Define HTTP Method Endpoints
Source: https://github.com/cleverbrush/framework/blob/master/libs/server/README.md
Examples of defining endpoints for common HTTP methods (GET, POST, PUT, DELETE) using the `endpoint` singleton.
```typescript
import { endpoint } from '@cleverbrush/server';
const getUser = endpoint.get('/api/users/:id');
const postUser = endpoint.post('/api/users');
const putUser = endpoint.put('/api/users/:id');
const delUser = endpoint.delete('/api/users/:id');
```
--------------------------------
### Client Initialization and Authentication
Source: https://github.com/cleverbrush/framework/blob/master/libs/client/README.md
Demonstrates how to create a client instance and how authentication tokens are automatically appended to WebSocket connections.
```APIDOC
## Client Initialization
### Description
Initialize the client with your API endpoint and configuration, including a method to retrieve authentication tokens.
### Method
`createClient(api, options)`
### Parameters
- **api**: The API endpoint URL.
- **options** (object) - Optional configuration object:
- **baseUrl** (string) - The base URL for API requests.
- **getToken** (function) - A function that returns the authentication token.
### Request Example
```ts
const client = createClient(api, {
baseUrl: 'https://api.example.com',
getToken: () => localStorage.getItem('token'),
});
```
### Authentication
Auth tokens are sent as a `?token=` query parameter for WebSocket connections.
### Request Example
```ts
// Token is automatically appended:
// wss://api.example.com/ws/events?token=
const sub = client.live.events();
```
```
--------------------------------
### Registering and Handling Endpoints
Source: https://github.com/cleverbrush/framework/blob/master/libs/server/README.md
Demonstrates how to build a server instance and register handlers for specific endpoints, including per-endpoint middleware.
```APIDOC
## Registering and Handling Endpoints
```ts
const server = new ServerBuilder();
server.handle(CreateUser, ({ body, context }) => {
return ActionResult.created({ id: 42, ...body }, `/api/users/42`);
});
// Per-endpoint middleware
server.handle(AdminEp, ({ params }) => { /* ... */ }, {
middlewares: [loggingMiddleware]
});
await server.listen(3000);
```
```
--------------------------------
### Build All Libraries
Source: https://github.com/cleverbrush/framework/blob/master/CLAUDE.md
Build all publishable packages within the 'libs' directory, skipping website packages.
```bash
npm run build
```
--------------------------------
### Client Configuration Options
Source: https://github.com/cleverbrush/framework/blob/master/libs/client/README.md
Details the parameters available for `createClient`, including `baseUrl`, `getToken`, `onUnauthorized`, custom `fetch` implementation, default `headers`, `middlewares`, and `hooks`.
```markdown
| Parameter | Type | Description |
|-----------|------|-------------|
| `contract` | `ApiContract` | Contract created with `defineApi()` |
| `options.baseUrl` | `string` | Base URL prepended to every request (default: `''`) |
| `options.getToken` | `() => string \| null` | Returns auth token for `Authorization: Bearer` header |
| `options.onUnauthorized` | `() => void` | Called on 401 responses |
| `options.fetch` | `typeof fetch` | Custom fetch implementation (default: `globalThis.fetch`) |
| `options.headers` | `Record` | Extra headers sent with every request |
| `options.middlewares` | `Middleware[]` | Middleware functions that wrap the fetch call |
| `options.hooks` | `ClientHooks` | Lifecycle hooks invoked at various stages of a request |
```
--------------------------------
### View Demo Backend Logs
Source: https://github.com/cleverbrush/framework/blob/master/demos/e2e/README.md
Command to view logs from the demo backend service, useful for troubleshooting startup issues.
```bash
docker logs demos-backend-1
```
--------------------------------
### Build and Typecheck Docs Site
Source: https://github.com/cleverbrush/framework/blob/master/AGENTS.md
This command sequence builds all packages and performs typechecking specifically for the documentation website.
```bash
npm run lint && npm run build
npm run typecheck:docs-site
```
--------------------------------
### Run Quality Gates (Lint, Build, Test)
Source: https://github.com/cleverbrush/framework/blob/master/README.md
Execute these commands to ensure code quality and that all tests pass before committing changes. Website changes may require specific site build commands.
```bash
npm run lint
npm run build
npm run test
```
--------------------------------
### Endpoint Authorization
Source: https://github.com/cleverbrush/framework/blob/master/libs/server/README.md
Examples of securing endpoints using `authorize()`. The first example protects against any authenticated user, while the second restricts access to users with the 'admin' role.
```typescript
import { object, string } from '@cleverbrush/schema';
const UserPrincipal = object({ sub: string(), role: string() });
// Any authenticated user
const ProtectedEp = endpoint.get('/api/profile').authorize(UserPrincipal);
// Specific roles
const AdminEp = endpoint.delete('/api/users/:id').authorize(UserPrincipal, 'admin');
```
--------------------------------
### Validate Object Schema and Get Per-Property Errors
Source: https://github.com/cleverbrush/framework/blob/master/libs/schema/README.md
Use `ObjectSchemaBuilder.validate()` with `doNotStopOnFirstError: true` to get detailed validation results, including errors for individual properties via `getErrorsFor()`. This is the recommended method for inline form error display.
```typescript
const PersonSchema = object({
name: string().minLength(1),
address: object({
city: string(),
zip: number()
})
});
const result = PersonSchema.validate(person, {
doNotStopOnFirstError: true
});
if (!result.valid) {
// Get errors for a single property
const nameErrors = result.getErrorsFor((p) => p.name);
console.log(nameErrors.isValid); // false
console.log(nameErrors.errors); // ['must be at least 1 character']
console.log(nameErrors.seenValue); // the value that was validated
// Works with nested properties too
const cityErrors = result.getErrorsFor((p) => p.address.city);
console.log(cityErrors.errors);
}
```
--------------------------------
### Build and Test Project
Source: https://github.com/cleverbrush/framework/blob/master/CONTRIBUTING.md
Build all packages in the monorepo and run tests with typechecking.
```bash
npm run build
npm run test
```
--------------------------------
### GET /asyncapi.json
Source: https://github.com/cleverbrush/framework/blob/master/libs/server-openapi/README.md
Exposes an AsyncAPI 3.0 document for WebSocket subscriptions via middleware.
```APIDOC
## GET /asyncapi.json
### Description
Serves an automatically generated AsyncAPI 3.0 document based on WebSocket subscription registrations.
### Method
GET
### Endpoint
/asyncapi.json
### Response
#### Success Response (200)
- **body** (object) - The generated AsyncAPI 3.0 specification document.
```
--------------------------------
### Bootstrap OpenTelemetry SDK
Source: https://github.com/cleverbrush/framework/blob/master/libs/otel/README.md
Initialize the OpenTelemetry SDK with your service details and desired instrumentations. This must be run before any other code that relies on telemetry.
```typescript
// telemetry.ts — load FIRST
import {
setupOtel
} from '@cleverbrush/otel';
import {
outboundHttpInstrumentations,
runtimeMetrics
} from '@cleverbrush/otel/instrumentations';
export const otel = setupOtel({
serviceName: 'todo-backend',
serviceVersion: '1.0.0',
environment: process.env.NODE_ENV,
otlpEndpoint: process.env.OTEL_EXPORTER_OTLP_ENDPOINT,
instrumentations: [
...outboundHttpInstrumentations(),
...runtimeMetrics()
]
});
```
--------------------------------
### Cache Tags
Source: https://github.com/cleverbrush/framework/blob/master/libs/server/README.md
Defines how to use cache tags for invalidation on GET endpoints and how mutations can clear these tags.
```APIDOC
## Cache Tags
Tag-based cache invalidation. Tags declared on endpoints flow to the
[`cacheTags` middleware](/client/cache-tags) for automatic HTTP caching and
invalidation on mutating requests.
### Declaring Cache Tags
- **`.cacheTag(name)`**: Declares the endpoint's data belongs to a cache group. Use on GET endpoints.
- **`.clearsCacheTag(name)`**: Declares that this mutation clears matching cache entries on success. Use on POST / PUT / PATCH / DELETE.
- **`.cacheTag(name, p => ({ ... }))`**: Property-based tag; each selected property becomes part of the cache key (different pages → different entries).
- **Immutability**: Both methods return a new builder; the original is unchanged.
```ts
const ListTodos = endpoint
.get('/api/todos')
.query(TodoListQuerySchema)
.cacheTag('todo-list', p => ({ page: p.query.page, limit: p.query.limit }))
.returns(array(TodoSchema));
const UpdateTodo = endpoint
.patch('/api/todos/:id')
.body(UpdateTodoBody)
.clearsCacheTag('todo-list') // clears the collection cache
.clearsCacheTag('todo', p => ({ id: p.params.id })) // clears specific entity
.returns(TodoSchema);
```
```
--------------------------------
### Build and Typecheck Schema Site
Source: https://github.com/cleverbrush/framework/blob/master/AGENTS.md
This command sequence builds all packages and performs typechecking specifically for the schema website.
```bash
npm run lint && npm run build
npm run typecheck:schema-site
```
--------------------------------
### Validate Any Promise with `promise()`
Source: https://github.com/cleverbrush/framework/blob/master/libs/schema/README.md
Use `promise()` to validate that a value is a JavaScript Promise. This example shows untyped validation.
```typescript
import { promise, string, number, InferType } from '@cleverbrush/schema';
// Untyped — validates that the value is any Promise
const anyPromise = promise();
anyPromise.validate(Promise.resolve(42)); // { valid: true }
anyPromise.validate('not a promise' as any); // { valid: false }
```
--------------------------------
### Retrieve and execute a mapper function
Source: https://github.com/cleverbrush/framework/blob/master/libs/mapper/README.md
Use the registry to get a registered mapping function and apply it to a source object.
```typescript
const mapFn = registry.getMapper(ApiUser, DomainUser);
const result = await mapFn(sourceObject);
```
--------------------------------
### Dependency Injection
Source: https://github.com/cleverbrush/framework/blob/master/libs/server/README.md
Illustrates how to use dependency injection to provide services, like repositories, to endpoint handlers.
```APIDOC
## Dependency Injection
```ts
import { ServiceCollection } from '@cleverbrush/di';
import { object, func, string } from '@cleverbrush/schema';
const IUserRepo = object({ findById: func() });
const GetUser = endpoint
.get('/api/users/:id')
.inject({ repo: IUserRepo });
server
.services(svc => svc.addSingleton(IUserRepo, () => new UserRepository()))
.handle(GetUser, ({ params }, { repo }) => {
return repo.findById(params.id);
});
```
```
--------------------------------
### toJsonSchema Function
Source: https://github.com/cleverbrush/framework/blob/master/libs/schema-json/README.md
Converts a `@cleverbrush/schema` builder to a JSON Schema object. It handles descriptions, examples, and discriminated unions automatically.
```APIDOC
## toJsonSchema(schema, opts?)
### Description
Converts a `@cleverbrush/schema` builder to a JSON Schema object.
### Signature
```ts
function toJsonSchema(
schema: SchemaBuilder,
opts?: ToJsonSchemaOptions,
): Record
```
### Parameters
#### Parameters
- **schema** (SchemaBuilder) - Required - any builder from `@cleverbrush/schema`
- **opts** (ToJsonSchemaOptions) - Optional - optional output configuration
### Returns
A plain JavaScript object that is safe to `JSON.stringify`.
### Features
- Descriptions set via `.describe(text)` are emitted as the `description` field.
- Examples set via `.example(value)` are emitted as the `examples` array.
#### Discriminated unions
When a `union()` is a discriminated union (all branches are objects sharing a required property with unique literal values), `toJsonSchema()` automatically emits the `discriminator` keyword alongside `anyOf`.
When a `nameResolver` is provided and union branches resolve to `$ref` pointers, a `mapping` is also emitted, enabling code-generation tools to produce proper tagged union types.
#### `ToJsonSchemaOptions`
| Option | Type | Default | Description |
| --- | --- | --- | --- |
| `draft` | `'2020-12' | '07'` | `'2020-12'` | JSON Schema draft version for the `$schema` URI |
| `$schema` | `boolean` | `true` | Whether to include the `$schema` header in the output |
| `nameResolver` | `(schema: SchemaBuilder) => string | null` | `undefined` | Called for every node before conversion. Return a non-null string to emit `{ $ref: '#/components/schemas/' }` instead of an inline schema. |
### Examples
```ts
// Embed in OpenAPI (suppress the $schema header)
t অনুমোদিত(schema, { $schema: false });
// Use Draft 07
t অনুমোদিত(schema, { draft: '07' });
```
```
--------------------------------
### Embed Schema in OpenAPI
Source: https://github.com/cleverbrush/framework/blob/master/libs/schema-json/README.md
Example of using `toJsonSchema` to embed a schema within an OpenAPI specification by suppressing the `$schema` header.
```typescript
toJsonSchema(schema, { $schema: false });
```
--------------------------------
### Run Node.js with Telemetry Import
Source: https://github.com/cleverbrush/framework/blob/master/libs/otel/README.md
Execute your Node.js application, ensuring the telemetry initialization script is imported first.
```bash
node --import ./dist/telemetry.js dist/index.js
```
--------------------------------
### JobScheduler Events
Source: https://github.com/cleverbrush/framework/blob/master/libs/scheduler/README.md
Emits events related to job execution lifecycle, including start, end, errors, timeouts, and messages.
```APIDOC
## JobScheduler Events
### `job:start`
Emitted when a job begins execution.
```typescript
scheduler.on('job:start', ({ jobId, instanceId, startDate }) => { ... });
```
### `job:end`
Emitted when a job completes successfully.
```typescript
scheduler.on('job:end', ({ jobId, instanceId, startDate, endDate, stdout, stderr }) => { ... });
```
### `job:error`
Emitted when a job encounters an error during execution.
```typescript
scheduler.on('job:error', ({ jobId, instanceId, startDate, endDate, stdout, stderr }) => { ... });
```
### `job:timeout`
Emitted when a job exceeds its specified timeout.
```typescript
scheduler.on('job:timeout', ({ jobId, instanceId, startDate, endDate }) => { ... });
```
### `job:message`
Emitted when a job sends a message to the scheduler.
```typescript
scheduler.on('job:message', ({ jobId, instanceId, message }) => { ... });
```
#### Event Payload Properties:
- `jobId` (string): The ID of the job.
- `instanceId` (string): A unique identifier for this specific job run.
- `startDate` (Date): The timestamp when the job started.
- `endDate` (Date): The timestamp when the job ended.
- `stdout` (string): The standard output from the job execution.
- `stderr` (string): The standard error output from the job execution.
- `message` (any): The message payload sent from the job.
```
--------------------------------
### Use JSON Schema Draft 07
Source: https://github.com/cleverbrush/framework/blob/master/libs/schema-json/README.md
Example of configuring `toJsonSchema` to output JSON Schema using the Draft 07 specification.
```typescript
toJsonSchema(schema, { draft: '07' });
```
--------------------------------
### Queries with Parameters
Source: https://github.com/cleverbrush/framework/blob/master/libs/client/README.md
Demonstrates how to fetch data for a specific resource using query parameters, such as an item's ID.
```APIDOC
## Queries with Parameters
```tsx
function TodoDetail({ id }: { id: number }) {
const { data } = client.todos.get.useQuery({ params: { id } });
return
{data?.title}
;
}
```
```
--------------------------------
### Convert SchemaBuilder to JSON Schema
Source: https://github.com/cleverbrush/framework/blob/master/libs/schema-json/README.md
Converts a schema builder instance into a JSON Schema object. Descriptions and examples from the builder are preserved.
```typescript
function toJsonSchema(
schema: SchemaBuilder,
opts?: ToJsonSchemaOptions,
): Record
```
--------------------------------
### Initialize Knex with ClickhouseKnexClient
Source: https://github.com/cleverbrush/framework/blob/master/libs/knex-clickhouse/README.md
Directly use ClickhouseKnexClient with Knex for more control over initialization. Requires importing Knex and ClickhouseKnexClient.
```typescript
import Knex from 'knex';
import { ClickhouseKnexClient } from '@cleverbrush/knex-clickhouse';
const db = Knex({
client: ClickhouseKnexClient,
connection: {
url: 'http://localhost:8123',
user: 'default',
password: '',
database: 'my_database'
}
});
```
--------------------------------
### Snapshot Documentation
Source: https://github.com/cleverbrush/framework/blob/master/DOCS_PIPELINE.md
Commands to snapshot the current documentation for a specific release version.
```bash
npm run docs # regenerate latest
npm run docs:snapshot # copies latest/ → v{version}/, updates picker
git add website/public/api-docs/
git commit -m "docs: snapshot v1.2.0 API reference"
```
--------------------------------
### query(knex, schema, baseQuery?)
Source: https://github.com/cleverbrush/framework/blob/master/libs/knex-schema/README.md
Creates a `SchemaQueryBuilder`. `schema` must have `.hasTableName()` set. Optionally pass a `baseQuery` as the starting point.
```APIDOC
## `query(knex, schema, baseQuery?)`
Creates a `SchemaQueryBuilder`. `schema` must have `.hasTableName()` set.
Optionally pass a `baseQuery` (e.g. a scoped `knex('users').where('deleted_at', null)`) as the starting point.
```
--------------------------------
### Run UI End-to-End Tests
Source: https://github.com/cleverbrush/framework/blob/master/demos/e2e/README.md
Execute only the UI project's end-to-end tests. This requires Chromium to be installed. This command is run from the repository root.
```bash
npm run test:e2e:ui
```