Slonik Utilities
Slonik Utilities provides a set of helper functions designed to simplify common data manipulation operations within a PostgreSQL database when using the Slonik client library. It abstracts away the direct construction of parameterized SQL queries for tasks such as `UPDATE`, `UPDATE ... DISTINCT`, and `UPSERT`, allowing developers to express these operations using JavaScript objects. The library is currently at stable version 2.0.2 and receives updates primarily to maintain compatibility with new major versions of Slonik (e.g., supporting Slonik v29). Its key differentiators include enhancing developer productivity by reducing boilerplate SQL, improving type safety through its TypeScript definitions, and mitigating SQL injection risks by leveraging Slonik's tagged template literals internally. It does not replace Slonik but complements it by offering a higher-level, opinionated API for frequent DML patterns.
Common errors
-
TypeError: Cannot read properties of undefined (reading 'query')
cause The `connection` object passed to `slonik-utilities` functions is not a valid Slonik `Connection` or `Pool` instance, or it's `undefined`.fixEnsure you are passing a valid `Slonik` `Connection` or `Pool` instance. When using a `pool.connect()` callback, ensure you pass the `connection` argument from the callback, e.g., `const result = await pool.connect(async (connection) => update(connection, ...));` -
Error: Slonik client has not been configured.
cause This error originates from `slonik` itself, indicating that `createPool` was not called or its connection string was invalid, preventing a proper Slonik client from being initialized.fixVerify your Slonik pool creation. Ensure `createPool` is called with a valid `connectionString` (e.g., `process.env.DATABASE_URL`) and that your database is accessible. -
TypeError: require() of ES Module [...] from [...] not supported.
cause Attempting to use `require()` to import `slonik-utilities` when the package is an ES Module, or the package is not installed.fixInstall the package (`npm install slonik-utilities`). If the error persists and you are in a Node.js project, switch to `import` statements and ensure your project is configured for ESM (e.g., `"type": "module"` in `package.json` or `.mjs` file extension).
Warnings
- breaking Slonik-utilities requires a peer dependency of `slonik` version `>28`. Mismatched Slonik versions can lead to type errors, runtime failures, or unexpected behavior due to API changes in Slonik itself.
- breaking Since major version 2.0.0, `slonik-utilities` is published as an ESM module. Attempting to `require()` it in a CommonJS context will result in a `TypeError: require() of ES Module`.
- gotcha When passing named value bindings or boolean expression values, `slonik-utilities` (and Slonik by default) will automatically snake_case property names to match typical PostgreSQL column naming conventions. If your column names use a different casing (e.g., `camelCase`), you must explicitly match them or configure Slonik's naming convention transformer.
- deprecated In version 1.9.1, the library removed the `Type` suffix from its TypeScript interfaces (e.g., `UpdateResultType` became `UpdateResult`). While not a runtime breaking change, it requires updates to type imports in TypeScript projects.
Install
-
npm install slonik-utilities -
yarn add slonik-utilities -
pnpm add slonik-utilities
Imports
- update
const { update } = require('slonik-utilities');import { update } from 'slonik-utilities'; - updateDistinct
const updateDistinct = require('slonik-utilities').updateDistinct;import { updateDistinct } from 'slonik-utilities'; - upsert
import upsert from 'slonik-utilities';
import { upsert } from 'slonik-utilities';
Quickstart
import { createPool, sql } from 'slonik';
import { update } from 'slonik-utilities';
const connectionString = process.env.DATABASE_URL ?? 'postgres://user:password@localhost:5432/database';
async function runExample() {
const pool = await createPool(connectionString);
try {
// Create a dummy table for demonstration
await pool.query(sql`
CREATE TABLE IF NOT EXISTS "user" (
id SERIAL PRIMARY KEY,
given_name TEXT,
last_name TEXT
);
`);
// Insert some initial data
await pool.query(sql`
INSERT INTO "user" (given_name, last_name) VALUES ('John', 'Doe'), ('Jane', 'Smith');
`);
console.log('Initial data inserted.');
// Use slonik-utilities to update rows matching a condition
const updateResult = await pool.connect(async (connection) => {
return await update(
connection,
'user',
{
givenName: 'Jonathan'
},
{
lastName: 'Doe'
}
);
});
console.log(`Updated ${updateResult.rowCount} row(s).`);
// Verify the update
const updatedUsers = await pool.query(sql`SELECT * FROM "user" WHERE last_name = 'Doe'`);
console.log('Updated user:', updatedUsers.rows[0]);
} catch (error) {
console.error('Error during example execution:', error);
} finally {
await pool.end();
}
}
runExample();