Skip to content

Commit f21a4da

Browse files
authored
Merge pull request #1076 from supabase/fix/upgrade-pg-for-scraml-handling
fix: upgrade pg package
2 parents 03df514 + 0749094 commit f21a4da

3 files changed

Lines changed: 243 additions & 85 deletions

File tree

CLAUDE.md

Lines changed: 205 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,205 @@
1+
# CLAUDE.md
2+
3+
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
4+
5+
## Overview
6+
7+
postgres-meta is a RESTful API for managing PostgreSQL databases. It provides a normalized interface over the PostgreSQL system catalog, exposing database objects (tables, columns, functions, etc.) through a Fastify-based REST API. The library can be used both as a standalone server and as an npm package.
8+
9+
## Development Commands
10+
11+
### Development Server
12+
```bash
13+
npm run dev # Start dev server with Docker DB (auto-cleans on exit)
14+
npm run dev:code # Start dev server without DB setup (if DB already running)
15+
```
16+
17+
The dev server uses nodemon with ts-node/esm loader and pipes output through pino-pretty for readable logs.
18+
19+
### Building
20+
```bash
21+
npm run build # Compile TypeScript + copy SQL files to dist/
22+
npm run clean # Remove dist/ and tsconfig.tsbuildinfo
23+
npm run check # Type-check without emitting files
24+
```
25+
26+
Build process: TypeScript compilation (tsc) + copying `src/lib/sql/*.sql` files to `dist/lib/sql/` via cpy-cli.
27+
28+
### Testing
29+
```bash
30+
npm test # Full test: db:clean -> db:run -> test:run -> db:clean
31+
npm run test:run # Run tests only (DB must be running)
32+
npm run test:update # Update test snapshots (runs db:clean -> db:run first)
33+
```
34+
35+
Tests use Vitest with snapshot testing. Test files are split between `test/lib/` (library tests) and `test/server/` (API tests). All tests import from `test/index.test.ts` which orchestrates test execution.
36+
37+
**Important**: Tests require Docker. The test DB is managed via `test/db/docker-compose.yml` and runs on port 5432. Tests run sequentially (`maxConcurrency: 1`) and use `pool: 'forks'` to avoid memory issues.
38+
39+
### Database Management
40+
```bash
41+
npm run db:run # Start test DB in Docker (detached, with healthcheck)
42+
npm run db:clean # Stop and remove test DB containers
43+
```
44+
45+
### Type Generation
46+
```bash
47+
npm run gen:types:typescript # Generate TypeScript types from DB schema
48+
npm run gen:types:python # Generate Python types (Pydantic models)
49+
npm run gen:types:go # Generate Go types
50+
npm run gen:types:swift # Generate Swift types (beta)
51+
52+
# With custom DB connection:
53+
PG_META_DB_URL=postgresql://... npm run gen:types:typescript
54+
```
55+
56+
Type generation is controlled by `PG_META_GENERATE_TYPES` env var and runs the server in special mode (exits after generating types to stdout).
57+
58+
### Code Quality
59+
```bash
60+
npm run format # Format code with Prettier
61+
```
62+
63+
## Architecture
64+
65+
### Two-Layer Design
66+
67+
1. **Library Layer** (`src/lib/`): Core PostgreSQL introspection logic
68+
- `PostgresMeta.ts`: Main class that aggregates all metadata managers
69+
- `PostgresMeta*.ts`: Individual managers for each database object type (columns, tables, functions, etc.)
70+
- `sql/*.sql.ts`: SQL query templates for fetching metadata from system catalogs
71+
- `Parser.ts`: SQL parsing, formatting, and deparsing (uses pgsql-parser)
72+
- `db.ts`: Connection pooling and query execution with error handling
73+
74+
2. **Server Layer** (`src/server/`): REST API built with Fastify
75+
- `server.ts`: Entry point, handles normal server mode + type generation mode
76+
- `app.ts`: Main Fastify app with routes, CORS, Swagger docs
77+
- `admin-app.ts`: Admin server (runs on PG_META_PORT + 1) for metrics
78+
- `routes/*.ts`: REST endpoints mapping to library methods
79+
- `templates/*.ts`: Type generation templates for different languages
80+
81+
### Object Manager Pattern
82+
83+
Each PostgreSQL object type has a dedicated manager class following this pattern:
84+
- `PostgresMetaTables`, `PostgresMetaColumns`, `PostgresMetaFunctions`, etc.
85+
- Each manager has methods: `list()`, `retrieve()`, `create()`, `update()`, `remove()`
86+
- Managers compose SQL from `src/lib/sql/*.sql.ts` templates
87+
- All methods return `PostgresMetaResult<T>` = `{ data: T | null, error: Error | null }`
88+
89+
### SQL Query Organization
90+
91+
SQL queries are defined in `src/lib/sql/*.sql.ts` as TypeScript template literals:
92+
- Queries use `pg-format` for safe parameterization
93+
- Complex queries join against `pg_catalog` and `information_schema`
94+
- Build process copies SQL files to `dist/lib/sql/` for runtime access
95+
96+
### Connection Pooling
97+
98+
- Uses custom `@supabase/pg` fork (v0.0.3) instead of standard `pg`
99+
- Connection pool initialized in `db.ts` via `init(config)`
100+
- Pool configuration supports:
101+
- `connectionTimeoutMillis`: Connection timeout (default 15s)
102+
- `query_timeout`: Query timeout (default 55s)
103+
- `maxResultSize`: Max result size in bytes (default 2GB, configurable via `PG_META_MAX_RESULT_SIZE_MB`)
104+
- SSL configuration via `PG_META_DB_SSL_ROOT_CERT`
105+
- Custom error handling for `RESULT_SIZE_EXCEEDED` errors
106+
- Pool auto-reconnects on connection errors by calling `pool.end()` and reinitializing
107+
108+
### Error Handling
109+
110+
Database errors are formatted to mimic `psql` output:
111+
- Includes severity, error code, message, line number, position marker
112+
- Position calculation accounts for injected `SET statement_timeout` prefix
113+
- Returns structured errors: `{ code, message, formattedError, position, detail, hint }`
114+
115+
### Type Generation
116+
117+
Type generation (`npm run gen:types:*`) works by:
118+
1. Connecting to a database (test DB or custom via `PG_META_DB_URL`)
119+
2. Fetching all schemas, tables, columns, relationships, functions, types
120+
3. Passing data to language-specific templates in `src/server/templates/*.ts`
121+
4. Templates output type definitions to stdout
122+
123+
Environment variables:
124+
- `PG_META_GENERATE_TYPES`: Language (typescript, python, go, swift)
125+
- `PG_META_GENERATE_TYPES_INCLUDED_SCHEMAS`: Comma-separated schemas to include
126+
- `PG_META_GENERATE_TYPES_DETECT_ONE_TO_ONE_RELATIONSHIPS`: Enable 1:1 relationship detection
127+
- `PG_META_POSTGREST_VERSION`: PostgREST version for TypeScript template compatibility
128+
129+
## Environment Variables
130+
131+
Required for server operation:
132+
```bash
133+
PG_META_HOST=0.0.0.0 # Server host
134+
PG_META_PORT=8080 # Server port (admin runs on +1)
135+
PG_META_DB_HOST=localhost # PostgreSQL host
136+
PG_META_DB_NAME=postgres # Database name
137+
PG_META_DB_USER=postgres # Database user
138+
PG_META_DB_PORT=5432 # PostgreSQL port
139+
PG_META_DB_PASSWORD=postgres # Database password (or use CRYPTO_KEY for secrets)
140+
PG_META_DB_SSL_MODE=disable # SSL mode (disable, require, verify-full, etc.)
141+
```
142+
143+
Alternative connection:
144+
```bash
145+
PG_META_DB_URL=postgresql://... # Full connection string (overrides individual params)
146+
```
147+
148+
Performance tuning:
149+
```bash
150+
PG_CONN_TIMEOUT_SECS=15 # Connection timeout (default: 15)
151+
PG_QUERY_TIMEOUT_SECS=55 # Query timeout (default: 55)
152+
PG_META_MAX_RESULT_SIZE_MB=20 # Max query result size in MB (default: 2048MB)
153+
PG_META_MAX_BODY_LIMIT_MB=3 # Max request body size in MB (default: 3MB)
154+
```
155+
156+
## Testing Notes
157+
158+
### Snapshot Testing
159+
Tests use Vitest inline snapshots (`toMatchInlineSnapshot`). When fixing bugs:
160+
1. Add test case reproducing the bug
161+
2. Fix the bug
162+
3. Run `npm run test:update` (adds `-u` flag to vitest)
163+
4. Review git diff of snapshots - `id` field changes are expected
164+
5. Remove `-u` flag before committing (or use `npm run test` directly)
165+
166+
### Test Structure
167+
- `test/lib/*.ts`: Direct library tests using `pgMeta` instance
168+
- `test/server/*.ts`: HTTP API tests using Fastify test utils
169+
- `test/index.test.ts`: Main entry point that imports all test modules
170+
- `test/db/`: Docker Compose config for test database with SSL enabled
171+
172+
### Custom Database Connection
173+
To test against a different database:
174+
```bash
175+
PG_META_DB_URL=postgresql://user:pass@host:port/dbname npm run dev:code
176+
```
177+
178+
## Module System
179+
180+
This project uses **ESM** (ES Modules):
181+
- `"type": "module"` in package.json
182+
- Import statements use `.js` extension (TypeScript convention for ESM)
183+
- Node >=20 required
184+
- ts-node runs with `--loader ts-node/esm` flag
185+
- Uses import attributes for JSON: `import pkg from '#package.json' with { type: 'json' }`
186+
187+
## Special Imports
188+
189+
The `#package.json` import is defined in package.json `imports` field:
190+
```json
191+
"imports": {
192+
"#package.json": "./package.json"
193+
}
194+
```
195+
196+
This allows importing package.json metadata in ESM without path resolution issues.
197+
198+
## OpenAPI Documentation
199+
200+
Generate OpenAPI spec:
201+
```bash
202+
npm run docs:export > openapi.json
203+
```
204+
205+
Uses Fastify's `@fastify/swagger` plugin. Routes define schemas using `@sinclair/typebox` for automatic OpenAPI generation.

0 commit comments

Comments
 (0)