soff-money 0.2.8 → 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.
package/README.md CHANGED
@@ -147,6 +147,9 @@ const [share1, share2, share3] = total.distributeByRatios([1, 2, 2]);
147
147
  // From decimal (recommended)
148
148
  Money.fromDecimal(1500.5, COP);
149
149
 
150
+ // From formatted string
151
+ Money.fromString('$ 1.500,50', ARS);
152
+
150
153
  // From cents (when you already have cents)
151
154
  Money.fromCents(150050, COP);
152
155
 
@@ -1,2 +1,2 @@
1
- 'use strict';var y=class r{constructor(e,t){if(!Number.isInteger(e))throw new Error("Money must be created with an integer number of cents");this.cents=e,this.currency=t,Object.freeze(this);}static fromCents(e,t){return new r(Math.round(e),t)}static fromDecimal(e,t){let n=Math.pow(10,t.decimals),c=Math.round(e*n);return new r(c,t)}static zero(e){return new r(0,e)}add(e){return this.assertSameCurrency(e),new r(this.cents+e.cents,this.currency)}subtract(e){return this.assertSameCurrency(e),new r(this.cents-e.cents,this.currency)}multiply(e){return new r(Math.round(this.cents*e),this.currency)}divide(e){if(e===0)throw new Error("Cannot divide by zero");return new r(Math.round(this.cents/e),this.currency)}distribute(e){if(e<=0||!Number.isInteger(e))throw new Error("Parts must be a positive integer");let t=Math.floor(this.cents/e),n=this.cents%e,c=[];for(let s=0;s<e;s++){let o=s<n?1:0;c.push(new r(t+o,this.currency));}return c}distributeByRatios(e){if(e.length===0)throw new Error("Ratios array cannot be empty");let t=e.reduce((s,o)=>s+o,0);if(t<=0)throw new Error("Sum of ratios must be positive");let n=this.cents,c=[];for(let s=0;s<e.length;s++)if(s===e.length-1)c.push(new r(n,this.currency));else {let o=Math.round(this.cents*e[s]/t);c.push(new r(o,this.currency)),n-=o;}return c}format(e={}){let{showSymbol:t=true,showDecimals:n=true,symbolPosition:c}=e,s=this.toDecimal(),o=Math.abs(s),h=s<0,i;if(n&&this.currency.decimals>0){let[a,u]=o.toFixed(this.currency.decimals).split(".");i=`${this.formatInteger(a)}${this.currency.decimalSeparator}${u}`;}else i=this.formatInteger(Math.round(o).toString());if(h&&(i=`-${i}`),t){let a=c??this.currency.symbolPosition,u=this.currency.symbolSpacing?" ":"";a==="before"?i=`${this.currency.symbol}${u}${i}`:i=`${i}${u}${this.currency.symbol}`;}return i}toDecimal(){return this.cents/Math.pow(10,this.currency.decimals)}equals(e){return this.cents===e.cents&&this.currency.code===e.currency.code}greaterThan(e){return this.assertSameCurrency(e),this.cents>e.cents}lessThan(e){return this.assertSameCurrency(e),this.cents<e.cents}greaterThanOrEqual(e){return this.assertSameCurrency(e),this.cents>=e.cents}lessThanOrEqual(e){return this.assertSameCurrency(e),this.cents<=e.cents}isZero(){return this.cents===0}isPositive(){return this.cents>0}isNegative(){return this.cents<0}abs(){return new r(Math.abs(this.cents),this.currency)}negate(){return new r(-this.cents,this.currency)}percentage(e){return new r(Math.round(this.cents*e/100),this.currency)}addPercentage(e){return this.add(this.percentage(e))}subtractPercentage(e){return this.subtract(this.percentage(e))}min(e){return this.assertSameCurrency(e),this.cents<=e.cents?this:new r(e.cents,this.currency)}max(e){return this.assertSameCurrency(e),this.cents>=e.cents?this:new r(e.cents,this.currency)}clamp(e,t){return this.max(e).min(t)}toCents(){return this.cents}isBetween(e,t){return this.assertSameCurrency(e),this.assertSameCurrency(t),this.cents>=e.cents&&this.cents<=t.cents}static sum(e){if(e.length===0)throw new Error("Cannot sum empty array");let t=e[0].currency,n=e.reduce((c,s)=>{if(s.currency.code!==t.code)throw new Error("Cannot sum different currencies");return c+s.cents},0);return new r(n,t)}static minimum(e){if(e.length===0)throw new Error("Cannot get minimum of empty array");return e.reduce((t,n)=>n.cents<t.cents?n:t)}static maximum(e){if(e.length===0)throw new Error("Cannot get maximum of empty array");return e.reduce((t,n)=>n.cents>t.cents?n:t)}static average(e){if(e.length===0)throw new Error("Cannot calculate average of empty array");return r.sum(e).divide(e.length)}toJSON(){return {cents:this.cents,currency:this.currency.code}}toString(){return this.format()}formatInteger(e){let t=[],n=e;for(;n.length>3;)t.unshift(n.slice(-3)),n=n.slice(0,-3);return n&&t.unshift(n),t.join(this.currency.thousandsSeparator)}assertSameCurrency(e){if(this.currency.code!==e.currency.code)throw new Error(`Cannot perform operation with different currencies: ${this.currency.code} and ${e.currency.code}`)}};exports.Money=y;//# sourceMappingURL=index.cjs.map
1
+ 'use strict';var y=class s{constructor(e,t){if(!Number.isInteger(e))throw new Error("Money must be created with an integer number of cents");this.cents=e,this.currency=t,Object.freeze(this);}static fromCents(e,t){return new s(Math.round(e),t)}static fromDecimal(e,t){let r=Math.pow(10,t.decimals),o=Math.round(e*r);return new s(o,t)}static fromString(e,t){let r=e.replace(t.symbol,"").trim(),o=c=>c.replace(/[.*+?^${}()|[\]\\]/g,"\\$&");if(t.thousandsSeparator){let c=new RegExp(o(t.thousandsSeparator),"g");r=r.replace(c,"");}t.decimalSeparator&&t.decimalSeparator!=="."&&(r=r.replace(t.decimalSeparator,".")),r=r.replace(/\s+/g,"");let n=parseFloat(r);if(isNaN(n))throw new Error(`Cannot parse "${e}" as money`);return s.fromDecimal(n,t)}static zero(e){return new s(0,e)}add(e){return this.assertSameCurrency(e),new s(this.cents+e.cents,this.currency)}subtract(e){return this.assertSameCurrency(e),new s(this.cents-e.cents,this.currency)}multiply(e){return new s(Math.round(this.cents*e),this.currency)}divide(e){if(e===0)throw new Error("Cannot divide by zero");return new s(Math.round(this.cents/e),this.currency)}distribute(e){if(e<=0||!Number.isInteger(e))throw new Error("Parts must be a positive integer");let t=Math.floor(this.cents/e),r=this.cents%e,o=[];for(let n=0;n<e;n++){let c=n<r?1:0;o.push(new s(t+c,this.currency));}return o}distributeByRatios(e){if(e.length===0)throw new Error("Ratios array cannot be empty");let t=e.reduce((n,c)=>n+c,0);if(t<=0)throw new Error("Sum of ratios must be positive");let r=this.cents,o=[];for(let n=0;n<e.length;n++)if(n===e.length-1)o.push(new s(r,this.currency));else {let c=Math.round(this.cents*e[n]/t);o.push(new s(c,this.currency)),r-=c;}return o}format(e={}){let{showSymbol:t=true,showDecimals:r=true,symbolPosition:o}=e,n=this.toDecimal(),c=Math.abs(n),h=n<0,i;if(r&&this.currency.decimals>0){let[u,a]=c.toFixed(this.currency.decimals).split(".");i=`${this.formatInteger(u)}${this.currency.decimalSeparator}${a}`;}else i=this.formatInteger(Math.round(c).toString());if(h&&(i=`-${i}`),t){let u=o??this.currency.symbolPosition,a=this.currency.symbolSpacing?" ":"";u==="before"?i=`${this.currency.symbol}${a}${i}`:i=`${i}${a}${this.currency.symbol}`;}return i}toDecimal(){return this.cents/Math.pow(10,this.currency.decimals)}equals(e){return this.cents===e.cents&&this.currency.code===e.currency.code}greaterThan(e){return this.assertSameCurrency(e),this.cents>e.cents}lessThan(e){return this.assertSameCurrency(e),this.cents<e.cents}greaterThanOrEqual(e){return this.assertSameCurrency(e),this.cents>=e.cents}lessThanOrEqual(e){return this.assertSameCurrency(e),this.cents<=e.cents}isZero(){return this.cents===0}isPositive(){return this.cents>0}isNegative(){return this.cents<0}abs(){return new s(Math.abs(this.cents),this.currency)}negate(){return new s(-this.cents,this.currency)}percentage(e){return new s(Math.round(this.cents*e/100),this.currency)}addPercentage(e){return this.add(this.percentage(e))}subtractPercentage(e){return this.subtract(this.percentage(e))}min(e){return this.assertSameCurrency(e),this.cents<=e.cents?this:new s(e.cents,this.currency)}max(e){return this.assertSameCurrency(e),this.cents>=e.cents?this:new s(e.cents,this.currency)}clamp(e,t){return this.max(e).min(t)}toCents(){return this.cents}isBetween(e,t){return this.assertSameCurrency(e),this.assertSameCurrency(t),this.cents>=e.cents&&this.cents<=t.cents}static sum(e){if(e.length===0)throw new Error("Cannot sum empty array");let t=e[0].currency,r=e.reduce((o,n)=>{if(n.currency.code!==t.code)throw new Error("Cannot sum different currencies");return o+n.cents},0);return new s(r,t)}static minimum(e){if(e.length===0)throw new Error("Cannot get minimum of empty array");return e.reduce((t,r)=>r.cents<t.cents?r:t)}static maximum(e){if(e.length===0)throw new Error("Cannot get maximum of empty array");return e.reduce((t,r)=>r.cents>t.cents?r:t)}static average(e){if(e.length===0)throw new Error("Cannot calculate average of empty array");return s.sum(e).divide(e.length)}toJSON(){return {cents:this.cents,currency:this.currency.code}}toString(){return this.format()}formatInteger(e){let t=[],r=e;for(;r.length>3;)t.unshift(r.slice(-3)),r=r.slice(0,-3);return r&&t.unshift(r),t.join(this.currency.thousandsSeparator)}assertSameCurrency(e){if(this.currency.code!==e.currency.code)throw new Error(`Cannot perform operation with different currencies: ${this.currency.code} and ${e.currency.code}`)}};exports.Money=y;//# sourceMappingURL=index.cjs.map
2
2
  //# sourceMappingURL=index.cjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/core/money.ts"],"names":["Money","_Money","cents","currency","amount","multiplier","other","factor","divisor","parts","quotient","remainder","result","i","extra","ratios","total","sum","r","remaining","share","options","showSymbol","showDecimals","symbolPosition","decimal","absValue","isNegative","formatted","intPart","decPart","pos","space","percent","minValue","maxValue","min","max","values","m","intStr"],"mappings":"aAKO,IAAMA,CAAAA,CAAN,MAAMC,CAAwB,CAI3B,YAAYC,CAAAA,CAAeC,CAAAA,CAAoB,CACrD,GAAI,CAAC,MAAA,CAAO,UAAUD,CAAK,CAAA,CACzB,MAAM,IAAI,KAAA,CAAM,uDAAuD,EAEzE,IAAA,CAAK,KAAA,CAAQA,CAAAA,CACb,IAAA,CAAK,QAAA,CAAWC,CAAAA,CAChB,OAAO,MAAA,CAAO,IAAI,EACpB,CAKA,OAAO,UAAUD,CAAAA,CAAeC,CAAAA,CAA2B,CACzD,OAAO,IAAIF,CAAAA,CAAM,KAAK,KAAA,CAAMC,CAAK,CAAA,CAAGC,CAAQ,CAC9C,CAMA,OAAO,WAAA,CAAYC,CAAAA,CAAgBD,CAAAA,CAA2B,CAC5D,IAAME,CAAAA,CAAa,KAAK,GAAA,CAAI,EAAA,CAAIF,EAAS,QAAQ,CAAA,CAC3CD,EAAQ,IAAA,CAAK,KAAA,CAAME,CAAAA,CAASC,CAAU,CAAA,CAC5C,OAAO,IAAIJ,CAAAA,CAAMC,CAAAA,CAAOC,CAAQ,CAClC,CAKA,OAAO,KAAKA,CAAAA,CAA2B,CACrC,OAAO,IAAIF,CAAAA,CAAM,CAAA,CAAGE,CAAQ,CAC9B,CAKA,GAAA,CAAIG,CAAAA,CAAsB,CACxB,OAAA,IAAA,CAAK,mBAAmBA,CAAK,CAAA,CACtB,IAAIL,CAAAA,CAAM,IAAA,CAAK,KAAA,CAAQK,EAAM,KAAA,CAAO,IAAA,CAAK,QAAQ,CAC1D,CAKA,QAAA,CAASA,EAAsB,CAC7B,OAAA,IAAA,CAAK,kBAAA,CAAmBA,CAAK,CAAA,CACtB,IAAIL,EAAM,IAAA,CAAK,KAAA,CAAQK,EAAM,KAAA,CAAO,IAAA,CAAK,QAAQ,CAC1D,CAKA,QAAA,CAASC,CAAAA,CAAuB,CAC9B,OAAO,IAAIN,CAAAA,CAAM,IAAA,CAAK,KAAA,CAAM,IAAA,CAAK,KAAA,CAAQM,CAAM,EAAG,IAAA,CAAK,QAAQ,CACjE,CAKA,MAAA,CAAOC,CAAAA,CAAwB,CAC7B,GAAIA,CAAAA,GAAY,CAAA,CACd,MAAM,IAAI,KAAA,CAAM,uBAAuB,CAAA,CAEzC,OAAO,IAAIP,CAAAA,CAAM,IAAA,CAAK,KAAA,CAAM,KAAK,KAAA,CAAQO,CAAO,CAAA,CAAG,IAAA,CAAK,QAAQ,CAClE,CAOA,UAAA,CAAWC,CAAAA,CAAwB,CACjC,GAAIA,CAAAA,EAAS,CAAA,EAAK,CAAC,MAAA,CAAO,SAAA,CAAUA,CAAK,CAAA,CACvC,MAAM,IAAI,KAAA,CAAM,kCAAkC,CAAA,CAGpD,IAAMC,CAAAA,CAAW,IAAA,CAAK,MAAM,IAAA,CAAK,KAAA,CAAQD,CAAK,CAAA,CACxCE,CAAAA,CAAY,IAAA,CAAK,MAAQF,CAAAA,CAEzBG,CAAAA,CAAkB,EAAC,CACzB,IAAA,IAASC,CAAAA,CAAI,EAAGA,CAAAA,CAAIJ,CAAAA,CAAOI,CAAAA,EAAAA,CAAK,CAE9B,IAAMC,CAAAA,CAAQD,EAAIF,CAAAA,CAAY,CAAA,CAAI,CAAA,CAClCC,CAAAA,CAAO,IAAA,CAAK,IAAIX,EAAMS,CAAAA,CAAWI,CAAAA,CAAO,IAAA,CAAK,QAAQ,CAAC,EACxD,CAEA,OAAOF,CACT,CAMA,kBAAA,CAAmBG,CAAAA,CAA2B,CAC5C,GAAIA,CAAAA,CAAO,MAAA,GAAW,EACpB,MAAM,IAAI,MAAM,8BAA8B,CAAA,CAGhD,IAAMC,CAAAA,CAAQD,CAAAA,CAAO,MAAA,CAAO,CAACE,CAAAA,CAAKC,CAAAA,GAAMD,CAAAA,CAAMC,CAAAA,CAAG,CAAC,CAAA,CAClD,GAAIF,CAAAA,EAAS,CAAA,CACX,MAAM,IAAI,KAAA,CAAM,gCAAgC,EAGlD,IAAIG,CAAAA,CAAY,IAAA,CAAK,KAAA,CACfP,CAAAA,CAAkB,GAExB,IAAA,IAASC,CAAAA,CAAI,CAAA,CAAGA,CAAAA,CAAIE,CAAAA,CAAO,MAAA,CAAQF,IACjC,GAAIA,CAAAA,GAAME,CAAAA,CAAO,MAAA,CAAS,CAAA,CAExBH,CAAAA,CAAO,KAAK,IAAIX,CAAAA,CAAMkB,CAAAA,CAAW,IAAA,CAAK,QAAQ,CAAC,OAC1C,CACL,IAAMC,EAAQ,IAAA,CAAK,KAAA,CAAO,KAAK,KAAA,CAAQL,CAAAA,CAAOF,CAAC,CAAA,CAAKG,CAAK,CAAA,CACzDJ,EAAO,IAAA,CAAK,IAAIX,CAAAA,CAAMmB,CAAAA,CAAO,IAAA,CAAK,QAAQ,CAAC,CAAA,CAC3CD,CAAAA,EAAaC,EACf,CAGF,OAAOR,CACT,CAKA,MAAA,CAAOS,CAAAA,CAAyB,EAAC,CAAW,CAC1C,GAAM,CAAE,UAAA,CAAAC,CAAAA,CAAa,IAAA,CAAM,YAAA,CAAAC,CAAAA,CAAe,IAAA,CAAM,eAAAC,CAAe,CAAA,CAAIH,CAAAA,CAE7DI,CAAAA,CAAU,IAAA,CAAK,SAAA,GACfC,CAAAA,CAAW,IAAA,CAAK,GAAA,CAAID,CAAO,CAAA,CAC3BE,CAAAA,CAAaF,EAAU,CAAA,CAGzBG,CAAAA,CACJ,GAAIL,CAAAA,EAAgB,IAAA,CAAK,SAAS,QAAA,CAAW,CAAA,CAAG,CAC9C,GAAM,CAACM,CAAAA,CAASC,CAAO,CAAA,CAAIJ,CAAAA,CAAS,OAAA,CAAQ,IAAA,CAAK,QAAA,CAAS,QAAQ,EAAE,KAAA,CAAM,GAAG,CAAA,CAE7EE,CAAAA,CAAY,CAAA,EADS,IAAA,CAAK,cAAcC,CAAO,CACpB,CAAA,EAAG,IAAA,CAAK,QAAA,CAAS,gBAAgB,GAAGC,CAAO,CAAA,EACxE,CAAA,KACEF,CAAAA,CAAY,IAAA,CAAK,aAAA,CAAc,KAAK,KAAA,CAAMF,CAAQ,CAAA,CAAE,QAAA,EAAU,CAAA,CAShE,GALIC,CAAAA,GACFC,CAAAA,CAAY,CAAA,CAAA,EAAIA,CAAS,CAAA,CAAA,CAAA,CAIvBN,CAAAA,CAAY,CACd,IAAMS,CAAAA,CAAMP,GAAkB,IAAA,CAAK,QAAA,CAAS,eACtCQ,CAAAA,CAAQ,IAAA,CAAK,QAAA,CAAS,aAAA,CAAgB,GAAA,CAAM,EAAA,CAE9CD,IAAQ,QAAA,CACVH,CAAAA,CAAY,CAAA,EAAG,IAAA,CAAK,QAAA,CAAS,MAAM,GAAGI,CAAK,CAAA,EAAGJ,CAAS,CAAA,CAAA,CAEvDA,CAAAA,CAAY,CAAA,EAAGA,CAAS,CAAA,EAAGI,CAAK,CAAA,EAAG,IAAA,CAAK,QAAA,CAAS,MAAM,GAE3D,CAEA,OAAOJ,CACT,CAKA,SAAA,EAAoB,CAClB,OAAO,IAAA,CAAK,KAAA,CAAQ,IAAA,CAAK,GAAA,CAAI,EAAA,CAAI,IAAA,CAAK,SAAS,QAAQ,CACzD,CAKA,MAAA,CAAOtB,CAAAA,CAAwB,CAC7B,OAAO,IAAA,CAAK,KAAA,GAAUA,EAAM,KAAA,EAAS,IAAA,CAAK,SAAS,IAAA,GAASA,CAAAA,CAAM,QAAA,CAAS,IAC7E,CAKA,WAAA,CAAYA,EAAwB,CAClC,OAAA,IAAA,CAAK,kBAAA,CAAmBA,CAAK,CAAA,CACtB,IAAA,CAAK,MAAQA,CAAAA,CAAM,KAC5B,CAKA,QAAA,CAASA,CAAAA,CAAwB,CAC/B,YAAK,kBAAA,CAAmBA,CAAK,CAAA,CACtB,IAAA,CAAK,KAAA,CAAQA,CAAAA,CAAM,KAC5B,CAKA,kBAAA,CAAmBA,CAAAA,CAAwB,CACzC,OAAA,IAAA,CAAK,kBAAA,CAAmBA,CAAK,CAAA,CACtB,IAAA,CAAK,KAAA,EAASA,CAAAA,CAAM,KAC7B,CAKA,gBAAgBA,CAAAA,CAAwB,CACtC,OAAA,IAAA,CAAK,kBAAA,CAAmBA,CAAK,CAAA,CACtB,KAAK,KAAA,EAASA,CAAAA,CAAM,KAC7B,CAKA,MAAA,EAAkB,CAChB,OAAO,IAAA,CAAK,KAAA,GAAU,CACxB,CAKA,UAAA,EAAsB,CACpB,OAAO,IAAA,CAAK,KAAA,CAAQ,CACtB,CAKA,UAAA,EAAsB,CACpB,OAAO,IAAA,CAAK,KAAA,CAAQ,CACtB,CAKA,GAAA,EAAa,CACX,OAAO,IAAIL,CAAAA,CAAM,IAAA,CAAK,GAAA,CAAI,IAAA,CAAK,KAAK,CAAA,CAAG,IAAA,CAAK,QAAQ,CACtD,CAKA,MAAA,EAAgB,CACd,OAAO,IAAIA,CAAAA,CAAM,CAAC,IAAA,CAAK,KAAA,CAAO,KAAK,QAAQ,CAC7C,CAMA,UAAA,CAAWgC,CAAAA,CAAwB,CACjC,OAAO,IAAIhC,CAAAA,CAAM,KAAK,KAAA,CAAO,IAAA,CAAK,MAAQgC,CAAAA,CAAW,GAAG,CAAA,CAAG,IAAA,CAAK,QAAQ,CAC1E,CAMA,aAAA,CAAcA,CAAAA,CAAwB,CACpC,OAAO,IAAA,CAAK,GAAA,CAAI,KAAK,UAAA,CAAWA,CAAO,CAAC,CAC1C,CAMA,kBAAA,CAAmBA,EAAwB,CACzC,OAAO,IAAA,CAAK,QAAA,CAAS,IAAA,CAAK,UAAA,CAAWA,CAAO,CAAC,CAC/C,CAKA,GAAA,CAAI3B,CAAAA,CAAsB,CACxB,YAAK,kBAAA,CAAmBA,CAAK,CAAA,CACtB,IAAA,CAAK,KAAA,EAASA,CAAAA,CAAM,MAAQ,IAAA,CAAO,IAAIL,CAAAA,CAAMK,CAAAA,CAAM,KAAA,CAAO,IAAA,CAAK,QAAQ,CAChF,CAKA,IAAIA,CAAAA,CAAsB,CACxB,YAAK,kBAAA,CAAmBA,CAAK,CAAA,CACtB,IAAA,CAAK,KAAA,EAASA,CAAAA,CAAM,MAAQ,IAAA,CAAO,IAAIL,CAAAA,CAAMK,CAAAA,CAAM,KAAA,CAAO,IAAA,CAAK,QAAQ,CAChF,CAKA,KAAA,CAAM4B,CAAAA,CAAkBC,CAAAA,CAAyB,CAC/C,OAAO,IAAA,CAAK,GAAA,CAAID,CAAQ,CAAA,CAAE,GAAA,CAAIC,CAAQ,CACxC,CAKA,OAAA,EAAkB,CAChB,OAAO,IAAA,CAAK,KACd,CAKA,SAAA,CAAUC,CAAAA,CAAaC,CAAAA,CAAsB,CAC3C,OAAA,IAAA,CAAK,kBAAA,CAAmBD,CAAG,CAAA,CAC3B,IAAA,CAAK,kBAAA,CAAmBC,CAAG,CAAA,CACpB,IAAA,CAAK,OAASD,CAAAA,CAAI,KAAA,EAAS,KAAK,KAAA,EAASC,CAAAA,CAAI,KACtD,CAKA,OAAO,GAAA,CAAIC,CAAAA,CAAyB,CAClC,GAAIA,EAAO,MAAA,GAAW,CAAA,CACpB,MAAM,IAAI,KAAA,CAAM,wBAAwB,EAE1C,IAAMnC,CAAAA,CAAWmC,CAAAA,CAAO,CAAC,CAAA,CAAE,QAAA,CACrBtB,EAAQsB,CAAAA,CAAO,MAAA,CAAO,CAACrB,CAAAA,CAAKsB,CAAAA,GAAM,CACtC,GAAIA,CAAAA,CAAE,QAAA,CAAS,IAAA,GAASpC,CAAAA,CAAS,IAAA,CAC/B,MAAM,IAAI,KAAA,CAAM,iCAAiC,CAAA,CAEnD,OAAOc,CAAAA,CAAMsB,CAAAA,CAAE,KACjB,CAAA,CAAG,CAAC,CAAA,CACJ,OAAO,IAAItC,CAAAA,CAAMe,EAAOb,CAAQ,CAClC,CAKA,OAAO,OAAA,CAAQmC,EAAyB,CACtC,GAAIA,CAAAA,CAAO,MAAA,GAAW,CAAA,CACpB,MAAM,IAAI,KAAA,CAAM,mCAAmC,CAAA,CAErD,OAAOA,CAAAA,CAAO,MAAA,CAAO,CAACF,CAAAA,CAAKG,CAAAA,GAAOA,CAAAA,CAAE,KAAA,CAAQH,CAAAA,CAAI,KAAA,CAAQG,EAAIH,CAAI,CAClE,CAKA,OAAO,OAAA,CAAQE,CAAAA,CAAyB,CACtC,GAAIA,CAAAA,CAAO,MAAA,GAAW,CAAA,CACpB,MAAM,IAAI,MAAM,mCAAmC,CAAA,CAErD,OAAOA,CAAAA,CAAO,MAAA,CAAO,CAACD,EAAKE,CAAAA,GAAOA,CAAAA,CAAE,KAAA,CAAQF,CAAAA,CAAI,KAAA,CAAQE,CAAAA,CAAIF,CAAI,CAClE,CAKA,OAAO,OAAA,CAAQC,CAAAA,CAAyB,CACtC,GAAIA,CAAAA,CAAO,MAAA,GAAW,CAAA,CACpB,MAAM,IAAI,MAAM,yCAAyC,CAAA,CAG3D,OADcrC,CAAAA,CAAM,GAAA,CAAIqC,CAAM,EACjB,MAAA,CAAOA,CAAAA,CAAO,MAAM,CACnC,CAKA,MAAA,EAA8C,CAC5C,OAAO,CACL,KAAA,CAAO,IAAA,CAAK,KAAA,CACZ,QAAA,CAAU,KAAK,QAAA,CAAS,IAC1B,CACF,CAKA,QAAA,EAAmB,CACjB,OAAO,IAAA,CAAK,MAAA,EACd,CAEQ,aAAA,CAAcE,CAAAA,CAAwB,CAC5C,IAAM/B,CAAAA,CAAkB,EAAC,CACrBU,CAAAA,CAAYqB,CAAAA,CAEhB,KAAOrB,CAAAA,CAAU,MAAA,CAAS,GACxBV,CAAAA,CAAM,OAAA,CAAQU,EAAU,KAAA,CAAM,EAAE,CAAC,CAAA,CACjCA,CAAAA,CAAYA,CAAAA,CAAU,MAAM,CAAA,CAAG,EAAE,CAAA,CAGnC,OAAIA,CAAAA,EACFV,CAAAA,CAAM,QAAQU,CAAS,CAAA,CAGlBV,CAAAA,CAAM,IAAA,CAAK,IAAA,CAAK,QAAA,CAAS,kBAAkB,CACpD,CAEQ,kBAAA,CAAmBH,CAAAA,CAAqB,CAC9C,GAAI,KAAK,QAAA,CAAS,IAAA,GAASA,CAAAA,CAAM,QAAA,CAAS,IAAA,CACxC,MAAM,IAAI,KAAA,CACR,CAAA,oDAAA,EAAuD,IAAA,CAAK,QAAA,CAAS,IAAI,CAAA,KAAA,EAAQA,EAAM,QAAA,CAAS,IAAI,CAAA,CACtG,CAEJ,CACF","file":"index.cjs","sourcesContent":["import type { Currency, FormatOptions, IMoney } from './types.js';\n\n/**\n * Immutable Money class that uses integer arithmetic for precision\n */\nexport class Money implements IMoney {\n readonly cents: number;\n readonly currency: Currency;\n\n private constructor(cents: number, currency: Currency) {\n if (!Number.isInteger(cents)) {\n throw new Error('Money must be created with an integer number of cents');\n }\n this.cents = cents;\n this.currency = currency;\n Object.freeze(this);\n }\n\n /**\n * Create money from cents (smallest unit)\n */\n static fromCents(cents: number, currency: Currency): Money {\n return new Money(Math.round(cents), currency);\n }\n\n /**\n * Create money from a decimal amount\n * @example Money.fromDecimal(100.50, USD) creates $100.50\n */\n static fromDecimal(amount: number, currency: Currency): Money {\n const multiplier = Math.pow(10, currency.decimals);\n const cents = Math.round(amount * multiplier);\n return new Money(cents, currency);\n }\n\n /**\n * Create zero money\n */\n static zero(currency: Currency): Money {\n return new Money(0, currency);\n }\n\n /**\n * Add another money value (must be same currency)\n */\n add(other: IMoney): Money {\n this.assertSameCurrency(other);\n return new Money(this.cents + other.cents, this.currency);\n }\n\n /**\n * Subtract another money value (must be same currency)\n */\n subtract(other: IMoney): Money {\n this.assertSameCurrency(other);\n return new Money(this.cents - other.cents, this.currency);\n }\n\n /**\n * Multiply by a factor (rounds to nearest cent)\n */\n multiply(factor: number): Money {\n return new Money(Math.round(this.cents * factor), this.currency);\n }\n\n /**\n * Divide by a divisor (rounds to nearest cent)\n */\n divide(divisor: number): Money {\n if (divisor === 0) {\n throw new Error('Cannot divide by zero');\n }\n return new Money(Math.round(this.cents / divisor), this.currency);\n }\n\n /**\n * Distribute money evenly without losing cents\n * The remainder is distributed to the first parts\n * @example $100 / 3 = [$33.34, $33.33, $33.33]\n */\n distribute(parts: number): Money[] {\n if (parts <= 0 || !Number.isInteger(parts)) {\n throw new Error('Parts must be a positive integer');\n }\n\n const quotient = Math.floor(this.cents / parts);\n const remainder = this.cents % parts;\n\n const result: Money[] = [];\n for (let i = 0; i < parts; i++) {\n // Add 1 cent to the first 'remainder' parts\n const extra = i < remainder ? 1 : 0;\n result.push(new Money(quotient + extra, this.currency));\n }\n\n return result;\n }\n\n /**\n * Distribute money according to ratios\n * @example $100 with ratios [1, 2, 2] = [$20, $40, $40]\n */\n distributeByRatios(ratios: number[]): Money[] {\n if (ratios.length === 0) {\n throw new Error('Ratios array cannot be empty');\n }\n\n const total = ratios.reduce((sum, r) => sum + r, 0);\n if (total <= 0) {\n throw new Error('Sum of ratios must be positive');\n }\n\n let remaining = this.cents;\n const result: Money[] = [];\n\n for (let i = 0; i < ratios.length; i++) {\n if (i === ratios.length - 1) {\n // Last part gets whatever is remaining to avoid rounding errors\n result.push(new Money(remaining, this.currency));\n } else {\n const share = Math.round((this.cents * ratios[i]) / total);\n result.push(new Money(share, this.currency));\n remaining -= share;\n }\n }\n\n return result;\n }\n\n /**\n * Format money for display\n */\n format(options: FormatOptions = {}): string {\n const { showSymbol = true, showDecimals = true, symbolPosition } = options;\n\n const decimal = this.toDecimal();\n const absValue = Math.abs(decimal);\n const isNegative = decimal < 0;\n\n // Format the number\n let formatted: string;\n if (showDecimals && this.currency.decimals > 0) {\n const [intPart, decPart] = absValue.toFixed(this.currency.decimals).split('.');\n const intFormatted = this.formatInteger(intPart);\n formatted = `${intFormatted}${this.currency.decimalSeparator}${decPart}`;\n } else {\n formatted = this.formatInteger(Math.round(absValue).toString());\n }\n\n // Add negative sign\n if (isNegative) {\n formatted = `-${formatted}`;\n }\n\n // Add symbol\n if (showSymbol) {\n const pos = symbolPosition ?? this.currency.symbolPosition;\n const space = this.currency.symbolSpacing ? ' ' : '';\n\n if (pos === 'before') {\n formatted = `${this.currency.symbol}${space}${formatted}`;\n } else {\n formatted = `${formatted}${space}${this.currency.symbol}`;\n }\n }\n\n return formatted;\n }\n\n /**\n * Get the decimal representation\n */\n toDecimal(): number {\n return this.cents / Math.pow(10, this.currency.decimals);\n }\n\n /**\n * Check equality with another money value\n */\n equals(other: IMoney): boolean {\n return this.cents === other.cents && this.currency.code === other.currency.code;\n }\n\n /**\n * Check if greater than another money value\n */\n greaterThan(other: IMoney): boolean {\n this.assertSameCurrency(other);\n return this.cents > other.cents;\n }\n\n /**\n * Check if less than another money value\n */\n lessThan(other: IMoney): boolean {\n this.assertSameCurrency(other);\n return this.cents < other.cents;\n }\n\n /**\n * Check if greater than or equal\n */\n greaterThanOrEqual(other: IMoney): boolean {\n this.assertSameCurrency(other);\n return this.cents >= other.cents;\n }\n\n /**\n * Check if less than or equal\n */\n lessThanOrEqual(other: IMoney): boolean {\n this.assertSameCurrency(other);\n return this.cents <= other.cents;\n }\n\n /**\n * Check if zero\n */\n isZero(): boolean {\n return this.cents === 0;\n }\n\n /**\n * Check if positive\n */\n isPositive(): boolean {\n return this.cents > 0;\n }\n\n /**\n * Check if negative\n */\n isNegative(): boolean {\n return this.cents < 0;\n }\n\n /**\n * Get absolute value\n */\n abs(): Money {\n return new Money(Math.abs(this.cents), this.currency);\n }\n\n /**\n * Negate the value\n */\n negate(): Money {\n return new Money(-this.cents, this.currency);\n }\n\n /**\n * Calculate a percentage of this money\n * @example money.percentage(10) returns 10% of the amount\n */\n percentage(percent: number): Money {\n return new Money(Math.round((this.cents * percent) / 100), this.currency);\n }\n\n /**\n * Add a percentage to this money\n * @example money.addPercentage(19) adds 19% (like tax)\n */\n addPercentage(percent: number): Money {\n return this.add(this.percentage(percent));\n }\n\n /**\n * Subtract a percentage from this money\n * @example money.subtractPercentage(10) subtracts 10% (like discount)\n */\n subtractPercentage(percent: number): Money {\n return this.subtract(this.percentage(percent));\n }\n\n /**\n * Get the minimum of this and another money value\n */\n min(other: IMoney): Money {\n this.assertSameCurrency(other);\n return this.cents <= other.cents ? this : new Money(other.cents, this.currency);\n }\n\n /**\n * Get the maximum of this and another money value\n */\n max(other: IMoney): Money {\n this.assertSameCurrency(other);\n return this.cents >= other.cents ? this : new Money(other.cents, this.currency);\n }\n\n /**\n * Clamp this money between a minimum and maximum\n */\n clamp(minValue: IMoney, maxValue: IMoney): Money {\n return this.max(minValue).min(maxValue);\n }\n\n /**\n * Get cents (smallest unit)\n */\n toCents(): number {\n return this.cents;\n }\n\n /**\n * Check if within a range (inclusive)\n */\n isBetween(min: IMoney, max: IMoney): boolean {\n this.assertSameCurrency(min);\n this.assertSameCurrency(max);\n return this.cents >= min.cents && this.cents <= max.cents;\n }\n\n /**\n * Sum multiple money values\n */\n static sum(values: IMoney[]): Money {\n if (values.length === 0) {\n throw new Error('Cannot sum empty array');\n }\n const currency = values[0].currency;\n const total = values.reduce((sum, m) => {\n if (m.currency.code !== currency.code) {\n throw new Error('Cannot sum different currencies');\n }\n return sum + m.cents;\n }, 0);\n return new Money(total, currency);\n }\n\n /**\n * Get the minimum from an array of money values\n */\n static minimum(values: IMoney[]): Money {\n if (values.length === 0) {\n throw new Error('Cannot get minimum of empty array');\n }\n return values.reduce((min, m) => (m.cents < min.cents ? m : min)) as Money;\n }\n\n /**\n * Get the maximum from an array of money values\n */\n static maximum(values: IMoney[]): Money {\n if (values.length === 0) {\n throw new Error('Cannot get maximum of empty array');\n }\n return values.reduce((max, m) => (m.cents > max.cents ? m : max)) as Money;\n }\n\n /**\n * Calculate the average of money values\n */\n static average(values: IMoney[]): Money {\n if (values.length === 0) {\n throw new Error('Cannot calculate average of empty array');\n }\n const total = Money.sum(values);\n return total.divide(values.length);\n }\n\n /**\n * Convert to JSON-serializable object\n */\n toJSON(): { cents: number; currency: string } {\n return {\n cents: this.cents,\n currency: this.currency.code,\n };\n }\n\n /**\n * String representation\n */\n toString(): string {\n return this.format();\n }\n\n private formatInteger(intStr: string): string {\n const parts: string[] = [];\n let remaining = intStr;\n\n while (remaining.length > 3) {\n parts.unshift(remaining.slice(-3));\n remaining = remaining.slice(0, -3);\n }\n\n if (remaining) {\n parts.unshift(remaining);\n }\n\n return parts.join(this.currency.thousandsSeparator);\n }\n\n private assertSameCurrency(other: IMoney): void {\n if (this.currency.code !== other.currency.code) {\n throw new Error(\n `Cannot perform operation with different currencies: ${this.currency.code} and ${other.currency.code}`\n );\n }\n }\n}\n"]}
1
+ {"version":3,"sources":["../../src/core/money.ts"],"names":["Money","_Money","cents","currency","amount","multiplier","value","cleanValue","escapeRegex","str","thousandsRegex","decimalAmount","other","factor","divisor","parts","quotient","remainder","result","i","extra","ratios","total","sum","r","remaining","share","options","showSymbol","showDecimals","symbolPosition","decimal","absValue","isNegative","formatted","intPart","decPart","pos","space","percent","minValue","maxValue","min","max","values","m","intStr"],"mappings":"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","file":"index.cjs","sourcesContent":["import type { Currency, FormatOptions, IMoney } from './types.js';\n\n/**\n * Immutable Money class that uses integer arithmetic for precision\n */\nexport class Money implements IMoney {\n readonly cents: number;\n readonly currency: Currency;\n\n private constructor(cents: number, currency: Currency) {\n if (!Number.isInteger(cents)) {\n throw new Error('Money must be created with an integer number of cents');\n }\n this.cents = cents;\n this.currency = currency;\n Object.freeze(this);\n }\n\n /**\n * Create money from cents (smallest unit)\n */\n static fromCents(cents: number, currency: Currency): Money {\n return new Money(Math.round(cents), currency);\n }\n\n /**\n * Create money from a decimal amount\n * @example Money.fromDecimal(100.50, USD) creates $100.50\n */\n static fromDecimal(amount: number, currency: Currency): Money {\n const multiplier = Math.pow(10, currency.decimals);\n const cents = Math.round(amount * multiplier);\n return new Money(cents, currency);\n }\n\n /**\n * Create money from a formatted string\n * @example Money.fromString(\"$ 1.500,50\", ARS) creates $1,500.50\n */\n static fromString(value: string, currency: Currency): Money {\n let cleanValue = value.replace(currency.symbol, '').trim();\n\n const escapeRegex = (str: string) => str.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n\n if (currency.thousandsSeparator) {\n const thousandsRegex = new RegExp(escapeRegex(currency.thousandsSeparator), 'g');\n cleanValue = cleanValue.replace(thousandsRegex, '');\n }\n\n if (currency.decimalSeparator && currency.decimalSeparator !== '.') {\n cleanValue = cleanValue.replace(currency.decimalSeparator, '.');\n }\n\n cleanValue = cleanValue.replace(/\\s+/g, '');\n\n const decimalAmount = parseFloat(cleanValue);\n\n if (isNaN(decimalAmount)) {\n throw new Error(`Cannot parse \"${value}\" as money`);\n }\n\n return Money.fromDecimal(decimalAmount, currency);\n }\n\n /**\n * Create zero money\n */\n static zero(currency: Currency): Money {\n return new Money(0, currency);\n }\n\n /**\n * Add another money value (must be same currency)\n */\n add(other: IMoney): Money {\n this.assertSameCurrency(other);\n return new Money(this.cents + other.cents, this.currency);\n }\n\n /**\n * Subtract another money value (must be same currency)\n */\n subtract(other: IMoney): Money {\n this.assertSameCurrency(other);\n return new Money(this.cents - other.cents, this.currency);\n }\n\n /**\n * Multiply by a factor (rounds to nearest cent)\n */\n multiply(factor: number): Money {\n return new Money(Math.round(this.cents * factor), this.currency);\n }\n\n /**\n * Divide by a divisor (rounds to nearest cent)\n */\n divide(divisor: number): Money {\n if (divisor === 0) {\n throw new Error('Cannot divide by zero');\n }\n return new Money(Math.round(this.cents / divisor), this.currency);\n }\n\n /**\n * Distribute money evenly without losing cents\n * The remainder is distributed to the first parts\n * @example $100 / 3 = [$33.34, $33.33, $33.33]\n */\n distribute(parts: number): Money[] {\n if (parts <= 0 || !Number.isInteger(parts)) {\n throw new Error('Parts must be a positive integer');\n }\n\n const quotient = Math.floor(this.cents / parts);\n const remainder = this.cents % parts;\n\n const result: Money[] = [];\n for (let i = 0; i < parts; i++) {\n // Add 1 cent to the first 'remainder' parts\n const extra = i < remainder ? 1 : 0;\n result.push(new Money(quotient + extra, this.currency));\n }\n\n return result;\n }\n\n /**\n * Distribute money according to ratios\n * @example $100 with ratios [1, 2, 2] = [$20, $40, $40]\n */\n distributeByRatios(ratios: number[]): Money[] {\n if (ratios.length === 0) {\n throw new Error('Ratios array cannot be empty');\n }\n\n const total = ratios.reduce((sum, r) => sum + r, 0);\n if (total <= 0) {\n throw new Error('Sum of ratios must be positive');\n }\n\n let remaining = this.cents;\n const result: Money[] = [];\n\n for (let i = 0; i < ratios.length; i++) {\n if (i === ratios.length - 1) {\n // Last part gets whatever is remaining to avoid rounding errors\n result.push(new Money(remaining, this.currency));\n } else {\n const share = Math.round((this.cents * ratios[i]) / total);\n result.push(new Money(share, this.currency));\n remaining -= share;\n }\n }\n\n return result;\n }\n\n /**\n * Format money for display\n */\n format(options: FormatOptions = {}): string {\n const { showSymbol = true, showDecimals = true, symbolPosition } = options;\n\n const decimal = this.toDecimal();\n const absValue = Math.abs(decimal);\n const isNegative = decimal < 0;\n\n // Format the number\n let formatted: string;\n if (showDecimals && this.currency.decimals > 0) {\n const [intPart, decPart] = absValue.toFixed(this.currency.decimals).split('.');\n const intFormatted = this.formatInteger(intPart);\n formatted = `${intFormatted}${this.currency.decimalSeparator}${decPart}`;\n } else {\n formatted = this.formatInteger(Math.round(absValue).toString());\n }\n\n // Add negative sign\n if (isNegative) {\n formatted = `-${formatted}`;\n }\n\n // Add symbol\n if (showSymbol) {\n const pos = symbolPosition ?? this.currency.symbolPosition;\n const space = this.currency.symbolSpacing ? ' ' : '';\n\n if (pos === 'before') {\n formatted = `${this.currency.symbol}${space}${formatted}`;\n } else {\n formatted = `${formatted}${space}${this.currency.symbol}`;\n }\n }\n\n return formatted;\n }\n\n /**\n * Get the decimal representation\n */\n toDecimal(): number {\n return this.cents / Math.pow(10, this.currency.decimals);\n }\n\n /**\n * Check equality with another money value\n */\n equals(other: IMoney): boolean {\n return this.cents === other.cents && this.currency.code === other.currency.code;\n }\n\n /**\n * Check if greater than another money value\n */\n greaterThan(other: IMoney): boolean {\n this.assertSameCurrency(other);\n return this.cents > other.cents;\n }\n\n /**\n * Check if less than another money value\n */\n lessThan(other: IMoney): boolean {\n this.assertSameCurrency(other);\n return this.cents < other.cents;\n }\n\n /**\n * Check if greater than or equal\n */\n greaterThanOrEqual(other: IMoney): boolean {\n this.assertSameCurrency(other);\n return this.cents >= other.cents;\n }\n\n /**\n * Check if less than or equal\n */\n lessThanOrEqual(other: IMoney): boolean {\n this.assertSameCurrency(other);\n return this.cents <= other.cents;\n }\n\n /**\n * Check if zero\n */\n isZero(): boolean {\n return this.cents === 0;\n }\n\n /**\n * Check if positive\n */\n isPositive(): boolean {\n return this.cents > 0;\n }\n\n /**\n * Check if negative\n */\n isNegative(): boolean {\n return this.cents < 0;\n }\n\n /**\n * Get absolute value\n */\n abs(): Money {\n return new Money(Math.abs(this.cents), this.currency);\n }\n\n /**\n * Negate the value\n */\n negate(): Money {\n return new Money(-this.cents, this.currency);\n }\n\n /**\n * Calculate a percentage of this money\n * @example money.percentage(10) returns 10% of the amount\n */\n percentage(percent: number): Money {\n return new Money(Math.round((this.cents * percent) / 100), this.currency);\n }\n\n /**\n * Add a percentage to this money\n * @example money.addPercentage(19) adds 19% (like tax)\n */\n addPercentage(percent: number): Money {\n return this.add(this.percentage(percent));\n }\n\n /**\n * Subtract a percentage from this money\n * @example money.subtractPercentage(10) subtracts 10% (like discount)\n */\n subtractPercentage(percent: number): Money {\n return this.subtract(this.percentage(percent));\n }\n\n /**\n * Get the minimum of this and another money value\n */\n min(other: IMoney): Money {\n this.assertSameCurrency(other);\n return this.cents <= other.cents ? this : new Money(other.cents, this.currency);\n }\n\n /**\n * Get the maximum of this and another money value\n */\n max(other: IMoney): Money {\n this.assertSameCurrency(other);\n return this.cents >= other.cents ? this : new Money(other.cents, this.currency);\n }\n\n /**\n * Clamp this money between a minimum and maximum\n */\n clamp(minValue: IMoney, maxValue: IMoney): Money {\n return this.max(minValue).min(maxValue);\n }\n\n /**\n * Get cents (smallest unit)\n */\n toCents(): number {\n return this.cents;\n }\n\n /**\n * Check if within a range (inclusive)\n */\n isBetween(min: IMoney, max: IMoney): boolean {\n this.assertSameCurrency(min);\n this.assertSameCurrency(max);\n return this.cents >= min.cents && this.cents <= max.cents;\n }\n\n /**\n * Sum multiple money values\n */\n static sum(values: IMoney[]): Money {\n if (values.length === 0) {\n throw new Error('Cannot sum empty array');\n }\n const currency = values[0].currency;\n const total = values.reduce((sum, m) => {\n if (m.currency.code !== currency.code) {\n throw new Error('Cannot sum different currencies');\n }\n return sum + m.cents;\n }, 0);\n return new Money(total, currency);\n }\n\n /**\n * Get the minimum from an array of money values\n */\n static minimum(values: IMoney[]): Money {\n if (values.length === 0) {\n throw new Error('Cannot get minimum of empty array');\n }\n return values.reduce((min, m) => (m.cents < min.cents ? m : min)) as Money;\n }\n\n /**\n * Get the maximum from an array of money values\n */\n static maximum(values: IMoney[]): Money {\n if (values.length === 0) {\n throw new Error('Cannot get maximum of empty array');\n }\n return values.reduce((max, m) => (m.cents > max.cents ? m : max)) as Money;\n }\n\n /**\n * Calculate the average of money values\n */\n static average(values: IMoney[]): Money {\n if (values.length === 0) {\n throw new Error('Cannot calculate average of empty array');\n }\n const total = Money.sum(values);\n return total.divide(values.length);\n }\n\n /**\n * Convert to JSON-serializable object\n */\n toJSON(): { cents: number; currency: string } {\n return {\n cents: this.cents,\n currency: this.currency.code,\n };\n }\n\n /**\n * String representation\n */\n toString(): string {\n return this.format();\n }\n\n private formatInteger(intStr: string): string {\n const parts: string[] = [];\n let remaining = intStr;\n\n while (remaining.length > 3) {\n parts.unshift(remaining.slice(-3));\n remaining = remaining.slice(0, -3);\n }\n\n if (remaining) {\n parts.unshift(remaining);\n }\n\n return parts.join(this.currency.thousandsSeparator);\n }\n\n private assertSameCurrency(other: IMoney): void {\n if (this.currency.code !== other.currency.code) {\n throw new Error(\n `Cannot perform operation with different currencies: ${this.currency.code} and ${other.currency.code}`\n );\n }\n }\n}\n"]}
@@ -84,6 +84,11 @@ declare class Money implements IMoney {
84
84
  * @example Money.fromDecimal(100.50, USD) creates $100.50
85
85
  */
86
86
  static fromDecimal(amount: number, currency: Currency): Money;
87
+ /**
88
+ * Create money from a formatted string
89
+ * @example Money.fromString("$ 1.500,50", ARS) creates $1,500.50
90
+ */
91
+ static fromString(value: string, currency: Currency): Money;
87
92
  /**
88
93
  * Create zero money
89
94
  */
@@ -84,6 +84,11 @@ declare class Money implements IMoney {
84
84
  * @example Money.fromDecimal(100.50, USD) creates $100.50
85
85
  */
86
86
  static fromDecimal(amount: number, currency: Currency): Money;
87
+ /**
88
+ * Create money from a formatted string
89
+ * @example Money.fromString("$ 1.500,50", ARS) creates $1,500.50
90
+ */
91
+ static fromString(value: string, currency: Currency): Money;
87
92
  /**
88
93
  * Create zero money
89
94
  */
@@ -1,2 +1,2 @@
1
- var y=class r{constructor(e,t){if(!Number.isInteger(e))throw new Error("Money must be created with an integer number of cents");this.cents=e,this.currency=t,Object.freeze(this);}static fromCents(e,t){return new r(Math.round(e),t)}static fromDecimal(e,t){let n=Math.pow(10,t.decimals),c=Math.round(e*n);return new r(c,t)}static zero(e){return new r(0,e)}add(e){return this.assertSameCurrency(e),new r(this.cents+e.cents,this.currency)}subtract(e){return this.assertSameCurrency(e),new r(this.cents-e.cents,this.currency)}multiply(e){return new r(Math.round(this.cents*e),this.currency)}divide(e){if(e===0)throw new Error("Cannot divide by zero");return new r(Math.round(this.cents/e),this.currency)}distribute(e){if(e<=0||!Number.isInteger(e))throw new Error("Parts must be a positive integer");let t=Math.floor(this.cents/e),n=this.cents%e,c=[];for(let s=0;s<e;s++){let o=s<n?1:0;c.push(new r(t+o,this.currency));}return c}distributeByRatios(e){if(e.length===0)throw new Error("Ratios array cannot be empty");let t=e.reduce((s,o)=>s+o,0);if(t<=0)throw new Error("Sum of ratios must be positive");let n=this.cents,c=[];for(let s=0;s<e.length;s++)if(s===e.length-1)c.push(new r(n,this.currency));else {let o=Math.round(this.cents*e[s]/t);c.push(new r(o,this.currency)),n-=o;}return c}format(e={}){let{showSymbol:t=true,showDecimals:n=true,symbolPosition:c}=e,s=this.toDecimal(),o=Math.abs(s),h=s<0,i;if(n&&this.currency.decimals>0){let[a,u]=o.toFixed(this.currency.decimals).split(".");i=`${this.formatInteger(a)}${this.currency.decimalSeparator}${u}`;}else i=this.formatInteger(Math.round(o).toString());if(h&&(i=`-${i}`),t){let a=c??this.currency.symbolPosition,u=this.currency.symbolSpacing?" ":"";a==="before"?i=`${this.currency.symbol}${u}${i}`:i=`${i}${u}${this.currency.symbol}`;}return i}toDecimal(){return this.cents/Math.pow(10,this.currency.decimals)}equals(e){return this.cents===e.cents&&this.currency.code===e.currency.code}greaterThan(e){return this.assertSameCurrency(e),this.cents>e.cents}lessThan(e){return this.assertSameCurrency(e),this.cents<e.cents}greaterThanOrEqual(e){return this.assertSameCurrency(e),this.cents>=e.cents}lessThanOrEqual(e){return this.assertSameCurrency(e),this.cents<=e.cents}isZero(){return this.cents===0}isPositive(){return this.cents>0}isNegative(){return this.cents<0}abs(){return new r(Math.abs(this.cents),this.currency)}negate(){return new r(-this.cents,this.currency)}percentage(e){return new r(Math.round(this.cents*e/100),this.currency)}addPercentage(e){return this.add(this.percentage(e))}subtractPercentage(e){return this.subtract(this.percentage(e))}min(e){return this.assertSameCurrency(e),this.cents<=e.cents?this:new r(e.cents,this.currency)}max(e){return this.assertSameCurrency(e),this.cents>=e.cents?this:new r(e.cents,this.currency)}clamp(e,t){return this.max(e).min(t)}toCents(){return this.cents}isBetween(e,t){return this.assertSameCurrency(e),this.assertSameCurrency(t),this.cents>=e.cents&&this.cents<=t.cents}static sum(e){if(e.length===0)throw new Error("Cannot sum empty array");let t=e[0].currency,n=e.reduce((c,s)=>{if(s.currency.code!==t.code)throw new Error("Cannot sum different currencies");return c+s.cents},0);return new r(n,t)}static minimum(e){if(e.length===0)throw new Error("Cannot get minimum of empty array");return e.reduce((t,n)=>n.cents<t.cents?n:t)}static maximum(e){if(e.length===0)throw new Error("Cannot get maximum of empty array");return e.reduce((t,n)=>n.cents>t.cents?n:t)}static average(e){if(e.length===0)throw new Error("Cannot calculate average of empty array");return r.sum(e).divide(e.length)}toJSON(){return {cents:this.cents,currency:this.currency.code}}toString(){return this.format()}formatInteger(e){let t=[],n=e;for(;n.length>3;)t.unshift(n.slice(-3)),n=n.slice(0,-3);return n&&t.unshift(n),t.join(this.currency.thousandsSeparator)}assertSameCurrency(e){if(this.currency.code!==e.currency.code)throw new Error(`Cannot perform operation with different currencies: ${this.currency.code} and ${e.currency.code}`)}};export{y as Money};//# sourceMappingURL=index.js.map
1
+ var y=class s{constructor(e,t){if(!Number.isInteger(e))throw new Error("Money must be created with an integer number of cents");this.cents=e,this.currency=t,Object.freeze(this);}static fromCents(e,t){return new s(Math.round(e),t)}static fromDecimal(e,t){let r=Math.pow(10,t.decimals),o=Math.round(e*r);return new s(o,t)}static fromString(e,t){let r=e.replace(t.symbol,"").trim(),o=c=>c.replace(/[.*+?^${}()|[\]\\]/g,"\\$&");if(t.thousandsSeparator){let c=new RegExp(o(t.thousandsSeparator),"g");r=r.replace(c,"");}t.decimalSeparator&&t.decimalSeparator!=="."&&(r=r.replace(t.decimalSeparator,".")),r=r.replace(/\s+/g,"");let n=parseFloat(r);if(isNaN(n))throw new Error(`Cannot parse "${e}" as money`);return s.fromDecimal(n,t)}static zero(e){return new s(0,e)}add(e){return this.assertSameCurrency(e),new s(this.cents+e.cents,this.currency)}subtract(e){return this.assertSameCurrency(e),new s(this.cents-e.cents,this.currency)}multiply(e){return new s(Math.round(this.cents*e),this.currency)}divide(e){if(e===0)throw new Error("Cannot divide by zero");return new s(Math.round(this.cents/e),this.currency)}distribute(e){if(e<=0||!Number.isInteger(e))throw new Error("Parts must be a positive integer");let t=Math.floor(this.cents/e),r=this.cents%e,o=[];for(let n=0;n<e;n++){let c=n<r?1:0;o.push(new s(t+c,this.currency));}return o}distributeByRatios(e){if(e.length===0)throw new Error("Ratios array cannot be empty");let t=e.reduce((n,c)=>n+c,0);if(t<=0)throw new Error("Sum of ratios must be positive");let r=this.cents,o=[];for(let n=0;n<e.length;n++)if(n===e.length-1)o.push(new s(r,this.currency));else {let c=Math.round(this.cents*e[n]/t);o.push(new s(c,this.currency)),r-=c;}return o}format(e={}){let{showSymbol:t=true,showDecimals:r=true,symbolPosition:o}=e,n=this.toDecimal(),c=Math.abs(n),h=n<0,i;if(r&&this.currency.decimals>0){let[u,a]=c.toFixed(this.currency.decimals).split(".");i=`${this.formatInteger(u)}${this.currency.decimalSeparator}${a}`;}else i=this.formatInteger(Math.round(c).toString());if(h&&(i=`-${i}`),t){let u=o??this.currency.symbolPosition,a=this.currency.symbolSpacing?" ":"";u==="before"?i=`${this.currency.symbol}${a}${i}`:i=`${i}${a}${this.currency.symbol}`;}return i}toDecimal(){return this.cents/Math.pow(10,this.currency.decimals)}equals(e){return this.cents===e.cents&&this.currency.code===e.currency.code}greaterThan(e){return this.assertSameCurrency(e),this.cents>e.cents}lessThan(e){return this.assertSameCurrency(e),this.cents<e.cents}greaterThanOrEqual(e){return this.assertSameCurrency(e),this.cents>=e.cents}lessThanOrEqual(e){return this.assertSameCurrency(e),this.cents<=e.cents}isZero(){return this.cents===0}isPositive(){return this.cents>0}isNegative(){return this.cents<0}abs(){return new s(Math.abs(this.cents),this.currency)}negate(){return new s(-this.cents,this.currency)}percentage(e){return new s(Math.round(this.cents*e/100),this.currency)}addPercentage(e){return this.add(this.percentage(e))}subtractPercentage(e){return this.subtract(this.percentage(e))}min(e){return this.assertSameCurrency(e),this.cents<=e.cents?this:new s(e.cents,this.currency)}max(e){return this.assertSameCurrency(e),this.cents>=e.cents?this:new s(e.cents,this.currency)}clamp(e,t){return this.max(e).min(t)}toCents(){return this.cents}isBetween(e,t){return this.assertSameCurrency(e),this.assertSameCurrency(t),this.cents>=e.cents&&this.cents<=t.cents}static sum(e){if(e.length===0)throw new Error("Cannot sum empty array");let t=e[0].currency,r=e.reduce((o,n)=>{if(n.currency.code!==t.code)throw new Error("Cannot sum different currencies");return o+n.cents},0);return new s(r,t)}static minimum(e){if(e.length===0)throw new Error("Cannot get minimum of empty array");return e.reduce((t,r)=>r.cents<t.cents?r:t)}static maximum(e){if(e.length===0)throw new Error("Cannot get maximum of empty array");return e.reduce((t,r)=>r.cents>t.cents?r:t)}static average(e){if(e.length===0)throw new Error("Cannot calculate average of empty array");return s.sum(e).divide(e.length)}toJSON(){return {cents:this.cents,currency:this.currency.code}}toString(){return this.format()}formatInteger(e){let t=[],r=e;for(;r.length>3;)t.unshift(r.slice(-3)),r=r.slice(0,-3);return r&&t.unshift(r),t.join(this.currency.thousandsSeparator)}assertSameCurrency(e){if(this.currency.code!==e.currency.code)throw new Error(`Cannot perform operation with different currencies: ${this.currency.code} and ${e.currency.code}`)}};export{y as Money};//# sourceMappingURL=index.js.map
2
2
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/core/money.ts"],"names":["Money","_Money","cents","currency","amount","multiplier","other","factor","divisor","parts","quotient","remainder","result","i","extra","ratios","total","sum","r","remaining","share","options","showSymbol","showDecimals","symbolPosition","decimal","absValue","isNegative","formatted","intPart","decPart","pos","space","percent","minValue","maxValue","min","max","values","m","intStr"],"mappings":"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","file":"index.js","sourcesContent":["import type { Currency, FormatOptions, IMoney } from './types.js';\n\n/**\n * Immutable Money class that uses integer arithmetic for precision\n */\nexport class Money implements IMoney {\n readonly cents: number;\n readonly currency: Currency;\n\n private constructor(cents: number, currency: Currency) {\n if (!Number.isInteger(cents)) {\n throw new Error('Money must be created with an integer number of cents');\n }\n this.cents = cents;\n this.currency = currency;\n Object.freeze(this);\n }\n\n /**\n * Create money from cents (smallest unit)\n */\n static fromCents(cents: number, currency: Currency): Money {\n return new Money(Math.round(cents), currency);\n }\n\n /**\n * Create money from a decimal amount\n * @example Money.fromDecimal(100.50, USD) creates $100.50\n */\n static fromDecimal(amount: number, currency: Currency): Money {\n const multiplier = Math.pow(10, currency.decimals);\n const cents = Math.round(amount * multiplier);\n return new Money(cents, currency);\n }\n\n /**\n * Create zero money\n */\n static zero(currency: Currency): Money {\n return new Money(0, currency);\n }\n\n /**\n * Add another money value (must be same currency)\n */\n add(other: IMoney): Money {\n this.assertSameCurrency(other);\n return new Money(this.cents + other.cents, this.currency);\n }\n\n /**\n * Subtract another money value (must be same currency)\n */\n subtract(other: IMoney): Money {\n this.assertSameCurrency(other);\n return new Money(this.cents - other.cents, this.currency);\n }\n\n /**\n * Multiply by a factor (rounds to nearest cent)\n */\n multiply(factor: number): Money {\n return new Money(Math.round(this.cents * factor), this.currency);\n }\n\n /**\n * Divide by a divisor (rounds to nearest cent)\n */\n divide(divisor: number): Money {\n if (divisor === 0) {\n throw new Error('Cannot divide by zero');\n }\n return new Money(Math.round(this.cents / divisor), this.currency);\n }\n\n /**\n * Distribute money evenly without losing cents\n * The remainder is distributed to the first parts\n * @example $100 / 3 = [$33.34, $33.33, $33.33]\n */\n distribute(parts: number): Money[] {\n if (parts <= 0 || !Number.isInteger(parts)) {\n throw new Error('Parts must be a positive integer');\n }\n\n const quotient = Math.floor(this.cents / parts);\n const remainder = this.cents % parts;\n\n const result: Money[] = [];\n for (let i = 0; i < parts; i++) {\n // Add 1 cent to the first 'remainder' parts\n const extra = i < remainder ? 1 : 0;\n result.push(new Money(quotient + extra, this.currency));\n }\n\n return result;\n }\n\n /**\n * Distribute money according to ratios\n * @example $100 with ratios [1, 2, 2] = [$20, $40, $40]\n */\n distributeByRatios(ratios: number[]): Money[] {\n if (ratios.length === 0) {\n throw new Error('Ratios array cannot be empty');\n }\n\n const total = ratios.reduce((sum, r) => sum + r, 0);\n if (total <= 0) {\n throw new Error('Sum of ratios must be positive');\n }\n\n let remaining = this.cents;\n const result: Money[] = [];\n\n for (let i = 0; i < ratios.length; i++) {\n if (i === ratios.length - 1) {\n // Last part gets whatever is remaining to avoid rounding errors\n result.push(new Money(remaining, this.currency));\n } else {\n const share = Math.round((this.cents * ratios[i]) / total);\n result.push(new Money(share, this.currency));\n remaining -= share;\n }\n }\n\n return result;\n }\n\n /**\n * Format money for display\n */\n format(options: FormatOptions = {}): string {\n const { showSymbol = true, showDecimals = true, symbolPosition } = options;\n\n const decimal = this.toDecimal();\n const absValue = Math.abs(decimal);\n const isNegative = decimal < 0;\n\n // Format the number\n let formatted: string;\n if (showDecimals && this.currency.decimals > 0) {\n const [intPart, decPart] = absValue.toFixed(this.currency.decimals).split('.');\n const intFormatted = this.formatInteger(intPart);\n formatted = `${intFormatted}${this.currency.decimalSeparator}${decPart}`;\n } else {\n formatted = this.formatInteger(Math.round(absValue).toString());\n }\n\n // Add negative sign\n if (isNegative) {\n formatted = `-${formatted}`;\n }\n\n // Add symbol\n if (showSymbol) {\n const pos = symbolPosition ?? this.currency.symbolPosition;\n const space = this.currency.symbolSpacing ? ' ' : '';\n\n if (pos === 'before') {\n formatted = `${this.currency.symbol}${space}${formatted}`;\n } else {\n formatted = `${formatted}${space}${this.currency.symbol}`;\n }\n }\n\n return formatted;\n }\n\n /**\n * Get the decimal representation\n */\n toDecimal(): number {\n return this.cents / Math.pow(10, this.currency.decimals);\n }\n\n /**\n * Check equality with another money value\n */\n equals(other: IMoney): boolean {\n return this.cents === other.cents && this.currency.code === other.currency.code;\n }\n\n /**\n * Check if greater than another money value\n */\n greaterThan(other: IMoney): boolean {\n this.assertSameCurrency(other);\n return this.cents > other.cents;\n }\n\n /**\n * Check if less than another money value\n */\n lessThan(other: IMoney): boolean {\n this.assertSameCurrency(other);\n return this.cents < other.cents;\n }\n\n /**\n * Check if greater than or equal\n */\n greaterThanOrEqual(other: IMoney): boolean {\n this.assertSameCurrency(other);\n return this.cents >= other.cents;\n }\n\n /**\n * Check if less than or equal\n */\n lessThanOrEqual(other: IMoney): boolean {\n this.assertSameCurrency(other);\n return this.cents <= other.cents;\n }\n\n /**\n * Check if zero\n */\n isZero(): boolean {\n return this.cents === 0;\n }\n\n /**\n * Check if positive\n */\n isPositive(): boolean {\n return this.cents > 0;\n }\n\n /**\n * Check if negative\n */\n isNegative(): boolean {\n return this.cents < 0;\n }\n\n /**\n * Get absolute value\n */\n abs(): Money {\n return new Money(Math.abs(this.cents), this.currency);\n }\n\n /**\n * Negate the value\n */\n negate(): Money {\n return new Money(-this.cents, this.currency);\n }\n\n /**\n * Calculate a percentage of this money\n * @example money.percentage(10) returns 10% of the amount\n */\n percentage(percent: number): Money {\n return new Money(Math.round((this.cents * percent) / 100), this.currency);\n }\n\n /**\n * Add a percentage to this money\n * @example money.addPercentage(19) adds 19% (like tax)\n */\n addPercentage(percent: number): Money {\n return this.add(this.percentage(percent));\n }\n\n /**\n * Subtract a percentage from this money\n * @example money.subtractPercentage(10) subtracts 10% (like discount)\n */\n subtractPercentage(percent: number): Money {\n return this.subtract(this.percentage(percent));\n }\n\n /**\n * Get the minimum of this and another money value\n */\n min(other: IMoney): Money {\n this.assertSameCurrency(other);\n return this.cents <= other.cents ? this : new Money(other.cents, this.currency);\n }\n\n /**\n * Get the maximum of this and another money value\n */\n max(other: IMoney): Money {\n this.assertSameCurrency(other);\n return this.cents >= other.cents ? this : new Money(other.cents, this.currency);\n }\n\n /**\n * Clamp this money between a minimum and maximum\n */\n clamp(minValue: IMoney, maxValue: IMoney): Money {\n return this.max(minValue).min(maxValue);\n }\n\n /**\n * Get cents (smallest unit)\n */\n toCents(): number {\n return this.cents;\n }\n\n /**\n * Check if within a range (inclusive)\n */\n isBetween(min: IMoney, max: IMoney): boolean {\n this.assertSameCurrency(min);\n this.assertSameCurrency(max);\n return this.cents >= min.cents && this.cents <= max.cents;\n }\n\n /**\n * Sum multiple money values\n */\n static sum(values: IMoney[]): Money {\n if (values.length === 0) {\n throw new Error('Cannot sum empty array');\n }\n const currency = values[0].currency;\n const total = values.reduce((sum, m) => {\n if (m.currency.code !== currency.code) {\n throw new Error('Cannot sum different currencies');\n }\n return sum + m.cents;\n }, 0);\n return new Money(total, currency);\n }\n\n /**\n * Get the minimum from an array of money values\n */\n static minimum(values: IMoney[]): Money {\n if (values.length === 0) {\n throw new Error('Cannot get minimum of empty array');\n }\n return values.reduce((min, m) => (m.cents < min.cents ? m : min)) as Money;\n }\n\n /**\n * Get the maximum from an array of money values\n */\n static maximum(values: IMoney[]): Money {\n if (values.length === 0) {\n throw new Error('Cannot get maximum of empty array');\n }\n return values.reduce((max, m) => (m.cents > max.cents ? m : max)) as Money;\n }\n\n /**\n * Calculate the average of money values\n */\n static average(values: IMoney[]): Money {\n if (values.length === 0) {\n throw new Error('Cannot calculate average of empty array');\n }\n const total = Money.sum(values);\n return total.divide(values.length);\n }\n\n /**\n * Convert to JSON-serializable object\n */\n toJSON(): { cents: number; currency: string } {\n return {\n cents: this.cents,\n currency: this.currency.code,\n };\n }\n\n /**\n * String representation\n */\n toString(): string {\n return this.format();\n }\n\n private formatInteger(intStr: string): string {\n const parts: string[] = [];\n let remaining = intStr;\n\n while (remaining.length > 3) {\n parts.unshift(remaining.slice(-3));\n remaining = remaining.slice(0, -3);\n }\n\n if (remaining) {\n parts.unshift(remaining);\n }\n\n return parts.join(this.currency.thousandsSeparator);\n }\n\n private assertSameCurrency(other: IMoney): void {\n if (this.currency.code !== other.currency.code) {\n throw new Error(\n `Cannot perform operation with different currencies: ${this.currency.code} and ${other.currency.code}`\n );\n }\n }\n}\n"]}
1
+ {"version":3,"sources":["../../src/core/money.ts"],"names":["Money","_Money","cents","currency","amount","multiplier","value","cleanValue","escapeRegex","str","thousandsRegex","decimalAmount","other","factor","divisor","parts","quotient","remainder","result","i","extra","ratios","total","sum","r","remaining","share","options","showSymbol","showDecimals","symbolPosition","decimal","absValue","isNegative","formatted","intPart","decPart","pos","space","percent","minValue","maxValue","min","max","values","m","intStr"],"mappings":"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","file":"index.js","sourcesContent":["import type { Currency, FormatOptions, IMoney } from './types.js';\n\n/**\n * Immutable Money class that uses integer arithmetic for precision\n */\nexport class Money implements IMoney {\n readonly cents: number;\n readonly currency: Currency;\n\n private constructor(cents: number, currency: Currency) {\n if (!Number.isInteger(cents)) {\n throw new Error('Money must be created with an integer number of cents');\n }\n this.cents = cents;\n this.currency = currency;\n Object.freeze(this);\n }\n\n /**\n * Create money from cents (smallest unit)\n */\n static fromCents(cents: number, currency: Currency): Money {\n return new Money(Math.round(cents), currency);\n }\n\n /**\n * Create money from a decimal amount\n * @example Money.fromDecimal(100.50, USD) creates $100.50\n */\n static fromDecimal(amount: number, currency: Currency): Money {\n const multiplier = Math.pow(10, currency.decimals);\n const cents = Math.round(amount * multiplier);\n return new Money(cents, currency);\n }\n\n /**\n * Create money from a formatted string\n * @example Money.fromString(\"$ 1.500,50\", ARS) creates $1,500.50\n */\n static fromString(value: string, currency: Currency): Money {\n let cleanValue = value.replace(currency.symbol, '').trim();\n\n const escapeRegex = (str: string) => str.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n\n if (currency.thousandsSeparator) {\n const thousandsRegex = new RegExp(escapeRegex(currency.thousandsSeparator), 'g');\n cleanValue = cleanValue.replace(thousandsRegex, '');\n }\n\n if (currency.decimalSeparator && currency.decimalSeparator !== '.') {\n cleanValue = cleanValue.replace(currency.decimalSeparator, '.');\n }\n\n cleanValue = cleanValue.replace(/\\s+/g, '');\n\n const decimalAmount = parseFloat(cleanValue);\n\n if (isNaN(decimalAmount)) {\n throw new Error(`Cannot parse \"${value}\" as money`);\n }\n\n return Money.fromDecimal(decimalAmount, currency);\n }\n\n /**\n * Create zero money\n */\n static zero(currency: Currency): Money {\n return new Money(0, currency);\n }\n\n /**\n * Add another money value (must be same currency)\n */\n add(other: IMoney): Money {\n this.assertSameCurrency(other);\n return new Money(this.cents + other.cents, this.currency);\n }\n\n /**\n * Subtract another money value (must be same currency)\n */\n subtract(other: IMoney): Money {\n this.assertSameCurrency(other);\n return new Money(this.cents - other.cents, this.currency);\n }\n\n /**\n * Multiply by a factor (rounds to nearest cent)\n */\n multiply(factor: number): Money {\n return new Money(Math.round(this.cents * factor), this.currency);\n }\n\n /**\n * Divide by a divisor (rounds to nearest cent)\n */\n divide(divisor: number): Money {\n if (divisor === 0) {\n throw new Error('Cannot divide by zero');\n }\n return new Money(Math.round(this.cents / divisor), this.currency);\n }\n\n /**\n * Distribute money evenly without losing cents\n * The remainder is distributed to the first parts\n * @example $100 / 3 = [$33.34, $33.33, $33.33]\n */\n distribute(parts: number): Money[] {\n if (parts <= 0 || !Number.isInteger(parts)) {\n throw new Error('Parts must be a positive integer');\n }\n\n const quotient = Math.floor(this.cents / parts);\n const remainder = this.cents % parts;\n\n const result: Money[] = [];\n for (let i = 0; i < parts; i++) {\n // Add 1 cent to the first 'remainder' parts\n const extra = i < remainder ? 1 : 0;\n result.push(new Money(quotient + extra, this.currency));\n }\n\n return result;\n }\n\n /**\n * Distribute money according to ratios\n * @example $100 with ratios [1, 2, 2] = [$20, $40, $40]\n */\n distributeByRatios(ratios: number[]): Money[] {\n if (ratios.length === 0) {\n throw new Error('Ratios array cannot be empty');\n }\n\n const total = ratios.reduce((sum, r) => sum + r, 0);\n if (total <= 0) {\n throw new Error('Sum of ratios must be positive');\n }\n\n let remaining = this.cents;\n const result: Money[] = [];\n\n for (let i = 0; i < ratios.length; i++) {\n if (i === ratios.length - 1) {\n // Last part gets whatever is remaining to avoid rounding errors\n result.push(new Money(remaining, this.currency));\n } else {\n const share = Math.round((this.cents * ratios[i]) / total);\n result.push(new Money(share, this.currency));\n remaining -= share;\n }\n }\n\n return result;\n }\n\n /**\n * Format money for display\n */\n format(options: FormatOptions = {}): string {\n const { showSymbol = true, showDecimals = true, symbolPosition } = options;\n\n const decimal = this.toDecimal();\n const absValue = Math.abs(decimal);\n const isNegative = decimal < 0;\n\n // Format the number\n let formatted: string;\n if (showDecimals && this.currency.decimals > 0) {\n const [intPart, decPart] = absValue.toFixed(this.currency.decimals).split('.');\n const intFormatted = this.formatInteger(intPart);\n formatted = `${intFormatted}${this.currency.decimalSeparator}${decPart}`;\n } else {\n formatted = this.formatInteger(Math.round(absValue).toString());\n }\n\n // Add negative sign\n if (isNegative) {\n formatted = `-${formatted}`;\n }\n\n // Add symbol\n if (showSymbol) {\n const pos = symbolPosition ?? this.currency.symbolPosition;\n const space = this.currency.symbolSpacing ? ' ' : '';\n\n if (pos === 'before') {\n formatted = `${this.currency.symbol}${space}${formatted}`;\n } else {\n formatted = `${formatted}${space}${this.currency.symbol}`;\n }\n }\n\n return formatted;\n }\n\n /**\n * Get the decimal representation\n */\n toDecimal(): number {\n return this.cents / Math.pow(10, this.currency.decimals);\n }\n\n /**\n * Check equality with another money value\n */\n equals(other: IMoney): boolean {\n return this.cents === other.cents && this.currency.code === other.currency.code;\n }\n\n /**\n * Check if greater than another money value\n */\n greaterThan(other: IMoney): boolean {\n this.assertSameCurrency(other);\n return this.cents > other.cents;\n }\n\n /**\n * Check if less than another money value\n */\n lessThan(other: IMoney): boolean {\n this.assertSameCurrency(other);\n return this.cents < other.cents;\n }\n\n /**\n * Check if greater than or equal\n */\n greaterThanOrEqual(other: IMoney): boolean {\n this.assertSameCurrency(other);\n return this.cents >= other.cents;\n }\n\n /**\n * Check if less than or equal\n */\n lessThanOrEqual(other: IMoney): boolean {\n this.assertSameCurrency(other);\n return this.cents <= other.cents;\n }\n\n /**\n * Check if zero\n */\n isZero(): boolean {\n return this.cents === 0;\n }\n\n /**\n * Check if positive\n */\n isPositive(): boolean {\n return this.cents > 0;\n }\n\n /**\n * Check if negative\n */\n isNegative(): boolean {\n return this.cents < 0;\n }\n\n /**\n * Get absolute value\n */\n abs(): Money {\n return new Money(Math.abs(this.cents), this.currency);\n }\n\n /**\n * Negate the value\n */\n negate(): Money {\n return new Money(-this.cents, this.currency);\n }\n\n /**\n * Calculate a percentage of this money\n * @example money.percentage(10) returns 10% of the amount\n */\n percentage(percent: number): Money {\n return new Money(Math.round((this.cents * percent) / 100), this.currency);\n }\n\n /**\n * Add a percentage to this money\n * @example money.addPercentage(19) adds 19% (like tax)\n */\n addPercentage(percent: number): Money {\n return this.add(this.percentage(percent));\n }\n\n /**\n * Subtract a percentage from this money\n * @example money.subtractPercentage(10) subtracts 10% (like discount)\n */\n subtractPercentage(percent: number): Money {\n return this.subtract(this.percentage(percent));\n }\n\n /**\n * Get the minimum of this and another money value\n */\n min(other: IMoney): Money {\n this.assertSameCurrency(other);\n return this.cents <= other.cents ? this : new Money(other.cents, this.currency);\n }\n\n /**\n * Get the maximum of this and another money value\n */\n max(other: IMoney): Money {\n this.assertSameCurrency(other);\n return this.cents >= other.cents ? this : new Money(other.cents, this.currency);\n }\n\n /**\n * Clamp this money between a minimum and maximum\n */\n clamp(minValue: IMoney, maxValue: IMoney): Money {\n return this.max(minValue).min(maxValue);\n }\n\n /**\n * Get cents (smallest unit)\n */\n toCents(): number {\n return this.cents;\n }\n\n /**\n * Check if within a range (inclusive)\n */\n isBetween(min: IMoney, max: IMoney): boolean {\n this.assertSameCurrency(min);\n this.assertSameCurrency(max);\n return this.cents >= min.cents && this.cents <= max.cents;\n }\n\n /**\n * Sum multiple money values\n */\n static sum(values: IMoney[]): Money {\n if (values.length === 0) {\n throw new Error('Cannot sum empty array');\n }\n const currency = values[0].currency;\n const total = values.reduce((sum, m) => {\n if (m.currency.code !== currency.code) {\n throw new Error('Cannot sum different currencies');\n }\n return sum + m.cents;\n }, 0);\n return new Money(total, currency);\n }\n\n /**\n * Get the minimum from an array of money values\n */\n static minimum(values: IMoney[]): Money {\n if (values.length === 0) {\n throw new Error('Cannot get minimum of empty array');\n }\n return values.reduce((min, m) => (m.cents < min.cents ? m : min)) as Money;\n }\n\n /**\n * Get the maximum from an array of money values\n */\n static maximum(values: IMoney[]): Money {\n if (values.length === 0) {\n throw new Error('Cannot get maximum of empty array');\n }\n return values.reduce((max, m) => (m.cents > max.cents ? m : max)) as Money;\n }\n\n /**\n * Calculate the average of money values\n */\n static average(values: IMoney[]): Money {\n if (values.length === 0) {\n throw new Error('Cannot calculate average of empty array');\n }\n const total = Money.sum(values);\n return total.divide(values.length);\n }\n\n /**\n * Convert to JSON-serializable object\n */\n toJSON(): { cents: number; currency: string } {\n return {\n cents: this.cents,\n currency: this.currency.code,\n };\n }\n\n /**\n * String representation\n */\n toString(): string {\n return this.format();\n }\n\n private formatInteger(intStr: string): string {\n const parts: string[] = [];\n let remaining = intStr;\n\n while (remaining.length > 3) {\n parts.unshift(remaining.slice(-3));\n remaining = remaining.slice(0, -3);\n }\n\n if (remaining) {\n parts.unshift(remaining);\n }\n\n return parts.join(this.currency.thousandsSeparator);\n }\n\n private assertSameCurrency(other: IMoney): void {\n if (this.currency.code !== other.currency.code) {\n throw new Error(\n `Cannot perform operation with different currencies: ${this.currency.code} and ${other.currency.code}`\n );\n }\n }\n}\n"]}
package/dist/index.cjs CHANGED
@@ -1,2 +1,2 @@
1
- 'use strict';var u=class n{constructor(e,r){if(!Number.isInteger(e))throw new Error("Money must be created with an integer number of cents");this.cents=e,this.currency=r,Object.freeze(this);}static fromCents(e,r){return new n(Math.round(e),r)}static fromDecimal(e,r){let t=Math.pow(10,r.decimals),s=Math.round(e*t);return new n(s,r)}static zero(e){return new n(0,e)}add(e){return this.assertSameCurrency(e),new n(this.cents+e.cents,this.currency)}subtract(e){return this.assertSameCurrency(e),new n(this.cents-e.cents,this.currency)}multiply(e){return new n(Math.round(this.cents*e),this.currency)}divide(e){if(e===0)throw new Error("Cannot divide by zero");return new n(Math.round(this.cents/e),this.currency)}distribute(e){if(e<=0||!Number.isInteger(e))throw new Error("Parts must be a positive integer");let r=Math.floor(this.cents/e),t=this.cents%e,s=[];for(let o=0;o<e;o++){let c=o<t?1:0;s.push(new n(r+c,this.currency));}return s}distributeByRatios(e){if(e.length===0)throw new Error("Ratios array cannot be empty");let r=e.reduce((o,c)=>o+c,0);if(r<=0)throw new Error("Sum of ratios must be positive");let t=this.cents,s=[];for(let o=0;o<e.length;o++)if(o===e.length-1)s.push(new n(t,this.currency));else {let c=Math.round(this.cents*e[o]/r);s.push(new n(c,this.currency)),t-=c;}return s}format(e={}){let{showSymbol:r=true,showDecimals:t=true,symbolPosition:s}=e,o=this.toDecimal(),c=Math.abs(o),l=o<0,i;if(t&&this.currency.decimals>0){let[y,a]=c.toFixed(this.currency.decimals).split(".");i=`${this.formatInteger(y)}${this.currency.decimalSeparator}${a}`;}else i=this.formatInteger(Math.round(c).toString());if(l&&(i=`-${i}`),r){let y=s??this.currency.symbolPosition,a=this.currency.symbolSpacing?" ":"";y==="before"?i=`${this.currency.symbol}${a}${i}`:i=`${i}${a}${this.currency.symbol}`;}return i}toDecimal(){return this.cents/Math.pow(10,this.currency.decimals)}equals(e){return this.cents===e.cents&&this.currency.code===e.currency.code}greaterThan(e){return this.assertSameCurrency(e),this.cents>e.cents}lessThan(e){return this.assertSameCurrency(e),this.cents<e.cents}greaterThanOrEqual(e){return this.assertSameCurrency(e),this.cents>=e.cents}lessThanOrEqual(e){return this.assertSameCurrency(e),this.cents<=e.cents}isZero(){return this.cents===0}isPositive(){return this.cents>0}isNegative(){return this.cents<0}abs(){return new n(Math.abs(this.cents),this.currency)}negate(){return new n(-this.cents,this.currency)}percentage(e){return new n(Math.round(this.cents*e/100),this.currency)}addPercentage(e){return this.add(this.percentage(e))}subtractPercentage(e){return this.subtract(this.percentage(e))}min(e){return this.assertSameCurrency(e),this.cents<=e.cents?this:new n(e.cents,this.currency)}max(e){return this.assertSameCurrency(e),this.cents>=e.cents?this:new n(e.cents,this.currency)}clamp(e,r){return this.max(e).min(r)}toCents(){return this.cents}isBetween(e,r){return this.assertSameCurrency(e),this.assertSameCurrency(r),this.cents>=e.cents&&this.cents<=r.cents}static sum(e){if(e.length===0)throw new Error("Cannot sum empty array");let r=e[0].currency,t=e.reduce((s,o)=>{if(o.currency.code!==r.code)throw new Error("Cannot sum different currencies");return s+o.cents},0);return new n(t,r)}static minimum(e){if(e.length===0)throw new Error("Cannot get minimum of empty array");return e.reduce((r,t)=>t.cents<r.cents?t:r)}static maximum(e){if(e.length===0)throw new Error("Cannot get maximum of empty array");return e.reduce((r,t)=>t.cents>r.cents?t:r)}static average(e){if(e.length===0)throw new Error("Cannot calculate average of empty array");return n.sum(e).divide(e.length)}toJSON(){return {cents:this.cents,currency:this.currency.code}}toString(){return this.format()}formatInteger(e){let r=[],t=e;for(;t.length>3;)r.unshift(t.slice(-3)),t=t.slice(0,-3);return t&&r.unshift(t),r.join(this.currency.thousandsSeparator)}assertSameCurrency(e){if(this.currency.code!==e.currency.code)throw new Error(`Cannot perform operation with different currencies: ${this.currency.code} and ${e.currency.code}`)}};var m={code:"COP",symbol:"$",decimals:2,thousandsSeparator:".",decimalSeparator:",",symbolPosition:"before",symbolSpacing:true},p={...m,decimals:0};var d={code:"MXN",symbol:"$",decimals:2,thousandsSeparator:",",decimalSeparator:".",symbolPosition:"before",symbolSpacing:false};var b={code:"ARS",symbol:"$",decimals:2,thousandsSeparator:".",decimalSeparator:",",symbolPosition:"before",symbolSpacing:true};var f={code:"BRL",symbol:"R$",decimals:2,thousandsSeparator:".",decimalSeparator:",",symbolPosition:"before",symbolSpacing:true};var M={code:"USD",symbol:"$",decimals:2,thousandsSeparator:",",decimalSeparator:".",symbolPosition:"before",symbolSpacing:false};var h={code:"CLP",symbol:"$",decimals:0,thousandsSeparator:".",decimalSeparator:",",symbolPosition:"before",symbolSpacing:true},C={...h,decimals:2};var S={code:"PEN",symbol:"S/",decimals:2,thousandsSeparator:",",decimalSeparator:".",symbolPosition:"before",symbolSpacing:true};var g={code:"UYU",symbol:"$",decimals:2,thousandsSeparator:".",decimalSeparator:",",symbolPosition:"before",symbolSpacing:true};var w={code:"EUR",symbol:"\u20AC",decimals:2,thousandsSeparator:".",decimalSeparator:",",symbolPosition:"after",symbolSpacing:true};exports.ARS=b;exports.BRL=f;exports.CLP=h;exports.CLP_DECIMALS=C;exports.COP=m;exports.COP_NO_DECIMALS=p;exports.EUR=w;exports.MXN=d;exports.Money=u;exports.PEN=S;exports.USD=M;exports.UYU=g;//# sourceMappingURL=index.cjs.map
1
+ 'use strict';var y=class o{constructor(e,r){if(!Number.isInteger(e))throw new Error("Money must be created with an integer number of cents");this.cents=e,this.currency=r,Object.freeze(this);}static fromCents(e,r){return new o(Math.round(e),r)}static fromDecimal(e,r){let t=Math.pow(10,r.decimals),s=Math.round(e*t);return new o(s,r)}static fromString(e,r){let t=e.replace(r.symbol,"").trim(),s=c=>c.replace(/[.*+?^${}()|[\]\\]/g,"\\$&");if(r.thousandsSeparator){let c=new RegExp(s(r.thousandsSeparator),"g");t=t.replace(c,"");}r.decimalSeparator&&r.decimalSeparator!=="."&&(t=t.replace(r.decimalSeparator,".")),t=t.replace(/\s+/g,"");let n=parseFloat(t);if(isNaN(n))throw new Error(`Cannot parse "${e}" as money`);return o.fromDecimal(n,r)}static zero(e){return new o(0,e)}add(e){return this.assertSameCurrency(e),new o(this.cents+e.cents,this.currency)}subtract(e){return this.assertSameCurrency(e),new o(this.cents-e.cents,this.currency)}multiply(e){return new o(Math.round(this.cents*e),this.currency)}divide(e){if(e===0)throw new Error("Cannot divide by zero");return new o(Math.round(this.cents/e),this.currency)}distribute(e){if(e<=0||!Number.isInteger(e))throw new Error("Parts must be a positive integer");let r=Math.floor(this.cents/e),t=this.cents%e,s=[];for(let n=0;n<e;n++){let c=n<t?1:0;s.push(new o(r+c,this.currency));}return s}distributeByRatios(e){if(e.length===0)throw new Error("Ratios array cannot be empty");let r=e.reduce((n,c)=>n+c,0);if(r<=0)throw new Error("Sum of ratios must be positive");let t=this.cents,s=[];for(let n=0;n<e.length;n++)if(n===e.length-1)s.push(new o(t,this.currency));else {let c=Math.round(this.cents*e[n]/r);s.push(new o(c,this.currency)),t-=c;}return s}format(e={}){let{showSymbol:r=true,showDecimals:t=true,symbolPosition:s}=e,n=this.toDecimal(),c=Math.abs(n),p=n<0,i;if(t&&this.currency.decimals>0){let[u,a]=c.toFixed(this.currency.decimals).split(".");i=`${this.formatInteger(u)}${this.currency.decimalSeparator}${a}`;}else i=this.formatInteger(Math.round(c).toString());if(p&&(i=`-${i}`),r){let u=s??this.currency.symbolPosition,a=this.currency.symbolSpacing?" ":"";u==="before"?i=`${this.currency.symbol}${a}${i}`:i=`${i}${a}${this.currency.symbol}`;}return i}toDecimal(){return this.cents/Math.pow(10,this.currency.decimals)}equals(e){return this.cents===e.cents&&this.currency.code===e.currency.code}greaterThan(e){return this.assertSameCurrency(e),this.cents>e.cents}lessThan(e){return this.assertSameCurrency(e),this.cents<e.cents}greaterThanOrEqual(e){return this.assertSameCurrency(e),this.cents>=e.cents}lessThanOrEqual(e){return this.assertSameCurrency(e),this.cents<=e.cents}isZero(){return this.cents===0}isPositive(){return this.cents>0}isNegative(){return this.cents<0}abs(){return new o(Math.abs(this.cents),this.currency)}negate(){return new o(-this.cents,this.currency)}percentage(e){return new o(Math.round(this.cents*e/100),this.currency)}addPercentage(e){return this.add(this.percentage(e))}subtractPercentage(e){return this.subtract(this.percentage(e))}min(e){return this.assertSameCurrency(e),this.cents<=e.cents?this:new o(e.cents,this.currency)}max(e){return this.assertSameCurrency(e),this.cents>=e.cents?this:new o(e.cents,this.currency)}clamp(e,r){return this.max(e).min(r)}toCents(){return this.cents}isBetween(e,r){return this.assertSameCurrency(e),this.assertSameCurrency(r),this.cents>=e.cents&&this.cents<=r.cents}static sum(e){if(e.length===0)throw new Error("Cannot sum empty array");let r=e[0].currency,t=e.reduce((s,n)=>{if(n.currency.code!==r.code)throw new Error("Cannot sum different currencies");return s+n.cents},0);return new o(t,r)}static minimum(e){if(e.length===0)throw new Error("Cannot get minimum of empty array");return e.reduce((r,t)=>t.cents<r.cents?t:r)}static maximum(e){if(e.length===0)throw new Error("Cannot get maximum of empty array");return e.reduce((r,t)=>t.cents>r.cents?t:r)}static average(e){if(e.length===0)throw new Error("Cannot calculate average of empty array");return o.sum(e).divide(e.length)}toJSON(){return {cents:this.cents,currency:this.currency.code}}toString(){return this.format()}formatInteger(e){let r=[],t=e;for(;t.length>3;)r.unshift(t.slice(-3)),t=t.slice(0,-3);return t&&r.unshift(t),r.join(this.currency.thousandsSeparator)}assertSameCurrency(e){if(this.currency.code!==e.currency.code)throw new Error(`Cannot perform operation with different currencies: ${this.currency.code} and ${e.currency.code}`)}};var m={code:"COP",symbol:"$",decimals:2,thousandsSeparator:".",decimalSeparator:",",symbolPosition:"before",symbolSpacing:true},h={...m,decimals:0};var d={code:"MXN",symbol:"$",decimals:2,thousandsSeparator:",",decimalSeparator:".",symbolPosition:"before",symbolSpacing:false};var b={code:"ARS",symbol:"$",decimals:2,thousandsSeparator:".",decimalSeparator:",",symbolPosition:"before",symbolSpacing:true};var f={code:"BRL",symbol:"R$",decimals:2,thousandsSeparator:".",decimalSeparator:",",symbolPosition:"before",symbolSpacing:true};var M={code:"USD",symbol:"$",decimals:2,thousandsSeparator:",",decimalSeparator:".",symbolPosition:"before",symbolSpacing:false};var l={code:"CLP",symbol:"$",decimals:0,thousandsSeparator:".",decimalSeparator:",",symbolPosition:"before",symbolSpacing:true},C={...l,decimals:2};var S={code:"PEN",symbol:"S/",decimals:2,thousandsSeparator:",",decimalSeparator:".",symbolPosition:"before",symbolSpacing:true};var g={code:"UYU",symbol:"$",decimals:2,thousandsSeparator:".",decimalSeparator:",",symbolPosition:"before",symbolSpacing:true};var w={code:"EUR",symbol:"\u20AC",decimals:2,thousandsSeparator:".",decimalSeparator:",",symbolPosition:"after",symbolSpacing:true};exports.ARS=b;exports.BRL=f;exports.CLP=l;exports.CLP_DECIMALS=C;exports.COP=m;exports.COP_NO_DECIMALS=h;exports.EUR=w;exports.MXN=d;exports.Money=y;exports.PEN=S;exports.USD=M;exports.UYU=g;//# sourceMappingURL=index.cjs.map
2
2
  //# sourceMappingURL=index.cjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/core/money.ts","../src/locales/co.ts","../src/locales/mx.ts","../src/locales/ar.ts","../src/locales/br.ts","../src/locales/us.ts","../src/locales/cl.ts","../src/locales/pe.ts","../src/locales/uy.ts","../src/locales/eu.ts"],"names":["Money","_Money","cents","currency","amount","multiplier","other","factor","divisor","parts","quotient","remainder","result","i","extra","ratios","total","sum","r","remaining","share","options","showSymbol","showDecimals","symbolPosition","decimal","absValue","isNegative","formatted","intPart","decPart","pos","space","percent","minValue","maxValue","min","max","values","m","intStr","COP","COP_NO_DECIMALS","MXN","ARS","BRL","USD","CLP","CLP_DECIMALS","PEN","UYU","EUR"],"mappings":"aAKO,IAAMA,CAAAA,CAAN,MAAMC,CAAwB,CAI3B,WAAA,CAAYC,CAAAA,CAAeC,CAAAA,CAAoB,CACrD,GAAI,CAAC,MAAA,CAAO,SAAA,CAAUD,CAAK,CAAA,CACzB,MAAM,IAAI,KAAA,CAAM,uDAAuD,CAAA,CAEzE,IAAA,CAAK,KAAA,CAAQA,CAAAA,CACb,IAAA,CAAK,QAAA,CAAWC,CAAAA,CAChB,MAAA,CAAO,MAAA,CAAO,IAAI,EACpB,CAKA,OAAO,SAAA,CAAUD,CAAAA,CAAeC,CAAAA,CAA2B,CACzD,OAAO,IAAIF,CAAAA,CAAM,IAAA,CAAK,KAAA,CAAMC,CAAK,CAAA,CAAGC,CAAQ,CAC9C,CAMA,OAAO,WAAA,CAAYC,CAAAA,CAAgBD,CAAAA,CAA2B,CAC5D,IAAME,CAAAA,CAAa,IAAA,CAAK,GAAA,CAAI,EAAA,CAAIF,CAAAA,CAAS,QAAQ,CAAA,CAC3CD,CAAAA,CAAQ,IAAA,CAAK,MAAME,CAAAA,CAASC,CAAU,CAAA,CAC5C,OAAO,IAAIJ,CAAAA,CAAMC,CAAAA,CAAOC,CAAQ,CAClC,CAKA,OAAO,IAAA,CAAKA,CAAAA,CAA2B,CACrC,OAAO,IAAIF,CAAAA,CAAM,CAAA,CAAGE,CAAQ,CAC9B,CAKA,GAAA,CAAIG,CAAAA,CAAsB,CACxB,OAAA,IAAA,CAAK,kBAAA,CAAmBA,CAAK,CAAA,CACtB,IAAIL,CAAAA,CAAM,IAAA,CAAK,KAAA,CAAQK,EAAM,KAAA,CAAO,IAAA,CAAK,QAAQ,CAC1D,CAKA,QAAA,CAASA,CAAAA,CAAsB,CAC7B,OAAA,IAAA,CAAK,kBAAA,CAAmBA,CAAK,CAAA,CACtB,IAAIL,CAAAA,CAAM,IAAA,CAAK,KAAA,CAAQK,CAAAA,CAAM,KAAA,CAAO,IAAA,CAAK,QAAQ,CAC1D,CAKA,QAAA,CAASC,CAAAA,CAAuB,CAC9B,OAAO,IAAIN,CAAAA,CAAM,IAAA,CAAK,KAAA,CAAM,IAAA,CAAK,KAAA,CAAQM,CAAM,CAAA,CAAG,IAAA,CAAK,QAAQ,CACjE,CAKA,MAAA,CAAOC,CAAAA,CAAwB,CAC7B,GAAIA,CAAAA,GAAY,CAAA,CACd,MAAM,IAAI,KAAA,CAAM,uBAAuB,CAAA,CAEzC,OAAO,IAAIP,CAAAA,CAAM,IAAA,CAAK,KAAA,CAAM,IAAA,CAAK,KAAA,CAAQO,CAAO,CAAA,CAAG,IAAA,CAAK,QAAQ,CAClE,CAOA,UAAA,CAAWC,CAAAA,CAAwB,CACjC,GAAIA,CAAAA,EAAS,CAAA,EAAK,CAAC,MAAA,CAAO,SAAA,CAAUA,CAAK,CAAA,CACvC,MAAM,IAAI,KAAA,CAAM,kCAAkC,CAAA,CAGpD,IAAMC,CAAAA,CAAW,IAAA,CAAK,KAAA,CAAM,IAAA,CAAK,KAAA,CAAQD,CAAK,CAAA,CACxCE,CAAAA,CAAY,IAAA,CAAK,KAAA,CAAQF,CAAAA,CAEzBG,CAAAA,CAAkB,EAAC,CACzB,IAAA,IAASC,CAAAA,CAAI,CAAA,CAAGA,CAAAA,CAAIJ,CAAAA,CAAOI,IAAK,CAE9B,IAAMC,CAAAA,CAAQD,CAAAA,CAAIF,CAAAA,CAAY,CAAA,CAAI,CAAA,CAClCC,CAAAA,CAAO,IAAA,CAAK,IAAIX,CAAAA,CAAMS,CAAAA,CAAWI,CAAAA,CAAO,IAAA,CAAK,QAAQ,CAAC,EACxD,CAEA,OAAOF,CACT,CAMA,kBAAA,CAAmBG,CAAAA,CAA2B,CAC5C,GAAIA,CAAAA,CAAO,MAAA,GAAW,CAAA,CACpB,MAAM,IAAI,KAAA,CAAM,8BAA8B,EAGhD,IAAMC,CAAAA,CAAQD,CAAAA,CAAO,MAAA,CAAO,CAACE,CAAAA,CAAKC,CAAAA,GAAMD,CAAAA,CAAMC,CAAAA,CAAG,CAAC,CAAA,CAClD,GAAIF,CAAAA,EAAS,CAAA,CACX,MAAM,IAAI,KAAA,CAAM,gCAAgC,CAAA,CAGlD,IAAIG,CAAAA,CAAY,IAAA,CAAK,KAAA,CACfP,CAAAA,CAAkB,EAAC,CAEzB,IAAA,IAASC,CAAAA,CAAI,CAAA,CAAGA,CAAAA,CAAIE,CAAAA,CAAO,MAAA,CAAQF,IACjC,GAAIA,CAAAA,GAAME,CAAAA,CAAO,MAAA,CAAS,CAAA,CAExBH,CAAAA,CAAO,IAAA,CAAK,IAAIX,CAAAA,CAAMkB,CAAAA,CAAW,IAAA,CAAK,QAAQ,CAAC,CAAA,CAAA,KAC1C,CACL,IAAMC,CAAAA,CAAQ,IAAA,CAAK,KAAA,CAAO,IAAA,CAAK,KAAA,CAAQL,CAAAA,CAAOF,CAAC,CAAA,CAAKG,CAAK,CAAA,CACzDJ,CAAAA,CAAO,IAAA,CAAK,IAAIX,CAAAA,CAAMmB,CAAAA,CAAO,IAAA,CAAK,QAAQ,CAAC,CAAA,CAC3CD,CAAAA,EAAaC,EACf,CAGF,OAAOR,CACT,CAKA,MAAA,CAAOS,CAAAA,CAAyB,EAAC,CAAW,CAC1C,GAAM,CAAE,UAAA,CAAAC,CAAAA,CAAa,IAAA,CAAM,YAAA,CAAAC,CAAAA,CAAe,IAAA,CAAM,cAAA,CAAAC,CAAe,CAAA,CAAIH,CAAAA,CAE7DI,CAAAA,CAAU,IAAA,CAAK,SAAA,EAAU,CACzBC,CAAAA,CAAW,IAAA,CAAK,GAAA,CAAID,CAAO,CAAA,CAC3BE,CAAAA,CAAaF,CAAAA,CAAU,CAAA,CAGzBG,CAAAA,CACJ,GAAIL,CAAAA,EAAgB,IAAA,CAAK,QAAA,CAAS,QAAA,CAAW,CAAA,CAAG,CAC9C,GAAM,CAACM,CAAAA,CAASC,CAAO,CAAA,CAAIJ,CAAAA,CAAS,OAAA,CAAQ,IAAA,CAAK,QAAA,CAAS,QAAQ,CAAA,CAAE,KAAA,CAAM,GAAG,CAAA,CAE7EE,CAAAA,CAAY,CAAA,EADS,IAAA,CAAK,aAAA,CAAcC,CAAO,CACpB,GAAG,IAAA,CAAK,QAAA,CAAS,gBAAgB,CAAA,EAAGC,CAAO,CAAA,EACxE,CAAA,KACEF,CAAAA,CAAY,IAAA,CAAK,aAAA,CAAc,IAAA,CAAK,KAAA,CAAMF,CAAQ,CAAA,CAAE,QAAA,EAAU,CAAA,CAShE,GALIC,CAAAA,GACFC,CAAAA,CAAY,CAAA,CAAA,EAAIA,CAAS,CAAA,CAAA,CAAA,CAIvBN,CAAAA,CAAY,CACd,IAAMS,CAAAA,CAAMP,CAAAA,EAAkB,IAAA,CAAK,QAAA,CAAS,cAAA,CACtCQ,CAAAA,CAAQ,KAAK,QAAA,CAAS,aAAA,CAAgB,GAAA,CAAM,EAAA,CAE9CD,CAAAA,GAAQ,QAAA,CACVH,CAAAA,CAAY,CAAA,EAAG,IAAA,CAAK,QAAA,CAAS,MAAM,CAAA,EAAGI,CAAK,CAAA,EAAGJ,CAAS,CAAA,CAAA,CAEvDA,CAAAA,CAAY,CAAA,EAAGA,CAAS,CAAA,EAAGI,CAAK,CAAA,EAAG,IAAA,CAAK,QAAA,CAAS,MAAM,CAAA,EAE3D,CAEA,OAAOJ,CACT,CAKA,SAAA,EAAoB,CAClB,OAAO,IAAA,CAAK,KAAA,CAAQ,IAAA,CAAK,GAAA,CAAI,EAAA,CAAI,IAAA,CAAK,QAAA,CAAS,QAAQ,CACzD,CAKA,MAAA,CAAOtB,CAAAA,CAAwB,CAC7B,OAAO,IAAA,CAAK,KAAA,GAAUA,CAAAA,CAAM,KAAA,EAAS,IAAA,CAAK,QAAA,CAAS,IAAA,GAASA,CAAAA,CAAM,QAAA,CAAS,IAC7E,CAKA,WAAA,CAAYA,CAAAA,CAAwB,CAClC,OAAA,IAAA,CAAK,kBAAA,CAAmBA,CAAK,CAAA,CACtB,KAAK,KAAA,CAAQA,CAAAA,CAAM,KAC5B,CAKA,QAAA,CAASA,CAAAA,CAAwB,CAC/B,OAAA,IAAA,CAAK,kBAAA,CAAmBA,CAAK,CAAA,CACtB,IAAA,CAAK,KAAA,CAAQA,CAAAA,CAAM,KAC5B,CAKA,kBAAA,CAAmBA,CAAAA,CAAwB,CACzC,OAAA,IAAA,CAAK,kBAAA,CAAmBA,CAAK,CAAA,CACtB,IAAA,CAAK,KAAA,EAASA,CAAAA,CAAM,KAC7B,CAKA,eAAA,CAAgBA,CAAAA,CAAwB,CACtC,OAAA,IAAA,CAAK,mBAAmBA,CAAK,CAAA,CACtB,IAAA,CAAK,KAAA,EAASA,CAAAA,CAAM,KAC7B,CAKA,MAAA,EAAkB,CAChB,OAAO,IAAA,CAAK,KAAA,GAAU,CACxB,CAKA,UAAA,EAAsB,CACpB,OAAO,IAAA,CAAK,KAAA,CAAQ,CACtB,CAKA,UAAA,EAAsB,CACpB,OAAO,IAAA,CAAK,KAAA,CAAQ,CACtB,CAKA,GAAA,EAAa,CACX,OAAO,IAAIL,EAAM,IAAA,CAAK,GAAA,CAAI,IAAA,CAAK,KAAK,CAAA,CAAG,IAAA,CAAK,QAAQ,CACtD,CAKA,MAAA,EAAgB,CACd,OAAO,IAAIA,CAAAA,CAAM,CAAC,IAAA,CAAK,KAAA,CAAO,IAAA,CAAK,QAAQ,CAC7C,CAMA,UAAA,CAAWgC,CAAAA,CAAwB,CACjC,OAAO,IAAIhC,CAAAA,CAAM,IAAA,CAAK,KAAA,CAAO,IAAA,CAAK,KAAA,CAAQgC,CAAAA,CAAW,GAAG,CAAA,CAAG,IAAA,CAAK,QAAQ,CAC1E,CAMA,aAAA,CAAcA,CAAAA,CAAwB,CACpC,OAAO,IAAA,CAAK,GAAA,CAAI,IAAA,CAAK,UAAA,CAAWA,CAAO,CAAC,CAC1C,CAMA,kBAAA,CAAmBA,CAAAA,CAAwB,CACzC,OAAO,IAAA,CAAK,QAAA,CAAS,IAAA,CAAK,UAAA,CAAWA,CAAO,CAAC,CAC/C,CAKA,GAAA,CAAI3B,CAAAA,CAAsB,CACxB,YAAK,kBAAA,CAAmBA,CAAK,CAAA,CACtB,IAAA,CAAK,KAAA,EAASA,CAAAA,CAAM,KAAA,CAAQ,IAAA,CAAO,IAAIL,CAAAA,CAAMK,CAAAA,CAAM,KAAA,CAAO,IAAA,CAAK,QAAQ,CAChF,CAKA,GAAA,CAAIA,CAAAA,CAAsB,CACxB,OAAA,IAAA,CAAK,kBAAA,CAAmBA,CAAK,CAAA,CACtB,IAAA,CAAK,KAAA,EAASA,CAAAA,CAAM,KAAA,CAAQ,IAAA,CAAO,IAAIL,CAAAA,CAAMK,CAAAA,CAAM,KAAA,CAAO,KAAK,QAAQ,CAChF,CAKA,KAAA,CAAM4B,CAAAA,CAAkBC,CAAAA,CAAyB,CAC/C,OAAO,IAAA,CAAK,GAAA,CAAID,CAAQ,CAAA,CAAE,GAAA,CAAIC,CAAQ,CACxC,CAKA,OAAA,EAAkB,CAChB,OAAO,IAAA,CAAK,KACd,CAKA,SAAA,CAAUC,CAAAA,CAAaC,CAAAA,CAAsB,CAC3C,OAAA,IAAA,CAAK,kBAAA,CAAmBD,CAAG,CAAA,CAC3B,IAAA,CAAK,kBAAA,CAAmBC,CAAG,CAAA,CACpB,IAAA,CAAK,KAAA,EAASD,CAAAA,CAAI,KAAA,EAAS,IAAA,CAAK,KAAA,EAASC,CAAAA,CAAI,KACtD,CAKA,OAAO,GAAA,CAAIC,CAAAA,CAAyB,CAClC,GAAIA,CAAAA,CAAO,MAAA,GAAW,CAAA,CACpB,MAAM,IAAI,KAAA,CAAM,wBAAwB,CAAA,CAE1C,IAAMnC,CAAAA,CAAWmC,CAAAA,CAAO,CAAC,CAAA,CAAE,QAAA,CACrBtB,CAAAA,CAAQsB,CAAAA,CAAO,MAAA,CAAO,CAACrB,CAAAA,CAAKsB,CAAAA,GAAM,CACtC,GAAIA,CAAAA,CAAE,QAAA,CAAS,IAAA,GAASpC,CAAAA,CAAS,IAAA,CAC/B,MAAM,IAAI,KAAA,CAAM,iCAAiC,CAAA,CAEnD,OAAOc,CAAAA,CAAMsB,CAAAA,CAAE,KACjB,CAAA,CAAG,CAAC,CAAA,CACJ,OAAO,IAAItC,CAAAA,CAAMe,CAAAA,CAAOb,CAAQ,CAClC,CAKA,OAAO,OAAA,CAAQmC,CAAAA,CAAyB,CACtC,GAAIA,CAAAA,CAAO,MAAA,GAAW,CAAA,CACpB,MAAM,IAAI,KAAA,CAAM,mCAAmC,CAAA,CAErD,OAAOA,CAAAA,CAAO,MAAA,CAAO,CAACF,CAAAA,CAAKG,CAAAA,GAAOA,CAAAA,CAAE,KAAA,CAAQH,CAAAA,CAAI,KAAA,CAAQG,CAAAA,CAAIH,CAAI,CAClE,CAKA,OAAO,OAAA,CAAQE,CAAAA,CAAyB,CACtC,GAAIA,CAAAA,CAAO,MAAA,GAAW,CAAA,CACpB,MAAM,IAAI,MAAM,mCAAmC,CAAA,CAErD,OAAOA,CAAAA,CAAO,MAAA,CAAO,CAACD,CAAAA,CAAKE,CAAAA,GAAOA,CAAAA,CAAE,KAAA,CAAQF,CAAAA,CAAI,KAAA,CAAQE,CAAAA,CAAIF,CAAI,CAClE,CAKA,OAAO,OAAA,CAAQC,CAAAA,CAAyB,CACtC,GAAIA,CAAAA,CAAO,MAAA,GAAW,CAAA,CACpB,MAAM,IAAI,KAAA,CAAM,yCAAyC,CAAA,CAG3D,OADcrC,CAAAA,CAAM,GAAA,CAAIqC,CAAM,CAAA,CACjB,MAAA,CAAOA,CAAAA,CAAO,MAAM,CACnC,CAKA,MAAA,EAA8C,CAC5C,OAAO,CACL,KAAA,CAAO,IAAA,CAAK,KAAA,CACZ,QAAA,CAAU,IAAA,CAAK,QAAA,CAAS,IAC1B,CACF,CAKA,QAAA,EAAmB,CACjB,OAAO,IAAA,CAAK,MAAA,EACd,CAEQ,aAAA,CAAcE,CAAAA,CAAwB,CAC5C,IAAM/B,CAAAA,CAAkB,GACpBU,CAAAA,CAAYqB,CAAAA,CAEhB,KAAOrB,CAAAA,CAAU,MAAA,CAAS,CAAA,EACxBV,CAAAA,CAAM,OAAA,CAAQU,CAAAA,CAAU,KAAA,CAAM,EAAE,CAAC,CAAA,CACjCA,CAAAA,CAAYA,CAAAA,CAAU,KAAA,CAAM,CAAA,CAAG,EAAE,CAAA,CAGnC,OAAIA,CAAAA,EACFV,CAAAA,CAAM,OAAA,CAAQU,CAAS,CAAA,CAGlBV,CAAAA,CAAM,IAAA,CAAK,IAAA,CAAK,QAAA,CAAS,kBAAkB,CACpD,CAEQ,mBAAmBH,CAAAA,CAAqB,CAC9C,GAAI,IAAA,CAAK,QAAA,CAAS,IAAA,GAASA,CAAAA,CAAM,QAAA,CAAS,IAAA,CACxC,MAAM,IAAI,KAAA,CACR,CAAA,oDAAA,EAAuD,IAAA,CAAK,QAAA,CAAS,IAAI,CAAA,KAAA,EAAQA,CAAAA,CAAM,QAAA,CAAS,IAAI,CAAA,CACtG,CAEJ,CACF,EC3YO,IAAMmC,CAAAA,CAAgB,CAC3B,IAAA,CAAM,KAAA,CACN,MAAA,CAAQ,GAAA,CACR,QAAA,CAAU,EACV,kBAAA,CAAoB,GAAA,CACpB,gBAAA,CAAkB,GAAA,CAClB,cAAA,CAAgB,QAAA,CAChB,aAAA,CAAe,IACjB,CAAA,CAMaC,CAAAA,CAA4B,CACvC,GAAGD,CAAAA,CACH,QAAA,CAAU,CACZ,ECjBO,IAAME,CAAAA,CAAgB,CAC3B,IAAA,CAAM,KAAA,CACN,MAAA,CAAQ,GAAA,CACR,QAAA,CAAU,CAAA,CACV,kBAAA,CAAoB,GAAA,CACpB,gBAAA,CAAkB,GAAA,CAClB,cAAA,CAAgB,QAAA,CAChB,aAAA,CAAe,KACjB,ECRO,IAAMC,CAAAA,CAAgB,CAC3B,IAAA,CAAM,KAAA,CACN,MAAA,CAAQ,GAAA,CACR,QAAA,CAAU,CAAA,CACV,kBAAA,CAAoB,GAAA,CACpB,gBAAA,CAAkB,GAAA,CAClB,cAAA,CAAgB,QAAA,CAChB,aAAA,CAAe,IACjB,ECRO,IAAMC,CAAAA,CAAgB,CAC3B,IAAA,CAAM,KAAA,CACN,MAAA,CAAQ,IAAA,CACR,QAAA,CAAU,CAAA,CACV,kBAAA,CAAoB,GAAA,CACpB,gBAAA,CAAkB,GAAA,CAClB,eAAgB,QAAA,CAChB,aAAA,CAAe,IACjB,ECRO,IAAMC,CAAAA,CAAgB,CAC3B,IAAA,CAAM,KAAA,CACN,MAAA,CAAQ,GAAA,CACR,QAAA,CAAU,CAAA,CACV,kBAAA,CAAoB,GAAA,CACpB,gBAAA,CAAkB,GAAA,CAClB,cAAA,CAAgB,QAAA,CAChB,aAAA,CAAe,KACjB,ECPO,IAAMC,CAAAA,CAAgB,CAC3B,IAAA,CAAM,KAAA,CACN,MAAA,CAAQ,GAAA,CACR,QAAA,CAAU,CAAA,CACV,kBAAA,CAAoB,IACpB,gBAAA,CAAkB,GAAA,CAClB,cAAA,CAAgB,QAAA,CAChB,aAAA,CAAe,IACjB,CAAA,CAMaC,CAAAA,CAAyB,CACpC,GAAGD,CAAAA,CACH,QAAA,CAAU,CACZ,EClBO,IAAME,CAAAA,CAAgB,CAC3B,IAAA,CAAM,KAAA,CACN,MAAA,CAAQ,IAAA,CACR,QAAA,CAAU,CAAA,CACV,kBAAA,CAAoB,GAAA,CACpB,gBAAA,CAAkB,GAAA,CAClB,cAAA,CAAgB,QAAA,CAChB,aAAA,CAAe,IACjB,MCRaC,CAAAA,CAAgB,CAC3B,IAAA,CAAM,KAAA,CACN,MAAA,CAAQ,GAAA,CACR,QAAA,CAAU,CAAA,CACV,kBAAA,CAAoB,GAAA,CACpB,gBAAA,CAAkB,GAAA,CAClB,cAAA,CAAgB,QAAA,CAChB,aAAA,CAAe,IACjB,ECRO,IAAMC,CAAAA,CAAgB,CAC3B,IAAA,CAAM,KAAA,CACN,MAAA,CAAQ,QAAA,CACR,QAAA,CAAU,CAAA,CACV,kBAAA,CAAoB,GAAA,CACpB,gBAAA,CAAkB,GAAA,CAClB,cAAA,CAAgB,OAAA,CAChB,cAAe,IACjB","file":"index.cjs","sourcesContent":["import type { Currency, FormatOptions, IMoney } from './types.js';\n\n/**\n * Immutable Money class that uses integer arithmetic for precision\n */\nexport class Money implements IMoney {\n readonly cents: number;\n readonly currency: Currency;\n\n private constructor(cents: number, currency: Currency) {\n if (!Number.isInteger(cents)) {\n throw new Error('Money must be created with an integer number of cents');\n }\n this.cents = cents;\n this.currency = currency;\n Object.freeze(this);\n }\n\n /**\n * Create money from cents (smallest unit)\n */\n static fromCents(cents: number, currency: Currency): Money {\n return new Money(Math.round(cents), currency);\n }\n\n /**\n * Create money from a decimal amount\n * @example Money.fromDecimal(100.50, USD) creates $100.50\n */\n static fromDecimal(amount: number, currency: Currency): Money {\n const multiplier = Math.pow(10, currency.decimals);\n const cents = Math.round(amount * multiplier);\n return new Money(cents, currency);\n }\n\n /**\n * Create zero money\n */\n static zero(currency: Currency): Money {\n return new Money(0, currency);\n }\n\n /**\n * Add another money value (must be same currency)\n */\n add(other: IMoney): Money {\n this.assertSameCurrency(other);\n return new Money(this.cents + other.cents, this.currency);\n }\n\n /**\n * Subtract another money value (must be same currency)\n */\n subtract(other: IMoney): Money {\n this.assertSameCurrency(other);\n return new Money(this.cents - other.cents, this.currency);\n }\n\n /**\n * Multiply by a factor (rounds to nearest cent)\n */\n multiply(factor: number): Money {\n return new Money(Math.round(this.cents * factor), this.currency);\n }\n\n /**\n * Divide by a divisor (rounds to nearest cent)\n */\n divide(divisor: number): Money {\n if (divisor === 0) {\n throw new Error('Cannot divide by zero');\n }\n return new Money(Math.round(this.cents / divisor), this.currency);\n }\n\n /**\n * Distribute money evenly without losing cents\n * The remainder is distributed to the first parts\n * @example $100 / 3 = [$33.34, $33.33, $33.33]\n */\n distribute(parts: number): Money[] {\n if (parts <= 0 || !Number.isInteger(parts)) {\n throw new Error('Parts must be a positive integer');\n }\n\n const quotient = Math.floor(this.cents / parts);\n const remainder = this.cents % parts;\n\n const result: Money[] = [];\n for (let i = 0; i < parts; i++) {\n // Add 1 cent to the first 'remainder' parts\n const extra = i < remainder ? 1 : 0;\n result.push(new Money(quotient + extra, this.currency));\n }\n\n return result;\n }\n\n /**\n * Distribute money according to ratios\n * @example $100 with ratios [1, 2, 2] = [$20, $40, $40]\n */\n distributeByRatios(ratios: number[]): Money[] {\n if (ratios.length === 0) {\n throw new Error('Ratios array cannot be empty');\n }\n\n const total = ratios.reduce((sum, r) => sum + r, 0);\n if (total <= 0) {\n throw new Error('Sum of ratios must be positive');\n }\n\n let remaining = this.cents;\n const result: Money[] = [];\n\n for (let i = 0; i < ratios.length; i++) {\n if (i === ratios.length - 1) {\n // Last part gets whatever is remaining to avoid rounding errors\n result.push(new Money(remaining, this.currency));\n } else {\n const share = Math.round((this.cents * ratios[i]) / total);\n result.push(new Money(share, this.currency));\n remaining -= share;\n }\n }\n\n return result;\n }\n\n /**\n * Format money for display\n */\n format(options: FormatOptions = {}): string {\n const { showSymbol = true, showDecimals = true, symbolPosition } = options;\n\n const decimal = this.toDecimal();\n const absValue = Math.abs(decimal);\n const isNegative = decimal < 0;\n\n // Format the number\n let formatted: string;\n if (showDecimals && this.currency.decimals > 0) {\n const [intPart, decPart] = absValue.toFixed(this.currency.decimals).split('.');\n const intFormatted = this.formatInteger(intPart);\n formatted = `${intFormatted}${this.currency.decimalSeparator}${decPart}`;\n } else {\n formatted = this.formatInteger(Math.round(absValue).toString());\n }\n\n // Add negative sign\n if (isNegative) {\n formatted = `-${formatted}`;\n }\n\n // Add symbol\n if (showSymbol) {\n const pos = symbolPosition ?? this.currency.symbolPosition;\n const space = this.currency.symbolSpacing ? ' ' : '';\n\n if (pos === 'before') {\n formatted = `${this.currency.symbol}${space}${formatted}`;\n } else {\n formatted = `${formatted}${space}${this.currency.symbol}`;\n }\n }\n\n return formatted;\n }\n\n /**\n * Get the decimal representation\n */\n toDecimal(): number {\n return this.cents / Math.pow(10, this.currency.decimals);\n }\n\n /**\n * Check equality with another money value\n */\n equals(other: IMoney): boolean {\n return this.cents === other.cents && this.currency.code === other.currency.code;\n }\n\n /**\n * Check if greater than another money value\n */\n greaterThan(other: IMoney): boolean {\n this.assertSameCurrency(other);\n return this.cents > other.cents;\n }\n\n /**\n * Check if less than another money value\n */\n lessThan(other: IMoney): boolean {\n this.assertSameCurrency(other);\n return this.cents < other.cents;\n }\n\n /**\n * Check if greater than or equal\n */\n greaterThanOrEqual(other: IMoney): boolean {\n this.assertSameCurrency(other);\n return this.cents >= other.cents;\n }\n\n /**\n * Check if less than or equal\n */\n lessThanOrEqual(other: IMoney): boolean {\n this.assertSameCurrency(other);\n return this.cents <= other.cents;\n }\n\n /**\n * Check if zero\n */\n isZero(): boolean {\n return this.cents === 0;\n }\n\n /**\n * Check if positive\n */\n isPositive(): boolean {\n return this.cents > 0;\n }\n\n /**\n * Check if negative\n */\n isNegative(): boolean {\n return this.cents < 0;\n }\n\n /**\n * Get absolute value\n */\n abs(): Money {\n return new Money(Math.abs(this.cents), this.currency);\n }\n\n /**\n * Negate the value\n */\n negate(): Money {\n return new Money(-this.cents, this.currency);\n }\n\n /**\n * Calculate a percentage of this money\n * @example money.percentage(10) returns 10% of the amount\n */\n percentage(percent: number): Money {\n return new Money(Math.round((this.cents * percent) / 100), this.currency);\n }\n\n /**\n * Add a percentage to this money\n * @example money.addPercentage(19) adds 19% (like tax)\n */\n addPercentage(percent: number): Money {\n return this.add(this.percentage(percent));\n }\n\n /**\n * Subtract a percentage from this money\n * @example money.subtractPercentage(10) subtracts 10% (like discount)\n */\n subtractPercentage(percent: number): Money {\n return this.subtract(this.percentage(percent));\n }\n\n /**\n * Get the minimum of this and another money value\n */\n min(other: IMoney): Money {\n this.assertSameCurrency(other);\n return this.cents <= other.cents ? this : new Money(other.cents, this.currency);\n }\n\n /**\n * Get the maximum of this and another money value\n */\n max(other: IMoney): Money {\n this.assertSameCurrency(other);\n return this.cents >= other.cents ? this : new Money(other.cents, this.currency);\n }\n\n /**\n * Clamp this money between a minimum and maximum\n */\n clamp(minValue: IMoney, maxValue: IMoney): Money {\n return this.max(minValue).min(maxValue);\n }\n\n /**\n * Get cents (smallest unit)\n */\n toCents(): number {\n return this.cents;\n }\n\n /**\n * Check if within a range (inclusive)\n */\n isBetween(min: IMoney, max: IMoney): boolean {\n this.assertSameCurrency(min);\n this.assertSameCurrency(max);\n return this.cents >= min.cents && this.cents <= max.cents;\n }\n\n /**\n * Sum multiple money values\n */\n static sum(values: IMoney[]): Money {\n if (values.length === 0) {\n throw new Error('Cannot sum empty array');\n }\n const currency = values[0].currency;\n const total = values.reduce((sum, m) => {\n if (m.currency.code !== currency.code) {\n throw new Error('Cannot sum different currencies');\n }\n return sum + m.cents;\n }, 0);\n return new Money(total, currency);\n }\n\n /**\n * Get the minimum from an array of money values\n */\n static minimum(values: IMoney[]): Money {\n if (values.length === 0) {\n throw new Error('Cannot get minimum of empty array');\n }\n return values.reduce((min, m) => (m.cents < min.cents ? m : min)) as Money;\n }\n\n /**\n * Get the maximum from an array of money values\n */\n static maximum(values: IMoney[]): Money {\n if (values.length === 0) {\n throw new Error('Cannot get maximum of empty array');\n }\n return values.reduce((max, m) => (m.cents > max.cents ? m : max)) as Money;\n }\n\n /**\n * Calculate the average of money values\n */\n static average(values: IMoney[]): Money {\n if (values.length === 0) {\n throw new Error('Cannot calculate average of empty array');\n }\n const total = Money.sum(values);\n return total.divide(values.length);\n }\n\n /**\n * Convert to JSON-serializable object\n */\n toJSON(): { cents: number; currency: string } {\n return {\n cents: this.cents,\n currency: this.currency.code,\n };\n }\n\n /**\n * String representation\n */\n toString(): string {\n return this.format();\n }\n\n private formatInteger(intStr: string): string {\n const parts: string[] = [];\n let remaining = intStr;\n\n while (remaining.length > 3) {\n parts.unshift(remaining.slice(-3));\n remaining = remaining.slice(0, -3);\n }\n\n if (remaining) {\n parts.unshift(remaining);\n }\n\n return parts.join(this.currency.thousandsSeparator);\n }\n\n private assertSameCurrency(other: IMoney): void {\n if (this.currency.code !== other.currency.code) {\n throw new Error(\n `Cannot perform operation with different currencies: ${this.currency.code} and ${other.currency.code}`\n );\n }\n }\n}\n","import type { Currency } from '../core/types.js';\n\n/**\n * Colombian Peso (COP)\n * Format: $ 1.000,00\n */\nexport const COP: Currency = {\n code: 'COP',\n symbol: '$',\n decimals: 2,\n thousandsSeparator: '.',\n decimalSeparator: ',',\n symbolPosition: 'before',\n symbolSpacing: true,\n};\n\n/**\n * Colombian Peso without decimals (common usage)\n * Format: $ 1.000\n */\nexport const COP_NO_DECIMALS: Currency = {\n ...COP,\n decimals: 0,\n};\n","import type { Currency } from '../core/types.js';\n\n/**\n * Mexican Peso (MXN)\n * Format: $1,000.00\n */\nexport const MXN: Currency = {\n code: 'MXN',\n symbol: '$',\n decimals: 2,\n thousandsSeparator: ',',\n decimalSeparator: '.',\n symbolPosition: 'before',\n symbolSpacing: false,\n};\n","import type { Currency } from '../core/types.js';\n\n/**\n * Argentine Peso (ARS)\n * Format: $ 1.000,00\n */\nexport const ARS: Currency = {\n code: 'ARS',\n symbol: '$',\n decimals: 2,\n thousandsSeparator: '.',\n decimalSeparator: ',',\n symbolPosition: 'before',\n symbolSpacing: true,\n};\n","import type { Currency } from '../core/types.js';\n\n/**\n * Brazilian Real (BRL)\n * Format: R$ 1.000,00\n */\nexport const BRL: Currency = {\n code: 'BRL',\n symbol: 'R$',\n decimals: 2,\n thousandsSeparator: '.',\n decimalSeparator: ',',\n symbolPosition: 'before',\n symbolSpacing: true,\n};\n","import type { Currency } from '../core/types.js';\n\n/**\n * US Dollar (USD)\n * Format: $1,000.00\n */\nexport const USD: Currency = {\n code: 'USD',\n symbol: '$',\n decimals: 2,\n thousandsSeparator: ',',\n decimalSeparator: '.',\n symbolPosition: 'before',\n symbolSpacing: false,\n};\n","import type { Currency } from '../core/types.js';\n\n/**\n * Chilean Peso (CLP)\n * Format: $ 1.500\n * Note: CLP doesn't use decimal places in common usage\n */\nexport const CLP: Currency = {\n code: 'CLP',\n symbol: '$',\n decimals: 0,\n thousandsSeparator: '.',\n decimalSeparator: ',',\n symbolPosition: 'before',\n symbolSpacing: true,\n};\n\n/**\n * Chilean Peso with decimals (for precise calculations)\n * Format: $ 1.500,00\n */\nexport const CLP_DECIMALS: Currency = {\n ...CLP,\n decimals: 2,\n};\n","import type { Currency } from '../core/types.js';\n\n/**\n * Peruvian Sol (PEN)\n * Format: S/ 1,500.00\n */\nexport const PEN: Currency = {\n code: 'PEN',\n symbol: 'S/',\n decimals: 2,\n thousandsSeparator: ',',\n decimalSeparator: '.',\n symbolPosition: 'before',\n symbolSpacing: true,\n};\n","import type { Currency } from '../core/types.js';\n\n/**\n * Uruguayan Peso (UYU)\n * Format: $ 1.500,00\n */\nexport const UYU: Currency = {\n code: 'UYU',\n symbol: '$',\n decimals: 2,\n thousandsSeparator: '.',\n decimalSeparator: ',',\n symbolPosition: 'before',\n symbolSpacing: true,\n};\n","import type { Currency } from '../core/types.js';\n\n/**\n * Euro (EUR)\n * Format: 1.500,00 €\n */\nexport const EUR: Currency = {\n code: 'EUR',\n symbol: '€',\n decimals: 2,\n thousandsSeparator: '.',\n decimalSeparator: ',',\n symbolPosition: 'after',\n symbolSpacing: true,\n};\n"]}
1
+ {"version":3,"sources":["../src/core/money.ts","../src/locales/co.ts","../src/locales/mx.ts","../src/locales/ar.ts","../src/locales/br.ts","../src/locales/us.ts","../src/locales/cl.ts","../src/locales/pe.ts","../src/locales/uy.ts","../src/locales/eu.ts"],"names":["Money","_Money","cents","currency","amount","multiplier","value","cleanValue","escapeRegex","str","thousandsRegex","decimalAmount","other","factor","divisor","parts","quotient","remainder","result","i","extra","ratios","total","sum","r","remaining","share","options","showSymbol","showDecimals","symbolPosition","decimal","absValue","isNegative","formatted","intPart","decPart","pos","space","percent","minValue","maxValue","min","max","values","m","intStr","COP","COP_NO_DECIMALS","MXN","ARS","BRL","USD","CLP","CLP_DECIMALS","PEN","UYU","EUR"],"mappings":"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","file":"index.cjs","sourcesContent":["import type { Currency, FormatOptions, IMoney } from './types.js';\n\n/**\n * Immutable Money class that uses integer arithmetic for precision\n */\nexport class Money implements IMoney {\n readonly cents: number;\n readonly currency: Currency;\n\n private constructor(cents: number, currency: Currency) {\n if (!Number.isInteger(cents)) {\n throw new Error('Money must be created with an integer number of cents');\n }\n this.cents = cents;\n this.currency = currency;\n Object.freeze(this);\n }\n\n /**\n * Create money from cents (smallest unit)\n */\n static fromCents(cents: number, currency: Currency): Money {\n return new Money(Math.round(cents), currency);\n }\n\n /**\n * Create money from a decimal amount\n * @example Money.fromDecimal(100.50, USD) creates $100.50\n */\n static fromDecimal(amount: number, currency: Currency): Money {\n const multiplier = Math.pow(10, currency.decimals);\n const cents = Math.round(amount * multiplier);\n return new Money(cents, currency);\n }\n\n /**\n * Create money from a formatted string\n * @example Money.fromString(\"$ 1.500,50\", ARS) creates $1,500.50\n */\n static fromString(value: string, currency: Currency): Money {\n let cleanValue = value.replace(currency.symbol, '').trim();\n\n const escapeRegex = (str: string) => str.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n\n if (currency.thousandsSeparator) {\n const thousandsRegex = new RegExp(escapeRegex(currency.thousandsSeparator), 'g');\n cleanValue = cleanValue.replace(thousandsRegex, '');\n }\n\n if (currency.decimalSeparator && currency.decimalSeparator !== '.') {\n cleanValue = cleanValue.replace(currency.decimalSeparator, '.');\n }\n\n cleanValue = cleanValue.replace(/\\s+/g, '');\n\n const decimalAmount = parseFloat(cleanValue);\n\n if (isNaN(decimalAmount)) {\n throw new Error(`Cannot parse \"${value}\" as money`);\n }\n\n return Money.fromDecimal(decimalAmount, currency);\n }\n\n /**\n * Create zero money\n */\n static zero(currency: Currency): Money {\n return new Money(0, currency);\n }\n\n /**\n * Add another money value (must be same currency)\n */\n add(other: IMoney): Money {\n this.assertSameCurrency(other);\n return new Money(this.cents + other.cents, this.currency);\n }\n\n /**\n * Subtract another money value (must be same currency)\n */\n subtract(other: IMoney): Money {\n this.assertSameCurrency(other);\n return new Money(this.cents - other.cents, this.currency);\n }\n\n /**\n * Multiply by a factor (rounds to nearest cent)\n */\n multiply(factor: number): Money {\n return new Money(Math.round(this.cents * factor), this.currency);\n }\n\n /**\n * Divide by a divisor (rounds to nearest cent)\n */\n divide(divisor: number): Money {\n if (divisor === 0) {\n throw new Error('Cannot divide by zero');\n }\n return new Money(Math.round(this.cents / divisor), this.currency);\n }\n\n /**\n * Distribute money evenly without losing cents\n * The remainder is distributed to the first parts\n * @example $100 / 3 = [$33.34, $33.33, $33.33]\n */\n distribute(parts: number): Money[] {\n if (parts <= 0 || !Number.isInteger(parts)) {\n throw new Error('Parts must be a positive integer');\n }\n\n const quotient = Math.floor(this.cents / parts);\n const remainder = this.cents % parts;\n\n const result: Money[] = [];\n for (let i = 0; i < parts; i++) {\n // Add 1 cent to the first 'remainder' parts\n const extra = i < remainder ? 1 : 0;\n result.push(new Money(quotient + extra, this.currency));\n }\n\n return result;\n }\n\n /**\n * Distribute money according to ratios\n * @example $100 with ratios [1, 2, 2] = [$20, $40, $40]\n */\n distributeByRatios(ratios: number[]): Money[] {\n if (ratios.length === 0) {\n throw new Error('Ratios array cannot be empty');\n }\n\n const total = ratios.reduce((sum, r) => sum + r, 0);\n if (total <= 0) {\n throw new Error('Sum of ratios must be positive');\n }\n\n let remaining = this.cents;\n const result: Money[] = [];\n\n for (let i = 0; i < ratios.length; i++) {\n if (i === ratios.length - 1) {\n // Last part gets whatever is remaining to avoid rounding errors\n result.push(new Money(remaining, this.currency));\n } else {\n const share = Math.round((this.cents * ratios[i]) / total);\n result.push(new Money(share, this.currency));\n remaining -= share;\n }\n }\n\n return result;\n }\n\n /**\n * Format money for display\n */\n format(options: FormatOptions = {}): string {\n const { showSymbol = true, showDecimals = true, symbolPosition } = options;\n\n const decimal = this.toDecimal();\n const absValue = Math.abs(decimal);\n const isNegative = decimal < 0;\n\n // Format the number\n let formatted: string;\n if (showDecimals && this.currency.decimals > 0) {\n const [intPart, decPart] = absValue.toFixed(this.currency.decimals).split('.');\n const intFormatted = this.formatInteger(intPart);\n formatted = `${intFormatted}${this.currency.decimalSeparator}${decPart}`;\n } else {\n formatted = this.formatInteger(Math.round(absValue).toString());\n }\n\n // Add negative sign\n if (isNegative) {\n formatted = `-${formatted}`;\n }\n\n // Add symbol\n if (showSymbol) {\n const pos = symbolPosition ?? this.currency.symbolPosition;\n const space = this.currency.symbolSpacing ? ' ' : '';\n\n if (pos === 'before') {\n formatted = `${this.currency.symbol}${space}${formatted}`;\n } else {\n formatted = `${formatted}${space}${this.currency.symbol}`;\n }\n }\n\n return formatted;\n }\n\n /**\n * Get the decimal representation\n */\n toDecimal(): number {\n return this.cents / Math.pow(10, this.currency.decimals);\n }\n\n /**\n * Check equality with another money value\n */\n equals(other: IMoney): boolean {\n return this.cents === other.cents && this.currency.code === other.currency.code;\n }\n\n /**\n * Check if greater than another money value\n */\n greaterThan(other: IMoney): boolean {\n this.assertSameCurrency(other);\n return this.cents > other.cents;\n }\n\n /**\n * Check if less than another money value\n */\n lessThan(other: IMoney): boolean {\n this.assertSameCurrency(other);\n return this.cents < other.cents;\n }\n\n /**\n * Check if greater than or equal\n */\n greaterThanOrEqual(other: IMoney): boolean {\n this.assertSameCurrency(other);\n return this.cents >= other.cents;\n }\n\n /**\n * Check if less than or equal\n */\n lessThanOrEqual(other: IMoney): boolean {\n this.assertSameCurrency(other);\n return this.cents <= other.cents;\n }\n\n /**\n * Check if zero\n */\n isZero(): boolean {\n return this.cents === 0;\n }\n\n /**\n * Check if positive\n */\n isPositive(): boolean {\n return this.cents > 0;\n }\n\n /**\n * Check if negative\n */\n isNegative(): boolean {\n return this.cents < 0;\n }\n\n /**\n * Get absolute value\n */\n abs(): Money {\n return new Money(Math.abs(this.cents), this.currency);\n }\n\n /**\n * Negate the value\n */\n negate(): Money {\n return new Money(-this.cents, this.currency);\n }\n\n /**\n * Calculate a percentage of this money\n * @example money.percentage(10) returns 10% of the amount\n */\n percentage(percent: number): Money {\n return new Money(Math.round((this.cents * percent) / 100), this.currency);\n }\n\n /**\n * Add a percentage to this money\n * @example money.addPercentage(19) adds 19% (like tax)\n */\n addPercentage(percent: number): Money {\n return this.add(this.percentage(percent));\n }\n\n /**\n * Subtract a percentage from this money\n * @example money.subtractPercentage(10) subtracts 10% (like discount)\n */\n subtractPercentage(percent: number): Money {\n return this.subtract(this.percentage(percent));\n }\n\n /**\n * Get the minimum of this and another money value\n */\n min(other: IMoney): Money {\n this.assertSameCurrency(other);\n return this.cents <= other.cents ? this : new Money(other.cents, this.currency);\n }\n\n /**\n * Get the maximum of this and another money value\n */\n max(other: IMoney): Money {\n this.assertSameCurrency(other);\n return this.cents >= other.cents ? this : new Money(other.cents, this.currency);\n }\n\n /**\n * Clamp this money between a minimum and maximum\n */\n clamp(minValue: IMoney, maxValue: IMoney): Money {\n return this.max(minValue).min(maxValue);\n }\n\n /**\n * Get cents (smallest unit)\n */\n toCents(): number {\n return this.cents;\n }\n\n /**\n * Check if within a range (inclusive)\n */\n isBetween(min: IMoney, max: IMoney): boolean {\n this.assertSameCurrency(min);\n this.assertSameCurrency(max);\n return this.cents >= min.cents && this.cents <= max.cents;\n }\n\n /**\n * Sum multiple money values\n */\n static sum(values: IMoney[]): Money {\n if (values.length === 0) {\n throw new Error('Cannot sum empty array');\n }\n const currency = values[0].currency;\n const total = values.reduce((sum, m) => {\n if (m.currency.code !== currency.code) {\n throw new Error('Cannot sum different currencies');\n }\n return sum + m.cents;\n }, 0);\n return new Money(total, currency);\n }\n\n /**\n * Get the minimum from an array of money values\n */\n static minimum(values: IMoney[]): Money {\n if (values.length === 0) {\n throw new Error('Cannot get minimum of empty array');\n }\n return values.reduce((min, m) => (m.cents < min.cents ? m : min)) as Money;\n }\n\n /**\n * Get the maximum from an array of money values\n */\n static maximum(values: IMoney[]): Money {\n if (values.length === 0) {\n throw new Error('Cannot get maximum of empty array');\n }\n return values.reduce((max, m) => (m.cents > max.cents ? m : max)) as Money;\n }\n\n /**\n * Calculate the average of money values\n */\n static average(values: IMoney[]): Money {\n if (values.length === 0) {\n throw new Error('Cannot calculate average of empty array');\n }\n const total = Money.sum(values);\n return total.divide(values.length);\n }\n\n /**\n * Convert to JSON-serializable object\n */\n toJSON(): { cents: number; currency: string } {\n return {\n cents: this.cents,\n currency: this.currency.code,\n };\n }\n\n /**\n * String representation\n */\n toString(): string {\n return this.format();\n }\n\n private formatInteger(intStr: string): string {\n const parts: string[] = [];\n let remaining = intStr;\n\n while (remaining.length > 3) {\n parts.unshift(remaining.slice(-3));\n remaining = remaining.slice(0, -3);\n }\n\n if (remaining) {\n parts.unshift(remaining);\n }\n\n return parts.join(this.currency.thousandsSeparator);\n }\n\n private assertSameCurrency(other: IMoney): void {\n if (this.currency.code !== other.currency.code) {\n throw new Error(\n `Cannot perform operation with different currencies: ${this.currency.code} and ${other.currency.code}`\n );\n }\n }\n}\n","import type { Currency } from '../core/types.js';\n\n/**\n * Colombian Peso (COP)\n * Format: $ 1.000,00\n */\nexport const COP: Currency = {\n code: 'COP',\n symbol: '$',\n decimals: 2,\n thousandsSeparator: '.',\n decimalSeparator: ',',\n symbolPosition: 'before',\n symbolSpacing: true,\n};\n\n/**\n * Colombian Peso without decimals (common usage)\n * Format: $ 1.000\n */\nexport const COP_NO_DECIMALS: Currency = {\n ...COP,\n decimals: 0,\n};\n","import type { Currency } from '../core/types.js';\n\n/**\n * Mexican Peso (MXN)\n * Format: $1,000.00\n */\nexport const MXN: Currency = {\n code: 'MXN',\n symbol: '$',\n decimals: 2,\n thousandsSeparator: ',',\n decimalSeparator: '.',\n symbolPosition: 'before',\n symbolSpacing: false,\n};\n","import type { Currency } from '../core/types.js';\n\n/**\n * Argentine Peso (ARS)\n * Format: $ 1.000,00\n */\nexport const ARS: Currency = {\n code: 'ARS',\n symbol: '$',\n decimals: 2,\n thousandsSeparator: '.',\n decimalSeparator: ',',\n symbolPosition: 'before',\n symbolSpacing: true,\n};\n","import type { Currency } from '../core/types.js';\n\n/**\n * Brazilian Real (BRL)\n * Format: R$ 1.000,00\n */\nexport const BRL: Currency = {\n code: 'BRL',\n symbol: 'R$',\n decimals: 2,\n thousandsSeparator: '.',\n decimalSeparator: ',',\n symbolPosition: 'before',\n symbolSpacing: true,\n};\n","import type { Currency } from '../core/types.js';\n\n/**\n * US Dollar (USD)\n * Format: $1,000.00\n */\nexport const USD: Currency = {\n code: 'USD',\n symbol: '$',\n decimals: 2,\n thousandsSeparator: ',',\n decimalSeparator: '.',\n symbolPosition: 'before',\n symbolSpacing: false,\n};\n","import type { Currency } from '../core/types.js';\n\n/**\n * Chilean Peso (CLP)\n * Format: $ 1.500\n * Note: CLP doesn't use decimal places in common usage\n */\nexport const CLP: Currency = {\n code: 'CLP',\n symbol: '$',\n decimals: 0,\n thousandsSeparator: '.',\n decimalSeparator: ',',\n symbolPosition: 'before',\n symbolSpacing: true,\n};\n\n/**\n * Chilean Peso with decimals (for precise calculations)\n * Format: $ 1.500,00\n */\nexport const CLP_DECIMALS: Currency = {\n ...CLP,\n decimals: 2,\n};\n","import type { Currency } from '../core/types.js';\n\n/**\n * Peruvian Sol (PEN)\n * Format: S/ 1,500.00\n */\nexport const PEN: Currency = {\n code: 'PEN',\n symbol: 'S/',\n decimals: 2,\n thousandsSeparator: ',',\n decimalSeparator: '.',\n symbolPosition: 'before',\n symbolSpacing: true,\n};\n","import type { Currency } from '../core/types.js';\n\n/**\n * Uruguayan Peso (UYU)\n * Format: $ 1.500,00\n */\nexport const UYU: Currency = {\n code: 'UYU',\n symbol: '$',\n decimals: 2,\n thousandsSeparator: '.',\n decimalSeparator: ',',\n symbolPosition: 'before',\n symbolSpacing: true,\n};\n","import type { Currency } from '../core/types.js';\n\n/**\n * Euro (EUR)\n * Format: 1.500,00 €\n */\nexport const EUR: Currency = {\n code: 'EUR',\n symbol: '€',\n decimals: 2,\n thousandsSeparator: '.',\n decimalSeparator: ',',\n symbolPosition: 'after',\n symbolSpacing: true,\n};\n"]}
package/dist/index.js CHANGED
@@ -1,2 +1,2 @@
1
- var u=class n{constructor(e,r){if(!Number.isInteger(e))throw new Error("Money must be created with an integer number of cents");this.cents=e,this.currency=r,Object.freeze(this);}static fromCents(e,r){return new n(Math.round(e),r)}static fromDecimal(e,r){let t=Math.pow(10,r.decimals),s=Math.round(e*t);return new n(s,r)}static zero(e){return new n(0,e)}add(e){return this.assertSameCurrency(e),new n(this.cents+e.cents,this.currency)}subtract(e){return this.assertSameCurrency(e),new n(this.cents-e.cents,this.currency)}multiply(e){return new n(Math.round(this.cents*e),this.currency)}divide(e){if(e===0)throw new Error("Cannot divide by zero");return new n(Math.round(this.cents/e),this.currency)}distribute(e){if(e<=0||!Number.isInteger(e))throw new Error("Parts must be a positive integer");let r=Math.floor(this.cents/e),t=this.cents%e,s=[];for(let o=0;o<e;o++){let c=o<t?1:0;s.push(new n(r+c,this.currency));}return s}distributeByRatios(e){if(e.length===0)throw new Error("Ratios array cannot be empty");let r=e.reduce((o,c)=>o+c,0);if(r<=0)throw new Error("Sum of ratios must be positive");let t=this.cents,s=[];for(let o=0;o<e.length;o++)if(o===e.length-1)s.push(new n(t,this.currency));else {let c=Math.round(this.cents*e[o]/r);s.push(new n(c,this.currency)),t-=c;}return s}format(e={}){let{showSymbol:r=true,showDecimals:t=true,symbolPosition:s}=e,o=this.toDecimal(),c=Math.abs(o),l=o<0,i;if(t&&this.currency.decimals>0){let[y,a]=c.toFixed(this.currency.decimals).split(".");i=`${this.formatInteger(y)}${this.currency.decimalSeparator}${a}`;}else i=this.formatInteger(Math.round(c).toString());if(l&&(i=`-${i}`),r){let y=s??this.currency.symbolPosition,a=this.currency.symbolSpacing?" ":"";y==="before"?i=`${this.currency.symbol}${a}${i}`:i=`${i}${a}${this.currency.symbol}`;}return i}toDecimal(){return this.cents/Math.pow(10,this.currency.decimals)}equals(e){return this.cents===e.cents&&this.currency.code===e.currency.code}greaterThan(e){return this.assertSameCurrency(e),this.cents>e.cents}lessThan(e){return this.assertSameCurrency(e),this.cents<e.cents}greaterThanOrEqual(e){return this.assertSameCurrency(e),this.cents>=e.cents}lessThanOrEqual(e){return this.assertSameCurrency(e),this.cents<=e.cents}isZero(){return this.cents===0}isPositive(){return this.cents>0}isNegative(){return this.cents<0}abs(){return new n(Math.abs(this.cents),this.currency)}negate(){return new n(-this.cents,this.currency)}percentage(e){return new n(Math.round(this.cents*e/100),this.currency)}addPercentage(e){return this.add(this.percentage(e))}subtractPercentage(e){return this.subtract(this.percentage(e))}min(e){return this.assertSameCurrency(e),this.cents<=e.cents?this:new n(e.cents,this.currency)}max(e){return this.assertSameCurrency(e),this.cents>=e.cents?this:new n(e.cents,this.currency)}clamp(e,r){return this.max(e).min(r)}toCents(){return this.cents}isBetween(e,r){return this.assertSameCurrency(e),this.assertSameCurrency(r),this.cents>=e.cents&&this.cents<=r.cents}static sum(e){if(e.length===0)throw new Error("Cannot sum empty array");let r=e[0].currency,t=e.reduce((s,o)=>{if(o.currency.code!==r.code)throw new Error("Cannot sum different currencies");return s+o.cents},0);return new n(t,r)}static minimum(e){if(e.length===0)throw new Error("Cannot get minimum of empty array");return e.reduce((r,t)=>t.cents<r.cents?t:r)}static maximum(e){if(e.length===0)throw new Error("Cannot get maximum of empty array");return e.reduce((r,t)=>t.cents>r.cents?t:r)}static average(e){if(e.length===0)throw new Error("Cannot calculate average of empty array");return n.sum(e).divide(e.length)}toJSON(){return {cents:this.cents,currency:this.currency.code}}toString(){return this.format()}formatInteger(e){let r=[],t=e;for(;t.length>3;)r.unshift(t.slice(-3)),t=t.slice(0,-3);return t&&r.unshift(t),r.join(this.currency.thousandsSeparator)}assertSameCurrency(e){if(this.currency.code!==e.currency.code)throw new Error(`Cannot perform operation with different currencies: ${this.currency.code} and ${e.currency.code}`)}};var m={code:"COP",symbol:"$",decimals:2,thousandsSeparator:".",decimalSeparator:",",symbolPosition:"before",symbolSpacing:true},p={...m,decimals:0};var d={code:"MXN",symbol:"$",decimals:2,thousandsSeparator:",",decimalSeparator:".",symbolPosition:"before",symbolSpacing:false};var b={code:"ARS",symbol:"$",decimals:2,thousandsSeparator:".",decimalSeparator:",",symbolPosition:"before",symbolSpacing:true};var f={code:"BRL",symbol:"R$",decimals:2,thousandsSeparator:".",decimalSeparator:",",symbolPosition:"before",symbolSpacing:true};var M={code:"USD",symbol:"$",decimals:2,thousandsSeparator:",",decimalSeparator:".",symbolPosition:"before",symbolSpacing:false};var h={code:"CLP",symbol:"$",decimals:0,thousandsSeparator:".",decimalSeparator:",",symbolPosition:"before",symbolSpacing:true},C={...h,decimals:2};var S={code:"PEN",symbol:"S/",decimals:2,thousandsSeparator:",",decimalSeparator:".",symbolPosition:"before",symbolSpacing:true};var g={code:"UYU",symbol:"$",decimals:2,thousandsSeparator:".",decimalSeparator:",",symbolPosition:"before",symbolSpacing:true};var w={code:"EUR",symbol:"\u20AC",decimals:2,thousandsSeparator:".",decimalSeparator:",",symbolPosition:"after",symbolSpacing:true};export{b as ARS,f as BRL,h as CLP,C as CLP_DECIMALS,m as COP,p as COP_NO_DECIMALS,w as EUR,d as MXN,u as Money,S as PEN,M as USD,g as UYU};//# sourceMappingURL=index.js.map
1
+ var y=class o{constructor(e,r){if(!Number.isInteger(e))throw new Error("Money must be created with an integer number of cents");this.cents=e,this.currency=r,Object.freeze(this);}static fromCents(e,r){return new o(Math.round(e),r)}static fromDecimal(e,r){let t=Math.pow(10,r.decimals),s=Math.round(e*t);return new o(s,r)}static fromString(e,r){let t=e.replace(r.symbol,"").trim(),s=c=>c.replace(/[.*+?^${}()|[\]\\]/g,"\\$&");if(r.thousandsSeparator){let c=new RegExp(s(r.thousandsSeparator),"g");t=t.replace(c,"");}r.decimalSeparator&&r.decimalSeparator!=="."&&(t=t.replace(r.decimalSeparator,".")),t=t.replace(/\s+/g,"");let n=parseFloat(t);if(isNaN(n))throw new Error(`Cannot parse "${e}" as money`);return o.fromDecimal(n,r)}static zero(e){return new o(0,e)}add(e){return this.assertSameCurrency(e),new o(this.cents+e.cents,this.currency)}subtract(e){return this.assertSameCurrency(e),new o(this.cents-e.cents,this.currency)}multiply(e){return new o(Math.round(this.cents*e),this.currency)}divide(e){if(e===0)throw new Error("Cannot divide by zero");return new o(Math.round(this.cents/e),this.currency)}distribute(e){if(e<=0||!Number.isInteger(e))throw new Error("Parts must be a positive integer");let r=Math.floor(this.cents/e),t=this.cents%e,s=[];for(let n=0;n<e;n++){let c=n<t?1:0;s.push(new o(r+c,this.currency));}return s}distributeByRatios(e){if(e.length===0)throw new Error("Ratios array cannot be empty");let r=e.reduce((n,c)=>n+c,0);if(r<=0)throw new Error("Sum of ratios must be positive");let t=this.cents,s=[];for(let n=0;n<e.length;n++)if(n===e.length-1)s.push(new o(t,this.currency));else {let c=Math.round(this.cents*e[n]/r);s.push(new o(c,this.currency)),t-=c;}return s}format(e={}){let{showSymbol:r=true,showDecimals:t=true,symbolPosition:s}=e,n=this.toDecimal(),c=Math.abs(n),p=n<0,i;if(t&&this.currency.decimals>0){let[u,a]=c.toFixed(this.currency.decimals).split(".");i=`${this.formatInteger(u)}${this.currency.decimalSeparator}${a}`;}else i=this.formatInteger(Math.round(c).toString());if(p&&(i=`-${i}`),r){let u=s??this.currency.symbolPosition,a=this.currency.symbolSpacing?" ":"";u==="before"?i=`${this.currency.symbol}${a}${i}`:i=`${i}${a}${this.currency.symbol}`;}return i}toDecimal(){return this.cents/Math.pow(10,this.currency.decimals)}equals(e){return this.cents===e.cents&&this.currency.code===e.currency.code}greaterThan(e){return this.assertSameCurrency(e),this.cents>e.cents}lessThan(e){return this.assertSameCurrency(e),this.cents<e.cents}greaterThanOrEqual(e){return this.assertSameCurrency(e),this.cents>=e.cents}lessThanOrEqual(e){return this.assertSameCurrency(e),this.cents<=e.cents}isZero(){return this.cents===0}isPositive(){return this.cents>0}isNegative(){return this.cents<0}abs(){return new o(Math.abs(this.cents),this.currency)}negate(){return new o(-this.cents,this.currency)}percentage(e){return new o(Math.round(this.cents*e/100),this.currency)}addPercentage(e){return this.add(this.percentage(e))}subtractPercentage(e){return this.subtract(this.percentage(e))}min(e){return this.assertSameCurrency(e),this.cents<=e.cents?this:new o(e.cents,this.currency)}max(e){return this.assertSameCurrency(e),this.cents>=e.cents?this:new o(e.cents,this.currency)}clamp(e,r){return this.max(e).min(r)}toCents(){return this.cents}isBetween(e,r){return this.assertSameCurrency(e),this.assertSameCurrency(r),this.cents>=e.cents&&this.cents<=r.cents}static sum(e){if(e.length===0)throw new Error("Cannot sum empty array");let r=e[0].currency,t=e.reduce((s,n)=>{if(n.currency.code!==r.code)throw new Error("Cannot sum different currencies");return s+n.cents},0);return new o(t,r)}static minimum(e){if(e.length===0)throw new Error("Cannot get minimum of empty array");return e.reduce((r,t)=>t.cents<r.cents?t:r)}static maximum(e){if(e.length===0)throw new Error("Cannot get maximum of empty array");return e.reduce((r,t)=>t.cents>r.cents?t:r)}static average(e){if(e.length===0)throw new Error("Cannot calculate average of empty array");return o.sum(e).divide(e.length)}toJSON(){return {cents:this.cents,currency:this.currency.code}}toString(){return this.format()}formatInteger(e){let r=[],t=e;for(;t.length>3;)r.unshift(t.slice(-3)),t=t.slice(0,-3);return t&&r.unshift(t),r.join(this.currency.thousandsSeparator)}assertSameCurrency(e){if(this.currency.code!==e.currency.code)throw new Error(`Cannot perform operation with different currencies: ${this.currency.code} and ${e.currency.code}`)}};var m={code:"COP",symbol:"$",decimals:2,thousandsSeparator:".",decimalSeparator:",",symbolPosition:"before",symbolSpacing:true},h={...m,decimals:0};var d={code:"MXN",symbol:"$",decimals:2,thousandsSeparator:",",decimalSeparator:".",symbolPosition:"before",symbolSpacing:false};var b={code:"ARS",symbol:"$",decimals:2,thousandsSeparator:".",decimalSeparator:",",symbolPosition:"before",symbolSpacing:true};var f={code:"BRL",symbol:"R$",decimals:2,thousandsSeparator:".",decimalSeparator:",",symbolPosition:"before",symbolSpacing:true};var M={code:"USD",symbol:"$",decimals:2,thousandsSeparator:",",decimalSeparator:".",symbolPosition:"before",symbolSpacing:false};var l={code:"CLP",symbol:"$",decimals:0,thousandsSeparator:".",decimalSeparator:",",symbolPosition:"before",symbolSpacing:true},C={...l,decimals:2};var S={code:"PEN",symbol:"S/",decimals:2,thousandsSeparator:",",decimalSeparator:".",symbolPosition:"before",symbolSpacing:true};var g={code:"UYU",symbol:"$",decimals:2,thousandsSeparator:".",decimalSeparator:",",symbolPosition:"before",symbolSpacing:true};var w={code:"EUR",symbol:"\u20AC",decimals:2,thousandsSeparator:".",decimalSeparator:",",symbolPosition:"after",symbolSpacing:true};export{b as ARS,f as BRL,l as CLP,C as CLP_DECIMALS,m as COP,h as COP_NO_DECIMALS,w as EUR,d as MXN,y as Money,S as PEN,M as USD,g as UYU};//# sourceMappingURL=index.js.map
2
2
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/core/money.ts","../src/locales/co.ts","../src/locales/mx.ts","../src/locales/ar.ts","../src/locales/br.ts","../src/locales/us.ts","../src/locales/cl.ts","../src/locales/pe.ts","../src/locales/uy.ts","../src/locales/eu.ts"],"names":["Money","_Money","cents","currency","amount","multiplier","other","factor","divisor","parts","quotient","remainder","result","i","extra","ratios","total","sum","r","remaining","share","options","showSymbol","showDecimals","symbolPosition","decimal","absValue","isNegative","formatted","intPart","decPart","pos","space","percent","minValue","maxValue","min","max","values","m","intStr","COP","COP_NO_DECIMALS","MXN","ARS","BRL","USD","CLP","CLP_DECIMALS","PEN","UYU","EUR"],"mappings":"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","file":"index.js","sourcesContent":["import type { Currency, FormatOptions, IMoney } from './types.js';\n\n/**\n * Immutable Money class that uses integer arithmetic for precision\n */\nexport class Money implements IMoney {\n readonly cents: number;\n readonly currency: Currency;\n\n private constructor(cents: number, currency: Currency) {\n if (!Number.isInteger(cents)) {\n throw new Error('Money must be created with an integer number of cents');\n }\n this.cents = cents;\n this.currency = currency;\n Object.freeze(this);\n }\n\n /**\n * Create money from cents (smallest unit)\n */\n static fromCents(cents: number, currency: Currency): Money {\n return new Money(Math.round(cents), currency);\n }\n\n /**\n * Create money from a decimal amount\n * @example Money.fromDecimal(100.50, USD) creates $100.50\n */\n static fromDecimal(amount: number, currency: Currency): Money {\n const multiplier = Math.pow(10, currency.decimals);\n const cents = Math.round(amount * multiplier);\n return new Money(cents, currency);\n }\n\n /**\n * Create zero money\n */\n static zero(currency: Currency): Money {\n return new Money(0, currency);\n }\n\n /**\n * Add another money value (must be same currency)\n */\n add(other: IMoney): Money {\n this.assertSameCurrency(other);\n return new Money(this.cents + other.cents, this.currency);\n }\n\n /**\n * Subtract another money value (must be same currency)\n */\n subtract(other: IMoney): Money {\n this.assertSameCurrency(other);\n return new Money(this.cents - other.cents, this.currency);\n }\n\n /**\n * Multiply by a factor (rounds to nearest cent)\n */\n multiply(factor: number): Money {\n return new Money(Math.round(this.cents * factor), this.currency);\n }\n\n /**\n * Divide by a divisor (rounds to nearest cent)\n */\n divide(divisor: number): Money {\n if (divisor === 0) {\n throw new Error('Cannot divide by zero');\n }\n return new Money(Math.round(this.cents / divisor), this.currency);\n }\n\n /**\n * Distribute money evenly without losing cents\n * The remainder is distributed to the first parts\n * @example $100 / 3 = [$33.34, $33.33, $33.33]\n */\n distribute(parts: number): Money[] {\n if (parts <= 0 || !Number.isInteger(parts)) {\n throw new Error('Parts must be a positive integer');\n }\n\n const quotient = Math.floor(this.cents / parts);\n const remainder = this.cents % parts;\n\n const result: Money[] = [];\n for (let i = 0; i < parts; i++) {\n // Add 1 cent to the first 'remainder' parts\n const extra = i < remainder ? 1 : 0;\n result.push(new Money(quotient + extra, this.currency));\n }\n\n return result;\n }\n\n /**\n * Distribute money according to ratios\n * @example $100 with ratios [1, 2, 2] = [$20, $40, $40]\n */\n distributeByRatios(ratios: number[]): Money[] {\n if (ratios.length === 0) {\n throw new Error('Ratios array cannot be empty');\n }\n\n const total = ratios.reduce((sum, r) => sum + r, 0);\n if (total <= 0) {\n throw new Error('Sum of ratios must be positive');\n }\n\n let remaining = this.cents;\n const result: Money[] = [];\n\n for (let i = 0; i < ratios.length; i++) {\n if (i === ratios.length - 1) {\n // Last part gets whatever is remaining to avoid rounding errors\n result.push(new Money(remaining, this.currency));\n } else {\n const share = Math.round((this.cents * ratios[i]) / total);\n result.push(new Money(share, this.currency));\n remaining -= share;\n }\n }\n\n return result;\n }\n\n /**\n * Format money for display\n */\n format(options: FormatOptions = {}): string {\n const { showSymbol = true, showDecimals = true, symbolPosition } = options;\n\n const decimal = this.toDecimal();\n const absValue = Math.abs(decimal);\n const isNegative = decimal < 0;\n\n // Format the number\n let formatted: string;\n if (showDecimals && this.currency.decimals > 0) {\n const [intPart, decPart] = absValue.toFixed(this.currency.decimals).split('.');\n const intFormatted = this.formatInteger(intPart);\n formatted = `${intFormatted}${this.currency.decimalSeparator}${decPart}`;\n } else {\n formatted = this.formatInteger(Math.round(absValue).toString());\n }\n\n // Add negative sign\n if (isNegative) {\n formatted = `-${formatted}`;\n }\n\n // Add symbol\n if (showSymbol) {\n const pos = symbolPosition ?? this.currency.symbolPosition;\n const space = this.currency.symbolSpacing ? ' ' : '';\n\n if (pos === 'before') {\n formatted = `${this.currency.symbol}${space}${formatted}`;\n } else {\n formatted = `${formatted}${space}${this.currency.symbol}`;\n }\n }\n\n return formatted;\n }\n\n /**\n * Get the decimal representation\n */\n toDecimal(): number {\n return this.cents / Math.pow(10, this.currency.decimals);\n }\n\n /**\n * Check equality with another money value\n */\n equals(other: IMoney): boolean {\n return this.cents === other.cents && this.currency.code === other.currency.code;\n }\n\n /**\n * Check if greater than another money value\n */\n greaterThan(other: IMoney): boolean {\n this.assertSameCurrency(other);\n return this.cents > other.cents;\n }\n\n /**\n * Check if less than another money value\n */\n lessThan(other: IMoney): boolean {\n this.assertSameCurrency(other);\n return this.cents < other.cents;\n }\n\n /**\n * Check if greater than or equal\n */\n greaterThanOrEqual(other: IMoney): boolean {\n this.assertSameCurrency(other);\n return this.cents >= other.cents;\n }\n\n /**\n * Check if less than or equal\n */\n lessThanOrEqual(other: IMoney): boolean {\n this.assertSameCurrency(other);\n return this.cents <= other.cents;\n }\n\n /**\n * Check if zero\n */\n isZero(): boolean {\n return this.cents === 0;\n }\n\n /**\n * Check if positive\n */\n isPositive(): boolean {\n return this.cents > 0;\n }\n\n /**\n * Check if negative\n */\n isNegative(): boolean {\n return this.cents < 0;\n }\n\n /**\n * Get absolute value\n */\n abs(): Money {\n return new Money(Math.abs(this.cents), this.currency);\n }\n\n /**\n * Negate the value\n */\n negate(): Money {\n return new Money(-this.cents, this.currency);\n }\n\n /**\n * Calculate a percentage of this money\n * @example money.percentage(10) returns 10% of the amount\n */\n percentage(percent: number): Money {\n return new Money(Math.round((this.cents * percent) / 100), this.currency);\n }\n\n /**\n * Add a percentage to this money\n * @example money.addPercentage(19) adds 19% (like tax)\n */\n addPercentage(percent: number): Money {\n return this.add(this.percentage(percent));\n }\n\n /**\n * Subtract a percentage from this money\n * @example money.subtractPercentage(10) subtracts 10% (like discount)\n */\n subtractPercentage(percent: number): Money {\n return this.subtract(this.percentage(percent));\n }\n\n /**\n * Get the minimum of this and another money value\n */\n min(other: IMoney): Money {\n this.assertSameCurrency(other);\n return this.cents <= other.cents ? this : new Money(other.cents, this.currency);\n }\n\n /**\n * Get the maximum of this and another money value\n */\n max(other: IMoney): Money {\n this.assertSameCurrency(other);\n return this.cents >= other.cents ? this : new Money(other.cents, this.currency);\n }\n\n /**\n * Clamp this money between a minimum and maximum\n */\n clamp(minValue: IMoney, maxValue: IMoney): Money {\n return this.max(minValue).min(maxValue);\n }\n\n /**\n * Get cents (smallest unit)\n */\n toCents(): number {\n return this.cents;\n }\n\n /**\n * Check if within a range (inclusive)\n */\n isBetween(min: IMoney, max: IMoney): boolean {\n this.assertSameCurrency(min);\n this.assertSameCurrency(max);\n return this.cents >= min.cents && this.cents <= max.cents;\n }\n\n /**\n * Sum multiple money values\n */\n static sum(values: IMoney[]): Money {\n if (values.length === 0) {\n throw new Error('Cannot sum empty array');\n }\n const currency = values[0].currency;\n const total = values.reduce((sum, m) => {\n if (m.currency.code !== currency.code) {\n throw new Error('Cannot sum different currencies');\n }\n return sum + m.cents;\n }, 0);\n return new Money(total, currency);\n }\n\n /**\n * Get the minimum from an array of money values\n */\n static minimum(values: IMoney[]): Money {\n if (values.length === 0) {\n throw new Error('Cannot get minimum of empty array');\n }\n return values.reduce((min, m) => (m.cents < min.cents ? m : min)) as Money;\n }\n\n /**\n * Get the maximum from an array of money values\n */\n static maximum(values: IMoney[]): Money {\n if (values.length === 0) {\n throw new Error('Cannot get maximum of empty array');\n }\n return values.reduce((max, m) => (m.cents > max.cents ? m : max)) as Money;\n }\n\n /**\n * Calculate the average of money values\n */\n static average(values: IMoney[]): Money {\n if (values.length === 0) {\n throw new Error('Cannot calculate average of empty array');\n }\n const total = Money.sum(values);\n return total.divide(values.length);\n }\n\n /**\n * Convert to JSON-serializable object\n */\n toJSON(): { cents: number; currency: string } {\n return {\n cents: this.cents,\n currency: this.currency.code,\n };\n }\n\n /**\n * String representation\n */\n toString(): string {\n return this.format();\n }\n\n private formatInteger(intStr: string): string {\n const parts: string[] = [];\n let remaining = intStr;\n\n while (remaining.length > 3) {\n parts.unshift(remaining.slice(-3));\n remaining = remaining.slice(0, -3);\n }\n\n if (remaining) {\n parts.unshift(remaining);\n }\n\n return parts.join(this.currency.thousandsSeparator);\n }\n\n private assertSameCurrency(other: IMoney): void {\n if (this.currency.code !== other.currency.code) {\n throw new Error(\n `Cannot perform operation with different currencies: ${this.currency.code} and ${other.currency.code}`\n );\n }\n }\n}\n","import type { Currency } from '../core/types.js';\n\n/**\n * Colombian Peso (COP)\n * Format: $ 1.000,00\n */\nexport const COP: Currency = {\n code: 'COP',\n symbol: '$',\n decimals: 2,\n thousandsSeparator: '.',\n decimalSeparator: ',',\n symbolPosition: 'before',\n symbolSpacing: true,\n};\n\n/**\n * Colombian Peso without decimals (common usage)\n * Format: $ 1.000\n */\nexport const COP_NO_DECIMALS: Currency = {\n ...COP,\n decimals: 0,\n};\n","import type { Currency } from '../core/types.js';\n\n/**\n * Mexican Peso (MXN)\n * Format: $1,000.00\n */\nexport const MXN: Currency = {\n code: 'MXN',\n symbol: '$',\n decimals: 2,\n thousandsSeparator: ',',\n decimalSeparator: '.',\n symbolPosition: 'before',\n symbolSpacing: false,\n};\n","import type { Currency } from '../core/types.js';\n\n/**\n * Argentine Peso (ARS)\n * Format: $ 1.000,00\n */\nexport const ARS: Currency = {\n code: 'ARS',\n symbol: '$',\n decimals: 2,\n thousandsSeparator: '.',\n decimalSeparator: ',',\n symbolPosition: 'before',\n symbolSpacing: true,\n};\n","import type { Currency } from '../core/types.js';\n\n/**\n * Brazilian Real (BRL)\n * Format: R$ 1.000,00\n */\nexport const BRL: Currency = {\n code: 'BRL',\n symbol: 'R$',\n decimals: 2,\n thousandsSeparator: '.',\n decimalSeparator: ',',\n symbolPosition: 'before',\n symbolSpacing: true,\n};\n","import type { Currency } from '../core/types.js';\n\n/**\n * US Dollar (USD)\n * Format: $1,000.00\n */\nexport const USD: Currency = {\n code: 'USD',\n symbol: '$',\n decimals: 2,\n thousandsSeparator: ',',\n decimalSeparator: '.',\n symbolPosition: 'before',\n symbolSpacing: false,\n};\n","import type { Currency } from '../core/types.js';\n\n/**\n * Chilean Peso (CLP)\n * Format: $ 1.500\n * Note: CLP doesn't use decimal places in common usage\n */\nexport const CLP: Currency = {\n code: 'CLP',\n symbol: '$',\n decimals: 0,\n thousandsSeparator: '.',\n decimalSeparator: ',',\n symbolPosition: 'before',\n symbolSpacing: true,\n};\n\n/**\n * Chilean Peso with decimals (for precise calculations)\n * Format: $ 1.500,00\n */\nexport const CLP_DECIMALS: Currency = {\n ...CLP,\n decimals: 2,\n};\n","import type { Currency } from '../core/types.js';\n\n/**\n * Peruvian Sol (PEN)\n * Format: S/ 1,500.00\n */\nexport const PEN: Currency = {\n code: 'PEN',\n symbol: 'S/',\n decimals: 2,\n thousandsSeparator: ',',\n decimalSeparator: '.',\n symbolPosition: 'before',\n symbolSpacing: true,\n};\n","import type { Currency } from '../core/types.js';\n\n/**\n * Uruguayan Peso (UYU)\n * Format: $ 1.500,00\n */\nexport const UYU: Currency = {\n code: 'UYU',\n symbol: '$',\n decimals: 2,\n thousandsSeparator: '.',\n decimalSeparator: ',',\n symbolPosition: 'before',\n symbolSpacing: true,\n};\n","import type { Currency } from '../core/types.js';\n\n/**\n * Euro (EUR)\n * Format: 1.500,00 €\n */\nexport const EUR: Currency = {\n code: 'EUR',\n symbol: '€',\n decimals: 2,\n thousandsSeparator: '.',\n decimalSeparator: ',',\n symbolPosition: 'after',\n symbolSpacing: true,\n};\n"]}
1
+ {"version":3,"sources":["../src/core/money.ts","../src/locales/co.ts","../src/locales/mx.ts","../src/locales/ar.ts","../src/locales/br.ts","../src/locales/us.ts","../src/locales/cl.ts","../src/locales/pe.ts","../src/locales/uy.ts","../src/locales/eu.ts"],"names":["Money","_Money","cents","currency","amount","multiplier","value","cleanValue","escapeRegex","str","thousandsRegex","decimalAmount","other","factor","divisor","parts","quotient","remainder","result","i","extra","ratios","total","sum","r","remaining","share","options","showSymbol","showDecimals","symbolPosition","decimal","absValue","isNegative","formatted","intPart","decPart","pos","space","percent","minValue","maxValue","min","max","values","m","intStr","COP","COP_NO_DECIMALS","MXN","ARS","BRL","USD","CLP","CLP_DECIMALS","PEN","UYU","EUR"],"mappings":"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","file":"index.js","sourcesContent":["import type { Currency, FormatOptions, IMoney } from './types.js';\n\n/**\n * Immutable Money class that uses integer arithmetic for precision\n */\nexport class Money implements IMoney {\n readonly cents: number;\n readonly currency: Currency;\n\n private constructor(cents: number, currency: Currency) {\n if (!Number.isInteger(cents)) {\n throw new Error('Money must be created with an integer number of cents');\n }\n this.cents = cents;\n this.currency = currency;\n Object.freeze(this);\n }\n\n /**\n * Create money from cents (smallest unit)\n */\n static fromCents(cents: number, currency: Currency): Money {\n return new Money(Math.round(cents), currency);\n }\n\n /**\n * Create money from a decimal amount\n * @example Money.fromDecimal(100.50, USD) creates $100.50\n */\n static fromDecimal(amount: number, currency: Currency): Money {\n const multiplier = Math.pow(10, currency.decimals);\n const cents = Math.round(amount * multiplier);\n return new Money(cents, currency);\n }\n\n /**\n * Create money from a formatted string\n * @example Money.fromString(\"$ 1.500,50\", ARS) creates $1,500.50\n */\n static fromString(value: string, currency: Currency): Money {\n let cleanValue = value.replace(currency.symbol, '').trim();\n\n const escapeRegex = (str: string) => str.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n\n if (currency.thousandsSeparator) {\n const thousandsRegex = new RegExp(escapeRegex(currency.thousandsSeparator), 'g');\n cleanValue = cleanValue.replace(thousandsRegex, '');\n }\n\n if (currency.decimalSeparator && currency.decimalSeparator !== '.') {\n cleanValue = cleanValue.replace(currency.decimalSeparator, '.');\n }\n\n cleanValue = cleanValue.replace(/\\s+/g, '');\n\n const decimalAmount = parseFloat(cleanValue);\n\n if (isNaN(decimalAmount)) {\n throw new Error(`Cannot parse \"${value}\" as money`);\n }\n\n return Money.fromDecimal(decimalAmount, currency);\n }\n\n /**\n * Create zero money\n */\n static zero(currency: Currency): Money {\n return new Money(0, currency);\n }\n\n /**\n * Add another money value (must be same currency)\n */\n add(other: IMoney): Money {\n this.assertSameCurrency(other);\n return new Money(this.cents + other.cents, this.currency);\n }\n\n /**\n * Subtract another money value (must be same currency)\n */\n subtract(other: IMoney): Money {\n this.assertSameCurrency(other);\n return new Money(this.cents - other.cents, this.currency);\n }\n\n /**\n * Multiply by a factor (rounds to nearest cent)\n */\n multiply(factor: number): Money {\n return new Money(Math.round(this.cents * factor), this.currency);\n }\n\n /**\n * Divide by a divisor (rounds to nearest cent)\n */\n divide(divisor: number): Money {\n if (divisor === 0) {\n throw new Error('Cannot divide by zero');\n }\n return new Money(Math.round(this.cents / divisor), this.currency);\n }\n\n /**\n * Distribute money evenly without losing cents\n * The remainder is distributed to the first parts\n * @example $100 / 3 = [$33.34, $33.33, $33.33]\n */\n distribute(parts: number): Money[] {\n if (parts <= 0 || !Number.isInteger(parts)) {\n throw new Error('Parts must be a positive integer');\n }\n\n const quotient = Math.floor(this.cents / parts);\n const remainder = this.cents % parts;\n\n const result: Money[] = [];\n for (let i = 0; i < parts; i++) {\n // Add 1 cent to the first 'remainder' parts\n const extra = i < remainder ? 1 : 0;\n result.push(new Money(quotient + extra, this.currency));\n }\n\n return result;\n }\n\n /**\n * Distribute money according to ratios\n * @example $100 with ratios [1, 2, 2] = [$20, $40, $40]\n */\n distributeByRatios(ratios: number[]): Money[] {\n if (ratios.length === 0) {\n throw new Error('Ratios array cannot be empty');\n }\n\n const total = ratios.reduce((sum, r) => sum + r, 0);\n if (total <= 0) {\n throw new Error('Sum of ratios must be positive');\n }\n\n let remaining = this.cents;\n const result: Money[] = [];\n\n for (let i = 0; i < ratios.length; i++) {\n if (i === ratios.length - 1) {\n // Last part gets whatever is remaining to avoid rounding errors\n result.push(new Money(remaining, this.currency));\n } else {\n const share = Math.round((this.cents * ratios[i]) / total);\n result.push(new Money(share, this.currency));\n remaining -= share;\n }\n }\n\n return result;\n }\n\n /**\n * Format money for display\n */\n format(options: FormatOptions = {}): string {\n const { showSymbol = true, showDecimals = true, symbolPosition } = options;\n\n const decimal = this.toDecimal();\n const absValue = Math.abs(decimal);\n const isNegative = decimal < 0;\n\n // Format the number\n let formatted: string;\n if (showDecimals && this.currency.decimals > 0) {\n const [intPart, decPart] = absValue.toFixed(this.currency.decimals).split('.');\n const intFormatted = this.formatInteger(intPart);\n formatted = `${intFormatted}${this.currency.decimalSeparator}${decPart}`;\n } else {\n formatted = this.formatInteger(Math.round(absValue).toString());\n }\n\n // Add negative sign\n if (isNegative) {\n formatted = `-${formatted}`;\n }\n\n // Add symbol\n if (showSymbol) {\n const pos = symbolPosition ?? this.currency.symbolPosition;\n const space = this.currency.symbolSpacing ? ' ' : '';\n\n if (pos === 'before') {\n formatted = `${this.currency.symbol}${space}${formatted}`;\n } else {\n formatted = `${formatted}${space}${this.currency.symbol}`;\n }\n }\n\n return formatted;\n }\n\n /**\n * Get the decimal representation\n */\n toDecimal(): number {\n return this.cents / Math.pow(10, this.currency.decimals);\n }\n\n /**\n * Check equality with another money value\n */\n equals(other: IMoney): boolean {\n return this.cents === other.cents && this.currency.code === other.currency.code;\n }\n\n /**\n * Check if greater than another money value\n */\n greaterThan(other: IMoney): boolean {\n this.assertSameCurrency(other);\n return this.cents > other.cents;\n }\n\n /**\n * Check if less than another money value\n */\n lessThan(other: IMoney): boolean {\n this.assertSameCurrency(other);\n return this.cents < other.cents;\n }\n\n /**\n * Check if greater than or equal\n */\n greaterThanOrEqual(other: IMoney): boolean {\n this.assertSameCurrency(other);\n return this.cents >= other.cents;\n }\n\n /**\n * Check if less than or equal\n */\n lessThanOrEqual(other: IMoney): boolean {\n this.assertSameCurrency(other);\n return this.cents <= other.cents;\n }\n\n /**\n * Check if zero\n */\n isZero(): boolean {\n return this.cents === 0;\n }\n\n /**\n * Check if positive\n */\n isPositive(): boolean {\n return this.cents > 0;\n }\n\n /**\n * Check if negative\n */\n isNegative(): boolean {\n return this.cents < 0;\n }\n\n /**\n * Get absolute value\n */\n abs(): Money {\n return new Money(Math.abs(this.cents), this.currency);\n }\n\n /**\n * Negate the value\n */\n negate(): Money {\n return new Money(-this.cents, this.currency);\n }\n\n /**\n * Calculate a percentage of this money\n * @example money.percentage(10) returns 10% of the amount\n */\n percentage(percent: number): Money {\n return new Money(Math.round((this.cents * percent) / 100), this.currency);\n }\n\n /**\n * Add a percentage to this money\n * @example money.addPercentage(19) adds 19% (like tax)\n */\n addPercentage(percent: number): Money {\n return this.add(this.percentage(percent));\n }\n\n /**\n * Subtract a percentage from this money\n * @example money.subtractPercentage(10) subtracts 10% (like discount)\n */\n subtractPercentage(percent: number): Money {\n return this.subtract(this.percentage(percent));\n }\n\n /**\n * Get the minimum of this and another money value\n */\n min(other: IMoney): Money {\n this.assertSameCurrency(other);\n return this.cents <= other.cents ? this : new Money(other.cents, this.currency);\n }\n\n /**\n * Get the maximum of this and another money value\n */\n max(other: IMoney): Money {\n this.assertSameCurrency(other);\n return this.cents >= other.cents ? this : new Money(other.cents, this.currency);\n }\n\n /**\n * Clamp this money between a minimum and maximum\n */\n clamp(minValue: IMoney, maxValue: IMoney): Money {\n return this.max(minValue).min(maxValue);\n }\n\n /**\n * Get cents (smallest unit)\n */\n toCents(): number {\n return this.cents;\n }\n\n /**\n * Check if within a range (inclusive)\n */\n isBetween(min: IMoney, max: IMoney): boolean {\n this.assertSameCurrency(min);\n this.assertSameCurrency(max);\n return this.cents >= min.cents && this.cents <= max.cents;\n }\n\n /**\n * Sum multiple money values\n */\n static sum(values: IMoney[]): Money {\n if (values.length === 0) {\n throw new Error('Cannot sum empty array');\n }\n const currency = values[0].currency;\n const total = values.reduce((sum, m) => {\n if (m.currency.code !== currency.code) {\n throw new Error('Cannot sum different currencies');\n }\n return sum + m.cents;\n }, 0);\n return new Money(total, currency);\n }\n\n /**\n * Get the minimum from an array of money values\n */\n static minimum(values: IMoney[]): Money {\n if (values.length === 0) {\n throw new Error('Cannot get minimum of empty array');\n }\n return values.reduce((min, m) => (m.cents < min.cents ? m : min)) as Money;\n }\n\n /**\n * Get the maximum from an array of money values\n */\n static maximum(values: IMoney[]): Money {\n if (values.length === 0) {\n throw new Error('Cannot get maximum of empty array');\n }\n return values.reduce((max, m) => (m.cents > max.cents ? m : max)) as Money;\n }\n\n /**\n * Calculate the average of money values\n */\n static average(values: IMoney[]): Money {\n if (values.length === 0) {\n throw new Error('Cannot calculate average of empty array');\n }\n const total = Money.sum(values);\n return total.divide(values.length);\n }\n\n /**\n * Convert to JSON-serializable object\n */\n toJSON(): { cents: number; currency: string } {\n return {\n cents: this.cents,\n currency: this.currency.code,\n };\n }\n\n /**\n * String representation\n */\n toString(): string {\n return this.format();\n }\n\n private formatInteger(intStr: string): string {\n const parts: string[] = [];\n let remaining = intStr;\n\n while (remaining.length > 3) {\n parts.unshift(remaining.slice(-3));\n remaining = remaining.slice(0, -3);\n }\n\n if (remaining) {\n parts.unshift(remaining);\n }\n\n return parts.join(this.currency.thousandsSeparator);\n }\n\n private assertSameCurrency(other: IMoney): void {\n if (this.currency.code !== other.currency.code) {\n throw new Error(\n `Cannot perform operation with different currencies: ${this.currency.code} and ${other.currency.code}`\n );\n }\n }\n}\n","import type { Currency } from '../core/types.js';\n\n/**\n * Colombian Peso (COP)\n * Format: $ 1.000,00\n */\nexport const COP: Currency = {\n code: 'COP',\n symbol: '$',\n decimals: 2,\n thousandsSeparator: '.',\n decimalSeparator: ',',\n symbolPosition: 'before',\n symbolSpacing: true,\n};\n\n/**\n * Colombian Peso without decimals (common usage)\n * Format: $ 1.000\n */\nexport const COP_NO_DECIMALS: Currency = {\n ...COP,\n decimals: 0,\n};\n","import type { Currency } from '../core/types.js';\n\n/**\n * Mexican Peso (MXN)\n * Format: $1,000.00\n */\nexport const MXN: Currency = {\n code: 'MXN',\n symbol: '$',\n decimals: 2,\n thousandsSeparator: ',',\n decimalSeparator: '.',\n symbolPosition: 'before',\n symbolSpacing: false,\n};\n","import type { Currency } from '../core/types.js';\n\n/**\n * Argentine Peso (ARS)\n * Format: $ 1.000,00\n */\nexport const ARS: Currency = {\n code: 'ARS',\n symbol: '$',\n decimals: 2,\n thousandsSeparator: '.',\n decimalSeparator: ',',\n symbolPosition: 'before',\n symbolSpacing: true,\n};\n","import type { Currency } from '../core/types.js';\n\n/**\n * Brazilian Real (BRL)\n * Format: R$ 1.000,00\n */\nexport const BRL: Currency = {\n code: 'BRL',\n symbol: 'R$',\n decimals: 2,\n thousandsSeparator: '.',\n decimalSeparator: ',',\n symbolPosition: 'before',\n symbolSpacing: true,\n};\n","import type { Currency } from '../core/types.js';\n\n/**\n * US Dollar (USD)\n * Format: $1,000.00\n */\nexport const USD: Currency = {\n code: 'USD',\n symbol: '$',\n decimals: 2,\n thousandsSeparator: ',',\n decimalSeparator: '.',\n symbolPosition: 'before',\n symbolSpacing: false,\n};\n","import type { Currency } from '../core/types.js';\n\n/**\n * Chilean Peso (CLP)\n * Format: $ 1.500\n * Note: CLP doesn't use decimal places in common usage\n */\nexport const CLP: Currency = {\n code: 'CLP',\n symbol: '$',\n decimals: 0,\n thousandsSeparator: '.',\n decimalSeparator: ',',\n symbolPosition: 'before',\n symbolSpacing: true,\n};\n\n/**\n * Chilean Peso with decimals (for precise calculations)\n * Format: $ 1.500,00\n */\nexport const CLP_DECIMALS: Currency = {\n ...CLP,\n decimals: 2,\n};\n","import type { Currency } from '../core/types.js';\n\n/**\n * Peruvian Sol (PEN)\n * Format: S/ 1,500.00\n */\nexport const PEN: Currency = {\n code: 'PEN',\n symbol: 'S/',\n decimals: 2,\n thousandsSeparator: ',',\n decimalSeparator: '.',\n symbolPosition: 'before',\n symbolSpacing: true,\n};\n","import type { Currency } from '../core/types.js';\n\n/**\n * Uruguayan Peso (UYU)\n * Format: $ 1.500,00\n */\nexport const UYU: Currency = {\n code: 'UYU',\n symbol: '$',\n decimals: 2,\n thousandsSeparator: '.',\n decimalSeparator: ',',\n symbolPosition: 'before',\n symbolSpacing: true,\n};\n","import type { Currency } from '../core/types.js';\n\n/**\n * Euro (EUR)\n * Format: 1.500,00 €\n */\nexport const EUR: Currency = {\n code: 'EUR',\n symbol: '€',\n decimals: 2,\n thousandsSeparator: '.',\n decimalSeparator: ',',\n symbolPosition: 'after',\n symbolSpacing: true,\n};\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "soff-money",
3
- "version": "0.2.8",
3
+ "version": "0.2.9",
4
4
  "description": "Safe money handling for JavaScript with integer-based arithmetic and LATAM locale formatting",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",