# API Overview

The generated reference is written to `dist/docs/` by `npm run build:docs`, and served at `http://localhost/docs/` by
the documentation site. This page is the short version, plus the rule that decides what belongs on it.

## What counts as API

A symbol is public when it is re-exported from [`src/index.ts`](../../src/index.ts) or
[`src/middlewares/index.ts`](../../src/middlewares/index.ts), and internal when it is not. There is no second mechanism:
`package.json#exports` names only those two entries and the bundles built from them, so nothing under `lib/` reaches a
consumer by any other path.

Both files are barrels. Behaviour lives in the layers beneath them, so the public surface is something you can see at a
glance rather than something you have to read code to determine.

## The main entry

```ts
import { … } from '@bayudwiyansatria/cloudflare'
```

### Bindings

One accessor per Cloudflare binding, all over the abstract `Binding` base.

| Export                 | Wraps                    | `wrangler.json` key         |
| ---------------------- | ------------------------ | --------------------------- |
| `AIBinding`            | `Ai`                     | `ai`                        |
| `AnalyticsBinding`     | `AnalyticsEngineDataset` | `analytics_engine_datasets` |
| `D1Binding`            | `D1Database`             | `d1_databases`              |
| `DurableObjectBinding` | `DurableObjectNamespace` | `durable_objects.bindings`  |
| `HyperdriveBinding`    | `Hyperdrive`             | `hyperdrive`                |
| `KVBinding`            | `KVNamespace`            | `kv_namespaces`             |
| `QueueBinding`         | `Queue`                  | `queues.producers`          |
| `R2Binding`            | `R2Bucket`               | `r2_buckets`                |
| `RateLimitBinding`     | `RateLimit`              | `ratelimits`                |
| `VectorizeBinding`     | `Vectorize`              | `vectorize`                 |

`Binding` itself is exported so a project can add an accessor for a binding this package does not cover yet.

### Services

One capability service per accessor, each implementing an interface from `@bayudwiyansatria/core`. This is the layer
business logic should depend on.

| Export                 | Implements              |
| ---------------------- | ----------------------- |
| `AIService`            | `InferenceEngine`       |
| `AnalyticsService`     | `TelemetrySink`         |
| `D1Service`            | `DataStore`             |
| `DurableObjectService` | `CoordinationStore`     |
| `HyperdriveService`    | `SqlConnectionProvider` |
| `KVService`            | `CacheStore`            |
| `QueueService`         | `MessageQueue`          |
| `R2Service`            | `ObjectStore`           |
| `RateLimitService`     | `RateLimiter`           |
| `VectorizeService`     | `VectorIndex`           |

Depending on the interface rather than the class is what lets a service be substituted — including for one of the
kernel's `Noop*` implementations in a test.

### Configuration, platform, and errors

| Export                                                  | Kind      | Notes                                                        |
| ------------------------------------------------------- | --------- | ------------------------------------------------------------ |
| `cloudflareDefaults`                                    | constant  | the binding-backed half of the configuration surface         |
| `CloudflareRequestMetadata`                             | class     | the one reader of `cf-ray`, `cf-connecting-ip`, `request.cf` |
| `MissingBindingError`                                   | class     | extends the kernel's `MissingCapabilityError`                |
| `CloudflareEnv`                                         | interface | the environment contract a consuming Worker extends          |
| twelve `*Settings` interfaces                           | types     | the shape of each module's configuration                     |
| `HyperdriveCredentials`, `D1Statement`, `D1WriteResult` | types     | supporting shapes                                            |

## The `./middlewares` entry

```ts
import { logToAnalytics, SecurityMiddleware } from '@bayudwiyansatria/cloudflare/middlewares'
```

| Export               | Kind               | Notes                                               |
| -------------------- | ------------------ | --------------------------------------------------- |
| `SecurityMiddleware` | class              | CORS, origin guard, client-IP capture, API-key auth |
| `logToAnalytics`     | middleware handler | one log line and one metric per request             |

Separate because `hono` is an **optional** peer dependency. A Worker that uses the bindings but not this middleware
never resolves Hono at all — and that only holds while nothing outside `src/middlewares/` imports it, which a lint rule
enforces.

## Errors across the package boundary

`MissingBindingError` extends `MissingCapabilityError` from the kernel, so an application can catch the general case
without naming Cloudflare:

```ts
import { MissingCapabilityError } from '@bayudwiyansatria/core'

try {
  await db.first(env, 'SELECT 1')
} catch (error) {
  if (error instanceof MissingCapabilityError) {
    // a resource this deployment never provisioned
  }
}
```

That `instanceof` holds only while a single copy of the kernel is loaded, which is why `rollup.config.ts` marks it
external and the `assertExternals` plugin beside it fails the build if that ever stops holding.

## Adding to the surface

Adding an export is a deliberate act, not a side effect of writing a file:

1. Write the declaration in its own file, named after it.
2. Re-export it from the directory barrel.
3. Re-export it from `src/index.ts` (or `src/middlewares/index.ts`) with a documented `@module` entry.

Skipping step 3 keeps it internal, which is the right answer for anything a consumer has no reason to touch.
