@codelusitan/genericfunctions
v2.3.1
Published
A collection of shared utility modules for CodeLusitan Node.js projects. Provides the PostgreSQL generic model/repository pattern (`buildModel`, `genericModel`, `genericRepository`), controller helpers, error handling, and general-purpose utilities — each
Readme
@codelusitan/genericfunctions
A collection of shared utility modules for CodeLusitan Node.js projects. Provides the PostgreSQL generic model/repository pattern (buildModel, genericModel, genericRepository), controller helpers, error handling, and general-purpose utilities — each independently importable.
Installation
npm install @codelusitan/genericfunctionsPackage Structure
@codelusitan/genericfunctions/
├── index.js ← main entry, flat + namespaced re-exports
├── enums/ ← Field/Relation visibility & relation-type constants
├── genericRepository/ ← Postgres CRUD repository factory
├── genericModel/ ← field visibility, validation, relations, hooks on top of a repository
├── buildModel/ ← wires genericRepository + genericModel for a simple table
├── dbUtils/ ← Postgres query helpers (executeQuery, ObjectToSQL, fieldsToSelectStatement...)
├── controllers/ ← HTTP request param validation
├── error/ ← structured error logging
├── logger/ ← console logger factory
├── routerHelpers/ ← generic Express CRUD route handlers (_genericRouterHandlers)
└── utils/ ← pure helper functions (strings, hashing, bcrypt, etc.)v2.0.0: the legacy MSSQL-oriented
modelfactory and its Symbol-basedenumswere removed. This package now targets the PostgreSQL/RLS pattern used by thesrc/modules/*(v3 architecture) services (LusoLog, LusoMail, LusoMeet, LusoPay), and is the target for migrating LusoUser, LusoTick and LusoProject off their legacyapis/controllers/modelsstructure.v2.1.0: added
loggerandrouterHelpers— these were being copy-pasted verbatim into every service (src/utils/logger.js,src/router/helpers.js,src/utils/miscellaneous.js).utilsalready covered everythingmiscellaneous.jsreimplemented; services should consume it from here instead of keeping a local copy.
Modules
enums
Field visibility and relation-type constants used across the model layer. Used as the default
deps.enums by buildModel/genericModel when a project doesn't supply its own.
const { Field, Relation } = require("@codelusitan/genericfunctions/enums");
Field.Options.Visibility.Show // "show"
Field.Options.Visibility.Hide // "hide"
Relation.Types.One_to_One // "one_to_one"
Relation.Types.One_to_Many // "one_to_many"
Relation.Types.Many_to_Many // "many_to_many"buildModel(tableName, idField, idType, fields, relations, hooks, modelName, deps)
Wires a Postgres CRUD repository (genericRepository) + genericModel for a table with no custom queries.
const { buildModel } = require("@codelusitan/genericfunctions");
module.exports = buildModel("Template", "idTemplate", "uuid", fields, relations, hooks, "Template", {
getPool: () => require("../database/pgClient").getPool(),
getModels: () => require("../models"),
});| Argument | Type | Description |
|---|---|---|
| tableName | string | Postgres table name |
| idField | string | Primary key column (e.g. 'idTemplate') |
| idType | 'uuid' \| 'int' | Primary key type |
| fields | Object | Field definitions (<entity>.fields.js) |
| relations | Object | Relation definitions (<entity>.relations.js) |
| hooks | Object | Lifecycle hooks, e.g. { afterFind } (<entity>.hooks.js) |
| modelName | string | Display name |
| deps | Object | { getPool, dbUtils?, enums?, getModels } — see below |
deps
| Key | Type | Description |
|---|---|---|
| getPool | () => Pool | Returns the project's pg pool/client (database/pgClient.js) |
| dbUtils | Object? | { insertIds, ObjectToSQL, executeQuery, fieldsToSelectStatement } — defaults to this package's dbUtils |
| enums | Object? | { Field.Options.Visibility, Relation.Types } — defaults to this package's enums |
| getModels | () => Object | Lazily returns the project's models registry (models/index.js), used to resolve relations |
Returns a model instance:
TemplateModel.get(ids, query, fields, options, transaction)
TemplateModel.getById(id, fields, options)
TemplateModel.insert(data, transaction)
TemplateModel.update(id, data, transaction)
TemplateModel.delete(id, transaction)
TemplateModel.validate(data)
TemplateModel.validateParams(fieldsDef, params)
TemplateModel.getIdentityFieldName()
// Field & relation key helpers
TemplateModel.allKeys
TemplateModel.allVisibleKeys
TemplateModel.visibleFieldsKeys
TemplateModel.invisiblesFieldsKeys
TemplateModel.allRelationsKeys
TemplateModel.visibleRelationsKeys
TemplateModel.invisibleRelationsKeysRelation options for get:
| Key | Type | Description |
|---|---|---|
| include | Array<string> | Relation names to resolve |
| depth | number | Current recursion depth (internal) |
| maxDepth | number | Maximum depth for nested relation resolution |
validateParams(fieldsDef, params) / validate(data)
Validates and coerces an incoming params object against a field definition.
const { success, data, errors } = TemplateModel.validate(req.body);
if (!success) return res.status(400).json({ errors });Supported field types: varchar/nvarchar/text, date/timestamptz, uuid/uniqueidentifier, int/integer/bigint/serial, float/decimal/numeric, jsonb/json.
genericModel / genericRepository
Available individually for modules with custom queries that can't use buildModel directly:
const { genericModel, genericRepository } = require("@codelusitan/genericfunctions");genericRepository(tableName, idField, idType, getPool, dbUtils)→{ getInfo, insert, update, delete }genericModel(modelsFunctions, selectFields, modelRelations, hooks, modelName, deps?)→ model instance (samedepsshape asbuildModel, all optional)
dbUtils
Postgres query helpers: executeQuery, convertNamedParams, ObjectToSQL, insertIds, fieldsToSelectStatement, buildInClause. Used as the default deps.dbUtils.
controllers
Utilities for validating HTTP request parameters.
const { checkParam, validateRequestParams } = require("@codelusitan/genericfunctions/controllers");checkParam(param, type)
Checks whether a value matches an expected type. Supports optional (?) and union (||) types.
checkParam("hello", "string") // true
checkParam(null, "string?") // true (optional)
checkParam(42, "string || number") // true (union)
checkParam([], "array") // false (empty arrays are invalid)validateRequestParams(specs, checkParamFn?)
Validates a list of named parameters and returns an array of error messages.
const errors = validateRequestParams([
{ value: req.body.email, name: "email", type: "string" },
{ value: req.body.age, name: "age", type: "number?" },
{ value: req.body.role, name: "role", type: "string", canBe: ["admin", "user"] },
]);
if (errors.length) return res.status(400).json({ errors });Each spec object:
| Key | Type | Description |
|---|---|---|
| value | any | The value to validate |
| name | string | Human-friendly name for error messages |
| type | string | Type string for checkParam |
| canBe | Array? | Optional whitelist of allowed literal values |
error
Structured error logging with source-aware formatting.
const { errorHandler } = require("@codelusitan/genericfunctions/error");errorHandler(error, name, from, local)
| Param | Type | Description |
|---|---|---|
| error | Error | The caught error object |
| name | string | Context label (e.g. function or route name) |
| from | string | Error source — use "axios" for HTTP client errors |
| local | any | Local variable snapshot for debugging |
try {
await axios.get("/api/data");
} catch (err) {
errorHandler(err, "fetchData", "axios", { userId });
}When from is "axios", the handler extracts and logs response.data, response.status, response.headers, request, and config automatically.
utils
Pure helper functions with no side effects.
const utils = require("@codelusitan/genericfunctions/utils");String
| Function | Signature | Description |
|---|---|---|
| isUUID | (val) → boolean | Validates a UUID v4 string |
| isString | (val) → boolean | Checks if a value is a string |
| capitalize | (word) → string | Capitalises the first letter of a word |
| validateEmail | (email) → boolean | Basic email format check |
| validatePassword | (password) → boolean | Min 6 chars, letters + numbers + special chars, max 255 |
| stripHTML | (str) → string | Strips HTML tags and entities |
| parseModuleName | (dirent) → string | Converts some-file.js → SomeFile |
Array
| Function | Signature | Description |
|---|---|---|
| intersect | (a, b) → Array | Returns elements present in both arrays |
| joinWith | (arr, separator, lastSeparator) → string | Join with a different last separator (e.g. ", " and " and ") |
Object / Type
| Function | Signature | Description |
|---|---|---|
| isObject | (val) → boolean | True if plain object (not array, not null) |
| isDate | (val) → boolean | True if valid Date instance |
ID / Hashing
| Function | Signature | Description |
|---|---|---|
| newId | () → string | Generates a timestamp-based unique ID |
| hash | (str) → number | Simple deterministic integer hash |
| encryptPassword | (password) → Promise<string> | bcrypt hash (salt rounds: 10) |
| comparePassword | (password, hash) → Promise<boolean> | bcrypt comparison |
logger
Tiny console logger factory shared by every service. Replaces a hand-rolled src/utils/logger.js.
const { createLogger } = require("@codelusitan/genericfunctions/logger");
const config = require("./config");
const logger = createLogger({ enableDebug: config.enableConsoleLogging });
logger.info("server.started", { port: config.port });
logger.error("db.connection_failed", { message: err.message });| Function | Signature | Description |
|---|---|---|
| createLogger | (options?) → { info, warn, error, debug } | options.enableDebug (default true) silences debug() calls when false |
Each level prints [ISO timestamp] [LEVEL] message {meta} to stdout (or stderr for error).
routerHelpers
Generic Express CRUD route handlers wired against any genericModel/buildModel-shaped model
(get/getById/insert/update/delete/validate/fields/name). Replaces a hand-rolled
src/router/helpers.js.
const { _genericRouterHandlers } = require("@codelusitan/genericfunctions/routerHelpers");
const Model = require("./model");
async function findHandler(query) {
return { ids: [], query };
}
const ctrl = _genericRouterHandlers(Model, findHandler);
router.get("/", ctrl.getAll);
router.get("/:id", ctrl.get);
router.post("/", ctrl.create);
router.put("/:id", ctrl.update);
router.delete("/:id", ctrl.delete);
router.post("/find", ctrl.find);
router.post("/findByIds", ctrl.findByIds);_genericRouterHandlers(myModel, findHandler, deps?) returns { getAll, get, findByIds, find, create, update, delete }. deps optionally overrides { enums, utils } — defaults to this package's own enums/utils, same pattern as buildModel.
Usage in a service
Each service can keep a thin local adapter at src/common/buildModel.js, since dbUtils and
enums now default to this package's own implementations:
const { getPool } = require("../database/pgClient");
const { buildModel } = require("@codelusitan/genericfunctions");
module.exports = (tableName, idField, idType, fields, relations, hooks, modelName) =>
buildModel(tableName, idField, idType, fields, relations, hooks, modelName, {
getPool,
getModels: () => require("../models"),
});Modules then call it exactly as before:
// modules/template/template.model.js
const buildModel = require("../../common/buildModel");
module.exports = buildModel("Template", "idTemplate", "uuid", fields, relations, hooks, "Template");Flat Imports
All modules are also re-exported flat from the root for convenience:
const {
checkParam,
validateRequestParams,
errorHandler,
capitalize,
isUUID,
newId,
encryptPassword,
// ...
} = require("@codelusitan/genericfunctions");License
ISC © CodeLusitan
