Last active
June 9, 2025 12:30
-
-
Save quidmonkey/7d9997ad62bc9c9140a4cf1edf9b6a02 to your computer and use it in GitHub Desktop.
Nodejs SQL Querying (node-pg) with Schemas/Types (zod), Error Handling, Logging, String Interpolation, and No ORM
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
import { Pool } from 'pg'; | |
import { ZodSchema } from 'zod'; | |
// Initialize the database connection pool | |
const pool = new Pool({ | |
user: 'your_db_user', | |
host: 'localhost', | |
database: 'your_db_name', | |
password: 'your_password', | |
port: 5432, | |
}); | |
export async function queryTyped<T>( | |
sql: string, | |
schema: ZodSchema<T>, | |
params?: any[] | |
): Promise<T[]> { | |
const client = await pool.connect(); | |
try { | |
const result = await client.query(sql, params); | |
// Validate and parse each row | |
return result.rows.map((row, index) => { | |
const parsed = schema.safeParse(row); | |
if (!parsed.success) { | |
console.error(`Validation error at row ${index}:`, parsed.error.format()); | |
throw new Error(`Invalid row at index ${index}`); | |
} | |
return parsed.data; | |
}); | |
} catch (error) { | |
console.error('Query error:', error); | |
throw error; | |
} finally { | |
client.release(); | |
} | |
} |
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
import { queryTyped } from './db'; | |
import { UserSchema, User } from './types'; | |
async function getUsers() { | |
const users = await queryTyped<User>( | |
'SELECT id, username, email FROM users', | |
UserSchema | |
); | |
console.log(users); | |
} | |
getUsers(); |
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
import { queryTyped } from './db'; | |
import { User } from './types'; | |
import { z } from 'zod'; | |
const NewRecord = z.object({ | |
id: z.number(), // Assume ID is auto-generated and returned | |
}); | |
export async function insertUser(user: Omit<User, 'id'>): Promise<User> { | |
const sql = ` | |
INSERT INTO users (username, email) | |
VALUES ($1, $2) | |
RETURNING id, username, email | |
`; | |
const params = [user.username, user.email]; | |
const result = await queryTyped<User>( | |
sql, | |
NewRecord, | |
params | |
); | |
return result[0]; // Assuming a single insert | |
} | |
async function insertExampleUser() { | |
const newUser = { | |
username: 'alice', | |
email: '[email protected]', | |
}; | |
try { | |
const inserted = await insertUser(newUser); | |
console.log('Inserted user:', inserted); | |
} catch (err) { | |
console.error('Failed to insert user:', err); | |
} | |
} | |
insertExampleUser(); |
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
import { z } from 'zod'; | |
export const UserSchema = z.object({ | |
id: z.number(), | |
username: z.string(), | |
email: z.string().email(), | |
}); | |
export type User = z.infer<typeof UserSchema>; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment