Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -53,3 +53,15 @@ jobs:
node-version: '20'
- run: npm install
- run: npm run test-ts

generate:
timeout-minutes: 5
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '20'
- run: npm install
- run: npm run generate
- run: git diff --exit-code lib/
28 changes: 28 additions & 0 deletions generator/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# PostgreSQL Type OID Generator

Generates PostgreSQL builtin type OIDs for `node-pg-types`.

## Usage

```sh
npm install
npm run generate
```

This will:

- Start all specified Postgres versions in containers
- Run the generator in another container
- Query for builtin type OIDs
- Generate `../lib/builtins.js`
- Tear down the containers

## Adding PostgreSQL Versions

To query additional PostgreSQL versions, edit the files in this directory:

1. Update the version list in `generate.js`
2. Add the new PostgreSQL service to `docker-compose.yml`
3. Add the service dependency to the generator service instructing it to wait for the PostgreSQL service to be ready

Types from multiple PostgreSQL versions are automatically merged.
22 changes: 22 additions & 0 deletions generator/docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
services:
postgres-11:
image: postgres:11-alpine
environment:
POSTGRES_PASSWORD: postgres
healthcheck:
test: ["CMD-SHELL", "pg_isready"]
interval: 5s
timeout: 5s
retries: 5

generator:
image: node:20-alpine
working_dir: /app
command: node generator/generate.js
depends_on:
postgres-11:
condition: service_healthy
volumes:
- ../:/app
environment:
OUTPUT_PATH: /app/lib
134 changes: 134 additions & 0 deletions generator/generate.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
#!/usr/bin/env node

const { Client } = require('pg')
const fs = require('fs')
const path = require('path')

const query = `
SELECT json_object_agg(UPPER(PT.typname), PT.oid::int4 ORDER BY pt.oid)
FROM pg_type PT
WHERE typnamespace = (SELECT pgn.oid FROM pg_namespace pgn WHERE nspname = 'pg_catalog') -- Take only builting Postgres types with stable OID (extension types are not guaranted to be stable)
AND typtype = 'b' -- Only basic types
AND typelem = 0 -- Ignore aliases
AND typisdefined -- Ignore undefined types
`

const postgresVersions = ['11']

async function queryPostgresVersion (version) {
const host = `postgres-${version}`
console.log(`Querying PostgreSQL ${version} at ${host}...`)

const client = new Client({
host: host,
port: 5432,
user: process.env.PGUSER || 'postgres',
password: process.env.PGPASSWORD || 'postgres',
database: process.env.PGDATABASE || 'postgres'
})

try {
await client.connect()
const result = await client.query(query)
const types = result.rows[0].json_object_agg
console.log(`Found ${Object.keys(types).length} types in PostgreSQL ${version}`)
return types
} finally {
await client.end()
}
}

async function generate () {
console.log('Starting PostgreSQL type generation...')

// Query all available PostgreSQL versions in parallel
const typeResults = await Promise.all(
postgresVersions.map(version => queryPostgresVersion(version))
)

// Merge all types from different versions
let allTypes = {}
for (const types of typeResults) {
allTypes = { ...allTypes, ...types }
}

console.log(`Total unique types found: ${Object.keys(allTypes).length}`)

// Determine output directory
const outputDir = process.env.OUTPUT_PATH || path.join(__dirname, '..', 'lib')

// Generate main builtins file
const header = `/**
PostgreSQL builtin type OIDs

DO NOT EDIT THIS FILE BY HAND!
This file is generated automatically by the generator in generator/generate.js
To modify the types, edit the generator script and run: npm run generate

Generated by querying PostgreSQL ${postgresVersions.join(', ')} to ensure comprehensive
type coverage for parsing.

Query used:
${query.trim()}
*/`

const entries = Object.entries(allTypes)
.sort(([, a], [, b]) => a - b)
.map(([name, oid]) => ` ${name}: ${oid}`)
.join(',\n')

const content = `${header}

module.exports = {
${entries}
}
`

// Write main builtins file
const outputPath = path.join(outputDir, 'builtins.js')
await fs.promises.writeFile(outputPath, content)

// Generate TypeScript definitions
const tsHeader = `/**
PostgreSQL builtin type OIDs (TypeScript definitions)

DO NOT EDIT THIS FILE BY HAND!
This file is generated automatically by the generator in generator/generate.js
To modify the types, edit the generator script and run: npm run generate

Generated by querying PostgreSQL ${postgresVersions.join(', ')} to ensure comprehensive
type coverage for parsing.

Query used:
${query.trim()}
*/`

const tsEntries = Object.entries(allTypes)
.sort(([, a], [, b]) => a - b)
.map(([name, oid]) => ` ${name} = ${oid}`)
.join(',\n')

const tsContent = `${tsHeader}

export enum builtins {
${tsEntries}
}
`

// Write TypeScript definitions file
const tsOutputPath = path.join(outputDir, 'builtins.d.ts')
await fs.promises.writeFile(tsOutputPath, tsContent)

console.log('Generated lib/builtins.js and lib/builtins.d.ts successfully')
}

async function main () {
try {
await generate()
} catch (err) {
console.error('Error generating types:', err)
process.exit(1)
}
}

main()
68 changes: 4 additions & 64 deletions index.d.ts
Original file line number Diff line number Diff line change
@@ -1,68 +1,8 @@
export enum builtins {
BOOL = 16,
BYTEA = 17,
CHAR = 18,
INT8 = 20,
INT2 = 21,
INT4 = 23,
REGPROC = 24,
TEXT = 25,
OID = 26,
TID = 27,
XID = 28,
CID = 29,
JSON = 114,
XML = 142,
PG_NODE_TREE = 194,
SMGR = 210,
PATH = 602,
POLYGON = 604,
CIDR = 650,
FLOAT4 = 700,
FLOAT8 = 701,
ABSTIME = 702,
RELTIME = 703,
TINTERVAL = 704,
CIRCLE = 718,
MACADDR8 = 774,
MONEY = 790,
MACADDR = 829,
INET = 869,
ACLITEM = 1033,
BPCHAR = 1042,
VARCHAR = 1043,
DATE = 1082,
TIME = 1083,
TIMESTAMP = 1114,
TIMESTAMPTZ = 1184,
INTERVAL = 1186,
TIMETZ = 1266,
BIT = 1560,
VARBIT = 1562,
NUMERIC = 1700,
REFCURSOR = 1790,
REGPROCEDURE = 2202,
REGOPER = 2203,
REGOPERATOR = 2204,
REGCLASS = 2205,
REGTYPE = 2206,
UUID = 2950,
TXID_SNAPSHOT = 2970,
PG_LSN = 3220,
PG_NDISTINCT = 3361,
PG_DEPENDENCIES = 3402,
TSVECTOR = 3614,
TSQUERY = 3615,
GTSVECTOR = 3642,
REGCONFIG = 3734,
REGDICTIONARY = 3769,
JSONB = 3802,
REGNAMESPACE = 4089,
REGROLE = 4096
}
import * as _builtins from './lib/builtins';

export type TypeId = builtins;
export type TypesBuiltins = typeof builtins;
export const builtins: typeof _builtins.builtins;
export type TypeId = _builtins.builtins;
export type TypesBuiltins = typeof _builtins.builtins;

export type TypeParser<I extends (string | Buffer), T> = (value: I) => T;

Expand Down
81 changes: 81 additions & 0 deletions lib/builtins.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
/**
PostgreSQL builtin type OIDs (TypeScript definitions)

DO NOT EDIT THIS FILE BY HAND!
This file is generated automatically by the generator in generator/generate.js
To modify the types, edit the generator script and run: npm run generate

Generated by querying PostgreSQL 11 to ensure comprehensive
type coverage for parsing.

Query used:
SELECT json_object_agg(UPPER(PT.typname), PT.oid::int4 ORDER BY pt.oid)
FROM pg_type PT
WHERE typnamespace = (SELECT pgn.oid FROM pg_namespace pgn WHERE nspname = 'pg_catalog') -- Take only builting Postgres types with stable OID (extension types are not guaranted to be stable)
AND typtype = 'b' -- Only basic types
AND typelem = 0 -- Ignore aliases
AND typisdefined -- Ignore undefined types
*/

export enum builtins {
BOOL = 16,
BYTEA = 17,
CHAR = 18,
INT8 = 20,
INT2 = 21,
INT4 = 23,
REGPROC = 24,
TEXT = 25,
OID = 26,
TID = 27,
XID = 28,
CID = 29,
JSON = 114,
XML = 142,
PG_NODE_TREE = 194,
SMGR = 210,
PATH = 602,
POLYGON = 604,
CIDR = 650,
FLOAT4 = 700,
FLOAT8 = 701,
ABSTIME = 702,
RELTIME = 703,
TINTERVAL = 704,
CIRCLE = 718,
MACADDR8 = 774,
MONEY = 790,
MACADDR = 829,
INET = 869,
ACLITEM = 1033,
BPCHAR = 1042,
VARCHAR = 1043,
DATE = 1082,
TIME = 1083,
TIMESTAMP = 1114,
TIMESTAMPTZ = 1184,
INTERVAL = 1186,
TIMETZ = 1266,
BIT = 1560,
VARBIT = 1562,
NUMERIC = 1700,
REFCURSOR = 1790,
REGPROCEDURE = 2202,
REGOPER = 2203,
REGOPERATOR = 2204,
REGCLASS = 2205,
REGTYPE = 2206,
UUID = 2950,
TXID_SNAPSHOT = 2970,
PG_LSN = 3220,
PG_NDISTINCT = 3361,
PG_DEPENDENCIES = 3402,
TSVECTOR = 3614,
TSQUERY = 3615,
GTSVECTOR = 3642,
REGCONFIG = 3734,
REGDICTIONARY = 3769,
JSONB = 3802,
REGNAMESPACE = 4089,
REGROLE = 4096
}
22 changes: 15 additions & 7 deletions lib/builtins.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,20 @@
/**
* Following query was used to generate this file:
PostgreSQL builtin type OIDs

SELECT json_object_agg(UPPER(PT.typname), PT.oid::int4 ORDER BY pt.oid)
FROM pg_type PT
WHERE typnamespace = (SELECT pgn.oid FROM pg_namespace pgn WHERE nspname = 'pg_catalog') -- Take only builting Postgres types with stable OID (extension types are not guaranted to be stable)
AND typtype = 'b' -- Only basic types
AND typelem = 0 -- Ignore aliases
AND typisdefined -- Ignore undefined types
DO NOT EDIT THIS FILE BY HAND!
This file is generated automatically by the generator in generator/generate.js
To modify the types, edit the generator script and run: npm run generate

Generated by querying PostgreSQL 11 to ensure comprehensive
type coverage for parsing.

Query used:
SELECT json_object_agg(UPPER(PT.typname), PT.oid::int4 ORDER BY pt.oid)
FROM pg_type PT
WHERE typnamespace = (SELECT pgn.oid FROM pg_namespace pgn WHERE nspname = 'pg_catalog') -- Take only builting Postgres types with stable OID (extension types are not guaranted to be stable)
AND typtype = 'b' -- Only basic types
AND typelem = 0 -- Ignore aliases
AND typisdefined -- Ignore undefined types
*/

module.exports = {
Expand Down
Loading