@archerjessop/utilities 7.19.0 → 7.20.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.
@@ -0,0 +1,2 @@
1
+ import{INTEREST_RATE_TIERS as e,DEFAULT_CAP_RATE as r,determineInterestRateType as n,SELLER_FI_AMORTIZATION as t,SELLER_FI_INTEREST_RATE as c}from"../config/financial.js";import{resolveListingFinancials as o,calculateAssignmentFee as i,calculatePMT as l}from"./calculations.js";const s=[{downPercent:60,dscrPercent:70,sellerPercent:40},{downPercent:50,dscrPercent:60,sellerPercent:50},{downPercent:40,dscrPercent:50,sellerPercent:60},{downPercent:30,dscrPercent:40,sellerPercent:70},{downPercent:20,dscrPercent:30,sellerPercent:80}],u=s[s.length-1];function tierAnnualDebtService(e,r,n,o){return 12*l(r*(e.dscrPercent/100),n,o)+12*l(r*(e.sellerPercent/100),c,t)}function sweepTiers(e,r,n,t,c){for(const o of s){const i=e-tierAnnualDebtService(o,r,n,t),l=o.downPercent/100*r;if(i>0&&l>=c)return{cashFlow:i,tier:o}}return null}function calculateEquityCarryScore({bedroomCount:t=null,capRate:c,price:l,propertyType:s="mfr",units:a=null}={}){const d=Number(l);if(!Number.isFinite(d)||d<=0)return null;const p=null==c||""===c?NaN:Number(c),m=Number.isFinite(p)?p/100:null,P=Number(a),f=n(s,Number.isFinite(P)?P:void 0),{amortization:w,rate:b}=e[f],{noi:y}=o({bedroomCount:t,estimatedCapRate:r,price:d,propertyType:s,reportedCapRate:m});let N,_,h=sweepTiers(y,d,b,w,0);if(h)N="prospect",_=d;else{const e=.85*d;h=sweepTiers(y,e,b,w,0),h?(N="discount",_=e):(N="dead",_=d)}const C=y-tierAnnualDebtService(u,_,b,w),F=_>0?C/_:0;let S;return S="dead"===N?"none":F>.08?"high":F>=.04?"medium":"low",{assignment:i(_),cap_source:null===m?"estimate":"reported",cash_flow:h?h.cashFlow:null,deal_pool:N,downpayment_percent:h?h.tier.downPercent:-1,equity_tier:h?{...h.tier}:null,offer_price:_,raw_yield:F,yield_band:S}}export{s as EQUITY_CARRY_TIERS,calculateEquityCarryScore};
2
+ //# sourceMappingURL=equity-carry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"equity-carry.js","sources":["../../src/financial/equity-carry.js"],"sourcesContent":["// src/financial/equity-carry.js\n\nimport { DEFAULT_CAP_RATE, INTEREST_RATE_TIERS, SELLER_FI_AMORTIZATION, SELLER_FI_INTEREST_RATE, determineInterestRateType } from \"../config/financial.js\";\nimport { calculateAssignmentFee, calculatePMT, resolveListingFinancials } from \"./calculations.js\";\n\n/**\n * Equity Carry financing tiers (constant 110% leverage: DSCR % + seller carry % = 110).\n * Ordered highest down-payment first so a sweep stops at the strongest qualifying tier:\n * cash flow falls as the down payment rises (more of the stack moves to the market-rate\n * DSCR leg and off the 0% seller note), so the first tier that clears in a 60->20 sweep is\n * the highest down payment that still cash-flows.\n */\nexport const EQUITY_CARRY_TIERS = [\n { downPercent: 60, dscrPercent: 70, sellerPercent: 40 },\n { downPercent: 50, dscrPercent: 60, sellerPercent: 50 },\n { downPercent: 40, dscrPercent: 50, sellerPercent: 60 },\n { downPercent: 30, dscrPercent: 40, sellerPercent: 70 },\n { downPercent: 20, dscrPercent: 30, sellerPercent: 80 },\n];\n\nconst DISCOUNT_BASIS = 0.85;\nconst FIXED_YIELD_TIER = EQUITY_CARRY_TIERS[EQUITY_CARRY_TIERS.length - 1]; // 20% down\nconst YIELD_BAND_HIGH = 0.08;\nconst YIELD_BAND_MEDIUM = 0.04;\n\n/**\n * Annual debt service for one tier at a given price basis, from the suite primitives.\n * DSCR leg amortizes at the property's market rate/term; the seller carry leg is 0% / 30yr.\n * @param {{dscrPercent:number, sellerPercent:number}} tier\n * @param {number} basis - Price the financing is sized against (asking or discounted)\n * @param {number} dscrRate - DSCR annual interest rate (decimal)\n * @param {number} dscrAmortization - DSCR amortization (years)\n * @returns {number} Combined annual debt service (DSCR + seller carry)\n */\nfunction tierAnnualDebtService(tier, basis, dscrRate, dscrAmortization) {\n const dscrAnnual = calculatePMT(basis * (tier.dscrPercent / 100), dscrRate, dscrAmortization) * 12;\n const sellerAnnual = calculatePMT(basis * (tier.sellerPercent / 100), SELLER_FI_INTEREST_RATE, SELLER_FI_AMORTIZATION) * 12;\n return dscrAnnual + sellerAnnual;\n}\n\n/**\n * Sweep the tiers (60 -> 20) at one price basis; return the first (highest down payment)\n * tier whose annual cash flow is positive AND whose down payment covers any known debt.\n * @returns {{tier:object, cashFlow:number}|null} Winning tier + its annual cash flow, or null\n */\nfunction sweepTiers(noi, basis, dscrRate, dscrAmortization, estimatedDebt) {\n for (const tier of EQUITY_CARRY_TIERS) {\n const cashFlow = noi - tierAnnualDebtService(tier, basis, dscrRate, dscrAmortization);\n const downPayment = (tier.downPercent / 100) * basis;\n if (cashFlow > 0 && downPayment >= estimatedDebt) {\n return { cashFlow, tier };\n }\n }\n return null;\n}\n\n/**\n * Score a scraped listing with the Equity Carry Method and route it to a deal pool.\n *\n * Pure, no IO. Accepts inputs in the raw shape Postgres returns: `price` and `capRate` may\n * be NUMERIC strings, and `capRate` is a PERCENT (e.g. \"6.5\", not 0.065) — both are coerced\n * here, so the trap where a clean-decimal fixture passes while production data fails silently\n * cannot occur. A null/non-finite reported cap falls back to DEFAULT_CAP_RATE for multifamily.\n *\n * At score time the property is assumed 100% equity (estimatedDebt = 0), so debt coverage\n * always passes and the routing is driven purely by cash flow; the real debt figure is tested\n * later by the debt drain, which demotes uncovered prospect/discount rows to `shadow`.\n *\n * Run A (routing): sweep 60->20 at the asking price; the first qualifying tier => prospect.\n * If none qualify, re-sweep at 85% of asking; the first qualifying tier => discount. If none\n * qualify in either pass => dead.\n *\n * Run B (comparable yield): independent of Run A, the cash flow at a fixed 20%-down stack on\n * the chosen offer price, divided by that offer price. Banded high/medium/low; dead rows are\n * forced to band `none` (the raw yield is still returned).\n *\n * @param {Object} input\n * @param {number|null} [input.bedroomCount] - Bedroom count (assisted living NOI only)\n * @param {number|string|null} input.capRate - Reported cap rate as a PERCENT; null => estimate\n * @param {number|string} input.price - Asking price (positive); null/0 returns null\n * @param {string} [input.propertyType] - DB property type (mfr/str/assisted/other)\n * @param {number|string|null} [input.units] - Unit count (selects residential vs commercial DSCR tier)\n * @returns {{assignment:number, cap_source:string, cash_flow:(number|null), deal_pool:string, downpayment_percent:number, equity_tier:(object|null), offer_price:number, raw_yield:number, yield_band:string}|null}\n * `cap_source` is \"reported\" when a usable cap was supplied, \"estimate\" when the row was\n * scored on DEFAULT_CAP_RATE because none was — the UI flags \"estimate\" rows as\n * needs-confirmation and offers a manual cap-rate input that re-scores the row. Most\n * meaningful for cap-driven types (mfr/other); STR/assisted derive NOI from other models.\n * Null when price is not a positive number (caller should skip + log; the SQL gate excludes these).\n */\nexport function calculateEquityCarryScore({\n bedroomCount = null,\n capRate,\n price,\n propertyType = \"mfr\",\n units = null,\n} = {}) {\n const priceNum = Number(price);\n if (!Number.isFinite(priceNum) || priceNum <= 0) return null;\n\n const capPercent = capRate === null || capRate === undefined || capRate === \"\" ? NaN : Number(capRate);\n const reportedCapRate = Number.isFinite(capPercent) ? capPercent / 100 : null;\n\n const unitsNum = Number(units);\n const rateType = determineInterestRateType(propertyType, Number.isFinite(unitsNum) ? unitsNum : undefined);\n const { amortization: dscrAmortization, rate: dscrRate } = INTEREST_RATE_TIERS[rateType];\n\n const { noi } = resolveListingFinancials({\n bedroomCount,\n estimatedCapRate: DEFAULT_CAP_RATE,\n price: priceNum,\n propertyType,\n reportedCapRate,\n });\n\n const estimatedDebt = 0;\n\n let dealPool;\n let offerPrice;\n let winner = sweepTiers(noi, priceNum, dscrRate, dscrAmortization, estimatedDebt);\n if (winner) {\n dealPool = \"prospect\";\n offerPrice = priceNum;\n } else {\n const discountBasis = priceNum * DISCOUNT_BASIS;\n winner = sweepTiers(noi, discountBasis, dscrRate, dscrAmortization, estimatedDebt);\n if (winner) {\n dealPool = \"discount\";\n offerPrice = discountBasis;\n } else {\n dealPool = \"dead\";\n offerPrice = priceNum;\n }\n }\n\n const cashFlow20 = noi - tierAnnualDebtService(FIXED_YIELD_TIER, offerPrice, dscrRate, dscrAmortization);\n const rawYield = offerPrice > 0 ? cashFlow20 / offerPrice : 0;\n\n let yieldBand;\n if (dealPool === \"dead\") {\n yieldBand = \"none\";\n } else if (rawYield > YIELD_BAND_HIGH) {\n yieldBand = \"high\";\n } else if (rawYield >= YIELD_BAND_MEDIUM) {\n yieldBand = \"medium\";\n } else {\n yieldBand = \"low\";\n }\n\n return {\n assignment: calculateAssignmentFee(offerPrice),\n cap_source: reportedCapRate === null ? \"estimate\" : \"reported\",\n cash_flow: winner ? winner.cashFlow : null,\n deal_pool: dealPool,\n downpayment_percent: winner ? winner.tier.downPercent : -1,\n equity_tier: winner ? { ...winner.tier } : null,\n offer_price: offerPrice,\n raw_yield: rawYield,\n yield_band: yieldBand,\n };\n}\n"],"names":["EQUITY_CARRY_TIERS","downPercent","dscrPercent","sellerPercent","FIXED_YIELD_TIER","length","tierAnnualDebtService","tier","basis","dscrRate","dscrAmortization","calculatePMT","SELLER_FI_INTEREST_RATE","SELLER_FI_AMORTIZATION","sweepTiers","noi","estimatedDebt","cashFlow","downPayment","calculateEquityCarryScore","bedroomCount","capRate","price","propertyType","units","priceNum","Number","isFinite","capPercent","NaN","reportedCapRate","unitsNum","rateType","determineInterestRateType","undefined","amortization","rate","INTEREST_RATE_TIERS","resolveListingFinancials","estimatedCapRate","DEFAULT_CAP_RATE","dealPool","offerPrice","winner","discountBasis","cashFlow20","rawYield","yieldBand","assignment","calculateAssignmentFee","cap_source","cash_flow","deal_pool","downpayment_percent","equity_tier","offer_price","raw_yield","yield_band"],"mappings":"sRAYY,MAACA,EAAqB,CAChC,CAAEC,YAAa,GAAIC,YAAa,GAAIC,cAAe,IACnD,CAAEF,YAAa,GAAIC,YAAa,GAAIC,cAAe,IACnD,CAAEF,YAAa,GAAIC,YAAa,GAAIC,cAAe,IACnD,CAAEF,YAAa,GAAIC,YAAa,GAAIC,cAAe,IACnD,CAAEF,YAAa,GAAIC,YAAa,GAAIC,cAAe,KAI/CC,EAAmBJ,EAAmBA,EAAmBK,OAAS,GAaxE,SAASC,sBAAsBC,EAAMC,EAAOC,EAAUC,GAGpD,OAFgG,GAA7EC,EAAaH,GAASD,EAAKL,YAAc,KAAMO,EAAUC,GAC6C,GAApGC,EAAaH,GAASD,EAAKJ,cAAgB,KAAMS,EAAyBC,EAEjG,CAOA,SAASC,WAAWC,EAAKP,EAAOC,EAAUC,EAAkBM,GAC1D,IAAK,MAAMT,KAAQP,EAAoB,CACrC,MAAMiB,EAAWF,EAAMT,sBAAsBC,EAAMC,EAAOC,EAAUC,GAC9DQ,EAAeX,EAAKN,YAAc,IAAOO,EAC/C,GAAIS,EAAW,GAAKC,GAAeF,EACjC,MAAO,CAAEC,WAAUV,OAEvB,CACA,OAAO,IACT,CAmCO,SAASY,2BAA0BC,aACxCA,EAAe,KAAIC,QACnBA,EAAOC,MACPA,EAAKC,aACLA,EAAe,MAAKC,MACpBA,EAAQ,MACN,IACF,MAAMC,EAAWC,OAAOJ,GACxB,IAAKI,OAAOC,SAASF,IAAaA,GAAY,EAAG,OAAO,KAExD,MAAMG,EAAaP,SAAyD,KAAZA,EAAiBQ,IAAMH,OAAOL,GACxFS,EAAkBJ,OAAOC,SAASC,GAAcA,EAAa,IAAM,KAEnEG,EAAWL,OAAOF,GAClBQ,EAAWC,EAA0BV,EAAcG,OAAOC,SAASI,GAAYA,OAAWG,IACxFC,aAAczB,EAAkB0B,KAAM3B,GAAa4B,EAAoBL,IAEzEjB,IAAEA,GAAQuB,EAAyB,CACvClB,eACAmB,iBAAkBC,EAClBlB,MAAOG,EACPF,eACAO,oBAKF,IAAIW,EACAC,EACAC,EAAS7B,WAAWC,EAAKU,EAAUhB,EAAUC,EAJ3B,GAKtB,GAAIiC,EACFF,EAAW,WACXC,EAAajB,MACR,CACL,MAAMmB,EAvGa,IAuGGnB,EACtBkB,EAAS7B,WAAWC,EAAK6B,EAAenC,EAAUC,EAV9B,GAWhBiC,GACFF,EAAW,WACXC,EAAaE,IAEbH,EAAW,OACXC,EAAajB,EAEjB,CAEA,MAAMoB,EAAa9B,EAAMT,sBAAsBF,EAAkBsC,EAAYjC,EAAUC,GACjFoC,EAAWJ,EAAa,EAAIG,EAAaH,EAAa,EAE5D,IAAIK,EAWJ,OATEA,EADe,SAAbN,EACU,OACHK,EAtHW,IAuHR,OACHA,GAvHa,IAwHV,SAEA,MAGP,CACLE,WAAYC,EAAuBP,GACnCQ,WAAgC,OAApBpB,EAA2B,WAAa,WACpDqB,UAAWR,EAASA,EAAO1B,SAAW,KACtCmC,UAAWX,EACXY,oBAAqBV,EAASA,EAAOpC,KAAKN,aAAc,EACxDqD,YAAaX,EAAS,IAAKA,EAAOpC,MAAS,KAC3CgD,YAAab,EACbc,UAAWV,EACXW,WAAYV,EAEhB"}
package/dist/index.js CHANGED
@@ -1,2 +1,2 @@
1
- export{calculateAppreciatedValue,calculateAssignmentFee,calculateBalloonBalance,calculateCOCR30,calculateCOCRAtPercent,calculateCashFlow,calculateCashFlowYield,calculateCashOutAfterRefi,calculateDiscountFromPrice,calculateNOIByType,calculateNetToBuyer,calculatePMT,calculatePriceForCOCR,calculatePriceFromDiscount,calculateSTRNOI,equityPercentFromDebt,resolveListingFinancials,safePercentage}from"./financial/calculations.js";export{fetchDebt}from"./services/debt.js";export{formatCurrency,formatPercentage,formatPriceValue}from"./financial/formatters.js";export{calculateOriginalPrice,convertCapRateToDecimal,createExportObjectCore,formatDownPaymentPercent,mapPropertyType}from"./export/export-logic.js";export{calculateDOM,formatDate}from"./date/utilities.js";export{calculateCursorPosition,extractNumericValue,filterNumericInput,formatInputDisplay,formatLiveInput,formatLiveNumber,parseNumericInput}from"./formatting/financial-formatting.js";export{normalizeWhitespace}from"./formatting/text.js";export{CALCULATION_TOLERANCE,DEFAULT_CAP_RATE,DEFAULT_DOWN_PAYMENT,DEFAULT_DSCR_PERCENTAGE,DEFAULT_EQUITY_ESTIMATE,DEFAULT_INTEREST_RATE_TYPE,FINANCIAL_CONSTANTS,INTEREST_RATE_TIERS,MAX_ITERATIONS,SELLER_FI_AMORTIZATION,SELLER_FI_CARRY,SELLER_FI_DOWN_PAYMENT,SELLER_FI_INTEREST_RATE,determineInterestRateType}from"./config/financial.js";export{ASSISTED_LIVING,MULTIFAMILY,PROPERTY_TYPES,PROPERTY_TYPE_CONSTANTS,STR}from"./config/property-types.js";export{ASSIGNMENT_FEE_PERCENTAGE,BUSINESS_CONSTANTS,BUYER_AGENT_COMMISSION,CLOSING_COSTS_PERCENTAGE,CONSERVATIVE_COCR15_PRICE_MULTIPLIER,HARD_MONEY_RATE,MAX_COCR15_PRICE_MULTIPLIER,MINIMUM_COCR15_PRICE,NET_TO_BUYER_PERCENTAGE,REHAB_RATE,SELLER_AGENT_COMMISSION}from"./config/business.js";export{lookupLOI}from"./services/loi-lookup.js";export{LOI_LOOKUP_CONFIG,LOI_SENT_STATUS,MATCH_TYPES}from"./config/loi-lookup.js";export{getEnvVar,isBrowserEnvironment,isNodeEnvironment}from"./environment/utilities.js";const e="./dist/styles/base.css";export{e as STYLES_PATH};
1
+ export{calculateAppreciatedValue,calculateAssignmentFee,calculateBalloonBalance,calculateCOCR30,calculateCOCRAtPercent,calculateCashFlow,calculateCashFlowYield,calculateCashOutAfterRefi,calculateDiscountFromPrice,calculateNOIByType,calculateNetToBuyer,calculatePMT,calculatePriceForCOCR,calculatePriceFromDiscount,calculateSTRNOI,equityPercentFromDebt,resolveListingFinancials,safePercentage}from"./financial/calculations.js";export{EQUITY_CARRY_TIERS,calculateEquityCarryScore}from"./financial/equity-carry.js";export{fetchDebt}from"./services/debt.js";export{formatCurrency,formatPercentage,formatPriceValue}from"./financial/formatters.js";export{calculateOriginalPrice,convertCapRateToDecimal,createExportObjectCore,formatDownPaymentPercent,mapPropertyType}from"./export/export-logic.js";export{calculateDOM,formatDate}from"./date/utilities.js";export{calculateCursorPosition,extractNumericValue,filterNumericInput,formatInputDisplay,formatLiveInput,formatLiveNumber,parseNumericInput}from"./formatting/financial-formatting.js";export{normalizeWhitespace}from"./formatting/text.js";export{CALCULATION_TOLERANCE,DEFAULT_CAP_RATE,DEFAULT_DOWN_PAYMENT,DEFAULT_DSCR_PERCENTAGE,DEFAULT_EQUITY_ESTIMATE,DEFAULT_INTEREST_RATE_TYPE,FINANCIAL_CONSTANTS,INTEREST_RATE_TIERS,MAX_ITERATIONS,SELLER_FI_AMORTIZATION,SELLER_FI_CARRY,SELLER_FI_DOWN_PAYMENT,SELLER_FI_INTEREST_RATE,determineInterestRateType}from"./config/financial.js";export{ASSISTED_LIVING,MULTIFAMILY,PROPERTY_TYPES,PROPERTY_TYPE_CONSTANTS,STR}from"./config/property-types.js";export{ASSIGNMENT_FEE_PERCENTAGE,BUSINESS_CONSTANTS,BUYER_AGENT_COMMISSION,CLOSING_COSTS_PERCENTAGE,CONSERVATIVE_COCR15_PRICE_MULTIPLIER,HARD_MONEY_RATE,MAX_COCR15_PRICE_MULTIPLIER,MINIMUM_COCR15_PRICE,NET_TO_BUYER_PERCENTAGE,REHAB_RATE,SELLER_AGENT_COMMISSION}from"./config/business.js";export{lookupLOI}from"./services/loi-lookup.js";export{LOI_LOOKUP_CONFIG,LOI_SENT_STATUS,MATCH_TYPES}from"./config/loi-lookup.js";export{getEnvVar,isBrowserEnvironment,isNodeEnvironment}from"./environment/utilities.js";const e="./dist/styles/base.css";export{e as STYLES_PATH};
2
2
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":["../src/index.js"],"sourcesContent":["/**\r\n * @archerjessop/utilities\r\n * Shared utilities for ArcherJessop property analysis tools\r\n */\r\n\r\n// Financial calculations\r\nexport { \r\n calculateAppreciatedValue,\r\n calculateAssignmentFee,\r\n calculateBalloonBalance,\r\n calculateCashFlow,\r\n calculateCashFlowYield,\r\n calculateCashOutAfterRefi,\r\n calculateCOCR30, \r\n calculateCOCRAtPercent,\r\n calculateDiscountFromPrice,\r\n calculateNetToBuyer,\r\n calculateNOIByType,\r\n calculatePMT,\r\n calculatePriceForCOCR,\r\n calculatePriceFromDiscount,\r\n calculateSTRNOI,\r\n equityPercentFromDebt,\r\n resolveListingFinancials,\r\n safePercentage,\r\n} from \"./financial/calculations.js\";\r\n\r\n// Agnostic debt service (pure IO; Node + browser)\r\nexport { fetchDebt } from \"./services/debt.js\";\r\n\r\n// Financial formatters\r\nexport { formatCurrency, formatPriceValue, formatPercentage } from \"./financial/formatters.js\";\r\n\r\n// Export logic (pure export-object creation)\r\nexport {\r\n calculateOriginalPrice,\r\n convertCapRateToDecimal,\r\n createExportObjectCore,\r\n formatDownPaymentPercent,\r\n mapPropertyType,\r\n} from \"./export/export-logic.js\";\r\n\r\n// Date utilities\r\nexport { calculateDOM, formatDate } from \"./date/utilities.js\";\r\n\r\n// Formatting utilities\r\nexport { \r\n calculateCursorPosition,\r\n extractNumericValue,\r\n filterNumericInput,\r\n formatInputDisplay,\r\n formatLiveInput,\r\n formatLiveNumber,\r\n parseNumericInput\r\n} from \"./formatting/financial-formatting.js\";\r\n\r\n// Text formatting utilities\r\nexport { normalizeWhitespace } from \"./formatting/text.js\";\r\n\r\n// Configuration constants\r\nexport * from \"./config/financial.js\";\r\nexport * from \"./config/property-types.js\";\r\nexport * from \"./config/business.js\";\r\n\r\nexport const STYLES_PATH = \"./dist/styles/base.css\";\r\n\r\n// LOI Lookup service and config\r\nexport { lookupLOI } from \"./services/loi-lookup.js\";\r\nexport { LOI_LOOKUP_CONFIG, MATCH_TYPES, LOI_SENT_STATUS } from \"./config/loi-lookup.js\";\r\n\r\n// Environment utilities\r\nexport { \r\n getEnvVar, \r\n isNodeEnvironment, \r\n isBrowserEnvironment \r\n} from \"./environment/utilities.js\";"],"names":["STYLES_PATH"],"mappings":"k6DAgEY,MAACA,EAAc"}
1
+ {"version":3,"file":"index.js","sources":["../src/index.js"],"sourcesContent":["/**\r\n * @archerjessop/utilities\r\n * Shared utilities for ArcherJessop property analysis tools\r\n */\r\n\r\n// Financial calculations\r\nexport { \r\n calculateAppreciatedValue,\r\n calculateAssignmentFee,\r\n calculateBalloonBalance,\r\n calculateCashFlow,\r\n calculateCashFlowYield,\r\n calculateCashOutAfterRefi,\r\n calculateCOCR30, \r\n calculateCOCRAtPercent,\r\n calculateDiscountFromPrice,\r\n calculateNetToBuyer,\r\n calculateNOIByType,\r\n calculatePMT,\r\n calculatePriceForCOCR,\r\n calculatePriceFromDiscount,\r\n calculateSTRNOI,\r\n equityPercentFromDebt,\r\n resolveListingFinancials,\r\n safePercentage,\r\n} from \"./financial/calculations.js\";\r\n\r\n// Equity Carry scoring engine (pure; scores scraped listings into deal pools)\r\nexport { EQUITY_CARRY_TIERS, calculateEquityCarryScore } from \"./financial/equity-carry.js\";\r\n\r\n// Agnostic debt service (pure IO; Node + browser)\r\nexport { fetchDebt } from \"./services/debt.js\";\r\n\r\n// Financial formatters\r\nexport { formatCurrency, formatPriceValue, formatPercentage } from \"./financial/formatters.js\";\r\n\r\n// Export logic (pure export-object creation)\r\nexport {\r\n calculateOriginalPrice,\r\n convertCapRateToDecimal,\r\n createExportObjectCore,\r\n formatDownPaymentPercent,\r\n mapPropertyType,\r\n} from \"./export/export-logic.js\";\r\n\r\n// Date utilities\r\nexport { calculateDOM, formatDate } from \"./date/utilities.js\";\r\n\r\n// Formatting utilities\r\nexport { \r\n calculateCursorPosition,\r\n extractNumericValue,\r\n filterNumericInput,\r\n formatInputDisplay,\r\n formatLiveInput,\r\n formatLiveNumber,\r\n parseNumericInput\r\n} from \"./formatting/financial-formatting.js\";\r\n\r\n// Text formatting utilities\r\nexport { normalizeWhitespace } from \"./formatting/text.js\";\r\n\r\n// Configuration constants\r\nexport * from \"./config/financial.js\";\r\nexport * from \"./config/property-types.js\";\r\nexport * from \"./config/business.js\";\r\n\r\nexport const STYLES_PATH = \"./dist/styles/base.css\";\r\n\r\n// LOI Lookup service and config\r\nexport { lookupLOI } from \"./services/loi-lookup.js\";\r\nexport { LOI_LOOKUP_CONFIG, MATCH_TYPES, LOI_SENT_STATUS } from \"./config/loi-lookup.js\";\r\n\r\n// Environment utilities\r\nexport { \r\n getEnvVar, \r\n isNodeEnvironment, \r\n isBrowserEnvironment \r\n} from \"./environment/utilities.js\";"],"names":["STYLES_PATH"],"mappings":"w/DAmEY,MAACA,EAAc"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@archerjessop/utilities",
3
- "version": "7.19.0",
3
+ "version": "7.20.0",
4
4
  "description": "Shared utilities for ArcherJessop property analysis tools",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",