Skip to content

feat(pgpm): pluggable migration-driver contract + generic plugin loader#1352

Merged
pyramation merged 1 commit into
mainfrom
feat/pgpm-driver-plugin
Jul 10, 2026
Merged

feat(pgpm): pluggable migration-driver contract + generic plugin loader#1352
pyramation merged 1 commit into
mainfrom
feat/pgpm-driver-plugin

Conversation

@pyramation

Copy link
Copy Markdown
Contributor

Summary

Step 1 of making pgpm pluggable so it can target alternate backends (PGlite now, others like Turso/libSQL later) without pgpm core/CLI depending on any backend. This PR is pure additive plumbing — the built-in pg (server) path is unchanged (a driver is undefined by default).

The contract (@pgpmjs/types): a driver plugin is any package exporting a well-known factory. pgpm depends only on this interface, never on a backend or its deps.

export type PgpmDriverFactory =
  (options?) => Promise<{ capabilities: PgpmDriverCapabilities; teardown: () => Promise<void> }>;

export interface PgpmDriverConfig { plugin: string; options?: Record<string, unknown>; }
// PgpmOptions gains: driver?: PgpmDriverConfig   (undefined = built-in pg path)

capabilities (createdb / dump / serverLifecycle / multiConnection) will later let the CLI generically skip server-only steps instead of hard-coding if (pglite).

The loader (pgpm/cli/src/utils/driver.ts): resolves the plugin from the consumer's project, exactly like ESLint/Babel resolve plugins — pgpm ships zero backend deps.

const requireFrom = createRequire(join(cwd, 'package.json'));
const mod = requireFrom(requireFrom.resolve(cfg.plugin));
return (mod.createPgpmDriver ?? mod.default?.createPgpmDriver)(cfg.options);
  • makage dual-build safe: uses createRequire from node:module, not bare require.resolve / await import(). In the ESM bundle (module: es2022) a bare require is undefined at runtime; in the CJS bundle tsc downlevels import() back to require. createRequire behaves identically in both — verified against dist/ and dist/esm/.
  • driverOverrideFromArgv maps --pglite (bare → in-memory), --pglite=<dir> (→ options.dataDir), and --driver <pkg>; --pglite wins over --driver.
  • resolveDriverConfig handles precedence (override beats pgpm.json) and option merging for the same plugin.
  • Clear errors: "not installed in this project" (with npm i hint) and "does not export createPgpmDriver".

Tests

13 unit tests in pgpm/cli/__tests__/driver.test.ts (arg mapping, config precedence/merge, server-path passthrough, missing-plugin + non-plugin errors). Both @pgpmjs/types and pgpm/cli build (CJS + ESM).

Not in this PR (follow-ups per the plan)

Wiring activateDriver into deploy/verify/revert with capability-driven guards; @pgpmjs/pglite-adapter implementing createPgpmDriver; pgpm init --pglite; the pglite/* boilerplate family. Then Turso/libSQL as a separate plugin.

Link to Devin session: https://app.devin.ai/sessions/424b76f81a60499493ac946b57136ad9
Requested by: @pyramation

Adds the driver-plugin seam so pgpm can target alternate backends (PGlite, and
later others) without pgpm core/CLI depending on any backend.

- @pgpmjs/types: PgpmDriverConfig / PgpmDriverFactory / PgpmDriverSession /
  PgpmDriverCapabilities contract + PgpmOptions.driver (undefined = built-in pg).
- pgpm/cli: activateDriver() resolves the plugin from the CONSUMER's node_modules
  via createRequire (dual CJS/ESM safe, no bare require in ESM output) and calls
  its createPgpmDriver export. driverOverrideFromArgv maps --pglite / --driver.
- 13 unit tests (arg mapping, config precedence/merge, missing-plugin + non-plugin
  errors, server-path passthrough).

Pure additive plumbing; no backend deps in pgpm; server path unchanged.
@pyramation pyramation self-assigned this Jul 10, 2026
@devin-ai-integration

Copy link
Copy Markdown
Contributor

🤖 Devin AI Engineer

I'll be helping with this pull request! Here's what you should know:

✅ I will automatically:

  • Address comments on this PR. Add '(aside)' to your comment to have me ignore it.
  • Look at CI failures and help fix them

Note: I can only respond to comments from users who have write access to this repository.

⚙️ Control Options:

  • Disable automatic comment, CI, and merge conflict monitoring

@pyramation pyramation merged commit 69dcbbf into main Jul 10, 2026
37 checks passed
@pyramation pyramation deleted the feat/pgpm-driver-plugin branch July 10, 2026 22:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant