azure-postgres-ts – skill Viết lách & Nội dung cho agent AI
Kết nối đến Azure Database for PostgreSQL Flexible Server từ Node.js/TypeScript bằng gói pg (node-postgres).
Cài skill azure-postgres-ts bằng một lệnh
Chọn công cụ bạn đang dùng, copy lệnh và dán vào terminal. Skill sẽ nằm trong thư mục skills của công cụ đó và sẵn sàng dùng ở phiên làm việc tiếp theo.
Claude Code
mkdir -p ~/.claude/skills && curl -fsSL https://skill.dn1nguoi.com/z/azure-postgres-ts-efc93.tgz | tar xz -C ~/.claude/skills
Gọi trong Claude Code: /azure-postgres-ts – rồi mô tả công việc bạn muốn làm.
Codex
mkdir -p ~/.codex/skills && curl -fsSL https://skill.dn1nguoi.com/z/azure-postgres-ts-efc93.tgz | tar xz -C ~/.codex/skills
Gọi trong Codex: $azure-postgres-ts – rồi mô tả công việc bạn muốn làm.
Hermes Agent
mkdir -p ~/.hermes/skills && curl -fsSL https://skill.dn1nguoi.com/z/azure-postgres-ts-efc93.tgz | tar xz -C ~/.hermes/skills
Gọi trong Hermes Agent: /azure-postgres-ts – rồi mô tả công việc bạn muốn làm.
DeepSeek
mkdir -p ~/.deepcode/skills && curl -fsSL https://skill.dn1nguoi.com/z/azure-postgres-ts-efc93.tgz | tar xz -C ~/.deepcode/skills
Gọi trong DeepSeek: /azure-postgres-ts – rồi mô tả công việc bạn muốn làm.
Nội dung SKILL.md
Nội dung SKILL.md gốc bằng tiếng Anh.
Azure PostgreSQL for TypeScript (node-postgres)
Connect to Azure Database for PostgreSQL Flexible Server using the pg (node-postgres) package with support for password and Microsoft Entra ID (passwordless) authentication.
Installation
npm install pg @azure/identity
npm install -D @types/pgEnvironment Variables
# Required
AZURE_POSTGRESQL_HOST=<server>.postgres.database.azure.com
AZURE_POSTGRESQL_DATABASE=<database>
AZURE_POSTGRESQL_PORT=5432
# For password authentication
AZURE_POSTGRESQL_USER=<username>
AZURE_POSTGRESQL_PASSWORD=<password>
# For Entra ID authentication
AZURE_POSTGRESQL_USER=<entra-user>@<server> # e.g., [email protected]
AZURE_POSTGRESQL_CLIENTID=<managed-identity-client-id> # For user-assigned identityAuthentication
Option 1: Password Authentication
import { Client, Pool } from "pg";
const client = new Client({
host: process.env.AZURE_POSTGRESQL_HOST,
database: process.env.AZURE_POSTGRESQL_DATABASE,
user: process.env.AZURE_POSTGRESQL_USER,
password: process.env.AZURE_POSTGRESQL_PASSWORD,
port: Number(process.env.AZURE_POSTGRESQL_PORT) || 5432,
ssl: { rejectUnauthorized: true } // Required for Azure
});
await client.connect();Option 2: Microsoft Entra ID (Passwordless) - Recommended
import { Client, Pool } from "pg";
import { DefaultAzureCredential } from "@azure/identity";
// For system-assigned managed identity
const credential = new DefaultAzureCredential();
// For user-assigned managed identity
// const credential = new DefaultAzureCredential({
// managedIdentityClientId: process.env.AZURE_POSTGRESQL_CLIENTID
// });
// Acquire access token for Azure PostgreSQL
const tokenResponse = await credential.getToken(
"https://ossrdbms-aad.database.windows.net/.default"
);
const client = new Client({
host: process.env.AZURE_POSTGRESQL_HOST,
database: process.env.AZURE_POSTGRESQL_DATABASE,
user: process.env.AZURE_POSTGRESQL_USER, // Entra ID user
password: tokenResponse.token, // Token as password
port: Number(process.env.AZURE_POSTGRESQL_PORT) || 5432,
ssl: { rejectUnauthorized: true }
});
await client.connect();Examples are separate sketches requiring imports/schema and an authorized non-production database. Parameter binding protects values, not identifiers or tenant authorization. TypeScript query generics are compile-time assertions, not runtime result validation. On rollback failure, destroy the client instead of returning it to the pool; preserve the original error.
Core Workflows
1. Single Client Connection
import { Client } from "pg";
const client = new Client({
host: process.env.AZURE_POSTGRESQL_HOST,
database: process.env.AZURE_POSTGRESQL_DATABASE,
user: process.env.AZURE_POSTGRESQL_USER,
password: process.env.AZURE_POSTGRESQL_PASSWORD,
port: 5432,
ssl: { rejectUnauthorized: true }
});
try {
await client.connect();
const result = await client.query("SELECT NOW() as current_time");
console.log(result.rows[0].current_time);
} finally {
await client.end(); // Always close connection
}2. Connection Pool (Recommended for Production)
import { Pool } from "pg";
const pool = new Pool({
host: process.env.AZURE_POSTGRESQL_HOST,
database: process.env.AZURE_POSTGRESQL_DATABASE,
user: process.env.AZURE_POSTGRESQL_USER,
password: process.env.AZURE_POSTGRESQL_PASSWORD,
port: 5432,
ssl: { rejectUnauthorized: true },
// Pool configuration
max: 20, // Maximum connections in pool
idleTimeoutMillis: 30000, // Close idle connections after 30s
connectionTimeoutMillis: 10000 // Timeout for new connections
});
// Query using pool (automatically acquires and releases connection)
const result = await pool.query("SELECT * FROM users WHERE id = $1", [userId]);
// Explicit checkout for multiple queries
const client = await pool.connect();
try {
const res1 = await client.query("SELECT * FROM users");
const res2 = await client.query("SELECT * FROM orders");
} finally {
client.release(); // Return connection to pool
}
// Cleanup on shutdown
await pool.end();3. Parameterized Queries (Prevent SQL Injection)
// ALWAYS use parameterized queries - never concatenate user input
const userId = 123;
const email = "[email protected]";
// Single parameter
const result = await pool.query(
"SELECT * FROM users WHERE id = $1",
[userId]
);
// Multiple parameters
const result = await pool.query(
"INSERT INTO users (email, name, created_at) VALUES ($1, $2, NOW()) RETURNING *",
[email, "John Doe"]
);
// Array parameter
const ids = [1, 2, 3, 4, 5];
const result = await pool.query(
"SELECT * FROM users WHERE id = ANY($1::int[])",
[ids]
);4. Transactions
const client = await pool.connect();
try {
await client.query("BEGIN");
const userResult = await client.query(
"INSERT INTO users (email) VALUES ($1) RETURNING id",
["[email protected]"]
);
const userId = userResult.rows[0].id;
await client.query(
"INSERT INTO orders (user_id, total) VALUES ($1, $2)",
[userId, 99.99]
);
await client.query("COMMIT");
} catch (error) {
await client.query("ROLLBACK");
throw error;
} finally {
client.release();
}5. Transaction Helper Function
async function withTransaction<T>(
pool: Pool,
fn: (client: PoolClient) => Promise<T>
): Promise<T> {
const client = await pool.connect();
try {
await client.query("BEGIN");
const result = await fn(client);
await client.query("COMMIT");
return result;
} catch (error) {
await client.query("ROLLBACK");
throw error;
} finally {
client.release();
}
}
// Usage
const order = await withTransaction(pool, async (client) => {
const user = await client.query(
"INSERT INTO users (email) VALUES ($1) RETURNING *",
["[email protected]"]
);
const order = await client.query(
"INSERT INTO orders (user_id, total) VALUES ($1, $2) RETURNING *",
[user.rows[0].id, 99.99]
);
return order.rows[0];
});6. Typed Queries with TypeScript
import { Pool, QueryResult } from "pg";
interface User {
id: number;
email: string;
name: string;
created_at: Date;
}
// Type the query result
const result: QueryResult<User> = await pool.query<User>(
"SELECT * FROM users WHERE id = $1",
[userId]
);
const user: User | undefined = result.rows[0];
// Type-safe insert
async function createUser(
pool: Pool,
email: string,
name: string
): Promise<User> {
const result = await pool.query<User>(
"INSERT INTO users (email, name) VALUES ($1, $2) RETURNING *",
[email, name]
);
return result.rows[0];
}Pool with Entra ID Token Refresh
Use the installed node-postgres version's supported dynamic password callback so new connections obtain a current token. Do not tear down and recreate a shared pool on every token expiry: concurrent callers can race with shutdown.
import { Pool } from "pg";
import { DefaultAzureCredential } from "@azure/identity";
const credential = new DefaultAzureCredential();
const azurePool = new Pool({
host: process.env.AZURE_POSTGRESQL_HOST,
database: process.env.AZURE_POSTGRESQL_DATABASE,
user: process.env.AZURE_POSTGRESQL_USER,
ssl: { rejectUnauthorized: true },
password: async () => {
const token = await credential.getToken("https://ossrdbms-aad.database.windows.net/.default");
if (!token) throw new Error("Token acquisition failed");
return token.token;
},
});Verify Entra principal mapping and server authentication settings first. Tokens are secrets; never log them. Token expiration is supplied by the issuer, not a guaranteed one-hour lifetime.
Error Handling
import { DatabaseError } from "pg";
try {
await pool.query("INSERT INTO users (email) VALUES ($1)", [email]);
} catch (error) {
if (error instanceof DatabaseError) {
switch (error.code) {
case "23505": // unique_violation
console.error("Duplicate entry (details redacted)");
break;
case "23503": // foreign_key_violation
console.error("Foreign key constraint failed (details redacted)");
break;
case "42P01": // undefined_table
console.error("Table does not exist:", error.message);
break;
case "28P01": // invalid_password
console.error("Authentication failed");
break;
case "57P03": // cannot_connect_now (server starting)
console.error("Server unavailable, retry later");
break;
default:
console.error(`PostgreSQL error ${error.code}: ${error.message}`);
}
}
throw error;
}Connection String Format
// Alternative: Use connection string
const pool = new Pool({
connectionString: `postgres://${encodeURIComponent(user)}:${encodeURIComponent(password)}@${host}:${… (nội dung đầy đủ có trong gói tải về)
Skill liên quan
- azure-resource-manager-postgresql-dotnet – SDK Azure PostgreSQL Flexible Server cho .NET. Quản lý cơ sở dữ liệu cho các triển khai…
- on-call-handoff-patterns – Thành thạo việc bàn giao ca trực on-call với truyền ngữ cảnh, quy trình leo thang…
- sms – Khi người dùng muốn lên kế hoạch, xây dựng hoặc tối ưu marketing qua SMS, MMS hoặc…
- postmortem-writing – Viết postmortem không đổ lỗi (blameless) hiệu quả với phân tích nguyên nhân gốc, dòng…
- eu-ai-act-specialist – Tuân thủ vận hành EU AI Act (Regulation (EU) 2024/1689) cho đội ngũ compliance. Ba quyết…
- bash-defensive-patterns – Làm chủ kỹ thuật lập trình Bash phòng thủ cho script chuẩn production. Dùng khi viết…
- eu-ai-act-specialist – Tuân thủ vận hành EU AI Act (Quy định (EU) 2024/1689) cho đội ngũ tuân thủ. Ba quyết…
- video – Khi người dùng muốn tạo, sinh hoặc sản xuất nội dung video bằng công cụ AI hoặc…