Shared

codi-node-utils

The shared Node.js utilities package used by booki-api.

codi-node-utils is published as @codisolutions23/node-utils and imported by booki-api. It provides infrastructure utilities so they don't get duplicated across backend services.

Exports Reference

Database — MongoDB

import { useAtlas } from '@codisolutions23/node-utils'

const { connect, getDb, startSession } = useAtlas()

// Connect on app startup
await connect(mongoUri)

// Get collection
const col = getDb().collection<IUser>('users')

// Start a transaction session
const session = await startSession()

Cache — Redis

import { useCache, useRedis } from '@codisolutions23/node-utils'

// useCache: high-level key/value operations
const { getCache, setCache, delCache, delCacheGroup } = useCache()

await setCache('key', value, 300)          // TTL in seconds
const data = await getCache('key')
await delCache('key')
await delCacheGroup('users')               // delete all keys matching 'users:*'

// useRedis: direct ioredis client
const redis = useRedis()
await redis.set('key', 'value')

Authentication

import { authenticate, signJwtToken } from '@codisolutions23/node-utils'

// Middleware factory — attach to routes
const authMiddleware = authenticate(accessTokenSecret, existsByJti)

// Sign a JWT
const token = signJwtToken(payload, secret, '15m')

Passwords & Tokens

import { comparePasswords, hashToken } from '@codisolutions23/node-utils'

const match = await comparePasswords(plainText, hash)
const hashed = hashToken(rawRefreshToken)   // SHA-256 hash for refresh tokens at rest

HTTP Errors

import {
  HttpError,
  BadRequestError,
  UnauthorizedError,
  ForbiddenError,
  NotFoundError,
  ConflictError,
  UnprocessableEntityError,
  InternalServerError,
} from '@codisolutions23/node-utils'

throw new NotFoundError('User not found.')
throw new ConflictError('Email already in use.')
throw new UnprocessableEntityError(joiError.message)

Error Handler Middleware

import { errorHandler } from '@codisolutions23/node-utils'

// Register last in app.ts
app.use(errorHandler)

Pagination

import { paginate } from '@codisolutions23/node-utils'

// Called inside base.repo.ts after an aggregate query
const result = paginate(data, totalCount, page, limit)
// Returns: { items, total, page, limit, pages }

Utilities

import {
  buildCacheKey,
  toObjectId,
  logger,
} from '@codisolutions23/node-utils'

// Deterministic Redis key from collection + params
const key = buildCacheKey('users', { organizationId, page, limit })

// Convert string → MongoDB ObjectId safely
const id = toObjectId(stringId)

// Winston logger
logger.info('Server started')
logger.error('Unexpected failure', { error })

Email & Storage

import { mailer, useHandlebarsCompiler, s3 } from '@codisolutions23/node-utils'

// Send email
const html = await useHandlebarsCompiler().compile('booking-confirmation', data)
await mailer.sendMail({ to, subject, html })

// Upload to S3
await s3.putObject({ Bucket, Key, Body })

Cron Jobs

import { useCronJob } from '@codisolutions23/node-utils'

useCronJob('0 0 * * *', async () => {
  // Runs daily at midnight
  await cleanExpiredTokens()
})

Request Types

import type { AuthenticatedRequest } from '@codisolutions23/node-utils'

// Extends Express Request with:
// req.user  — decoded JWT payload
// req.token — raw Bearer token string

async function getProfile(req: AuthenticatedRequest, res: Response, next: NextFunction) {
  const userId = req.user!._id
  // ...
}