electric-sql / electric-sql/electric
Allow `runMigrations` to accept a caller-owned PostgreSQL client
- Dominant language
- TypeScript
- Stars
- 10.4k
- Forks
- 375
- Avg merge
- 3d 1h
- Merged PRs (30d)
- 18
Description
## Problem
`@electric-ax/agents-server` currently exports:
```ts
runMigrations(postgresUrl: string): Promise
```
The function creates its own `postgres` client from the URL. A caller cannot supply the client that it already configured with a custom CA, an exact TLS server name, pooling rules, or other connection policy.
The function also closes its internal client only after a successful migration. A migration error can leave that client open.
## Requested behavior
Allow callers to run the packaged migrations with connection policy that they configure before the call. Keep the existing URL form compatible.
### Option A: accept a caller owned client
Add a public overload or equivalent typed API that accepts the package's exported `PgClient`.
```ts
const client = postgres(connectionOptions)
try {
await runMigrations(client)
} finally {
await client.end()
}
```
The migration function uses this client and never closes it. The caller owns its lifecycle on success and failure.
This is the preferred option. It supports the full `postgres` client configuration without copying that dependency's option types into the Agents Server API. The cost is that each caller must close its client.
### Option B: accept structured connection configuration
Add a typed configuration object that contains the connection and TLS fields needed to create the migration client.
The migration function creates the client and closes it in `finally`. This is easier for callers that do not already own a client. The cost is a wider public API that can drift as `postgres` connection options change.
## Proposed compatibility contract
- Keep `runMigrations(postgresUrl: string)` working.
- Prefer a direct caller owned `PgClient` overload.
- Do not close a caller owned client.
- Close every library owned client after success or failure.
- Run migrations through the exact client supplied by the caller.
- Keep connection values out of logs and errors added by this change.
- Export all new public types from the package root.
The final API shape can follow existing repository conventions, but its ownership rules must be visible in the type or API documentation.
## Acceptance criteria
- A package consumer can pass a configured `PgClient` through the public `@electric-ax/agents-server` export.
- The existing URL call remains source compatible.
- A public boundary type test proves that both supported forms compile.
- A runtime test proves that migrations use the caller supplied client.
- Tests prove that the function does not close a caller owned client after success or failure.
- Tests prove that the function closes a library owned client after success or failure.
- Tests fail when any ownership or cleanup invariant is removed.
- The package typecheck, focused tests, build, style checks, formatting checks, and required release note or changeset checks pass.
## Non-goals
- Do not add a migration command or process entrypoint.
- Do not read credentials or connection settings from files or environment variables in this API.
- Do not log connection strings, passwords, certificates, or client options.
- Do not change the Agents Server runtime connection model outside the migration API.
## Downstream use
Some deployments require a custom CA and exact PostgreSQL DNS identity. They can construct a client under their own secret and TLS policy, call the migration API, and close the client without passing credentials through a URL or child process environment.
Contributor guide
Research direction
Start at the exported runMigrations entry point in @electric-ax/agents-server and trace its current client creation and migration flow. Add the public boundary type and runtime tests described in the acceptance criteria, covering both URL and caller-owned PgClient forms, ownership, cleanup, and compatibility. Confirm package typecheck, focused tests, build, style, formatting, and release-note checks pass.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- postgres, typescript
- Domain
- api, backend, databases
- Issue type
- Feature
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 68/100