testing/schema_introspect.ts

PostgreSQL schema introspection — produces a normalized, JSON-serializable snapshot of a database's structure for cross-impl parity checks.

The snapshot covers:

  • Tables with columns (data type, nullability, default, identity)
  • Indexes with canonical Postgres-rendered definitions
  • Constraints (CHECK, FOREIGN KEY, PRIMARY KEY, UNIQUE, EXCLUSION)
  • Sequences with data type — distinguishes int4 (SERIAL) from int8 (BIGSERIAL)
  • Enum types (CREATE TYPE ... AS ENUM) with labels in declared order — so a label set / ordering drift (e.g. cell_visibility) is a gated fact, not invisible

Designed for pg_catalog introspection — works against both PostgreSQL and PGlite. The snapshot is fully deterministic: every collection sorts by a stable key and excludes time-varying fields like applied_at.

Paired with testing/schema_parity.ts for comparison + assertion helpers.

view source

Declarations
#

10 declarations

ColumnSnapshot
#

testing/schema_introspect.ts view source

ZodObject<{ data_type: ZodString; udt_name: ZodString; is_nullable: ZodBoolean; column_default: ZodNullable<ZodString>; is_identity: ZodBoolean; }, $strip> import type {ColumnSnapshot} from '@fuzdev/fuz_app/testing/schema_introspect.js';

Per-column structural metadata. The Zod schema is the canonical source for the column shape — SchemaSnapshot reuses it as the cross-impl _testing_schema_snapshot RPC action's wire validator, so the introspection type and the wire contract can't drift apart.

EnumTypeSnapshot
#

testing/schema_introspect.ts view source

ZodObject<{ labels: ZodArray<ZodString>; }, $strip> import type {EnumTypeSnapshot} from '@fuzdev/fuz_app/testing/schema_introspect.js';

Enum-type metadata — the labels of a CREATE TYPE ... AS ENUM, captured in pg_enum.enumsortorder (declaration) order. Order is significant: a Postgres enum's labels are an ordered set, and reordering them is a schema change, so the parity diff compares the arrays positionally.

MigrationTracker
#

testing/schema_introspect.ts view source

ZodObject<{ entries: ZodArray<ZodObject<{ namespace: ZodString; name: ZodString; sequence: ZodNumber; }, $strip>>; }, $strip> import type {MigrationTracker} from '@fuzdev/fuz_app/testing/schema_introspect.js';

The full schema_version tracker as a deterministically-ordered list, wrapped in an object so it round-trips cleanly as a JSON-RPC result. Sorted by (namespace, sequence) on capture.

MigrationTrackerEntry
#

testing/schema_introspect.ts view source

ZodObject<{ namespace: ZodString; name: ZodString; sequence: ZodNumber; }, $strip> import type {MigrationTrackerEntry} from '@fuzdev/fuz_app/testing/schema_introspect.js';

A single schema_version tracker row — the migration-identity primitive.

Where SchemaSnapshot is provenance-agnostic (it captures the resulting tables and deliberately *excludes* the tracker), this is the tracker: the (namespace, name, sequence) the migration runner records per applied migration. sequence carries order; name carries identity (the PK is (namespace, name)). The cross-impl gate diffs these between the two bootstrapped spines so a migration-name or partitioning drift — invisible to the schema snapshot — is a gated fact, not a latent interop break.

query_migration_tracker
#

testing/schema_introspect.ts view source

(db: Db): Promise<{ entries: { namespace: string; name: string; sequence: number; }[]; }> import {query_migration_tracker} from '@fuzdev/fuz_app/testing/schema_introspect.js';

Read every schema_version row into a deterministic MigrationTracker.

The migration-identity twin of query_schema_snapshot: that captures the resulting schema (and excludes this tracker); this captures the tracker rows themselves, so the cross-impl gate can assert the two spines record byte-identical migration identity.

db

type Db

returns

Promise<{ entries: { namespace: string; name: string; sequence: number; }[]; }>

query_schema_snapshot
#

testing/schema_introspect.ts view source

(db: Db, options?: QuerySchemaSnapshotOptions): Promise<{ tables: Record<string, { columns: Record<string, { data_type: string; udt_name: string; is_nullable: boolean; column_default: string | null; is_identity: boolean; }>; indexes: { ...; }[]; constraints: { ...; }[]; }>; sequences: Record<...>; enums: Record<...>; }> import {query_schema_snapshot} from '@fuzdev/fuz_app/testing/schema_introspect.js';

Introspect a live database into a deterministic SchemaSnapshot.

Reads information_schema and pg_catalog to capture tables, columns, indexes, constraints, and sequences.

The schema_version migration tracker never appears in the tables field — it's framework bookkeeping created by the migration runner, identical across consumers, and would only add noise.

db

type Db

options

default {}

returns

Promise<{ tables: Record<string, { columns: Record<string, { data_type: string; udt_name: string; is_nullable: boolean; column_default: string | null; is_identity: boolean; }>; indexes: { name: string; definition: string; }[]; constraints: { ...; }[]; }>; sequences: Record<...>; enums: Record<...>; }>

QuerySchemaSnapshotOptions
#

testing/schema_introspect.ts view source

QuerySchemaSnapshotOptions import type {QuerySchemaSnapshotOptions} from '@fuzdev/fuz_app/testing/schema_introspect.js';

Filter options for query_schema_snapshot.

schema?

Schema name to introspect — defaults to 'public'. Single-schema only; cross-schema introspection isn't a current need.

type string

readonly

exclude_tables?

Tables to exclude from the snapshot. The schema_version migration tracker is always excluded — it's framework bookkeeping created by the migration runner, identical across impls, and not part of any consumer's domain schema.

type ReadonlyArray<string>

readonly

SchemaSnapshot
#

testing/schema_introspect.ts view source

ZodObject<{ tables: ZodRecord<ZodString, ZodObject<{ columns: ZodRecord<ZodString, ZodObject<{ data_type: ZodString; udt_name: ZodString; is_nullable: ZodBoolean; column_default: ZodNullable<...>; is_identity: ZodBoolean; }, $strip>>; indexes: ZodArray<...>; constraints: ZodArray<...>; }, $strip>>; sequences: ZodRec... import type {SchemaSnapshot} from '@fuzdev/fuz_app/testing/schema_introspect.js';

Normalized database schema snapshot for parity comparison — the single source of truth for the snapshot shape across the introspection query (query_schema_snapshot), the diff comparator (testing/schema_parity.ts), and the cross-impl RPC action's wire validator (testing/cross_backend/testing_reset_actions.ts).

All fields are deterministically ordered on capture so structural equality via JSON.stringify or per-key comparison yields stable results.

SequenceSnapshot
#

testing/schema_introspect.ts view source

ZodObject<{ data_type: ZodString; }, $strip> import type {SequenceSnapshot} from '@fuzdev/fuz_app/testing/schema_introspect.js';

Sequence metadata — data_type is bigint (BIGSERIAL) or integer (SERIAL).

TableSnapshot
#

testing/schema_introspect.ts view source

ZodObject<{ columns: ZodRecord<ZodString, ZodObject<{ data_type: ZodString; udt_name: ZodString; is_nullable: ZodBoolean; column_default: ZodNullable<ZodString>; is_identity: ZodBoolean; }, $strip>>; indexes: ZodArray<...>; constraints: ZodArray<...>; }, $strip> import type {TableSnapshot} from '@fuzdev/fuz_app/testing/schema_introspect.js';

Per-table structural metadata.

Depends on
#

Imported by
#