Skip to content

Instantly share code, notes, and snippets.

@quidmonkey
Last active June 9, 2025 12:30
Show Gist options
  • Save quidmonkey/7d9997ad62bc9c9140a4cf1edf9b6a02 to your computer and use it in GitHub Desktop.
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
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();
}
}
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();
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();
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