financial-calculators-ts 0.4.0

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.
Files changed (35) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +621 -0
  3. package/dist/calculators/AutoLoan.d.ts +42 -0
  4. package/dist/calculators/AutoLoan.js +65 -0
  5. package/dist/calculators/BreakEven.d.ts +43 -0
  6. package/dist/calculators/BreakEven.js +66 -0
  7. package/dist/calculators/CompoundInterest.d.ts +43 -0
  8. package/dist/calculators/CompoundInterest.js +88 -0
  9. package/dist/calculators/DebtPayoff.d.ts +39 -0
  10. package/dist/calculators/DebtPayoff.js +72 -0
  11. package/dist/calculators/DollarCostAveraging.d.ts +41 -0
  12. package/dist/calculators/DollarCostAveraging.js +67 -0
  13. package/dist/calculators/InflationAdjustedReturn.d.ts +36 -0
  14. package/dist/calculators/InflationAdjustedReturn.js +52 -0
  15. package/dist/calculators/LoanAmortization.d.ts +48 -0
  16. package/dist/calculators/LoanAmortization.js +86 -0
  17. package/dist/calculators/PresentValue.d.ts +31 -0
  18. package/dist/calculators/PresentValue.js +53 -0
  19. package/dist/calculators/ROI.d.ts +42 -0
  20. package/dist/calculators/ROI.js +61 -0
  21. package/dist/calculators/RetirementSavings.d.ts +45 -0
  22. package/dist/calculators/RetirementSavings.js +81 -0
  23. package/dist/calculators/RuleOf72.d.ts +36 -0
  24. package/dist/calculators/RuleOf72.js +45 -0
  25. package/dist/calculators/SavingsGoal.d.ts +47 -0
  26. package/dist/calculators/SavingsGoal.js +84 -0
  27. package/dist/calculators/SimpleInterest.d.ts +26 -0
  28. package/dist/calculators/SimpleInterest.js +46 -0
  29. package/dist/calculators/TaxBracket.d.ts +53 -0
  30. package/dist/calculators/TaxBracket.js +86 -0
  31. package/dist/calculators/mortgage.d.ts +40 -0
  32. package/dist/calculators/mortgage.js +87 -0
  33. package/dist/index.d.ts +28 -0
  34. package/dist/index.js +38 -0
  35. package/package.json +48 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2023 jklamert
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,621 @@
1
+ # Calculators
2
+
3
+ [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](https://opensource.org/licenses/MIT)
4
+ [![TypeScript](https://img.shields.io/badge/TypeScript-6.0-3178C6.svg)](https://www.typescriptlang.org/)
5
+ [![Node.js](https://img.shields.io/badge/Node.js-%3E%3D18-339933.svg)](https://nodejs.org/)
6
+ [![Tests](https://img.shields.io/badge/Tests-173%20passing-brightgreen.svg)](#testing)
7
+
8
+ A TypeScript library of **15 financial calculators** covering interest, loans, investments, taxes, and business analysis. Zero dependencies, fully typed, with strict mode enabled.
9
+
10
+ ---
11
+
12
+ ## Table of Contents
13
+
14
+ - [Installation](#installation)
15
+ - [Quick Start](#quick-start)
16
+ - [Calculators](#calculators)
17
+ - [Interest & Growth](#interest--growth)
18
+ - [Loans & Debt](#loans--debt)
19
+ - [Investments & Savings](#investments--savings)
20
+ - [Tax & Business](#tax--business)
21
+ - [Scripts](#scripts)
22
+ - [Testing](#testing)
23
+ - [Contributing](#contributing)
24
+ - [License](#license)
25
+
26
+ ---
27
+
28
+ ## Installation
29
+
30
+ ```bash
31
+ npm install calculators
32
+ ```
33
+
34
+ Or clone and build from source:
35
+
36
+ ```bash
37
+ git clone https://github.com/your-username/Calculators.git
38
+ cd Calculators
39
+ npm install
40
+ npm run build
41
+ ```
42
+
43
+ ## Quick Start
44
+
45
+ ```typescript
46
+ import { Mortgage, CompoundInterest, Compound } from "calculators";
47
+
48
+ // Calculate monthly mortgage payment
49
+ const mortgage = new Mortgage(350000, 70000, 6.5, 30);
50
+ const result = mortgage.calculate();
51
+ console.log(result.monthlyPayment); // 1770.27
52
+
53
+ // Calculate compound interest
54
+ const ci = new CompoundInterest(10000, 5, 10, Compound.Monthly);
55
+ console.log(ci.calculate()); // 16470.09
56
+ ```
57
+
58
+ ## Calculators
59
+
60
+ ### Interest & Growth
61
+
62
+ #### SimpleInterest
63
+
64
+ Calculates simple interest using `A = P(1 + rt)`.
65
+
66
+ ```typescript
67
+ import { SimpleInterest } from "calculators";
68
+
69
+ const si = new SimpleInterest(1000, 5, 3);
70
+ // constructor(principal, ratePercentage, years)
71
+ console.log(si.calculate()); // 1150.00
72
+ ```
73
+
74
+ | Parameter | Type | Description |
75
+ |---|---|---|
76
+ | `principal` | `number` | Initial amount (must be > 0) |
77
+ | `ratePercentage` | `number` | Annual rate as a percentage, 0-100 |
78
+ | `years` | `number` | Time period in years (>= 0) |
79
+
80
+ **Returns:** `number` — the total amount (principal + interest).
81
+
82
+ ---
83
+
84
+ #### CompoundInterest
85
+
86
+ Calculates compound interest using `A = P(1 + r/n)^(nt)`.
87
+
88
+ ```typescript
89
+ import { CompoundInterest, Compound } from "calculators";
90
+
91
+ const ci = new CompoundInterest(5000, 8, 5, Compound.Quarterly);
92
+ console.log(ci.calculate()); // 7429.74
93
+ ```
94
+
95
+ | Parameter | Type | Description |
96
+ |---|---|---|
97
+ | `principal` | `number` | Initial amount (must be > 0) |
98
+ | `ratePercentage` | `number` | Annual rate, 0-100 |
99
+ | `years` | `number` | Time period (must be > 0) |
100
+ | `compound` | `Compound` | `Compound.Monthly`, `Compound.Quarterly`, or `Compound.Annually` |
101
+
102
+ **Returns:** `number` — the total amount after compounding.
103
+
104
+ ---
105
+
106
+ #### RuleOf72
107
+
108
+ Estimates the time required to double an investment.
109
+
110
+ ```typescript
111
+ import { RuleOf72 } from "calculators";
112
+
113
+ const r72 = new RuleOf72(8);
114
+ const result = r72.calculate();
115
+ console.log(result.estimatedYears); // 9
116
+ console.log(result.exactYears); // 9.01
117
+ ```
118
+
119
+ | Parameter | Type | Description |
120
+ |---|---|---|
121
+ | `ratePercentage` | `number` | Annual rate, 0 < rate < 100 |
122
+
123
+ **Returns:** `RuleOf72Result`
124
+
125
+ | Field | Type | Description |
126
+ |---|---|---|
127
+ | `estimatedYears` | `number` | 72 / rate (rounded to 2 decimals) |
128
+ | `exactYears` | `number` | ln(2) / ln(1 + rate/100) |
129
+
130
+ ---
131
+
132
+ ### Loans & Debt
133
+
134
+ #### Mortgage
135
+
136
+ Calculates monthly and yearly mortgage payments.
137
+
138
+ ```typescript
139
+ import { Mortgage } from "calculators";
140
+
141
+ const m = new Mortgage(300000, 60000, 6, 30);
142
+ // constructor(amount, downPayment, ratePercentage, years)
143
+ const result = m.calculate();
144
+ console.log(result.monthlyPayment); // 1438.92
145
+ console.log(result.yearlyPayment); // 17267.04
146
+ console.log(result.totalNumberOfPayments); // 360
147
+ ```
148
+
149
+ | Parameter | Type | Description |
150
+ |---|---|---|
151
+ | `amount` | `number` | Total property price (must be > 0) |
152
+ | `downPayment` | `number` | Down payment (>= 0, must be < amount) |
153
+ | `ratePercentage` | `number` | Annual rate, 0 < rate < 100 |
154
+ | `years` | `number` | Loan term as a positive integer |
155
+
156
+ **Returns:** `MortgageResult`
157
+
158
+ | Field | Type | Description |
159
+ |---|---|---|
160
+ | `monthlyPayment` | `number` | Monthly payment amount |
161
+ | `yearlyPayment` | `number` | Annual payment amount |
162
+ | `totalNumberOfPayments` | `number` | Total number of monthly payments |
163
+
164
+ ---
165
+
166
+ #### LoanAmortization
167
+
168
+ Generates a full amortization schedule with principal/interest breakdown per payment.
169
+
170
+ ```typescript
171
+ import { LoanAmortization } from "calculators";
172
+
173
+ const la = new LoanAmortization(200000, 6, 30);
174
+ const result = la.calculate();
175
+
176
+ console.log(result.monthlyPayment); // 1199.10
177
+ console.log(result.totalInterest); // 231677.04
178
+ console.log(result.schedule[0]);
179
+ // { payment: 1, principal: 199.10, interest: 1000.00, remainingBalance: 199800.90 }
180
+ ```
181
+
182
+ | Parameter | Type | Description |
183
+ |---|---|---|
184
+ | `loanAmount` | `number` | Loan principal (must be > 0) |
185
+ | `ratePercentage` | `number` | Annual rate, 0 < rate < 100 |
186
+ | `years` | `number` | Loan term as a positive integer (max 100) |
187
+
188
+ **Returns:** `AmortizationResult`
189
+
190
+ | Field | Type | Description |
191
+ |---|---|---|
192
+ | `monthlyPayment` | `number` | Fixed monthly payment |
193
+ | `totalPayments` | `number` | Total number of payments |
194
+ | `totalInterest` | `number` | Total interest paid over the life of the loan |
195
+ | `schedule` | `AmortizationEntry[]` | Per-payment breakdown |
196
+
197
+ Each `AmortizationEntry`:
198
+
199
+ | Field | Type | Description |
200
+ |---|---|---|
201
+ | `payment` | `number` | Payment number (1-indexed) |
202
+ | `principal` | `number` | Principal portion of the payment |
203
+ | `interest` | `number` | Interest portion of the payment |
204
+ | `remainingBalance` | `number` | Balance remaining after payment |
205
+
206
+ ---
207
+
208
+ #### AutoLoan
209
+
210
+ Calculates auto loan payments using the standard amortization formula, with term in months.
211
+
212
+ ```typescript
213
+ import { AutoLoan } from "calculators";
214
+
215
+ const al = new AutoLoan(35000, 5000, 4.5, 60);
216
+ // constructor(vehiclePrice, downPayment, ratePercentage, termMonths)
217
+ const result = al.calculate();
218
+ console.log(result.monthlyPayment); // 559.28
219
+ console.log(result.totalInterest); // 3556.80
220
+ ```
221
+
222
+ | Parameter | Type | Description |
223
+ |---|---|---|
224
+ | `vehiclePrice` | `number` | Vehicle price (must be > 0) |
225
+ | `downPayment` | `number` | Down payment (>= 0, must be < price) |
226
+ | `ratePercentage` | `number` | Annual rate, 0 < rate < 100 |
227
+ | `termMonths` | `number` | Loan term in months (positive integer) |
228
+
229
+ **Returns:** `AutoLoanResult`
230
+
231
+ | Field | Type | Description |
232
+ |---|---|---|
233
+ | `loanAmount` | `number` | Financed amount (price - down payment) |
234
+ | `monthlyPayment` | `number` | Monthly payment |
235
+ | `totalPaid` | `number` | Total of all payments |
236
+ | `totalInterest` | `number` | Total interest paid |
237
+
238
+ ---
239
+
240
+ #### DebtPayoff
241
+
242
+ Calculates how long it takes to pay off a debt with a fixed monthly payment.
243
+
244
+ ```typescript
245
+ import { DebtPayoff } from "calculators";
246
+
247
+ const dp = new DebtPayoff(5000, 18, 200);
248
+ // constructor(balance, ratePercentage, monthlyPayment)
249
+ const result = dp.calculate();
250
+ console.log(result.months); // 32
251
+ console.log(result.totalInterest); // 1313.97
252
+ ```
253
+
254
+ | Parameter | Type | Description |
255
+ |---|---|---|
256
+ | `balance` | `number` | Outstanding debt (must be > 0) |
257
+ | `ratePercentage` | `number` | Annual rate, 0 < rate < 100 |
258
+ | `monthlyPayment` | `number` | Fixed payment (must exceed monthly interest) |
259
+
260
+ **Returns:** `DebtPayoffResult`
261
+
262
+ | Field | Type | Description |
263
+ |---|---|---|
264
+ | `months` | `number` | Number of months to pay off |
265
+ | `totalPaid` | `number` | Total amount paid |
266
+ | `totalInterest` | `number` | Total interest paid |
267
+
268
+ ---
269
+
270
+ ### Investments & Savings
271
+
272
+ #### RetirementSavings
273
+
274
+ Projects the future value of retirement savings with regular contributions.
275
+
276
+ ```typescript
277
+ import { RetirementSavings } from "calculators";
278
+
279
+ const rs = new RetirementSavings(50000, 500, 7, 25);
280
+ // constructor(initialBalance, monthlyContribution, ratePercentage, years)
281
+ const result = rs.calculate();
282
+ console.log(result.futureValue); // 676,570+ (varies by rounding)
283
+ console.log(result.totalContributions); // 150000
284
+ console.log(result.totalInterest); // futureValue - 50000 - 150000
285
+ ```
286
+
287
+ | Parameter | Type | Description |
288
+ |---|---|---|
289
+ | `initialBalance` | `number` | Starting balance (>= 0) |
290
+ | `monthlyContribution` | `number` | Monthly contribution (>= 0) |
291
+ | `ratePercentage` | `number` | Annual return rate, 0-100 |
292
+ | `years` | `number` | Investment horizon (must be > 0) |
293
+
294
+ **Returns:** `RetirementResult`
295
+
296
+ | Field | Type | Description |
297
+ |---|---|---|
298
+ | `futureValue` | `number` | Projected total value |
299
+ | `totalContributions` | `number` | Sum of all contributions |
300
+ | `totalInterest` | `number` | Total growth from interest |
301
+
302
+ ---
303
+
304
+ #### PresentValue
305
+
306
+ Calculates the present value of a future sum: `PV = FV / (1 + r)^n`.
307
+
308
+ ```typescript
309
+ import { PresentValue } from "calculators";
310
+
311
+ const pv = new PresentValue(10000, 5, 10);
312
+ // constructor(futureValue, ratePercentage, years)
313
+ console.log(pv.calculate()); // 6139.13
314
+ ```
315
+
316
+ | Parameter | Type | Description |
317
+ |---|---|---|
318
+ | `futureValue` | `number` | Future amount (must be > 0) |
319
+ | `ratePercentage` | `number` | Discount rate, 0-100 |
320
+ | `years` | `number` | Time period (must be > 0) |
321
+
322
+ **Returns:** `number` — the present value.
323
+
324
+ ---
325
+
326
+ #### SavingsGoal
327
+
328
+ Calculates the monthly savings needed to reach a financial goal.
329
+
330
+ ```typescript
331
+ import { SavingsGoal } from "calculators";
332
+
333
+ const sg = new SavingsGoal(50000, 10000, 5, 5);
334
+ // constructor(goalAmount, currentSavings, ratePercentage, years)
335
+ const result = sg.calculate();
336
+ console.log(result.monthlySavings); // ~588
337
+ console.log(result.totalContributions); // monthlySavings * 60
338
+ console.log(result.interestEarned); // goal - currentSavings - contributions
339
+ ```
340
+
341
+ | Parameter | Type | Description |
342
+ |---|---|---|
343
+ | `goalAmount` | `number` | Target amount (must be > 0) |
344
+ | `currentSavings` | `number` | Current savings (>= 0, must be < goal) |
345
+ | `ratePercentage` | `number` | Annual return rate, 0-100 |
346
+ | `years` | `number` | Time horizon (must be > 0) |
347
+
348
+ **Returns:** `SavingsGoalResult`
349
+
350
+ | Field | Type | Description |
351
+ |---|---|---|
352
+ | `monthlySavings` | `number` | Required monthly savings |
353
+ | `totalContributions` | `number` | Total amount contributed |
354
+ | `interestEarned` | `number` | Total interest earned |
355
+
356
+ ---
357
+
358
+ #### DollarCostAveraging
359
+
360
+ Simulates periodic fixed-amount investments at varying prices.
361
+
362
+ ```typescript
363
+ import { DollarCostAveraging } from "calculators";
364
+
365
+ const prices = [50, 45, 55, 40, 60];
366
+ const dca = new DollarCostAveraging(100, prices);
367
+ // constructor(investmentPerPeriod, prices)
368
+ const result = dca.calculate();
369
+ console.log(result.totalShares);
370
+ console.log(result.averageCostPerShare);
371
+ console.log(result.totalInvested); // 500
372
+ ```
373
+
374
+ | Parameter | Type | Description |
375
+ |---|---|---|
376
+ | `investmentPerPeriod` | `number` | Fixed investment amount (must be > 0) |
377
+ | `prices` | `number[]` | Array of prices per period (all must be > 0) |
378
+
379
+ **Returns:** `DCAResult`
380
+
381
+ | Field | Type | Description |
382
+ |---|---|---|
383
+ | `totalInvested` | `number` | Total amount invested |
384
+ | `totalShares` | `number` | Total shares purchased |
385
+ | `averageCostPerShare` | `number` | Average cost per share |
386
+ | `currentValue` | `number` | Value at the final price |
387
+ | `gainLoss` | `number` | Dollar gain or loss (currentValue - totalInvested) |
388
+
389
+ ---
390
+
391
+ #### ROI
392
+
393
+ Calculates return on investment with optional annualized ROI.
394
+
395
+ ```typescript
396
+ import { ROI } from "calculators";
397
+
398
+ const roi = new ROI(10000, 15000, 3);
399
+ // constructor(cost, revenue, years?)
400
+ const result = roi.calculate();
401
+ console.log(result.roi); // 50.00
402
+ console.log(result.annualizedRoi); // 14.47
403
+ console.log(result.netProfit); // 5000.00
404
+ ```
405
+
406
+ | Parameter | Type | Description |
407
+ |---|---|---|
408
+ | `cost` | `number` | Initial investment (must be > 0) |
409
+ | `revenue` | `number` | Total return (>= 0) |
410
+ | `years` | `number?` | Optional holding period for annualized ROI |
411
+
412
+ **Returns:** `ROIResult`
413
+
414
+ | Field | Type | Description |
415
+ |---|---|---|
416
+ | `roi` | `number` | ROI as a percentage |
417
+ | `annualizedRoi` | `number?` | Annualized ROI (if years provided) |
418
+ | `netProfit` | `number` | Revenue minus cost |
419
+
420
+ ---
421
+
422
+ #### InflationAdjustedReturn
423
+
424
+ Calculates the real rate of return after inflation using the Fisher equation.
425
+
426
+ ```typescript
427
+ import { InflationAdjustedReturn } from "calculators";
428
+
429
+ const iar = new InflationAdjustedReturn(10, 3);
430
+ // constructor(nominalRatePercentage, inflationRatePercentage)
431
+ const result = iar.calculate();
432
+ console.log(result.realReturn); // 6.80
433
+ ```
434
+
435
+ | Parameter | Type | Description |
436
+ |---|---|---|
437
+ | `nominalRatePercentage` | `number` | Nominal return rate, 0-100 |
438
+ | `inflationRatePercentage` | `number` | Inflation rate, 0 to <100 |
439
+
440
+ **Returns:** `InflationAdjustedResult`
441
+
442
+ | Field | Type | Description |
443
+ |---|---|---|
444
+ | `realReturn` | `number` | Real return percentage |
445
+ | `nominalRate` | `number` | Input nominal rate |
446
+ | `inflationRate` | `number` | Input inflation rate |
447
+
448
+ ---
449
+
450
+ ### Tax & Business
451
+
452
+ #### TaxBracket
453
+
454
+ Calculates progressive income tax with bracket breakdown.
455
+
456
+ ```typescript
457
+ import { TaxBracket } from "calculators";
458
+ import type { Bracket } from "calculators";
459
+
460
+ const brackets: Bracket[] = [
461
+ { min: 0, max: 11000, rate: 10 },
462
+ { min: 11000, max: 44725, rate: 12 },
463
+ { min: 44725, max: 95375, rate: 22 },
464
+ { min: 95375, max: 182100, rate: 24 },
465
+ ];
466
+
467
+ const tb = new TaxBracket(100000, brackets);
468
+ const result = tb.calculate();
469
+ console.log(result.totalTax); // Total tax owed
470
+ console.log(result.effectiveRate); // Effective tax rate %
471
+ console.log(result.marginalRate); // Highest applicable bracket rate
472
+ console.log(result.brackets); // Per-bracket breakdown
473
+ ```
474
+
475
+ | Parameter | Type | Description |
476
+ |---|---|---|
477
+ | `income` | `number` | Taxable income (must be > 0) |
478
+ | `taxBrackets` | `Bracket[]` | Array of tax brackets (non-overlapping) |
479
+
480
+ Each `Bracket`:
481
+
482
+ | Field | Type | Description |
483
+ |---|---|---|
484
+ | `min` | `number` | Bracket lower bound (>= 0) |
485
+ | `max` | `number` | Bracket upper bound (must be > min) |
486
+ | `rate` | `number` | Tax rate for this bracket, 0-100 |
487
+
488
+ **Returns:** `TaxBracketResult`
489
+
490
+ | Field | Type | Description |
491
+ |---|---|---|
492
+ | `totalTax` | `number` | Total tax owed |
493
+ | `effectiveRate` | `number` | Effective tax rate as a percentage |
494
+ | `marginalRate` | `number` | Marginal (highest applicable) tax rate |
495
+ | `brackets` | `BracketBreakdown[]` | Per-bracket tax detail |
496
+
497
+ ---
498
+
499
+ #### BreakEven
500
+
501
+ Calculates the break-even point in units and revenue.
502
+
503
+ ```typescript
504
+ import { BreakEven } from "calculators";
505
+
506
+ const be = new BreakEven(50000, 100, 60);
507
+ // constructor(fixedCosts, pricePerUnit, variableCostPerUnit)
508
+ const result = be.calculate();
509
+ console.log(result.breakEvenUnits); // 1250
510
+ console.log(result.breakEvenRevenue); // 125000
511
+ console.log(result.contributionMargin); // 40
512
+ ```
513
+
514
+ | Parameter | Type | Description |
515
+ |---|---|---|
516
+ | `fixedCosts` | `number` | Total fixed costs (must be > 0) |
517
+ | `pricePerUnit` | `number` | Selling price per unit (must be > 0) |
518
+ | `variableCostPerUnit` | `number` | Variable cost per unit (>= 0, must be < price) |
519
+
520
+ **Returns:** `BreakEvenResult`
521
+
522
+ | Field | Type | Description |
523
+ |---|---|---|
524
+ | `breakEvenUnits` | `number` | Units to sell to break even (rounded up) |
525
+ | `breakEvenRevenue` | `number` | Revenue at break-even point |
526
+ | `contributionMargin` | `number` | Price minus variable cost per unit |
527
+ | `contributionMarginRatio` | `number` | Contribution margin as a percentage of price |
528
+
529
+ ---
530
+
531
+ ## Scripts
532
+
533
+ | Command | Description |
534
+ |---|---|
535
+ | `npm test` | Run all tests with Jest |
536
+ | `npm run build` | Compile TypeScript to `dist/` |
537
+ | `npm run publish-lib` | Build and publish to npm |
538
+ | `npm run publish-beta` | Build and publish with `beta` tag |
539
+ | `npm run publish-dryrun` | Build and simulate publish |
540
+ | `npm run patch` | Bump patch version |
541
+ | `npm run minor` | Bump minor version |
542
+ | `npm run major` | Bump major version |
543
+
544
+ ## Testing
545
+
546
+ The library includes **173 tests** across 15 test suites covering:
547
+
548
+ - Input validation (boundary values, negative inputs, zero values)
549
+ - Mathematical correctness (verified against known financial formulas)
550
+ - Edge cases (rounding precision, exact payoff, single-period calculations)
551
+ - Safety guards (loop limits, maximum term lengths)
552
+
553
+ ```bash
554
+ npm test
555
+ ```
556
+
557
+ ## Project Structure
558
+
559
+ ```
560
+ Calculators/
561
+ app/
562
+ index.ts # Library entry point (all exports)
563
+ calculators/
564
+ SimpleInterest.ts
565
+ CompoundInterest.ts
566
+ mortgage.ts
567
+ LoanAmortization.ts
568
+ RetirementSavings.ts
569
+ PresentValue.ts
570
+ DebtPayoff.ts
571
+ ROI.ts
572
+ RuleOf72.ts
573
+ InflationAdjustedReturn.ts
574
+ DollarCostAveraging.ts
575
+ AutoLoan.ts
576
+ SavingsGoal.ts
577
+ BreakEven.ts
578
+ TaxBracket.ts
579
+ __tests__/ # Jest test suites (one per calculator)
580
+ dist/ # Compiled output (generated)
581
+ tsconfig.json # Build config (strict mode)
582
+ tsconfig.test.json # Test config (extends build)
583
+ jest.config.js # Jest configuration
584
+ ```
585
+
586
+ ## Contributing
587
+
588
+ 1. Fork the repository
589
+ 2. Create a feature branch: `git checkout -b feature/my-calculator`
590
+ 3. Write tests first (TDD) in `app/__tests__/`
591
+ 4. Implement the calculator in `app/calculators/`
592
+ 5. Export from `app/index.ts`
593
+ 6. Ensure all tests pass: `npm test`
594
+ 7. Ensure the build is clean: `npm run build`
595
+ 8. Submit a pull request
596
+
597
+ All calculators follow the same pattern:
598
+
599
+ ```typescript
600
+ export interface MyCalculatorResult {
601
+ // typed result fields
602
+ }
603
+
604
+ export default class MyCalculator {
605
+ constructor(/* parameters */) { /* assign fields */ }
606
+
607
+ _validate() {
608
+ // throw descriptive errors for invalid inputs
609
+ }
610
+
611
+ calculate(): MyCalculatorResult {
612
+ this._validate();
613
+ // computation with toFixed(2) rounding
614
+ return { /* result */ };
615
+ }
616
+ }
617
+ ```
618
+
619
+ ## License
620
+
621
+ [MIT](https://opensource.org/licenses/MIT)
@@ -0,0 +1,42 @@
1
+ export interface AutoLoanResult {
2
+ loanAmount: number;
3
+ monthlyPayment: number;
4
+ totalPaid: number;
5
+ totalInterest: number;
6
+ }
7
+ /**
8
+ * Auto loan calculator. Uses the standard amortization formula
9
+ * with term specified in months: M = P[r(1+r)^n] / [(1+r)^n - 1].
10
+ *
11
+ * @example
12
+ * ```typescript
13
+ * const al = new AutoLoan(35000, 5000, 4.5, 60);
14
+ * const result = al.calculate();
15
+ * result.monthlyPayment; // 559.28
16
+ * result.totalInterest; // 3556.80
17
+ * ```
18
+ */
19
+ export default class AutoLoan {
20
+ vehiclePrice: number;
21
+ downPayment: number;
22
+ rate: number;
23
+ termMonths: number;
24
+ /**
25
+ * @param vehiclePrice - Total vehicle price (must be > 0).
26
+ * @param downPayment - Down payment amount (>= 0, must be less than vehiclePrice).
27
+ * @param ratePercentage - Annual interest rate as a percentage (0 < rate < 100).
28
+ * @param termMonths - Loan term in months (positive integer).
29
+ */
30
+ constructor(vehiclePrice: number, downPayment: number, ratePercentage: number, termMonths: number);
31
+ /**
32
+ * Validates that all inputs are within acceptable ranges.
33
+ * @throws {Error} If any input is invalid.
34
+ */
35
+ _validate(): void;
36
+ /**
37
+ * Computes the monthly payment, total paid, and total interest for the auto loan.
38
+ * @returns An {@link AutoLoanResult} with loanAmount, monthlyPayment, totalPaid, and totalInterest.
39
+ * @throws {Error} If any input is invalid.
40
+ */
41
+ calculate(): AutoLoanResult;
42
+ }