@utilix-tech/sdk 0.33.0 → 0.35.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.
- package/CHANGELOG.md +8 -0
- package/README.md +26 -8
- package/dist/{chunk-CSNTHZHF.js → chunk-3YUKLV5N.js} +81 -1
- package/dist/{chunk-ZPQOE7KD.js → chunk-7AJRK57W.js} +29 -1
- package/dist/{chunk-H2USEUHD.js → chunk-F2CEN226.js} +306 -1
- package/dist/{chunk-6FIB72KX.js → chunk-YEXQDI3J.js} +63 -1
- package/dist/{data-C4lCByXw.d.cts → data-CFeS9kes.d.cts} +35 -2
- package/dist/{data-C4lCByXw.d.ts → data-CFeS9kes.d.ts} +35 -2
- package/dist/index.cjs +475 -0
- package/dist/index.d.cts +4 -4
- package/dist/index.d.ts +4 -4
- package/dist/index.js +4 -4
- package/dist/{network-D7Epuerc.d.cts → network-DfY5Ikvr.d.cts} +34 -2
- package/dist/{network-D7Epuerc.d.ts → network-DfY5Ikvr.d.ts} +34 -2
- package/dist/{text-CA-zuD0C.d.cts → text-kHkT9VtT.d.cts} +34 -2
- package/dist/{text-CA-zuD0C.d.ts → text-kHkT9VtT.d.ts} +34 -2
- package/dist/tools/data.cjs +62 -0
- package/dist/tools/data.d.cts +1 -1
- package/dist/tools/data.d.ts +1 -1
- package/dist/tools/data.js +1 -1
- package/dist/tools/network.cjs +80 -0
- package/dist/tools/network.d.cts +1 -1
- package/dist/tools/network.d.ts +1 -1
- package/dist/tools/network.js +1 -1
- package/dist/tools/text.cjs +305 -0
- package/dist/tools/text.d.cts +1 -1
- package/dist/tools/text.d.ts +1 -1
- package/dist/tools/text.js +1 -1
- package/dist/tools/units.cjs +28 -0
- package/dist/tools/units.d.cts +1 -1
- package/dist/tools/units.d.ts +1 -1
- package/dist/tools/units.js +1 -1
- package/dist/{units-BhoxdHhs.d.ts → units-c90DW-OZ.d.cts} +30 -2
- package/dist/{units-BhoxdHhs.d.cts → units-c90DW-OZ.d.ts} +30 -2
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,14 @@
|
|
|
2
2
|
|
|
3
3
|
Full release notes for all Utilix surfaces (browser tools, REST API, SDKs, MCP server) live at [utilix.tech/changelog](https://utilix.tech/changelog). This file tracks just this package.
|
|
4
4
|
|
|
5
|
+
## 0.35.0
|
|
6
|
+
- Add `calculateRoi` (roi-calculator): return on investment percent from an initial and final value, plus the annualized (CAGR) return given an optional holding period in years.
|
|
7
|
+
- Add `searchEmoji`, `getEmojiByShortcode`, `getEmojiByChar`, `getEmojiByCategory`, `getEmojiCategories` (emoji-lookup): search a curated table of ~280 common emoji by name, keyword, or GitHub-style shortcode, or look one up exactly.
|
|
8
|
+
|
|
9
|
+
## 0.34.0
|
|
10
|
+
- Add `buildReferrerPolicy` (referrer-policy-builder): build a Referrer-Policy header value from one or more policy tokens with a plain-English explanation of each and warnings for risky choices like unsafe-url.
|
|
11
|
+
- Add `generateMarkdownToc` (markdown-toc-generator): scan a Markdown document's ATX headings and build a nested table of contents with GitHub-style anchor slugs, disambiguating duplicates.
|
|
12
|
+
|
|
5
13
|
## 0.33.0
|
|
6
14
|
- Add `lintConventionalCommit` (conventional-commit-linter): lint a git commit message against the Conventional Commits v1.0.0 spec, checking header format, blank-line separation, footer tokens, and BREAKING CHANGE casing.
|
|
7
15
|
- Add `calculateSavingsGoal` (savings-goal-calculator): solve for months to reach a savings goal at a fixed monthly contribution, or the monthly contribution required to hit a goal by a target month count.
|
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# @utilix-tech/sdk
|
|
2
2
|
|
|
3
|
-
**
|
|
3
|
+
**600 developer utility functions for Node.js: runs locally, no API key required.**
|
|
4
4
|
|
|
5
5
|
[](https://www.npmjs.com/package/@utilix-tech/sdk)
|
|
6
6
|
[](https://www.npmjs.com/package/@utilix-tech/sdk)
|
|
@@ -140,7 +140,8 @@ generateHtpasswdFile([{ username: "alice", password: "secret" }]);
|
|
|
140
140
|
```ts
|
|
141
141
|
import { convertCase, slugify, countWords, generateWords, generateParagraphs,
|
|
142
142
|
escapeString, htmlToMarkdown, applyOps, detectPassiveVoice, scoreReadability,
|
|
143
|
-
detectFillerWords, calculateStringDistance, analyzeSentenceLengths
|
|
143
|
+
detectFillerWords, calculateStringDistance, analyzeSentenceLengths,
|
|
144
|
+
searchEmoji, getEmojiByShortcode } from "@utilix-tech/sdk/text";
|
|
144
145
|
|
|
145
146
|
convertCase("hello world", "camelCase"); // "helloWorld"
|
|
146
147
|
convertCase("hello world", "PascalCase"); // "HelloWorld"
|
|
@@ -177,17 +178,22 @@ calculateStringDistance("kitten", "sitting");
|
|
|
177
178
|
// Histogram + mean/median/stddev of sentence lengths, distinct from readability grade scores
|
|
178
179
|
analyzeSentenceLengths("The cat sat on the mat. It was a sunny day, and the dog ran across the yard to play.");
|
|
179
180
|
// { sentenceCount: 2, meanLength: 10, stdDev: 4, consistency: "Moderate variation in sentence length", buckets: [...] }
|
|
181
|
+
|
|
182
|
+
// Search ~280 common emoji by name, keyword, or GitHub-style shortcode
|
|
183
|
+
searchEmoji("fire"); // [{ emoji: "🔥", name: "fire", shortcode: "fire", codepoint: "U+1F525", ... }]
|
|
184
|
+
getEmojiByShortcode(":joy:"); // { emoji: "😂", name: "face with tears of joy", ... }
|
|
180
185
|
```
|
|
181
186
|
|
|
182
187
|
---
|
|
183
188
|
|
|
184
|
-
### `/data`: CSV / YAML / TOML / XML / INI / NDJSON / .env diff / subtitles / Markdown front matter
|
|
189
|
+
### `/data`: CSV / YAML / TOML / XML / INI / NDJSON / .env diff / subtitles / Markdown front matter & TOC
|
|
185
190
|
|
|
186
191
|
```ts
|
|
187
192
|
import { parseCsv, csvToJson, validateYaml, tomlToJson, jsonToToml,
|
|
188
193
|
formatXml, xmlToJson, jsonToXml, parseIni,
|
|
189
194
|
validateNdjson, formatNdjson, ndjsonToJsonArray, diffEnvExample,
|
|
190
|
-
parseSubtitles, convertSubtitles, shiftSubtitles, parseFrontMatter
|
|
195
|
+
parseSubtitles, convertSubtitles, shiftSubtitles, parseFrontMatter,
|
|
196
|
+
generateMarkdownToc } from "@utilix-tech/sdk/data";
|
|
191
197
|
|
|
192
198
|
// CSV
|
|
193
199
|
const rows = parseCsv("name,age\nalice,30\nbob,25");
|
|
@@ -225,6 +231,10 @@ shiftSubtitles("1\n00:00:01,000 --> 00:00:04,000\nHi\n", -2.5);
|
|
|
225
231
|
// Markdown front matter: split a document into its YAML front matter and body
|
|
226
232
|
parseFrontMatter("---\ntitle: Hello World\ntags: [foo, bar]\n---\n# Body");
|
|
227
233
|
// { frontMatter: { title: "Hello World", tags: ["foo", "bar"] }, body: "# Body", hasFrontMatter: true, ... }
|
|
234
|
+
|
|
235
|
+
// Markdown table of contents: ATX headings -> nested links with GitHub-style slugs
|
|
236
|
+
generateMarkdownToc("# Title\n\n## Section One\n\n## Section Two\n");
|
|
237
|
+
// { toc: "- [Title](#title)\n - [Section One](#section-one)\n - [Section Two](#section-two)", entries: [...] }
|
|
228
238
|
```
|
|
229
239
|
|
|
230
240
|
---
|
|
@@ -286,7 +296,7 @@ formatIso8601Duration(90061); // { iso: "P1DT1H1M1S", ... }
|
|
|
286
296
|
### `/units`: Conversions
|
|
287
297
|
|
|
288
298
|
```ts
|
|
289
|
-
import { convertBytes, pxToAll, convert, formatValue, validateCardNumber, validateIban, calculateLoan, validateBarcode, calculateTax, calculateCompoundInterest, validateIsbn, calculateTipSplit, calculateSimpleInterest, calculateTimeValue, calculatePercentageChange, convertAprApy, calculateMarginMarkup, calculateDiscount, applySuccessiveDiscounts, calculateBreakEven, calculateVideoBitrate, calculateRuleOf72, calculateEmi } from "@utilix-tech/sdk/units";
|
|
299
|
+
import { convertBytes, pxToAll, convert, formatValue, validateCardNumber, validateIban, calculateLoan, validateBarcode, calculateTax, calculateCompoundInterest, validateIsbn, calculateTipSplit, calculateSimpleInterest, calculateTimeValue, calculatePercentageChange, convertAprApy, calculateMarginMarkup, calculateDiscount, applySuccessiveDiscounts, calculateBreakEven, calculateVideoBitrate, calculateRuleOf72, calculateEmi, calculateRoi } from "@utilix-tech/sdk/units";
|
|
290
300
|
|
|
291
301
|
// File sizes
|
|
292
302
|
convertBytes(1073741824, "GB"); // 1
|
|
@@ -380,6 +390,10 @@ calculateRuleOf72(8, "rate-to-years");
|
|
|
380
390
|
// EMI: equated monthly installment with a year-by-year principal/interest breakdown
|
|
381
391
|
calculateEmi(500000, 8.5, 5, "years");
|
|
382
392
|
// { emi: 10258.27, totalInterest: 115495.89, tenureMonths: 60, yearlyBreakdown: [...] }
|
|
393
|
+
|
|
394
|
+
// ROI: return on investment percent, plus annualized (CAGR) return if years is given
|
|
395
|
+
calculateRoi({ initialValue: 1000, finalValue: 1610.51, years: 5 });
|
|
396
|
+
// { profit: 610.51, roiPercent: 61.051, annualizedReturnPercent: 10, ... }
|
|
383
397
|
```
|
|
384
398
|
|
|
385
399
|
---
|
|
@@ -390,7 +404,7 @@ calculateEmi(500000, 8.5, 5, "years");
|
|
|
390
404
|
import { getStatusCode, isValidIp, isValidIpv4, isValidIpv6,
|
|
391
405
|
searchStatusCodes, buildGeoUrl, countryCodeToFlag,
|
|
392
406
|
parseHar, validateSitemap, validateRobotsTxt,
|
|
393
|
-
parseUserAgent, buildCacheControl, parseIpv6Address } from "@utilix-tech/sdk/network";
|
|
407
|
+
parseUserAgent, buildCacheControl, buildReferrerPolicy, parseIpv6Address } from "@utilix-tech/sdk/network";
|
|
394
408
|
|
|
395
409
|
getStatusCode(404);
|
|
396
410
|
// { code: 404, text: "Not Found", description: "...", category: "Client Error" }
|
|
@@ -425,6 +439,10 @@ validateRobotsTxt("User-agent: *\nDisallow: /admin\nSitemap: https://example.com
|
|
|
425
439
|
buildCacheControl({ visibility: "public", maxAge: 3600, mustRevalidate: true });
|
|
426
440
|
// { header: "public, max-age=3600, must-revalidate", directives: [...], warnings: [] }
|
|
427
441
|
|
|
442
|
+
// Build and explain a Referrer-Policy header from one or more fallback-chain tokens
|
|
443
|
+
buildReferrerPolicy("strict-origin-when-cross-origin");
|
|
444
|
+
// { header: "strict-origin-when-cross-origin", metaTag: '<meta name="referrer" content="...">', policies: [...], warnings: [] }
|
|
445
|
+
|
|
428
446
|
// Expand/compress an IPv6 address (RFC 5952) and classify its address type
|
|
429
447
|
parseIpv6Address("2001:db8::ff00:42:8329");
|
|
430
448
|
// { expanded: "2001:0db8:0000:0000:0000:ff00:0042:8329", compressed: "2001:db8::ff00:42:8329",
|
|
@@ -658,11 +676,11 @@ readVideoInfo(new Uint8Array(videoBytes));
|
|
|
658
676
|
| `@utilix-tech/sdk/json` | Format, minify, diff, validate, JSONPath, CSV↔JSON, YAML↔JSON, TS types from data or from a JSON Schema |
|
|
659
677
|
| `@utilix-tech/sdk/encoding` | Base64, URL, HTML entities, Base32/Base58/Base62 encode/decode |
|
|
660
678
|
| `@utilix-tech/sdk/hashing` | MD5, SHA-1/256/512, bcrypt, HMAC, .htpasswd |
|
|
661
|
-
| `@utilix-tech/sdk/text` | Case convert, slugify, word count, lorem ipsum, line ops, HTML→Markdown, Levenshtein/Damerau string distance, readability scoring, sentence length distribution |
|
|
679
|
+
| `@utilix-tech/sdk/text` | Case convert, slugify, word count, lorem ipsum, line ops, HTML→Markdown, Levenshtein/Damerau string distance, readability scoring, sentence length distribution, emoji lookup |
|
|
662
680
|
| `@utilix-tech/sdk/data` | CSV, YAML, TOML, XML, INI, NDJSON parse and convert, SRT/WebVTT subtitles, Markdown front matter parser |
|
|
663
681
|
| `@utilix-tech/sdk/generators` | UUID v4/v7, ULID, passwords, strength check, entropy estimator, fake data |
|
|
664
682
|
| `@utilix-tech/sdk/time` | Date diff, timezone convert, cron parse, relative time |
|
|
665
|
-
| `@utilix-tech/sdk/units` | Bytes, CSS px/rem, number bases, currency format, credit card/IBAN/barcode/ISBN validation, loan calculator, EMI calculator, compound/simple interest calculators, VAT/sales tax calculator, tip/bill split calculator, break-even point calculator, Rule of 72 calculator, savings goal calculator |
|
|
683
|
+
| `@utilix-tech/sdk/units` | Bytes, CSS px/rem, number bases, currency format, credit card/IBAN/barcode/ISBN validation, loan calculator, EMI calculator, compound/simple interest calculators, VAT/sales tax calculator, tip/bill split calculator, break-even point calculator, Rule of 72 calculator, savings goal calculator, ROI calculator |
|
|
666
684
|
| `@utilix-tech/sdk/network` | HTTP status codes, IP validation, country flags, geolocation URLs, HAR file parsing, User-Agent parsing, IPv6 address compress/expand |
|
|
667
685
|
| `@utilix-tech/sdk/api` | cURL build/parse, JWT decode/sign, JWKS parse, CORS headers, CSP header |
|
|
668
686
|
| `@utilix-tech/sdk/code` | SQL format/minify, HTML format/minify, regex tester, GraphQL format, MIME type lookup, GitHub URL parsing, regex ReDoS detector, Conventional Commits linter |
|
|
@@ -5,11 +5,13 @@ var network_exports = {};
|
|
|
5
5
|
__export(network_exports, {
|
|
6
6
|
DNS_RECORD_TYPES: () => DNS_RECORD_TYPES,
|
|
7
7
|
HTTP_HEADERS: () => HTTP_HEADERS,
|
|
8
|
+
REFERRER_POLICY_VALUES: () => REFERRER_POLICY_VALUES,
|
|
8
9
|
STATUS_CODES: () => STATUS_CODES,
|
|
9
10
|
buildCacheControl: () => buildCacheControl,
|
|
10
11
|
buildDnsQueryUrl: () => buildDnsQueryUrl,
|
|
11
12
|
buildGeoUrl: () => buildGeoUrl,
|
|
12
13
|
buildMapUrl: () => buildMapUrl,
|
|
14
|
+
buildReferrerPolicy: () => buildReferrerPolicy,
|
|
13
15
|
countryCodeToFlag: () => countryCodeToFlag,
|
|
14
16
|
formatCoordinates: () => formatCoordinates,
|
|
15
17
|
formatTtl: () => formatTtl,
|
|
@@ -1815,6 +1817,84 @@ function buildCacheControl(options = {}) {
|
|
|
1815
1817
|
const snippet = `Cache-Control: ${header}`;
|
|
1816
1818
|
return { header, headerName: "Cache-Control", snippet, directives, warnings };
|
|
1817
1819
|
}
|
|
1820
|
+
var REFERRER_POLICY_VALUES = [
|
|
1821
|
+
"no-referrer",
|
|
1822
|
+
"no-referrer-when-downgrade",
|
|
1823
|
+
"origin",
|
|
1824
|
+
"origin-when-cross-origin",
|
|
1825
|
+
"same-origin",
|
|
1826
|
+
"strict-origin",
|
|
1827
|
+
"strict-origin-when-cross-origin",
|
|
1828
|
+
"unsafe-url"
|
|
1829
|
+
];
|
|
1830
|
+
var _REFERRER_POLICY_INFO = {
|
|
1831
|
+
"no-referrer": {
|
|
1832
|
+
explanation: "Never sends the Referer header, on any request. The strictest option; the destination learns nothing about where the request came from.",
|
|
1833
|
+
leaksPathAndQuery: false,
|
|
1834
|
+
sentOnDowngrade: false
|
|
1835
|
+
},
|
|
1836
|
+
"no-referrer-when-downgrade": {
|
|
1837
|
+
explanation: "Sends the full URL (origin, path, and query string) for same-security-level or upgrading requests, but omits the header entirely when navigating from HTTPS to HTTP. This was the legacy browser default before strict-origin-when-cross-origin.",
|
|
1838
|
+
leaksPathAndQuery: true,
|
|
1839
|
+
sentOnDowngrade: false
|
|
1840
|
+
},
|
|
1841
|
+
origin: {
|
|
1842
|
+
explanation: "Sends only the origin (scheme, host, and port) on every request, same-origin or cross-origin, including on a downgrade. The path and query string are always stripped.",
|
|
1843
|
+
leaksPathAndQuery: false,
|
|
1844
|
+
sentOnDowngrade: true
|
|
1845
|
+
},
|
|
1846
|
+
"origin-when-cross-origin": {
|
|
1847
|
+
explanation: "Sends the full URL for same-origin requests, but only the origin for cross-origin requests. Still sends the origin on a downgrade.",
|
|
1848
|
+
leaksPathAndQuery: true,
|
|
1849
|
+
sentOnDowngrade: true
|
|
1850
|
+
},
|
|
1851
|
+
"same-origin": {
|
|
1852
|
+
explanation: "Sends the full URL for same-origin requests, and no Referer header at all for cross-origin requests.",
|
|
1853
|
+
leaksPathAndQuery: true,
|
|
1854
|
+
sentOnDowngrade: false
|
|
1855
|
+
},
|
|
1856
|
+
"strict-origin": {
|
|
1857
|
+
explanation: "Sends only the origin, and only when the security level stays the same or improves (HTTPS to HTTPS, or HTTP to anything). Nothing is sent on a downgrade from HTTPS to HTTP.",
|
|
1858
|
+
leaksPathAndQuery: false,
|
|
1859
|
+
sentOnDowngrade: false
|
|
1860
|
+
},
|
|
1861
|
+
"strict-origin-when-cross-origin": {
|
|
1862
|
+
explanation: "Sends the full URL for same-origin requests, only the origin for cross-origin requests at the same or better security level, and nothing at all on a downgrade. This is the current browser default when no policy is set.",
|
|
1863
|
+
leaksPathAndQuery: true,
|
|
1864
|
+
sentOnDowngrade: false
|
|
1865
|
+
},
|
|
1866
|
+
"unsafe-url": {
|
|
1867
|
+
explanation: "Always sends the full URL, including path and query string, on every request, even on a downgrade from HTTPS to HTTP. Generally discouraged: query strings can carry session tokens or other sensitive data that then leaks to third-party destinations and to the network on an insecure connection.",
|
|
1868
|
+
leaksPathAndQuery: true,
|
|
1869
|
+
sentOnDowngrade: true
|
|
1870
|
+
}
|
|
1871
|
+
};
|
|
1872
|
+
function buildReferrerPolicy(policies) {
|
|
1873
|
+
const list = Array.isArray(policies) ? policies : [policies];
|
|
1874
|
+
const trimmed = list.map((p) => typeof p === "string" ? p.trim() : "").filter((p) => p !== "");
|
|
1875
|
+
if (trimmed.length === 0) {
|
|
1876
|
+
return { error: "At least one policy value is required" };
|
|
1877
|
+
}
|
|
1878
|
+
const entries = [];
|
|
1879
|
+
for (const value of trimmed) {
|
|
1880
|
+
if (!REFERRER_POLICY_VALUES.includes(value)) {
|
|
1881
|
+
return { error: `'${value}' is not a valid Referrer-Policy value. Valid values: ${REFERRER_POLICY_VALUES.join(", ")}` };
|
|
1882
|
+
}
|
|
1883
|
+
entries.push({ value, ..._REFERRER_POLICY_INFO[value] });
|
|
1884
|
+
}
|
|
1885
|
+
const warnings = [];
|
|
1886
|
+
const last = entries[entries.length - 1];
|
|
1887
|
+
if (last.value === "unsafe-url") {
|
|
1888
|
+
warnings.push("unsafe-url sends the full URL, including query strings, on every request, even over an insecure downgrade. Prefer strict-origin-when-cross-origin unless you have a specific reason to leak full URLs.");
|
|
1889
|
+
}
|
|
1890
|
+
if (entries.length > 1 && entries.some((e, i) => i !== entries.length - 1 && e.value === last.value)) {
|
|
1891
|
+
warnings.push("The same policy value appears more than once in the fallback chain, which has no effect beyond the first occurrence.");
|
|
1892
|
+
}
|
|
1893
|
+
const header = entries.map((e) => e.value).join(", ");
|
|
1894
|
+
const snippet = `Referrer-Policy: ${header}`;
|
|
1895
|
+
const metaTag = `<meta name="referrer" content="${last.value}">`;
|
|
1896
|
+
return { header, headerName: "Referrer-Policy", snippet, metaTag, policies: entries, warnings };
|
|
1897
|
+
}
|
|
1818
1898
|
function isValidIpv6HexGroup(g) {
|
|
1819
1899
|
return /^[0-9a-fA-F]{1,4}$/.test(g);
|
|
1820
1900
|
}
|
|
@@ -1904,4 +1984,4 @@ function parseIpv6Address(input) {
|
|
|
1904
1984
|
};
|
|
1905
1985
|
}
|
|
1906
1986
|
|
|
1907
|
-
export { DNS_RECORD_TYPES, HTTP_HEADERS, STATUS_CODES, buildCacheControl, buildDnsQueryUrl, buildGeoUrl, buildMapUrl, countryCodeToFlag, formatCoordinates, formatTtl, getByCategory, getHeader, getHeadersByCategory, getStatusByCategory, getStatusCode, isClientError, isServerError, isSuccess, isValidIp, isValidIpv4, isValidIpv6, network_exports, parseDnsResponse, parseGeoResponse, parseHar, parseIpv6Address, parseUserAgent, searchHeaders, searchStatusCodes, statusCodeToText, typeNumberToLabel, validateDomain, validateHeaderName, validateHeaderValue, validateRobotsTxt, validateSitemap };
|
|
1987
|
+
export { DNS_RECORD_TYPES, HTTP_HEADERS, REFERRER_POLICY_VALUES, STATUS_CODES, buildCacheControl, buildDnsQueryUrl, buildGeoUrl, buildMapUrl, buildReferrerPolicy, countryCodeToFlag, formatCoordinates, formatTtl, getByCategory, getHeader, getHeadersByCategory, getStatusByCategory, getStatusCode, isClientError, isServerError, isSuccess, isValidIp, isValidIpv4, isValidIpv6, network_exports, parseDnsResponse, parseGeoResponse, parseHar, parseIpv6Address, parseUserAgent, searchHeaders, searchStatusCodes, statusCodeToText, typeNumberToLabel, validateDomain, validateHeaderName, validateHeaderValue, validateRobotsTxt, validateSitemap };
|
|
@@ -26,6 +26,7 @@ __export(units_exports, {
|
|
|
26
26
|
calculateLoan: () => calculateLoan,
|
|
27
27
|
calculateMarginMarkup: () => calculateMarginMarkup,
|
|
28
28
|
calculatePercentageChange: () => calculatePercentageChange,
|
|
29
|
+
calculateRoi: () => calculateRoi,
|
|
29
30
|
calculateRuleOf72: () => calculateRuleOf72,
|
|
30
31
|
calculateSavingsGoal: () => calculateSavingsGoal,
|
|
31
32
|
calculateSimpleInterest: () => calculateSimpleInterest,
|
|
@@ -1809,5 +1810,32 @@ function calculateSavingsGoal(input) {
|
|
|
1809
1810
|
finalBalance: round4(goalAmount)
|
|
1810
1811
|
};
|
|
1811
1812
|
}
|
|
1813
|
+
function calculateRoi(input) {
|
|
1814
|
+
const { initialValue, finalValue, years } = input;
|
|
1815
|
+
if (!Number.isFinite(initialValue) || initialValue <= 0) {
|
|
1816
|
+
return { error: "initialValue must be a finite number greater than zero" };
|
|
1817
|
+
}
|
|
1818
|
+
if (!Number.isFinite(finalValue) || finalValue < 0) {
|
|
1819
|
+
return { error: "finalValue must be a finite, non-negative number" };
|
|
1820
|
+
}
|
|
1821
|
+
const round4 = (n) => Math.round(n * 1e4) / 1e4;
|
|
1822
|
+
const profit = finalValue - initialValue;
|
|
1823
|
+
const roiPercent = profit / initialValue * 100;
|
|
1824
|
+
const result = {
|
|
1825
|
+
initialValue: round4(initialValue),
|
|
1826
|
+
finalValue: round4(finalValue),
|
|
1827
|
+
profit: round4(profit),
|
|
1828
|
+
roiPercent: round4(roiPercent)
|
|
1829
|
+
};
|
|
1830
|
+
if (years !== void 0) {
|
|
1831
|
+
if (!Number.isFinite(years) || years <= 0) {
|
|
1832
|
+
return { error: "years must be a finite number greater than zero when provided" };
|
|
1833
|
+
}
|
|
1834
|
+
const annualizedReturnPercent = (Math.pow(finalValue / initialValue, 1 / years) - 1) * 100;
|
|
1835
|
+
result.years = round4(years);
|
|
1836
|
+
result.annualizedReturnPercent = round4(annualizedReturnPercent);
|
|
1837
|
+
}
|
|
1838
|
+
return result;
|
|
1839
|
+
}
|
|
1812
1840
|
|
|
1813
|
-
export { BASE_LABELS, BASE_PREFIXES, BYTE_UNITS, COMMON_CURRENCIES, COMMON_LOCALES, COMMON_PERMISSIONS, COMMON_RATIOS, COMMON_SIZES, COMMON_TAX_RATES, COMMON_TIP_PERCENTAGES, COMMON_VIEWPORTS, applySuccessiveDiscounts, autoFormat, bumpVersion, calcAspectRatio, calcSubnet, calculateBreakEven, calculateCompoundInterest, calculateDiscount, calculateEmi, calculateLoan, calculateMarginMarkup, calculatePercentageChange, calculateRuleOf72, calculateSavingsGoal, calculateSimpleInterest, calculateTax, calculateTimeValue, calculateTipSplit, calculateVideoBitrate, compareSemver, convert, convertAprApy, convertBytes, convertIp, coverBox, decimalToIp, decimalToIpCidr, describePermissions, fitIntoBox, formatNumber, formatValue, formatVwValue, formatWithSeparator, gcd, ipFromBinary, ipFromDecimal, ipFromHex, ipToBinary, ipToDecimal, ipToDecimalCidr, ipToHex, ipToOctal, isValid, isValidCidr, isValidIp, isValidIpv4, marginToMarkup, markupToMargin, octalToPermissions, parseFileSize, parseInput, parseNumberString, parseSemver, permissionsToChmod, permissionsToOctal, permissionsToSymbolic, ptToPx, pxToAll, pxToViewport, remToPx, satisfiesRange, scaleByHeight, scaleByWidth, sortVersions, splitSubnet, symbolicToPermissions, units_exports, validateBarcode, validateCardNumber, validateIban, validateIsbn, viewportToPx };
|
|
1841
|
+
export { BASE_LABELS, BASE_PREFIXES, BYTE_UNITS, COMMON_CURRENCIES, COMMON_LOCALES, COMMON_PERMISSIONS, COMMON_RATIOS, COMMON_SIZES, COMMON_TAX_RATES, COMMON_TIP_PERCENTAGES, COMMON_VIEWPORTS, applySuccessiveDiscounts, autoFormat, bumpVersion, calcAspectRatio, calcSubnet, calculateBreakEven, calculateCompoundInterest, calculateDiscount, calculateEmi, calculateLoan, calculateMarginMarkup, calculatePercentageChange, calculateRoi, calculateRuleOf72, calculateSavingsGoal, calculateSimpleInterest, calculateTax, calculateTimeValue, calculateTipSplit, calculateVideoBitrate, compareSemver, convert, convertAprApy, convertBytes, convertIp, coverBox, decimalToIp, decimalToIpCidr, describePermissions, fitIntoBox, formatNumber, formatValue, formatVwValue, formatWithSeparator, gcd, ipFromBinary, ipFromDecimal, ipFromHex, ipToBinary, ipToDecimal, ipToDecimalCidr, ipToHex, ipToOctal, isValid, isValidCidr, isValidIp, isValidIpv4, marginToMarkup, markupToMargin, octalToPermissions, parseFileSize, parseInput, parseNumberString, parseSemver, permissionsToChmod, permissionsToOctal, permissionsToSymbolic, ptToPx, pxToAll, pxToViewport, remToPx, satisfiesRange, scaleByHeight, scaleByWidth, sortVersions, splitSubnet, symbolicToPermissions, units_exports, validateBarcode, validateCardNumber, validateIban, validateIsbn, viewportToPx };
|