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

# Typed Resources

> Declare external data, bind a deployment and query ordinary typed tables

A resource declares the external data your application uses. Deployment bindings
supply its coordinates and a reference to a private credential. The generated
`resources` namespace connects these two parts without handwritten addresses.

```mermaid theme={"theme":{"light":"github-light-default","dark":"github-dark-default"}}
flowchart LR
  D[Resource declaration] --> G[Code generation]
  G --> R[Typed resource reference]
  R --> B[Deployment binding]
  C[Private credential inventory] --> B
  B --> S[Existing source owner]
  S --> T[Typed table]
  T --> Q[Reactive query]
  R --> W[Durable calls]
```

## Declare resources

```ts bijection/sources.ts theme={"theme":{"light":"github-light-default","dark":"github-dark-default"}}
import { dataset, kubernetes, pubsub } from "@bijectionhq/component-support/connectors";
import { v } from "bijection/values";

export const inventory = dataset.table({
  schema: { sku: v.string(), available: v.number() },
});
export const orders = pubsub.subscription({
  schema: { orderId: v.string(), amount: v.number() },
});
export const pods = kubernetes.pods();
```

These declarations contain schemas and provider semantics. Endpoints, dataset
names, subscriptions, namespaces and credentials belong to the deployment.
Dataset fields default to the schema's names; supply `fields` when source names differ.

```ts bijection/schema.ts theme={"theme":{"light":"github-light-default","dark":"github-dark-default"}}
import { defineSchema, defineTable } from "bijection/server";
import { inventory, orders, pods } from "./sources";
import { internal } from "./_generated/api";

export default defineSchema({
  tables: {
    inventory: defineTable(inventory)
      .access({ read: internal.access.readResources, reads: [] }).index("by_sku", ["sku"]),
    orders: defineTable(orders)
      .access({ read: internal.access.readResources, reads: [] }).index("by_order", ["data.orderId"]),
    pods: defineTable(pods)
      .access({ read: internal.access.readResources, reads: [] }).index("by_namespace", ["metadata.namespace"]),
  },
});
```

The example uses one read policy for signed-in application users. Bind your
application's narrower policies here when resources belong to different owners.
Source-owned tables already have their native write boundary.

```ts bijection/access.ts theme={"theme":{"light":"github-light-default","dark":"github-dark-default"}}
import { internalQuery } from "./_generated/server";
import { readAccessArgs, readAccessResults } from "bijection/server";

export const readResources = internalQuery({
  policy: { reads: [] },
  args: readAccessArgs,
  returns: readAccessResults,
  handler: async (ctx, { requests }) => {
    if (!(await ctx.auth.getUserIdentity())) throw new Error("Sign in first");
    return requests.map(() => null);
  },
});
```

`defineTable(resource)` infers the record type. There is no second validator to
keep synchronized. Pub/Sub rows are message occurrences with `messageId`,
`publishedAt`, `attributes` and typed `data`. Pods expose typed `metadata`, `spec`
and `status` fields.

## Bind a deployment

Provision each private credential with `bijection connection credential create <name> --from-file <file>`. The credential's provider-specific envelope contains
authentication material; put non-secret installation values in setup.

Place this file next to `bijection.json`:

```ts bijection.bindings.ts theme={"theme":{"light":"github-light-default","dark":"github-dark-default"}}
import { bind, defineBindings } from "bijection/deployment";
import { dataset, kubernetes, pubsub } from "@bijectionhq/component-support/connectors";
import { resources } from "./bijection/_generated/api";

export default defineBindings([
  bind(resources.sources.inventory, {
    setup: { endpoint: "https://reader.example.com", dataset: "inventory" },
    credential: dataset.credential("INVENTORY"),
  }),
  bind(resources.sources.orders, {
    setup: { subscription: "projects/acme/subscriptions/orders" },
    credential: pubsub.credential("ORDERS"),
  }),
  bind(resources.sources.pods, {
    setup: { endpoint: "https://cluster.example.com", namespace: "production" },
    credential: kubernetes.credential("CLUSTER"),
  }),
]);
```

The usual `bijection dev` and deployment push load this file after code generation
and apply it after the code and schema are deployed. Imported configuration files
participate in the dev watch. Dry runs validate the file without applying it.
The bindings program runs in the CLI and is never uploaded as application code.

The deployed resource contract validates setup and credential references. Binding
verifies provider identity, installs the existing source owner and schedules
acquisition. Reapplying unchanged configuration preserves its generation. Removing
a binding entry retains imported data and private credentials.

## Query and observe

```ts bijection/inventory.ts theme={"theme":{"light":"github-light-default","dark":"github-dark-default"}}
import { query } from "./_generated/server";
import { resources } from "./_generated/api";

export const list = query({
  args: {},
  handler: (ctx) => ctx.db.query("inventory").take(50),
});
export const status = query({
  args: {},
  handler: (ctx) => ctx.resources.status(resources.sources.inventory),
});
```

These are ordinary reactive queries. `useQuery(api.inventory.list)` receives typed
rows through the normal client. Resource status uses the installed source's
existing authority and query dependencies. It reports serving evidence separately
from acquisition work. An acquisition interval does not promise population
coverage or freshness. A missing or ambiguous installation produces a diagnostic;
use an explicit `sourceId` to select among authorized installations.

## Share a connection

The simple binding above supplies everything at once. An operator program can
share connection-owned fields and credential custody across several resources:

```ts theme={"theme":{"light":"github-light-default","dark":"github-dark-default"}}
import { createDeploymentManagement } from "bijection/browser";

const management = createDeploymentManagement({ url, adminKey });
const cluster = await management.connections.create(resources.sources.pods, {
  setup: { endpoint: "https://cluster.example.com" },
  credential: kubernetes.credential("CLUSTER"),
});
const binding = await management.resources.bind(resources.sources.pods, {
  connection: cluster,
  setup: { namespace: "production" },
});
await management.resources.ready(binding);
```

The deployed declaration determines which fields the connection owns. A shared
binding cannot override those fields or its credential. Connections are immutable
and identified by their admitted configuration. Changing one creates a new
connection; each binding explicitly selects it and pins its own generation and
credential revision. Background work never silently switches configuration.

## Preserve atomic acquisition groups

Some providers acquire several tables together. Declare one group and bind it once:

```ts bijection/sources.ts theme={"theme":{"light":"github-light-default","dark":"github-dark-default"}}
import { postgres } from "@bijectionhq/component-support/connectors";
import { v } from "bijection/values";

export const sales = postgres.database({
  tables: {
    orders: { id: v.int64(), customerId: v.int64() },
    lines: { id: v.int64(), orderId: v.int64(), amount: v.int64() },
  },
});
```

Use `defineTable(sales.tables.orders)` and `defineTable(sales.tables.lines)` in the
schema. PostgreSQL keeps its consistent initial snapshot and atomic transaction
publication. Mail accounts similarly expose `tables.messages`, `tables.contents`
and `tables.memberships` under one acquisition owner. A group status read selects
a typed collection name:

```ts theme={"theme":{"light":"github-light-default","dark":"github-dark-default"}}
await ctx.resources.status(resources.sources.sales, { collection: "orders" });
```

## Commands use durable calls

Generated resource references expose only declared commands, with inferred
arguments, under `resources.<module>.<export>.commands`. Submit them from mutations
through `ctx.calls.add`. A command changing a record requires its local target.
A collection create can infer its target when exactly one resource source is
installed. A child create still requires its parent record.

For example, a Calendar resource's update capability uses the ordinary mutation
and generated-reference conventions:

```ts theme={"theme":{"light":"github-light-default","dark":"github-dark-default"}}
export const renameEvent = mutation({
  args: { id: v.id("calendarEvents"), summary: v.string() },
  handler: (ctx, args) => ctx.calls.add(
    "rename",
    resources.sources.calendar.commands.updateEvent,
    { target: args.id, args: { summary: args.summary } },
  ),
});
```

The native command owner retains occurrence identity, policy, approval, connection
and source custody. Retrying a mutation retains the same call. A lost provider
answer remains unknown when the provider supplies no proof or safe retry contract.
Resource declarations do not invent write capabilities or delivery guarantees.

## Provider recipes

All constructors are exported by `@bijectionhq/component-support/connectors`.
They compose the existing native protocols and their evidence rules.

| Provider | Declaration | Output |
| - | - | - |
| Dataset | `dataset.table({ schema })` | Projected accepted dataset records |
| Pub/Sub | `pubsub.subscription({ schema })` | Typed message occurrences |
| Kubernetes | `kubernetes.pods()` | Structured Pod observations |
| MongoDB | `mongo.collection({ schema })` | Projected documents |
| Convex | `convex.table({ schema })` | Projected export and document-log records |
| DynamoDB | `dynamodb.table()` | Native keyed item observations |
| Git | `git.references()` | Reference, commit and changed paths |
| Sheets | `sheets.rows()` | Enrolled row identities and string cells |
| BigQuery | `bigquery.appends({ schema })` | Typed append payloads and exact window text |
| SQL | `sql.table({ schema, dialect, key, changes })` | Projected relational records |
| OData | `odata.entities({ schema, key })` | Projected entity observations |
| SFTP | `sftp.directory()` | File metadata, inline bytes or protected files |
| AS2 | `as2.documents({ schema, document, items })` | Decoded interchange items |
| PostgreSQL | `postgres.database({ tables })` | One atomic group of typed tables |
| Mail | `mailbox.account()` | Messages, content and memberships together |
| Bayeux | `bayeux.channel({ schema, path, channel, identity, events })` | Typed event occurrences |
| Salesforce | `salesforce.events({ schema, event })`, `salesforce.changes({ schema, object })` | Typed platform/CDC events; gaps remain explicit |
| Pulsar | `pulsar.subscription({ topic, schema })` | Typed message occurrences |
| Kinesis | `kinesis.stream({ stream, schema })` | Typed message occurrences |
| SQS | `sqs.queue({ queue, schema })` | Typed message occurrences |
| Service Bus | `serviceBus.subscription({ entity, schema })` | Typed message occurrences |
| Redis | `redis.stream({ stream, schema })` | Typed message occurrences |
| JetStream | `jetstream.stream({ stream, schema })` | Typed message occurrences |
| RabbitMQ | `rabbitmq.stream({ stream, schema })`, `rabbitmq.queue({ queue, schema })` | Typed message occurrences |
| MQTT | `mqtt.topic({ topic, identity, schema })` | Occurrences keyed by declared publisher identity |
| Kafka | `kafka.latest({ topic, record, latest })` | Typed latest rows with declared ordering |
| Google Calendar | `googleCalendar.calendar({ governingRules })` | HTTP event reads and declared commands |

Broker routing names remain logical declarations where the native protocol owns
routing. Endpoints, subscriptions and credentials remain deployment configuration.
Operational messages validate JSON and the declared schema before acknowledging
receipts. Raw archives, event histories, conditional writes and custom HTTP
protocols remain explicit capabilities of the lower-level authoring primitives.

Connector authors use `defineResource` or `defineResourceGroup` from
`bijection/connectors` over an ordinary integration. These primitives emit the
resource metadata that code generation, shared connections, bindings and the
native admission owner all consume.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.