UNPKG

@nerdware/ddb-single-table

Version:

A schema-based DynamoDB modeling tool, high-level API, and type-generator built to supercharge single-table designs!⚡

122 lines (121 loc) 4.88 kB
import { CONNREFUSED as ECONNREFUSED } from "node:dns"; import { safeJsonStringify, isPlainObject, isString } from "@nerdware/ts-type-safety-utils"; /** Internal `errors` util */ const isNonEmptyString = (value) => isString(value) && !!value; /** * This is the base `error` class for custom errors defined in this package. If the * `message` arg is anything other than a truthy string, then the resultant Error's * `message` property will be set to a default value. A second `fallbackMsg` arg can * be provided to override the default message. */ export class DdbSingleTableError extends Error { static DEFAULT_MSG = "An unknown error occurred"; name; constructor(message, fallbackMsg = DdbSingleTableError.DEFAULT_MSG) { // This ctor allows `message` to be any type, but it's only used if it's a truthy string. super(isNonEmptyString(message) ? message : fallbackMsg); this.name = this.constructor.name; Error.captureStackTrace(this, DdbSingleTableError); } } /** * This error is used for network/connection errors. */ export class DdbConnectionError extends DdbSingleTableError { static DEFAULT_MSG = "Failed to connect to the provided DynamoDB endpoint"; /** Dictionary of relevant, connection-related NodeJS `err.code` values. */ static NODE_ERROR_CODES = { ECONNREFUSED, }; /** The {@link NodeJS.ErrnoException|NodeJS error code}. */ code; constructor(arg) { // Set defaults: let message = DdbConnectionError.DEFAULT_MSG, code = DdbConnectionError.NODE_ERROR_CODES.ECONNREFUSED; if (isNonEmptyString(arg)) { message = arg; } else if (isPlainObject(arg)) { if (isNonEmptyString(arg.message)) message += ` (${arg.message})`; if (isNonEmptyString(arg.code)) code = arg.code; } super(message); this.code = code; Error.captureStackTrace(this, DdbConnectionError); } } /** * This error is thrown by schema-validation functions when a `TableKeysSchema` * or `ModelSchema` is invalid. * * The provided {@link SchemaValidationErrorPayload} is used to create an error * message formatted as follows: * * > `{schemaName} is invalid: {problem}.` */ export class SchemaValidationError extends DdbSingleTableError { static DEFAULT_MSG = "Invalid schema"; constructor(message) { const msgOrFormattedString = isPlainObject(message) && isString(message.schemaName) && isString(message.problem) ? `${message.schemaName} is invalid: ${message.problem}.` : message; super(msgOrFormattedString, SchemaValidationError.DEFAULT_MSG); Error.captureStackTrace(this, SchemaValidationError); } } /** * This error is thrown by Model `IOAction` functions when run-time input * data is invalid. */ export class ItemInputError extends DdbSingleTableError { static DEFAULT_MSG = "Invalid item input"; constructor(message) { super(message, ItemInputError.DEFAULT_MSG); Error.captureStackTrace(this, ItemInputError); } } /** * This error is thrown by expression-generator utils when a run-time arg is invalid * (e.g., more than two K-V pairs for a `KeyConditionExpression`). * * To provide a consistent error message format, provide an [`InvalidExpressionErrorPayload`][err] * to the constructor. * * [err]: {@link InvalidExpressionErrorPayload} */ export class InvalidExpressionError extends DdbSingleTableError { static DEFAULT_MSG = "Invalid expression"; constructor(arg) { const message = isNonEmptyString(arg) ? arg : isPlainObject(arg) && isString(arg.expressionName) && isString(arg.invalidValueDescription) && isString(arg.problem) ? `Invalid ${arg.invalidValueDescription} (generating ${arg.expressionName}): \n` + `${arg.problem}: ${safeJsonStringify(arg.invalidValue, null, 2)}` : InvalidExpressionError.DEFAULT_MSG; super(message); Error.captureStackTrace(this, InvalidExpressionError); } } /** * Helper function which provides a consistent attribute identifier for error messages. */ export const getAttrErrID = (modelName, attrName, { alias }) => { return `${modelName} property "${alias || attrName}"`; }; /** * Helper function which stringifies a nested schema for error messages. */ export const stringifyNestedSchema = (nestedSchema, spaces = 2) => { // prettier-ignore const strippedKeys = [ "isHashKey", "isRangeKey", "index", "required", "alias", "default", "validate", "transformValue", ]; return safeJsonStringify(nestedSchema, (key, value) => { return typeof key === "string" && strippedKeys.includes(key) ? undefined : value; }, spaces); };