# pgflow 0.5.4: Context - Simplify Your Handler Functions

import { Aside, Steps } from "@astrojs/starlight/components";

<Aside type="caution" title="API Change in v0.6.0">
  **Breaking Change**: Starting with pgflow v0.6.0, the context API has been simplified. The `anonSupabase` and `serviceSupabase` clients have been replaced with a single `supabase` client (initialized with service role key).

  If you're using v0.6.0 or later, replace any usage of `ctx.anonSupabase` or `ctx.serviceSupabase` with `ctx.supabase`.
</Aside>

Workers now pass a **context object** as a second parameter to all handlers, providing ready-to-use database connections, environment variables, and Supabase clients.

## The Problem We Solved

Previously, handlers relied on global singletons or manual resource initialization:

```typescript del={2,3} ins="ctx" ins="ctx.sql" ins="ctx.serviceSupabase"
// Before: Global resources that complicated testing and lifecycle management
import { sql } from '../db.js';
import { supabase } from '../supabase-client.js';

// After: Clean dependency injection via context
async function processPayment(input, ctx) {
  const [payment] = await ctx.sql`
    SELECT * FROM payments WHERE id = ${input.paymentId}
  `;
  await ctx.serviceSupabase.from('audit_logs').insert({
    action: 'payment_processed',
    payment_id: input.paymentId
  });
}
```

## What's in the Context

**Core resources** (always available):
- `env` - Environment variables
- `shutdownSignal` - AbortSignal for graceful shutdown
- `rawMessage` - pgmq message metadata (msg_id, read_ct, etc.)
- `stepTask` - Step execution details (flows only)

**Supabase resources**:
- `sql` - PostgreSQL client (postgres.js)
- `anonSupabase` - Client with anon key (respects RLS)
- `serviceSupabase` - Client with service role (bypasses RLS)

## Key Benefits

1. **Zero Configuration** - No connection boilerplate
2. **Managed Resources** - pgflow handles pooling and lifecycle
3. **Type Safety** - Full TypeScript support
4. **Testable** - Mock only what you use:

```typescript ins="{ env: { API_KEY: 'test' } }"
// Handler uses only env? Test with only env:
await handler(input, { env: { API_KEY: 'test' } });
```

## Migration

Existing handlers continue to work. Add the context parameter when you need platform resources:

```typescript ins="ctx" ins="ctx.sql"
// Old handlers work fine
async function handler(input) { return { ok: true }; }

// New handlers get context
async function handler(input, ctx) {
  const data = await ctx.sql`SELECT * FROM table`;
  return { ok: true, count: data.length };
}
```

:::note[This is Just the Beginning]
Context is how pgflow manages resources. Soon you'll define your own resources (OpenAI, Stripe, Redis, helpers) and access them the same way. Start using context now to be ready.
:::

**Updated packages**: `@pgflow/edge-worker` and `@pgflow/dsl`