@parsrun/core 0.2.5 → 0.2.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/decimal.ts"],"sourcesContent":["/**\n * @parsrun/core - Decimal Utilities\n * Precise decimal calculations for financial and quantity operations.\n * Edge-compatible - no external dependencies.\n *\n * @example\n * ```typescript\n * import { Decimal, decimal } from '@parsrun/core';\n *\n * // Create decimals\n * const price = new Decimal('19.99');\n * const quantity = decimal(3);\n *\n * // Arithmetic operations (chainable)\n * const total = price.mul(quantity).round(2);\n * console.log(total.toString()); // '59.97'\n *\n * // Static helpers\n * const sum = Decimal.sum(['10.50', '20.25', '15.75']);\n * const avg = Decimal.avg([100, 200, 300]);\n * ```\n */\n\n/**\n * Internal precision for calculations (number of decimal places)\n */\nconst PRECISION = 20;\n\n/**\n * Decimal class for precise arithmetic operations.\n * Uses string-based representation internally to avoid floating point issues.\n *\n * @example\n * ```typescript\n * const a = new Decimal('0.1');\n * const b = new Decimal('0.2');\n * const c = a.add(b);\n * console.log(c.toString()); // '0.3' (not 0.30000000000000004)\n * ```\n */\nexport class Decimal {\n private value: string;\n\n constructor(value: number | string | Decimal) {\n if (value instanceof Decimal) {\n this.value = value.value;\n } else if (typeof value === \"number\") {\n this.value = this.normalizeNumber(value);\n } else {\n this.value = this.normalizeString(value);\n }\n }\n\n private normalizeNumber(n: number): string {\n if (!isFinite(n)) {\n throw new Error(`Invalid number: ${n}`);\n }\n return n.toFixed(PRECISION).replace(/\\.?0+$/, \"\") || \"0\";\n }\n\n private normalizeString(s: string): string {\n const trimmed = s.trim();\n if (!/^-?\\d*\\.?\\d+$/.test(trimmed)) {\n throw new Error(`Invalid decimal string: ${s}`);\n }\n return trimmed.replace(/^(-?)0+(?=\\d)/, \"$1\").replace(/\\.?0+$/, \"\") || \"0\";\n }\n\n /**\n * Add another value to this decimal.\n * @param other - Value to add\n * @returns A new Decimal with the result\n */\n add(other: number | string | Decimal): Decimal {\n const a = parseFloat(this.value);\n const b = parseFloat(other instanceof Decimal ? other.value : String(other));\n return new Decimal(a + b);\n }\n\n /**\n * Subtract a value from this decimal.\n * @param other - Value to subtract\n * @returns A new Decimal with the result\n */\n sub(other: number | string | Decimal): Decimal {\n const a = parseFloat(this.value);\n const b = parseFloat(other instanceof Decimal ? other.value : String(other));\n return new Decimal(a - b);\n }\n\n /**\n * Multiply this decimal by another value.\n * @param other - Value to multiply by\n * @returns A new Decimal with the result\n */\n mul(other: number | string | Decimal): Decimal {\n const a = parseFloat(this.value);\n const b = parseFloat(other instanceof Decimal ? other.value : String(other));\n return new Decimal(a * b);\n }\n\n /**\n * Divide this decimal by another value.\n * @param other - Value to divide by\n * @returns A new Decimal with the result\n * @throws Error if dividing by zero\n */\n div(other: number | string | Decimal): Decimal {\n const a = parseFloat(this.value);\n const b = parseFloat(other instanceof Decimal ? other.value : String(other));\n if (b === 0) {\n throw new Error(\"Division by zero\");\n }\n return new Decimal(a / b);\n }\n\n /**\n * Get the modulo (remainder) of dividing this decimal by another value.\n * @param other - Value to divide by\n * @returns A new Decimal with the remainder\n */\n mod(other: number | string | Decimal): Decimal {\n const a = parseFloat(this.value);\n const b = parseFloat(other instanceof Decimal ? other.value : String(other));\n return new Decimal(a % b);\n }\n\n /**\n * Raise this decimal to a power.\n * @param exp - The exponent\n * @returns A new Decimal with the result\n */\n pow(exp: number): Decimal {\n const a = parseFloat(this.value);\n return new Decimal(Math.pow(a, exp));\n }\n\n /**\n * Calculate the square root of this decimal.\n * @returns A new Decimal with the square root\n * @throws Error if the value is negative\n */\n sqrt(): Decimal {\n const a = parseFloat(this.value);\n if (a < 0) {\n throw new Error(\"Square root of negative number\");\n }\n return new Decimal(Math.sqrt(a));\n }\n\n /**\n * Get the absolute value of this decimal.\n * @returns A new Decimal with the absolute value\n */\n abs(): Decimal {\n const a = parseFloat(this.value);\n return new Decimal(Math.abs(a));\n }\n\n /**\n * Negate this decimal (multiply by -1).\n * @returns A new Decimal with the negated value\n */\n neg(): Decimal {\n const a = parseFloat(this.value);\n return new Decimal(-a);\n }\n\n /**\n * Round to the specified number of decimal places using standard rounding.\n * @param decimals - Number of decimal places (default: 0)\n * @returns A new Decimal with the rounded value\n */\n round(decimals: number = 0): Decimal {\n const a = parseFloat(this.value);\n const factor = Math.pow(10, decimals);\n return new Decimal(Math.round(a * factor) / factor);\n }\n\n /**\n * Round down to the specified number of decimal places.\n * @param decimals - Number of decimal places (default: 0)\n * @returns A new Decimal with the floored value\n */\n floor(decimals: number = 0): Decimal {\n const a = parseFloat(this.value);\n const factor = Math.pow(10, decimals);\n return new Decimal(Math.floor(a * factor) / factor);\n }\n\n /**\n * Round up to the specified number of decimal places.\n * @param decimals - Number of decimal places (default: 0)\n * @returns A new Decimal with the ceiled value\n */\n ceil(decimals: number = 0): Decimal {\n const a = parseFloat(this.value);\n const factor = Math.pow(10, decimals);\n return new Decimal(Math.ceil(a * factor) / factor);\n }\n\n /**\n * Compare this decimal to another value.\n * @param other - Value to compare against\n * @returns -1 if less, 0 if equal, 1 if greater\n */\n cmp(other: number | string | Decimal): -1 | 0 | 1 {\n const a = parseFloat(this.value);\n const b = parseFloat(other instanceof Decimal ? other.value : String(other));\n if (a < b) return -1;\n if (a > b) return 1;\n return 0;\n }\n\n /**\n * Check if this decimal equals another value.\n * @param other - Value to compare against\n * @returns True if values are equal\n */\n eq(other: number | string | Decimal): boolean {\n return this.cmp(other) === 0;\n }\n\n /**\n * Check if this decimal is greater than another value.\n * @param other - Value to compare against\n * @returns True if this is greater\n */\n gt(other: number | string | Decimal): boolean {\n return this.cmp(other) === 1;\n }\n\n /**\n * Check if this decimal is greater than or equal to another value.\n * @param other - Value to compare against\n * @returns True if this is greater or equal\n */\n gte(other: number | string | Decimal): boolean {\n return this.cmp(other) >= 0;\n }\n\n /**\n * Check if this decimal is less than another value.\n * @param other - Value to compare against\n * @returns True if this is less\n */\n lt(other: number | string | Decimal): boolean {\n return this.cmp(other) === -1;\n }\n\n /**\n * Check if this decimal is less than or equal to another value.\n * @param other - Value to compare against\n * @returns True if this is less or equal\n */\n lte(other: number | string | Decimal): boolean {\n return this.cmp(other) <= 0;\n }\n\n /**\n * Check if this decimal is exactly zero.\n * @returns True if value is zero\n */\n isZero(): boolean {\n return parseFloat(this.value) === 0;\n }\n\n /**\n * Check if this decimal is positive (greater than zero).\n * @returns True if value is positive\n */\n isPositive(): boolean {\n return parseFloat(this.value) > 0;\n }\n\n /**\n * Check if this decimal is negative (less than zero).\n * @returns True if value is negative\n */\n isNegative(): boolean {\n return parseFloat(this.value) < 0;\n }\n\n /**\n * Convert this decimal to a JavaScript number.\n * @returns The numeric value\n */\n toNumber(): number {\n return parseFloat(this.value);\n }\n\n /**\n * Convert this decimal to its string representation.\n * @returns The string value\n */\n toString(): string {\n return this.value;\n }\n\n /**\n * Format this decimal with a fixed number of decimal places.\n * @param decimals - Number of decimal places (default: 2)\n * @returns Formatted string\n */\n toFixed(decimals: number = 2): string {\n return parseFloat(this.value).toFixed(decimals);\n }\n\n /**\n * Convert to JSON (returns string representation for serialization).\n * @returns The string value for JSON serialization\n */\n toJSON(): string {\n return this.value;\n }\n\n /**\n * Create a Decimal from a value (alias for constructor).\n * @param value - The value to convert\n * @returns A new Decimal instance\n */\n static from(value: number | string | Decimal): Decimal {\n return new Decimal(value);\n }\n\n /**\n * Calculate the sum of an array of values.\n * @param values - Array of values to sum\n * @returns A new Decimal with the sum\n */\n static sum(values: (number | string | Decimal)[]): Decimal {\n return values.reduce<Decimal>(\n (acc, val) => acc.add(val),\n new Decimal(0)\n );\n }\n\n /**\n * Calculate the average of an array of values.\n * @param values - Array of values to average\n * @returns A new Decimal with the average (0 if empty array)\n */\n static avg(values: (number | string | Decimal)[]): Decimal {\n if (values.length === 0) return new Decimal(0);\n return Decimal.sum(values).div(values.length);\n }\n\n /**\n * Find the minimum value from the provided values.\n * @param values - Values to compare\n * @returns A new Decimal with the minimum value\n * @throws Error if no values provided\n */\n static min(...values: (number | string | Decimal)[]): Decimal {\n if (values.length === 0) throw new Error(\"No values provided\");\n return values.reduce<Decimal>((min, val) => {\n const d = new Decimal(val);\n return d.lt(min) ? d : min;\n }, new Decimal(values[0]!));\n }\n\n /**\n * Find the maximum value from the provided values.\n * @param values - Values to compare\n * @returns A new Decimal with the maximum value\n * @throws Error if no values provided\n */\n static max(...values: (number | string | Decimal)[]): Decimal {\n if (values.length === 0) throw new Error(\"No values provided\");\n return values.reduce<Decimal>((max, val) => {\n const d = new Decimal(val);\n return d.gt(max) ? d : max;\n }, new Decimal(values[0]!));\n }\n}\n\n/**\n * Utility functions for working with decimals in database operations.\n * Provides helpers for converting between JavaScript numbers and database decimal strings.\n *\n * @example\n * ```typescript\n * // Convert numeric fields before database insert\n * const data = DecimalUtils.prepareForDatabase(\n * { price: 19.99, quantity: 5 },\n * ['price']\n * );\n *\n * // Format for display\n * DecimalUtils.formatCurrency('19.99', { currency: 'USD' }); // '$19.99'\n * ```\n */\nexport const DecimalUtils = {\n /**\n * Convert a number to a database-safe decimal string.\n * @param value - The value to convert\n * @returns The decimal string or null if value is null/undefined\n */\n toDecimalString(value: number | string | null | undefined): string | null {\n if (value === null || value === undefined) return null;\n return new Decimal(value).toString();\n },\n\n /**\n * Convert a database decimal string to a JavaScript number.\n * @param value - The decimal string from database\n * @returns The numeric value (0 if null/undefined/empty)\n */\n fromDecimalString(value: string | null | undefined): number {\n if (!value) return 0;\n return new Decimal(value).toNumber();\n },\n\n /**\n * Multiply two values with precise decimal arithmetic.\n * @param a - First value\n * @param b - Second value\n * @returns The product as a string\n */\n multiply(a: number | string, b: number | string): string {\n return new Decimal(a).mul(b).toString();\n },\n\n /**\n * Add two values with precise decimal arithmetic.\n * @param a - First value\n * @param b - Second value\n * @returns The sum as a string\n */\n add(a: number | string, b: number | string): string {\n return new Decimal(a).add(b).toString();\n },\n\n /**\n * Subtract two values with precise decimal arithmetic.\n * @param a - Value to subtract from\n * @param b - Value to subtract\n * @returns The difference as a string\n */\n subtract(a: number | string, b: number | string): string {\n return new Decimal(a).sub(b).toString();\n },\n\n /**\n * Divide two values with precise decimal arithmetic.\n * @param a - Dividend\n * @param b - Divisor\n * @returns The quotient as a string\n */\n divide(a: number | string, b: number | string): string {\n return new Decimal(a).div(b).toString();\n },\n\n /**\n * Format a decimal value for display with fixed decimal places.\n * @param value - The value to format\n * @param decimalPlaces - Number of decimal places (default: 2)\n * @returns Formatted string\n */\n format(value: string | number, decimalPlaces: number = 2): string {\n return new Decimal(value).toFixed(decimalPlaces);\n },\n\n /**\n * Format a value as currency using Intl.NumberFormat.\n * @param value - The value to format\n * @param options - Currency formatting options\n * @returns Formatted currency string\n */\n formatCurrency(\n value: string | number,\n options: {\n currency?: string;\n locale?: string;\n decimals?: number;\n } = {}\n ): string {\n const { currency = \"USD\", locale = \"en-US\", decimals = 2 } = options;\n const num = new Decimal(value).toNumber();\n return new Intl.NumberFormat(locale, {\n style: \"currency\",\n currency,\n minimumFractionDigits: decimals,\n maximumFractionDigits: decimals,\n }).format(num);\n },\n\n /**\n * Prepare an object for database insert/update by converting numeric fields to decimal strings.\n * @param data - The object to prepare\n * @param decimalFields - Array of field names that should be converted to decimal strings\n * @returns A new object with specified fields converted to decimal strings\n */\n prepareForDatabase<T extends Record<string, unknown>>(\n data: T,\n decimalFields: string[]\n ): T {\n const result = { ...data };\n for (const field of decimalFields) {\n if (field in result && result[field] !== undefined && result[field] !== null) {\n const value = result[field];\n if (typeof value === \"number\") {\n (result as Record<string, unknown>)[field] = DecimalUtils.toDecimalString(value);\n }\n }\n }\n return result;\n },\n\n /**\n * Parse an object from database by converting decimal string fields to JavaScript numbers.\n * @param data - The object from database\n * @param decimalFields - Array of field names that should be converted from decimal strings\n * @returns A new object with specified fields converted to numbers\n */\n parseFromDatabase<T extends Record<string, unknown>>(\n data: T,\n decimalFields: string[]\n ): T {\n const result = { ...data };\n for (const field of decimalFields) {\n if (field in result && result[field] !== undefined && result[field] !== null) {\n const value = result[field];\n if (typeof value === \"string\") {\n (result as Record<string, unknown>)[field] = DecimalUtils.fromDecimalString(value);\n }\n }\n }\n return result;\n },\n};\n\n/**\n * Shorthand function for creating a Decimal instance.\n *\n * @param value - The value to convert to a Decimal\n * @returns A new Decimal instance\n *\n * @example\n * ```typescript\n * const price = decimal('19.99');\n * const total = decimal(100).mul(price);\n * ```\n */\nexport function decimal(value: number | string): Decimal {\n return new Decimal(value);\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/decimal.ts"],"sourcesContent":["/**\n * @parsrun/core - Decimal Utilities\n * Precise decimal calculations for financial and quantity operations.\n * Edge-compatible - wraps decimal.js for arbitrary precision arithmetic.\n *\n * @example\n * ```typescript\n * import { Decimal, decimal } from '@parsrun/core';\n *\n * // Create decimals\n * const price = new Decimal('19.99');\n * const quantity = decimal(3);\n *\n * // Arithmetic operations (chainable)\n * const total = price.mul(quantity).round(2);\n * console.log(total.toString()); // '59.97'\n *\n * // Precision info\n * const d = new Decimal('123.45');\n * d.precision(); // 5 (total significant digits)\n * d.decimalPlaces(); // 2 (digits after decimal point)\n *\n * // Static helpers\n * const sum = Decimal.sum(['10.50', '20.25', '15.75']);\n * const avg = Decimal.avg([100, 200, 300]);\n * ```\n */\n\nimport DecimalJS from 'decimal.js';\n\n// Configure decimal.js for financial precision\nDecimalJS.set({\n precision: 40,\n rounding: DecimalJS.ROUND_HALF_UP,\n toExpNeg: -9,\n toExpPos: 21,\n});\n\n/**\n * Decimal class for precise arithmetic operations.\n * Wraps decimal.js to provide arbitrary precision decimal arithmetic.\n *\n * @example\n * ```typescript\n * const a = new Decimal('0.1');\n * const b = new Decimal('0.2');\n * const c = a.add(b);\n * console.log(c.toString()); // '0.3' (not 0.30000000000000004)\n * ```\n */\nexport class Decimal {\n private readonly _value: DecimalJS;\n\n constructor(value: number | string | Decimal | DecimalJS) {\n if (value instanceof Decimal) {\n this._value = value._value;\n } else if (value instanceof DecimalJS) {\n this._value = value;\n } else {\n this._value = new DecimalJS(value);\n }\n }\n\n /**\n * Add another value to this decimal.\n * @param other - Value to add\n * @returns A new Decimal with the result\n */\n add(other: number | string | Decimal): Decimal {\n const otherValue = other instanceof Decimal ? other._value : other;\n return new Decimal(this._value.plus(otherValue));\n }\n\n /**\n * Subtract a value from this decimal.\n * @param other - Value to subtract\n * @returns A new Decimal with the result\n */\n sub(other: number | string | Decimal): Decimal {\n const otherValue = other instanceof Decimal ? other._value : other;\n return new Decimal(this._value.minus(otherValue));\n }\n\n /**\n * Multiply this decimal by another value.\n * @param other - Value to multiply by\n * @returns A new Decimal with the result\n */\n mul(other: number | string | Decimal): Decimal {\n const otherValue = other instanceof Decimal ? other._value : other;\n return new Decimal(this._value.times(otherValue));\n }\n\n /**\n * Divide this decimal by another value.\n * @param other - Value to divide by\n * @returns A new Decimal with the result\n * @throws Error if dividing by zero\n */\n div(other: number | string | Decimal): Decimal {\n const otherValue = other instanceof Decimal ? other._value : other;\n const divisor = new DecimalJS(otherValue);\n if (divisor.isZero()) {\n throw new Error('Division by zero');\n }\n return new Decimal(this._value.dividedBy(divisor));\n }\n\n /**\n * Get the modulo (remainder) of dividing this decimal by another value.\n * @param other - Value to divide by\n * @returns A new Decimal with the remainder\n */\n mod(other: number | string | Decimal): Decimal {\n const otherValue = other instanceof Decimal ? other._value : other;\n return new Decimal(this._value.modulo(otherValue));\n }\n\n /**\n * Raise this decimal to a power.\n * @param exp - The exponent\n * @returns A new Decimal with the result\n */\n pow(exp: number): Decimal {\n return new Decimal(this._value.pow(exp));\n }\n\n /**\n * Calculate the square root of this decimal.\n * @returns A new Decimal with the square root\n * @throws Error if the value is negative\n */\n sqrt(): Decimal {\n if (this._value.isNegative()) {\n throw new Error('Square root of negative number');\n }\n return new Decimal(this._value.sqrt());\n }\n\n /**\n * Get the absolute value of this decimal.\n * @returns A new Decimal with the absolute value\n */\n abs(): Decimal {\n return new Decimal(this._value.abs());\n }\n\n /**\n * Negate this decimal (multiply by -1).\n * @returns A new Decimal with the negated value\n */\n neg(): Decimal {\n return new Decimal(this._value.negated());\n }\n\n /**\n * Round to the specified number of decimal places using standard rounding.\n * @param decimals - Number of decimal places (default: 0)\n * @returns A new Decimal with the rounded value\n */\n round(decimals: number = 0): Decimal {\n return new Decimal(this._value.toDecimalPlaces(decimals, DecimalJS.ROUND_HALF_UP));\n }\n\n /**\n * Round down to the specified number of decimal places.\n * @param decimals - Number of decimal places (default: 0)\n * @returns A new Decimal with the floored value\n */\n floor(decimals: number = 0): Decimal {\n return new Decimal(this._value.toDecimalPlaces(decimals, DecimalJS.ROUND_FLOOR));\n }\n\n /**\n * Round up to the specified number of decimal places.\n * @param decimals - Number of decimal places (default: 0)\n * @returns A new Decimal with the ceiled value\n */\n ceil(decimals: number = 0): Decimal {\n return new Decimal(this._value.toDecimalPlaces(decimals, DecimalJS.ROUND_CEIL));\n }\n\n /**\n * Compare this decimal to another value.\n * @param other - Value to compare against\n * @returns -1 if less, 0 if equal, 1 if greater\n */\n cmp(other: number | string | Decimal): -1 | 0 | 1 {\n const otherValue = other instanceof Decimal ? other._value : other;\n return this._value.comparedTo(otherValue) as -1 | 0 | 1;\n }\n\n /**\n * Check if this decimal equals another value.\n * @param other - Value to compare against\n * @returns True if values are equal\n */\n eq(other: number | string | Decimal): boolean {\n const otherValue = other instanceof Decimal ? other._value : other;\n return this._value.equals(otherValue);\n }\n\n /**\n * Check if this decimal is greater than another value.\n * @param other - Value to compare against\n * @returns True if this is greater\n */\n gt(other: number | string | Decimal): boolean {\n const otherValue = other instanceof Decimal ? other._value : other;\n return this._value.greaterThan(otherValue);\n }\n\n /**\n * Check if this decimal is greater than or equal to another value.\n * @param other - Value to compare against\n * @returns True if this is greater or equal\n */\n gte(other: number | string | Decimal): boolean {\n const otherValue = other instanceof Decimal ? other._value : other;\n return this._value.greaterThanOrEqualTo(otherValue);\n }\n\n /**\n * Check if this decimal is less than another value.\n * @param other - Value to compare against\n * @returns True if this is less\n */\n lt(other: number | string | Decimal): boolean {\n const otherValue = other instanceof Decimal ? other._value : other;\n return this._value.lessThan(otherValue);\n }\n\n /**\n * Check if this decimal is less than or equal to another value.\n * @param other - Value to compare against\n * @returns True if this is less or equal\n */\n lte(other: number | string | Decimal): boolean {\n const otherValue = other instanceof Decimal ? other._value : other;\n return this._value.lessThanOrEqualTo(otherValue);\n }\n\n /**\n * Check if this decimal is exactly zero.\n * @returns True if value is zero\n */\n isZero(): boolean {\n return this._value.isZero();\n }\n\n /**\n * Check if this decimal is positive (greater than zero).\n * @returns True if value is positive\n */\n isPositive(): boolean {\n return this._value.isPositive() && !this._value.isZero();\n }\n\n /**\n * Check if this decimal is negative (less than zero).\n * @returns True if value is negative\n */\n isNegative(): boolean {\n return this._value.isNegative();\n }\n\n /**\n * Check if this decimal is an integer (no decimal places).\n * @returns True if value is an integer\n */\n isInteger(): boolean {\n return this._value.isInteger();\n }\n\n /**\n * Get the number of decimal places (digits after the decimal point).\n * @returns Number of decimal places\n *\n * @example\n * ```typescript\n * new Decimal('123.45').decimalPlaces(); // 2\n * new Decimal('100').decimalPlaces(); // 0\n * new Decimal('1.500').decimalPlaces(); // 1 (trailing zeros removed)\n * ```\n */\n decimalPlaces(): number {\n return this._value.decimalPlaces();\n }\n\n /**\n * Get the precision (total number of significant digits).\n * @param includeZeros - If true, include trailing zeros in the count\n * @returns The precision\n *\n * @example\n * ```typescript\n * new Decimal('123.45').precision(); // 5\n * new Decimal('100').precision(); // 1\n * new Decimal('100').precision(true); // 3\n * ```\n */\n precision(includeZeros: boolean = false): number {\n return this._value.precision(includeZeros);\n }\n\n /**\n * Convert this decimal to a JavaScript number.\n * Warning: May lose precision for very large or very precise numbers.\n * @returns The numeric value\n */\n toNumber(): number {\n return this._value.toNumber();\n }\n\n /**\n * Convert this decimal to its string representation.\n * @returns The string value\n */\n toString(): string {\n return this._value.toString();\n }\n\n /**\n * Format this decimal with a fixed number of decimal places.\n * @param decimals - Number of decimal places (default: 2)\n * @returns Formatted string\n */\n toFixed(decimals: number = 2): string {\n return this._value.toFixed(decimals);\n }\n\n /**\n * Convert to JSON (returns string representation for serialization).\n * @returns The string value for JSON serialization\n */\n toJSON(): string {\n return this._value.toString();\n }\n\n /**\n * Get the underlying decimal.js instance.\n * Useful for advanced operations not covered by this wrapper.\n * @returns The underlying DecimalJS instance\n */\n toDecimalJS(): DecimalJS {\n return this._value;\n }\n\n /**\n * Create a Decimal from a value (alias for constructor).\n * @param value - The value to convert\n * @returns A new Decimal instance\n */\n static from(value: number | string | Decimal): Decimal {\n return new Decimal(value);\n }\n\n /**\n * Calculate the sum of an array of values.\n * @param values - Array of values to sum\n * @returns A new Decimal with the sum\n */\n static sum(values: (number | string | Decimal)[]): Decimal {\n return values.reduce<Decimal>(\n (acc, val) => acc.add(val),\n new Decimal(0)\n );\n }\n\n /**\n * Calculate the average of an array of values.\n * @param values - Array of values to average\n * @returns A new Decimal with the average (0 if empty array)\n */\n static avg(values: (number | string | Decimal)[]): Decimal {\n if (values.length === 0) return new Decimal(0);\n return Decimal.sum(values).div(values.length);\n }\n\n /**\n * Find the minimum value from the provided values.\n * @param values - Values to compare\n * @returns A new Decimal with the minimum value\n * @throws Error if no values provided\n */\n static min(...values: (number | string | Decimal)[]): Decimal {\n if (values.length === 0) throw new Error('No values provided');\n return values.reduce<Decimal>((min, val) => {\n const d = new Decimal(val);\n return d.lt(min) ? d : min;\n }, new Decimal(values[0]!));\n }\n\n /**\n * Find the maximum value from the provided values.\n * @param values - Values to compare\n * @returns A new Decimal with the maximum value\n * @throws Error if no values provided\n */\n static max(...values: (number | string | Decimal)[]): Decimal {\n if (values.length === 0) throw new Error('No values provided');\n return values.reduce<Decimal>((max, val) => {\n const d = new Decimal(val);\n return d.gt(max) ? d : max;\n }, new Decimal(values[0]!));\n }\n\n /**\n * Check if a value is a valid decimal representation.\n * @param value - The value to check\n * @returns True if the value can be converted to a Decimal\n */\n static isValid(value: unknown): boolean {\n if (value === null || value === undefined) return false;\n if (value instanceof Decimal) return true;\n try {\n new DecimalJS(value as string | number);\n return true;\n } catch {\n return false;\n }\n }\n\n /**\n * Create a Decimal or return null if the value is invalid.\n * @param value - The value to convert\n * @returns A Decimal or null\n */\n static tryParse(value: unknown): Decimal | null {\n if (!Decimal.isValid(value)) return null;\n return new Decimal(value as number | string | Decimal);\n }\n}\n\n/**\n * Utility functions for working with decimals in database operations.\n * Provides helpers for converting between JavaScript numbers and database decimal strings.\n *\n * @example\n * ```typescript\n * // Convert numeric fields before database insert\n * const data = DecimalUtils.prepareForDatabase(\n * { price: 19.99, quantity: 5 },\n * ['price']\n * );\n *\n * // Format for display\n * DecimalUtils.formatCurrency('19.99', { currency: 'USD' }); // '$19.99'\n * ```\n */\nexport const DecimalUtils = {\n /**\n * Convert a number to a database-safe decimal string.\n * @param value - The value to convert\n * @returns The decimal string or null if value is null/undefined\n */\n toDecimalString(value: number | string | null | undefined): string | null {\n if (value === null || value === undefined) return null;\n return new Decimal(value).toString();\n },\n\n /**\n * Convert a database decimal string to a JavaScript number.\n * @param value - The decimal string from database\n * @returns The numeric value (0 if null/undefined/empty)\n */\n fromDecimalString(value: string | null | undefined): number {\n if (!value) return 0;\n return new Decimal(value).toNumber();\n },\n\n /**\n * Multiply two values with precise decimal arithmetic.\n * @param a - First value\n * @param b - Second value\n * @returns The product as a string\n */\n multiply(a: number | string, b: number | string): string {\n return new Decimal(a).mul(b).toString();\n },\n\n /**\n * Add two values with precise decimal arithmetic.\n * @param a - First value\n * @param b - Second value\n * @returns The sum as a string\n */\n add(a: number | string, b: number | string): string {\n return new Decimal(a).add(b).toString();\n },\n\n /**\n * Subtract two values with precise decimal arithmetic.\n * @param a - Value to subtract from\n * @param b - Value to subtract\n * @returns The difference as a string\n */\n subtract(a: number | string, b: number | string): string {\n return new Decimal(a).sub(b).toString();\n },\n\n /**\n * Divide two values with precise decimal arithmetic.\n * @param a - Dividend\n * @param b - Divisor\n * @returns The quotient as a string\n */\n divide(a: number | string, b: number | string): string {\n return new Decimal(a).div(b).toString();\n },\n\n /**\n * Format a decimal value for display with fixed decimal places.\n * @param value - The value to format\n * @param decimalPlaces - Number of decimal places (default: 2)\n * @returns Formatted string\n */\n format(value: string | number, decimalPlaces: number = 2): string {\n return new Decimal(value).toFixed(decimalPlaces);\n },\n\n /**\n * Format a value as currency using Intl.NumberFormat.\n * @param value - The value to format\n * @param options - Currency formatting options\n * @returns Formatted currency string\n */\n formatCurrency(\n value: string | number,\n options: {\n currency?: string;\n locale?: string;\n decimals?: number;\n } = {}\n ): string {\n const { currency = 'USD', locale = 'en-US', decimals = 2 } = options;\n const num = new Decimal(value).toNumber();\n return new Intl.NumberFormat(locale, {\n style: 'currency',\n currency,\n minimumFractionDigits: decimals,\n maximumFractionDigits: decimals,\n }).format(num);\n },\n\n /**\n * Prepare an object for database insert/update by converting numeric fields to decimal strings.\n * @param data - The object to prepare\n * @param decimalFields - Array of field names that should be converted to decimal strings\n * @returns A new object with specified fields converted to decimal strings\n */\n prepareForDatabase<T extends Record<string, unknown>>(\n data: T,\n decimalFields: string[]\n ): T {\n const result = { ...data };\n for (const field of decimalFields) {\n if (field in result && result[field] !== undefined && result[field] !== null) {\n const value = result[field];\n if (typeof value === 'number' || typeof value === 'string') {\n (result as Record<string, unknown>)[field] = DecimalUtils.toDecimalString(value);\n } else if (value instanceof Decimal) {\n (result as Record<string, unknown>)[field] = value.toString();\n }\n }\n }\n return result;\n },\n\n /**\n * Parse an object from database by converting decimal string fields to Decimal instances.\n * @param data - The object from database\n * @param decimalFields - Array of field names that should be converted to Decimal\n * @returns A new object with specified fields converted to Decimal instances\n */\n parseFromDatabase<T extends Record<string, unknown>>(\n data: T,\n decimalFields: string[]\n ): T {\n const result = { ...data };\n for (const field of decimalFields) {\n if (field in result && result[field] !== undefined && result[field] !== null) {\n const value = result[field];\n if (typeof value === 'string' || typeof value === 'number') {\n (result as Record<string, unknown>)[field] = new Decimal(value);\n }\n }\n }\n return result;\n },\n\n /**\n * Validate that a value matches the specified precision and scale.\n * @param value - The value to validate\n * @param precision - Total number of digits (integer + decimal)\n * @param scale - Number of decimal places\n * @returns An error message if invalid, or null if valid\n *\n * @example\n * ```typescript\n * DecimalUtils.validate('123.45', 5, 2); // null (valid)\n * DecimalUtils.validate('123.456', 5, 2); // \"max 2 decimal places allowed\"\n * DecimalUtils.validate('1234.56', 5, 2); // \"max 3 integer digits allowed\"\n * ```\n */\n validate(\n value: number | string | Decimal,\n precision: number,\n scale: number\n ): string | null {\n const d = value instanceof Decimal ? value : new Decimal(value);\n const maxIntDigits = precision - scale;\n\n // Check scale (decimal places)\n if (d.decimalPlaces() > scale) {\n return `max ${scale} decimal places allowed`;\n }\n\n // Check integer digits\n const absValue = d.abs();\n if (!absValue.isZero()) {\n // Count integer digits: precision(true) - decimalPlaces\n // But for numbers like 100, precision(true) gives 3, which is correct\n // For 100.00, we need the integer part's digit count\n const integerPart = absValue.floor(0);\n const intDigits = integerPart.isZero() ? 0 : integerPart.precision(true);\n\n if (intDigits > maxIntDigits) {\n return `max ${maxIntDigits} integer digits allowed`;\n }\n }\n\n return null;\n },\n};\n\n/**\n * Shorthand function for creating a Decimal instance.\n *\n * @param value - The value to convert to a Decimal\n * @returns A new Decimal instance\n *\n * @example\n * ```typescript\n * const price = decimal('19.99');\n * const total = decimal(100).mul(price);\n * ```\n */\nexport function decimal(value: number | string): Decimal {\n return new Decimal(value);\n}\n"],"mappings":"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","names":[]}
package/dist/index.d.ts CHANGED
@@ -6,6 +6,7 @@ export { AccessLevel, AuthContext, DeepPartial, IpRestrictions, MembershipPermis
6
6
  export { AccountLockedError, AuthError, ConflictError, DuplicateError, ForbiddenError, InvalidCredentialsError, MembershipError, MembershipExpiredError, MembershipNotFoundError, NotFoundError, ParsError, RateLimitError, SessionExpiredError, TenantError, TenantNotFoundError, TenantSuspendedError, TwoFactorRequiredError, UnauthorizedError, ValidationError, ValidationErrorDetail } from './errors.js';
7
7
  export { ErrorCategory, ErrorCode, ErrorCodeDefinition, ErrorCodes, getErrorCode, getErrorCodesByCategory, getStatusForCode, isRetryableError } from './error-codes.js';
8
8
  export { AxiomTransport, AxiomTransportOptions, LogtapeLogger, LogtapeTransport, LogtapeTransportOptions, SentryClient, SentryEvent, SentryTransport, SentryTransportOptions, createAxiomTransport, createLogtapeTransport, createSentryTransport } from './transports/index.js';
9
+ import 'decimal.js';
9
10
 
10
11
  /**
11
12
  * @module
package/dist/index.js CHANGED
@@ -481,40 +481,32 @@ function createRequestLogger(baseLogger, request) {
481
481
  }
482
482
 
483
483
  // src/decimal.ts
484
- var PRECISION = 20;
484
+ import DecimalJS from "decimal.js";
485
+ DecimalJS.set({
486
+ precision: 40,
487
+ rounding: DecimalJS.ROUND_HALF_UP,
488
+ toExpNeg: -9,
489
+ toExpPos: 21
490
+ });
485
491
  var Decimal = class _Decimal {
486
- value;
492
+ _value;
487
493
  constructor(value) {
488
494
  if (value instanceof _Decimal) {
489
- this.value = value.value;
490
- } else if (typeof value === "number") {
491
- this.value = this.normalizeNumber(value);
495
+ this._value = value._value;
496
+ } else if (value instanceof DecimalJS) {
497
+ this._value = value;
492
498
  } else {
493
- this.value = this.normalizeString(value);
499
+ this._value = new DecimalJS(value);
494
500
  }
495
501
  }
496
- normalizeNumber(n) {
497
- if (!isFinite(n)) {
498
- throw new Error(`Invalid number: ${n}`);
499
- }
500
- return n.toFixed(PRECISION).replace(/\.?0+$/, "") || "0";
501
- }
502
- normalizeString(s) {
503
- const trimmed = s.trim();
504
- if (!/^-?\d*\.?\d+$/.test(trimmed)) {
505
- throw new Error(`Invalid decimal string: ${s}`);
506
- }
507
- return trimmed.replace(/^(-?)0+(?=\d)/, "$1").replace(/\.?0+$/, "") || "0";
508
- }
509
502
  /**
510
503
  * Add another value to this decimal.
511
504
  * @param other - Value to add
512
505
  * @returns A new Decimal with the result
513
506
  */
514
507
  add(other) {
515
- const a = parseFloat(this.value);
516
- const b = parseFloat(other instanceof _Decimal ? other.value : String(other));
517
- return new _Decimal(a + b);
508
+ const otherValue = other instanceof _Decimal ? other._value : other;
509
+ return new _Decimal(this._value.plus(otherValue));
518
510
  }
519
511
  /**
520
512
  * Subtract a value from this decimal.
@@ -522,9 +514,8 @@ var Decimal = class _Decimal {
522
514
  * @returns A new Decimal with the result
523
515
  */
524
516
  sub(other) {
525
- const a = parseFloat(this.value);
526
- const b = parseFloat(other instanceof _Decimal ? other.value : String(other));
527
- return new _Decimal(a - b);
517
+ const otherValue = other instanceof _Decimal ? other._value : other;
518
+ return new _Decimal(this._value.minus(otherValue));
528
519
  }
529
520
  /**
530
521
  * Multiply this decimal by another value.
@@ -532,9 +523,8 @@ var Decimal = class _Decimal {
532
523
  * @returns A new Decimal with the result
533
524
  */
534
525
  mul(other) {
535
- const a = parseFloat(this.value);
536
- const b = parseFloat(other instanceof _Decimal ? other.value : String(other));
537
- return new _Decimal(a * b);
526
+ const otherValue = other instanceof _Decimal ? other._value : other;
527
+ return new _Decimal(this._value.times(otherValue));
538
528
  }
539
529
  /**
540
530
  * Divide this decimal by another value.
@@ -543,12 +533,12 @@ var Decimal = class _Decimal {
543
533
  * @throws Error if dividing by zero
544
534
  */
545
535
  div(other) {
546
- const a = parseFloat(this.value);
547
- const b = parseFloat(other instanceof _Decimal ? other.value : String(other));
548
- if (b === 0) {
536
+ const otherValue = other instanceof _Decimal ? other._value : other;
537
+ const divisor = new DecimalJS(otherValue);
538
+ if (divisor.isZero()) {
549
539
  throw new Error("Division by zero");
550
540
  }
551
- return new _Decimal(a / b);
541
+ return new _Decimal(this._value.dividedBy(divisor));
552
542
  }
553
543
  /**
554
544
  * Get the modulo (remainder) of dividing this decimal by another value.
@@ -556,9 +546,8 @@ var Decimal = class _Decimal {
556
546
  * @returns A new Decimal with the remainder
557
547
  */
558
548
  mod(other) {
559
- const a = parseFloat(this.value);
560
- const b = parseFloat(other instanceof _Decimal ? other.value : String(other));
561
- return new _Decimal(a % b);
549
+ const otherValue = other instanceof _Decimal ? other._value : other;
550
+ return new _Decimal(this._value.modulo(otherValue));
562
551
  }
563
552
  /**
564
553
  * Raise this decimal to a power.
@@ -566,8 +555,7 @@ var Decimal = class _Decimal {
566
555
  * @returns A new Decimal with the result
567
556
  */
568
557
  pow(exp) {
569
- const a = parseFloat(this.value);
570
- return new _Decimal(Math.pow(a, exp));
558
+ return new _Decimal(this._value.pow(exp));
571
559
  }
572
560
  /**
573
561
  * Calculate the square root of this decimal.
@@ -575,27 +563,24 @@ var Decimal = class _Decimal {
575
563
  * @throws Error if the value is negative
576
564
  */
577
565
  sqrt() {
578
- const a = parseFloat(this.value);
579
- if (a < 0) {
566
+ if (this._value.isNegative()) {
580
567
  throw new Error("Square root of negative number");
581
568
  }
582
- return new _Decimal(Math.sqrt(a));
569
+ return new _Decimal(this._value.sqrt());
583
570
  }
584
571
  /**
585
572
  * Get the absolute value of this decimal.
586
573
  * @returns A new Decimal with the absolute value
587
574
  */
588
575
  abs() {
589
- const a = parseFloat(this.value);
590
- return new _Decimal(Math.abs(a));
576
+ return new _Decimal(this._value.abs());
591
577
  }
592
578
  /**
593
579
  * Negate this decimal (multiply by -1).
594
580
  * @returns A new Decimal with the negated value
595
581
  */
596
582
  neg() {
597
- const a = parseFloat(this.value);
598
- return new _Decimal(-a);
583
+ return new _Decimal(this._value.negated());
599
584
  }
600
585
  /**
601
586
  * Round to the specified number of decimal places using standard rounding.
@@ -603,9 +588,7 @@ var Decimal = class _Decimal {
603
588
  * @returns A new Decimal with the rounded value
604
589
  */
605
590
  round(decimals = 0) {
606
- const a = parseFloat(this.value);
607
- const factor = Math.pow(10, decimals);
608
- return new _Decimal(Math.round(a * factor) / factor);
591
+ return new _Decimal(this._value.toDecimalPlaces(decimals, DecimalJS.ROUND_HALF_UP));
609
592
  }
610
593
  /**
611
594
  * Round down to the specified number of decimal places.
@@ -613,9 +596,7 @@ var Decimal = class _Decimal {
613
596
  * @returns A new Decimal with the floored value
614
597
  */
615
598
  floor(decimals = 0) {
616
- const a = parseFloat(this.value);
617
- const factor = Math.pow(10, decimals);
618
- return new _Decimal(Math.floor(a * factor) / factor);
599
+ return new _Decimal(this._value.toDecimalPlaces(decimals, DecimalJS.ROUND_FLOOR));
619
600
  }
620
601
  /**
621
602
  * Round up to the specified number of decimal places.
@@ -623,9 +604,7 @@ var Decimal = class _Decimal {
623
604
  * @returns A new Decimal with the ceiled value
624
605
  */
625
606
  ceil(decimals = 0) {
626
- const a = parseFloat(this.value);
627
- const factor = Math.pow(10, decimals);
628
- return new _Decimal(Math.ceil(a * factor) / factor);
607
+ return new _Decimal(this._value.toDecimalPlaces(decimals, DecimalJS.ROUND_CEIL));
629
608
  }
630
609
  /**
631
610
  * Compare this decimal to another value.
@@ -633,11 +612,8 @@ var Decimal = class _Decimal {
633
612
  * @returns -1 if less, 0 if equal, 1 if greater
634
613
  */
635
614
  cmp(other) {
636
- const a = parseFloat(this.value);
637
- const b = parseFloat(other instanceof _Decimal ? other.value : String(other));
638
- if (a < b) return -1;
639
- if (a > b) return 1;
640
- return 0;
615
+ const otherValue = other instanceof _Decimal ? other._value : other;
616
+ return this._value.comparedTo(otherValue);
641
617
  }
642
618
  /**
643
619
  * Check if this decimal equals another value.
@@ -645,7 +621,8 @@ var Decimal = class _Decimal {
645
621
  * @returns True if values are equal
646
622
  */
647
623
  eq(other) {
648
- return this.cmp(other) === 0;
624
+ const otherValue = other instanceof _Decimal ? other._value : other;
625
+ return this._value.equals(otherValue);
649
626
  }
650
627
  /**
651
628
  * Check if this decimal is greater than another value.
@@ -653,7 +630,8 @@ var Decimal = class _Decimal {
653
630
  * @returns True if this is greater
654
631
  */
655
632
  gt(other) {
656
- return this.cmp(other) === 1;
633
+ const otherValue = other instanceof _Decimal ? other._value : other;
634
+ return this._value.greaterThan(otherValue);
657
635
  }
658
636
  /**
659
637
  * Check if this decimal is greater than or equal to another value.
@@ -661,7 +639,8 @@ var Decimal = class _Decimal {
661
639
  * @returns True if this is greater or equal
662
640
  */
663
641
  gte(other) {
664
- return this.cmp(other) >= 0;
642
+ const otherValue = other instanceof _Decimal ? other._value : other;
643
+ return this._value.greaterThanOrEqualTo(otherValue);
665
644
  }
666
645
  /**
667
646
  * Check if this decimal is less than another value.
@@ -669,7 +648,8 @@ var Decimal = class _Decimal {
669
648
  * @returns True if this is less
670
649
  */
671
650
  lt(other) {
672
- return this.cmp(other) === -1;
651
+ const otherValue = other instanceof _Decimal ? other._value : other;
652
+ return this._value.lessThan(otherValue);
673
653
  }
674
654
  /**
675
655
  * Check if this decimal is less than or equal to another value.
@@ -677,42 +657,80 @@ var Decimal = class _Decimal {
677
657
  * @returns True if this is less or equal
678
658
  */
679
659
  lte(other) {
680
- return this.cmp(other) <= 0;
660
+ const otherValue = other instanceof _Decimal ? other._value : other;
661
+ return this._value.lessThanOrEqualTo(otherValue);
681
662
  }
682
663
  /**
683
664
  * Check if this decimal is exactly zero.
684
665
  * @returns True if value is zero
685
666
  */
686
667
  isZero() {
687
- return parseFloat(this.value) === 0;
668
+ return this._value.isZero();
688
669
  }
689
670
  /**
690
671
  * Check if this decimal is positive (greater than zero).
691
672
  * @returns True if value is positive
692
673
  */
693
674
  isPositive() {
694
- return parseFloat(this.value) > 0;
675
+ return this._value.isPositive() && !this._value.isZero();
695
676
  }
696
677
  /**
697
678
  * Check if this decimal is negative (less than zero).
698
679
  * @returns True if value is negative
699
680
  */
700
681
  isNegative() {
701
- return parseFloat(this.value) < 0;
682
+ return this._value.isNegative();
683
+ }
684
+ /**
685
+ * Check if this decimal is an integer (no decimal places).
686
+ * @returns True if value is an integer
687
+ */
688
+ isInteger() {
689
+ return this._value.isInteger();
690
+ }
691
+ /**
692
+ * Get the number of decimal places (digits after the decimal point).
693
+ * @returns Number of decimal places
694
+ *
695
+ * @example
696
+ * ```typescript
697
+ * new Decimal('123.45').decimalPlaces(); // 2
698
+ * new Decimal('100').decimalPlaces(); // 0
699
+ * new Decimal('1.500').decimalPlaces(); // 1 (trailing zeros removed)
700
+ * ```
701
+ */
702
+ decimalPlaces() {
703
+ return this._value.decimalPlaces();
704
+ }
705
+ /**
706
+ * Get the precision (total number of significant digits).
707
+ * @param includeZeros - If true, include trailing zeros in the count
708
+ * @returns The precision
709
+ *
710
+ * @example
711
+ * ```typescript
712
+ * new Decimal('123.45').precision(); // 5
713
+ * new Decimal('100').precision(); // 1
714
+ * new Decimal('100').precision(true); // 3
715
+ * ```
716
+ */
717
+ precision(includeZeros = false) {
718
+ return this._value.precision(includeZeros);
702
719
  }
703
720
  /**
704
721
  * Convert this decimal to a JavaScript number.
722
+ * Warning: May lose precision for very large or very precise numbers.
705
723
  * @returns The numeric value
706
724
  */
707
725
  toNumber() {
708
- return parseFloat(this.value);
726
+ return this._value.toNumber();
709
727
  }
710
728
  /**
711
729
  * Convert this decimal to its string representation.
712
730
  * @returns The string value
713
731
  */
714
732
  toString() {
715
- return this.value;
733
+ return this._value.toString();
716
734
  }
717
735
  /**
718
736
  * Format this decimal with a fixed number of decimal places.
@@ -720,14 +738,22 @@ var Decimal = class _Decimal {
720
738
  * @returns Formatted string
721
739
  */
722
740
  toFixed(decimals = 2) {
723
- return parseFloat(this.value).toFixed(decimals);
741
+ return this._value.toFixed(decimals);
724
742
  }
725
743
  /**
726
744
  * Convert to JSON (returns string representation for serialization).
727
745
  * @returns The string value for JSON serialization
728
746
  */
729
747
  toJSON() {
730
- return this.value;
748
+ return this._value.toString();
749
+ }
750
+ /**
751
+ * Get the underlying decimal.js instance.
752
+ * Useful for advanced operations not covered by this wrapper.
753
+ * @returns The underlying DecimalJS instance
754
+ */
755
+ toDecimalJS() {
756
+ return this._value;
731
757
  }
732
758
  /**
733
759
  * Create a Decimal from a value (alias for constructor).
@@ -783,6 +809,30 @@ var Decimal = class _Decimal {
783
809
  return d.gt(max) ? d : max;
784
810
  }, new _Decimal(values[0]));
785
811
  }
812
+ /**
813
+ * Check if a value is a valid decimal representation.
814
+ * @param value - The value to check
815
+ * @returns True if the value can be converted to a Decimal
816
+ */
817
+ static isValid(value) {
818
+ if (value === null || value === void 0) return false;
819
+ if (value instanceof _Decimal) return true;
820
+ try {
821
+ new DecimalJS(value);
822
+ return true;
823
+ } catch {
824
+ return false;
825
+ }
826
+ }
827
+ /**
828
+ * Create a Decimal or return null if the value is invalid.
829
+ * @param value - The value to convert
830
+ * @returns A Decimal or null
831
+ */
832
+ static tryParse(value) {
833
+ if (!_Decimal.isValid(value)) return null;
834
+ return new _Decimal(value);
835
+ }
786
836
  };
787
837
  var DecimalUtils = {
788
838
  /**
@@ -875,30 +925,62 @@ var DecimalUtils = {
875
925
  for (const field of decimalFields) {
876
926
  if (field in result && result[field] !== void 0 && result[field] !== null) {
877
927
  const value = result[field];
878
- if (typeof value === "number") {
928
+ if (typeof value === "number" || typeof value === "string") {
879
929
  result[field] = DecimalUtils.toDecimalString(value);
930
+ } else if (value instanceof Decimal) {
931
+ result[field] = value.toString();
880
932
  }
881
933
  }
882
934
  }
883
935
  return result;
884
936
  },
885
937
  /**
886
- * Parse an object from database by converting decimal string fields to JavaScript numbers.
938
+ * Parse an object from database by converting decimal string fields to Decimal instances.
887
939
  * @param data - The object from database
888
- * @param decimalFields - Array of field names that should be converted from decimal strings
889
- * @returns A new object with specified fields converted to numbers
940
+ * @param decimalFields - Array of field names that should be converted to Decimal
941
+ * @returns A new object with specified fields converted to Decimal instances
890
942
  */
891
943
  parseFromDatabase(data, decimalFields) {
892
944
  const result = { ...data };
893
945
  for (const field of decimalFields) {
894
946
  if (field in result && result[field] !== void 0 && result[field] !== null) {
895
947
  const value = result[field];
896
- if (typeof value === "string") {
897
- result[field] = DecimalUtils.fromDecimalString(value);
948
+ if (typeof value === "string" || typeof value === "number") {
949
+ result[field] = new Decimal(value);
898
950
  }
899
951
  }
900
952
  }
901
953
  return result;
954
+ },
955
+ /**
956
+ * Validate that a value matches the specified precision and scale.
957
+ * @param value - The value to validate
958
+ * @param precision - Total number of digits (integer + decimal)
959
+ * @param scale - Number of decimal places
960
+ * @returns An error message if invalid, or null if valid
961
+ *
962
+ * @example
963
+ * ```typescript
964
+ * DecimalUtils.validate('123.45', 5, 2); // null (valid)
965
+ * DecimalUtils.validate('123.456', 5, 2); // "max 2 decimal places allowed"
966
+ * DecimalUtils.validate('1234.56', 5, 2); // "max 3 integer digits allowed"
967
+ * ```
968
+ */
969
+ validate(value, precision, scale) {
970
+ const d = value instanceof Decimal ? value : new Decimal(value);
971
+ const maxIntDigits = precision - scale;
972
+ if (d.decimalPlaces() > scale) {
973
+ return `max ${scale} decimal places allowed`;
974
+ }
975
+ const absValue = d.abs();
976
+ if (!absValue.isZero()) {
977
+ const integerPart = absValue.floor(0);
978
+ const intDigits = integerPart.isZero() ? 0 : integerPart.precision(true);
979
+ if (intDigits > maxIntDigits) {
980
+ return `max ${maxIntDigits} integer digits allowed`;
981
+ }
982
+ }
983
+ return null;
902
984
  }
903
985
  };
904
986
  function decimal(value) {