Skip to content

Allow runMigrations to accept a caller-owned PostgreSQL client #4746

Description

@adityavkk

Problem

@electric-ax/agents-server currently exports:

runMigrations(postgresUrl: string): Promise<void>

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.

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions