@utilix-tech/sdk 0.28.0 → 0.30.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 +28 -11
- package/dist/{chunk-2CJSLYWI.js → chunk-3TYWIX3B.js} +107 -1
- package/dist/{chunk-Y5OOP6WN.js → chunk-CSNTHZHF.js} +90 -1
- package/dist/{chunk-47DTCCQJ.js → chunk-L6V4W4SU.js} +112 -1
- package/dist/{chunk-WO3LJMVV.js → chunk-WVEKRKGU.js} +101 -1
- package/dist/{generators-BGtRGpJZ.d.cts → generators-Du8cBesn.d.cts} +45 -2
- package/dist/{generators-BGtRGpJZ.d.ts → generators-Du8cBesn.d.ts} +45 -2
- package/dist/index.cjs +406 -0
- package/dist/index.d.cts +4 -4
- package/dist/index.d.ts +4 -4
- package/dist/index.js +4 -4
- package/dist/{json-DEVFIpsC.d.ts → json-Ta9JykSB.d.cts} +36 -2
- package/dist/{json-DEVFIpsC.d.cts → json-Ta9JykSB.d.ts} +36 -2
- package/dist/{media-cuxfzXxw.d.cts → media-fD8dJ5qR.d.cts} +29 -2
- package/dist/{media-cuxfzXxw.d.ts → media-fD8dJ5qR.d.ts} +29 -2
- package/dist/{network-BJOjJnmY.d.ts → network-D7Epuerc.d.cts} +23 -2
- package/dist/{network-BJOjJnmY.d.cts → network-D7Epuerc.d.ts} +23 -2
- package/dist/tools/generators.cjs +106 -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 +100 -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/media.cjs +111 -0
- package/dist/tools/media.d.cts +1 -1
- package/dist/tools/media.d.ts +1 -1
- package/dist/tools/media.js +1 -1
- package/dist/tools/network.cjs +89 -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/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.30.0
|
|
6
|
+
- Add `jsonSchemaToTypescript` (json-schema-to-typescript): convert a JSON Schema document into TypeScript interfaces/types, reading `required`/`enum`/`oneOf`/`anyOf`/`allOf`/`$ref` directly instead of inferring from an example payload.
|
|
7
|
+
- Add `estimatePasswordEntropy` (password-entropy-estimator): bits of entropy from a password's character pool, a strength label, and crack-time estimates across four guess-rate scenarios.
|
|
8
|
+
|
|
9
|
+
## 0.29.0
|
|
10
|
+
- Add `readPdfPageDimensions` (pdf-page-dimensions): each page's MediaBox width/height (points and inches), rotation, and orientation, walking the Root -> Pages -> Kids tree and inheriting from ancestor nodes, plus a common paper size match (Letter, A4, etc.).
|
|
11
|
+
- Add `parseIpv6Address` (ipv6-compressor): expand an IPv6 address to its full 8-group form or compress it to its RFC 5952 canonical shortest form, classify its address type, and handle an embedded IPv4 suffix or zone ID.
|
|
12
|
+
|
|
5
13
|
## 0.28.0
|
|
6
14
|
- Add `readVideoInfo` (mp4-webm-video-info): duration, resolution, and video/audio codec identifiers from an MP4 (ISO BMFF moov box) or WebM (EBML/Matroska Segment) container header, with no frame decoding or transcoding.
|
|
7
15
|
|
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# @utilix-tech/sdk
|
|
2
2
|
|
|
3
|
-
**
|
|
3
|
+
**583 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)
|
|
@@ -65,7 +65,7 @@ const { formatJson } = require("@utilix-tech/sdk/json");
|
|
|
65
65
|
### `/json`: JSON Tools
|
|
66
66
|
|
|
67
67
|
```ts
|
|
68
|
-
import { formatJson, minifyJson, diffJson, jsonToTypescript, validateJson,
|
|
68
|
+
import { formatJson, minifyJson, diffJson, jsonToTypescript, jsonSchemaToTypescript, validateJson,
|
|
69
69
|
evaluateJsonPath, resolveJsonPointer, jsonToCsv, yamlToJson, jsonToYaml, getJsonStats } from "@utilix-tech/sdk/json";
|
|
70
70
|
|
|
71
71
|
// Format with 2-space indent
|
|
@@ -77,6 +77,9 @@ diffJson(jsonA, jsonB);
|
|
|
77
77
|
// Generate TypeScript interface from JSON
|
|
78
78
|
jsonToTypescript('{"id":1,"name":"Alice"}', { rootName: "User" });
|
|
79
79
|
|
|
80
|
+
// Generate TypeScript interfaces from a JSON Schema (reads required/enum/$ref directly)
|
|
81
|
+
jsonSchemaToTypescript('{"type":"object","properties":{"name":{"type":"string"}},"required":["name"]}', { rootName: "User" });
|
|
82
|
+
|
|
80
83
|
// Query with JSONPath
|
|
81
84
|
evaluateJsonPath(obj, "$.users[*].name");
|
|
82
85
|
|
|
@@ -222,14 +225,17 @@ shiftSubtitles("1\n00:00:01,000 --> 00:00:04,000\nHi\n", -2.5);
|
|
|
222
225
|
|
|
223
226
|
```ts
|
|
224
227
|
import { generateUuid, generateV4, generateV7, generateUlid,
|
|
225
|
-
generatePassword, checkStrength, generateData } from "@utilix-tech/sdk/generators";
|
|
228
|
+
generatePassword, checkStrength, estimatePasswordEntropy, generateData } from "@utilix-tech/sdk/generators";
|
|
226
229
|
|
|
227
230
|
generateUuid(); // "f47ac10b-58cc-4372-a567-0e02b2c3d479" (v4)
|
|
228
231
|
generateV7(); // time-ordered UUID v7
|
|
229
232
|
generateUlid(); // "01ARZ3NDEKTSV4RRFFQ69G5FAV"
|
|
230
233
|
|
|
231
234
|
generatePassword({ length: 16, symbols: true, numbers: true });
|
|
232
|
-
checkStrength("P@ssw0rd!"); // { score: 4, label: "Strong",
|
|
235
|
+
checkStrength("P@ssw0rd!"); // { score: 4, label: "Strong", color: "#16a34a" }
|
|
236
|
+
|
|
237
|
+
// Actual bits of entropy from the character pool, plus crack-time estimates
|
|
238
|
+
estimatePasswordEntropy("Tr0ub4dor&3xyzKL9!"); // { entropyBits: 118.26, strength: "strong", crackTimes: [...] }
|
|
233
239
|
|
|
234
240
|
// Generate fake data rows
|
|
235
241
|
generateData([
|
|
@@ -372,7 +378,7 @@ calculateRuleOf72(8, "rate-to-years");
|
|
|
372
378
|
import { getStatusCode, isValidIp, isValidIpv4, isValidIpv6,
|
|
373
379
|
searchStatusCodes, buildGeoUrl, countryCodeToFlag,
|
|
374
380
|
parseHar, validateSitemap, validateRobotsTxt,
|
|
375
|
-
parseUserAgent, buildCacheControl } from "@utilix-tech/sdk/network";
|
|
381
|
+
parseUserAgent, buildCacheControl, parseIpv6Address } from "@utilix-tech/sdk/network";
|
|
376
382
|
|
|
377
383
|
getStatusCode(404);
|
|
378
384
|
// { code: 404, text: "Not Found", description: "...", category: "Client Error" }
|
|
@@ -406,6 +412,11 @@ validateRobotsTxt("User-agent: *\nDisallow: /admin\nSitemap: https://example.com
|
|
|
406
412
|
// Build and explain a Cache-Control response header from directives
|
|
407
413
|
buildCacheControl({ visibility: "public", maxAge: 3600, mustRevalidate: true });
|
|
408
414
|
// { header: "public, max-age=3600, must-revalidate", directives: [...], warnings: [] }
|
|
415
|
+
|
|
416
|
+
// Expand/compress an IPv6 address (RFC 5952) and classify its address type
|
|
417
|
+
parseIpv6Address("2001:db8::ff00:42:8329");
|
|
418
|
+
// { expanded: "2001:0db8:0000:0000:0000:ff00:0042:8329", compressed: "2001:db8::ff00:42:8329",
|
|
419
|
+
// groups: [...], zoneId: null, addressType: "documentation" }
|
|
409
420
|
```
|
|
410
421
|
|
|
411
422
|
---
|
|
@@ -561,10 +572,10 @@ analyzeString("café"); // { length: 4, codePoints: [...], ... }
|
|
|
561
572
|
|
|
562
573
|
---
|
|
563
574
|
|
|
564
|
-
### `/media`: Image Header Parsing, EXIF, PDF, WAV, ID3, ICO, FLAC & Video Metadata
|
|
575
|
+
### `/media`: Image Header Parsing, EXIF, PDF Metadata & Page Dimensions, WAV, ID3, ICO, FLAC & Video Metadata
|
|
565
576
|
|
|
566
577
|
```ts
|
|
567
|
-
import { readImageInfo, readExifData, readPdfMetadata, readWavInfo, readId3Tags, readIcoInfo, readFlacInfo, readVideoInfo } from "@utilix-tech/sdk/media";
|
|
578
|
+
import { readImageInfo, readExifData, readPdfMetadata, readPdfPageDimensions, readWavInfo, readId3Tags, readIcoInfo, readFlacInfo, readVideoInfo } from "@utilix-tech/sdk/media";
|
|
568
579
|
|
|
569
580
|
// Reads format, dimensions, bit depth, and alpha channel straight from
|
|
570
581
|
// file bytes: no decoding, no canvas, no image library.
|
|
@@ -584,6 +595,12 @@ const pdfBytes = await fs.promises.readFile("report.pdf");
|
|
|
584
595
|
readPdfMetadata(new Uint8Array(pdfBytes));
|
|
585
596
|
// { version: "1.7", pageCount: 12, title: "Q3 Report", author: "Jane Doe", ... }
|
|
586
597
|
|
|
598
|
+
// Lists each page's MediaBox width/height (points and inches), rotation, and
|
|
599
|
+
// orientation by walking the Root -> Pages -> Kids tree, inheriting from
|
|
600
|
+
// ancestor nodes as the PDF spec requires. Also flags common paper sizes.
|
|
601
|
+
readPdfPageDimensions(new Uint8Array(pdfBytes));
|
|
602
|
+
// { version: "1.7", pageCount: 12, pages: [{ pageNumber: 1, widthPt: 612, heightPt: 792, rotation: 0, orientation: "portrait", paperSize: "Letter" }, ...] }
|
|
603
|
+
|
|
587
604
|
// Reads sample rate, channels, bit depth, and duration from a WAV file's
|
|
588
605
|
// RIFF/fmt/data chunk headers: no audio library required.
|
|
589
606
|
const wavBytes = await fs.promises.readFile("recording.wav");
|
|
@@ -626,22 +643,22 @@ readVideoInfo(new Uint8Array(videoBytes));
|
|
|
626
643
|
|
|
627
644
|
| Import | What it does |
|
|
628
645
|
|---|---|
|
|
629
|
-
| `@utilix-tech/sdk/json` | Format, minify, diff, validate, JSONPath, CSV↔JSON, YAML↔JSON, TS types |
|
|
646
|
+
| `@utilix-tech/sdk/json` | Format, minify, diff, validate, JSONPath, CSV↔JSON, YAML↔JSON, TS types from data or from a JSON Schema |
|
|
630
647
|
| `@utilix-tech/sdk/encoding` | Base64, URL, HTML entities, Base32/Base58/Base62 encode/decode |
|
|
631
648
|
| `@utilix-tech/sdk/hashing` | MD5, SHA-1/256/512, bcrypt, HMAC, .htpasswd |
|
|
632
649
|
| `@utilix-tech/sdk/text` | Case convert, slugify, word count, lorem ipsum, line ops, HTML→Markdown, Levenshtein/Damerau string distance |
|
|
633
650
|
| `@utilix-tech/sdk/data` | CSV, YAML, TOML, XML, INI, NDJSON parse and convert, SRT/WebVTT subtitles |
|
|
634
|
-
| `@utilix-tech/sdk/generators` | UUID v4/v7, ULID, passwords, strength check, fake data |
|
|
651
|
+
| `@utilix-tech/sdk/generators` | UUID v4/v7, ULID, passwords, strength check, entropy estimator, fake data |
|
|
635
652
|
| `@utilix-tech/sdk/time` | Date diff, timezone convert, cron parse, relative time |
|
|
636
653
|
| `@utilix-tech/sdk/units` | Bytes, CSS px/rem, number bases, currency format, credit card/IBAN/barcode/ISBN validation, loan calculator, compound/simple interest calculators, VAT/sales tax calculator, tip/bill split calculator, break-even point calculator, Rule of 72 calculator |
|
|
637
|
-
| `@utilix-tech/sdk/network` | HTTP status codes, IP validation, country flags, geolocation URLs, HAR file parsing, User-Agent parsing |
|
|
654
|
+
| `@utilix-tech/sdk/network` | HTTP status codes, IP validation, country flags, geolocation URLs, HAR file parsing, User-Agent parsing, IPv6 address compress/expand |
|
|
638
655
|
| `@utilix-tech/sdk/api` | cURL build/parse, JWT decode/sign, JWKS parse, CORS headers, CSP header |
|
|
639
656
|
| `@utilix-tech/sdk/code` | SQL format/minify, HTML format/minify, regex tester, GraphQL format, MIME type lookup, GitHub URL parsing |
|
|
640
657
|
| `@utilix-tech/sdk/color` | Hex/RGB/HSL/HSV/CMYK convert, palette generation, contrast check |
|
|
641
658
|
| `@utilix-tech/sdk/css` | CSS gradient, box-shadow, border-radius, keyframe animation generators |
|
|
642
659
|
| `@utilix-tech/sdk/misc` | SVG optimize/sanitize, file size format, Unicode inspector |
|
|
643
660
|
| `@utilix-tech/sdk/ai_agent` | Token estimate/trim, chunk text, extract URLs/JSON/keywords, sanitize HTML, flatten/merge JSON, dedupe lines, validate schema, PII/secret/injection detect, vector similarity |
|
|
644
|
-
| `@utilix-tech/sdk/media` | Image format & dimension reading from raw bytes (PNG, JPEG, GIF, WebP, BMP); PDF metadata reading; WAV audio info; ID3 tags; ICO favicon inspection; FLAC metadata reading; MP4/WebM video info |
|
|
661
|
+
| `@utilix-tech/sdk/media` | Image format & dimension reading from raw bytes (PNG, JPEG, GIF, WebP, BMP); PDF metadata reading; PDF page dimension/orientation listing; WAV audio info; ID3 tags; ICO favicon inspection; FLAC metadata reading; MP4/WebM video info |
|
|
645
662
|
|
|
646
663
|
---
|
|
647
664
|
|
|
@@ -12,6 +12,7 @@ __export(generators_exports, {
|
|
|
12
12
|
SYMBOL_CHARS: () => SYMBOL_CHARS,
|
|
13
13
|
ULID_REGEX: () => ULID_REGEX,
|
|
14
14
|
checkStrength: () => checkStrength,
|
|
15
|
+
estimatePasswordEntropy: () => estimatePasswordEntropy,
|
|
15
16
|
generateBulk: () => generateBulk,
|
|
16
17
|
generateBulkPasswords: () => generateBulkPasswords,
|
|
17
18
|
generateBulkUlids: () => generateBulkUlids,
|
|
@@ -228,6 +229,111 @@ function checkStrength(password) {
|
|
|
228
229
|
color: levels[score].color
|
|
229
230
|
};
|
|
230
231
|
}
|
|
232
|
+
var _SYMBOL_POOL_CHARS = " !\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~";
|
|
233
|
+
var _SYMBOL_POOL_SET = new Set(_SYMBOL_POOL_CHARS.split(""));
|
|
234
|
+
function _hasSymbolChar(password) {
|
|
235
|
+
for (const ch of password) {
|
|
236
|
+
if (_SYMBOL_POOL_SET.has(ch)) return true;
|
|
237
|
+
}
|
|
238
|
+
return false;
|
|
239
|
+
}
|
|
240
|
+
function _hasSequentialRun(password, minRun) {
|
|
241
|
+
let ascRun = 1;
|
|
242
|
+
let descRun = 1;
|
|
243
|
+
for (let i = 1; i < password.length; i++) {
|
|
244
|
+
const prev = password.charCodeAt(i - 1);
|
|
245
|
+
const curr = password.charCodeAt(i);
|
|
246
|
+
if (curr === prev + 1) {
|
|
247
|
+
ascRun++;
|
|
248
|
+
descRun = 1;
|
|
249
|
+
} else if (curr === prev - 1) {
|
|
250
|
+
descRun++;
|
|
251
|
+
ascRun = 1;
|
|
252
|
+
} else {
|
|
253
|
+
ascRun = 1;
|
|
254
|
+
descRun = 1;
|
|
255
|
+
}
|
|
256
|
+
if (ascRun >= minRun || descRun >= minRun) return true;
|
|
257
|
+
}
|
|
258
|
+
return false;
|
|
259
|
+
}
|
|
260
|
+
function _formatCrackDuration(seconds) {
|
|
261
|
+
if (!isFinite(seconds)) return "effectively never";
|
|
262
|
+
if (seconds < 1) return "instantly";
|
|
263
|
+
const units = [
|
|
264
|
+
["century", 315576e4],
|
|
265
|
+
["year", 31557600],
|
|
266
|
+
["month", 2629800],
|
|
267
|
+
["day", 86400],
|
|
268
|
+
["hour", 3600],
|
|
269
|
+
["minute", 60],
|
|
270
|
+
["second", 1]
|
|
271
|
+
];
|
|
272
|
+
for (const [name, unitSeconds] of units) {
|
|
273
|
+
if (seconds >= unitSeconds) {
|
|
274
|
+
const value = seconds / unitSeconds;
|
|
275
|
+
if (name === "century" && value > 1e3) return "longer than the age of the universe";
|
|
276
|
+
const rounded = value >= 100 ? Math.round(value) : Math.round(value * 10) / 10;
|
|
277
|
+
const plural = name === "century" ? "centuries" : `${name}s`;
|
|
278
|
+
return `${rounded} ${rounded === 1 ? name : plural}`;
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
return "instantly";
|
|
282
|
+
}
|
|
283
|
+
function estimatePasswordEntropy(password) {
|
|
284
|
+
if (!password) return { error: "Password is required" };
|
|
285
|
+
const hasLowercase = /[a-z]/.test(password);
|
|
286
|
+
const hasUppercase = /[A-Z]/.test(password);
|
|
287
|
+
const hasDigits = /[0-9]/.test(password);
|
|
288
|
+
const hasSymbols = _hasSymbolChar(password);
|
|
289
|
+
const hasOther = /[^\x20-\x7e]/.test(password);
|
|
290
|
+
let poolSize = 0;
|
|
291
|
+
if (hasLowercase) poolSize += 26;
|
|
292
|
+
if (hasUppercase) poolSize += 26;
|
|
293
|
+
if (hasDigits) poolSize += 10;
|
|
294
|
+
if (hasSymbols) poolSize += _SYMBOL_POOL_CHARS.length;
|
|
295
|
+
if (hasOther) poolSize += 100;
|
|
296
|
+
const entropyBits = Math.round(password.length * Math.log2(poolSize) * 100) / 100;
|
|
297
|
+
let strength;
|
|
298
|
+
if (entropyBits < 28) strength = "very-weak";
|
|
299
|
+
else if (entropyBits < 36) strength = "weak";
|
|
300
|
+
else if (entropyBits < 60) strength = "fair";
|
|
301
|
+
else if (entropyBits < 128) strength = "strong";
|
|
302
|
+
else strength = "very-strong";
|
|
303
|
+
const averageGuesses = Math.pow(2, entropyBits) / 2;
|
|
304
|
+
const scenarios = [
|
|
305
|
+
{ scenario: "Online, throttled (100 guesses/hour)", guessesPerSecond: 100 / 3600 },
|
|
306
|
+
{ scenario: "Online, unthrottled (10 guesses/sec)", guessesPerSecond: 10 },
|
|
307
|
+
{ scenario: "Offline, slow hash e.g. bcrypt (10k guesses/sec)", guessesPerSecond: 1e4 },
|
|
308
|
+
{ scenario: "Offline, fast hash / GPU cluster (10B guesses/sec)", guessesPerSecond: 1e10 }
|
|
309
|
+
];
|
|
310
|
+
const crackTimes = scenarios.map((s) => ({
|
|
311
|
+
scenario: s.scenario,
|
|
312
|
+
guessesPerSecond: s.guessesPerSecond,
|
|
313
|
+
humanReadable: _formatCrackDuration(averageGuesses / s.guessesPerSecond)
|
|
314
|
+
}));
|
|
315
|
+
const warnings = [];
|
|
316
|
+
if (password.length < 8) {
|
|
317
|
+
warnings.push("Shorter than 8 characters \u2014 most sites and cracking tools treat this as trivially weak regardless of entropy.");
|
|
318
|
+
}
|
|
319
|
+
if (/(.)\1{2,}/.test(password)) {
|
|
320
|
+
warnings.push('Contains a repeated character run (e.g. "aaa"), which is easier to guess than the entropy figure implies.');
|
|
321
|
+
}
|
|
322
|
+
if (_hasSequentialRun(password, 3)) {
|
|
323
|
+
warnings.push('Contains a sequential run (e.g. "abc" or "321"), which is easier to guess than the entropy figure implies.');
|
|
324
|
+
}
|
|
325
|
+
if (poolSize <= 26) {
|
|
326
|
+
warnings.push("Uses only one character class \u2014 mixing in uppercase, digits, or symbols raises the character pool and entropy.");
|
|
327
|
+
}
|
|
328
|
+
return {
|
|
329
|
+
length: password.length,
|
|
330
|
+
charset: { hasLowercase, hasUppercase, hasDigits, hasSymbols, hasOther, poolSize },
|
|
331
|
+
entropyBits,
|
|
332
|
+
strength,
|
|
333
|
+
crackTimes,
|
|
334
|
+
warnings
|
|
335
|
+
};
|
|
336
|
+
}
|
|
231
337
|
var DATA_TYPES = [
|
|
232
338
|
{ value: "name", label: "Full Name", example: "John Smith" },
|
|
233
339
|
{ value: "email", label: "Email Address", example: "john.smith@gmail.com" },
|
|
@@ -517,4 +623,4 @@ async function generateQrDataUrl(text, options) {
|
|
|
517
623
|
});
|
|
518
624
|
}
|
|
519
625
|
|
|
520
|
-
export { AMBIGUOUS_CHARS, DATA_TYPES, DEFAULT_OPTIONS, DEFAULT_QR_OPTIONS, SYMBOL_CHARS, ULID_REGEX, checkStrength, generateBulk, generateBulkPasswords, generateBulkUlids, generateData, generatePassword, generateQrDataUrl, generateQrSvg, generateSingle, generateUlid, generateUuid, generateV4, generateV7, generators_exports, isValidUlid, isValidUuid, parseUlid, parseUuidVersion };
|
|
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 };
|
|
@@ -27,6 +27,7 @@ __export(network_exports, {
|
|
|
27
27
|
parseDnsResponse: () => parseDnsResponse,
|
|
28
28
|
parseGeoResponse: () => parseGeoResponse,
|
|
29
29
|
parseHar: () => parseHar,
|
|
30
|
+
parseIpv6Address: () => parseIpv6Address,
|
|
30
31
|
parseUserAgent: () => parseUserAgent,
|
|
31
32
|
searchHeaders: () => searchHeaders,
|
|
32
33
|
searchStatusCodes: () => searchStatusCodes,
|
|
@@ -1814,5 +1815,93 @@ function buildCacheControl(options = {}) {
|
|
|
1814
1815
|
const snippet = `Cache-Control: ${header}`;
|
|
1815
1816
|
return { header, headerName: "Cache-Control", snippet, directives, warnings };
|
|
1816
1817
|
}
|
|
1818
|
+
function isValidIpv6HexGroup(g) {
|
|
1819
|
+
return /^[0-9a-fA-F]{1,4}$/.test(g);
|
|
1820
|
+
}
|
|
1821
|
+
function isValidIpv6Ipv4Quad(quad) {
|
|
1822
|
+
const parts = quad.split(".");
|
|
1823
|
+
if (parts.length !== 4) return false;
|
|
1824
|
+
return parts.every((p) => /^\d{1,3}$/.test(p) && Number(p) <= 255);
|
|
1825
|
+
}
|
|
1826
|
+
function classifyIpv6(groups) {
|
|
1827
|
+
const first = parseInt(groups[0], 16);
|
|
1828
|
+
if (groups.every((g) => g === "0000")) return "unspecified";
|
|
1829
|
+
if (groups.slice(0, 7).every((g) => g === "0000") && groups[7] === "0001") return "loopback";
|
|
1830
|
+
if (groups.slice(0, 4).every((g) => g === "0000") && groups[4] === "0000" && groups[5] === "ffff") return "ipv4-mapped";
|
|
1831
|
+
if (groups[0] === "2001" && groups[1] === "0db8") return "documentation";
|
|
1832
|
+
if ((first & 65280) === 65280) return "multicast";
|
|
1833
|
+
if ((first & 65472) === 65152) return "link-local";
|
|
1834
|
+
if ((first & 65024) === 64512) return "unique-local";
|
|
1835
|
+
return "global-unicast";
|
|
1836
|
+
}
|
|
1837
|
+
function compressIpv6Groups(groups) {
|
|
1838
|
+
const short = groups.map((g) => g.replace(/^0+(?=.)/, ""));
|
|
1839
|
+
let bestStart = -1;
|
|
1840
|
+
let bestLen = 0;
|
|
1841
|
+
let curStart = -1;
|
|
1842
|
+
let curLen = 0;
|
|
1843
|
+
for (let i = 0; i < short.length; i++) {
|
|
1844
|
+
if (short[i] === "0") {
|
|
1845
|
+
if (curStart === -1) curStart = i;
|
|
1846
|
+
curLen++;
|
|
1847
|
+
if (curLen > bestLen) {
|
|
1848
|
+
bestLen = curLen;
|
|
1849
|
+
bestStart = curStart;
|
|
1850
|
+
}
|
|
1851
|
+
} else {
|
|
1852
|
+
curStart = -1;
|
|
1853
|
+
curLen = 0;
|
|
1854
|
+
}
|
|
1855
|
+
}
|
|
1856
|
+
if (bestLen < 2) return short.join(":");
|
|
1857
|
+
const before = short.slice(0, bestStart).join(":");
|
|
1858
|
+
const after = short.slice(bestStart + bestLen).join(":");
|
|
1859
|
+
return `${before}::${after}`;
|
|
1860
|
+
}
|
|
1861
|
+
function parseIpv6Address(input) {
|
|
1862
|
+
let s = input.trim();
|
|
1863
|
+
if (s.startsWith("[") && s.includes("]")) s = s.slice(1, s.indexOf("]"));
|
|
1864
|
+
let zoneId = null;
|
|
1865
|
+
const pctIdx = s.indexOf("%");
|
|
1866
|
+
if (pctIdx !== -1) {
|
|
1867
|
+
zoneId = s.slice(pctIdx + 1);
|
|
1868
|
+
s = s.slice(0, pctIdx);
|
|
1869
|
+
}
|
|
1870
|
+
if (!s) return { error: "Empty address" };
|
|
1871
|
+
const doubleColonCount = (s.match(/::/g) ?? []).length;
|
|
1872
|
+
if (doubleColonCount > 1) return { error: 'Address contains more than one "::"' };
|
|
1873
|
+
const ipv4Match = s.match(/(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})$/);
|
|
1874
|
+
if (ipv4Match) {
|
|
1875
|
+
const quad = ipv4Match[1];
|
|
1876
|
+
if (!isValidIpv6Ipv4Quad(quad)) return { error: `Invalid embedded IPv4 address: ${quad}` };
|
|
1877
|
+
const parts = quad.split(".").map(Number);
|
|
1878
|
+
const hi = (parts[0] << 8 | parts[1]).toString(16);
|
|
1879
|
+
const lo = (parts[2] << 8 | parts[3]).toString(16);
|
|
1880
|
+
s = s.slice(0, s.length - quad.length) + `${hi}:${lo}`;
|
|
1881
|
+
}
|
|
1882
|
+
let groups;
|
|
1883
|
+
if (s.includes("::")) {
|
|
1884
|
+
const [left, right] = s.split("::");
|
|
1885
|
+
const leftGroups = left ? left.split(":") : [];
|
|
1886
|
+
const rightGroups = right ? right.split(":") : [];
|
|
1887
|
+
const missing = 8 - (leftGroups.length + rightGroups.length);
|
|
1888
|
+
if (missing < 1) return { error: 'The "::" shorthand must represent at least one group of zeros' };
|
|
1889
|
+
if (![...leftGroups, ...rightGroups].every(isValidIpv6HexGroup)) return { error: "Invalid hex group in address" };
|
|
1890
|
+
groups = [...leftGroups, ...Array(missing).fill("0"), ...rightGroups];
|
|
1891
|
+
} else {
|
|
1892
|
+
groups = s.split(":");
|
|
1893
|
+
if (groups.length !== 8) return { error: `Expected 8 groups, got ${groups.length}` };
|
|
1894
|
+
if (!groups.every(isValidIpv6HexGroup)) return { error: "Invalid hex group in address" };
|
|
1895
|
+
}
|
|
1896
|
+
const expandedGroups = groups.map((g) => g.padStart(4, "0").toLowerCase());
|
|
1897
|
+
const suffix = zoneId ? `%${zoneId}` : "";
|
|
1898
|
+
return {
|
|
1899
|
+
expanded: expandedGroups.join(":") + suffix,
|
|
1900
|
+
compressed: compressIpv6Groups(expandedGroups) + suffix,
|
|
1901
|
+
groups: expandedGroups,
|
|
1902
|
+
zoneId,
|
|
1903
|
+
addressType: classifyIpv6(expandedGroups)
|
|
1904
|
+
};
|
|
1905
|
+
}
|
|
1817
1906
|
|
|
1818
|
-
export { DNS_RECORD_TYPES, HTTP_HEADERS, STATUS_CODES, buildCacheControl, buildDnsQueryUrl, buildGeoUrl, buildMapUrl, countryCodeToFlag, formatCoordinates, formatTtl, getByCategory, getHeader, getHeadersByCategory, getStatusByCategory, getStatusCode, isClientError, isServerError, isSuccess, isValidIp, isValidIpv4, isValidIpv6, network_exports, parseDnsResponse, parseGeoResponse, parseHar, parseUserAgent, searchHeaders, searchStatusCodes, statusCodeToText, typeNumberToLabel, validateDomain, validateHeaderName, validateHeaderValue, validateRobotsTxt, validateSitemap };
|
|
1907
|
+
export { DNS_RECORD_TYPES, HTTP_HEADERS, STATUS_CODES, buildCacheControl, buildDnsQueryUrl, buildGeoUrl, buildMapUrl, countryCodeToFlag, formatCoordinates, formatTtl, getByCategory, getHeader, getHeadersByCategory, getStatusByCategory, getStatusCode, isClientError, isServerError, isSuccess, isValidIp, isValidIpv4, isValidIpv6, network_exports, parseDnsResponse, parseGeoResponse, parseHar, parseIpv6Address, parseUserAgent, searchHeaders, searchStatusCodes, statusCodeToText, typeNumberToLabel, validateDomain, validateHeaderName, validateHeaderValue, validateRobotsTxt, validateSitemap };
|
|
@@ -9,6 +9,7 @@ __export(media_exports, {
|
|
|
9
9
|
readId3Tags: () => readId3Tags,
|
|
10
10
|
readImageInfo: () => readImageInfo,
|
|
11
11
|
readPdfMetadata: () => readPdfMetadata,
|
|
12
|
+
readPdfPageDimensions: () => readPdfPageDimensions,
|
|
12
13
|
readVideoInfo: () => readVideoInfo,
|
|
13
14
|
readWavInfo: () => readWavInfo
|
|
14
15
|
});
|
|
@@ -468,6 +469,116 @@ function readPdfMetadata(bytes) {
|
|
|
468
469
|
encrypted
|
|
469
470
|
};
|
|
470
471
|
}
|
|
472
|
+
var PDF_COMMON_PAPER_SIZES = [
|
|
473
|
+
{ name: "Letter", widthPt: 612, heightPt: 792 },
|
|
474
|
+
{ name: "Legal", widthPt: 612, heightPt: 1008 },
|
|
475
|
+
{ name: "Tabloid", widthPt: 792, heightPt: 1224 },
|
|
476
|
+
{ name: "A3", widthPt: 842, heightPt: 1191 },
|
|
477
|
+
{ name: "A4", widthPt: 595, heightPt: 842 },
|
|
478
|
+
{ name: "A5", widthPt: 420, heightPt: 595 },
|
|
479
|
+
{ name: "B5", widthPt: 499, heightPt: 709 }
|
|
480
|
+
];
|
|
481
|
+
function matchPaperSize(widthPt, heightPt) {
|
|
482
|
+
for (const size of PDF_COMMON_PAPER_SIZES) {
|
|
483
|
+
const w = Math.abs(widthPt - size.widthPt) <= 1;
|
|
484
|
+
const h = Math.abs(heightPt - size.heightPt) <= 1;
|
|
485
|
+
const wSwapped = Math.abs(widthPt - size.heightPt) <= 1;
|
|
486
|
+
const hSwapped = Math.abs(heightPt - size.widthPt) <= 1;
|
|
487
|
+
if (w && h || wSwapped && hSwapped) return size.name;
|
|
488
|
+
}
|
|
489
|
+
return null;
|
|
490
|
+
}
|
|
491
|
+
function parsePdfMediaBox(dict) {
|
|
492
|
+
const m = dict.match(/\/MediaBox\s*\[\s*(-?[\d.]+)\s+(-?[\d.]+)\s+(-?[\d.]+)\s+(-?[\d.]+)\s*\]/);
|
|
493
|
+
if (!m) return null;
|
|
494
|
+
return [Number(m[1]), Number(m[2]), Number(m[3]), Number(m[4])];
|
|
495
|
+
}
|
|
496
|
+
function parsePdfRotate(dict) {
|
|
497
|
+
const m = dict.match(/\/Rotate\s+(-?\d+)/);
|
|
498
|
+
return m ? Number(m[1]) : null;
|
|
499
|
+
}
|
|
500
|
+
function buildPdfPageDimension(pageNumber, mediaBox, rotate) {
|
|
501
|
+
const rotation = (rotate % 360 + 360) % 360;
|
|
502
|
+
if (!mediaBox) {
|
|
503
|
+
return { pageNumber, widthPt: null, heightPt: null, widthIn: null, heightIn: null, rotation, orientation: null, paperSize: null };
|
|
504
|
+
}
|
|
505
|
+
const [llx, lly, urx, ury] = mediaBox;
|
|
506
|
+
let widthPt = Math.abs(urx - llx);
|
|
507
|
+
let heightPt = Math.abs(ury - lly);
|
|
508
|
+
if (rotation === 90 || rotation === 270) [widthPt, heightPt] = [heightPt, widthPt];
|
|
509
|
+
const orientation = widthPt === heightPt ? "square" : widthPt > heightPt ? "landscape" : "portrait";
|
|
510
|
+
return {
|
|
511
|
+
pageNumber,
|
|
512
|
+
widthPt: round2(widthPt),
|
|
513
|
+
heightPt: round2(heightPt),
|
|
514
|
+
widthIn: round2(widthPt / 72),
|
|
515
|
+
heightIn: round2(heightPt / 72),
|
|
516
|
+
rotation,
|
|
517
|
+
orientation,
|
|
518
|
+
paperSize: matchPaperSize(widthPt, heightPt)
|
|
519
|
+
};
|
|
520
|
+
}
|
|
521
|
+
function walkPdfPageTree(objMap, nodeBody, inherited, visited, nodeKey, out) {
|
|
522
|
+
if (visited.has(nodeKey)) return;
|
|
523
|
+
visited.add(nodeKey);
|
|
524
|
+
const mediaBox = parsePdfMediaBox(nodeBody) ?? inherited.mediaBox;
|
|
525
|
+
const rotateMatch = parsePdfRotate(nodeBody);
|
|
526
|
+
const rotate = rotateMatch !== null ? rotateMatch : inherited.rotate;
|
|
527
|
+
if (/\/Type\s*\/Page(?!s)\b/.test(nodeBody)) {
|
|
528
|
+
out.push(buildPdfPageDimension(out.length + 1, mediaBox, rotate));
|
|
529
|
+
return;
|
|
530
|
+
}
|
|
531
|
+
const kidsMatch = nodeBody.match(/\/Kids\s*\[([^\]]*)\]/);
|
|
532
|
+
if (!kidsMatch) return;
|
|
533
|
+
const kidRefs = [...kidsMatch[1].matchAll(/(\d+)\s+(\d+)\s+R/g)];
|
|
534
|
+
for (const ref of kidRefs) {
|
|
535
|
+
const key = `${ref[1]} ${ref[2]}`;
|
|
536
|
+
const body = objMap.get(key);
|
|
537
|
+
if (body) walkPdfPageTree(objMap, body, { mediaBox, rotate }, visited, key, out);
|
|
538
|
+
}
|
|
539
|
+
}
|
|
540
|
+
function readPdfPageDimensions(bytes) {
|
|
541
|
+
if (bytes.length < 8) return { error: "File too small to be a PDF" };
|
|
542
|
+
const header = bytesToLatin1(bytes.subarray(0, 16));
|
|
543
|
+
const versionMatch = header.match(/%PDF-(\d\.\d)/);
|
|
544
|
+
if (!versionMatch) return { error: "Not a valid PDF file (missing %PDF header)" };
|
|
545
|
+
const version = versionMatch[1];
|
|
546
|
+
const text = bytesToLatin1(bytes);
|
|
547
|
+
const objBlocks = [...text.matchAll(/(\d+)\s+(\d+)\s+obj([\s\S]*?)endobj/g)];
|
|
548
|
+
const objMap = /* @__PURE__ */ new Map();
|
|
549
|
+
for (const b of objBlocks) objMap.set(`${b[1]} ${b[2]}`, b[3]);
|
|
550
|
+
const out = [];
|
|
551
|
+
const visited = /* @__PURE__ */ new Set();
|
|
552
|
+
let pagesRootBody = null;
|
|
553
|
+
const trailerMatches = [...text.matchAll(/trailer\s*<<([\s\S]*?)>>/g)];
|
|
554
|
+
if (trailerMatches.length > 0) {
|
|
555
|
+
const trailer = trailerMatches[trailerMatches.length - 1][1];
|
|
556
|
+
const rootRef = trailer.match(/\/Root\s+(\d+)\s+(\d+)\s+R/);
|
|
557
|
+
if (rootRef) {
|
|
558
|
+
const catalogBody = objMap.get(`${rootRef[1]} ${rootRef[2]}`);
|
|
559
|
+
const pagesRef = catalogBody?.match(/\/Pages\s+(\d+)\s+(\d+)\s+R/);
|
|
560
|
+
if (pagesRef) pagesRootBody = objMap.get(`${pagesRef[1]} ${pagesRef[2]}`) ?? null;
|
|
561
|
+
}
|
|
562
|
+
}
|
|
563
|
+
if (!pagesRootBody) {
|
|
564
|
+
for (const b of objBlocks) {
|
|
565
|
+
if (/\/Type\s*\/Pages\b/.test(b[3]) && !/\/Parent\s+\d+\s+\d+\s+R/.test(b[3])) {
|
|
566
|
+
pagesRootBody = b[3];
|
|
567
|
+
break;
|
|
568
|
+
}
|
|
569
|
+
}
|
|
570
|
+
}
|
|
571
|
+
if (pagesRootBody) walkPdfPageTree(objMap, pagesRootBody, { mediaBox: null, rotate: 0 }, visited, "root", out);
|
|
572
|
+
if (out.length === 0) {
|
|
573
|
+
for (const b of objBlocks) {
|
|
574
|
+
if (/\/Type\s*\/Page(?!s)\b/.test(b[3])) {
|
|
575
|
+
out.push(buildPdfPageDimension(out.length + 1, parsePdfMediaBox(b[3]), parsePdfRotate(b[3]) ?? 0));
|
|
576
|
+
}
|
|
577
|
+
}
|
|
578
|
+
}
|
|
579
|
+
if (out.length === 0) return { error: "Could not locate any page objects in this PDF" };
|
|
580
|
+
return { version, pageCount: out.length, pages: out };
|
|
581
|
+
}
|
|
471
582
|
var AUDIO_FORMAT_LABELS = {
|
|
472
583
|
1: "PCM",
|
|
473
584
|
3: "IEEE float",
|
|
@@ -1110,4 +1221,4 @@ function parseWebm(bytes) {
|
|
|
1110
1221
|
return result;
|
|
1111
1222
|
}
|
|
1112
1223
|
|
|
1113
|
-
export { media_exports, readExifData, readFlacInfo, readIcoInfo, readId3Tags, readImageInfo, readPdfMetadata, readVideoInfo, readWavInfo };
|
|
1224
|
+
export { media_exports, readExifData, readFlacInfo, readIcoInfo, readId3Tags, readImageInfo, readPdfMetadata, readPdfPageDimensions, readVideoInfo, readWavInfo };
|
|
@@ -15,6 +15,7 @@ __export(json_exports, {
|
|
|
15
15
|
inferGoType: () => inferGoType,
|
|
16
16
|
inferPythonType: () => inferPythonType,
|
|
17
17
|
inferType: () => inferType,
|
|
18
|
+
jsonSchemaToTypescript: () => jsonSchemaToTypescript,
|
|
18
19
|
jsonToCsv: () => jsonToCsv,
|
|
19
20
|
jsonToGo: () => jsonToGo,
|
|
20
21
|
jsonToPython: () => jsonToPython,
|
|
@@ -1302,5 +1303,104 @@ function resolveJsonPointer(json, pointer) {
|
|
|
1302
1303
|
}
|
|
1303
1304
|
return { pointer, found: true, value: current, tokens };
|
|
1304
1305
|
}
|
|
1306
|
+
function _schemaRefName(ref) {
|
|
1307
|
+
const parts = ref.split("/");
|
|
1308
|
+
return _capitalize(parts[parts.length - 1] || "Ref");
|
|
1309
|
+
}
|
|
1310
|
+
function _schemaLiteralType(value) {
|
|
1311
|
+
if (typeof value === "string") return JSON.stringify(value);
|
|
1312
|
+
if (typeof value === "number" || typeof value === "boolean") return String(value);
|
|
1313
|
+
if (value === null) return "null";
|
|
1314
|
+
return JSON.stringify(value);
|
|
1315
|
+
}
|
|
1316
|
+
function _safePropertyKey(key) {
|
|
1317
|
+
return /^[A-Za-z_$][A-Za-z0-9_$]*$/.test(key) ? key : JSON.stringify(key);
|
|
1318
|
+
}
|
|
1319
|
+
function _schemaToTsType(schema, name, interfaces) {
|
|
1320
|
+
if (schema.$ref) return _schemaRefName(schema.$ref);
|
|
1321
|
+
if (schema.const !== void 0) return _schemaLiteralType(schema.const);
|
|
1322
|
+
if (schema.enum) return schema.enum.map(_schemaLiteralType).join(" | ");
|
|
1323
|
+
if (schema.oneOf) return schema.oneOf.map((s, i) => _schemaToTsType(s, `${name}Variant${i}`, interfaces)).join(" | ");
|
|
1324
|
+
if (schema.anyOf) return schema.anyOf.map((s, i) => _schemaToTsType(s, `${name}Variant${i}`, interfaces)).join(" | ");
|
|
1325
|
+
if (schema.allOf) return schema.allOf.map((s, i) => _schemaToTsType(s, `${name}Part${i}`, interfaces)).join(" & ");
|
|
1326
|
+
const types = Array.isArray(schema.type) ? schema.type : schema.type ? [schema.type] : [];
|
|
1327
|
+
const nullable = types.includes("null");
|
|
1328
|
+
const nonNullTypes = types.filter((t) => t !== "null");
|
|
1329
|
+
const primaryType = nonNullTypes[0] ?? (schema.properties || schema.additionalProperties !== void 0 ? "object" : void 0);
|
|
1330
|
+
let result;
|
|
1331
|
+
switch (primaryType) {
|
|
1332
|
+
case "string":
|
|
1333
|
+
result = "string";
|
|
1334
|
+
break;
|
|
1335
|
+
case "number":
|
|
1336
|
+
case "integer":
|
|
1337
|
+
result = "number";
|
|
1338
|
+
break;
|
|
1339
|
+
case "boolean":
|
|
1340
|
+
result = "boolean";
|
|
1341
|
+
break;
|
|
1342
|
+
case "array": {
|
|
1343
|
+
const itemsSchema = Array.isArray(schema.items) ? schema.items[0] : schema.items;
|
|
1344
|
+
const itemType = itemsSchema ? _schemaToTsType(itemsSchema, `${name}Item`, interfaces) : "unknown";
|
|
1345
|
+
result = `${itemType}[]`;
|
|
1346
|
+
break;
|
|
1347
|
+
}
|
|
1348
|
+
case "object": {
|
|
1349
|
+
_buildSchemaInterface(schema, name, interfaces);
|
|
1350
|
+
result = name;
|
|
1351
|
+
break;
|
|
1352
|
+
}
|
|
1353
|
+
default:
|
|
1354
|
+
result = "unknown";
|
|
1355
|
+
}
|
|
1356
|
+
return nullable ? `${result} | null` : result;
|
|
1357
|
+
}
|
|
1358
|
+
function _buildSchemaInterface(schema, name, interfaces) {
|
|
1359
|
+
if (interfaces.has(name)) return;
|
|
1360
|
+
const required = new Set(schema.required ?? []);
|
|
1361
|
+
const lines = [`interface ${name} {`];
|
|
1362
|
+
for (const [key, propSchema] of Object.entries(schema.properties ?? {})) {
|
|
1363
|
+
if (propSchema.description) lines.push(` /** ${propSchema.description} */`);
|
|
1364
|
+
const optional = required.has(key) ? "" : "?";
|
|
1365
|
+
const propType = _schemaToTsType(propSchema, _capitalize(key), interfaces);
|
|
1366
|
+
lines.push(` ${_safePropertyKey(key)}${optional}: ${propType};`);
|
|
1367
|
+
}
|
|
1368
|
+
if (schema.additionalProperties === true) {
|
|
1369
|
+
lines.push(" [key: string]: unknown;");
|
|
1370
|
+
} else if (schema.additionalProperties && typeof schema.additionalProperties === "object") {
|
|
1371
|
+
const addType = _schemaToTsType(schema.additionalProperties, `${name}Value`, interfaces);
|
|
1372
|
+
lines.push(` [key: string]: ${addType};`);
|
|
1373
|
+
}
|
|
1374
|
+
lines.push("}");
|
|
1375
|
+
interfaces.set(name, lines.join("\n"));
|
|
1376
|
+
}
|
|
1377
|
+
function jsonSchemaToTypescript(schemaJson, options) {
|
|
1378
|
+
let schema;
|
|
1379
|
+
try {
|
|
1380
|
+
schema = JSON.parse(schemaJson);
|
|
1381
|
+
} catch {
|
|
1382
|
+
return { error: "Invalid JSON input" };
|
|
1383
|
+
}
|
|
1384
|
+
if (typeof schema !== "object" || schema === null || Array.isArray(schema)) {
|
|
1385
|
+
return { error: "Schema must be a JSON object" };
|
|
1386
|
+
}
|
|
1387
|
+
const rootName = options?.rootName ?? "Root";
|
|
1388
|
+
const typedSchema = schema;
|
|
1389
|
+
const interfaces = /* @__PURE__ */ new Map();
|
|
1390
|
+
const defs = { ...typedSchema.$defs ?? {}, ...typedSchema.definitions ?? {} };
|
|
1391
|
+
for (const [defName, defSchema] of Object.entries(defs)) {
|
|
1392
|
+
const defTypeName = _capitalize(defName);
|
|
1393
|
+
const defType = _schemaToTsType(defSchema, defTypeName, interfaces);
|
|
1394
|
+
if (!interfaces.has(defTypeName)) {
|
|
1395
|
+
interfaces.set(defTypeName, `type ${defTypeName} = ${defType};`);
|
|
1396
|
+
}
|
|
1397
|
+
}
|
|
1398
|
+
const rootType = _schemaToTsType(typedSchema, rootName, interfaces);
|
|
1399
|
+
const parts = [...interfaces.values()];
|
|
1400
|
+
if (!interfaces.has(rootName)) {
|
|
1401
|
+
parts.push(`type ${rootName} = ${rootType};`);
|
|
1402
|
+
}
|
|
1403
|
+
return parts.join("\n\n");
|
|
1404
|
+
}
|
|
1305
1405
|
|
|
1306
|
-
export { csvToJson, detectFormat, diffJson, evaluateJsonPath, formatDiffLine, formatJson, generateExample, getJsonStats, inferGoType, inferPythonType, inferType, jsonToCsv, jsonToGo, jsonToPython, jsonToTypescript, jsonToYaml, jsonToZod, json_exports, minifyJson, parseJson, parseStructs, resolveJsonPointer, toPascalCase, toSnakeCase, validateJson, validateJsonPath, validateJsonString, yamlToJson };
|
|
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 };
|