feat(pglite): pgpm→PGlite plugin — pg-cache + pgsql-client driver seams, @pgpmjs/pglite-adapter, pglite-test#1350
Merged
Merged
Conversation
Contributor
🤖 Devin AI EngineerI'll be helping with this pull request! Here's what you should know: ✅ I will automatically:
Note: I can only respond to comments from users who have write access to this repository. ⚙️ Control Options:
|
|
Review the following changes in direct dependencies. Learn more about Socket for GitHub.
|
Registers an in-process PGlite instance as the pg-cache pool factory so the unmodified pgpm engine deploys/verifies/reverts migrations into PGlite (WASM Postgres) with no server and no socket. All @electric-sql/pglite deps live in this adapter; core stays PGlite-free. - broaden pg-cache PgPoolFactory to return pg.Pool | QueryablePool (pg.Pool still satisfies it; default path unchanged) - 6 tests: deploy -> verify -> data -> revert into in-process PGlite with the default useTransaction:true (single session, no cross-connection deadlock) - run in the no-services unit-tests CI tier
- pgsql-client: add registerPgClientFactory/defaultPgClientFactory seam (mirror of pg-cache pool seam); PgClient routes its underlying client through it. Default = new pg.Client, fully backward-compatible. - pglite-adapter: extract shared query runner; add createPgliteClient so the same in-process session backs both pool and client seams. - pglite-test: new drop-in getConnections backed by in-process PGlite (no server/createdb/psql). SharedTxn ref-counts transaction control so the standard two-client beforeEach/afterEach savepoint harness works over one PGlite session. Seeds via seed.pgpm(). 5 tests: deploy, per-test isolation, RLS role/JWT switching incl. WITH CHECK. - CI: add postgres/pglite-test to the no-services unit-tests (pglite) batch.
- Make @electric-sql/pglite a peerDependency of @pgpmjs/pglite-adapter and pglite-test (kept as a pinned devDependency for the monorepo build/tests), so consumers pin the PGlite version and avoid duplicate installs. - Harden pglite-test getConnections: restore the previous client factory on teardown (instead of resetting to default) and unwind seams if setup throws. - Rename workflow pglite-poc.yaml -> pglite.yaml (job pglite-socket-e2e); it is the standalone wire-protocol e2e demo. The in-process path already runs in the no-services unit-tests (pglite) job in run-tests.yaml. - Add CHANGELOG.md stubs for both new packages.
- Drop package-lock.json; add pnpm-lock.yaml (installed with --ignore-workspace so it stays standalone on the published @pgpmjs/core, not the workspace build). - Rename run.mjs -> run.js (package.json already has type:module). - Workflow pglite.yaml: pnpm/action-setup + pnpm install --ignore-workspace / pnpm start. - Rewrite poc/pglite/README.md in the sibling test-framework style (badges, structure).
Repo convention avoids package type:module. All three @electric-sql/pglite* packages expose a require entry, so run.js uses CommonJS require + async main().
- Move poc/pglite -> examples/pglite-socket (no more 'poc'). - Make it a proper workspace package: workspace deps (@pgpmjs/core, pg-cache), jest.config.js + tsconfig.json + CHANGELOG; drop standalone pnpm-lock.yaml and the --ignore-workspace install. - Convert run.js -> __tests__/socket.e2e.test.ts (jest, real expect assertions); teardownPgPools() in afterAll so no idle-pool noise. - Delete bespoke .github/workflows/pglite.yaml; run the socket e2e in the existing no-services unit-tests (pglite) batch in run-tests.yaml alongside the adapter + pglite-test.
…file delta Exact pg@8.22.0 in the example forced a repo-wide pg 8.21.0->8.22.0 bump in the lockfile, which drifted the graphile/postgraphile plan-step resolution and broke graphile-bulk-mutations. Match the repo's ^8.21.0 and keep the lockfile delta to just the new example package.
…ce, drop 'forking the base' framing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Brings PGlite (WASM Postgres) into the pgpm ecosystem as a plugin, keeping all
@electric-sql/pglite*deps out of pgpm core and out ofpgsql-client/pgsql-test— mirroring thedrizzle-orm-test/supabase-testprecedent. Nobody usingpgpm/pgsql-testis affected; the default path is byte-identical.The stack talks to Postgres through node-
pgin two places, so there are two independent seams (both default-preserving), and the PGlite deps live only in two new leaf packages:What's here (in rollout order)
1. Socket e2e + CI (
poc/pglite/,.github/workflows/pglite.yaml, jobpglite-socket-e2e) — the unmodified pgpm engine doesdeploy → verify → pgvector round-trip → revertagainst PGlite over apg-gatewaysocket shim, no Postgres service container. Standalone (own lockfile, outside the pnpm workspace). Kept as a wire-protocol demonstration distinct from the in-process path below.2.
pg-cachedriver seam —getPgPoolroutes pool construction through a registrable factory; default unchanged. Factory return broadened so an adapter can return anyQueryablePool(a realpg.Poolstructurally satisfies it). 19 unit tests.3.
@pgpmjs/pglite-adapter(new — one of only two packages importing@electric-sql/pglite) — registers an in-process PGlite instance as the pg-cache factory, so the unmodified pgpm engine deploys into PGlite with no socket, no server:The pool maps node-
pg's two protocols onto PGlite: parameterized →db.query, parameterless/multi-statement (pgpm bootstrap) →db.exec. 6 tests.4.
pgsql-clientclient-factory seam — mirror of the pg-cache pool seam, becausepgsql-client/pgsql-testbuildpg.Clients directly (not viagetPgPool):Default =
new pg.Client(...), fully backward-compatible. 4 unit tests.Publish readiness:
@electric-sql/pgliteis a peerDependency of both new packages (pinned devDependency for the monorepo build/tests) so consumers pin the version and avoid duplicate installs.pglite-test.getConnectionsrestores the previous client factory on teardown and unwinds the seams if setup throws (no cross-suite leakage). Both packages carryCHANGELOG.mdandpublishConfig.5.
pglite-test(new — the second pglite-importing package) — a drop-ingetConnections()likedrizzle-orm-test/supabase-test, backed by an in-process PGlite instance. Composes both seams (registerPglite+registerPgClientFactory) sopganddbshare one PGlite session:Because PGlite is a single session, transaction control is ref-counted (
SharedTxn) so the standard two-clientbeforeEach()/afterEach()savepoint harness emits exactly oneBEGIN/SAVEPOINT/ROLLBACK/COMMITper test (single-clientdb-only also works). No PGlite-awareDbAdminsubclass was needed — the instance is the database; extension/role bootstrap runs viapglite.extensionSql. 5 tests: deploy, per-test isolation, and RLS role + JWT-claim switching incl.WITH CHECK.Key findings
useTransaction:false(a txn on one TCP session +isDeployed()on another deadlocks a single-connection backend). In-process, both seams funnel to PGlite's single session, soBEGIN/isDeployed()/COMMITinterleave safely. Deferred as optional — only relevant to a hypothetical multi-connection single-writer backend.pgsql-testbypasses the pg-cache seam, which is exactly why the client-factory seam (part 4) exists:PgTestClientextendspgsql-client'sPgClient(new Client()) and never callsgetPgPool.Tests / CI
All 38 checks green, including the new no-services
unit-tests (pglite, postgres/pglite-adapter postgres/pglite-test)job and Socket Security for@electric-sql/pglite@0.5.4.Scope: no pgpm core source changed. Both seams are additive and default-preserving; all
@electric-sql/pglite*code lives in@pgpmjs/pglite-adapterandpglite-test.Not in this PR (follow-ups)
pglite-test-suitewiring +getConnectionsmanager/adminparity.pgpm init --pglitescaffolder (CLI-layer convenience; no PGlite dep in core).Link to Devin session: https://app.devin.ai/sessions/424b76f81a60499493ac946b57136ad9
Requested by: @pyramation