| name | ephemeral-pgpm-fixtures |
| description | Ephemeral pgpm fixture modules — install real published @pgpm/* modules into the gitignored root extensions/ directory and deploy them into test databases with seed.pgpm, instead of hand-maintaining copies of production DDL. Use when running or writing integration tests that need metaschema/services/module schemas, when tests fail with 'no pgpm module or workspace found', or when bumping fixture module versions. |
| compatibility | pgpm, pgsql-test, graphile-test, graphql-server-test, Jest, PostgreSQL |
| metadata | {"author":"constructive-io","version":"1.0.0"} |
Ephemeral pgpm Fixtures
Integration tests that need production-shaped Constructive schemas (metaschema,
services, module registration tables) deploy the real published @pgpm/*
modules rather than hand-written SQL approximations. The repo root is itself
a pgpm workspace (pgpm.json): modules are pinned in its dependencies field
and installed into the gitignored root extensions/ directory.
When to Apply
- Running integration tests in
graphql/server-test, graphile/graphile-function-bindings, or anything that seeds with seed.pgpm(...)
- A test fails with
seed.pgpm: no pgpm module or workspace found at ...
- Bumping the fixture modules to a newer published version
- Adding a new test that needs metaschema/services/module DDL
Setup (local + CI)
pnpm install
pnpm build
pnpm fixtures:install
fixtures:install is idempotent — it skips modules already present. Use
pnpm fixtures:install:force to reinstall everything.
Using the modules in tests
import { getConnections, seed } from 'pgsql-test';
const repoRoot = path.resolve(__dirname, '../../..');
await getConnections(options, [
seed.pgpm(repoRoot),
seed.sqlfile([
])
]);
Key facts:
seed.pgpm(dir) deploys a pgpm module (and its dependencies) into the isolated test database; pass a workspace root (e.g. the repo root) to deploy every installed module once, in dependency order. Workspace-wide deploys require an explicit cwd — seed.pgpm() with no args stays module-only. Don't chain multiple seed.pgpm(module) calls that share dependencies — fast deploys are not idempotent across calls.
- The real modules grant to
administrator/authenticated — there are no anonymous grants anywhere (matching production). Server plugins resolve module registrations (metaschema config) without the request role (withPgClient(null, ...)), so anonymous request paths never need grants on the metaschema schemas.
- Per-app generated tables (compute
function_definitions, storage tables) are NOT published modules — they stay as hand-written fixtures (__fixtures__/seed/compute/setup.sql, simple-seed-storage/).
- The deterministic pgpm engine fixtures under
__fixtures__/sqitch/ are intentionally frozen — never replace them with installed modules.
Upgrading module versions
node pgpm/cli/dist/index.js install -W @pgpm/metaschema-modules@latest
This installs the latest published version and records it in the root
pgpm.json — commit the 1-line version bump.
Workspace-level pgpm install -W
pgpm install -W (--workspace-root) installs at a workspace root (no module/.control file needed):
- with no args, it installs everything pinned in the workspace
pgpm.json dependencies
- with explicit packages, it installs them and records resolved versions back into
pgpm.json
--force reinstalls even if the extension directories already exist
Workspace module discovery is scoped to the workspace's declared packages
globs plus extensions/ — nested workspaces (like __fixtures__/sqitch/*)
are never part of the parent workspace's module map.