🚀 Socket Launch Week Day 5:Introducing Repository Access Permissions and Custom Roles.Learn more
Sign In

@web-im/utils

Package Overview
Dependencies
Maintainers
1
Versions
9
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@web-im/utils

Web-IM Utilities

Source
npmnpm
Version
1.0.1
Version published
Weekly downloads
24
-20%
Maintainers
1
Weekly downloads
 
Created
Source

@web-im/utils

Server-side helpers: validators, error/log/data shapes, encryption, Sequelize/RabbitMQ/Redis bindings.

pnpm add @web-im/utils
# or
npm install @web-im/utils

Imports

Subpath imports are tree-shakable and recommended:

import { isUUID } from '@web-im/utils/validator';
import { AppError, throwAppError } from '@web-im/utils/error';
import { logError } from '@web-im/utils/log';

The flat barrel re-exports everything. Modules whose names collide on connect / disconnect (db, rabbit, redis) are exposed as namespaces:

import { db, rabbit, redis, AppError, isUUID } from '@web-im/utils';

await db.connect();
await rabbit.connect();
await redis.connect();

Modules

validator

Type guards for runtime shape checks. All return boolean.

FunctionTrue when...
isBuffer(v)v instanceof Buffer
isSymbol(v)typeof symbol
isUndefined(v)undefined
isNull(v)null
isArray(v)array
isNonEmptyArray(v)array with at least one item
isBoolean(v)boolean
isNumber(v)typeof number (does not include numeric strings)
isInteger(v)numeric and integer
isNumeric(v)number or numeric string
isString(v)string
isNonEmptyString(v)string and not ''
isObject(v)plain object
isNonNullObject(v)plain object with at least one key
isEmpty(v) / isNotEmpty(v)empty by any of the above
isFunction(v)function or async function
isAsyncFunction(v)async function
isUUID(v)valid UUID string
isEmail(v)matches x@y
isPhoneNumber(v)matches a flexible international format
isURL(v)parseable http(s)://... URL
isTCNumber(v)valid Turkish national ID (11-digit, checksum)
import { isUUID, isEmail, isNonEmptyArray } from '@web-im/utils/validator';

isUUID('00000000-0000-4000-8000-000000000000'); // true
isEmail('hi@example.com');                       // true
isNonEmptyArray([1, 2, 3]);                      // true

error

import { AppError, ResponseError, throwAppError, getErrorString } from '@web-im/utils/error';

throw new AppError('Resource not found', 'NOT_FOUND', { id: '123' });

// auto-derives a code from the message
throw new AppError('Invalid token');           // code: 'INVALID_TOKEN'

// HTTP-flavored error
throw new ResponseError('Forbidden', 403);

// helper
throwAppError('Bad input', 'VALIDATION_ERROR', { field: 'email' });

// formatted "{message} - [{func} @ {file}:{line}:{col}]"
console.log(getErrorString(new Error('boom')));

data

import { paging, toResult, IList, IInfiniteList } from '@web-im/utils/data';

paging(100);              // { offset: 0, limit: 20, total: 100 }
paging(50, 100, 10);      // { offset: 0, limit: 10, total: 50 } (offset clamped)
paging(5000, 0, 5000);    // { offset: 0, limit: 1000, total: 5000 } (limit capped)

toResult(undefined, { id: 1 });   // { success: true, payload: { id: 1 } }
toResult(new AppError('boom'));   // { success: false, error }
toResult(new Error('boom'));      // wraps as AppError('SYSTEM_ERROR')

crypt

import {
  createHash, comparePassword, createRandomHash, createKey,
  createToken, getRandomNumber, createSimpleHash
} from '@web-im/utils/crypt';

createHash('hello');                     // HMAC-SHA256, secret = process.env.TOKEN_SECRET
createHash('hello', 'md5');              // simple md5
createHash('hello', 'sha256', 'mySec');  // explicit secret

comparePassword(savedHash, plain);       // boolean
createRandomHash(80);                    // hex string of length 80
createKey(6);                            // 6-digit numeric token, e.g. '482913'
createToken(5);                          // 5-char alphanumeric, e.g. 'A2K9F'
getRandomNumber(1, 100);                 // inclusive integer in [1, 100]

encryption

AES-256-GCM with auth tag, IV-prefixed binary output.

import { getKey, encrypt, decrypt } from '@web-im/utils/encryption';

const key = getKey('my-password', 'my-salt');
const ciphertext = encrypt('secret message', key);   // Buffer
const plaintext  = decrypt(ciphertext, key);         // 'secret message'

log

File-rotated logging into ${ROOT_PATH}/${LOGS_PATH || 'logs'}/YYYY-MM-DD-{type}.log (UTC). Optional admin-email digest via sendMessage('message.send', ...) to the rabbit queue when SEND_LOGS=true.

import { logInfo, logWarning, logError, writeToFile, showMessages } from '@web-im/utils/log';

await logInfo('app started');
await logWarning('cache miss', true);          // also console.log
await logError('Login failed', err, { userId });

writeToFile('boot complete', 'info');          // sync write, returns { path, name, fullPath }

showMessages([
  'PORT  : 3000',
  'NODE  : 20.x'
]);

dto

Joi schema validation + a generic data-mapping wrapper.

import { validateSchema, phoneNumberValidation } from '@web-im/utils/dto';
import joi from 'joi';

const schema = joi.object({ email: joi.string().email().required() });

// sync — throws AppError('VALIDATION_ERROR') with details
const value = validateSchema(schema, { email: 'a@b.co' });

// async
const value2 = await validateSchema(schema, { email: 'a@b.co' }, true);

// custom Joi rule
joi.string().custom(phoneNumberValidation);

db

Sequelize wrapper with reconnection, replica support, and a typed filter/sort/paginate DSL.

import { db } from '@web-im/utils';
// or: import * as db from '@web-im/utils/db';

await db.connect();
const sequelize = db.sequelize();

// safe SQL string
db.escapeString("o'reilly", true);   // "'o''reilly'"

// build a WHERE from a structured filter
const where = await db.filtering([
  ['email', 'contains', 'gmail'],
  ['status', 'isAnyOf', ['active', 'pending']]
]);

// Joi schema for user-supplied filter input
const schema = db.JoiFilter('email', 'string');

// paginated list
const page = await db.getList<User>({
  offset: 0,
  limit: 20,
  sqlBody: async (alias, withColumns) => `SELECT ... FROM users AS "${alias}"`,
  dataModel: rows => rows
});

await db.disconnect();

Required env: DB_ENGINE, DB_HOST, DB_PORT, DB_NAME, DB_USER, DB_PASS, DB_USE_SSL. Comma-separate hosts/ports for read replicas.

rabbit

RabbitMQ client with auto-reconnect, message streaming for payloads larger than RABBIT_MESSAGE_MAX_SIZE (default 5 MB), and request/response over reply queues.

import { rabbit } from '@web-im/utils';

await rabbit.connect();

// fire-and-forget
await rabbit.sendMessage('log.event', { action: 'login', user_id: id });

// request → reply
const result = await rabbit.sendMessageForReply('account.find', { id });

// listen
await rabbit.receiveMessage('account', async (params) => {
  return { success: true, payload: { ... } };
});

// pub/sub
await rabbit.publishMessage('user', 'updated', { id });
await rabbit.receivePublishedMessage('user', '*', payload => { ... });

// hook all queues + exchanges to the eventEmitter (read from env)
await rabbit.listen(true);

Required env: RABBIT_HOST, RABBIT_PORT, RABBIT_USER, RABBIT_PASS, RABBIT_VHOST, RABBIT_NAMESPACE, RABBIT_QUEUES, RABBIT_EXCHANGES, RABBIT_TIMEOUT.

redis

import { redis } from '@web-im/utils';

const client = await redis.connect();   // RedisClient or RedisCluster
await client.set('key', 'value');
await redis.disconnect();

Required env: REDIS_HOST, REDIS_PORT, REDIS_USER, REDIS_PASS, REDIS_DB. Comma-separate hosts to enable cluster mode.

events

Singleton wildcard EventEmitter2 plus an attachEvents helper that wires events/**/*.js files at a path.

import eventEmitter, { attachEvents, eventResult } from '@web-im/utils/events';

eventEmitter.on('user.created', (payload, cb) => {
  cb(null, { id: payload.id });
});

await attachEvents(__dirname);   // loads ./events/*.js based on EVENTS env

jobs

Loads jobs/**/*.js and runs each export inside a fresh vm context.

import { runJobs } from '@web-im/utils/jobs';

await runJobs(__dirname, { db, rabbit });

Filter set via JOBS=* or JOBS=foo,bar.run.

output

Express middleware helper. Wraps a callback into a structured { success, payload | error, transaction } response, with optional rabbit logging on LOG=request,response.

import { toResponse, responseData, IRequest } from '@web-im/utils/output';

app.post('/login', (req, res) => {
  toResponse(req, res, async (transactionId) => {
    return { token: '...' };
  });
});

// manual shape
res.json(responseData(null, { token: '...' }));

config

Imported for side effects: loads .env from the workspace root, sets process.env.WORKING_PATH, ROOT_PATH, normalizes ROUTE_PREFIX. Imported automatically by other modules — you rarely import it directly.

Repository

github.com/morsaken/web-im-helpers — see the workspace README for the companion @web-im/react package.

License

MIT

Keywords

utils

FAQs

Package last updated on 25 Apr 2026

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts