@wirms/calculator-engine 1.0.1
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/dist/index.d.mts +56 -0
- package/dist/index.d.ts +56 -0
- package/dist/index.js +141 -0
- package/dist/index.mjs +110 -0
- package/package.json +31 -0
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
interface DSCRInput {
|
|
2
|
+
/** Purchase price or current value */
|
|
3
|
+
purchasePrice: number;
|
|
4
|
+
/** Loan-to-value ratio as decimal (e.g. 0.75) */
|
|
5
|
+
ltv: number;
|
|
6
|
+
/** Annual interest rate as decimal (e.g. 0.08 for 8%) */
|
|
7
|
+
interestRate: number;
|
|
8
|
+
/** Loan term in years */
|
|
9
|
+
loanTermYears: number;
|
|
10
|
+
/** Amortization period in years */
|
|
11
|
+
amortizationYears: number;
|
|
12
|
+
/** Monthly gross rental income */
|
|
13
|
+
monthlyRent: number;
|
|
14
|
+
/** Monthly vacancy allowance (dollar amount) */
|
|
15
|
+
vacancyAmount?: number;
|
|
16
|
+
/** Monthly management fee (dollar amount) */
|
|
17
|
+
managementAmount?: number;
|
|
18
|
+
/** Monthly insurance */
|
|
19
|
+
monthlyInsurance?: number;
|
|
20
|
+
/** Monthly property taxes */
|
|
21
|
+
monthlyTaxes?: number;
|
|
22
|
+
/** Monthly HOA */
|
|
23
|
+
monthlyHOA?: number;
|
|
24
|
+
/** Other monthly expenses */
|
|
25
|
+
otherMonthlyExpenses?: number;
|
|
26
|
+
/** Whether this is an interest-only loan */
|
|
27
|
+
interestOnly?: boolean;
|
|
28
|
+
}
|
|
29
|
+
interface DSCRResult {
|
|
30
|
+
dscr: number;
|
|
31
|
+
loanAmount: number;
|
|
32
|
+
monthlyPayment: number;
|
|
33
|
+
annualNOI: number;
|
|
34
|
+
annualDebtService: number;
|
|
35
|
+
monthlyNOI: number;
|
|
36
|
+
grossMonthlyIncome: number;
|
|
37
|
+
totalMonthlyExpenses: number;
|
|
38
|
+
cashFlow: number;
|
|
39
|
+
/** DSCR tier label */
|
|
40
|
+
tier: 'excellent' | 'good' | 'acceptable' | 'weak' | 'negative';
|
|
41
|
+
}
|
|
42
|
+
interface SolverResult {
|
|
43
|
+
value: number;
|
|
44
|
+
resultingDSCR: number;
|
|
45
|
+
feasible: boolean;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
declare function clamp(value: number, min: number, max: number): number;
|
|
49
|
+
declare function formatCurrency(value: number, decimals?: number): string;
|
|
50
|
+
declare function calculateDSCR(input: DSCRInput): DSCRResult;
|
|
51
|
+
/** Find max loan amount that achieves targetDSCR */
|
|
52
|
+
declare function solveMaxLoan(input: Omit<DSCRInput, 'ltv'>, targetDSCR: number): SolverResult;
|
|
53
|
+
/** Find minimum monthly rent to achieve targetDSCR */
|
|
54
|
+
declare function solveMinRent(input: DSCRInput, targetDSCR: number): SolverResult;
|
|
55
|
+
|
|
56
|
+
export { type DSCRInput, type DSCRResult, type SolverResult, calculateDSCR, clamp, formatCurrency, solveMaxLoan, solveMinRent };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
interface DSCRInput {
|
|
2
|
+
/** Purchase price or current value */
|
|
3
|
+
purchasePrice: number;
|
|
4
|
+
/** Loan-to-value ratio as decimal (e.g. 0.75) */
|
|
5
|
+
ltv: number;
|
|
6
|
+
/** Annual interest rate as decimal (e.g. 0.08 for 8%) */
|
|
7
|
+
interestRate: number;
|
|
8
|
+
/** Loan term in years */
|
|
9
|
+
loanTermYears: number;
|
|
10
|
+
/** Amortization period in years */
|
|
11
|
+
amortizationYears: number;
|
|
12
|
+
/** Monthly gross rental income */
|
|
13
|
+
monthlyRent: number;
|
|
14
|
+
/** Monthly vacancy allowance (dollar amount) */
|
|
15
|
+
vacancyAmount?: number;
|
|
16
|
+
/** Monthly management fee (dollar amount) */
|
|
17
|
+
managementAmount?: number;
|
|
18
|
+
/** Monthly insurance */
|
|
19
|
+
monthlyInsurance?: number;
|
|
20
|
+
/** Monthly property taxes */
|
|
21
|
+
monthlyTaxes?: number;
|
|
22
|
+
/** Monthly HOA */
|
|
23
|
+
monthlyHOA?: number;
|
|
24
|
+
/** Other monthly expenses */
|
|
25
|
+
otherMonthlyExpenses?: number;
|
|
26
|
+
/** Whether this is an interest-only loan */
|
|
27
|
+
interestOnly?: boolean;
|
|
28
|
+
}
|
|
29
|
+
interface DSCRResult {
|
|
30
|
+
dscr: number;
|
|
31
|
+
loanAmount: number;
|
|
32
|
+
monthlyPayment: number;
|
|
33
|
+
annualNOI: number;
|
|
34
|
+
annualDebtService: number;
|
|
35
|
+
monthlyNOI: number;
|
|
36
|
+
grossMonthlyIncome: number;
|
|
37
|
+
totalMonthlyExpenses: number;
|
|
38
|
+
cashFlow: number;
|
|
39
|
+
/** DSCR tier label */
|
|
40
|
+
tier: 'excellent' | 'good' | 'acceptable' | 'weak' | 'negative';
|
|
41
|
+
}
|
|
42
|
+
interface SolverResult {
|
|
43
|
+
value: number;
|
|
44
|
+
resultingDSCR: number;
|
|
45
|
+
feasible: boolean;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
declare function clamp(value: number, min: number, max: number): number;
|
|
49
|
+
declare function formatCurrency(value: number, decimals?: number): string;
|
|
50
|
+
declare function calculateDSCR(input: DSCRInput): DSCRResult;
|
|
51
|
+
/** Find max loan amount that achieves targetDSCR */
|
|
52
|
+
declare function solveMaxLoan(input: Omit<DSCRInput, 'ltv'>, targetDSCR: number): SolverResult;
|
|
53
|
+
/** Find minimum monthly rent to achieve targetDSCR */
|
|
54
|
+
declare function solveMinRent(input: DSCRInput, targetDSCR: number): SolverResult;
|
|
55
|
+
|
|
56
|
+
export { type DSCRInput, type DSCRResult, type SolverResult, calculateDSCR, clamp, formatCurrency, solveMaxLoan, solveMinRent };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/index.ts
|
|
21
|
+
var index_exports = {};
|
|
22
|
+
__export(index_exports, {
|
|
23
|
+
calculateDSCR: () => calculateDSCR,
|
|
24
|
+
clamp: () => clamp,
|
|
25
|
+
formatCurrency: () => formatCurrency,
|
|
26
|
+
solveMaxLoan: () => solveMaxLoan,
|
|
27
|
+
solveMinRent: () => solveMinRent
|
|
28
|
+
});
|
|
29
|
+
module.exports = __toCommonJS(index_exports);
|
|
30
|
+
|
|
31
|
+
// src/dscr/engine.ts
|
|
32
|
+
function clamp(value, min, max) {
|
|
33
|
+
return Math.max(min, Math.min(max, value));
|
|
34
|
+
}
|
|
35
|
+
function formatCurrency(value, decimals = 0) {
|
|
36
|
+
return new Intl.NumberFormat("en-US", {
|
|
37
|
+
style: "currency",
|
|
38
|
+
currency: "USD",
|
|
39
|
+
minimumFractionDigits: decimals,
|
|
40
|
+
maximumFractionDigits: decimals
|
|
41
|
+
}).format(value);
|
|
42
|
+
}
|
|
43
|
+
function calcMonthlyPayment(principal, annualRate, amortYears, interestOnly) {
|
|
44
|
+
if (principal <= 0 || annualRate <= 0) return 0;
|
|
45
|
+
const monthlyRate = annualRate / 12;
|
|
46
|
+
if (interestOnly) return principal * monthlyRate;
|
|
47
|
+
const n = amortYears * 12;
|
|
48
|
+
return principal * monthlyRate * Math.pow(1 + monthlyRate, n) / (Math.pow(1 + monthlyRate, n) - 1);
|
|
49
|
+
}
|
|
50
|
+
function getDSCRTier(dscr) {
|
|
51
|
+
if (dscr >= 1.5) return "excellent";
|
|
52
|
+
if (dscr >= 1.25) return "good";
|
|
53
|
+
if (dscr >= 1) return "acceptable";
|
|
54
|
+
if (dscr >= 0) return "weak";
|
|
55
|
+
return "negative";
|
|
56
|
+
}
|
|
57
|
+
function calculateDSCR(input) {
|
|
58
|
+
const loanAmount = input.purchasePrice * input.ltv;
|
|
59
|
+
const monthlyPayment = calcMonthlyPayment(
|
|
60
|
+
loanAmount,
|
|
61
|
+
input.interestRate,
|
|
62
|
+
input.amortizationYears,
|
|
63
|
+
input.interestOnly ?? false
|
|
64
|
+
);
|
|
65
|
+
const grossMonthly = input.monthlyRent;
|
|
66
|
+
const totalExpenses = (input.vacancyAmount ?? 0) + (input.managementAmount ?? 0) + (input.monthlyInsurance ?? 0) + (input.monthlyTaxes ?? 0) + (input.monthlyHOA ?? 0) + (input.otherMonthlyExpenses ?? 0);
|
|
67
|
+
const monthlyNOI = grossMonthly - totalExpenses;
|
|
68
|
+
const annualNOI = monthlyNOI * 12;
|
|
69
|
+
const annualDebtService = monthlyPayment * 12;
|
|
70
|
+
const dscr = annualDebtService > 0 ? annualNOI / annualDebtService : 0;
|
|
71
|
+
const cashFlow = monthlyNOI - monthlyPayment;
|
|
72
|
+
return {
|
|
73
|
+
dscr: Math.round(dscr * 100) / 100,
|
|
74
|
+
loanAmount: Math.round(loanAmount),
|
|
75
|
+
monthlyPayment: Math.round(monthlyPayment * 100) / 100,
|
|
76
|
+
annualNOI: Math.round(annualNOI),
|
|
77
|
+
annualDebtService: Math.round(annualDebtService),
|
|
78
|
+
monthlyNOI: Math.round(monthlyNOI * 100) / 100,
|
|
79
|
+
grossMonthlyIncome: grossMonthly,
|
|
80
|
+
totalMonthlyExpenses: totalExpenses,
|
|
81
|
+
cashFlow: Math.round(cashFlow * 100) / 100,
|
|
82
|
+
tier: getDSCRTier(dscr)
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
function solveMaxLoan(input, targetDSCR) {
|
|
86
|
+
const grossMonthly = input.monthlyRent;
|
|
87
|
+
const totalExpenses = (input.vacancyAmount ?? 0) + (input.managementAmount ?? 0) + (input.monthlyInsurance ?? 0) + (input.monthlyTaxes ?? 0) + (input.monthlyHOA ?? 0) + (input.otherMonthlyExpenses ?? 0);
|
|
88
|
+
const monthlyNOI = grossMonthly - totalExpenses;
|
|
89
|
+
const annualNOI = monthlyNOI * 12;
|
|
90
|
+
const maxAnnualDebtService = annualNOI / targetDSCR;
|
|
91
|
+
const maxMonthlyPayment = maxAnnualDebtService / 12;
|
|
92
|
+
if (maxMonthlyPayment <= 0) {
|
|
93
|
+
return { value: 0, resultingDSCR: 0, feasible: false };
|
|
94
|
+
}
|
|
95
|
+
const monthlyRate = input.interestRate / 12;
|
|
96
|
+
let maxLoan;
|
|
97
|
+
if (input.interestOnly) {
|
|
98
|
+
maxLoan = maxMonthlyPayment / monthlyRate;
|
|
99
|
+
} else {
|
|
100
|
+
const n = input.amortizationYears * 12;
|
|
101
|
+
maxLoan = maxMonthlyPayment * (Math.pow(1 + monthlyRate, n) - 1) / (monthlyRate * Math.pow(1 + monthlyRate, n));
|
|
102
|
+
}
|
|
103
|
+
const result = calculateDSCR({
|
|
104
|
+
...input,
|
|
105
|
+
purchasePrice: maxLoan,
|
|
106
|
+
ltv: 1
|
|
107
|
+
});
|
|
108
|
+
return {
|
|
109
|
+
value: Math.round(maxLoan),
|
|
110
|
+
resultingDSCR: result.dscr,
|
|
111
|
+
feasible: maxLoan > 0
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
function solveMinRent(input, targetDSCR) {
|
|
115
|
+
const loanAmount = input.purchasePrice * input.ltv;
|
|
116
|
+
const monthlyPayment = calcMonthlyPayment(
|
|
117
|
+
loanAmount,
|
|
118
|
+
input.interestRate,
|
|
119
|
+
input.amortizationYears,
|
|
120
|
+
input.interestOnly ?? false
|
|
121
|
+
);
|
|
122
|
+
const annualDebtService = monthlyPayment * 12;
|
|
123
|
+
const requiredAnnualNOI = targetDSCR * annualDebtService;
|
|
124
|
+
const requiredMonthlyNOI = requiredAnnualNOI / 12;
|
|
125
|
+
const totalExpenses = (input.vacancyAmount ?? 0) + (input.managementAmount ?? 0) + (input.monthlyInsurance ?? 0) + (input.monthlyTaxes ?? 0) + (input.monthlyHOA ?? 0) + (input.otherMonthlyExpenses ?? 0);
|
|
126
|
+
const minRent = requiredMonthlyNOI + totalExpenses;
|
|
127
|
+
const result = calculateDSCR({ ...input, monthlyRent: minRent });
|
|
128
|
+
return {
|
|
129
|
+
value: Math.round(minRent),
|
|
130
|
+
resultingDSCR: result.dscr,
|
|
131
|
+
feasible: minRent > 0
|
|
132
|
+
};
|
|
133
|
+
}
|
|
134
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
135
|
+
0 && (module.exports = {
|
|
136
|
+
calculateDSCR,
|
|
137
|
+
clamp,
|
|
138
|
+
formatCurrency,
|
|
139
|
+
solveMaxLoan,
|
|
140
|
+
solveMinRent
|
|
141
|
+
});
|
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
// src/dscr/engine.ts
|
|
2
|
+
function clamp(value, min, max) {
|
|
3
|
+
return Math.max(min, Math.min(max, value));
|
|
4
|
+
}
|
|
5
|
+
function formatCurrency(value, decimals = 0) {
|
|
6
|
+
return new Intl.NumberFormat("en-US", {
|
|
7
|
+
style: "currency",
|
|
8
|
+
currency: "USD",
|
|
9
|
+
minimumFractionDigits: decimals,
|
|
10
|
+
maximumFractionDigits: decimals
|
|
11
|
+
}).format(value);
|
|
12
|
+
}
|
|
13
|
+
function calcMonthlyPayment(principal, annualRate, amortYears, interestOnly) {
|
|
14
|
+
if (principal <= 0 || annualRate <= 0) return 0;
|
|
15
|
+
const monthlyRate = annualRate / 12;
|
|
16
|
+
if (interestOnly) return principal * monthlyRate;
|
|
17
|
+
const n = amortYears * 12;
|
|
18
|
+
return principal * monthlyRate * Math.pow(1 + monthlyRate, n) / (Math.pow(1 + monthlyRate, n) - 1);
|
|
19
|
+
}
|
|
20
|
+
function getDSCRTier(dscr) {
|
|
21
|
+
if (dscr >= 1.5) return "excellent";
|
|
22
|
+
if (dscr >= 1.25) return "good";
|
|
23
|
+
if (dscr >= 1) return "acceptable";
|
|
24
|
+
if (dscr >= 0) return "weak";
|
|
25
|
+
return "negative";
|
|
26
|
+
}
|
|
27
|
+
function calculateDSCR(input) {
|
|
28
|
+
const loanAmount = input.purchasePrice * input.ltv;
|
|
29
|
+
const monthlyPayment = calcMonthlyPayment(
|
|
30
|
+
loanAmount,
|
|
31
|
+
input.interestRate,
|
|
32
|
+
input.amortizationYears,
|
|
33
|
+
input.interestOnly ?? false
|
|
34
|
+
);
|
|
35
|
+
const grossMonthly = input.monthlyRent;
|
|
36
|
+
const totalExpenses = (input.vacancyAmount ?? 0) + (input.managementAmount ?? 0) + (input.monthlyInsurance ?? 0) + (input.monthlyTaxes ?? 0) + (input.monthlyHOA ?? 0) + (input.otherMonthlyExpenses ?? 0);
|
|
37
|
+
const monthlyNOI = grossMonthly - totalExpenses;
|
|
38
|
+
const annualNOI = monthlyNOI * 12;
|
|
39
|
+
const annualDebtService = monthlyPayment * 12;
|
|
40
|
+
const dscr = annualDebtService > 0 ? annualNOI / annualDebtService : 0;
|
|
41
|
+
const cashFlow = monthlyNOI - monthlyPayment;
|
|
42
|
+
return {
|
|
43
|
+
dscr: Math.round(dscr * 100) / 100,
|
|
44
|
+
loanAmount: Math.round(loanAmount),
|
|
45
|
+
monthlyPayment: Math.round(monthlyPayment * 100) / 100,
|
|
46
|
+
annualNOI: Math.round(annualNOI),
|
|
47
|
+
annualDebtService: Math.round(annualDebtService),
|
|
48
|
+
monthlyNOI: Math.round(monthlyNOI * 100) / 100,
|
|
49
|
+
grossMonthlyIncome: grossMonthly,
|
|
50
|
+
totalMonthlyExpenses: totalExpenses,
|
|
51
|
+
cashFlow: Math.round(cashFlow * 100) / 100,
|
|
52
|
+
tier: getDSCRTier(dscr)
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
function solveMaxLoan(input, targetDSCR) {
|
|
56
|
+
const grossMonthly = input.monthlyRent;
|
|
57
|
+
const totalExpenses = (input.vacancyAmount ?? 0) + (input.managementAmount ?? 0) + (input.monthlyInsurance ?? 0) + (input.monthlyTaxes ?? 0) + (input.monthlyHOA ?? 0) + (input.otherMonthlyExpenses ?? 0);
|
|
58
|
+
const monthlyNOI = grossMonthly - totalExpenses;
|
|
59
|
+
const annualNOI = monthlyNOI * 12;
|
|
60
|
+
const maxAnnualDebtService = annualNOI / targetDSCR;
|
|
61
|
+
const maxMonthlyPayment = maxAnnualDebtService / 12;
|
|
62
|
+
if (maxMonthlyPayment <= 0) {
|
|
63
|
+
return { value: 0, resultingDSCR: 0, feasible: false };
|
|
64
|
+
}
|
|
65
|
+
const monthlyRate = input.interestRate / 12;
|
|
66
|
+
let maxLoan;
|
|
67
|
+
if (input.interestOnly) {
|
|
68
|
+
maxLoan = maxMonthlyPayment / monthlyRate;
|
|
69
|
+
} else {
|
|
70
|
+
const n = input.amortizationYears * 12;
|
|
71
|
+
maxLoan = maxMonthlyPayment * (Math.pow(1 + monthlyRate, n) - 1) / (monthlyRate * Math.pow(1 + monthlyRate, n));
|
|
72
|
+
}
|
|
73
|
+
const result = calculateDSCR({
|
|
74
|
+
...input,
|
|
75
|
+
purchasePrice: maxLoan,
|
|
76
|
+
ltv: 1
|
|
77
|
+
});
|
|
78
|
+
return {
|
|
79
|
+
value: Math.round(maxLoan),
|
|
80
|
+
resultingDSCR: result.dscr,
|
|
81
|
+
feasible: maxLoan > 0
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
function solveMinRent(input, targetDSCR) {
|
|
85
|
+
const loanAmount = input.purchasePrice * input.ltv;
|
|
86
|
+
const monthlyPayment = calcMonthlyPayment(
|
|
87
|
+
loanAmount,
|
|
88
|
+
input.interestRate,
|
|
89
|
+
input.amortizationYears,
|
|
90
|
+
input.interestOnly ?? false
|
|
91
|
+
);
|
|
92
|
+
const annualDebtService = monthlyPayment * 12;
|
|
93
|
+
const requiredAnnualNOI = targetDSCR * annualDebtService;
|
|
94
|
+
const requiredMonthlyNOI = requiredAnnualNOI / 12;
|
|
95
|
+
const totalExpenses = (input.vacancyAmount ?? 0) + (input.managementAmount ?? 0) + (input.monthlyInsurance ?? 0) + (input.monthlyTaxes ?? 0) + (input.monthlyHOA ?? 0) + (input.otherMonthlyExpenses ?? 0);
|
|
96
|
+
const minRent = requiredMonthlyNOI + totalExpenses;
|
|
97
|
+
const result = calculateDSCR({ ...input, monthlyRent: minRent });
|
|
98
|
+
return {
|
|
99
|
+
value: Math.round(minRent),
|
|
100
|
+
resultingDSCR: result.dscr,
|
|
101
|
+
feasible: minRent > 0
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
export {
|
|
105
|
+
calculateDSCR,
|
|
106
|
+
clamp,
|
|
107
|
+
formatCurrency,
|
|
108
|
+
solveMaxLoan,
|
|
109
|
+
solveMinRent
|
|
110
|
+
};
|
package/package.json
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@wirms/calculator-engine",
|
|
3
|
+
"version": "1.0.1",
|
|
4
|
+
"description": "Pure TypeScript DSCR and investor calculator engine — zero dependencies",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"module": "dist/index.mjs",
|
|
7
|
+
"types": "dist/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"types": "./dist/index.d.ts",
|
|
11
|
+
"import": "./dist/index.mjs",
|
|
12
|
+
"require": "./dist/index.js"
|
|
13
|
+
}
|
|
14
|
+
},
|
|
15
|
+
"files": ["dist"],
|
|
16
|
+
"scripts": {
|
|
17
|
+
"build": "tsup src/index.ts --format cjs,esm --dts --clean",
|
|
18
|
+
"dev": "tsup src/index.ts --format cjs,esm --dts --watch"
|
|
19
|
+
},
|
|
20
|
+
"devDependencies": {
|
|
21
|
+
"tsup": "^8.0.0",
|
|
22
|
+
"typescript": "^5.4.0"
|
|
23
|
+
},
|
|
24
|
+
"repository": {
|
|
25
|
+
"type": "git",
|
|
26
|
+
"url": "https://github.com/roasst/investor-tools.git",
|
|
27
|
+
"directory": "packages/calculator-engine"
|
|
28
|
+
},
|
|
29
|
+
"author": "WIRMS <luke@roasst.com>",
|
|
30
|
+
"license": "UNLICENSED"
|
|
31
|
+
}
|