@utilix-tech/sdk 0.55.0 → 0.57.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 +16 -7
- package/dist/{chunk-WVEKRKGU.js → chunk-34C6GXCC.js} +34 -1
- package/dist/{chunk-3TYWIX3B.js → chunk-422ICOZX.js} +16 -1
- package/dist/{chunk-LI63MAZU.js → chunk-MRIGQRTU.js} +41 -1
- package/dist/{chunk-DEBIH7QS.js → chunk-TVSQ53TZ.js} +55 -1
- package/dist/{generators-Du8cBesn.d.cts → generators-DAXXrMvG.d.cts} +23 -2
- package/dist/{generators-Du8cBesn.d.ts → generators-DAXXrMvG.d.ts} +23 -2
- package/dist/index.cjs +142 -0
- package/dist/index.d.cts +4 -4
- package/dist/index.d.ts +4 -4
- package/dist/index.js +4 -4
- package/dist/{json-Ta9JykSB.d.ts → json-CaiYsGDQ.d.cts} +24 -2
- package/dist/{json-Ta9JykSB.d.cts → json-CaiYsGDQ.d.ts} +24 -2
- package/dist/{network-C6IcHeMB.d.cts → network-CoGf7_Op.d.cts} +37 -2
- package/dist/{network-C6IcHeMB.d.ts → network-CoGf7_Op.d.ts} +37 -2
- package/dist/tools/generators.cjs +15 -0
- package/dist/tools/generators.d.cts +1 -1
- package/dist/tools/generators.d.ts +1 -1
- package/dist/tools/generators.js +1 -1
- package/dist/tools/json.cjs +33 -0
- package/dist/tools/json.d.cts +1 -1
- package/dist/tools/json.d.ts +1 -1
- package/dist/tools/json.js +1 -1
- package/dist/tools/network.cjs +54 -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 +40 -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-BM1l5LG9.d.cts → units-BM9GkUZW.d.cts} +36 -2
- package/dist/{units-BM1l5LG9.d.ts → units-BM9GkUZW.d.ts} +36 -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.57.0
|
|
6
|
+
- Add `mergeJsonPatch`, `applyJsonMergePatch` (json-merge-patch): apply an RFC 7396 JSON Merge Patch document to a target JSON document, with null-valued patch keys removing the matching target key.
|
|
7
|
+
- Add `generateCspNonce` (csp-nonce-generator): generate a cryptographically random, base64-encoded Content-Security-Policy nonce with ready-to-paste header directive and script/style tag snippets.
|
|
8
|
+
|
|
9
|
+
## 0.56.0
|
|
10
|
+
- Add `buildAcceptLanguage`, `parseAcceptLanguage` (accept-language-parser): build an Accept-Language request-header value from locale/quality pairs sorted by descending preference, or parse an existing one into its ranked entries.
|
|
11
|
+
- Add `calculateBlendedLoanRate` (blended-loan-rate-calculator): compute the single weighted-average interest rate across a list of loan balances, plus combined monthly and annual interest accrual.
|
|
12
|
+
|
|
5
13
|
## 0.55.0
|
|
6
14
|
- Add `calculateDebtToIncomeRatio` (debt-to-income-ratio-calculator): compute the debt-to-income ratio (total monthly debt payments / gross monthly income) from one or more monthly debts, plus a qualitative tier matching common mortgage-lending guidance.
|
|
7
15
|
- Add `inferCsvColumnTypes` (csv-column-type-inferencer): parse CSV/TSV data and infer each column's data type (integer, float, boolean, ISO 8601 date, or string), flagging nullable columns and empty-cell counts.
|
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# @utilix-tech/sdk
|
|
2
2
|
|
|
3
|
-
**
|
|
3
|
+
**659 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)
|
|
@@ -66,7 +66,7 @@ const { formatJson } = require("@utilix-tech/sdk/json");
|
|
|
66
66
|
|
|
67
67
|
```ts
|
|
68
68
|
import { formatJson, minifyJson, diffJson, jsonToTypescript, jsonSchemaToTypescript, validateJson,
|
|
69
|
-
evaluateJsonPath, resolveJsonPointer, jsonToCsv, yamlToJson, jsonToYaml, getJsonStats } from "@utilix-tech/sdk/json";
|
|
69
|
+
evaluateJsonPath, resolveJsonPointer, applyJsonMergePatch, jsonToCsv, yamlToJson, jsonToYaml, getJsonStats } from "@utilix-tech/sdk/json";
|
|
70
70
|
|
|
71
71
|
// Format with 2-space indent
|
|
72
72
|
formatJson('{"name":"alice","age":30}', { indent: 2 });
|
|
@@ -87,6 +87,10 @@ evaluateJsonPath(obj, "$.users[*].name");
|
|
|
87
87
|
resolveJsonPointer('{"users":[{"name":"Alice"}]}', "/users/0/name");
|
|
88
88
|
// { found: true, value: "Alice", tokens: ["users", "0", "name"] }
|
|
89
89
|
|
|
90
|
+
// Apply an RFC 7396 JSON Merge Patch
|
|
91
|
+
applyJsonMergePatch('{"a":"b","c":{"d":"e","f":"g"}}', '{"a":"z","c":{"f":null}}');
|
|
92
|
+
// { result: { a: "z", c: { d: "e" } } }
|
|
93
|
+
|
|
90
94
|
// Convert JSON to CSV
|
|
91
95
|
jsonToCsv('[{"a":1,"b":2}]');
|
|
92
96
|
|
|
@@ -278,7 +282,7 @@ inferCsvColumnTypes("id,price,active\n1,9.99,true\n2,5,false");
|
|
|
278
282
|
|
|
279
283
|
```ts
|
|
280
284
|
import { generateUuid, generateV4, generateV7, generateUlid,
|
|
281
|
-
generatePassword, checkStrength, estimatePasswordEntropy, generateData } from "@utilix-tech/sdk/generators";
|
|
285
|
+
generatePassword, checkStrength, estimatePasswordEntropy, generateData, generateCspNonce } from "@utilix-tech/sdk/generators";
|
|
282
286
|
|
|
283
287
|
generateUuid(); // "f47ac10b-58cc-4372-a567-0e02b2c3d479" (v4)
|
|
284
288
|
generateV7(); // time-ordered UUID v7
|
|
@@ -296,6 +300,10 @@ generateData([
|
|
|
296
300
|
{ name: "email", type: "email" },
|
|
297
301
|
{ name: "age", type: "number" },
|
|
298
302
|
], 10); // 10 rows
|
|
303
|
+
|
|
304
|
+
// Cryptographically random CSP nonce, plus ready-to-paste snippets
|
|
305
|
+
generateCspNonce(16);
|
|
306
|
+
// { nonce: "...", scriptSrcDirective: "script-src 'nonce-...'", scriptTag: '<script nonce="...">' }
|
|
299
307
|
```
|
|
300
308
|
|
|
301
309
|
---
|
|
@@ -331,7 +339,7 @@ formatIso8601Duration(90061); // { iso: "P1DT1H1M1S", ... }
|
|
|
331
339
|
### `/units`: Conversions
|
|
332
340
|
|
|
333
341
|
```ts
|
|
334
|
-
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 } from "@utilix-tech/sdk/units";
|
|
342
|
+
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 } from "@utilix-tech/sdk/units";
|
|
335
343
|
|
|
336
344
|
// File sizes
|
|
337
345
|
convertBytes(1073741824, "GB"); // 1
|
|
@@ -487,7 +495,8 @@ import { getStatusCode, isValidIp, isValidIpv4, isValidIpv6,
|
|
|
487
495
|
buildRangeHeader, parseContentRangeHeader, buildVaryHeader, parseVaryHeader, validateManifest,
|
|
488
496
|
buildPermissionsPolicy, parsePermissionsPolicy, buildClientHints, parseClientHintHeaders,
|
|
489
497
|
buildContentDisposition, parseContentDisposition,
|
|
490
|
-
buildXContentTypeOptionsHeader, parseXContentTypeOptionsHeader, assessContentTypeRisk
|
|
498
|
+
buildXContentTypeOptionsHeader, parseXContentTypeOptionsHeader, assessContentTypeRisk,
|
|
499
|
+
buildAcceptLanguage, parseAcceptLanguage } from "@utilix-tech/sdk/network";
|
|
491
500
|
|
|
492
501
|
getStatusCode(404);
|
|
493
502
|
// { code: 404, text: "Not Found", description: "...", category: "Client Error" }
|
|
@@ -855,12 +864,12 @@ inspectGifFrames(new Uint8Array(gifBytes));
|
|
|
855
864
|
|
|
856
865
|
| Import | What it does |
|
|
857
866
|
|---|---|
|
|
858
|
-
| `@utilix-tech/sdk/json` | Format, minify, diff, validate, JSONPath, CSV↔JSON, YAML↔JSON, TS types from data or from a JSON Schema |
|
|
867
|
+
| `@utilix-tech/sdk/json` | Format, minify, diff, validate, JSONPath, JSON Pointer, RFC 7396 merge patch, CSV↔JSON, YAML↔JSON, TS types from data or from a JSON Schema |
|
|
859
868
|
| `@utilix-tech/sdk/encoding` | Base64, URL, HTML entities, Base32/Base58/Base62 encode/decode |
|
|
860
869
|
| `@utilix-tech/sdk/hashing` | MD5, SHA-1/256/512, bcrypt, HMAC, .htpasswd, SRI hashes, content-hash ETag generation |
|
|
861
870
|
| `@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 |
|
|
862
871
|
| `@utilix-tech/sdk/data` | CSV, YAML, TOML, XML, INI, NDJSON parse and convert, SRT/WebVTT subtitles, Markdown front matter parser, YAML anchor/alias resolver, CSV column type inferencer |
|
|
863
|
-
| `@utilix-tech/sdk/generators` | UUID v4/v7, ULID, passwords, strength check, entropy estimator, fake data |
|
|
872
|
+
| `@utilix-tech/sdk/generators` | UUID v4/v7, ULID, passwords, strength check, entropy estimator, fake data, CSP nonce generator |
|
|
864
873
|
| `@utilix-tech/sdk/time` | Date diff, timezone convert, cron parse, relative time |
|
|
865
874
|
| `@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 |
|
|
866
875
|
| `@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 |
|
|
@@ -4,6 +4,7 @@ import * as yaml from 'js-yaml';
|
|
|
4
4
|
// src/tools/json.ts
|
|
5
5
|
var json_exports = {};
|
|
6
6
|
__export(json_exports, {
|
|
7
|
+
applyJsonMergePatch: () => applyJsonMergePatch,
|
|
7
8
|
csvToJson: () => csvToJson,
|
|
8
9
|
detectFormat: () => detectFormat,
|
|
9
10
|
diffJson: () => diffJson,
|
|
@@ -22,6 +23,7 @@ __export(json_exports, {
|
|
|
22
23
|
jsonToTypescript: () => jsonToTypescript,
|
|
23
24
|
jsonToYaml: () => jsonToYaml,
|
|
24
25
|
jsonToZod: () => jsonToZod,
|
|
26
|
+
mergeJsonPatch: () => mergeJsonPatch,
|
|
25
27
|
minifyJson: () => minifyJson,
|
|
26
28
|
parseJson: () => parseJson,
|
|
27
29
|
parseStructs: () => parseStructs,
|
|
@@ -1402,5 +1404,36 @@ function jsonSchemaToTypescript(schemaJson, options) {
|
|
|
1402
1404
|
}
|
|
1403
1405
|
return parts.join("\n\n");
|
|
1404
1406
|
}
|
|
1407
|
+
function _isMergePatchObject(value) {
|
|
1408
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
1409
|
+
}
|
|
1410
|
+
function mergeJsonPatch(target, patch) {
|
|
1411
|
+
if (!_isMergePatchObject(patch)) return patch;
|
|
1412
|
+
const result = _isMergePatchObject(target) ? { ...target } : {};
|
|
1413
|
+
for (const key of Object.keys(patch)) {
|
|
1414
|
+
const value = patch[key];
|
|
1415
|
+
if (value === null) {
|
|
1416
|
+
delete result[key];
|
|
1417
|
+
} else {
|
|
1418
|
+
result[key] = mergeJsonPatch(result[key], value);
|
|
1419
|
+
}
|
|
1420
|
+
}
|
|
1421
|
+
return result;
|
|
1422
|
+
}
|
|
1423
|
+
function applyJsonMergePatch(targetJson, patchJson) {
|
|
1424
|
+
let target;
|
|
1425
|
+
try {
|
|
1426
|
+
target = JSON.parse(targetJson);
|
|
1427
|
+
} catch {
|
|
1428
|
+
return { error: "Target is not valid JSON" };
|
|
1429
|
+
}
|
|
1430
|
+
let patch;
|
|
1431
|
+
try {
|
|
1432
|
+
patch = JSON.parse(patchJson);
|
|
1433
|
+
} catch {
|
|
1434
|
+
return { error: "Patch is not valid JSON" };
|
|
1435
|
+
}
|
|
1436
|
+
return { result: mergeJsonPatch(target, patch) };
|
|
1437
|
+
}
|
|
1405
1438
|
|
|
1406
|
-
export { csvToJson, detectFormat, diffJson, evaluateJsonPath, formatDiffLine, formatJson, generateExample, getJsonStats, inferGoType, inferPythonType, inferType, jsonSchemaToTypescript, jsonToCsv, jsonToGo, jsonToPython, jsonToTypescript, jsonToYaml, jsonToZod, json_exports, minifyJson, parseJson, parseStructs, resolveJsonPointer, toPascalCase, toSnakeCase, validateJson, validateJsonPath, validateJsonString, yamlToJson };
|
|
1439
|
+
export { applyJsonMergePatch, csvToJson, detectFormat, diffJson, evaluateJsonPath, formatDiffLine, formatJson, generateExample, getJsonStats, inferGoType, inferPythonType, inferType, jsonSchemaToTypescript, jsonToCsv, jsonToGo, jsonToPython, jsonToTypescript, jsonToYaml, jsonToZod, json_exports, mergeJsonPatch, minifyJson, parseJson, parseStructs, resolveJsonPointer, toPascalCase, toSnakeCase, validateJson, validateJsonPath, validateJsonString, yamlToJson };
|
|
@@ -16,6 +16,7 @@ __export(generators_exports, {
|
|
|
16
16
|
generateBulk: () => generateBulk,
|
|
17
17
|
generateBulkPasswords: () => generateBulkPasswords,
|
|
18
18
|
generateBulkUlids: () => generateBulkUlids,
|
|
19
|
+
generateCspNonce: () => generateCspNonce,
|
|
19
20
|
generateData: () => generateData,
|
|
20
21
|
generatePassword: () => generatePassword,
|
|
21
22
|
generateQrDataUrl: () => generateQrDataUrl,
|
|
@@ -622,5 +623,19 @@ async function generateQrDataUrl(text, options) {
|
|
|
622
623
|
}
|
|
623
624
|
});
|
|
624
625
|
}
|
|
626
|
+
function generateCspNonce(byteLength = 16) {
|
|
627
|
+
if (!Number.isInteger(byteLength) || byteLength < 8 || byteLength > 64) {
|
|
628
|
+
return { error: "Byte length must be a whole number between 8 and 64" };
|
|
629
|
+
}
|
|
630
|
+
const nonce = randomBytes(byteLength).toString("base64");
|
|
631
|
+
return {
|
|
632
|
+
nonce,
|
|
633
|
+
byteLength,
|
|
634
|
+
scriptSrcDirective: `script-src 'nonce-${nonce}'`,
|
|
635
|
+
styleSrcDirective: `style-src 'nonce-${nonce}'`,
|
|
636
|
+
scriptTag: `<script nonce="${nonce}">`,
|
|
637
|
+
styleTag: `<style nonce="${nonce}">`
|
|
638
|
+
};
|
|
639
|
+
}
|
|
625
640
|
|
|
626
|
-
export { AMBIGUOUS_CHARS, DATA_TYPES, DEFAULT_OPTIONS, DEFAULT_QR_OPTIONS, SYMBOL_CHARS, ULID_REGEX, checkStrength, estimatePasswordEntropy, generateBulk, generateBulkPasswords, generateBulkUlids, generateData, generatePassword, generateQrDataUrl, generateQrSvg, generateSingle, generateUlid, generateUuid, generateV4, generateV7, generators_exports, isValidUlid, isValidUuid, parseUlid, parseUuidVersion };
|
|
641
|
+
export { AMBIGUOUS_CHARS, DATA_TYPES, DEFAULT_OPTIONS, DEFAULT_QR_OPTIONS, SYMBOL_CHARS, ULID_REGEX, checkStrength, estimatePasswordEntropy, generateBulk, generateBulkPasswords, generateBulkUlids, generateCspNonce, generateData, generatePassword, generateQrDataUrl, generateQrSvg, generateSingle, generateUlid, generateUuid, generateV4, generateV7, generators_exports, isValidUlid, isValidUuid, parseUlid, parseUuidVersion };
|
|
@@ -21,6 +21,7 @@ __export(units_exports, {
|
|
|
21
21
|
bumpVersion: () => bumpVersion,
|
|
22
22
|
calcAspectRatio: () => calcAspectRatio,
|
|
23
23
|
calcSubnet: () => calcSubnet,
|
|
24
|
+
calculateBlendedLoanRate: () => calculateBlendedLoanRate,
|
|
24
25
|
calculateBreakEven: () => calculateBreakEven,
|
|
25
26
|
calculateCashBreakdown: () => calculateCashBreakdown,
|
|
26
27
|
calculateCashRounding: () => calculateCashRounding,
|
|
@@ -2271,5 +2272,44 @@ function calculateDebtToIncomeRatio(debts, grossMonthlyIncome) {
|
|
|
2271
2272
|
tier: _classifyDti(dtiPercent)
|
|
2272
2273
|
};
|
|
2273
2274
|
}
|
|
2275
|
+
function calculateBlendedLoanRate(loans) {
|
|
2276
|
+
if (!Array.isArray(loans) || loans.length === 0) {
|
|
2277
|
+
return { error: "loans must be a non-empty array" };
|
|
2278
|
+
}
|
|
2279
|
+
const round22 = (n) => Math.round(n * 100) / 100;
|
|
2280
|
+
const round4 = (n) => Math.round(n * 1e4) / 1e4;
|
|
2281
|
+
let totalBalance = 0;
|
|
2282
|
+
for (let i = 0; i < loans.length; i++) {
|
|
2283
|
+
const loan = loans[i];
|
|
2284
|
+
if (typeof loan.balance !== "number" || !Number.isFinite(loan.balance) || loan.balance <= 0) {
|
|
2285
|
+
return { error: `loan ${i + 1}: balance must be a finite number greater than zero` };
|
|
2286
|
+
}
|
|
2287
|
+
if (typeof loan.ratePercent !== "number" || !Number.isFinite(loan.ratePercent) || loan.ratePercent < 0) {
|
|
2288
|
+
return { error: `loan ${i + 1}: ratePercent must be a finite, non-negative number` };
|
|
2289
|
+
}
|
|
2290
|
+
totalBalance += loan.balance;
|
|
2291
|
+
}
|
|
2292
|
+
let totalMonthlyInterest = 0;
|
|
2293
|
+
let weightedRateSum = 0;
|
|
2294
|
+
const results = loans.map((loan, i) => {
|
|
2295
|
+
const monthlyInterest = round22(loan.balance * loan.ratePercent / 100 / 12);
|
|
2296
|
+
totalMonthlyInterest += monthlyInterest;
|
|
2297
|
+
weightedRateSum += loan.balance * loan.ratePercent;
|
|
2298
|
+
return {
|
|
2299
|
+
label: loan.label?.trim() || `Loan ${i + 1}`,
|
|
2300
|
+
balance: loan.balance,
|
|
2301
|
+
ratePercent: loan.ratePercent,
|
|
2302
|
+
monthlyInterest,
|
|
2303
|
+
shareOfTotalPercent: round22(loan.balance / totalBalance * 100)
|
|
2304
|
+
};
|
|
2305
|
+
});
|
|
2306
|
+
return {
|
|
2307
|
+
loans: results,
|
|
2308
|
+
totalBalance: round22(totalBalance),
|
|
2309
|
+
weightedAverageRatePercent: round4(weightedRateSum / totalBalance),
|
|
2310
|
+
totalMonthlyInterest: round22(totalMonthlyInterest),
|
|
2311
|
+
totalAnnualInterest: round22(totalMonthlyInterest * 12)
|
|
2312
|
+
};
|
|
2313
|
+
}
|
|
2274
2314
|
|
|
2275
|
-
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, calculateBreakEven, calculateCashBreakdown, calculateCashRounding, calculateCdMaturity, calculateChange, calculateCompoundInterest, calculateCreditUtilization, calculateDebtToIncomeRatio, calculateDepreciationSchedule, calculateDiscount, calculateEmi, 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 };
|
|
2315
|
+
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, 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 };
|
|
@@ -13,6 +13,7 @@ __export(network_exports, {
|
|
|
13
13
|
X_CONTENT_TYPE_OPTIONS_HEADER: () => X_CONTENT_TYPE_OPTIONS_HEADER,
|
|
14
14
|
analyzeEmailHeaders: () => analyzeEmailHeaders,
|
|
15
15
|
assessContentTypeRisk: () => assessContentTypeRisk,
|
|
16
|
+
buildAcceptLanguage: () => buildAcceptLanguage,
|
|
16
17
|
buildCacheControl: () => buildCacheControl,
|
|
17
18
|
buildClientHints: () => buildClientHints,
|
|
18
19
|
buildContentDisposition: () => buildContentDisposition,
|
|
@@ -40,6 +41,7 @@ __export(network_exports, {
|
|
|
40
41
|
isValidIp: () => isValidIp,
|
|
41
42
|
isValidIpv4: () => isValidIpv4,
|
|
42
43
|
isValidIpv6: () => isValidIpv6,
|
|
44
|
+
parseAcceptLanguage: () => parseAcceptLanguage,
|
|
43
45
|
parseClientHintHeaders: () => parseClientHintHeaders,
|
|
44
46
|
parseContentDisposition: () => parseContentDisposition,
|
|
45
47
|
parseContentRangeHeader: () => parseContentRangeHeader,
|
|
@@ -2832,5 +2834,57 @@ function assessContentTypeRisk(contentType) {
|
|
|
2832
2834
|
reason: "Not a well-known type in this tool's lookup table. Treat any response type as sniffable unless you've confirmed the serving browser trusts it, and set nosniff regardless of type as a baseline defense."
|
|
2833
2835
|
};
|
|
2834
2836
|
}
|
|
2837
|
+
function formatAcceptLanguageQuality(q) {
|
|
2838
|
+
let s = q.toFixed(3);
|
|
2839
|
+
s = s.replace(/0+$/, "");
|
|
2840
|
+
s = s.replace(/\.$/, "");
|
|
2841
|
+
return s;
|
|
2842
|
+
}
|
|
2843
|
+
function formatAcceptLanguageEntries(entries) {
|
|
2844
|
+
return entries.map((e) => e.quality === 1 ? e.locale : `${e.locale};q=${formatAcceptLanguageQuality(e.quality)}`).join(", ");
|
|
2845
|
+
}
|
|
2846
|
+
function sortAcceptLanguageEntries(entries) {
|
|
2847
|
+
return entries.map((e, i) => ({ e, i })).sort((a, b) => b.e.quality - a.e.quality || a.i - b.i).map((x) => x.e);
|
|
2848
|
+
}
|
|
2849
|
+
function buildAcceptLanguage(locales) {
|
|
2850
|
+
if (!Array.isArray(locales) || locales.length === 0) return { error: "At least one locale is required" };
|
|
2851
|
+
const entries = [];
|
|
2852
|
+
for (let i = 0; i < locales.length; i++) {
|
|
2853
|
+
const { locale, quality } = locales[i];
|
|
2854
|
+
if (typeof locale !== "string" || locale.trim() === "") return { error: `locale ${i + 1}: locale is required` };
|
|
2855
|
+
const q = quality === void 0 ? 1 : quality;
|
|
2856
|
+
if (typeof q !== "number" || !Number.isFinite(q) || q < 0 || q > 1) {
|
|
2857
|
+
return { error: `locale ${i + 1}: quality must be between 0 and 1` };
|
|
2858
|
+
}
|
|
2859
|
+
entries.push({ locale: locale.trim(), quality: Math.round(q * 1e3) / 1e3 });
|
|
2860
|
+
}
|
|
2861
|
+
const sorted = sortAcceptLanguageEntries(entries);
|
|
2862
|
+
const headerValue = formatAcceptLanguageEntries(sorted);
|
|
2863
|
+
return { header: `Accept-Language: ${headerValue}`, headerValue, entries: sorted };
|
|
2864
|
+
}
|
|
2865
|
+
function parseAcceptLanguage(raw) {
|
|
2866
|
+
if (!raw || raw.trim() === "") return { error: "Input is empty" };
|
|
2867
|
+
const withoutLabel = raw.trim().replace(/^accept-language:\s*/i, "");
|
|
2868
|
+
const parts = withoutLabel.split(",").map((p) => p.trim()).filter((p) => p.length > 0);
|
|
2869
|
+
if (parts.length === 0) return { error: "Input is empty" };
|
|
2870
|
+
const entries = [];
|
|
2871
|
+
for (const part of parts) {
|
|
2872
|
+
const [localeRaw, ...paramsRaw] = part.split(";").map((s) => s.trim());
|
|
2873
|
+
if (!localeRaw) return { error: `Invalid entry: "${part}"` };
|
|
2874
|
+
let quality = 1;
|
|
2875
|
+
for (const param of paramsRaw) {
|
|
2876
|
+
const m = /^q=([\d.]+)$/i.exec(param);
|
|
2877
|
+
if (!m) return { error: `Invalid parameter in "${part}"` };
|
|
2878
|
+
quality = Number(m[1]);
|
|
2879
|
+
if (!Number.isFinite(quality) || quality < 0 || quality > 1) {
|
|
2880
|
+
return { error: `q value must be between 0 and 1 in "${part}"` };
|
|
2881
|
+
}
|
|
2882
|
+
}
|
|
2883
|
+
entries.push({ locale: localeRaw, quality: Math.round(quality * 1e3) / 1e3 });
|
|
2884
|
+
}
|
|
2885
|
+
const sorted = sortAcceptLanguageEntries(entries);
|
|
2886
|
+
const headerValue = formatAcceptLanguageEntries(sorted);
|
|
2887
|
+
return { header: `Accept-Language: ${headerValue}`, headerValue, entries: sorted };
|
|
2888
|
+
}
|
|
2835
2889
|
|
|
2836
|
-
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, buildCacheControl, buildClientHints, buildContentDisposition, buildDnsQueryUrl, buildGeoUrl, buildLinkHeader, buildMapUrl, buildPermissionsPolicy, buildRangeHeader, buildReferrerPolicy, buildVaryHeader, buildXContentTypeOptionsHeader, checkSetCookieHeader, countryCodeToFlag, formatCoordinates, formatTtl, getByCategory, getHeader, getHeadersByCategory, getStatusByCategory, getStatusCode, isClientError, isServerError, isSuccess, isValidIp, isValidIpv4, isValidIpv6, network_exports, parseClientHintHeaders, parseContentDisposition, parseContentRangeHeader, parseDnsResponse, parseGeoResponse, parseHar, parseIpv6Address, parsePermissionsPolicy, parseUserAgent, parseVaryHeader, parseXContentTypeOptionsHeader, searchHeaders, searchStatusCodes, splitSitemap, statusCodeToText, typeNumberToLabel, validateDomain, validateHeaderName, validateHeaderValue, validateManifest, validateRobotsTxt, validateSitemap };
|
|
2890
|
+
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, buildRangeHeader, buildReferrerPolicy, 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, parseUserAgent, parseVaryHeader, parseXContentTypeOptionsHeader, searchHeaders, searchStatusCodes, splitSitemap, statusCodeToText, typeNumberToLabel, validateDomain, validateHeaderName, validateHeaderValue, validateManifest, validateRobotsTxt, validateSitemap };
|
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
* - password-entropy-estimator : estimatePasswordEntropy
|
|
11
11
|
* - random-data : generateSingle, generateData
|
|
12
12
|
* - qr-code : generateQrSvg, generateQrDataUrl
|
|
13
|
+
* - csp-nonce-generator : generateCspNonce
|
|
13
14
|
*/
|
|
14
15
|
type UuidVersion = 'v4' | 'v7';
|
|
15
16
|
interface GeneratedUuid {
|
|
@@ -117,8 +118,27 @@ interface QrOptions {
|
|
|
117
118
|
declare const DEFAULT_QR_OPTIONS: QrOptions;
|
|
118
119
|
declare function generateQrSvg(text: string, options?: QrOptions): Promise<string>;
|
|
119
120
|
declare function generateQrDataUrl(text: string, options?: QrOptions): Promise<string>;
|
|
121
|
+
interface CspNonceResult {
|
|
122
|
+
nonce: string;
|
|
123
|
+
byteLength: number;
|
|
124
|
+
scriptSrcDirective: string;
|
|
125
|
+
styleSrcDirective: string;
|
|
126
|
+
scriptTag: string;
|
|
127
|
+
styleTag: string;
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* Generate a cryptographically random, base64-encoded nonce for a
|
|
131
|
+
* Content-Security-Policy script-src/style-src directive, along with
|
|
132
|
+
* ready-to-paste header directive and <script>/<style nonce="..."> tag
|
|
133
|
+
* snippets. Generates a fresh value on every call; the same value must be
|
|
134
|
+
* reused for both the header and the markup within a single request.
|
|
135
|
+
*/
|
|
136
|
+
declare function generateCspNonce(byteLength?: number): CspNonceResult | {
|
|
137
|
+
error: string;
|
|
138
|
+
};
|
|
120
139
|
|
|
121
140
|
declare const generators_AMBIGUOUS_CHARS: typeof AMBIGUOUS_CHARS;
|
|
141
|
+
type generators_CspNonceResult = CspNonceResult;
|
|
122
142
|
declare const generators_DATA_TYPES: typeof DATA_TYPES;
|
|
123
143
|
declare const generators_DEFAULT_OPTIONS: typeof DEFAULT_OPTIONS;
|
|
124
144
|
declare const generators_DEFAULT_QR_OPTIONS: typeof DEFAULT_QR_OPTIONS;
|
|
@@ -141,6 +161,7 @@ declare const generators_estimatePasswordEntropy: typeof estimatePasswordEntropy
|
|
|
141
161
|
declare const generators_generateBulk: typeof generateBulk;
|
|
142
162
|
declare const generators_generateBulkPasswords: typeof generateBulkPasswords;
|
|
143
163
|
declare const generators_generateBulkUlids: typeof generateBulkUlids;
|
|
164
|
+
declare const generators_generateCspNonce: typeof generateCspNonce;
|
|
144
165
|
declare const generators_generateData: typeof generateData;
|
|
145
166
|
declare const generators_generatePassword: typeof generatePassword;
|
|
146
167
|
declare const generators_generateQrDataUrl: typeof generateQrDataUrl;
|
|
@@ -155,7 +176,7 @@ declare const generators_isValidUuid: typeof isValidUuid;
|
|
|
155
176
|
declare const generators_parseUlid: typeof parseUlid;
|
|
156
177
|
declare const generators_parseUuidVersion: typeof parseUuidVersion;
|
|
157
178
|
declare namespace generators {
|
|
158
|
-
export { generators_AMBIGUOUS_CHARS as AMBIGUOUS_CHARS, generators_DATA_TYPES as DATA_TYPES, generators_DEFAULT_OPTIONS as DEFAULT_OPTIONS, generators_DEFAULT_QR_OPTIONS as DEFAULT_QR_OPTIONS, type generators_DataType as DataType, type generators_GeneratedUuid as GeneratedUuid, type generators_PasswordCharsetInfo as PasswordCharsetInfo, type generators_PasswordCrackTimeEstimate as PasswordCrackTimeEstimate, type generators_PasswordEntropyResult as PasswordEntropyResult, type generators_PasswordEntropyStrength as PasswordEntropyStrength, type generators_PasswordOptions as PasswordOptions, type generators_QrErrorLevel as QrErrorLevel, type generators_QrOptions as QrOptions, type generators_QrOutputFormat as QrOutputFormat, type generators_RandomConfig as RandomConfig, generators_SYMBOL_CHARS as SYMBOL_CHARS, generators_ULID_REGEX as ULID_REGEX, type generators_UuidVersion as UuidVersion, generators_checkStrength as checkStrength, generators_estimatePasswordEntropy as estimatePasswordEntropy, generators_generateBulk as generateBulk, generators_generateBulkPasswords as generateBulkPasswords, generators_generateBulkUlids as generateBulkUlids, generators_generateData as generateData, generators_generatePassword as generatePassword, generators_generateQrDataUrl as generateQrDataUrl, generators_generateQrSvg as generateQrSvg, generators_generateSingle as generateSingle, generators_generateUlid as generateUlid, generators_generateUuid as generateUuid, generators_generateV4 as generateV4, generators_generateV7 as generateV7, generators_isValidUlid as isValidUlid, generators_isValidUuid as isValidUuid, generators_parseUlid as parseUlid, generators_parseUuidVersion as parseUuidVersion };
|
|
179
|
+
export { generators_AMBIGUOUS_CHARS as AMBIGUOUS_CHARS, type generators_CspNonceResult as CspNonceResult, generators_DATA_TYPES as DATA_TYPES, generators_DEFAULT_OPTIONS as DEFAULT_OPTIONS, generators_DEFAULT_QR_OPTIONS as DEFAULT_QR_OPTIONS, type generators_DataType as DataType, type generators_GeneratedUuid as GeneratedUuid, type generators_PasswordCharsetInfo as PasswordCharsetInfo, type generators_PasswordCrackTimeEstimate as PasswordCrackTimeEstimate, type generators_PasswordEntropyResult as PasswordEntropyResult, type generators_PasswordEntropyStrength as PasswordEntropyStrength, type generators_PasswordOptions as PasswordOptions, type generators_QrErrorLevel as QrErrorLevel, type generators_QrOptions as QrOptions, type generators_QrOutputFormat as QrOutputFormat, type generators_RandomConfig as RandomConfig, generators_SYMBOL_CHARS as SYMBOL_CHARS, generators_ULID_REGEX as ULID_REGEX, type generators_UuidVersion as UuidVersion, generators_checkStrength as checkStrength, generators_estimatePasswordEntropy as estimatePasswordEntropy, generators_generateBulk as generateBulk, generators_generateBulkPasswords as generateBulkPasswords, generators_generateBulkUlids as generateBulkUlids, generators_generateCspNonce as generateCspNonce, generators_generateData as generateData, generators_generatePassword as generatePassword, generators_generateQrDataUrl as generateQrDataUrl, generators_generateQrSvg as generateQrSvg, generators_generateSingle as generateSingle, generators_generateUlid as generateUlid, generators_generateUuid as generateUuid, generators_generateV4 as generateV4, generators_generateV7 as generateV7, generators_isValidUlid as isValidUlid, generators_isValidUuid as isValidUuid, generators_parseUlid as parseUlid, generators_parseUuidVersion as parseUuidVersion };
|
|
159
180
|
}
|
|
160
181
|
|
|
161
|
-
export { AMBIGUOUS_CHARS as A,
|
|
182
|
+
export { AMBIGUOUS_CHARS as A, isValidUlid as B, type CspNonceResult as C, DATA_TYPES as D, isValidUuid as E, parseUlid as F, type GeneratedUuid as G, parseUuidVersion as H, type PasswordCharsetInfo as P, type QrErrorLevel as Q, type RandomConfig as R, SYMBOL_CHARS as S, ULID_REGEX as U, DEFAULT_OPTIONS as a, DEFAULT_QR_OPTIONS as b, type DataType as c, type PasswordCrackTimeEstimate as d, type PasswordEntropyResult as e, type PasswordEntropyStrength as f, generators as g, type PasswordOptions as h, type QrOptions as i, type QrOutputFormat as j, type UuidVersion as k, checkStrength as l, estimatePasswordEntropy as m, generateBulk as n, generateBulkPasswords as o, generateBulkUlids as p, generateCspNonce as q, generateData as r, generatePassword as s, generateQrDataUrl as t, generateQrSvg as u, generateSingle as v, generateUlid as w, generateUuid as x, generateV4 as y, generateV7 as z };
|
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
* - password-entropy-estimator : estimatePasswordEntropy
|
|
11
11
|
* - random-data : generateSingle, generateData
|
|
12
12
|
* - qr-code : generateQrSvg, generateQrDataUrl
|
|
13
|
+
* - csp-nonce-generator : generateCspNonce
|
|
13
14
|
*/
|
|
14
15
|
type UuidVersion = 'v4' | 'v7';
|
|
15
16
|
interface GeneratedUuid {
|
|
@@ -117,8 +118,27 @@ interface QrOptions {
|
|
|
117
118
|
declare const DEFAULT_QR_OPTIONS: QrOptions;
|
|
118
119
|
declare function generateQrSvg(text: string, options?: QrOptions): Promise<string>;
|
|
119
120
|
declare function generateQrDataUrl(text: string, options?: QrOptions): Promise<string>;
|
|
121
|
+
interface CspNonceResult {
|
|
122
|
+
nonce: string;
|
|
123
|
+
byteLength: number;
|
|
124
|
+
scriptSrcDirective: string;
|
|
125
|
+
styleSrcDirective: string;
|
|
126
|
+
scriptTag: string;
|
|
127
|
+
styleTag: string;
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* Generate a cryptographically random, base64-encoded nonce for a
|
|
131
|
+
* Content-Security-Policy script-src/style-src directive, along with
|
|
132
|
+
* ready-to-paste header directive and <script>/<style nonce="..."> tag
|
|
133
|
+
* snippets. Generates a fresh value on every call; the same value must be
|
|
134
|
+
* reused for both the header and the markup within a single request.
|
|
135
|
+
*/
|
|
136
|
+
declare function generateCspNonce(byteLength?: number): CspNonceResult | {
|
|
137
|
+
error: string;
|
|
138
|
+
};
|
|
120
139
|
|
|
121
140
|
declare const generators_AMBIGUOUS_CHARS: typeof AMBIGUOUS_CHARS;
|
|
141
|
+
type generators_CspNonceResult = CspNonceResult;
|
|
122
142
|
declare const generators_DATA_TYPES: typeof DATA_TYPES;
|
|
123
143
|
declare const generators_DEFAULT_OPTIONS: typeof DEFAULT_OPTIONS;
|
|
124
144
|
declare const generators_DEFAULT_QR_OPTIONS: typeof DEFAULT_QR_OPTIONS;
|
|
@@ -141,6 +161,7 @@ declare const generators_estimatePasswordEntropy: typeof estimatePasswordEntropy
|
|
|
141
161
|
declare const generators_generateBulk: typeof generateBulk;
|
|
142
162
|
declare const generators_generateBulkPasswords: typeof generateBulkPasswords;
|
|
143
163
|
declare const generators_generateBulkUlids: typeof generateBulkUlids;
|
|
164
|
+
declare const generators_generateCspNonce: typeof generateCspNonce;
|
|
144
165
|
declare const generators_generateData: typeof generateData;
|
|
145
166
|
declare const generators_generatePassword: typeof generatePassword;
|
|
146
167
|
declare const generators_generateQrDataUrl: typeof generateQrDataUrl;
|
|
@@ -155,7 +176,7 @@ declare const generators_isValidUuid: typeof isValidUuid;
|
|
|
155
176
|
declare const generators_parseUlid: typeof parseUlid;
|
|
156
177
|
declare const generators_parseUuidVersion: typeof parseUuidVersion;
|
|
157
178
|
declare namespace generators {
|
|
158
|
-
export { generators_AMBIGUOUS_CHARS as AMBIGUOUS_CHARS, generators_DATA_TYPES as DATA_TYPES, generators_DEFAULT_OPTIONS as DEFAULT_OPTIONS, generators_DEFAULT_QR_OPTIONS as DEFAULT_QR_OPTIONS, type generators_DataType as DataType, type generators_GeneratedUuid as GeneratedUuid, type generators_PasswordCharsetInfo as PasswordCharsetInfo, type generators_PasswordCrackTimeEstimate as PasswordCrackTimeEstimate, type generators_PasswordEntropyResult as PasswordEntropyResult, type generators_PasswordEntropyStrength as PasswordEntropyStrength, type generators_PasswordOptions as PasswordOptions, type generators_QrErrorLevel as QrErrorLevel, type generators_QrOptions as QrOptions, type generators_QrOutputFormat as QrOutputFormat, type generators_RandomConfig as RandomConfig, generators_SYMBOL_CHARS as SYMBOL_CHARS, generators_ULID_REGEX as ULID_REGEX, type generators_UuidVersion as UuidVersion, generators_checkStrength as checkStrength, generators_estimatePasswordEntropy as estimatePasswordEntropy, generators_generateBulk as generateBulk, generators_generateBulkPasswords as generateBulkPasswords, generators_generateBulkUlids as generateBulkUlids, generators_generateData as generateData, generators_generatePassword as generatePassword, generators_generateQrDataUrl as generateQrDataUrl, generators_generateQrSvg as generateQrSvg, generators_generateSingle as generateSingle, generators_generateUlid as generateUlid, generators_generateUuid as generateUuid, generators_generateV4 as generateV4, generators_generateV7 as generateV7, generators_isValidUlid as isValidUlid, generators_isValidUuid as isValidUuid, generators_parseUlid as parseUlid, generators_parseUuidVersion as parseUuidVersion };
|
|
179
|
+
export { generators_AMBIGUOUS_CHARS as AMBIGUOUS_CHARS, type generators_CspNonceResult as CspNonceResult, generators_DATA_TYPES as DATA_TYPES, generators_DEFAULT_OPTIONS as DEFAULT_OPTIONS, generators_DEFAULT_QR_OPTIONS as DEFAULT_QR_OPTIONS, type generators_DataType as DataType, type generators_GeneratedUuid as GeneratedUuid, type generators_PasswordCharsetInfo as PasswordCharsetInfo, type generators_PasswordCrackTimeEstimate as PasswordCrackTimeEstimate, type generators_PasswordEntropyResult as PasswordEntropyResult, type generators_PasswordEntropyStrength as PasswordEntropyStrength, type generators_PasswordOptions as PasswordOptions, type generators_QrErrorLevel as QrErrorLevel, type generators_QrOptions as QrOptions, type generators_QrOutputFormat as QrOutputFormat, type generators_RandomConfig as RandomConfig, generators_SYMBOL_CHARS as SYMBOL_CHARS, generators_ULID_REGEX as ULID_REGEX, type generators_UuidVersion as UuidVersion, generators_checkStrength as checkStrength, generators_estimatePasswordEntropy as estimatePasswordEntropy, generators_generateBulk as generateBulk, generators_generateBulkPasswords as generateBulkPasswords, generators_generateBulkUlids as generateBulkUlids, generators_generateCspNonce as generateCspNonce, generators_generateData as generateData, generators_generatePassword as generatePassword, generators_generateQrDataUrl as generateQrDataUrl, generators_generateQrSvg as generateQrSvg, generators_generateSingle as generateSingle, generators_generateUlid as generateUlid, generators_generateUuid as generateUuid, generators_generateV4 as generateV4, generators_generateV7 as generateV7, generators_isValidUlid as isValidUlid, generators_isValidUuid as isValidUuid, generators_parseUlid as parseUlid, generators_parseUuidVersion as parseUuidVersion };
|
|
159
180
|
}
|
|
160
181
|
|
|
161
|
-
export { AMBIGUOUS_CHARS as A,
|
|
182
|
+
export { AMBIGUOUS_CHARS as A, isValidUlid as B, type CspNonceResult as C, DATA_TYPES as D, isValidUuid as E, parseUlid as F, type GeneratedUuid as G, parseUuidVersion as H, type PasswordCharsetInfo as P, type QrErrorLevel as Q, type RandomConfig as R, SYMBOL_CHARS as S, ULID_REGEX as U, DEFAULT_OPTIONS as a, DEFAULT_QR_OPTIONS as b, type DataType as c, type PasswordCrackTimeEstimate as d, type PasswordEntropyResult as e, type PasswordEntropyStrength as f, generators as g, type PasswordOptions as h, type QrOptions as i, type QrOutputFormat as j, type UuidVersion as k, checkStrength as l, estimatePasswordEntropy as m, generateBulk as n, generateBulkPasswords as o, generateBulkUlids as p, generateCspNonce as q, generateData as r, generatePassword as s, generateQrDataUrl as t, generateQrSvg as u, generateSingle as v, generateUlid as w, generateUuid as x, generateV4 as y, generateV7 as z };
|
package/dist/index.cjs
CHANGED
|
@@ -42,6 +42,7 @@ var __export = (target, all) => {
|
|
|
42
42
|
// src/tools/json.ts
|
|
43
43
|
var json_exports = {};
|
|
44
44
|
__export(json_exports, {
|
|
45
|
+
applyJsonMergePatch: () => applyJsonMergePatch,
|
|
45
46
|
csvToJson: () => csvToJson,
|
|
46
47
|
detectFormat: () => detectFormat,
|
|
47
48
|
diffJson: () => diffJson,
|
|
@@ -60,6 +61,7 @@ __export(json_exports, {
|
|
|
60
61
|
jsonToTypescript: () => jsonToTypescript,
|
|
61
62
|
jsonToYaml: () => jsonToYaml,
|
|
62
63
|
jsonToZod: () => jsonToZod,
|
|
64
|
+
mergeJsonPatch: () => mergeJsonPatch,
|
|
63
65
|
minifyJson: () => minifyJson,
|
|
64
66
|
parseJson: () => parseJson,
|
|
65
67
|
parseStructs: () => parseStructs,
|
|
@@ -1440,6 +1442,37 @@ function jsonSchemaToTypescript(schemaJson, options) {
|
|
|
1440
1442
|
}
|
|
1441
1443
|
return parts.join("\n\n");
|
|
1442
1444
|
}
|
|
1445
|
+
function _isMergePatchObject(value) {
|
|
1446
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
1447
|
+
}
|
|
1448
|
+
function mergeJsonPatch(target, patch) {
|
|
1449
|
+
if (!_isMergePatchObject(patch)) return patch;
|
|
1450
|
+
const result = _isMergePatchObject(target) ? { ...target } : {};
|
|
1451
|
+
for (const key of Object.keys(patch)) {
|
|
1452
|
+
const value = patch[key];
|
|
1453
|
+
if (value === null) {
|
|
1454
|
+
delete result[key];
|
|
1455
|
+
} else {
|
|
1456
|
+
result[key] = mergeJsonPatch(result[key], value);
|
|
1457
|
+
}
|
|
1458
|
+
}
|
|
1459
|
+
return result;
|
|
1460
|
+
}
|
|
1461
|
+
function applyJsonMergePatch(targetJson, patchJson) {
|
|
1462
|
+
let target;
|
|
1463
|
+
try {
|
|
1464
|
+
target = JSON.parse(targetJson);
|
|
1465
|
+
} catch {
|
|
1466
|
+
return { error: "Target is not valid JSON" };
|
|
1467
|
+
}
|
|
1468
|
+
let patch;
|
|
1469
|
+
try {
|
|
1470
|
+
patch = JSON.parse(patchJson);
|
|
1471
|
+
} catch {
|
|
1472
|
+
return { error: "Patch is not valid JSON" };
|
|
1473
|
+
}
|
|
1474
|
+
return { result: mergeJsonPatch(target, patch) };
|
|
1475
|
+
}
|
|
1443
1476
|
|
|
1444
1477
|
// src/tools/encoding.ts
|
|
1445
1478
|
var encoding_exports = {};
|
|
@@ -6935,6 +6968,7 @@ __export(generators_exports, {
|
|
|
6935
6968
|
generateBulk: () => generateBulk,
|
|
6936
6969
|
generateBulkPasswords: () => generateBulkPasswords,
|
|
6937
6970
|
generateBulkUlids: () => generateBulkUlids,
|
|
6971
|
+
generateCspNonce: () => generateCspNonce,
|
|
6938
6972
|
generateData: () => generateData,
|
|
6939
6973
|
generatePassword: () => generatePassword,
|
|
6940
6974
|
generateQrDataUrl: () => generateQrDataUrl,
|
|
@@ -7541,6 +7575,20 @@ async function generateQrDataUrl(text, options) {
|
|
|
7541
7575
|
}
|
|
7542
7576
|
});
|
|
7543
7577
|
}
|
|
7578
|
+
function generateCspNonce(byteLength = 16) {
|
|
7579
|
+
if (!Number.isInteger(byteLength) || byteLength < 8 || byteLength > 64) {
|
|
7580
|
+
return { error: "Byte length must be a whole number between 8 and 64" };
|
|
7581
|
+
}
|
|
7582
|
+
const nonce = crypto.randomBytes(byteLength).toString("base64");
|
|
7583
|
+
return {
|
|
7584
|
+
nonce,
|
|
7585
|
+
byteLength,
|
|
7586
|
+
scriptSrcDirective: `script-src 'nonce-${nonce}'`,
|
|
7587
|
+
styleSrcDirective: `style-src 'nonce-${nonce}'`,
|
|
7588
|
+
scriptTag: `<script nonce="${nonce}">`,
|
|
7589
|
+
styleTag: `<style nonce="${nonce}">`
|
|
7590
|
+
};
|
|
7591
|
+
}
|
|
7544
7592
|
|
|
7545
7593
|
// src/tools/time.ts
|
|
7546
7594
|
var time_exports = {};
|
|
@@ -8338,6 +8386,7 @@ __export(units_exports, {
|
|
|
8338
8386
|
bumpVersion: () => bumpVersion,
|
|
8339
8387
|
calcAspectRatio: () => calcAspectRatio,
|
|
8340
8388
|
calcSubnet: () => calcSubnet,
|
|
8389
|
+
calculateBlendedLoanRate: () => calculateBlendedLoanRate,
|
|
8341
8390
|
calculateBreakEven: () => calculateBreakEven,
|
|
8342
8391
|
calculateCashBreakdown: () => calculateCashBreakdown,
|
|
8343
8392
|
calculateCashRounding: () => calculateCashRounding,
|
|
@@ -10588,6 +10637,45 @@ function calculateDebtToIncomeRatio(debts, grossMonthlyIncome) {
|
|
|
10588
10637
|
tier: _classifyDti(dtiPercent)
|
|
10589
10638
|
};
|
|
10590
10639
|
}
|
|
10640
|
+
function calculateBlendedLoanRate(loans) {
|
|
10641
|
+
if (!Array.isArray(loans) || loans.length === 0) {
|
|
10642
|
+
return { error: "loans must be a non-empty array" };
|
|
10643
|
+
}
|
|
10644
|
+
const round23 = (n) => Math.round(n * 100) / 100;
|
|
10645
|
+
const round4 = (n) => Math.round(n * 1e4) / 1e4;
|
|
10646
|
+
let totalBalance = 0;
|
|
10647
|
+
for (let i = 0; i < loans.length; i++) {
|
|
10648
|
+
const loan = loans[i];
|
|
10649
|
+
if (typeof loan.balance !== "number" || !Number.isFinite(loan.balance) || loan.balance <= 0) {
|
|
10650
|
+
return { error: `loan ${i + 1}: balance must be a finite number greater than zero` };
|
|
10651
|
+
}
|
|
10652
|
+
if (typeof loan.ratePercent !== "number" || !Number.isFinite(loan.ratePercent) || loan.ratePercent < 0) {
|
|
10653
|
+
return { error: `loan ${i + 1}: ratePercent must be a finite, non-negative number` };
|
|
10654
|
+
}
|
|
10655
|
+
totalBalance += loan.balance;
|
|
10656
|
+
}
|
|
10657
|
+
let totalMonthlyInterest = 0;
|
|
10658
|
+
let weightedRateSum = 0;
|
|
10659
|
+
const results = loans.map((loan, i) => {
|
|
10660
|
+
const monthlyInterest = round23(loan.balance * loan.ratePercent / 100 / 12);
|
|
10661
|
+
totalMonthlyInterest += monthlyInterest;
|
|
10662
|
+
weightedRateSum += loan.balance * loan.ratePercent;
|
|
10663
|
+
return {
|
|
10664
|
+
label: loan.label?.trim() || `Loan ${i + 1}`,
|
|
10665
|
+
balance: loan.balance,
|
|
10666
|
+
ratePercent: loan.ratePercent,
|
|
10667
|
+
monthlyInterest,
|
|
10668
|
+
shareOfTotalPercent: round23(loan.balance / totalBalance * 100)
|
|
10669
|
+
};
|
|
10670
|
+
});
|
|
10671
|
+
return {
|
|
10672
|
+
loans: results,
|
|
10673
|
+
totalBalance: round23(totalBalance),
|
|
10674
|
+
weightedAverageRatePercent: round4(weightedRateSum / totalBalance),
|
|
10675
|
+
totalMonthlyInterest: round23(totalMonthlyInterest),
|
|
10676
|
+
totalAnnualInterest: round23(totalMonthlyInterest * 12)
|
|
10677
|
+
};
|
|
10678
|
+
}
|
|
10591
10679
|
|
|
10592
10680
|
// src/tools/network.ts
|
|
10593
10681
|
var network_exports = {};
|
|
@@ -10602,6 +10690,7 @@ __export(network_exports, {
|
|
|
10602
10690
|
X_CONTENT_TYPE_OPTIONS_HEADER: () => X_CONTENT_TYPE_OPTIONS_HEADER,
|
|
10603
10691
|
analyzeEmailHeaders: () => analyzeEmailHeaders,
|
|
10604
10692
|
assessContentTypeRisk: () => assessContentTypeRisk,
|
|
10693
|
+
buildAcceptLanguage: () => buildAcceptLanguage,
|
|
10605
10694
|
buildCacheControl: () => buildCacheControl,
|
|
10606
10695
|
buildClientHints: () => buildClientHints,
|
|
10607
10696
|
buildContentDisposition: () => buildContentDisposition,
|
|
@@ -10629,6 +10718,7 @@ __export(network_exports, {
|
|
|
10629
10718
|
isValidIp: () => isValidIp2,
|
|
10630
10719
|
isValidIpv4: () => isValidIpv42,
|
|
10631
10720
|
isValidIpv6: () => isValidIpv6,
|
|
10721
|
+
parseAcceptLanguage: () => parseAcceptLanguage,
|
|
10632
10722
|
parseClientHintHeaders: () => parseClientHintHeaders,
|
|
10633
10723
|
parseContentDisposition: () => parseContentDisposition,
|
|
10634
10724
|
parseContentRangeHeader: () => parseContentRangeHeader,
|
|
@@ -13421,6 +13511,58 @@ function assessContentTypeRisk(contentType) {
|
|
|
13421
13511
|
reason: "Not a well-known type in this tool's lookup table. Treat any response type as sniffable unless you've confirmed the serving browser trusts it, and set nosniff regardless of type as a baseline defense."
|
|
13422
13512
|
};
|
|
13423
13513
|
}
|
|
13514
|
+
function formatAcceptLanguageQuality(q) {
|
|
13515
|
+
let s = q.toFixed(3);
|
|
13516
|
+
s = s.replace(/0+$/, "");
|
|
13517
|
+
s = s.replace(/\.$/, "");
|
|
13518
|
+
return s;
|
|
13519
|
+
}
|
|
13520
|
+
function formatAcceptLanguageEntries(entries) {
|
|
13521
|
+
return entries.map((e) => e.quality === 1 ? e.locale : `${e.locale};q=${formatAcceptLanguageQuality(e.quality)}`).join(", ");
|
|
13522
|
+
}
|
|
13523
|
+
function sortAcceptLanguageEntries(entries) {
|
|
13524
|
+
return entries.map((e, i) => ({ e, i })).sort((a, b) => b.e.quality - a.e.quality || a.i - b.i).map((x) => x.e);
|
|
13525
|
+
}
|
|
13526
|
+
function buildAcceptLanguage(locales) {
|
|
13527
|
+
if (!Array.isArray(locales) || locales.length === 0) return { error: "At least one locale is required" };
|
|
13528
|
+
const entries = [];
|
|
13529
|
+
for (let i = 0; i < locales.length; i++) {
|
|
13530
|
+
const { locale, quality } = locales[i];
|
|
13531
|
+
if (typeof locale !== "string" || locale.trim() === "") return { error: `locale ${i + 1}: locale is required` };
|
|
13532
|
+
const q = quality === void 0 ? 1 : quality;
|
|
13533
|
+
if (typeof q !== "number" || !Number.isFinite(q) || q < 0 || q > 1) {
|
|
13534
|
+
return { error: `locale ${i + 1}: quality must be between 0 and 1` };
|
|
13535
|
+
}
|
|
13536
|
+
entries.push({ locale: locale.trim(), quality: Math.round(q * 1e3) / 1e3 });
|
|
13537
|
+
}
|
|
13538
|
+
const sorted = sortAcceptLanguageEntries(entries);
|
|
13539
|
+
const headerValue = formatAcceptLanguageEntries(sorted);
|
|
13540
|
+
return { header: `Accept-Language: ${headerValue}`, headerValue, entries: sorted };
|
|
13541
|
+
}
|
|
13542
|
+
function parseAcceptLanguage(raw) {
|
|
13543
|
+
if (!raw || raw.trim() === "") return { error: "Input is empty" };
|
|
13544
|
+
const withoutLabel = raw.trim().replace(/^accept-language:\s*/i, "");
|
|
13545
|
+
const parts = withoutLabel.split(",").map((p) => p.trim()).filter((p) => p.length > 0);
|
|
13546
|
+
if (parts.length === 0) return { error: "Input is empty" };
|
|
13547
|
+
const entries = [];
|
|
13548
|
+
for (const part of parts) {
|
|
13549
|
+
const [localeRaw, ...paramsRaw] = part.split(";").map((s) => s.trim());
|
|
13550
|
+
if (!localeRaw) return { error: `Invalid entry: "${part}"` };
|
|
13551
|
+
let quality = 1;
|
|
13552
|
+
for (const param of paramsRaw) {
|
|
13553
|
+
const m = /^q=([\d.]+)$/i.exec(param);
|
|
13554
|
+
if (!m) return { error: `Invalid parameter in "${part}"` };
|
|
13555
|
+
quality = Number(m[1]);
|
|
13556
|
+
if (!Number.isFinite(quality) || quality < 0 || quality > 1) {
|
|
13557
|
+
return { error: `q value must be between 0 and 1 in "${part}"` };
|
|
13558
|
+
}
|
|
13559
|
+
}
|
|
13560
|
+
entries.push({ locale: localeRaw, quality: Math.round(quality * 1e3) / 1e3 });
|
|
13561
|
+
}
|
|
13562
|
+
const sorted = sortAcceptLanguageEntries(entries);
|
|
13563
|
+
const headerValue = formatAcceptLanguageEntries(sorted);
|
|
13564
|
+
return { header: `Accept-Language: ${headerValue}`, headerValue, entries: sorted };
|
|
13565
|
+
}
|
|
13424
13566
|
|
|
13425
13567
|
// src/tools/api.ts
|
|
13426
13568
|
var api_exports = {};
|