UNPKG

@nerdware/ddb-single-table

Version:

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

132 lines (131 loc) 5.76 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.stringifyNestedSchema = exports.getAttrErrID = exports.InvalidExpressionError = exports.ItemInputError = exports.SchemaValidationError = exports.DdbConnectionError = exports.DdbSingleTableError = void 0; const node_dns_1 = require("node:dns"); const ts_type_safety_utils_1 = require("@nerdware/ts-type-safety-utils"); /** Internal `errors` util */ const isNonEmptyString = (value) => (0, ts_type_safety_utils_1.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. */ 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); } } exports.DdbSingleTableError = DdbSingleTableError; /** * This error is used for network/connection errors. */ 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: node_dns_1.CONNREFUSED, }; /** 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 ((0, ts_type_safety_utils_1.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); } } exports.DdbConnectionError = 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}.` */ class SchemaValidationError extends DdbSingleTableError { static DEFAULT_MSG = "Invalid schema"; constructor(message) { const msgOrFormattedString = (0, ts_type_safety_utils_1.isPlainObject)(message) && (0, ts_type_safety_utils_1.isString)(message.schemaName) && (0, ts_type_safety_utils_1.isString)(message.problem) ? `${message.schemaName} is invalid: ${message.problem}.` : message; super(msgOrFormattedString, SchemaValidationError.DEFAULT_MSG); Error.captureStackTrace(this, SchemaValidationError); } } exports.SchemaValidationError = SchemaValidationError; /** * This error is thrown by Model `IOAction` functions when run-time input * data is invalid. */ class ItemInputError extends DdbSingleTableError { static DEFAULT_MSG = "Invalid item input"; constructor(message) { super(message, ItemInputError.DEFAULT_MSG); Error.captureStackTrace(this, ItemInputError); } } exports.ItemInputError = 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} */ class InvalidExpressionError extends DdbSingleTableError { static DEFAULT_MSG = "Invalid expression"; constructor(arg) { const message = isNonEmptyString(arg) ? arg : (0, ts_type_safety_utils_1.isPlainObject)(arg) && (0, ts_type_safety_utils_1.isString)(arg.expressionName) && (0, ts_type_safety_utils_1.isString)(arg.invalidValueDescription) && (0, ts_type_safety_utils_1.isString)(arg.problem) ? `Invalid ${arg.invalidValueDescription} (generating ${arg.expressionName}): \n` + `${arg.problem}: ${(0, ts_type_safety_utils_1.safeJsonStringify)(arg.invalidValue, null, 2)}` : InvalidExpressionError.DEFAULT_MSG; super(message); Error.captureStackTrace(this, InvalidExpressionError); } } exports.InvalidExpressionError = InvalidExpressionError; /** * Helper function which provides a consistent attribute identifier for error messages. */ const getAttrErrID = (modelName, attrName, { alias }) => { return `${modelName} property "${alias || attrName}"`; }; exports.getAttrErrID = getAttrErrID; /** * Helper function which stringifies a nested schema for error messages. */ const stringifyNestedSchema = (nestedSchema, spaces = 2) => { // prettier-ignore const strippedKeys = [ "isHashKey", "isRangeKey", "index", "required", "alias", "default", "validate", "transformValue", ]; return (0, ts_type_safety_utils_1.safeJsonStringify)(nestedSchema, (key, value) => { return typeof key === "string" && strippedKeys.includes(key) ? undefined : value; }, spaces); }; exports.stringifyNestedSchema = stringifyNestedSchema;