npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@soft-artel/modules

v1.2.10

Published

Exception, Validation

Downloads

1,460

Readme

Exception, Logger, Validation, Utils Module

Exception class enhances error handling by allowing for the categorization of exceptions through specific types and parameters. This structure provides greater clarity and detail, enabling developers to manage errors more effectively and respond with informative, context-rich messages.

Logger is a flexible and customizable logging library for Node.js and browsers. It supports various output formats and modes, making it suitable for debugging, error handling, and other logging scenarios that require detailed event tracking.

Valid provides a flexible and powerful way to validate data structures in TypeScript and JavaScript. You can define validation rules and schemas for your data, ensuring that they conform to expected types and formats.

Installation

npm install @soft-artel/modules

Exception

Exception Types

const ExceptionTitles = {
  TimeResync = "TimeResync",
  BadRequest = "BadRequest",
  Validation = "Validation",
  Authorize = "Authorize",
  AccessNotAllowed = "AccessNotAllowed",
  NotFound = "NotFound",
  MethodNotAllowed = "MethodNotAllowed",
  ExternalRequest = "ExternalRequest",
  Core = "Core",
  Service = "Service",
  DataSource = "DataSource",
  UserBlocked = "UserBlocked",
  IPAddressNotAllowed = "IPAddressNotAllowed",
  UnprocessableContent = "UnprocessableContent",
  NoInternet: "No internet connection",
  Server: "Server error",
};

Constructor

constructor(
    typeOrCode: ExceptionType | number,
    messageOrError: string | Error | unknown,
    params?: Record<string, any>,
    options?: Options
)

typeOrCode — This parameter can be either an ExceptionType (like 'BadRequest', 'NotFound', etc.) or a numerical HTTP status code. It determines the type of exception being created.

messageOrError — This can be a string representing the custom error message or another Error object. If an Error is provided, its message and stack trace will be used to populate the new exception.

params? — An object containing additional information related to the exception. This can be used to pass context-specific data that may be helpful for debugging or logging.

options? — An object conforming to the Options interface, allowing for further customization of the exception behavior (e.g., whether to show parameters in the response).

Usage

throw new Exception(ExceptionTitles.BadRequest, Error || "Message", {
  param: 1,
});

Logger

Default config logger

const defaultConfigLogger: Config = {
	stage: 		isBrowser ? '' : process.env.STAGE || 'dev',
	app: 		isBrowser ? '' : process.env.APP_NAME || '',
	version: 	isBrowser ? '' : process.env.APP_VER || '',
	format: 	isBrowser ? 'plain' : process.env.LOG_FORMAT === 'json' ? 'json' : 'plain',
	mode: 		isBrowser ? 'errors' : process.env.STAGE && process.env.STAGE !== 'test' ? 'errors' : 'silent',
}

Config

interface Config {
	stage: string, 
	app: string, 
	version: string,
	format: 'plain' | 'json'
	mode: 	'debug' | 'errors' | 'silent'
}	

stage — Represents the environment stage in which the application is running.

app — Specifies the name of the application.

version — Represents the version of the application.

format — Determines the output format of the log messages.

mode — Sets the logging mode to control the verbosity and type of log messages.

Buffer

interface Log{
	d: Date;   // log date
	t: LogType // log type
	m: string; // log mesage
	p?: any;   // log params
	s?: string // log stack
}

Modes of Operation

The Logger supports three modes of operation:

debug:

  • The logger outputs all messages with different collors (info, debug, dump, done, warning, and error). alt text

Or in JSON format.

errors:

  • The logger outputs only error messages (err), warning messages (wrn), and done messages (dne).
  • Logs are stored in the buffer, limited to 100 entries.
  • However, if an error occurs during the operation, it outputs all the logs that were recorded before the error.

silent:

  • In this mode, the logger does not output any messages at all.
  • Logs still be buffered.
Logger.shared.mode = "debug"; // Switch to debug mode

Copy Logger to log requests or paralells process

You can create a copy of shared logger with customized env for each request:

const requestLogger = Logger.shared.copy({
  status: number // request status
	dt: Date, // request date
	key: string, // request key
	loc: string  //  request location
	mem: number  //Memory usage
});

Example with Environment Variables

Logger can be configured using environment variables for flexibility across different stages of your application.

APP_NAME=myApp
APP_VER=1.0.0
STAGE=development
LOG_FORMAT=json
Logger.info("Application initialized"); // Will automatically use env config

API

The shared Logger instance that can be accessed globally.

Logger.shared;

Generates a new unique key for log tracing.

Logger.newKey;

Logs a detailed dump message, useful for outputting large objects or debug information.

Logger.dump(message: string, params?: any, isAlert?: boolean): void

Logs a debug message.

Logger.dbg(message: string, params?: any, isAlert?: boolean): void

Logs an informational message.

Logger.info(message: string, params?: any, isAlert?: boolean): void

Logs a warning.

Logger.warn(message: any, params?: any, isAlert?: boolean): void

Logs an error message. If the error is an Exception, it will also set the logger's status to the HTTP status code of the exception.

Logger.error(message: any, params?: any, isAlert?: boolean): void

Helper Functions

Helper function to convert an error to a structured log format.

convertError(err: any, paramsObj?: any): { message: string, params?: any, stack?: string }

Converts log parameters to a JSON string for output.

convertParamsToJson(log: Log, prefix: string): string

This function attempts to merge the environment object and the log object into a JSON string. If an error occurs, it is caught and logged, and the error message is returned.

makeJsonLogRowStr(env: ProcessEnv, log: Log): string

This function formats a log entry as a plain text string with color differentiation, including a timestamp, HTTP status, error message, and log parameters.

makePlainLogRowStr(env: ProcessEnv, log: Log, withPrefixOpt: string = ''): string

Usage

import { Logger } from "@soft-artel/modules";

Logger.info("Log an info message");

Logger.dbg("Log a debug message");

Logger.warn(new Error("Log a warning with additional parameters"), {
  additional: "info",
});

Logger.error(new Error("Log an error"), {
  cause: "Database not reachable",
});

Valid

Features

  • Support for Primitive Types: strings, numbers, booleans, etc.
  • Validation of Complex Structures: objects, arrays, and dictionaries.
  • Customizable Validation Rules: minimum and maximum values, patterns, lists of allowed values.
  • Partial Validation Support: allows for partial validation of objects (useful for PATCH requests).
  • Detailed Validation Errors: provides detailed information on which fields failed validation and why.

API

Types

Valid.Type

Enumeration of supported data types:

uuid - UUID strings serial - Auto-incrementing numbers smallint - Integers from -32768 to +32767 integer - Integers from -2147483648 to +2147483647 bigint - Large range integers coordinate - Coordinates with specified precision double - High-precision floating-point numbers string - Fixed-length strings text - Text fields with no length limit phone - Strings representing phone numbers boolean - Boolean values date - Dates without time zones datez - Dates with time zones timestamp - Timestamps daykey - Integers representing days email - Strings matching email format ipv4 - IPv4 addresses object - Objects array - Arrays dictionary - Dictionaries (objects with arbitrary keys) stream - Data streams buffer - Data buffers

Valid.RuleOptions

Object defining validation rules for a specific field:

type: Valid.Type - Data type null?: boolean - Is null allowed? default?: any - Default value if the field is absent min?: number - Minimum value or length max?: number - Maximum value or length mod?: number - Modulus for numeric values values?: any[] | object - Allowed values (enumeration) pattern?: string | RegExp - Pattern for strings schema?: Valid.Schema - Schema for nested objects rule?: Valid.RuleOptions| Valid.Type - Rule for array or dictionary items allowPartial?: boolean - Allow partial validation

Valid.Schema

Object where keys are field names and values are Valid.Rule or Valid.RuleOptions.

Functions

Valid.process

Main function for validating data.

Valid.process<I = any>(
  value: any,
  rule: Valid.Rule,
  allowPartial?: boolean
): I | Partial<I>

value: The value to validate rule: The validation rule or schema allowPartial: Allow partial validation (default is false)

Returns the validated value or throws a ValidationError.

Valid.Object

Creates a validation rule for objects.

Valid.Object<I>(
  schema: Valid.Schema<I>,
  options?: {
    null?: boolean;
    default?: Partial<I>;
    allowPartial?: boolean;
  }
): Valid.RuleOptions<I>

schema: Validation schema for the object options: Additional options

Valid.Patch

Creates a rule for partial validation of objects (useful for PATCH requests).

Valid.Patch<I>(schema: Valid.Schema<I>): Valid.RuleOptions<I>

Exceptions

ValidationError
class ValidationError extends Error {
  constructor(
    readonly propName: string,
    readonly value: any,
    readonly rule: Valid.Rule | Valid.Schema | undefined
  ) {
    super(`ValidationError: ${propName}`);
  }
}

propName: The field name that failed validation value: The invalid value rule: The violated rule or validation schema

Usage

Defining Validation Rules

You can define a validation schema for your data using the types and rules provided by the library.

const userSchema: Valid.Schema = {
  id: "uuid",
  name: { type: "string", min: 1, max: 100 },
  email: "email",
  age: { type: "integer", min: 0, max: 120 },
  isActive: { type: "boolean", default: true },
};

Validating Data

Use the Valid.process function to validate data against your schema.

try {
  const validUser = Valid.process(userData, Valid.Object(userSchema));
  // Data validated successfully
  console.log(validUser);
} catch (error) {
  // Handle validation errors
  console.error("Validation Error:", error.message);
}

Partial Object Validation

For cases where you need to validate only part of an object (e.g., during PATCH requests), you can use the allowPartial option.

try {
  const validPartialUser = Valid.process(
    partialUserData,
    Valid.Object(userSchema, { allowPartial: true })
  );
  // Partial data validated successfully
  console.log(validPartialUser);
} catch (error) {
  console.error("Validation Error:", error.message);
}

Util

This set of utility functions is designed to help with common tasks involving objects, enums, arrays, dates, numbers and strings. Each function addresses typical operations one might need in a project.

Objects

  • Checks if the parameter is a valid object.
isObject(obj?: any) 
  • Checks if the objects are equal by their keys.
isObjectsEqual(object?: any, object2?: any)
  • Returns an object of type Partial from the specified set of keys.
objPickKeys<O = Record<string, any>>( obj:O, keys: (keyof O)[]): Partial<O>
  • Removes the specified keys from the object and returns a new object without those keys.
objDeleteKeys<O>( obj:O, keys: (keyof O)[]): Partial<O>
  • Creates a reverse mapping for an object, where keys become values and values. become keys
reverseMapping(obj: {[key: number]: string}): {[key: string]: number}

Enums

  • Converts a numeric enum to an array of strings containing the enum's key names.
enumToKeysArray(enumObject: Object): string[]
  • Converts a string enum to an array of strings containing the enum's values.
enumToValuesArray(enumObject: Object): string[]

Arrays

  • Returns a random element from an array.
randomElement<I=any>( arr: I[]):I
  • Removes an element from an array if it is present.
deleteElement<I=any>( arr: I[], elm: I ): I[]
  • Checks if the text exists in the specified key of objects in an array.
findInArrayObjects( array: Record<string, any>[], key: string, text: string): boolean

Time and Delays

  • Delays execution for the specified number of milliseconds.
asyncSleep (ms: number, fn?: (id: any) => void): Promise<boolean>
  • Generates a numerical key for a given date in the format YYYYMMDD. If no date is provided, it uses the current date.
getDayKey(date?: Date): number
  • Returns a date adjusted for a given time zone offset in minutes.
getDateWithTimeZone(date?: Date, offsetMin?: number): Date
  • Formats a date into a string. It allows customization on how to display the date and time and whether to include seconds or only the date.
getFormattedDate(date?: Date, delimiter: string = 'в ', options: {...}): string
  • Parses an ISO date string and returns an object with separate strings for the date and time.
getDateAndTimeFromISO(isoString: string, offsetMin?: number): { date: string, time: string }
  • Returns the number of seconds that have passed since a specified time.
getTimeSecSince(since: number, sec = 'sec.')

Strings

  • Removes all non-numeric characters from a string.
strOnlyDigits(str: string): string
  • Searches for text within a string without case sensitivity.
findText(text?: string | null, inString?: string): boolean
  • Returns a string with the first letter capitalized.
static capitalize(str: string)

Numbers

  • Rounds a number to the specified number of decimal places.
mathRound(num: number, n: number = 2): number
  • Returns a string representation of a number with consideration for declension.
makeStringValue(dVal: number, bGender: boolean)
  • Checks a number and adds its representation and declension to an array.
checkNumber(fValue: number, oObjDesc: OrderItem, fnAddNum: FnAddNumber, fnAddDesc: FnAddNumber)
  • Converts a number into a string, considering declensions and currency descriptions.
numberToPhrase(fAmount: number, withCurrencyDesc: boolean = true)
  • Declines words based on the number provided.
declineWord(n: number, word: keyof typeof this.acceptedWords)
  • Returns the name of a month based on its number.
getMonthByNumber(number: number, isGenitive = true)

Format currency methods

  • Formats a number as a monetary amount with two decimal places and adds a currency symbol.
formatCurrencyNum(money: number, currency: string =''): string
  • Formats a string representing a numeric value
formatCurrencyStr(str: string, currency: string =''): string

Other methods

  • Formats full names into a short version (LastName I. O.).
getShortFIO(name?: string, surname?: string, patronymic?: string)