@utilix-tech/sdk 0.60.0 → 0.62.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 +7 -0
- package/README.md +23 -3
- package/dist/{chunk-2WT347WO.js → chunk-43L7H3L2.js} +96 -1
- package/dist/{chunk-B7366PQJ.js → chunk-43WFN3CW.js} +35 -1
- package/dist/index.cjs +129 -0
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +2 -2
- package/dist/{network-CXt69chQ.d.cts → network-DewFJy4E.d.cts} +62 -2
- package/dist/{network-CXt69chQ.d.ts → network-DewFJy4E.d.ts} +62 -2
- package/dist/tools/network.cjs +95 -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/units.cjs +34 -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-ClKR6Jxz.d.cts → units-izyUpUAb.d.cts} +23 -2
- package/dist/{units-ClKR6Jxz.d.ts → units-izyUpUAb.d.ts} +23 -2
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,13 @@
|
|
|
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.62.0
|
|
6
|
+
- Add `buildPriorityHeader`, `parsePriorityHeader` (priority-header): build an HTTP Priority request/response-header value from an urgency (0-7) and/or an incremental flag per RFC 9218, or parse an existing one into the same shape.
|
|
7
|
+
- Add `lookupCloseCode`, `listCloseCodes` (websocket-close-codes): look up what a WebSocket close code means per RFC 6455 and the IANA reserved ranges, or list every well-known code.
|
|
8
|
+
|
|
9
|
+
## 0.61.0
|
|
10
|
+
- Add `calculateExtraPaymentPayoff` (extra-payment-mortgage-calculator): compute how much faster a fixed-rate loan pays off, and how much interest is saved, when a fixed extra amount is added to every monthly payment.
|
|
11
|
+
|
|
5
12
|
## 0.60.0
|
|
6
13
|
- Add `buildRetryAfterHeader`, `parseRetryAfterHeader` (retry-after-builder): build an HTTP Retry-After response header from a delay in seconds or a target date, or parse an existing one, per RFC 9110.
|
|
7
14
|
- Add `calculateFreelancerRate` (freelancer-rate-calculator): solve for the minimum hourly rate a freelancer must charge to hit a target annual income, given billable hours, weeks worked, overhead, and a profit margin.
|
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# @utilix-tech/sdk
|
|
2
2
|
|
|
3
|
-
**
|
|
3
|
+
**670 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)
|
|
@@ -343,7 +343,7 @@ formatIso8601Duration(90061); // { iso: "P1DT1H1M1S", ... }
|
|
|
343
343
|
### `/units`: Conversions
|
|
344
344
|
|
|
345
345
|
```ts
|
|
346
|
-
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, compareUnitPrices, calculatePaybackPeriod, calculateCdMaturity, calculateDepreciationSchedule, calculateCashRounding, calculateMovingAverages, calculateGpa, calculateCreditUtilization, calculateDebtToIncomeRatio, calculateBlendedLoanRate, calculateFreelancerRate } from "@utilix-tech/sdk/units";
|
|
346
|
+
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, compareUnitPrices, calculatePaybackPeriod, calculateCdMaturity, calculateDepreciationSchedule, calculateCashRounding, calculateMovingAverages, calculateGpa, calculateCreditUtilization, calculateDebtToIncomeRatio, calculateBlendedLoanRate, calculateFreelancerRate, calculateExtraPaymentPayoff } from "@utilix-tech/sdk/units";
|
|
347
347
|
|
|
348
348
|
// File sizes
|
|
349
349
|
convertBytes(1073741824, "GB"); // 1
|
|
@@ -489,6 +489,10 @@ calculateDebtToIncomeRatio([{ label: "Rent", amount: 1500 }, { label: "Car loan"
|
|
|
489
489
|
// Minimum hourly rate to hit a target annual income, given billable hours, weeks worked, overhead, and margin
|
|
490
490
|
calculateFreelancerRate({ targetAnnualIncome: 80000, billableHoursPerWeek: 25, weeksPerYear: 48 });
|
|
491
491
|
// { hourlyRate: 66.67, dailyRate: 533.33, requiredAnnualRevenue: 80000, annualBillableHours: 1200, monthlyRevenueTarget: 6666.67 }
|
|
492
|
+
|
|
493
|
+
// How much sooner a loan pays off, and how much interest is saved, with a fixed extra monthly payment
|
|
494
|
+
calculateExtraPaymentPayoff(200000, 6, 360, 200);
|
|
495
|
+
// { monthlyPayment: 1199.1, newPayoffMonths: 252, monthsSaved: 108, interestSaved: 79800.86, ... }
|
|
492
496
|
```
|
|
493
497
|
|
|
494
498
|
---
|
|
@@ -639,6 +643,22 @@ buildRetryAfterHeader({ seconds: 120 });
|
|
|
639
643
|
// Parse an existing Retry-After header value into the same shape
|
|
640
644
|
parseRetryAfterHeader("Retry-After: 120");
|
|
641
645
|
// { header: "Retry-After: 120", headerValue: "120", type: "seconds", seconds: 120 }
|
|
646
|
+
|
|
647
|
+
// Build a Priority request/response header from urgency (0-7) and/or incremental, per RFC 9218
|
|
648
|
+
buildPriorityHeader({ urgency: 1, incremental: true });
|
|
649
|
+
// { header: "Priority: u=1, i", headerValue: "u=1, i", urgency: 1, incremental: true }
|
|
650
|
+
|
|
651
|
+
// Parse an existing Priority header value into the same shape, with spec defaults applied
|
|
652
|
+
parsePriorityHeader("u=2");
|
|
653
|
+
// { header: "Priority: u=2, i=?0", headerValue: "u=2, i=?0", urgency: 2, incremental: false }
|
|
654
|
+
|
|
655
|
+
// Look up what a WebSocket close code means, per RFC 6455 and the IANA reserved ranges
|
|
656
|
+
lookupCloseCode(1006);
|
|
657
|
+
// { code: 1006, name: "Abnormal Closure", description: "...", range: "standard", sentOnWire: false }
|
|
658
|
+
|
|
659
|
+
// List every well-known WebSocket close code (1000-1015)
|
|
660
|
+
listCloseCodes();
|
|
661
|
+
// [{ code: 1000, name: "Normal Closure", ... }, ...]
|
|
642
662
|
```
|
|
643
663
|
|
|
644
664
|
---
|
|
@@ -898,7 +918,7 @@ inspectGifFrames(new Uint8Array(gifBytes));
|
|
|
898
918
|
| `@utilix-tech/sdk/generators` | UUID v4/v7, ULID, passwords, strength check, entropy estimator, fake data, CSP nonce generator |
|
|
899
919
|
| `@utilix-tech/sdk/time` | Date diff, timezone convert, cron parse, relative time |
|
|
900
920
|
| `@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, cash denomination/till calculator, payback period calculator, CD maturity calculator, debt-to-income ratio calculator, freelancer hourly rate calculator |
|
|
901
|
-
| `@utilix-tech/sdk/network` | HTTP status codes, IP validation, country flags, geolocation URLs, HAR file parsing, User-Agent parsing, IPv6 address compress/expand, Permissions-Policy header builder, Client Hints header builder/parser, Content-Disposition header builder/parser, X-Content-Type-Options header builder/risk assessor, sitemap.xml validator, sitemap index splitter, Prefer header builder/parser (RFC 7240), Retry-After header builder/parser (RFC 9110) |
|
|
921
|
+
| `@utilix-tech/sdk/network` | HTTP status codes, IP validation, country flags, geolocation URLs, HAR file parsing, User-Agent parsing, IPv6 address compress/expand, Permissions-Policy header builder, Client Hints header builder/parser, Content-Disposition header builder/parser, X-Content-Type-Options header builder/risk assessor, sitemap.xml validator, sitemap index splitter, Prefer header builder/parser (RFC 7240), Retry-After header builder/parser (RFC 9110), Priority header builder/parser (RFC 9218), WebSocket close code reference/lookup |
|
|
902
922
|
| `@utilix-tech/sdk/api` | cURL build/parse, JWT decode/sign, JWKS parse, CORS headers, CSP header |
|
|
903
923
|
| `@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, package.json exports field validator |
|
|
904
924
|
| `@utilix-tech/sdk/color` | Hex/RGB/HSL/HSV/CMYK convert, palette generation, contrast check |
|
|
@@ -23,6 +23,7 @@ __export(network_exports, {
|
|
|
23
23
|
buildMapUrl: () => buildMapUrl,
|
|
24
24
|
buildPermissionsPolicy: () => buildPermissionsPolicy,
|
|
25
25
|
buildPreferHeader: () => buildPreferHeader,
|
|
26
|
+
buildPriorityHeader: () => buildPriorityHeader,
|
|
26
27
|
buildRangeHeader: () => buildRangeHeader,
|
|
27
28
|
buildReferrerPolicy: () => buildReferrerPolicy,
|
|
28
29
|
buildRetryAfterHeader: () => buildRetryAfterHeader,
|
|
@@ -43,6 +44,8 @@ __export(network_exports, {
|
|
|
43
44
|
isValidIp: () => isValidIp,
|
|
44
45
|
isValidIpv4: () => isValidIpv4,
|
|
45
46
|
isValidIpv6: () => isValidIpv6,
|
|
47
|
+
listCloseCodes: () => listCloseCodes,
|
|
48
|
+
lookupCloseCode: () => lookupCloseCode,
|
|
46
49
|
parseAcceptLanguage: () => parseAcceptLanguage,
|
|
47
50
|
parseClientHintHeaders: () => parseClientHintHeaders,
|
|
48
51
|
parseContentDisposition: () => parseContentDisposition,
|
|
@@ -53,6 +56,7 @@ __export(network_exports, {
|
|
|
53
56
|
parseIpv6Address: () => parseIpv6Address,
|
|
54
57
|
parsePermissionsPolicy: () => parsePermissionsPolicy,
|
|
55
58
|
parsePreferHeader: () => parsePreferHeader,
|
|
59
|
+
parsePriorityHeader: () => parsePriorityHeader,
|
|
56
60
|
parseRetryAfterHeader: () => parseRetryAfterHeader,
|
|
57
61
|
parseUserAgent: () => parseUserAgent,
|
|
58
62
|
parseVaryHeader: () => parseVaryHeader,
|
|
@@ -3019,5 +3023,96 @@ function parseRetryAfterHeader(raw) {
|
|
|
3019
3023
|
const httpDate = parsed.toUTCString();
|
|
3020
3024
|
return { header: `Retry-After: ${httpDate}`, headerValue: httpDate, type: "http-date", httpDate, iso: parsed.toISOString() };
|
|
3021
3025
|
}
|
|
3026
|
+
function isValidUrgency(n) {
|
|
3027
|
+
return typeof n === "number" && Number.isInteger(n) && n >= 0 && n <= 7;
|
|
3028
|
+
}
|
|
3029
|
+
function buildPriorityHeader(input) {
|
|
3030
|
+
const { urgency, incremental } = input ?? {};
|
|
3031
|
+
if (urgency === void 0 && incremental === void 0) {
|
|
3032
|
+
return { error: "Provide at least one of urgency or incremental" };
|
|
3033
|
+
}
|
|
3034
|
+
if (urgency !== void 0 && !isValidUrgency(urgency)) {
|
|
3035
|
+
return { error: "urgency must be an integer between 0 and 7" };
|
|
3036
|
+
}
|
|
3037
|
+
const parts = [];
|
|
3038
|
+
if (urgency !== void 0) parts.push(`u=${urgency}`);
|
|
3039
|
+
if (incremental === true) parts.push("i");
|
|
3040
|
+
else if (incremental === false) parts.push("i=?0");
|
|
3041
|
+
const headerValue = parts.join(", ");
|
|
3042
|
+
return {
|
|
3043
|
+
header: `Priority: ${headerValue}`,
|
|
3044
|
+
headerValue,
|
|
3045
|
+
urgency: urgency ?? 3,
|
|
3046
|
+
incremental: incremental ?? false
|
|
3047
|
+
};
|
|
3048
|
+
}
|
|
3049
|
+
function parsePriorityHeader(raw) {
|
|
3050
|
+
if (!raw || raw.trim() === "") return { error: "Input is empty" };
|
|
3051
|
+
const withoutLabel = raw.trim().replace(/^priority:\s*/i, "");
|
|
3052
|
+
const parts = withoutLabel.split(",").map((p) => p.trim()).filter((p) => p.length > 0);
|
|
3053
|
+
if (parts.length === 0) return { error: "Input is empty" };
|
|
3054
|
+
let urgency = 3;
|
|
3055
|
+
let incremental = false;
|
|
3056
|
+
for (const part of parts) {
|
|
3057
|
+
const eq = part.indexOf("=");
|
|
3058
|
+
const key = (eq === -1 ? part : part.slice(0, eq)).trim();
|
|
3059
|
+
const rawValue = eq === -1 ? void 0 : part.slice(eq + 1).trim();
|
|
3060
|
+
if (key === "u") {
|
|
3061
|
+
if (rawValue === void 0 || !/^\d+$/.test(rawValue)) return { error: `Invalid urgency value in "${part}"` };
|
|
3062
|
+
const n = Number(rawValue);
|
|
3063
|
+
if (n < 0 || n > 7) return { error: `urgency must be between 0 and 7, got ${n}` };
|
|
3064
|
+
urgency = n;
|
|
3065
|
+
} else if (key === "i") {
|
|
3066
|
+
if (rawValue === void 0 || rawValue === "?1") incremental = true;
|
|
3067
|
+
else if (rawValue === "?0") incremental = false;
|
|
3068
|
+
else return { error: `Invalid incremental value in "${part}"` };
|
|
3069
|
+
}
|
|
3070
|
+
}
|
|
3071
|
+
const headerValue = incremental ? `u=${urgency}, i` : `u=${urgency}, i=?0`;
|
|
3072
|
+
return { header: `Priority: ${headerValue}`, headerValue, urgency, incremental };
|
|
3073
|
+
}
|
|
3074
|
+
var WELL_KNOWN_CLOSE_CODES = {
|
|
3075
|
+
1e3: { name: "Normal Closure", description: "The connection successfully completed the purpose for which it was created.", sentOnWire: true },
|
|
3076
|
+
1001: { name: "Going Away", description: "An endpoint is going away, such as a server shutting down or a browser navigating away from the page.", sentOnWire: true },
|
|
3077
|
+
1002: { name: "Protocol Error", description: "An endpoint is terminating the connection due to a protocol error.", sentOnWire: true },
|
|
3078
|
+
1003: { name: "Unsupported Data", description: "An endpoint received a data type it cannot accept, such as a binary-only endpoint receiving a text message.", sentOnWire: true },
|
|
3079
|
+
1004: { name: "Reserved", description: "Reserved. A meaning might be defined in the future.", sentOnWire: true },
|
|
3080
|
+
1005: { name: "No Status Received", description: "A reserved value used internally by libraries to indicate no status code was actually present in the close frame. Must not be sent on the wire.", sentOnWire: false },
|
|
3081
|
+
1006: { name: "Abnormal Closure", description: "A reserved value used internally by libraries to indicate the connection closed without a close frame, e.g. the TCP connection dropped. Must not be sent on the wire.", sentOnWire: false },
|
|
3082
|
+
1007: { name: "Invalid frame payload data", description: "An endpoint is terminating the connection because it received data inconsistent with the message type, such as non-UTF-8 data in a text message.", sentOnWire: true },
|
|
3083
|
+
1008: { name: "Policy Violation", description: "A generic status code used when no other code fits and the endpoint does not want to reveal further details, or a message violated its policy.", sentOnWire: true },
|
|
3084
|
+
1009: { name: "Message Too Big", description: "An endpoint is terminating the connection because it received a message too large to process.", sentOnWire: true },
|
|
3085
|
+
1010: { name: "Mandatory Extension", description: "A client is terminating the connection because the server did not negotiate one or more extensions the client required.", sentOnWire: true },
|
|
3086
|
+
1011: { name: "Internal Error", description: "A server is terminating the connection because it encountered an unexpected condition that prevented it from fulfilling the request.", sentOnWire: true },
|
|
3087
|
+
1012: { name: "Service Restart", description: "The server is terminating the connection because it is restarting.", sentOnWire: true },
|
|
3088
|
+
1013: { name: "Try Again Later", description: "The server is terminating the connection due to a temporary condition, such as being overloaded, and the client should reconnect later.", sentOnWire: true },
|
|
3089
|
+
1014: { name: "Bad Gateway", description: "The server, acting as a gateway or proxy, received an invalid response from an upstream server it connected to while processing the request.", sentOnWire: true },
|
|
3090
|
+
1015: { name: "TLS Handshake", description: "A reserved value used internally by libraries to indicate the TLS handshake failed. Must not be sent on the wire.", sentOnWire: false }
|
|
3091
|
+
};
|
|
3092
|
+
function listCloseCodes() {
|
|
3093
|
+
return Object.entries(WELL_KNOWN_CLOSE_CODES).map(([code, info]) => ({ code: Number(code), name: info.name, description: info.description, range: "standard", sentOnWire: info.sentOnWire })).sort((a, b) => a.code - b.code);
|
|
3094
|
+
}
|
|
3095
|
+
function lookupCloseCode(code) {
|
|
3096
|
+
if (typeof code !== "number" || !Number.isInteger(code) || code < 0 || code > 65535) {
|
|
3097
|
+
return { error: "code must be an integer between 0 and 65535" };
|
|
3098
|
+
}
|
|
3099
|
+
const known = WELL_KNOWN_CLOSE_CODES[code];
|
|
3100
|
+
if (known) {
|
|
3101
|
+
return { code, name: known.name, description: known.description, range: "standard", sentOnWire: known.sentOnWire };
|
|
3102
|
+
}
|
|
3103
|
+
if (code < 1e3) {
|
|
3104
|
+
return { error: `${code} is not a valid WebSocket close code; codes below 1000 are not permitted on the wire` };
|
|
3105
|
+
}
|
|
3106
|
+
if (code <= 2999) {
|
|
3107
|
+
return { code, name: "Unassigned", description: "Reserved for future use by the WebSocket protocol specification. No meaning is defined yet.", range: "reserved-future", sentOnWire: true };
|
|
3108
|
+
}
|
|
3109
|
+
if (code <= 3999) {
|
|
3110
|
+
return { code, name: "Library/Framework Use", description: "Reserved for use by libraries, frameworks, and applications. Codes in this range are meant to be registered directly with IANA in the WebSocket Close Code Number Registry, so their meaning depends on which library or application defined them.", range: "library-framework", sentOnWire: true };
|
|
3111
|
+
}
|
|
3112
|
+
if (code <= 4999) {
|
|
3113
|
+
return { code, name: "Private Use", description: "Reserved for private use between a specific client and server implementation. These codes cannot be registered with IANA, so their meaning is defined entirely by the application using them.", range: "private-use", sentOnWire: true };
|
|
3114
|
+
}
|
|
3115
|
+
return { error: `${code} is outside the defined close code ranges (0-4999); codes 5000 and above have no assigned meaning` };
|
|
3116
|
+
}
|
|
3022
3117
|
|
|
3023
|
-
export { CLIENT_HINTS, DNS_RECORD_TYPES, HTTP_HEADERS, LINK_REL_VALUES, PERMISSIONS_POLICY_FEATURES, REFERRER_POLICY_VALUES, STATUS_CODES, X_CONTENT_TYPE_OPTIONS_HEADER, analyzeEmailHeaders, assessContentTypeRisk, buildAcceptLanguage, buildCacheControl, buildClientHints, buildContentDisposition, buildDnsQueryUrl, buildGeoUrl, buildLinkHeader, buildMapUrl, buildPermissionsPolicy, buildPreferHeader, buildRangeHeader, buildReferrerPolicy, buildRetryAfterHeader, buildVaryHeader, buildXContentTypeOptionsHeader, checkSetCookieHeader, countryCodeToFlag, formatCoordinates, formatTtl, getByCategory, getHeader, getHeadersByCategory, getStatusByCategory, getStatusCode, isClientError, isServerError, isSuccess, isValidIp, isValidIpv4, isValidIpv6, network_exports, parseAcceptLanguage, parseClientHintHeaders, parseContentDisposition, parseContentRangeHeader, parseDnsResponse, parseGeoResponse, parseHar, parseIpv6Address, parsePermissionsPolicy, parsePreferHeader, parseRetryAfterHeader, parseUserAgent, parseVaryHeader, parseXContentTypeOptionsHeader, searchHeaders, searchStatusCodes, splitSitemap, statusCodeToText, typeNumberToLabel, validateDomain, validateHeaderName, validateHeaderValue, validateManifest, validateRobotsTxt, validateSitemap };
|
|
3118
|
+
export { CLIENT_HINTS, DNS_RECORD_TYPES, HTTP_HEADERS, LINK_REL_VALUES, PERMISSIONS_POLICY_FEATURES, REFERRER_POLICY_VALUES, STATUS_CODES, X_CONTENT_TYPE_OPTIONS_HEADER, analyzeEmailHeaders, assessContentTypeRisk, buildAcceptLanguage, buildCacheControl, buildClientHints, buildContentDisposition, buildDnsQueryUrl, buildGeoUrl, buildLinkHeader, buildMapUrl, buildPermissionsPolicy, buildPreferHeader, buildPriorityHeader, buildRangeHeader, buildReferrerPolicy, buildRetryAfterHeader, buildVaryHeader, buildXContentTypeOptionsHeader, checkSetCookieHeader, countryCodeToFlag, formatCoordinates, formatTtl, getByCategory, getHeader, getHeadersByCategory, getStatusByCategory, getStatusCode, isClientError, isServerError, isSuccess, isValidIp, isValidIpv4, isValidIpv6, listCloseCodes, lookupCloseCode, network_exports, parseAcceptLanguage, parseClientHintHeaders, parseContentDisposition, parseContentRangeHeader, parseDnsResponse, parseGeoResponse, parseHar, parseIpv6Address, parsePermissionsPolicy, parsePreferHeader, parsePriorityHeader, parseRetryAfterHeader, parseUserAgent, parseVaryHeader, parseXContentTypeOptionsHeader, searchHeaders, searchStatusCodes, splitSitemap, statusCodeToText, typeNumberToLabel, validateDomain, validateHeaderName, validateHeaderValue, validateManifest, validateRobotsTxt, validateSitemap };
|
|
@@ -33,6 +33,7 @@ __export(units_exports, {
|
|
|
33
33
|
calculateDepreciationSchedule: () => calculateDepreciationSchedule,
|
|
34
34
|
calculateDiscount: () => calculateDiscount,
|
|
35
35
|
calculateEmi: () => calculateEmi,
|
|
36
|
+
calculateExtraPaymentPayoff: () => calculateExtraPaymentPayoff,
|
|
36
37
|
calculateFreelancerRate: () => calculateFreelancerRate,
|
|
37
38
|
calculateGpa: () => calculateGpa,
|
|
38
39
|
calculateLoan: () => calculateLoan,
|
|
@@ -1152,6 +1153,39 @@ function calculateLoan(principal, annualRatePercent, termMonths) {
|
|
|
1152
1153
|
schedule
|
|
1153
1154
|
};
|
|
1154
1155
|
}
|
|
1156
|
+
function calculateExtraPaymentPayoff(principal, annualRatePercent, termMonths, extraMonthlyPayment) {
|
|
1157
|
+
const baseline = calculateLoan(principal, annualRatePercent, termMonths);
|
|
1158
|
+
if ("error" in baseline) return baseline;
|
|
1159
|
+
if (!Number.isFinite(extraMonthlyPayment) || extraMonthlyPayment < 0) {
|
|
1160
|
+
return { error: "Extra monthly payment must be zero or a positive number" };
|
|
1161
|
+
}
|
|
1162
|
+
const monthlyRate = annualRatePercent / 100 / 12;
|
|
1163
|
+
const payment = round2(baseline.monthlyPayment) + round2(extraMonthlyPayment);
|
|
1164
|
+
let balance = round2(principal);
|
|
1165
|
+
let totalInterestPaid = 0;
|
|
1166
|
+
let payoffMonths = termMonths;
|
|
1167
|
+
for (let month = 1; month <= termMonths; month++) {
|
|
1168
|
+
const interest = monthlyRate === 0 ? 0 : round2(balance * monthlyRate);
|
|
1169
|
+
let principalPortion = payment - interest;
|
|
1170
|
+
if (principalPortion > balance) principalPortion = balance;
|
|
1171
|
+
totalInterestPaid += interest;
|
|
1172
|
+
balance = round2(balance - principalPortion);
|
|
1173
|
+
if (balance <= 0) {
|
|
1174
|
+
payoffMonths = month;
|
|
1175
|
+
break;
|
|
1176
|
+
}
|
|
1177
|
+
}
|
|
1178
|
+
return {
|
|
1179
|
+
monthlyPayment: round2(baseline.monthlyPayment),
|
|
1180
|
+
extraMonthlyPayment: round2(extraMonthlyPayment),
|
|
1181
|
+
baselinePayoffMonths: termMonths,
|
|
1182
|
+
baselineTotalInterest: baseline.totalInterest,
|
|
1183
|
+
newPayoffMonths: payoffMonths,
|
|
1184
|
+
newTotalInterest: round2(totalInterestPaid),
|
|
1185
|
+
monthsSaved: termMonths - payoffMonths,
|
|
1186
|
+
interestSaved: round2(baseline.totalInterest - totalInterestPaid)
|
|
1187
|
+
};
|
|
1188
|
+
}
|
|
1155
1189
|
var BARCODE_FORMAT_BY_LENGTH = { 8: "EAN-8", 12: "UPC-A", 13: "EAN-13" };
|
|
1156
1190
|
function computeBarcodeCheckDigit(dataDigits) {
|
|
1157
1191
|
let sum = 0;
|
|
@@ -2348,4 +2382,4 @@ function calculateFreelancerRate(input) {
|
|
|
2348
2382
|
};
|
|
2349
2383
|
}
|
|
2350
2384
|
|
|
2351
|
-
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, GPA_GRADE_POINTS, USD_DENOMINATIONS, applySuccessiveDiscounts, autoFormat, bumpVersion, calcAspectRatio, calcSubnet, calculateBlendedLoanRate, calculateBreakEven, calculateCashBreakdown, calculateCashRounding, calculateCdMaturity, calculateChange, calculateCompoundInterest, calculateCreditUtilization, calculateDebtToIncomeRatio, calculateDepreciationSchedule, calculateDiscount, calculateEmi, calculateFreelancerRate, calculateGpa, calculateLoan, calculateMarginMarkup, calculateMovingAverages, calculatePaybackPeriod, calculatePercentageChange, calculateRoi, calculateRuleOf72, calculateSavingsGoal, calculateSimpleInterest, calculateTax, calculateTimeValue, calculateTipSplit, calculateVideoBitrate, compareSemver, compareUnitPrices, 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 };
|
|
2385
|
+
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, GPA_GRADE_POINTS, USD_DENOMINATIONS, applySuccessiveDiscounts, autoFormat, bumpVersion, calcAspectRatio, calcSubnet, calculateBlendedLoanRate, calculateBreakEven, calculateCashBreakdown, calculateCashRounding, calculateCdMaturity, calculateChange, calculateCompoundInterest, calculateCreditUtilization, calculateDebtToIncomeRatio, calculateDepreciationSchedule, calculateDiscount, calculateEmi, calculateExtraPaymentPayoff, calculateFreelancerRate, calculateGpa, calculateLoan, calculateMarginMarkup, calculateMovingAverages, calculatePaybackPeriod, calculatePercentageChange, calculateRoi, calculateRuleOf72, calculateSavingsGoal, calculateSimpleInterest, calculateTax, calculateTimeValue, calculateTipSplit, calculateVideoBitrate, compareSemver, compareUnitPrices, 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 };
|
package/dist/index.cjs
CHANGED
|
@@ -8431,6 +8431,7 @@ __export(units_exports, {
|
|
|
8431
8431
|
calculateDepreciationSchedule: () => calculateDepreciationSchedule,
|
|
8432
8432
|
calculateDiscount: () => calculateDiscount,
|
|
8433
8433
|
calculateEmi: () => calculateEmi,
|
|
8434
|
+
calculateExtraPaymentPayoff: () => calculateExtraPaymentPayoff,
|
|
8434
8435
|
calculateFreelancerRate: () => calculateFreelancerRate,
|
|
8435
8436
|
calculateGpa: () => calculateGpa,
|
|
8436
8437
|
calculateLoan: () => calculateLoan,
|
|
@@ -9550,6 +9551,39 @@ function calculateLoan(principal, annualRatePercent, termMonths) {
|
|
|
9550
9551
|
schedule
|
|
9551
9552
|
};
|
|
9552
9553
|
}
|
|
9554
|
+
function calculateExtraPaymentPayoff(principal, annualRatePercent, termMonths, extraMonthlyPayment) {
|
|
9555
|
+
const baseline = calculateLoan(principal, annualRatePercent, termMonths);
|
|
9556
|
+
if ("error" in baseline) return baseline;
|
|
9557
|
+
if (!Number.isFinite(extraMonthlyPayment) || extraMonthlyPayment < 0) {
|
|
9558
|
+
return { error: "Extra monthly payment must be zero or a positive number" };
|
|
9559
|
+
}
|
|
9560
|
+
const monthlyRate = annualRatePercent / 100 / 12;
|
|
9561
|
+
const payment = round2(baseline.monthlyPayment) + round2(extraMonthlyPayment);
|
|
9562
|
+
let balance = round2(principal);
|
|
9563
|
+
let totalInterestPaid = 0;
|
|
9564
|
+
let payoffMonths = termMonths;
|
|
9565
|
+
for (let month = 1; month <= termMonths; month++) {
|
|
9566
|
+
const interest = monthlyRate === 0 ? 0 : round2(balance * monthlyRate);
|
|
9567
|
+
let principalPortion = payment - interest;
|
|
9568
|
+
if (principalPortion > balance) principalPortion = balance;
|
|
9569
|
+
totalInterestPaid += interest;
|
|
9570
|
+
balance = round2(balance - principalPortion);
|
|
9571
|
+
if (balance <= 0) {
|
|
9572
|
+
payoffMonths = month;
|
|
9573
|
+
break;
|
|
9574
|
+
}
|
|
9575
|
+
}
|
|
9576
|
+
return {
|
|
9577
|
+
monthlyPayment: round2(baseline.monthlyPayment),
|
|
9578
|
+
extraMonthlyPayment: round2(extraMonthlyPayment),
|
|
9579
|
+
baselinePayoffMonths: termMonths,
|
|
9580
|
+
baselineTotalInterest: baseline.totalInterest,
|
|
9581
|
+
newPayoffMonths: payoffMonths,
|
|
9582
|
+
newTotalInterest: round2(totalInterestPaid),
|
|
9583
|
+
monthsSaved: termMonths - payoffMonths,
|
|
9584
|
+
interestSaved: round2(baseline.totalInterest - totalInterestPaid)
|
|
9585
|
+
};
|
|
9586
|
+
}
|
|
9553
9587
|
var BARCODE_FORMAT_BY_LENGTH = { 8: "EAN-8", 12: "UPC-A", 13: "EAN-13" };
|
|
9554
9588
|
function computeBarcodeCheckDigit(dataDigits) {
|
|
9555
9589
|
let sum = 0;
|
|
@@ -10769,6 +10803,7 @@ __export(network_exports, {
|
|
|
10769
10803
|
buildMapUrl: () => buildMapUrl,
|
|
10770
10804
|
buildPermissionsPolicy: () => buildPermissionsPolicy,
|
|
10771
10805
|
buildPreferHeader: () => buildPreferHeader,
|
|
10806
|
+
buildPriorityHeader: () => buildPriorityHeader,
|
|
10772
10807
|
buildRangeHeader: () => buildRangeHeader,
|
|
10773
10808
|
buildReferrerPolicy: () => buildReferrerPolicy,
|
|
10774
10809
|
buildRetryAfterHeader: () => buildRetryAfterHeader,
|
|
@@ -10789,6 +10824,8 @@ __export(network_exports, {
|
|
|
10789
10824
|
isValidIp: () => isValidIp2,
|
|
10790
10825
|
isValidIpv4: () => isValidIpv42,
|
|
10791
10826
|
isValidIpv6: () => isValidIpv6,
|
|
10827
|
+
listCloseCodes: () => listCloseCodes,
|
|
10828
|
+
lookupCloseCode: () => lookupCloseCode,
|
|
10792
10829
|
parseAcceptLanguage: () => parseAcceptLanguage,
|
|
10793
10830
|
parseClientHintHeaders: () => parseClientHintHeaders,
|
|
10794
10831
|
parseContentDisposition: () => parseContentDisposition,
|
|
@@ -10799,6 +10836,7 @@ __export(network_exports, {
|
|
|
10799
10836
|
parseIpv6Address: () => parseIpv6Address,
|
|
10800
10837
|
parsePermissionsPolicy: () => parsePermissionsPolicy,
|
|
10801
10838
|
parsePreferHeader: () => parsePreferHeader,
|
|
10839
|
+
parsePriorityHeader: () => parsePriorityHeader,
|
|
10802
10840
|
parseRetryAfterHeader: () => parseRetryAfterHeader,
|
|
10803
10841
|
parseUserAgent: () => parseUserAgent,
|
|
10804
10842
|
parseVaryHeader: () => parseVaryHeader,
|
|
@@ -13765,6 +13803,97 @@ function parseRetryAfterHeader(raw) {
|
|
|
13765
13803
|
const httpDate = parsed.toUTCString();
|
|
13766
13804
|
return { header: `Retry-After: ${httpDate}`, headerValue: httpDate, type: "http-date", httpDate, iso: parsed.toISOString() };
|
|
13767
13805
|
}
|
|
13806
|
+
function isValidUrgency(n) {
|
|
13807
|
+
return typeof n === "number" && Number.isInteger(n) && n >= 0 && n <= 7;
|
|
13808
|
+
}
|
|
13809
|
+
function buildPriorityHeader(input) {
|
|
13810
|
+
const { urgency, incremental } = input ?? {};
|
|
13811
|
+
if (urgency === void 0 && incremental === void 0) {
|
|
13812
|
+
return { error: "Provide at least one of urgency or incremental" };
|
|
13813
|
+
}
|
|
13814
|
+
if (urgency !== void 0 && !isValidUrgency(urgency)) {
|
|
13815
|
+
return { error: "urgency must be an integer between 0 and 7" };
|
|
13816
|
+
}
|
|
13817
|
+
const parts = [];
|
|
13818
|
+
if (urgency !== void 0) parts.push(`u=${urgency}`);
|
|
13819
|
+
if (incremental === true) parts.push("i");
|
|
13820
|
+
else if (incremental === false) parts.push("i=?0");
|
|
13821
|
+
const headerValue = parts.join(", ");
|
|
13822
|
+
return {
|
|
13823
|
+
header: `Priority: ${headerValue}`,
|
|
13824
|
+
headerValue,
|
|
13825
|
+
urgency: urgency ?? 3,
|
|
13826
|
+
incremental: incremental ?? false
|
|
13827
|
+
};
|
|
13828
|
+
}
|
|
13829
|
+
function parsePriorityHeader(raw) {
|
|
13830
|
+
if (!raw || raw.trim() === "") return { error: "Input is empty" };
|
|
13831
|
+
const withoutLabel = raw.trim().replace(/^priority:\s*/i, "");
|
|
13832
|
+
const parts = withoutLabel.split(",").map((p) => p.trim()).filter((p) => p.length > 0);
|
|
13833
|
+
if (parts.length === 0) return { error: "Input is empty" };
|
|
13834
|
+
let urgency = 3;
|
|
13835
|
+
let incremental = false;
|
|
13836
|
+
for (const part of parts) {
|
|
13837
|
+
const eq = part.indexOf("=");
|
|
13838
|
+
const key = (eq === -1 ? part : part.slice(0, eq)).trim();
|
|
13839
|
+
const rawValue = eq === -1 ? void 0 : part.slice(eq + 1).trim();
|
|
13840
|
+
if (key === "u") {
|
|
13841
|
+
if (rawValue === void 0 || !/^\d+$/.test(rawValue)) return { error: `Invalid urgency value in "${part}"` };
|
|
13842
|
+
const n = Number(rawValue);
|
|
13843
|
+
if (n < 0 || n > 7) return { error: `urgency must be between 0 and 7, got ${n}` };
|
|
13844
|
+
urgency = n;
|
|
13845
|
+
} else if (key === "i") {
|
|
13846
|
+
if (rawValue === void 0 || rawValue === "?1") incremental = true;
|
|
13847
|
+
else if (rawValue === "?0") incremental = false;
|
|
13848
|
+
else return { error: `Invalid incremental value in "${part}"` };
|
|
13849
|
+
}
|
|
13850
|
+
}
|
|
13851
|
+
const headerValue = incremental ? `u=${urgency}, i` : `u=${urgency}, i=?0`;
|
|
13852
|
+
return { header: `Priority: ${headerValue}`, headerValue, urgency, incremental };
|
|
13853
|
+
}
|
|
13854
|
+
var WELL_KNOWN_CLOSE_CODES = {
|
|
13855
|
+
1e3: { name: "Normal Closure", description: "The connection successfully completed the purpose for which it was created.", sentOnWire: true },
|
|
13856
|
+
1001: { name: "Going Away", description: "An endpoint is going away, such as a server shutting down or a browser navigating away from the page.", sentOnWire: true },
|
|
13857
|
+
1002: { name: "Protocol Error", description: "An endpoint is terminating the connection due to a protocol error.", sentOnWire: true },
|
|
13858
|
+
1003: { name: "Unsupported Data", description: "An endpoint received a data type it cannot accept, such as a binary-only endpoint receiving a text message.", sentOnWire: true },
|
|
13859
|
+
1004: { name: "Reserved", description: "Reserved. A meaning might be defined in the future.", sentOnWire: true },
|
|
13860
|
+
1005: { name: "No Status Received", description: "A reserved value used internally by libraries to indicate no status code was actually present in the close frame. Must not be sent on the wire.", sentOnWire: false },
|
|
13861
|
+
1006: { name: "Abnormal Closure", description: "A reserved value used internally by libraries to indicate the connection closed without a close frame, e.g. the TCP connection dropped. Must not be sent on the wire.", sentOnWire: false },
|
|
13862
|
+
1007: { name: "Invalid frame payload data", description: "An endpoint is terminating the connection because it received data inconsistent with the message type, such as non-UTF-8 data in a text message.", sentOnWire: true },
|
|
13863
|
+
1008: { name: "Policy Violation", description: "A generic status code used when no other code fits and the endpoint does not want to reveal further details, or a message violated its policy.", sentOnWire: true },
|
|
13864
|
+
1009: { name: "Message Too Big", description: "An endpoint is terminating the connection because it received a message too large to process.", sentOnWire: true },
|
|
13865
|
+
1010: { name: "Mandatory Extension", description: "A client is terminating the connection because the server did not negotiate one or more extensions the client required.", sentOnWire: true },
|
|
13866
|
+
1011: { name: "Internal Error", description: "A server is terminating the connection because it encountered an unexpected condition that prevented it from fulfilling the request.", sentOnWire: true },
|
|
13867
|
+
1012: { name: "Service Restart", description: "The server is terminating the connection because it is restarting.", sentOnWire: true },
|
|
13868
|
+
1013: { name: "Try Again Later", description: "The server is terminating the connection due to a temporary condition, such as being overloaded, and the client should reconnect later.", sentOnWire: true },
|
|
13869
|
+
1014: { name: "Bad Gateway", description: "The server, acting as a gateway or proxy, received an invalid response from an upstream server it connected to while processing the request.", sentOnWire: true },
|
|
13870
|
+
1015: { name: "TLS Handshake", description: "A reserved value used internally by libraries to indicate the TLS handshake failed. Must not be sent on the wire.", sentOnWire: false }
|
|
13871
|
+
};
|
|
13872
|
+
function listCloseCodes() {
|
|
13873
|
+
return Object.entries(WELL_KNOWN_CLOSE_CODES).map(([code, info]) => ({ code: Number(code), name: info.name, description: info.description, range: "standard", sentOnWire: info.sentOnWire })).sort((a, b) => a.code - b.code);
|
|
13874
|
+
}
|
|
13875
|
+
function lookupCloseCode(code) {
|
|
13876
|
+
if (typeof code !== "number" || !Number.isInteger(code) || code < 0 || code > 65535) {
|
|
13877
|
+
return { error: "code must be an integer between 0 and 65535" };
|
|
13878
|
+
}
|
|
13879
|
+
const known = WELL_KNOWN_CLOSE_CODES[code];
|
|
13880
|
+
if (known) {
|
|
13881
|
+
return { code, name: known.name, description: known.description, range: "standard", sentOnWire: known.sentOnWire };
|
|
13882
|
+
}
|
|
13883
|
+
if (code < 1e3) {
|
|
13884
|
+
return { error: `${code} is not a valid WebSocket close code; codes below 1000 are not permitted on the wire` };
|
|
13885
|
+
}
|
|
13886
|
+
if (code <= 2999) {
|
|
13887
|
+
return { code, name: "Unassigned", description: "Reserved for future use by the WebSocket protocol specification. No meaning is defined yet.", range: "reserved-future", sentOnWire: true };
|
|
13888
|
+
}
|
|
13889
|
+
if (code <= 3999) {
|
|
13890
|
+
return { code, name: "Library/Framework Use", description: "Reserved for use by libraries, frameworks, and applications. Codes in this range are meant to be registered directly with IANA in the WebSocket Close Code Number Registry, so their meaning depends on which library or application defined them.", range: "library-framework", sentOnWire: true };
|
|
13891
|
+
}
|
|
13892
|
+
if (code <= 4999) {
|
|
13893
|
+
return { code, name: "Private Use", description: "Reserved for private use between a specific client and server implementation. These codes cannot be registered with IANA, so their meaning is defined entirely by the application using them.", range: "private-use", sentOnWire: true };
|
|
13894
|
+
}
|
|
13895
|
+
return { error: `${code} is outside the defined close code ranges (0-4999); codes 5000 and above have no assigned meaning` };
|
|
13896
|
+
}
|
|
13768
13897
|
|
|
13769
13898
|
// src/tools/api.ts
|
|
13770
13899
|
var api_exports = {};
|
package/dist/index.d.cts
CHANGED
|
@@ -5,8 +5,8 @@ export { t as text } from './text-DWUcY8H1.cjs';
|
|
|
5
5
|
export { d as data } from './data-vxXrBlWh.cjs';
|
|
6
6
|
export { g as generators } from './generators-DAXXrMvG.cjs';
|
|
7
7
|
export { t as time } from './time-KqJjdqII.cjs';
|
|
8
|
-
export { u as units } from './units-
|
|
9
|
-
export { n as network } from './network-
|
|
8
|
+
export { u as units } from './units-izyUpUAb.cjs';
|
|
9
|
+
export { n as network } from './network-DewFJy4E.cjs';
|
|
10
10
|
export { a as api } from './api-DmTNE4c1.cjs';
|
|
11
11
|
export { c as code } from './code-rxidGgvB.cjs';
|
|
12
12
|
export { c as color } from './color-tPwZCr9H.cjs';
|
package/dist/index.d.ts
CHANGED
|
@@ -5,8 +5,8 @@ export { t as text } from './text-DWUcY8H1.js';
|
|
|
5
5
|
export { d as data } from './data-vxXrBlWh.js';
|
|
6
6
|
export { g as generators } from './generators-DAXXrMvG.js';
|
|
7
7
|
export { t as time } from './time-KqJjdqII.js';
|
|
8
|
-
export { u as units } from './units-
|
|
9
|
-
export { n as network } from './network-
|
|
8
|
+
export { u as units } from './units-izyUpUAb.js';
|
|
9
|
+
export { n as network } from './network-DewFJy4E.js';
|
|
10
10
|
export { a as api } from './api-DmTNE4c1.js';
|
|
11
11
|
export { c as code } from './code-rxidGgvB.js';
|
|
12
12
|
export { c as color } from './color-tPwZCr9H.js';
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export { media_exports as media } from './chunk-226EH3ZI.js';
|
|
2
|
-
export { units_exports as units } from './chunk-
|
|
3
|
-
export { network_exports as network } from './chunk-
|
|
2
|
+
export { units_exports as units } from './chunk-43WFN3CW.js';
|
|
3
|
+
export { network_exports as network } from './chunk-43L7H3L2.js';
|
|
4
4
|
export { api_exports as api } from './chunk-52ZDKSIX.js';
|
|
5
5
|
export { code_exports as code } from './chunk-JW4NG2GN.js';
|
|
6
6
|
export { color_exports as color } from './chunk-BPVAB4P2.js';
|