> ## Documentation Index
> Fetch the complete documentation index at: https://kweri.uchenna.xyz/llms.txt
> Use this file to discover all available pages before exploring further.

# kweri-gen

> Generate type-safe client code from any OpenAPI specification.

## Overview

`kweri-gen` takes an OpenAPI 3.x specification and generates a single
`client.ts` file **into your own source tree**, containing:

* **TypeBox schemas** for every component and endpoint (method, path, parameters, responses)
* **`EndpointByMethod`** — the unified map used by `createReactPathHooks` and `createVuePathHooks`
* **`createClient`** — a typed client whose every method runs through the kweri runtime (cache, request dedup, stale-while-revalidate)

The output is plain TypeScript that your own build compiles. Commit it like any
other source file.

## Usage

```bash theme={null}
kweri-gen <openapi-source> [options]

Arguments:
  <openapi-source>    URL or local file path to an OpenAPI JSON or YAML spec

Options:
  -o, --out <dir>        Output directory (default: src/api/kweri)
  -f, --filename <name>  Output file name (default: client.ts; .ts appended if missing)
  -h, --help             Show help
```

External and internal `$ref` pointers are resolved automatically — there is no
separate bundling flag.

### Examples

```bash theme={null}
# From a URL (writes src/api/kweri/client.ts)
kweri-gen https://api.example.com/openapi.json

# From a local file, into a custom directory and file name
kweri-gen ./openapi.json --out src/generated --filename stocks

# A spec with external $refs (resolved automatically)
kweri-gen https://petstore3.swagger.io/api/v3/openapi.json
```

```json package.json theme={null}
{
  "scripts": {
    "gen": "kweri-gen https://api.example.com/openapi.json --out src/api/kweri"
  }
}
```

<Note>
  Run `kweri-gen` as an explicit `gen` script and commit the output — **not** as a
  `postinstall` hook. Writing into your own tree means the generated client
  survives reinstalls and works under npm, pnpm, and Yarn PnP.
</Note>

## Output

The generated file is written to `<out>/client.ts` (default
`src/api/kweri/client.ts`), relative to the current working directory.

### File structure

```ts theme={null}
// src/api/kweri/client.ts (abbreviated)

// AUTO-GENERATED by kweri-gen — do not edit by hand.
import { Type, type Static, type Endpoint, type Kweri } from "kweri"

// One TypeBox schema per endpoint
export const get_GetUser = Type.Object({
  method:     Type.Literal("GET"),
  path:       Type.Literal("/users/{id}"),
  parameters: Type.Object({ path: Type.Object({ id: Type.String() }) }),
  responses:  Type.Object({ 200: User })
})

// Unified map used by the path hooks
export const EndpointByMethod = {
  get:    { "/users": get_ListUsers, "/users/{id}": get_GetUser },
  post:   { "/users": post_CreateUser },
  delete: { "/users/{id}": delete_DeleteUser },
}

// Typed client — every call routes through kweri
export class GeneratedClient {
  private kweri: Kweri
  constructor(kweri: Kweri) { this.kweri = kweri }
  async getUser(params: Static<typeof get_GetUser>['parameters']): Promise<Static<typeof get_GetUser>['responses'][200]> {
    return this.kweri.query(__endpoint('GET', '/users/{id}'), params as any) as any
  }
  // ...
}

export function createClient(kweri: Kweri): GeneratedClient { /* ... */ }
```

## Using the generated client

Because the client routes through kweri, every call is cached and deduplicated:

```ts theme={null}
import { Kweri } from 'kweri'
import { createClient } from './api/kweri/client'

const kweri = new Kweri({ baseURL: 'https://api.example.com' })
const api = createClient(kweri)

const user = await api.getUser({ path: { id: '123' } })
```

## Using with path-based hooks

The generated `EndpointByMethod` works directly with `createReactPathHooks` and
`createVuePathHooks`. Import it from your generated file:

<Tabs>
  <Tab title="React">
    ```ts theme={null}
    import { useSyncExternalStore } from 'react'
    import { createReactPathHooks } from 'kweri'
    import { EndpointByMethod } from './api/kweri/client'
    import { kweri } from '@/lib/kweri'

    export const { useGet, usePost, usePut, usePatch, useDelete } =
      createReactPathHooks(useSyncExternalStore, kweri, EndpointByMethod)
    ```
  </Tab>

  <Tab title="Vue">
    ```ts theme={null}
    import { ref, watch, onUnmounted } from 'vue'
    import { createVuePathHooks } from 'kweri'
    import { EndpointByMethod } from './api/kweri/client'
    import { kweri } from '@/lib/kweri'

    export const { useGet, usePost, usePut, usePatch, useDelete } =
      createVuePathHooks({ ref, watch, onUnmounted }, kweri, EndpointByMethod)
    ```
  </Tab>
</Tabs>

## How endpoint resolution works

When you call `useGet('/users', {})`, the path hook:

1. Lowercases the method: `'get'`
2. Looks up `EndpointByMethod['get']['/users']` → the TypeBox schema (for types)
3. Extracts the `responses.200` (or `responses.201`) schema as the response type
4. Constructs a temporary `Endpoint` with `params: Type.Any()` (skips runtime param validation)
5. Delegates to the underlying `useQuery`

If the path isn't found in the map, the hook throws:

```
[kweri] No endpoint registered for GET /unknown-path
```

## Regenerating

Re-run `kweri-gen` whenever your API spec changes. The output file is completely
regenerated each time — don't edit `client.ts` by hand, your changes will be
overwritten. Commit the regenerated file so builds are deterministic and don't
depend on the API being reachable at build time.
